diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 0f4d9d16be..ac3ecd984b 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,9 +1,9 @@ stages: - build - assign_test + - host_test - unit_test - - test - - test_report + - integration_test - deploy variables: @@ -31,11 +31,25 @@ variables: APPLY_BOT_FILTER_SCRIPT: "$CI_PROJECT_DIR/tools/ci/apply_bot_filter.py" CHECKOUT_REF_SCRIPT: "$CI_PROJECT_DIR/tools/ci/checkout_project_ref.py" +# When 'fetch' strategy is used, Gitlab removes untracked files before checking out +# new revision. However if the new revision doesn't include some of the submodules +# which were present in the old revision, such submodule directories would not be +# removed by the checkout. This extra step ensures that these stale submodules +# are removed. +.git_clean_stale_submodules: &git_clean_stale_submodules > + find . -name '.git' -not -path './.git' -printf '%P\n' + | sed 's|/.git||' + | xargs -I {} sh -c ' + grep -q {} .gitmodules + || (echo "Removing {}, has .git directory but not in .gitmodules file" + && rm -rf {});' + # before each job, we need to check if this job is filtered by bot stage/job filter .apply_bot_filter: &apply_bot_filter python $APPLY_BOT_FILTER_SCRIPT || exit 0 before_script: + - *git_clean_stale_submodules # apply bot filter in before script - *apply_bot_filter # add gitlab ssh key @@ -56,6 +70,7 @@ before_script: .do_nothing_before: before_script: &do_nothing_before + - *git_clean_stale_submodules # apply bot filter in before script - *apply_bot_filter - echo "Not setting up GitLab key, not fetching submodules" @@ -63,6 +78,7 @@ before_script: .add_gitlab_key_before: before_script: &add_gitlab_key_before + - *git_clean_stale_submodules # apply bot filter in before script - *apply_bot_filter - echo "Not fetching submodules" @@ -135,6 +151,8 @@ build_ssc_01: build_ssc_02: <<: *build_ssc_template +# If you want to add new build ssc jobs, please add it into dependencies of `assign_test` and `.test_template` + build_esp_idf_tests: <<: *build_template artifacts: @@ -142,14 +160,14 @@ build_esp_idf_tests: - tools/unit-test-app/output - components/idf_test/unit_test/TestCaseAll.yml - components/idf_test/unit_test/CIConfigs/*.yml - expire_in: 6 mos + expire_in: 1 mos script: - cd tools/unit-test-app - - make help # make sure kconfig tools are built in single process + - MAKEFLAGS= make help # make sure kconfig tools are built in single process - make ut-clean-all-configs - export EXTRA_CFLAGS="-Werror -Werror=deprecated-declarations" - export EXTRA_CXXFLAGS=${EXTRA_CFLAGS} - - make ut-build-all-configs TESTS_ALL=1 + - make ut-build-all-configs - python tools/UnitTestParser.py .build_examples_template: &build_examples_template @@ -208,6 +226,7 @@ build_examples_06: build_examples_07: <<: *build_examples_template +# If you want to add new build example jobs, please add it into dependencies of `.example_test_template` build_docs: stage: build @@ -246,22 +265,21 @@ verify_cmake_style: script: tools/cmake/run_cmake_lint.sh -test_nvs_on_host: - stage: test +.host_test_template: &host_test_template + stage: host_test image: $CI_DOCKER_REGISTRY/esp32-ci-env$BOT_DOCKER_IMAGE_TAG tags: - host_test dependencies: [] + +test_nvs_on_host: + <<: *host_test_template script: - cd components/nvs_flash/test_nvs_host - make test test_nvs_coverage: - stage: test - image: $CI_DOCKER_REGISTRY/esp32-ci-env$BOT_DOCKER_IMAGE_TAG - tags: - - host_test - dependencies: [] + <<: *host_test_template artifacts: paths: - components/nvs_flash/test_nvs_host/coverage_report @@ -275,52 +293,52 @@ test_nvs_coverage: - make coverage_report test_partition_table_on_host: - stage: test - image: $CI_DOCKER_REGISTRY/esp32-ci-env$BOT_DOCKER_IMAGE_TAG + <<: *host_test_template tags: - build - dependencies: [] script: - cd components/partition_table/test_gen_esp32part_host - ./gen_esp32part_tests.py test_wl_on_host: - stage: test - image: $CI_DOCKER_REGISTRY/esp32-ci-env$BOT_DOCKER_IMAGE_TAG - tags: - - host_test + <<: *host_test_template artifacts: paths: - components/wear_levelling/test_wl_host/coverage_report.zip - dependencies: [] script: - cd components/wear_levelling/test_wl_host - make test -test_multi_heap_on_host: - stage: test - image: $CI_DOCKER_REGISTRY/esp32-ci-env$BOT_DOCKER_IMAGE_TAG +test_fatfs_on_host: + <<: *host_test_template tags: - - host_test + - wl_host_test + script: + - cd components/fatfs/test_fatfs_host/ + - make test + +test_spiffs_on_host: + <<: *host_test_template + tags: + - wl_host_test + script: + - cd components/spiffs/test_spiffs_host/ + - make test + +test_multi_heap_on_host: + <<: *host_test_template script: - cd components/heap/test_multi_heap_host - ./test_all_configs.sh test_confserver: - stage: test - image: $CI_DOCKER_REGISTRY/esp32-ci-env$BOT_DOCKER_IMAGE_TAG - tags: - - host_test + <<: *host_test_template script: - cd tools/kconfig_new/test - ./test_confserver.py test_build_system: - stage: test - image: $CI_DOCKER_REGISTRY/esp32-ci-env$BOT_DOCKER_IMAGE_TAG - tags: - - host_test - dependencies: [] + <<: *host_test_template script: - ${IDF_PATH}/tools/ci/test_configure_ci_environment.sh - rm -rf test_build_system @@ -329,11 +347,7 @@ test_build_system: - ${IDF_PATH}/tools/ci/test_build_system.sh test_build_system_cmake: - stage: test - image: $CI_DOCKER_REGISTRY/esp32-ci-env$BOT_DOCKER_IMAGE_TAG - tags: - - host_test - dependencies: [] + <<: *host_test_template script: - ${IDF_PATH}/tools/ci/test_configure_ci_environment.sh - rm -rf test_build_system @@ -341,73 +355,14 @@ test_build_system_cmake: - cd test_build_system - ${IDF_PATH}/tools/ci/test_build_system_cmake.sh -test_report: - stage: test_report - image: $CI_DOCKER_REGISTRY/esp32-ci-env$BOT_DOCKER_IMAGE_TAG - tags: - - report - only: - - master - - triggers - - schedules - - /^release\/v/ - - /^v\d+\.\d+(\.\d+)?($|-)/ - variables: - LOG_PATH: "$CI_PROJECT_DIR/$CI_COMMIT_SHA" - TEST_CASE_FILE_PATH: "$CI_PROJECT_DIR/components/idf_test" - REPORT_PATH: "$CI_PROJECT_DIR/CI_Test_Report" - MODULE_UPDATE_FILE: "$CI_PROJECT_DIR/tools/unit-test-app/tools/ModuleDefinition.yml" - #dependencies: - #We need all UT* and IT* artifacts except for only a few other - artifacts: - when: always - paths: - - $REPORT_PATH - - $LOG_PATH - expire_in: 12 mos - script: - # calc log path - - VER_NUM=`git rev-list HEAD | wc -l | awk '{print $1}'` - - SHA_ID=`echo $CI_COMMIT_SHA | cut -c 1-7` - - REVISION="${VER_NUM}_${SHA_ID}" - # replace / to _ in branch name - - ESCAPED_BRANCH_NAME=`echo $CI_COMMIT_REF_NAME | sed 's/\//___/g'` - # result path and artifacts path - - RESULT_PATH="$CI_PROJECT_NAME/$ESCAPED_BRANCH_NAME/$REVISION" - - ARTIFACTS_PATH="$GITLAB_HTTP_SERVER/idf/esp-idf/builds/$CI_JOB_ID/artifacts/browse/$CI_COMMIT_SHA" - # clone test bench - - git clone $GITLAB_SSH_SERVER/yinling/auto_test_script.git - - cd auto_test_script - - python $CHECKOUT_REF_SCRIPT auto_test_script - # generate report - - TEST_RESULT=Pass - - python CITestReport.py -l $LOG_PATH -t $TEST_CASE_FILE_PATH -p $REPORT_PATH -r $RESULT_PATH -a $ARTIFACTS_PATH -m $MODULE_UPDATE_FILE || TEST_RESULT=Fail - # commit to CI-test-result project - - git clone $GITLAB_SSH_SERVER/qa/CI-test-result.git - - rm -rf "CI-test-result/RawData/$RESULT_PATH" - - cp -R $CI_PROJECT_NAME CI-test-result/RawData - - cd CI-test-result - # config git user - - git config --global user.email "ci-test-result@espressif.com" - - git config --global user.name "ci-test-result" - # commit test result - - git add . - - git commit . -m "update test result for $CI_PROJECT_NAME/$CI_COMMIT_REF_NAME/$CI_COMMIT_SHA, pipeline ID $CI_PIPELINE_ID" || exit 0 - - git push origin master - - test "${TEST_RESULT}" = "Pass" || exit 1 - test_esp_err_to_name_on_host: - stage: test - image: $CI_DOCKER_REGISTRY/esp32-ci-env$BOT_DOCKER_IMAGE_TAG - tags: - - build - dependencies: [] + <<: *host_test_template script: - cd tools/ - ./gen_esp_err_to_name.py - git diff --exit-code -- ../components/esp32/esp_err_to_name.c || (echo 'Differences found. Please run gen_esp_err_to_name.py and commit the changes.'; exit 1) -push_master_to_github: +push_to_github: stage: deploy image: $CI_DOCKER_REGISTRY/esp32-ci-env$BOT_DOCKER_IMAGE_TAG tags: @@ -416,11 +371,8 @@ push_master_to_github: - master - /^release\/v/ - /^v\d+\.\d+(\.\d+)?($|-)/ - - feature/cmake when: on_success dependencies: [] - variables: - GITHUB_PUSH_REFS: refs/remotes/origin/release refs/remotes/origin/master refs/remotes/origin/feature/cmake before_script: *do_nothing_before script: - mkdir -p ~/.ssh @@ -431,15 +383,12 @@ push_master_to_github: - echo -e "Host github.com\n\tStrictHostKeyChecking no\n" >> ~/.ssh/config - git remote remove github &>/dev/null || true - git remote add github git@github.com:espressif/esp-idf.git - # What the next line of script does: goes through the list of refs for all branches we push to github, - # generates a snippet of shell which is evaluated. The snippet checks CI_COMMIT_SHA against the SHA - # (aka objectname) at tip of each branch, and if any SHAs match then it checks out the local branch - # and then pushes that ref to a corresponding github branch - - eval $(git for-each-ref --shell bash --format 'if [ $CI_COMMIT_SHA == %(objectname) ]; then git checkout -B %(refname:strip=3); git push --follow-tags github %(refname:strip=3); fi;' $GITHUB_PUSH_REFS) - + # Need separate push commands for tag builds and for branch builds + - "[ -n \"${CI_COMMIT_TAG}\" ] && git push github ${CI_COMMIT_TAG}" + - "[ -z \"${CI_COMMIT_TAG}\" ] && git push github ${CI_COMMIT_SHA}:refs/heads/${CI_COMMIT_REF_NAME}" deploy_docs: - stage: assign_test + stage: host_test image: $CI_DOCKER_REGISTRY/esp32-ci-env$BOT_DOCKER_IMAGE_TAG tags: - deploy @@ -474,7 +423,7 @@ deploy_docs: - echo "[document preview][zh_CN] $CI_DOCKER_REGISTRY/docs/esp-idf/zh_CN/${GIT_VER}/index.html" check_doc_links: - stage: test + stage: host_test image: $CI_DOCKER_REGISTRY/esp32-ci-env$BOT_DOCKER_IMAGE_TAG tags: - check_doc_links @@ -576,7 +525,7 @@ assign_test: - python CIAssignTestCases.py -t $IDF_PATH/components/idf_test/integration_test -c $IDF_PATH/.gitlab-ci.yml -b $IDF_PATH/SSC/ssc_bin .example_test_template: &example_test_template - stage: test + stage: integration_test when: on_success only: - master @@ -584,14 +533,21 @@ assign_test: - /^v\d+\.\d+(\.\d+)?($|-)/ - triggers - schedules - # gitlab ci do not support match job with RegEx or wildcard now in dependencies. - # we have a lot build example jobs and the binaries them exceed the limitation of artifacts. - # we can't artifact them in one job. For example test jobs, download all artifacts from previous stages. + dependencies: + - assign_test + - build_examples_00 + - build_examples_01 + - build_examples_02 + - build_examples_03 + - build_examples_04 + - build_examples_05 + - build_examples_06 + - build_examples_07 artifacts: when: always paths: - $LOG_PATH - expire_in: 6 mos + expire_in: 1 mos variables: TEST_FW_PATH: "$CI_PROJECT_DIR/tools/tiny-test-fw" TEST_CASE_PATH: "$CI_PROJECT_DIR/examples" @@ -623,7 +579,7 @@ assign_test: ENV_FILE: "$CI_PROJECT_DIR/ci-test-runner-configs/$CI_RUNNER_DESCRIPTION/EnvConfig.yml" .test_template: &test_template - stage: test + stage: integration_test when: on_success only: - master @@ -631,7 +587,6 @@ assign_test: - /^v\d+\.\d+(\.\d+)?($|-)/ - triggers - schedules - allow_failure: true dependencies: - assign_test - build_ssc_00 @@ -641,7 +596,7 @@ assign_test: when: always paths: - $LOG_PATH - expire_in: 6 mos + expire_in: 1 mos variables: LOCAL_ENV_CONFIG_PATH: "$CI_PROJECT_DIR/ci-test-runner-configs/$CI_RUNNER_DESCRIPTION/ESP32_IDF" LOG_PATH: "$CI_PROJECT_DIR/$CI_COMMIT_SHA" @@ -670,7 +625,7 @@ nvs_compatible_test: paths: - $LOG_PATH - nvs_wifi.bin - expire_in: 6 mos + expire_in: 1 mos tags: - ESP32_IDF - NVS_Compatible @@ -844,6 +799,48 @@ UT_001_24: - ESP32_IDF - UT_T1_1 +UT_001_25: + <<: *unit_test_template + tags: + - ESP32_IDF + - UT_T1_1 + +UT_001_26: + <<: *unit_test_template + tags: + - ESP32_IDF + - UT_T1_1 + +UT_001_27: + <<: *unit_test_template + tags: + - ESP32_IDF + - UT_T1_1 + +UT_001_28: + <<: *unit_test_template + tags: + - ESP32_IDF + - UT_T1_1 + +UT_001_29: + <<: *unit_test_template + tags: + - ESP32_IDF + - UT_T1_1 + +UT_001_30: + <<: *unit_test_template + tags: + - ESP32_IDF + - UT_T1_1 + +UT_001_31: + <<: *unit_test_template + tags: + - ESP32_IDF + - UT_T1_1 + UT_002_01: <<: *unit_test_template tags: @@ -936,6 +933,20 @@ UT_004_08: - UT_T1_1 - psram +UT_004_09: + <<: *unit_test_template + tags: + - ESP32_IDF + - UT_T1_1 + - psram + +UT_004_10: + <<: *unit_test_template + tags: + - ESP32_IDF + - UT_T1_1 + - psram + UT_005_01: <<: *unit_test_template tags: @@ -950,6 +961,87 @@ UT_005_02: - UT_T1_SPIMODE - psram +UT_006_01: + <<: *unit_test_template + tags: + - ESP32_IDF + - UT_T1_GPIO + +UT_006_02: + <<: *unit_test_template + tags: + - ESP32_IDF + - UT_T1_GPIO + +UT_006_03: + <<: *unit_test_template + tags: + - ESP32_IDF + - UT_T1_GPIO + +UT_006_04: + <<: *unit_test_template + tags: + - ESP32_IDF + - UT_T1_GPIO + - psram + +UT_008_01: + <<: *unit_test_template + tags: + - ESP32_IDF + - UT_T1_LEDC + +UT_008_02: + <<: *unit_test_template + tags: + - ESP32_IDF + - UT_T1_LEDC + +UT_008_03: + <<: *unit_test_template + tags: + - ESP32_IDF + - UT_T1_LEDC + +UT_008_04: + <<: *unit_test_template + tags: + - ESP32_IDF + - UT_T1_LEDC + - psram + +UT_010_01: + <<: *unit_test_template + tags: + - ESP32_IDF + - UT_T1_RMT + +UT_010_02: + <<: *unit_test_template + tags: + - ESP32_IDF + - UT_T1_RMT + +UT_010_03: + <<: *unit_test_template + tags: + - ESP32_IDF + - UT_T1_RMT + +UT_010_04: + <<: *unit_test_template + tags: + - ESP32_IDF + - UT_T1_RMT + - psram + +UT_601_01: + <<: *unit_test_template + tags: + - ESP32_IDF + - UT_T1_1 + IT_001_01: <<: *test_template tags: @@ -1118,6 +1210,12 @@ IT_010_01: - ESP32_IDF - SSC_T5_1 +IT_011_01: + <<: *test_template + tags: + - ESP32_IDF + - SSC_T50_1 + IT_501_01: <<: *test_template tags: diff --git a/Kconfig b/Kconfig index f6ebbc5731..76a9e57c34 100644 --- a/Kconfig +++ b/Kconfig @@ -42,137 +42,7 @@ endmenu # SDK tool configuration source "$COMPONENT_KCONFIGS_PROJBUILD" -menu "Compiler options" - -choice OPTIMIZATION_COMPILER - prompt "Optimization Level" - default OPTIMIZATION_LEVEL_DEBUG - help - This option sets compiler optimization level (gcc -O argument). - - - for "Release" setting, -Os flag is added to CFLAGS. - - for "Debug" setting, -Og flag is added to CFLAGS. - - "Release" with -Os produces smaller & faster compiled code but it - may be harder to correlated code addresses to source files when debugging. - - To add custom optimization settings, set CFLAGS and/or CPPFLAGS - in project makefile, before including $(IDF_PATH)/make/project.mk. Note that - custom optimization levels may be unsupported. - -config OPTIMIZATION_LEVEL_DEBUG - bool "Debug (-Og)" -config OPTIMIZATION_LEVEL_RELEASE - bool "Release (-Os)" -endchoice - -choice OPTIMIZATION_ASSERTION_LEVEL - prompt "Assertion level" - default OPTIMIZATION_ASSERTIONS_ENABLED - help - Assertions can be: - - Enabled. Failure will print verbose assertion details. This is the default. - - - Set to "silent" to save code size (failed assertions will abort() but user - needs to use the aborting address to find the line number with the failed assertion.) - - - Disabled entirely (not recommended for most configurations.) -DNDEBUG is added - to CPPFLAGS in this case. - -config OPTIMIZATION_ASSERTIONS_ENABLED - prompt "Enabled" - bool - help - Enable assertions. Assertion content and line number will be printed on failure. - -config OPTIMIZATION_ASSERTIONS_SILENT - prompt "Silent (saves code size)" - bool - help - Enable silent assertions. Failed assertions will abort(), user needs to - use the aborting address to find the line number with the failed assertion. - -config OPTIMIZATION_ASSERTIONS_DISABLED - prompt "Disabled (sets -DNDEBUG)" - bool - help - If assertions are disabled, -DNDEBUG is added to CPPFLAGS. - -endchoice # assertions - -menuconfig CXX_EXCEPTIONS - bool "Enable C++ exceptions" - default n - help - Enabling this option compiles all IDF C++ files with exception support enabled. - - Disabling this option disables C++ exception support in all compiled files, and any libstdc++ code which throws - an exception will abort instead. - - Enabling this option currently adds an additional ~500 bytes of heap overhead - when an exception is thrown in user code for the first time. - -config CXX_EXCEPTIONS_EMG_POOL_SIZE - int "Emergency Pool Size" - default 0 - depends on CXX_EXCEPTIONS - help - Size (in bytes) of the emergency memory pool for C++ exceptions. This pool will be used to allocate - memory for thrown exceptions when there is not enough memory on the heap. - -choice STACK_CHECK_MODE - prompt "Stack smashing protection mode" - default STACK_CHECK_NONE - help - Stack smashing protection mode. Emit extra code to check for buffer overflows, such as stack - smashing attacks. This is done by adding a guard variable to functions with vulnerable objects. - The guards are initialized when a function is entered and then checked when the function exits. - If a guard check fails, program is halted. Protection has the following modes: - - - In NORMAL mode (GCC flag: -fstack-protector) only functions that call - alloca, and functions with buffers larger than 8 bytes are protected. - - STRONG mode (GCC flag: -fstack-protector-strong) is like NORMAL, but - includes additional functions to be protected -- those that have - local array definitions, or have references to local frame addresses. - - In OVERALL mode (GCC flag: -fstack-protector-all) all functions are - protected. - - Modes have the following impact on code performance and coverage: - - performance: NORMAL > STRONG > OVERALL - - coverage: NORMAL < STRONG < OVERALL - - -config STACK_CHECK_NONE - bool "None" -config STACK_CHECK_NORM - bool "Normal" -config STACK_CHECK_STRONG - bool "Strong" -config STACK_CHECK_ALL - bool "Overall" -endchoice - -config STACK_CHECK - bool - default !STACK_CHECK_NONE - help - Stack smashing protection. - -config WARN_WRITE_STRINGS - bool "Enable -Wwrite-strings warning flag" - default "n" - help - Adds -Wwrite-strings flag for the C/C++ compilers. - - For C, this gives string constants the type "const char[]" so that - copying the address of one into a non-"const" "char *" pointer - produces a warning. This warning helps to find at compile time code - that tries to write into a string constant. - - For C++, this warns about the deprecated conversion from string - literals to "char *". - -endmenu # Compiler Options +source "$IDF_PATH/Kconfig.compiler" menu "Component config" source "$COMPONENT_KCONFIGS" diff --git a/Kconfig.compiler b/Kconfig.compiler new file mode 100644 index 0000000000..ab689e88f2 --- /dev/null +++ b/Kconfig.compiler @@ -0,0 +1,135 @@ +menu "Compiler options" + +choice OPTIMIZATION_COMPILER + prompt "Optimization Level" + default OPTIMIZATION_LEVEL_DEBUG + help + This option sets compiler optimization level (gcc -O argument). + + - for "Release" setting, -Os flag is added to CFLAGS. + - for "Debug" setting, -Og flag is added to CFLAGS. + + "Release" with -Os produces smaller & faster compiled code but it + may be harder to correlated code addresses to source files when debugging. + + To add custom optimization settings, set CFLAGS and/or CPPFLAGS + in project makefile, before including $(IDF_PATH)/make/project.mk. Note that + custom optimization levels may be unsupported. + +config OPTIMIZATION_LEVEL_DEBUG + bool "Debug (-Og)" +config OPTIMIZATION_LEVEL_RELEASE + bool "Release (-Os)" +endchoice + +choice OPTIMIZATION_ASSERTION_LEVEL + prompt "Assertion level" + default OPTIMIZATION_ASSERTIONS_ENABLED + help + Assertions can be: + + - Enabled. Failure will print verbose assertion details. This is the default. + + - Set to "silent" to save code size (failed assertions will abort() but user + needs to use the aborting address to find the line number with the failed assertion.) + + - Disabled entirely (not recommended for most configurations.) -DNDEBUG is added + to CPPFLAGS in this case. + +config OPTIMIZATION_ASSERTIONS_ENABLED + prompt "Enabled" + bool + help + Enable assertions. Assertion content and line number will be printed on failure. + +config OPTIMIZATION_ASSERTIONS_SILENT + prompt "Silent (saves code size)" + bool + help + Enable silent assertions. Failed assertions will abort(), user needs to + use the aborting address to find the line number with the failed assertion. + +config OPTIMIZATION_ASSERTIONS_DISABLED + prompt "Disabled (sets -DNDEBUG)" + bool + help + If assertions are disabled, -DNDEBUG is added to CPPFLAGS. + +endchoice # assertions + +menuconfig CXX_EXCEPTIONS + bool "Enable C++ exceptions" + default n + help + Enabling this option compiles all IDF C++ files with exception support enabled. + + Disabling this option disables C++ exception support in all compiled files, and any libstdc++ code which throws + an exception will abort instead. + + Enabling this option currently adds an additional ~500 bytes of heap overhead + when an exception is thrown in user code for the first time. + +config CXX_EXCEPTIONS_EMG_POOL_SIZE + int "Emergency Pool Size" + default 0 + depends on CXX_EXCEPTIONS + help + Size (in bytes) of the emergency memory pool for C++ exceptions. This pool will be used to allocate + memory for thrown exceptions when there is not enough memory on the heap. + +choice STACK_CHECK_MODE + prompt "Stack smashing protection mode" + default STACK_CHECK_NONE + help + Stack smashing protection mode. Emit extra code to check for buffer overflows, such as stack + smashing attacks. This is done by adding a guard variable to functions with vulnerable objects. + The guards are initialized when a function is entered and then checked when the function exits. + If a guard check fails, program is halted. Protection has the following modes: + + - In NORMAL mode (GCC flag: -fstack-protector) only functions that call alloca, + and functions with buffers larger than 8 bytes are protected. + + - STRONG mode (GCC flag: -fstack-protector-strong) is like NORMAL, but includes + additional functions to be protected -- those that have local array definitions, + or have references to local frame addresses. + + - In OVERALL mode (GCC flag: -fstack-protector-all) all functions are protected. + + Modes have the following impact on code performance and coverage: + + - performance: NORMAL > STRONG > OVERALL + + - coverage: NORMAL < STRONG < OVERALL + + +config STACK_CHECK_NONE + bool "None" +config STACK_CHECK_NORM + bool "Normal" +config STACK_CHECK_STRONG + bool "Strong" +config STACK_CHECK_ALL + bool "Overall" +endchoice + +config STACK_CHECK + bool + default !STACK_CHECK_NONE + help + Stack smashing protection. + +config WARN_WRITE_STRINGS + bool "Enable -Wwrite-strings warning flag" + default "n" + help + Adds -Wwrite-strings flag for the C/C++ compilers. + + For C, this gives string constants the type ``const char[]`` so that + copying the address of one into a non-const ``char *`` pointer + produces a warning. This warning helps to find at compile time code + that tries to write into a string constant. + + For C++, this warns about the deprecated conversion from string + literals to ``char *``. + +endmenu # Compiler Options diff --git a/README.md b/README.md index 631d54a407..dadcdfb61e 100644 --- a/README.md +++ b/README.md @@ -1,28 +1,33 @@ # Espressif IoT Development Framework -[![alt text](https://readthedocs.org/projects/docs/badge/?version=latest "Documentation Status")](https://esp-idf.readthedocs.io/en/latest/?badge=latest) +[![alt text](https://readthedocs.org/projects/docs/badge/?version=latest "Documentation Status")](https://docs.espressif.com/projects/esp-idf/en/latest/?badge=latest) ESP-IDF is the official development framework for the [ESP32](https://espressif.com/en/products/hardware/esp32/overview) chip. -# Developing With the ESP-IDF +# Developing With ESP-IDF ## Setting Up ESP-IDF See setup guides for detailed instructions to set up the ESP-IDF: -* [Windows Setup Guide](https://esp-idf.readthedocs.io/en/latest/get-started/windows-setup.html) -* [Mac OS Setup Guide](https://esp-idf.readthedocs.io/en/latest/get-started/macos-setup.html) -* [Linux Setup Guide](https://esp-idf.readthedocs.io/en/latest/get-started/linux-setup.html) +* [Getting Started Guide for the stable ESP-IDF version](https://docs.espressif.com/projects/esp-idf/en/stable/get-started/) +* [Getting Started Guide for the latest (master branch) ESP-IDF version](https://docs.espressif.com/projects/esp-idf/en/latest/get-started/) ## Finding a Project -As well as the [esp-idf-template](https://github.com/espressif/esp-idf-template) project mentioned in the setup guide, ESP-IDF comes with some example projects in the [examples](examples) directory. +As well as the [esp-idf-template](https://github.com/espressif/esp-idf-template) project mentioned in Getting Started, ESP-IDF comes with some example projects in the [examples](examples) directory. Once you've found the project you want to work with, change to its directory and you can configure and build it. +To start your own project based on an example, copy the example project directory outside of the ESP-IDF directory. + +# Quick Reference + +See the Getting Started guide links above for a detailed setup guide. This is a quick reference for common commands when working with ESP-IDF projects: + ## Configuring the Project -`idf.py menuconfig` +`make menuconfig` * Opens a text-based configuration menu for the project. * Use up & down arrow keys to navigate the menu. @@ -36,41 +41,54 @@ Once done configuring, press Escape multiple times to exit and say "Yes" to save ## Compiling the Project -`idf.py build` +`make -j4 all` ... will compile app, bootloader and generate a partition table based on the config. +NOTE: The `-j4` option causes `make` to run 4 parallel jobs. This is much faster than the default single job. The recommended number to pass to this option is `-j(number of CPUs + 1)`. + ## Flashing the Project When the build finishes, it will print a command line to use esptool.py to flash the chip. However you can also do this automatically by running: -`idf.py flash` +`make -j4 flash` -This will flash the entire project (app, bootloader and partition table) to a new chip. The settings for serial port flashing can be configured with `idf.py menuconfig`. +This will flash the entire project (app, bootloader and partition table) to a new chip. The settings for serial port flashing can be configured with `make menuconfig`. -You don't need to run `idf.py build` before running `idf.py flash`, `idf.py flash` will automatically rebuild anything which needs it. +You don't need to run `make all` before running `make flash`, `make flash` will automatically rebuild anything which needs it. ## Viewing Serial Output -The `idf.py monitor` target uses the [idf_monitor tool](https://esp-idf.readthedocs.io/en/latest/get-started/idf-monitor.html) to display serial output from the ESP32. idf_monitor also has a range of features to decode crash output and interact with the device. [Check the documentation page for details](https://esp-idf.readthedocs.io/en/latest/get-started/idf-monitor.html). +The `make monitor` target uses the [idf_monitor tool](https://docs.espressif.com/projects/esp-idf/en/latest/get-started/idf-monitor.html) to display serial output from the ESP32. idf_monitor also has a range of features to decode crash output and interact with the device. [Check the documentation page for details](https://docs.espressif.com/projects/esp-idf/en/latest/get-started/idf-monitor.html). Exit the monitor by typing Ctrl-]. -To flash and monitor output in one pass, you can run: +To build, flash and monitor output in one pass, you can run: -`idf.py flash monitor` +`make -j4 flash monitor` -## Compiling & Flashing Just the App +## Compiling & Flashing Only the App After the initial flash, you may just want to build and flash just your app, not the bootloader and partition table: -* `idf.py app` - build just the app. -* `idf.py app-flash` - flash just the app. +* `make app` - build just the app. +* `make app-flash` - flash just the app. -`idf.py app-flash` will automatically rebuild the app if it needs it. +`make app-flash` will automatically rebuild the app if any source files have changed. (In normal development there's no downside to reflashing the bootloader and partition table each time, if they haven't changed.) +## Parallel Builds + +ESP-IDF supports compiling multiple files in parallel, so all of the above commands can be run as `make -jN` where `N` is the number of parallel make processes to run (generally N should be equal to the number of CPU cores in your system, plus one.) + +Multiple make functions can be combined into one. For example: to build the app & bootloader using 5 jobs in parallel, then flash everything, and then display serial output from the ESP32 run: + +``` +make -j5 flash monitor +``` + + ## The Partition Table Once you've compiled your project, the "build" directory will contain a binary file with a name like "my_app.bin". This is an ESP32 image binary that can be loaded by the bootloader. @@ -79,29 +97,29 @@ A single ESP32's flash can contain multiple apps, as well as many different kind Each entry in the partition table has a name (label), type (app, data, or something else), subtype and the offset in flash where the partition is loaded. -The simplest way to use the partition table is to `idf.py menuconfig` and choose one of the simple predefined partition tables: +The simplest way to use the partition table is to `make menuconfig` and choose one of the simple predefined partition tables: * "Single factory app, no OTA" * "Factory app, two OTA definitions" -In both cases the factory app is flashed at offset 0x10000. If you `idf.py partition_table` then it will print a summary of the partition table. +In both cases the factory app is flashed at offset 0x10000. If you `make partition_table` then it will print a summary of the partition table. For more details about partition tables and how to create custom variations, view the [`docs/en/api-guides/partition-tables.rst`](docs/en/api-guides/partition-tables.rst) file. ## Erasing Flash -The `idf.py flash` target does not erase the entire flash contents. However it is sometimes useful to set the device back to a totally erased state, particularly when making partition table changes or OTA app updates. To erase the entire flash, run `idf.py erase_flash`. +The `make flash` target does not erase the entire flash contents. However it is sometimes useful to set the device back to a totally erased state, particularly when making partition table changes or OTA app updates. To erase the entire flash, run `make erase_flash`. -This can be combined with other targets, ie `idf.py erase_flash flash` will erase everything and then re-flash the new app, bootloader and partition table. +This can be combined with other targets, ie `make erase_flash flash` will erase everything and then re-flash the new app, bootloader and partition table. # Resources -* Documentation for the latest version: https://esp-idf.readthedocs.io/. This documentation is built from the [docs directory](docs) of this repository. +* Documentation for the latest version: https://docs.espressif.com/projects/esp-idf/. This documentation is built from the [docs directory](docs) of this repository. * The [esp32.com forum](https://esp32.com/) is a place to ask questions and find community resources. * [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://esp-idf.readthedocs.io/en/latest/contribute/index.html). +* 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). diff --git a/components/app_trace/Kconfig b/components/app_trace/Kconfig index d80331996b..d599efe85a 100644 --- a/components/app_trace/Kconfig +++ b/components/app_trace/Kconfig @@ -56,6 +56,7 @@ config ESP32_APPTRACE_PENDING_DATA_SIZE_MAX events will be discarded when main HW buffer is full. menu "FreeRTOS SystemView Tracing" + depends on ESP32_APPTRACE_ENABLE config SYSVIEW_ENABLE bool "SystemView Tracing Enable" depends on ESP32_APPTRACE_ENABLE diff --git a/components/app_trace/sys_view/esp32/SEGGER_RTT_esp32.c b/components/app_trace/sys_view/esp32/SEGGER_RTT_esp32.c index c8b199540e..0cb92be55c 100644 --- a/components/app_trace/sys_view/esp32/SEGGER_RTT_esp32.c +++ b/components/app_trace/sys_view/esp32/SEGGER_RTT_esp32.c @@ -20,7 +20,6 @@ #include "rom/ets_sys.h" #include "esp_app_trace.h" -#define LOG_LOCAL_LEVEL ESP_LOG_ERROR #include "esp_log.h" const static char *TAG = "segger_rtt"; @@ -125,7 +124,7 @@ unsigned SEGGER_RTT_WriteSkipNoLock(unsigned BufferIndex, const void* pBuffer, u uint8_t event_id = *pbuf; if (NumBytes > SYSVIEW_EVENTS_BUF_SZ) { - ESP_LOGE(TAG, "Too large event %d bytes!", NumBytes); + ESP_LOGE(TAG, "Too large event %u bytes!", NumBytes); return 0; } if (xPortGetCoreID()) { // dual core specific code diff --git a/components/app_update/esp_ota_ops.c b/components/app_update/esp_ota_ops.c index 1047d2117f..befdd33fc2 100644 --- a/components/app_update/esp_ota_ops.c +++ b/components/app_update/esp_ota_ops.c @@ -241,14 +241,6 @@ esp_err_t esp_ota_end(esp_ota_handle_t handle) goto cleanup; } -#ifdef CONFIG_SECURE_BOOT_ENABLED - ret = esp_secure_boot_verify_signature(it->part->address, data.image_len); - if (ret != ESP_OK) { - ret = ESP_ERR_OTA_VALIDATE_FAILED; - goto cleanup; - } -#endif - cleanup: LIST_REMOVE(it, entries); free(it); diff --git a/components/bootloader/Kconfig.projbuild b/components/bootloader/Kconfig.projbuild index f5394dc274..75dae508ae 100644 --- a/components/bootloader/Kconfig.projbuild +++ b/components/bootloader/Kconfig.projbuild @@ -142,7 +142,7 @@ config SECURE_BOOT_ENABLED When enabling secure boot, JTAG and ROM BASIC Interpreter are permanently disabled by default. - Refer to https://esp-idf.readthedocs.io/en/latest/security/secure-boot.html before enabling. + Refer to https://docs.espressif.com/projects/esp-idf/en/latest/security/secure-boot.html before enabling. choice SECURE_BOOTLOADER_MODE bool "Secure bootloader mode" @@ -206,7 +206,7 @@ config SECURE_BOOT_VERIFICATION_KEY PEM formatted private key using the espsecure.py extract_public_key command. - Refer to https://esp-idf.readthedocs.io/en/latest/security/secure-boot.html before enabling. + Refer to https://docs.espressif.com/projects/esp-idf/en/latest/security/secure-boot.html before enabling. config SECURE_BOOT_INSECURE bool "Allow potentially insecure options" @@ -217,7 +217,7 @@ config SECURE_BOOT_INSECURE Only enable these options if you are very sure. - Refer to https://esp-idf.readthedocs.io/en/latest/security/secure-boot.html before enabling. + Refer to https://docs.espressif.com/projects/esp-idf/en/latest/security/secure-boot.html before enabling. config FLASH_ENCRYPTION_ENABLED bool "Enable flash encryption on boot (READ DOCS FIRST)" @@ -228,7 +228,7 @@ config FLASH_ENCRYPTION_ENABLED Note: After first boot, the system will be permanently encrypted. Re-flashing an encrypted system is complicated and not always possible. - Read https://esp-idf.readthedocs.io/en/latest/security/flash-encryption.html before enabling. + Read https://docs.espressif.com/projects/esp-idf/en/latest/security/flash-encryption.html before enabling. config FLASH_ENCRYPTION_INSECURE bool "Allow potentially insecure options" @@ -275,6 +275,13 @@ config SECURE_BOOT_ALLOW_JTAG Only set this option in testing environments. +config SECURE_BOOT_ALLOW_SHORT_APP_PARTITION + bool "Allow app partition length not 64KB aligned" + depends on SECURE_BOOT_INSECURE + help + If not set (default), app partition size must be a multiple of 64KB. App images are padded to 64KB length, and the bootloader checks any trailing bytes after the signature (before the next 64KB boundary) have not been written. This is because flash cache maps entire 64KB pages into the address space. This prevents an attacker from appending unverified data after the app image in the flash, causing it to be mapped into the address space. + + Setting this option allows the app partition length to be unaligned, and disables padding of the app image to this length. It is generally not recommended to set this option, unless you have a legacy partitioning scheme which doesn't support 64KB aligned partition lengths. config FLASH_ENCRYPTION_UART_BOOTLOADER_ALLOW_ENCRYPT bool "Leave UART bootloader encryption enabled" diff --git a/components/bootloader/Makefile.projbuild b/components/bootloader/Makefile.projbuild index 7876635cc9..11ba9058a4 100644 --- a/components/bootloader/Makefile.projbuild +++ b/components/bootloader/Makefile.projbuild @@ -32,7 +32,8 @@ BOOTLOADER_MAKE= +\ V=$(V) \ BUILD_DIR_BASE=$(BOOTLOADER_BUILD_DIR) \ TEST_COMPONENTS= \ - TESTS_ALL= + TESTS_ALL= \ + EXCLUDE_COMPONENTS= .PHONY: bootloader-clean bootloader-flash bootloader-list-components bootloader $(BOOTLOADER_BIN) @@ -106,7 +107,7 @@ bootloader: $(BOOTLOADER_DIGEST_BIN) $(BOOTLOADER_DIGEST_BIN): $(BOOTLOADER_BIN) $(SECURE_BOOTLOADER_KEY) @echo "DIGEST $(notdir $@)" - $(Q) $(ESPSECUREPY) digest_secure_bootloader -k $(SECURE_BOOTLOADER_KEY) -o $@ $< + $(ESPSECUREPY) digest_secure_bootloader -k $(SECURE_BOOTLOADER_KEY) -o $@ $< else # CONFIG_SECURE_BOOT_ENABLED && !CONFIG_SECURE_BOOTLOADER_REFLASHABLE && !CONFIG_SECURE_BOOTLOADER_ONE_TIME_FLASH bootloader: diff --git a/components/bootloader/subproject/CMakeLists.txt b/components/bootloader/subproject/CMakeLists.txt index 228bd89914..7a34d8ea22 100644 --- a/components/bootloader/subproject/CMakeLists.txt +++ b/components/bootloader/subproject/CMakeLists.txt @@ -10,7 +10,7 @@ if(NOT IDF_PATH) "in by the parent build process.") endif() -set(COMPONENTS bootloader esptool_py esp32 soc bootloader_support log spi_flash micro-ecc soc) +set(COMPONENTS bootloader esptool_py esp32 partition_table soc bootloader_support log spi_flash micro-ecc soc) set(BOOTLOADER_BUILD 1) add_definitions(-DBOOTLOADER_BUILD=1) diff --git a/components/bootloader/subproject/main/bootloader_start.c b/components/bootloader/subproject/main/bootloader_start.c index 64af8268e4..d7c314b2e3 100644 --- a/components/bootloader/subproject/main/bootloader_start.c +++ b/components/bootloader/subproject/main/bootloader_start.c @@ -27,7 +27,7 @@ static const char* TAG = "boot"; -static esp_err_t select_image (esp_image_metadata_t *image_data); +static int select_partition_number (bootloader_state_t *bs); static int selected_boot_partition(const bootloader_state_t *bs); /* * We arrive here after the ROM bootloader finished loading this second stage bootloader from flash. @@ -37,41 +37,32 @@ static int selected_boot_partition(const bootloader_state_t *bs); void call_start_cpu0() { // 1. Hardware initialization - if(bootloader_init() != ESP_OK){ + if (bootloader_init() != ESP_OK) { return; } - // 2. Select image to boot - esp_image_metadata_t image_data; - if(select_image(&image_data) != ESP_OK){ - return; - } - - // 3. Loading the selected image - bootloader_utility_load_image(&image_data); -} - -// Selects image to boot -static esp_err_t select_image (esp_image_metadata_t *image_data) -{ - // 1. Load partition table + // 2. Select the number of boot partition bootloader_state_t bs = { 0 }; - if (!bootloader_utility_load_partition_table(&bs)) { - ESP_LOGE(TAG, "load partition table error!"); - return ESP_FAIL; - } - - // 2. Select boot partition - int boot_index = selected_boot_partition(&bs); - if(boot_index == INVALID_INDEX) { - return ESP_FAIL; // Unrecoverable failure (not due to corrupt ota data or bad partition contents) + int boot_index = select_partition_number(&bs); + if (boot_index == INVALID_INDEX) { + return; } // 3. Load the app image for booting - if (!bootloader_utility_load_boot_image(&bs, boot_index, image_data)) { - return ESP_FAIL; + bootloader_utility_load_boot_image(&bs, boot_index); +} + +// Select the number of boot partition +static int select_partition_number (bootloader_state_t *bs) +{ + // 1. Load partition table + if (!bootloader_utility_load_partition_table(bs)) { + ESP_LOGE(TAG, "load partition table error!"); + return INVALID_INDEX; } - return ESP_OK; + + // 2. Select the number of boot partition + return selected_boot_partition(bs); } /* diff --git a/components/bootloader/subproject/main/esp32.bootloader.ld b/components/bootloader/subproject/main/esp32.bootloader.ld index 54fe1a9a3c..8113987f4f 100644 --- a/components/bootloader/subproject/main/esp32.bootloader.ld +++ b/components/bootloader/subproject/main/esp32.bootloader.ld @@ -8,12 +8,14 @@ Linker file used to link the bootloader. The main purpose is to make sure the bootloader can load into main memory without overwriting itself. */ + MEMORY { /* I/O */ dport0_seg (RW) : org = 0x3FF00000, len = 0x10 - /* IRAM POOL1, used for APP CPU cache. We can abuse it in bootloader because APP CPU is still held in reset, the main app enables APP CPU cache */ - iram_seg (RWX) : org = 0x40078000, len = 0x8000 + /* IRAM POOL1, used for APP CPU cache. Bootloader runs from here during the final stage of loading the app because APP CPU is still held in reset, the main app enables APP CPU cache */ + iram_loader_seg (RWX) : org = 0x40078000, len = 0x8000 /* 32KB, APP CPU cache */ + iram_seg (RWX) : org = 0x40080000, len = 0x10000 /* 64KB, IRAM */ /* 64k at the end of DRAM, after ROM bootloader stack */ dram_seg (RW) : org = 0x3FFF0000, len = 0x10000 } @@ -24,7 +26,36 @@ ENTRY(call_start_cpu0); SECTIONS { - .iram1.text : + + .iram_loader.text : + { + . = ALIGN (16); + _stext = .; + _text_start = ABSOLUTE(.); + *(.stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*) + *(.iram1 .iram1.*) /* catch stray IRAM_ATTR */ + *liblog.a:(.literal .text .literal.* .text.*) + *libgcc.a:(.literal .text .literal.* .text.*) + *libbootloader_support.a:bootloader_flash.*(.literal .text .literal.* .text.*) + *libbootloader_support.a:bootloader_random.*(.literal .text .literal.* .text.*) + *libbootloader_support.a:bootloader_utility.*(.literal .text .literal.* .text.*) + *libbootloader_support.a:bootloader_sha.*(.literal .text .literal.* .text.*) + *libbootloader_support.a:efuse.*(.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.*) + *libbootloader_support.a:secure_boot.*(.literal .text .literal.* .text.*) + *libbootloader_support.a:secure_boot_signatures.*(.literal .text .literal.* .text.*) + *libmicro-ecc.a:*.*(.literal .text .literal.* .text.*) + *libspi_flash.a:*.*(.literal .text .literal.* .text.*) + *(.fini.literal) + *(.fini) + *(.gnu.version) + _text_end = ABSOLUTE(.); + _etext = .; + } > iram_loader_seg + + .iram.text : { . = ALIGN (16); *(.entry.text) @@ -88,13 +119,13 @@ SECTIONS . = (. + 3) & ~ 3; /* C++ constructor and destructor tables, properly ordered: */ __init_array_start = ABSOLUTE(.); - KEEP (*crtbegin.o(.ctors)) - KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors)) + KEEP (*crtbegin.*(.ctors)) + KEEP (*(EXCLUDE_FILE (*crtend.*) .ctors)) KEEP (*(SORT(.ctors.*))) KEEP (*(.ctors)) __init_array_end = ABSOLUTE(.); - KEEP (*crtbegin.o(.dtors)) - KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors)) + KEEP (*crtbegin.*(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.*) .dtors)) KEEP (*(SORT(.dtors.*))) KEEP (*(.dtors)) /* C++ exception handlers table: */ @@ -121,7 +152,7 @@ SECTIONS _stext = .; _text_start = ABSOLUTE(.); *(.literal .text .literal.* .text.* .stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*) - *(.iram1 .iram1.*) /* catch stray IRAM_ATTR */ + *(.iram .iram.*) /* catch stray IRAM_ATTR */ *(.fini.literal) *(.fini) *(.gnu.version) diff --git a/components/bootloader_support/include/esp_flash_partitions.h b/components/bootloader_support/include/esp_flash_partitions.h index 843e5a283c..b5f37aa5fc 100644 --- a/components/bootloader_support/include/esp_flash_partitions.h +++ b/components/bootloader_support/include/esp_flash_partitions.h @@ -17,17 +17,17 @@ #include "esp_err.h" #include "esp_flash_data_types.h" #include +#include "sdkconfig.h" /* Pre-partition table fixed flash offsets */ #define ESP_BOOTLOADER_DIGEST_OFFSET 0x0 #define ESP_BOOTLOADER_OFFSET 0x1000 /* Offset of bootloader image. Has matching value in bootloader KConfig.projbuild file. */ -#define ESP_BOOTLOADER_SIZE (ESP_PARTITION_TABLE_OFFSET - ESP_BOOTLOADER_OFFSET) -#define ESP_PARTITION_TABLE_OFFSET 0x8000 /* Offset of partition table. Has matching value in partition_table Kconfig.projbuild file. */ +#define ESP_PARTITION_TABLE_OFFSET CONFIG_PARTITION_TABLE_OFFSET /* Offset of partition table. Backwards-compatible name.*/ #define ESP_PARTITION_TABLE_MAX_LEN 0xC00 /* Maximum length of partition table data */ #define ESP_PARTITION_TABLE_MAX_ENTRIES (ESP_PARTITION_TABLE_MAX_LEN / sizeof(esp_partition_info_t)) /* Maximum length of partition table data, including terminating entry */ -/* @brief Verify the partition table (does not include verifying secure boot cryptographic signature) +/* @brief Verify the partition table * * @param partition_table Pointer to at least ESP_PARTITION_TABLE_MAX_ENTRIES of potential partition table data. (ESP_PARTITION_TABLE_MAX_LEN bytes.) * @param log_errors Log errors if the partition table is invalid. @@ -35,6 +35,13 @@ * * @return ESP_OK on success, ESP_ERR_INVALID_STATE if partition table is not valid. */ -esp_err_t esp_partition_table_basic_verify(const esp_partition_info_t *partition_table, bool log_errors, int *num_partitions); +esp_err_t esp_partition_table_verify(const esp_partition_info_t *partition_table, bool log_errors, int *num_partitions); + + +/* This function is included for compatibility with the ESP-IDF v3.x API */ +inline static __attribute__((deprecated)) esp_err_t esp_partition_table_basic_verify(const esp_partition_info_t *partition_table, bool log_errors, int *num_partitions) +{ + return esp_partition_table_verify(partition_table, log_errors, num_partitions); +} #endif diff --git a/components/bootloader_support/include_priv/bootloader_utility.h b/components/bootloader_support/include_priv/bootloader_utility.h index 6cf6a77e1a..d7231e6858 100644 --- a/components/bootloader_support/include_priv/bootloader_utility.h +++ b/components/bootloader_support/include_priv/bootloader_utility.h @@ -40,25 +40,15 @@ bool bootloader_utility_load_partition_table(bootloader_state_t* bs); int bootloader_utility_get_selected_boot_partition(const bootloader_state_t *bs); /** - * @brief Load the app image for booting. + * @brief Load the selected partition and start application. * * Start from partition 'start_index', if not bootable then work backwards to FACTORY_INDEX * (ie try any OTA slots in descending order and then the factory partition). * If still nothing, start from 'start_index + 1' and work up to highest numbered OTA partition. * If still nothing, try TEST_APP_INDEX. + * Everything this function calls must be located in the iram_loader_seg segment. * * @param[in] bs Bootloader state structure. * @param[in] start_index The index from which the search for images begins. - * @param[out] result The image found. - * @return Returns true on success, false if there's no bootable app in the partition table. */ -bool bootloader_utility_load_boot_image(const bootloader_state_t *bs, int start_index, esp_image_metadata_t *result); - -/** - * @brief Loading the selected image. - * - * Copy loaded segments to RAM, set up caches for mapped segments, and start application. - * - * @param[in] data Structure to hold on-flash image metadata. - */ -void bootloader_utility_load_image(const esp_image_metadata_t* image_data); +__attribute__((noreturn)) void bootloader_utility_load_boot_image(const bootloader_state_t *bs, int start_index); diff --git a/components/bootloader_support/src/bootloader_common.c b/components/bootloader_support/src/bootloader_common.c index 0d72c3e119..36b4b8ba2d 100644 --- a/components/bootloader_support/src/bootloader_common.c +++ b/components/bootloader_support/src/bootloader_common.c @@ -26,6 +26,7 @@ #include "esp_flash_partitions.h" #include "bootloader_flash.h" #include "bootloader_common.h" +#include "soc/gpio_periph.h" static const char* TAG = "boot_comm"; @@ -42,6 +43,9 @@ bool bootloader_common_ota_select_valid(const esp_ota_select_entry_t *s) esp_comm_gpio_hold_t bootloader_common_check_long_hold_gpio(uint32_t num_pin, uint32_t delay_sec) { gpio_pad_select_gpio(num_pin); + if (GPIO_PIN_MUX_REG[num_pin]) { + PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[num_pin]); + } gpio_pad_pullup(num_pin); uint32_t tm_start = esp_log_early_timestamp(); if (GPIO_INPUT_GET(num_pin) == 1) { @@ -96,26 +100,14 @@ bool bootloader_common_erase_part_type_data(const char *list_erase, bool ota_dat int num_partitions; bool ret = true; -#ifdef CONFIG_SECURE_BOOT_ENABLED - if (esp_secure_boot_enabled()) { - ESP_LOGI(TAG, "Verifying partition table signature..."); - err = esp_secure_boot_verify_signature(ESP_PARTITION_TABLE_ADDR, ESP_PARTITION_TABLE_MAX_LEN); - if (err != ESP_OK) { - ESP_LOGE(TAG, "Failed to verify partition table signature."); - return false; - } - ESP_LOGD(TAG, "Partition table signature verified"); - } -#endif - - partitions = bootloader_mmap(ESP_PARTITION_TABLE_ADDR, ESP_PARTITION_TABLE_MAX_LEN); + partitions = bootloader_mmap(ESP_PARTITION_TABLE_OFFSET, ESP_PARTITION_TABLE_MAX_LEN); if (!partitions) { - ESP_LOGE(TAG, "bootloader_mmap(0x%x, 0x%x) failed", ESP_PARTITION_TABLE_ADDR, ESP_PARTITION_TABLE_MAX_LEN); + ESP_LOGE(TAG, "bootloader_mmap(0x%x, 0x%x) failed", ESP_PARTITION_TABLE_OFFSET, ESP_PARTITION_TABLE_MAX_LEN); return false; } - ESP_LOGD(TAG, "mapped partition table 0x%x at 0x%x", ESP_PARTITION_TABLE_ADDR, (intptr_t)partitions); + ESP_LOGD(TAG, "mapped partition table 0x%x at 0x%x", ESP_PARTITION_TABLE_OFFSET, (intptr_t)partitions); - err = esp_partition_table_basic_verify(partitions, true, &num_partitions); + err = esp_partition_table_verify(partitions, true, &num_partitions); if (err != ESP_OK) { ESP_LOGE(TAG, "Failed to verify partition table"); ret = false; diff --git a/components/bootloader_support/src/bootloader_sha.c b/components/bootloader_support/src/bootloader_sha.c index be23f7f26a..a8d537e04e 100644 --- a/components/bootloader_support/src/bootloader_sha.c +++ b/components/bootloader_support/src/bootloader_sha.c @@ -28,7 +28,10 @@ bootloader_sha256_handle_t bootloader_sha256_start() return NULL; } mbedtls_sha256_init(ctx); - assert(mbedtls_sha256_starts_ret(ctx, false) == 0); + int ret = mbedtls_sha256_starts_ret(ctx, false); + if (ret != 0) { + return NULL; + } return ctx; } @@ -36,7 +39,8 @@ void bootloader_sha256_data(bootloader_sha256_handle_t handle, const void *data, { assert(handle != NULL); mbedtls_sha256_context *ctx = (mbedtls_sha256_context *)handle; - assert(mbedtls_sha256_update_ret(ctx, data, data_len) == 0); + int ret = mbedtls_sha256_update_ret(ctx, data, data_len); + assert(ret == 0); } void bootloader_sha256_finish(bootloader_sha256_handle_t handle, uint8_t *digest) @@ -44,7 +48,8 @@ void bootloader_sha256_finish(bootloader_sha256_handle_t handle, uint8_t *digest assert(handle != NULL); mbedtls_sha256_context *ctx = (mbedtls_sha256_context *)handle; if (digest != NULL) { - assert(mbedtls_sha256_finish_ret(ctx, digest) == 0); + int ret = mbedtls_sha256_finish_ret(ctx, digest); + assert(ret == 0); } mbedtls_sha256_free(ctx); free(handle); diff --git a/components/bootloader_support/src/bootloader_utility.c b/components/bootloader_support/src/bootloader_utility.c index eeaee21798..4b23b14cb5 100644 --- a/components/bootloader_support/src/bootloader_utility.c +++ b/components/bootloader_support/src/bootloader_utility.c @@ -55,6 +55,7 @@ static const char* TAG = "boot"; /* Reduce literal size for some generic string literals */ #define MAP_ERR_MSG "Image contains multiple %s segments. Only the last one will be mapped." +static void load_image(const esp_image_metadata_t* image_data); static void unpack_load_app(const esp_image_metadata_t *data); static void set_cache_and_start_app(uint32_t drom_addr, uint32_t drom_load_addr, @@ -71,26 +72,14 @@ bool bootloader_utility_load_partition_table(bootloader_state_t* bs) esp_err_t err; int num_partitions; -#ifdef CONFIG_SECURE_BOOT_ENABLED - if(esp_secure_boot_enabled()) { - ESP_LOGI(TAG, "Verifying partition table signature..."); - err = esp_secure_boot_verify_signature(ESP_PARTITION_TABLE_ADDR, ESP_PARTITION_TABLE_MAX_LEN); - if (err != ESP_OK) { - ESP_LOGE(TAG, "Failed to verify partition table signature."); - return false; - } - ESP_LOGD(TAG, "Partition table signature verified"); - } -#endif - - partitions = bootloader_mmap(ESP_PARTITION_TABLE_ADDR, ESP_PARTITION_TABLE_MAX_LEN); + partitions = bootloader_mmap(ESP_PARTITION_TABLE_OFFSET, ESP_PARTITION_TABLE_MAX_LEN); if (!partitions) { - ESP_LOGE(TAG, "bootloader_mmap(0x%x, 0x%x) failed", ESP_PARTITION_TABLE_ADDR, ESP_PARTITION_TABLE_MAX_LEN); - return false; + ESP_LOGE(TAG, "bootloader_mmap(0x%x, 0x%x) failed", ESP_PARTITION_TABLE_OFFSET, ESP_PARTITION_TABLE_MAX_LEN); + return false; } - ESP_LOGD(TAG, "mapped partition table 0x%x at 0x%x", ESP_PARTITION_TABLE_ADDR, (intptr_t)partitions); + ESP_LOGD(TAG, "mapped partition table 0x%x at 0x%x", ESP_PARTITION_TABLE_OFFSET, (intptr_t)partitions); - err = esp_partition_table_basic_verify(partitions, true, &num_partitions); + err = esp_partition_table_verify(partitions, true, &num_partitions); if (err != ESP_OK) { ESP_LOGE(TAG, "Failed to verify partition table"); return false; @@ -221,8 +210,8 @@ int bootloader_utility_get_selected_boot_partition(const bootloader_state_t *bs) bootloader_munmap(ota_select_map); ESP_LOGD(TAG, "OTA sequence values A 0x%08x B 0x%08x", sa.ota_seq, sb.ota_seq); - if(sa.ota_seq == UINT32_MAX && sb.ota_seq == UINT32_MAX) { - ESP_LOGD(TAG, "OTA sequence numbers both empty (all-0xFF)"); + if ((sa.ota_seq == UINT32_MAX && sb.ota_seq == UINT32_MAX) || (bs->app_count == 0)) { + ESP_LOGD(TAG, "OTA sequence numbers both empty (all-0xFF) or partition table does not have bootable ota_apps (app_count=%d)", bs->app_count); if (bs->factory.offset != 0) { ESP_LOGI(TAG, "Defaulting to factory image"); return FACTORY_INDEX; @@ -287,18 +276,21 @@ static bool try_load_partition(const esp_partition_pos_t *partition, esp_image_m #define TRY_LOG_FORMAT "Trying partition index %d offs 0x%x size 0x%x" -bool bootloader_utility_load_boot_image(const bootloader_state_t *bs, int start_index, esp_image_metadata_t *result) +void bootloader_utility_load_boot_image(const bootloader_state_t *bs, int start_index) { int index = start_index; esp_partition_pos_t part; + esp_image_metadata_t image_data; + if(start_index == TEST_APP_INDEX) { - if (try_load_partition(&bs->test, result)) { - return true; + if (try_load_partition(&bs->test, &image_data)) { + load_image(&image_data); } else { ESP_LOGE(TAG, "No bootable test partition in the partition table"); - return false; + return; } } + /* work backwards from start_index, down to the factory app */ for(index = start_index; index >= FACTORY_INDEX; index--) { part = index_to_partition(bs, index); @@ -306,8 +298,8 @@ bool bootloader_utility_load_boot_image(const bootloader_state_t *bs, int start_ continue; } ESP_LOGD(TAG, TRY_LOG_FORMAT, index, part.offset, part.size); - if (try_load_partition(&part, result)) { - return true; + if (try_load_partition(&part, &image_data)) { + load_image(&image_data); } log_invalid_app_partition(index); } @@ -319,23 +311,23 @@ bool bootloader_utility_load_boot_image(const bootloader_state_t *bs, int start_ continue; } ESP_LOGD(TAG, TRY_LOG_FORMAT, index, part.offset, part.size); - if (try_load_partition(&part, result)) { - return true; + if (try_load_partition(&part, &image_data)) { + load_image(&image_data); } log_invalid_app_partition(index); } - if (try_load_partition(&bs->test, result)) { + if (try_load_partition(&bs->test, &image_data)) { ESP_LOGW(TAG, "Falling back to test app as only bootable partition"); - return true; + load_image(&image_data); } ESP_LOGE(TAG, "No bootable app partitions in the partition table"); - bzero(result, sizeof(esp_image_metadata_t)); - return false; + bzero(&image_data, sizeof(esp_image_metadata_t)); } -void bootloader_utility_load_image(const esp_image_metadata_t* image_data) +// Copy loaded segments to RAM, set up caches for mapped segments, and start application. +static void load_image(const esp_image_metadata_t* image_data) { #if defined(CONFIG_SECURE_BOOT_ENABLED) || defined(CONFIG_FLASH_ENCRYPTION_ENABLED) esp_err_t err; @@ -463,7 +455,7 @@ static void set_cache_and_start_app( // Application will need to do Cache_Flush(1) and Cache_Read_Enable(1) ESP_LOGD(TAG, "start: 0x%08x", entry_addr); - typedef void (*entry_t)(void); + typedef void (*entry_t)(void) __attribute__((noreturn)); entry_t entry = ((entry_t) entry_addr); // TODO: we have used quite a bit of stack at this point. diff --git a/components/bootloader_support/src/flash_encrypt.c b/components/bootloader_support/src/flash_encrypt.c index 290a02a911..a9e8f8f9ba 100644 --- a/components/bootloader_support/src/flash_encrypt.c +++ b/components/bootloader_support/src/flash_encrypt.c @@ -254,7 +254,7 @@ static esp_err_t encrypt_and_load_partition_table(esp_partition_info_t *partitio ESP_LOGE(TAG, "Failed to read partition table data"); return err; } - if (esp_partition_table_basic_verify(partition_table, false, num_partitions) == ESP_OK) { + if (esp_partition_table_verify(partition_table, false, num_partitions) == ESP_OK) { ESP_LOGD(TAG, "partition table is plaintext. Encrypting..."); esp_err_t err = esp_flash_encrypt_region(ESP_PARTITION_TABLE_OFFSET, FLASH_SECTOR_SIZE); diff --git a/components/bootloader_support/src/flash_partitions.c b/components/bootloader_support/src/flash_partitions.c index f8a24f26c2..6686457338 100644 --- a/components/bootloader_support/src/flash_partitions.c +++ b/components/bootloader_support/src/flash_partitions.c @@ -20,7 +20,7 @@ static const char *TAG = "flash_parts"; -esp_err_t esp_partition_table_basic_verify(const esp_partition_info_t *partition_table, bool log_errors, int *num_partitions) +esp_err_t esp_partition_table_verify(const esp_partition_info_t *partition_table, bool log_errors, int *num_partitions) { int md5_found = 0; int num_parts; diff --git a/components/bootloader_support/src/flash_qio_mode.c b/components/bootloader_support/src/flash_qio_mode.c index 361e3d4ada..f7a0b414d7 100644 --- a/components/bootloader_support/src/flash_qio_mode.c +++ b/components/bootloader_support/src/flash_qio_mode.c @@ -35,6 +35,7 @@ #define CMD_WRDI 0x04 #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 */ static const char *TAG = "qio_mode"; @@ -65,6 +66,11 @@ static void write_status_8b_wrsr2(unsigned new_status); /* Write 16 bit status using WRSR */ static void write_status_16b_wrsr(unsigned new_status); +/* Read 8 bit status of XM25QU64A */ +static unsigned read_status_8b_xmc25qu64a(); +/* Write 8 bit status of XM25QU64A */ +static void write_status_8b_xmc25qu64a(unsigned new_status); + #define ESP32_D2WD_WP_GPIO 7 /* ESP32-D2WD has this GPIO wired to WP pin of flash */ #ifndef CONFIG_BOOTLOADER_SPI_WP_PIN // Set in menuconfig if SPI flasher config is set to a quad mode @@ -84,11 +90,12 @@ static void write_status_16b_wrsr(unsigned new_status); Searching of this table stops when the first match is found. */ const static qio_info_t chip_data[] = { -/* Manufacturer, mfg_id, flash_id, id mask, Read Status, Write Status, QIE Bit */ - { "MXIC", 0xC2, 0x2000, 0xFF00, read_status_8b_rdsr, write_status_8b_wrsr, 6 }, - { "ISSI", 0x9D, 0x4000, 0xCF00, read_status_8b_rdsr, write_status_8b_wrsr, 6 }, /* IDs 0x40xx, 0x70xx */ - { "WinBond", 0xEF, 0x4000, 0xFF00, read_status_16b_rdsr_rdsr2, write_status_16b_wrsr, 9 }, - { "GD", 0xC8, 0x6000, 0xFF00, read_status_16b_rdsr_rdsr2, write_status_16b_wrsr, 9 }, +/* Manufacturer, mfg_id, flash_id, id mask, Read Status, Write Status, QIE Bit */ + { "MXIC", 0xC2, 0x2000, 0xFF00, read_status_8b_rdsr, write_status_8b_wrsr, 6 }, + { "ISSI", 0x9D, 0x4000, 0xCF00, read_status_8b_rdsr, write_status_8b_wrsr, 6 }, /* IDs 0x40xx, 0x70xx */ + { "WinBond", 0xEF, 0x4000, 0xFF00, read_status_16b_rdsr_rdsr2, write_status_16b_wrsr, 9 }, + { "GD", 0xC8, 0x6000, 0xFF00, read_status_16b_rdsr_rdsr2, write_status_16b_wrsr, 9 }, + { "XM25QU64A", 0x20, 0x3817, 0xFFFF, read_status_8b_xmc25qu64a, write_status_8b_xmc25qu64a, 6 }, /* Final entry is default entry, if no other IDs have matched. @@ -96,7 +103,7 @@ const static qio_info_t chip_data[] = { GigaDevice (mfg ID 0xC8, flash IDs including 4016), FM25Q32 (QOUT mode only, mfg ID 0xA1, flash IDs including 4016) */ - { NULL, 0xFF, 0xFFFF, 0xFFFF, read_status_8b_rdsr2, write_status_8b_wrsr2, 1 }, + { NULL, 0xFF, 0xFFFF, 0xFFFF, read_status_8b_rdsr2, write_status_8b_wrsr2, 1 }, }; #define NUM_CHIPS (sizeof(chip_data) / sizeof(qio_info_t)) @@ -246,6 +253,24 @@ static void write_status_16b_wrsr(unsigned new_status) execute_flash_command(CMD_WRSR, new_status, 16, 0); } +static unsigned read_status_8b_xmc25qu64a() +{ + execute_flash_command(CMD_OTPEN, 0, 0, 0); /* Enter OTP mode */ + esp_rom_spiflash_wait_idle(&g_rom_flashchip); + uint32_t read_status = execute_flash_command(CMD_RDSR, 0, 0, 8); + execute_flash_command(CMD_WRDI, 0, 0, 0); /* Exit OTP mode */ + return read_status; +} + +static void write_status_8b_xmc25qu64a(unsigned new_status) +{ + execute_flash_command(CMD_OTPEN, 0, 0, 0); /* Enter OTP mode */ + esp_rom_spiflash_wait_idle(&g_rom_flashchip); + execute_flash_command(CMD_WRSR, new_status, 8, 0); + esp_rom_spiflash_wait_idle(&g_rom_flashchip); + execute_flash_command(CMD_WRDI, 0, 0, 0); /* Exit OTP mode */ +} + static uint32_t execute_flash_command(uint8_t command, uint32_t mosi_data, uint8_t mosi_len, uint8_t miso_len) { uint32_t old_ctrl_reg = SPIFLASH.ctrl.val; diff --git a/components/bootloader_support/src/secure_boot_signatures.c b/components/bootloader_support/src/secure_boot_signatures.c index 988ab7935f..ddb7ad73a6 100644 --- a/components/bootloader_support/src/secure_boot_signatures.c +++ b/components/bootloader_support/src/secure_boot_signatures.c @@ -84,10 +84,13 @@ esp_err_t esp_secure_boot_verify_signature_block(const esp_secure_boot_sig_block return ESP_FAIL; } + ESP_LOGD(TAG, "Verifying secure boot signature"); + is_valid = uECC_verify(signature_verification_key_start, image_digest, DIGEST_LEN, sig_block->signature, uECC_secp256r1()); + ESP_LOGD(TAG, "Verification result %d", is_valid); return is_valid ? ESP_OK : ESP_ERR_IMAGE_INVALID; } diff --git a/components/bt/Kconfig b/components/bt/Kconfig index 3074629c7e..952b832356 100644 --- a/components/bt/Kconfig +++ b/components/bt/Kconfig @@ -70,7 +70,7 @@ menu "MODEM SLEEP Options" config BTDM_CONTROLLER_MODEM_SLEEP bool "Bluetooth modem sleep" depends on BT_ENABLED - default y + default n help Enable/disable bluetooth controller low power mode. Note that currently there is problem in the combination use of bluetooth modem sleep and Dynamic Frequency Scaling(DFS). So do not enable DFS if bluetooth modem sleep is in use. @@ -220,6 +220,13 @@ config GATTC_ENABLE help This option can be close when the app work only on gatt server mode +config GATTC_CACHE_NVS_FLASH + bool "Save gattc cache data to nvs flash" + depends on GATTC_ENABLE + default n + help + This select can save gattc cache data to nvs flash + config BLE_SMP_ENABLE bool "Include BLE security module(SMP)" depends on BLUEDROID_ENABLED @@ -997,6 +1004,15 @@ config BT_BLE_DYNAMIC_ENV_MEMORY help This select can make the allocation of memory will become more flexible +config BLE_HOST_QUEUE_CONGESTION_CHECK + bool "BLE queue congestion check" + depends on BLUEDROID_ENABLED + default n + help + When scanning and scan duplicate is not enabled, if there are a lot of adv packets around or application layer + handling adv packets is slow, it will cause the controller memory to run out. if enabled, adv packets will be + lost when host queue is congested. + config BLE_SCAN_DUPLICATE bool "BLE Scan Duplicate Options" depends on BLUEDROID_ENABLED @@ -1007,8 +1023,8 @@ config BLE_SCAN_DUPLICATE config DUPLICATE_SCAN_CACHE_SIZE int "Maximum number of devices in scan duplicate filter" depends on BLE_SCAN_DUPLICATE - range 10 200 - default 20 + range 10 1000 + default 50 help Maximum number of devices which can be recorded in scan duplicate filter. When the maximum amount of device in the filter is reached, the cache will be refreshed. @@ -1023,8 +1039,8 @@ config BLE_MESH_SCAN_DUPLICATE_EN config MESH_DUPLICATE_SCAN_CACHE_SIZE int "Maximum number of Mesh adv packets in scan duplicate filter" depends on BLE_MESH_SCAN_DUPLICATE_EN - range 10 200 - default 50 + range 10 1000 + default 100 help Maximum number of adv packets which can be recorded in duplicate scan cache for BLE Mesh. When the maximum amount of device in the filter is reached, the cache will be refreshed. diff --git a/components/bt/bluedroid/api/esp_gattc_api.c b/components/bt/bluedroid/api/esp_gattc_api.c index fc431d6fb4..578916e5f2 100644 --- a/components/bt/bluedroid/api/esp_gattc_api.c +++ b/components/bt/bluedroid/api/esp_gattc_api.c @@ -164,6 +164,7 @@ esp_gatt_status_t esp_ble_gattc_get_all_char(esp_gatt_if_t gattc_if, ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED); if ((start_handle == 0) && (end_handle == 0)) { + *count = 0; return ESP_GATT_INVALID_HANDLE; } @@ -206,6 +207,7 @@ esp_gatt_status_t esp_ble_gattc_get_char_by_uuid(esp_gatt_if_t gattc_if, ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED); if (start_handle == 0 && end_handle == 0) { + *count = 0; return ESP_GATT_INVALID_HANDLE; } @@ -247,6 +249,7 @@ esp_gatt_status_t esp_ble_gattc_get_descr_by_char_handle(esp_gatt_if_t gattc_if, ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED); if (char_handle == 0) { + *count = 0; return ESP_GATT_INVALID_HANDLE; } @@ -269,6 +272,7 @@ esp_gatt_status_t esp_ble_gattc_get_include_service(esp_gatt_if_t gattc_if, ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED); if (start_handle == 0 && end_handle == 0) { + *count = 0; return ESP_GATT_INVALID_HANDLE; } @@ -291,6 +295,7 @@ esp_gatt_status_t esp_ble_gattc_get_attr_count(esp_gatt_if_t gattc_if, ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED); if ((start_handle == 0 && end_handle == 0) && (type != ESP_GATT_DB_DESCRIPTOR)) { + *count = 0; return ESP_GATT_INVALID_HANDLE; } @@ -308,6 +313,7 @@ esp_gatt_status_t esp_ble_gattc_get_db(esp_gatt_if_t gattc_if, uint16_t conn_id, ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED); if (start_handle == 0 && end_handle == 0) { + *count = 0; return ESP_GATT_INVALID_HANDLE; } diff --git a/components/bt/bluedroid/api/esp_gatts_api.c b/components/bt/bluedroid/api/esp_gatts_api.c index 8eab2e48c8..d40f2ac09a 100644 --- a/components/bt/bluedroid/api/esp_gatts_api.c +++ b/components/bt/bluedroid/api/esp_gatts_api.c @@ -261,7 +261,7 @@ esp_err_t esp_ble_gatts_send_indicate(esp_gatt_if_t gatts_if, uint16_t conn_id, ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED); if (L2CA_CheckIsCongest(L2CAP_ATT_CID, conn_id)) { - LOG_ERROR("%s, the l2cap chanel is congest.", __func__); + LOG_DEBUG("%s, the l2cap chanel is congest.", __func__); return ESP_FAIL; } diff --git a/components/bt/bluedroid/api/include/api/esp_gatts_api.h b/components/bt/bluedroid/api/include/api/esp_gatts_api.h index bc97b76e46..d25d297806 100644 --- a/components/bt/bluedroid/api/include/api/esp_gatts_api.h +++ b/components/bt/bluedroid/api/include/api/esp_gatts_api.h @@ -350,7 +350,8 @@ esp_err_t esp_ble_gatts_create_attr_tab(const esp_gatts_attr_db_t *gatts_attr_db uint8_t max_nb_attr, uint8_t srvc_inst_id); /** - * @brief This function is called to add an included service. After included + * @brief This function is called to add an included service. This function have to be called between + * 'esp_ble_gatts_create_service' and 'esp_ble_gatts_add_char'. After included * service is included, a callback event BTA_GATTS_ADD_INCL_SRVC_EVT * is reported the included service ID. * diff --git a/components/bt/bluedroid/bta/av/bta_av_aact.c b/components/bt/bluedroid/bta/av/bta_av_aact.c index 5c0d15de7d..9ac791c6fa 100644 --- a/components/bt/bluedroid/bta/av/bta_av_aact.c +++ b/components/bt/bluedroid/bta/av/bta_av_aact.c @@ -815,7 +815,7 @@ void bta_av_role_res (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data) p_scb->wait &= ~BTA_AV_WAIT_ROLE_SW_BITS; if (p_data->role_res.hci_status != HCI_SUCCESS) { p_scb->role &= ~BTA_AV_ROLE_START_INT; - bta_sys_idle(BTA_ID_AV, bta_av_cb.audio_open_cnt, p_scb->peer_addr); + bta_sys_idle(TSEP_TO_SYS_ID(p_scb->seps[p_scb->sep_idx].tsep), bta_av_cb.audio_open_cnt, p_scb->peer_addr); /* start failed because of role switch. */ start.chnl = p_scb->chnl; start.status = BTA_AV_FAIL_ROLE; @@ -956,7 +956,7 @@ void bta_av_do_disc_a2d (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data) p_scb->sec_mask = p_data->api_open.sec_mask; p_scb->use_rc = p_data->api_open.use_rc; - bta_sys_app_open(BTA_ID_AV, p_scb->app_id, p_scb->peer_addr); + bta_sys_app_open(TSEP_TO_SYS_ID(p_scb->seps[p_scb->sep_idx].tsep), p_scb->app_id, p_scb->peer_addr); /* allocate discovery database */ if (p_scb->p_disc_db == NULL) { @@ -1330,7 +1330,7 @@ void bta_av_str_opened (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data) L2CA_SetTxPriority(p_scb->l2c_cid, L2CAP_CHNL_PRIORITY_MEDIUM); L2CA_SetChnlFlushability (p_scb->l2c_cid, TRUE); - bta_sys_conn_open(BTA_ID_AV, p_scb->app_id, p_scb->peer_addr); + bta_sys_conn_open(TSEP_TO_SYS_ID(p_scb->seps[p_scb->sep_idx].tsep), p_scb->app_id, p_scb->peer_addr); memset(&p_scb->q_info, 0, sizeof(tBTA_AV_Q_INFO)); p_scb->l2c_bufs = 0; @@ -1933,8 +1933,7 @@ void bta_av_do_start (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data) if ((p_scb->started == FALSE) && ((p_scb->role & BTA_AV_ROLE_START_INT) == 0)) { p_scb->role |= BTA_AV_ROLE_START_INT; - bta_sys_busy(BTA_ID_AV, bta_av_cb.audio_open_cnt, p_scb->peer_addr); - + bta_sys_busy(TSEP_TO_SYS_ID(p_scb->seps[p_scb->sep_idx].tsep), bta_av_cb.audio_open_cnt, p_scb->peer_addr); AVDT_StartReq(&p_scb->avdt_handle, 1); } else if (p_scb->started) { p_scb->role |= BTA_AV_ROLE_START_INT; @@ -1969,7 +1968,7 @@ void bta_av_str_stopped (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data) APPL_TRACE_ERROR("bta_av_str_stopped:audio_open_cnt=%d, p_data %p", bta_av_cb.audio_open_cnt, p_data); - bta_sys_idle(BTA_ID_AV, bta_av_cb.audio_open_cnt, p_scb->peer_addr); + bta_sys_idle(TSEP_TO_SYS_ID(p_scb->seps[p_scb->sep_idx].tsep), bta_av_cb.audio_open_cnt, p_scb->peer_addr); if ((bta_av_cb.features & BTA_AV_FEAT_MASTER) == 0 || bta_av_cb.audio_open_cnt == 1) { policy |= HCI_ENABLE_MASTER_SLAVE_SWITCH; } @@ -2239,7 +2238,7 @@ void bta_av_start_ok (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data) if (p_data && (p_data->hdr.offset != BTA_AV_RS_NONE)) { p_scb->wait &= ~BTA_AV_WAIT_ROLE_SW_BITS; if (p_data->hdr.offset == BTA_AV_RS_FAIL) { - bta_sys_idle(BTA_ID_AV, bta_av_cb.audio_open_cnt, p_scb->peer_addr); + bta_sys_idle(TSEP_TO_SYS_ID(p_scb->seps[p_scb->sep_idx].tsep), bta_av_cb.audio_open_cnt, p_scb->peer_addr); start.chnl = p_scb->chnl; start.status = BTA_AV_FAIL_ROLE; start.hndl = p_scb->hndl; @@ -2275,9 +2274,9 @@ void bta_av_start_ok (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data) } /* tell role manager to check M/S role */ - bta_sys_conn_open(BTA_ID_AV, p_scb->app_id, p_scb->peer_addr); + bta_sys_conn_open(TSEP_TO_SYS_ID(p_scb->seps[p_scb->sep_idx].tsep), p_scb->app_id, p_scb->peer_addr); - bta_sys_busy(BTA_ID_AV, bta_av_cb.audio_open_cnt, p_scb->peer_addr); + bta_sys_busy(TSEP_TO_SYS_ID(p_scb->seps[p_scb->sep_idx].tsep), bta_av_cb.audio_open_cnt, p_scb->peer_addr); if (p_scb->media_type == AVDT_MEDIA_AUDIO) { /* in normal logic, conns should be bta_av_cb.audio_count - 1, @@ -2364,7 +2363,7 @@ void bta_av_start_failed (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data) UNUSED(p_data); if (p_scb->started == FALSE && p_scb->co_started == FALSE) { - bta_sys_idle(BTA_ID_AV, bta_av_cb.audio_open_cnt, p_scb->peer_addr); + bta_sys_idle(TSEP_TO_SYS_ID(p_scb->seps[p_scb->sep_idx].tsep), bta_av_cb.audio_open_cnt, p_scb->peer_addr); notify_start_failed(p_scb); } @@ -2413,7 +2412,8 @@ void bta_av_str_closed (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data) event = BTA_AV_OPEN_EVT; p_scb->open_status = BTA_AV_SUCCESS; - bta_sys_conn_close(BTA_ID_AV, p_scb->app_id, p_scb->peer_addr); + bta_sys_conn_close(TSEP_TO_SYS_ID(p_scb->seps[p_scb->sep_idx].tsep), p_scb->app_id, p_scb->peer_addr); + bta_av_cleanup(p_scb, p_data); (*bta_av_cb.p_cback)(event, &data); } else { @@ -2432,7 +2432,8 @@ void bta_av_str_closed (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data) data.close.disc_rsn = p_scb->disc_rsn; event = BTA_AV_CLOSE_EVT; - bta_sys_conn_close(BTA_ID_AV, p_scb->app_id, p_scb->peer_addr); + bta_sys_conn_close(TSEP_TO_SYS_ID(p_scb->seps[p_scb->sep_idx].tsep), p_scb->app_id, p_scb->peer_addr); + bta_av_cleanup(p_scb, p_data); (*bta_av_cb.p_cback)(event, &data); } @@ -2506,7 +2507,7 @@ void bta_av_suspend_cfm (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data) p_scb->cong = FALSE; } - bta_sys_idle(BTA_ID_AV, bta_av_cb.audio_open_cnt, p_scb->peer_addr); + bta_sys_idle(TSEP_TO_SYS_ID(p_scb->seps[p_scb->sep_idx].tsep), bta_av_cb.audio_open_cnt, p_scb->peer_addr); if ((bta_av_cb.features & BTA_AV_FEAT_MASTER) == 0 || bta_av_cb.audio_open_cnt == 1) { policy |= HCI_ENABLE_MASTER_SLAVE_SWITCH; } diff --git a/components/bt/bluedroid/bta/av/include/bta_av_int.h b/components/bt/bluedroid/bta/av/include/bta_av_int.h index 3a13c0cc52..0c9da001c6 100644 --- a/components/bt/bluedroid/bta/av/include/bta_av_int.h +++ b/components/bt/bluedroid/bta/av/include/bta_av_int.h @@ -153,6 +153,7 @@ enum { #define BTA_AV_MULTI_AV_SUPPORTED 0x01 #define BTA_AV_MULTI_AV_IN_USE 0x02 +#define TSEP_TO_SYS_ID(x) ((x) == AVDT_TSEP_SRC ? BTA_ID_AV : BTA_ID_AVK) /***************************************************************************** ** Data types diff --git a/components/bt/bluedroid/bta/dm/bta_dm_act.c b/components/bt/bluedroid/bta/dm/bta_dm_act.c index caa4943145..d16418cd3a 100644 --- a/components/bt/bluedroid/bta/dm/bta_dm_act.c +++ b/components/bt/bluedroid/bta/dm/bta_dm_act.c @@ -374,6 +374,12 @@ static void bta_dm_sys_hw_cback( tBTA_SYS_HW_EVT status ) bta_sys_hw_unregister( BTA_SYS_HW_BLUETOOTH ); /* notify BTA DM is now unactive */ bta_dm_cb.is_bta_dm_active = FALSE; +#if (defined BLE_INCLUDED && BLE_INCLUDED == TRUE) +#if (GATTC_INCLUDED == TRUE && GATTC_CACHE_NVS == TRUE) + /* clear the gattc cache address list */ + bta_gattc_co_cache_addr_deinit(); +#endif +#endif } else if ( status == BTA_SYS_HW_ON_EVT ) { /* FIXME: We should not unregister as the SYS shall invoke this callback on a H/W error. * We need to revisit when this platform has more than one BLuetooth H/W chip */ @@ -403,7 +409,7 @@ static void bta_dm_sys_hw_cback( tBTA_SYS_HW_EVT status ) BTM_SetDeviceClass (dev_class); #if (defined BLE_INCLUDED && BLE_INCLUDED == TRUE) -#if (GATTC_INCLUDED == TRUE) +#if (GATTC_INCLUDED == TRUE && GATTC_CACHE_NVS == TRUE) // load the gattc cache address list bta_gattc_co_cache_addr_init(); #endif /* #if (GATTC_INCLUDED = TRUE) */ @@ -596,16 +602,16 @@ void bta_dm_ble_read_adv_tx_power(tBTA_DM_MSG *p_data) if (p_data->read_tx_power.read_tx_power_cb != NULL) { BTM_BleReadAdvTxPower(p_data->read_tx_power.read_tx_power_cb); } else { - APPL_TRACE_ERROR("%s(), the callback function cann't be NULL.", __func__); + APPL_TRACE_ERROR("%s(), the callback function can't be NULL.", __func__); } } void bta_dm_ble_read_rssi(tBTA_DM_MSG *p_data) { if (p_data->rssi.read_rssi_cb != NULL) { - BTM_ReadRSSI(p_data->rssi.remote_addr, p_data->rssi.read_rssi_cb); + BTM_ReadRSSI(p_data->rssi.remote_addr, p_data->rssi.transport, p_data->rssi.read_rssi_cb); } else { - APPL_TRACE_ERROR("%s(), the callback function cann't be NULL.", __func__); + APPL_TRACE_ERROR("%s(), the callback function can't be NULL.", __func__); } } @@ -692,7 +698,7 @@ void bta_dm_set_visibility(tBTA_DM_MSG *p_data) ** Description Removes device, Disconnects ACL link if required. **** *******************************************************************************/ -void bta_dm_process_remove_device(BD_ADDR bd_addr) +static void bta_dm_process_remove_device(BD_ADDR bd_addr, tBT_TRANSPORT transport) { #if (BLE_INCLUDED == TRUE && GATTC_INCLUDED == TRUE) /* need to remove all pending background connection before unpair */ @@ -703,14 +709,18 @@ void bta_dm_process_remove_device(BD_ADDR bd_addr) #if (BLE_INCLUDED == TRUE && GATTC_INCLUDED == TRUE) /* remove all cached GATT information */ - BTA_GATTC_Refresh(bd_addr); + BTA_GATTC_Refresh(bd_addr, false); #endif - if (bta_dm_cb.p_sec_cback) { tBTA_DM_SEC sec_event; bdcpy(sec_event.link_down.bd_addr, bd_addr); sec_event.link_down.status = HCI_SUCCESS; - bta_dm_cb.p_sec_cback(BTA_DM_DEV_UNPAIRED_EVT, &sec_event); + if (transport == BT_TRANSPORT_LE){ + bta_dm_cb.p_sec_cback(BTA_DM_BLE_DEV_UNPAIRED_EVT, &sec_event); + } else { + bta_dm_cb.p_sec_cback(BTA_DM_DEV_UNPAIRED_EVT, &sec_event); + } + } } @@ -728,15 +738,11 @@ void bta_dm_remove_device(tBTA_DM_MSG *p_data) return; } - BD_ADDR other_address; - bdcpy(other_address, p_dev->bd_addr); - /* If ACL exists for the device in the remove_bond message*/ BOOLEAN continue_delete_dev = FALSE; - UINT8 other_transport = BT_TRANSPORT_INVALID; + UINT8 transport = p_dev->transport; - if (BTM_IsAclConnectionUp(p_dev->bd_addr, BT_TRANSPORT_LE) || - BTM_IsAclConnectionUp(p_dev->bd_addr, BT_TRANSPORT_BR_EDR)) { + if (BTM_IsAclConnectionUp(p_dev->bd_addr, transport)) { APPL_TRACE_DEBUG("%s: ACL Up count %d", __func__, bta_dm_cb.device_list.count); continue_delete_dev = FALSE; @@ -747,13 +753,6 @@ void bta_dm_remove_device(tBTA_DM_MSG *p_data) btm_remove_acl( p_dev->bd_addr, bta_dm_cb.device_list.peer_device[i].transport); APPL_TRACE_DEBUG("%s:transport = %d", __func__, bta_dm_cb.device_list.peer_device[i].transport); - - /* save the other transport to check if device is connected on other_transport */ - if (bta_dm_cb.device_list.peer_device[i].transport == BT_TRANSPORT_LE) { - other_transport = BT_TRANSPORT_BR_EDR; - } else { - other_transport = BT_TRANSPORT_LE; - } break; } } @@ -761,35 +760,9 @@ void bta_dm_remove_device(tBTA_DM_MSG *p_data) continue_delete_dev = TRUE; } - // If it is DUMO device and device is paired as different address, unpair that device - // if different address - BOOLEAN continue_delete_other_dev = FALSE; - if ((other_transport && (BTM_ReadConnectedTransportAddress(other_address, other_transport))) || - (!other_transport && (BTM_ReadConnectedTransportAddress(other_address, BT_TRANSPORT_BR_EDR) || - BTM_ReadConnectedTransportAddress(other_address, BT_TRANSPORT_LE)))) { - continue_delete_other_dev = FALSE; - /* Take the link down first, and mark the device for removal when disconnected */ - for (int i = 0; i < bta_dm_cb.device_list.count; i++) { - if (!bdcmp(bta_dm_cb.device_list.peer_device[i].peer_bdaddr, other_address)) { - bta_dm_cb.device_list.peer_device[i].conn_state = BTA_DM_UNPAIRING; - btm_remove_acl(other_address, bta_dm_cb.device_list.peer_device[i].transport); - break; - } - } - } else { - APPL_TRACE_DEBUG("%s: continue to delete the other dev ", __func__); - continue_delete_other_dev = TRUE; - } - /* Delete the device mentioned in the msg */ if (continue_delete_dev) { - bta_dm_process_remove_device(p_dev->bd_addr); - } - - /* Delete the other paired device too */ - BD_ADDR dummy_bda = {0}; - if (continue_delete_other_dev && (bdcmp(other_address, dummy_bda) != 0)) { - bta_dm_process_remove_device(other_address); + bta_dm_process_remove_device(p_dev->bd_addr, transport); } } @@ -887,7 +860,7 @@ void bta_dm_close_acl(tBTA_DM_MSG *p_data) /* need to remove all pending background connection if any */ BTA_GATTC_CancelOpen(0, p_remove_acl->bd_addr, FALSE); /* remove all cached GATT information */ - BTA_GATTC_Refresh(p_remove_acl->bd_addr); + BTA_GATTC_Refresh(p_remove_acl->bd_addr, false); #endif } /* otherwise, no action needed */ @@ -3336,7 +3309,7 @@ void bta_dm_acl_change(tBTA_DM_MSG *p_data) /* need to remove all pending background connection */ BTA_GATTC_CancelOpen(0, p_bda, FALSE); /* remove all cached GATT information */ - BTA_GATTC_Refresh(p_bda); + BTA_GATTC_Refresh(p_bda, false); #endif } @@ -3345,7 +3318,11 @@ void bta_dm_acl_change(tBTA_DM_MSG *p_data) if ( bta_dm_cb.p_sec_cback ) { bta_dm_cb.p_sec_cback(BTA_DM_LINK_DOWN_EVT, &conn); if ( issue_unpair_cb ) { - bta_dm_cb.p_sec_cback(BTA_DM_DEV_UNPAIRED_EVT, &conn); + if (p_data->acl_change.transport == BT_TRANSPORT_LE) { + bta_dm_cb.p_sec_cback(BTA_DM_BLE_DEV_UNPAIRED_EVT, &conn); + } else { + bta_dm_cb.p_sec_cback(BTA_DM_DEV_UNPAIRED_EVT, &conn); + } } } } @@ -3510,7 +3487,7 @@ static void bta_dm_remove_sec_dev_entry(BD_ADDR remote_bd_addr) /* need to remove all pending background connection */ BTA_GATTC_CancelOpen(0, remote_bd_addr, FALSE); /* remove all cached GATT information */ - BTA_GATTC_Refresh(remote_bd_addr); + BTA_GATTC_Refresh(remote_bd_addr, false); #endif } } @@ -4659,7 +4636,7 @@ void bta_dm_ble_set_rand_address(tBTA_DM_MSG *p_data) void bta_dm_ble_stop_advertising(tBTA_DM_MSG *p_data) { if (p_data->hdr.event != BTA_DM_API_BLE_STOP_ADV_EVT) { - APPL_TRACE_ERROR("Invalid BTA event,cann't stop the BLE adverting\n"); + APPL_TRACE_ERROR("Invalid BTA event,can't stop the BLE adverting\n"); } btm_ble_stop_adv(); diff --git a/components/bt/bluedroid/bta/dm/bta_dm_api.c b/components/bt/bluedroid/bta/dm/bta_dm_api.c index 1f2262ae90..c00a2e1d5e 100644 --- a/components/bt/bluedroid/bta/dm/bta_dm_api.c +++ b/components/bt/bluedroid/bta/dm/bta_dm_api.c @@ -206,12 +206,13 @@ void BTA_DmBleReadAdvTxPower(tBTA_CMPL_CB *cmpl_cb) } } -void BTA_DmBleReadRSSI(BD_ADDR remote_addr, tBTA_CMPL_CB *cmpl_cb) +void BTA_DmBleReadRSSI(BD_ADDR remote_addr, tBTA_TRANSPORT transport, tBTA_CMPL_CB *cmpl_cb) { tBTA_DM_API_READ_RSSI *p_msg; if ((p_msg = (tBTA_DM_API_READ_RSSI *)osi_malloc(sizeof(tBTA_DM_API_READ_RSSI))) != NULL) { p_msg->hdr.event = BTA_DM_API_BLE_READ_RSSI_EVT; memcpy(p_msg->remote_addr, remote_addr, sizeof(BD_ADDR)); + p_msg->transport = transport; p_msg->read_rssi_cb = cmpl_cb; bta_sys_sendmsg(p_msg); } @@ -569,7 +570,7 @@ void BTA_DmAddDevice(BD_ADDR bd_addr, DEV_CLASS dev_class, LINK_KEY link_key, ** Returns void ** *******************************************************************************/ -tBTA_STATUS BTA_DmRemoveDevice(BD_ADDR bd_addr) +tBTA_STATUS BTA_DmRemoveDevice(BD_ADDR bd_addr, tBT_TRANSPORT transport) { tBTA_DM_API_REMOVE_DEVICE *p_msg; @@ -578,6 +579,7 @@ tBTA_STATUS BTA_DmRemoveDevice(BD_ADDR bd_addr) p_msg->hdr.event = BTA_DM_API_REMOVE_DEVICE_EVT; bdcpy(p_msg->bd_addr, bd_addr); + p_msg->transport = transport; bta_sys_sendmsg(p_msg); } else { return BTA_FAILURE; diff --git a/components/bt/bluedroid/bta/dm/include/bta_dm_int.h b/components/bt/bluedroid/bta/dm/include/bta_dm_int.h index 8ee1dda61b..62fdd13d6e 100644 --- a/components/bt/bluedroid/bta/dm/include/bta_dm_int.h +++ b/components/bt/bluedroid/bta/dm/include/bta_dm_int.h @@ -196,6 +196,7 @@ typedef struct { typedef struct { BT_HDR hdr; BD_ADDR remote_addr; + tBTA_TRANSPORT transport; tBTA_CMPL_CB *read_rssi_cb; }tBTA_DM_API_READ_RSSI; @@ -391,6 +392,7 @@ typedef struct { typedef struct { BT_HDR hdr; BD_ADDR bd_addr; + UINT8 transport; } tBTA_DM_API_REMOVE_DEVICE; /* data type for BTA_DM_API_EXECUTE_CBACK_EVT */ diff --git a/components/bt/bluedroid/bta/gatt/bta_gattc_act.c b/components/bt/bluedroid/bta/gatt/bta_gattc_act.c index e836003dd4..29a9d47279 100644 --- a/components/bt/bluedroid/bta/gatt/bta_gattc_act.c +++ b/components/bt/bluedroid/bta/gatt/bta_gattc_act.c @@ -65,6 +65,7 @@ static void bta_gattc_pop_command_to_send(tBTA_GATTC_CLCB *p_clcb); static void bta_gattc_deregister_cmpl(tBTA_GATTC_RCB *p_clreg); static void bta_gattc_enc_cmpl_cback(tGATT_IF gattc_if, BD_ADDR bda); static void bta_gattc_cong_cback (UINT16 conn_id, BOOLEAN congested); +static void bta_gattc_req_cback (UINT16 conn_id, UINT32 trans_id, tGATTS_REQ_TYPE type, tGATTS_DATA *p_data); static tBTA_GATTC_FIND_SERVICE_CB bta_gattc_register_service_change_notify(UINT16 conn_id, BD_ADDR remote_bda); static tGATT_CBACK bta_gattc_cl_cback = { @@ -72,7 +73,7 @@ static tGATT_CBACK bta_gattc_cl_cback = { bta_gattc_cmpl_cback, bta_gattc_disc_res_cback, bta_gattc_disc_cmpl_cback, - NULL, + bta_gattc_req_cback, bta_gattc_enc_cmpl_cback, bta_gattc_cong_cback }; @@ -666,11 +667,16 @@ void bta_gattc_conn(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data) if (p_clcb->p_srcb->p_srvc_cache == NULL || p_clcb->p_srcb->state != BTA_GATTC_SERV_IDLE) { if (p_clcb->p_srcb->state == BTA_GATTC_SERV_IDLE) { +#if (GATTC_CACHE_NVS == TRUE) p_clcb->p_srcb->state = BTA_GATTC_SERV_LOAD; if (bta_gattc_cache_load(p_clcb)) { p_clcb->p_srcb->state = BTA_GATTC_SERV_IDLE; bta_gattc_reset_discover_st(p_clcb->p_srcb, BTA_GATT_OK); - } else { /* cache is building */ + //register service change + bta_gattc_register_service_change_notify(p_clcb->bta_conn_id, p_clcb->bda); + } else +#endif + { /* cache is building */ p_clcb->p_srcb->state = BTA_GATTC_SERV_DISC; /* cache load failure, start discovery */ bta_gattc_start_discover(p_clcb, NULL); @@ -1016,9 +1022,10 @@ void bta_gattc_disc_cmpl(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data) list_free(p_clcb->p_srcb->p_srvc_cache); p_clcb->p_srcb->p_srvc_cache = NULL; } - +#if(GATTC_CACHE_NVS == TRUE) /* used to reset cache in application */ bta_gattc_cache_reset(p_clcb->p_srcb->server_bda); +#endif } if (p_clcb->p_srcb && p_clcb->p_srcb->p_srvc_list) { /* release pending attribute list buffer */ @@ -1291,6 +1298,7 @@ void bta_gattc_write_cmpl(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_OP_CMPL *p_data) cb_data.write.conn_id = p_clcb->bta_conn_id; if (p_conn && p_conn->svc_change_descr_handle == cb_data.write.handle) { if(cb_data.write.status != BTA_GATT_OK) { + p_conn->write_remote_svc_change_ccc_done = FALSE; APPL_TRACE_ERROR("service change write ccc failed"); } return; @@ -1716,7 +1724,6 @@ void bta_gattc_process_api_refresh(tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA *p_msg) } if (found) { bta_gattc_sm_execute(p_clcb, BTA_GATTC_INT_DISCOVER_EVT, NULL); - bta_gattc_cache_reset(p_msg->api_conn.remote_bda); return; } } @@ -1726,8 +1733,6 @@ void bta_gattc_process_api_refresh(tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA *p_msg) p_srvc_cb->p_srvc_cache = NULL; } } - /* used to reset cache in application */ - bta_gattc_cache_reset(p_msg->api_conn.remote_bda); } void bta_gattc_process_api_cache_assoc(tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA *p_msg) @@ -1873,6 +1878,10 @@ BOOLEAN bta_gattc_process_srvc_chg_ind(UINT16 conn_id, /* if connection available, refresh cache by doing discovery now */ if (p_clcb != NULL) { + tBTA_GATTC_CONN *p_conn = bta_gattc_conn_find(p_clcb->bda); + if(p_conn) { + p_conn->write_remote_svc_change_ccc_done = FALSE; + } bta_gattc_sm_execute(p_clcb, BTA_GATTC_INT_DISCOVER_EVT, NULL); } } @@ -2085,6 +2094,27 @@ static void bta_gattc_cong_cback (UINT16 conn_id, BOOLEAN congested) } } +/******************************************************************************* +** +** Function bta_gattc_req_cback +** +** Description GATT request command callback for BTA GATT client. +** +** Returns void +** +********************************************************************************/ +static void bta_gattc_req_cback (UINT16 conn_id, UINT32 trans_id, tGATTS_REQ_TYPE type, tGATTS_DATA *p_data) +{ + /* GATTC doesn't need to process the GATT request commands. + * Add this callback here to avoid the warning "Call back not found for application" + * printed in the function gatt_sr_send_req_callback + * */ + UNUSED (conn_id); + UNUSED (trans_id) ; + UNUSED (type); + UNUSED (p_data); +} + #if BLE_INCLUDED == TRUE /******************************************************************************* ** @@ -2257,6 +2287,10 @@ tBTA_GATTC_FIND_SERVICE_CB bta_gattc_register_service_change_notify(UINT16 conn_ tBT_UUID gatt_service_uuid = {LEN_UUID_16, {UUID_SERVCLASS_GATT_SERVER}}; tBT_UUID gatt_service_change_uuid = {LEN_UUID_16, {GATT_UUID_GATT_SRV_CHGD}}; tBT_UUID gatt_ccc_uuid = {LEN_UUID_16, {GATT_UUID_CHAR_CLIENT_CONFIG}}; + tBTA_GATTC_CONN *p_conn = bta_gattc_conn_find_alloc(remote_bda); + if(p_conn && p_conn->write_remote_svc_change_ccc_done) { + return SERVICE_CHANGE_CCC_WRITTEN_SUCCESS; + } p_srcb = bta_gattc_find_srcb(remote_bda); if ((p_srcb != NULL) && (p_srcb->p_srvc_cache != NULL)) { @@ -2321,9 +2355,9 @@ tBTA_GATTC_FIND_SERVICE_CB bta_gattc_register_service_change_notify(UINT16 conn_ } if (gatt_ccc_found == TRUE){ - tBTA_GATTC_CONN *p_conn = bta_gattc_conn_find_alloc(remote_bda); if (p_conn) { p_conn->svc_change_descr_handle = p_desc->handle; + p_conn->write_remote_svc_change_ccc_done = TRUE; } result = SERVICE_CHANGE_CCC_WRITTEN_SUCCESS; uint16_t indicate_value = GATT_CLT_CONFIG_INDICATION; diff --git a/components/bt/bluedroid/bta/gatt/bta_gattc_api.c b/components/bt/bluedroid/bta/gatt/bta_gattc_api.c index b7c292a51e..45a155e1e6 100644 --- a/components/bt/bluedroid/bta/gatt/bta_gattc_api.c +++ b/components/bt/bluedroid/bta/gatt/bta_gattc_api.c @@ -912,12 +912,20 @@ tBTA_GATT_STATUS BTA_GATTC_DeregisterForNotifications (tBTA_GATTC_IF client_if, ** Description Refresh the server cache of the remote device ** ** Parameters remote_bda: remote device BD address. +** erase_flash: delete cache from nvs flash ** ** Returns void ** *******************************************************************************/ -void BTA_GATTC_Refresh(BD_ADDR remote_bda) +void BTA_GATTC_Refresh(BD_ADDR remote_bda, bool erase_flash) { +#if(GATTC_CACHE_NVS == TRUE) + if(erase_flash) { + /* used to reset cache in application */ + bta_gattc_cache_reset(remote_bda); + } +#endif + tBTA_GATTC_API_OPEN *p_buf; if ((p_buf = (tBTA_GATTC_API_OPEN *) osi_malloc(sizeof(tBTA_GATTC_API_OPEN))) != NULL) { diff --git a/components/bt/bluedroid/bta/gatt/bta_gattc_cache.c b/components/bt/bluedroid/bta/gatt/bta_gattc_cache.c index 8a5625356c..90a9d13502 100644 --- a/components/bt/bluedroid/bta/gatt/bta_gattc_cache.c +++ b/components/bt/bluedroid/bta/gatt/bta_gattc_cache.c @@ -346,6 +346,7 @@ static tBTA_GATT_STATUS bta_gattc_add_attr_to_cache(tBTA_GATTC_SERV *p_srvc_cb, tBT_UUID *p_uuid, UINT8 property, UINT16 incl_srvc_s_handle, + UINT16 incl_srvc_e_handle, tBTA_GATTC_ATTR_TYPE type) { #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE) @@ -370,18 +371,13 @@ static tBTA_GATT_STATUS bta_gattc_add_attr_to_cache(tBTA_GATTC_SERV *p_srvc_cb, isvc->handle = handle; memcpy(&isvc->uuid, p_uuid, sizeof(tBT_UUID)); isvc->incl_srvc_s_handle = incl_srvc_s_handle; + isvc->incl_srvc_e_handle = incl_srvc_e_handle; isvc->owning_service = service; isvc->included_service = bta_gattc_find_matching_service( p_srvc_cb->p_srvc_cache, incl_srvc_s_handle); if (!isvc->included_service) { - // if it is a secondary service, wait to update later - if(property == 0){ - p_srvc_cb->update_sec_sev = true; - } else { - APPL_TRACE_ERROR("%s: Illegal action to add non-existing included service!", __func__); - osi_free(isvc); - return GATT_WRONG_STATE; - } + // if can't find included service, wait to update later + p_srvc_cb->update_incl_srvc = true; } list_append(service->included_svc, isvc); @@ -604,10 +600,10 @@ static void bta_gattc_explore_srvc(UINT16 conn_id, tBTA_GATTC_SERV *p_srvc_cb) return; } } - //update include service when have secondary service - if(p_srvc_cb->update_sec_sev) { + // if update_incl_srvc is true, update include service + if(p_srvc_cb->update_incl_srvc) { bta_gattc_update_include_service(p_srvc_cb->p_srvc_cache); - p_srvc_cb->update_sec_sev = false; + p_srvc_cb->update_incl_srvc = false; } /* no service found at all, the end of server discovery*/ APPL_TRACE_DEBUG("%s no more services found", __func__); @@ -622,10 +618,11 @@ static void bta_gattc_explore_srvc(UINT16 conn_id, tBTA_GATTC_SERV *p_srvc_cb) L2CA_EnableUpdateBleConnParams(p_clcb->p_srcb->server_bda, TRUE); } #endif +#if(GATTC_CACHE_NVS == TRUE) /* save cache to NV */ p_clcb->p_srcb->state = BTA_GATTC_SERV_SAVE; - bta_gattc_cache_save(p_clcb->p_srcb, p_clcb->bta_conn_id); +#endif bta_gattc_reset_discover_st(p_clcb->p_srcb, BTA_GATT_OK); } /******************************************************************************* @@ -995,6 +992,7 @@ void bta_gattc_disc_res_cback (UINT16 conn_id, tGATT_DISC_TYPE disc_type, tGATT_ &p_data->value.incl_service.service_type, pri_srvc, p_data->value.incl_service.s_handle, + p_data->value.incl_service.e_handle, BTA_GATTC_ATTR_TYPE_INCL_SRVC); break; @@ -1008,10 +1006,14 @@ void bta_gattc_disc_res_cback (UINT16 conn_id, tGATT_DISC_TYPE disc_type, tGATT_ break; case GATT_DISC_CHAR_DSCPT: - bta_gattc_add_attr_to_cache(p_srvc_cb, p_data->handle, &p_data->type, 0, - 0 /* incl_srvc_handle */, + bta_gattc_add_attr_to_cache(p_srvc_cb, + p_data->handle, + &p_data->type, + 0, + 0 /* incl_srvc_s_handle */, + 0 /* incl_srvc_e_handle */, BTA_GATTC_ATTR_TYPE_CHAR_DESCR); - break; + break; } } } @@ -1352,7 +1354,7 @@ void bta_gattc_get_db_with_opration(UINT16 conn_id, BTGATT_DB_INCLUDED_SERVICE, p_isvc->handle, p_isvc->incl_srvc_s_handle /* s_handle */, - 0 /* e_handle */, + p_isvc->incl_srvc_e_handle /* e_handle */, p_isvc->handle, p_isvc->uuid, 0 /* property */); @@ -1650,7 +1652,8 @@ void bta_gattc_get_db_size_handle(UINT16 conn_id, UINT16 start_handle, UINT16 en tBTA_GATTC_CLCB *p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id); if (p_clcb == NULL) { - return NULL; + *count = 0; + return; } tBTA_GATTC_SERV *p_srcb = p_clcb->p_srcb; @@ -1919,12 +1922,21 @@ void bta_gattc_rebuild_cache(tBTA_GATTC_SERV *p_srvc_cb, UINT16 num_attr, break; case BTA_GATTC_ATTR_TYPE_CHAR_DESCR: + bta_gattc_add_attr_to_cache(p_srvc_cb, + p_attr->s_handle, + &p_attr->uuid, + p_attr->prop, + p_attr->incl_srvc_s_handle, + p_attr->incl_srvc_e_handle, + p_attr->attr_type); + break; case BTA_GATTC_ATTR_TYPE_INCL_SRVC: bta_gattc_add_attr_to_cache(p_srvc_cb, p_attr->s_handle, &p_attr->uuid, p_attr->prop, - p_attr->incl_srvc_handle, + p_attr->incl_srvc_s_handle, + p_attr->incl_srvc_e_handle, p_attr->attr_type); break; } @@ -1943,8 +1955,8 @@ void bta_gattc_rebuild_cache(tBTA_GATTC_SERV *p_srvc_cb, UINT16 num_attr, ** *******************************************************************************/ void bta_gattc_fill_nv_attr(tBTA_GATTC_NV_ATTR *p_attr, UINT8 type, UINT16 s_handle, - UINT16 e_handle, tBT_UUID uuid, UINT8 prop, UINT16 incl_srvc_handle, - BOOLEAN is_primary) + UINT16 e_handle, tBT_UUID uuid, UINT8 prop, UINT16 incl_srvc_s_handle, + UINT16 incl_srvc_e_handle, BOOLEAN is_primary) { p_attr->s_handle = s_handle; p_attr->e_handle = e_handle; @@ -1952,7 +1964,8 @@ void bta_gattc_fill_nv_attr(tBTA_GATTC_NV_ATTR *p_attr, UINT8 type, UINT16 s_han p_attr->is_primary = is_primary; p_attr->id = 0; p_attr->prop = prop; - p_attr->incl_srvc_handle = incl_srvc_handle; + p_attr->incl_srvc_s_handle = incl_srvc_s_handle; + p_attr->incl_srvc_e_handle = incl_srvc_e_handle; memcpy(&p_attr->uuid, &uuid, sizeof(tBT_UUID)); } @@ -1992,7 +2005,8 @@ void bta_gattc_cache_save(tBTA_GATTC_SERV *p_srvc_cb, UINT16 conn_id) p_cur_srvc->e_handle, p_cur_srvc->uuid, 0 /* properties */, - 0 /* incl_srvc_handle */, + 0 /* incl_srvc_s_handle */, + 0 /* incl_srvc_e_handle */, p_cur_srvc->is_primary); } @@ -2013,7 +2027,8 @@ void bta_gattc_cache_save(tBTA_GATTC_SERV *p_srvc_cb, UINT16 conn_id) 0, p_char->uuid, p_char->properties, - 0 /* incl_srvc_handle */, + 0 /* incl_srvc_s_handle */, + 0 /* incl_srvc_e_handle */, FALSE); if (!p_char->descriptors || list_is_empty(p_char->descriptors)) @@ -2029,7 +2044,8 @@ void bta_gattc_cache_save(tBTA_GATTC_SERV *p_srvc_cb, UINT16 conn_id) 0, p_desc->uuid, 0 /* properties */, - 0 /* incl_srvc_handle */, + 0 /* incl_srvc_s_handle */, + 0 /* incl_srvc_e_handle */, FALSE); } } @@ -2048,6 +2064,7 @@ void bta_gattc_cache_save(tBTA_GATTC_SERV *p_srvc_cb, UINT16 conn_id) p_isvc->uuid, 0 /* properties */, p_isvc->included_service->s_handle, + p_isvc->included_service->e_handle, FALSE); } } diff --git a/components/bt/bluedroid/bta/gatt/bta_gattc_co.c b/components/bt/bluedroid/bta/gatt/bta_gattc_co.c index 6c6fc460d3..1a1599af55 100644 --- a/components/bt/bluedroid/bta/gatt/bta_gattc_co.c +++ b/components/bt/bluedroid/bta/gatt/bta_gattc_co.c @@ -75,7 +75,7 @@ static void cacheReset(BD_ADDR bda) #else -static const char *cache_key = "gattc_cahe_key"; +static const char *cache_key = "gattc_cache_key"; static const char *cache_addr = "cache_addr_tab"; nvs_handle nvs_fp; @@ -144,7 +144,7 @@ static void cacheReset(BD_ADDR bda) char fname[255] = {0}; getFilename(fname, bda); UINT8 index = 0; - //cache_env.cache_addr + //cache_env.cache_addr if ((index = bta_gattc_co_find_addr_in_cache(bda)) != INVALID_ADDR_NUM) { //clear the association address pending in the source address. bta_gattc_co_cache_clear_assoc_addr(bda); @@ -152,7 +152,22 @@ static void cacheReset(BD_ADDR bda) nvs_erase_all(cache_env.cache_addr[index].cache_fp); nvs_close(cache_env.cache_addr[index].cache_fp); cache_env.cache_addr[index].is_open = FALSE; + } else { + cacheOpen(bda, false, &index); + if (cache_env.cache_addr[index].is_open) { + nvs_erase_all(cache_env.cache_addr[index].cache_fp); + nvs_close(cache_env.cache_addr[index].cache_fp); + cache_env.cache_addr[index].is_open = FALSE; + } else { + APPL_TRACE_ERROR("%s cacheOpen failed", __func__); + return; + } } + if(cache_env.num_addr == 0) { + APPL_TRACE_ERROR("%s cache addr list error", __func__); + return; + } + UINT8 num = cache_env.num_addr; //delete the server_bda in the addr_info list. for(UINT8 i = index; i < (num - 1); i++) { @@ -160,6 +175,40 @@ static void cacheReset(BD_ADDR bda) } //reduced the number address counter also cache_env.num_addr--; + + //update addr list to nvs flash + if(cache_env.num_addr > 0) { + //update + UINT8 *p_buf = osi_malloc(MAX_ADDR_LIST_CACHE_BUF); + if(!p_buf) { + APPL_TRACE_ERROR("%s malloc error", __func__); + return; + } + UINT16 length = cache_env.num_addr*(sizeof(BD_ADDR) + sizeof(hash_key_t)); + for (UINT8 i = 0; i < cache_env.num_addr; i++) { + //copy the address to the buffer. + memcpy(p_buf + i*(sizeof(BD_ADDR) + sizeof(hash_key_t)), cache_env.cache_addr[i].addr, sizeof(BD_ADDR)); + //copy the hash key to the buffer. + memcpy(p_buf + i*(sizeof(BD_ADDR) + sizeof(hash_key_t)) + sizeof(BD_ADDR), + cache_env.cache_addr[i].hash_key, sizeof(hash_key_t)); + } + if (cache_env.is_open) { + if (nvs_set_blob(cache_env.addr_fp, cache_key, p_buf, length) != ESP_OK) { + APPL_TRACE_WARNING("%s, nvs set blob failed", __func__); + } + } + osi_free(p_buf); + + } else { + //erase + if (cache_env.is_open) { + nvs_erase_all(cache_env.addr_fp); + nvs_close(cache_env.addr_fp); + cache_env.is_open = FALSE; + } else { + APPL_TRACE_WARNING("cache_env status is error"); + } + } } } @@ -325,10 +374,11 @@ void bta_gattc_co_cache_addr_init(void) esp_err_t err_code; UINT8 num_addr; UINT8 *p_buf = osi_malloc(MAX_ADDR_LIST_CACHE_BUF); - size_t length = 0; + size_t length = MAX_ADDR_LIST_CACHE_BUF; if ((err_code = nvs_open(cache_addr, NVS_READWRITE, &fp)) == ESP_OK) { cache_env.addr_fp = fp; + cache_env.is_open = TRUE; // Read previously saved blob if available if ((err_code = nvs_get_blob(fp, cache_key, p_buf, &length)) != ESP_OK) { if(err_code != ESP_ERR_NVS_NOT_FOUND) { @@ -361,6 +411,26 @@ void bta_gattc_co_cache_addr_init(void) return; } +void bta_gattc_co_cache_addr_deinit(void) +{ + if(!cache_env.is_open) { + return; + } + nvs_close(cache_env.addr_fp); + cache_env.is_open = false; + + for(UINT8 i = 0; i< cache_env.num_addr; i++) { + cache_addr_info_t *addr_info = &cache_env.cache_addr[i]; + if(addr_info) { + nvs_close(addr_info->cache_fp); + addr_info->is_open = false; + if(addr_info->assoc_addr) { + list_free(addr_info->assoc_addr); + } + } + } +} + BOOLEAN bta_gattc_co_addr_in_cache(BD_ADDR bda) { UINT8 addr_index = 0; diff --git a/components/bt/bluedroid/bta/gatt/include/bta_gattc_int.h b/components/bt/bluedroid/bta/gatt/include/bta_gattc_int.h index 89864aacea..68887f0891 100644 --- a/components/bt/bluedroid/bta/gatt/include/bta_gattc_int.h +++ b/components/bt/bluedroid/bta/gatt/include/bta_gattc_int.h @@ -300,7 +300,7 @@ typedef struct { UINT16 attr_index; /* cahce NV saving/loading attribute index */ UINT16 mtu; - bool update_sec_sev; + bool update_incl_srvc; } tBTA_GATTC_SERV; #ifndef BTA_GATTC_NOTIF_REG_MAX @@ -365,7 +365,8 @@ typedef struct { typedef struct { BOOLEAN in_use; BD_ADDR remote_bda; - UINT16 svc_change_descr_handle; + UINT16 svc_change_descr_handle; + BOOLEAN write_remote_svc_change_ccc_done; } tBTA_GATTC_CONN; enum { diff --git a/components/bt/bluedroid/bta/hf_client/bta_hf_client_sco.c b/components/bt/bluedroid/bta/hf_client/bta_hf_client_sco.c index 744edc9179..20b0cc7855 100644 --- a/components/bt/bluedroid/bta/hf_client/bta_hf_client_sco.c +++ b/components/bt/bluedroid/bta/hf_client/bta_hf_client_sco.c @@ -46,7 +46,7 @@ static const tBTM_ESCO_PARAMS bta_hf_client_esco_params[] = { BTM_SCO_PKT_TYPES_MASK_NO_3_EV3 | BTM_SCO_PKT_TYPES_MASK_NO_2_EV5 | BTM_SCO_PKT_TYPES_MASK_NO_3_EV5), - .retrans_effort = BTM_ESCO_RETRANS_POWER, + .retrans_effort = BTM_ESCO_RETRANS_OFF, }, /* ESCO CVSD */ { diff --git a/components/bt/bluedroid/bta/include/bta/bta_api.h b/components/bt/bluedroid/bta/include/bta/bta_api.h index 702701bd2e..fe53790939 100644 --- a/components/bt/bluedroid/bta/include/bta/bta_api.h +++ b/components/bt/bluedroid/bta/include/bta/bta_api.h @@ -631,10 +631,11 @@ typedef UINT8 tBTA_SIG_STRENGTH_MASK; #define BTA_DM_SP_RMT_OOB_EXT_EVT 23 /* Simple Pairing Remote OOB Extended Data request. */ #define BTA_DM_BLE_AUTH_CMPL_EVT 24 /* BLE Auth complete */ // btla-specific -- -#define BTA_DM_DEV_UNPAIRED_EVT 25 +#define BTA_DM_DEV_UNPAIRED_EVT 25 /* BT unpair event */ #define BTA_DM_HW_ERROR_EVT 26 /* BT Chip H/W error */ #define BTA_DM_LE_FEATURES_READ 27 /* Cotroller specific LE features are read */ #define BTA_DM_ENER_INFO_READ 28 /* Energy info read */ +#define BTA_DM_BLE_DEV_UNPAIRED_EVT 29 /* BLE unpair event */ typedef UINT8 tBTA_DM_SEC_EVT; /* Structure associated with BTA_DM_ENABLE_EVT */ @@ -1428,7 +1429,7 @@ extern void BTA_DmUpdateWhiteList(BOOLEAN add_remove, BD_ADDR remote_addr, tBTA extern void BTA_DmBleReadAdvTxPower(tBTA_CMPL_CB *cmpl_cb); -extern void BTA_DmBleReadRSSI(BD_ADDR remote_addr, tBTA_CMPL_CB *cmpl_cb); +extern void BTA_DmBleReadRSSI(BD_ADDR remote_addr, tBTA_TRANSPORT transport, tBTA_CMPL_CB *cmpl_cb); /******************************************************************************* ** @@ -1632,7 +1633,7 @@ extern void BTA_DmAddDevice(BD_ADDR bd_addr, DEV_CLASS dev_class, ** BTA_FAIL if operation failed. ** *******************************************************************************/ -extern tBTA_STATUS BTA_DmRemoveDevice(BD_ADDR bd_addr); +extern tBTA_STATUS BTA_DmRemoveDevice(BD_ADDR bd_addr, tBT_TRANSPORT transport); /******************************************************************************* ** diff --git a/components/bt/bluedroid/bta/include/bta/bta_gatt_api.h b/components/bt/bluedroid/bta/include/bta/bta_gatt_api.h index 72eb3643b6..9e59917518 100644 --- a/components/bt/bluedroid/bta/include/bta/bta_gatt_api.h +++ b/components/bt/bluedroid/bta/include/bta/bta_gatt_api.h @@ -282,7 +282,8 @@ typedef struct { UINT8 id; UINT8 prop; /* used when attribute type is characteristic */ BOOLEAN is_primary; /* used when attribute type is service */ - UINT16 incl_srvc_handle; /* used when attribute type is included service */ + UINT16 incl_srvc_s_handle; /* used when attribute type is included service */ + UINT16 incl_srvc_e_handle; /* used when attribute type is included service */ }tBTA_GATTC_NV_ATTR; /* callback data structure */ @@ -691,6 +692,7 @@ typedef struct tBT_UUID uuid; UINT16 handle; UINT16 incl_srvc_s_handle; + UINT16 incl_srvc_e_handle; tBTA_GATTC_SERVICE *owning_service; /* owning service*/ tBTA_GATTC_SERVICE *included_service; } __attribute__((packed)) tBTA_GATTC_INCLUDED_SVC; @@ -1096,11 +1098,12 @@ extern void BTA_GATTC_ReadMultiple(UINT16 conn_id, tBTA_GATTC_MULTI *p_read_mult ** Description Refresh the server cache of the remote device ** ** Parameters remote_bda: remote device BD address. +** erase_flash: delete cache from nvs flash ** ** Returns void ** *******************************************************************************/ -extern void BTA_GATTC_Refresh(BD_ADDR remote_bda); +extern void BTA_GATTC_Refresh(BD_ADDR remote_bda, bool erase_flash); extern void BTA_GATTC_CacheAssoc(tBTA_GATTC_IF client_if, BD_ADDR src_addr, BD_ADDR assoc_addr, BOOLEAN is_assoc); diff --git a/components/bt/bluedroid/bta/include/bta/bta_gattc_co.h b/components/bt/bluedroid/bta/include/bta/bta_gattc_co.h index a902a2edf2..44a0e18ef2 100644 --- a/components/bt/bluedroid/bta/include/bta/bta_gattc_co.h +++ b/components/bt/bluedroid/bta/include/bta/bta_gattc_co.h @@ -113,6 +113,8 @@ extern size_t bta_gattc_get_cache_attr_length(UINT8 index); extern void bta_gattc_co_cache_addr_init(void); +extern void bta_gattc_co_cache_addr_deinit(void); + extern BOOLEAN bta_gattc_co_addr_in_cache(BD_ADDR bda); extern uint8_t bta_gattc_co_find_addr_in_cache(BD_ADDR bda); diff --git a/components/bt/bluedroid/bta/jv/bta_jv_act.c b/components/bt/bluedroid/bta/jv/bta_jv_act.c index 12dfd13b25..de52f5f9eb 100644 --- a/components/bt/bluedroid/bta/jv/bta_jv_act.c +++ b/components/bt/bluedroid/bta/jv/bta_jv_act.c @@ -22,7 +22,6 @@ * ******************************************************************************/ -#include #include #include diff --git a/components/bt/bluedroid/btc/core/btc_dm.c b/components/bt/bluedroid/btc/core/btc_dm.c index 9f6c911058..7e09c9db0f 100644 --- a/components/bt/bluedroid/btc/core/btc_dm.c +++ b/components/bt/bluedroid/btc/core/btc_dm.c @@ -182,6 +182,10 @@ static void btc_dm_remove_ble_bonding_keys(void) static void btc_dm_save_ble_bonding_keys(void) { + if(!(pairing_cb.ble.is_penc_key_rcvd || pairing_cb.ble.is_pid_key_rcvd || pairing_cb.ble.is_pcsrk_key_rcvd || + pairing_cb.ble.is_lenc_key_rcvd || pairing_cb.ble.is_lcsrk_key_rcvd || pairing_cb.ble.is_lidk_key_rcvd)) { + return ; + } bt_bdaddr_t bd_addr; bdcpy(bd_addr.address, pairing_cb.bd_addr); @@ -495,10 +499,23 @@ void btc_dm_sec_cb_handler(btc_msg_t *msg) case BTA_DM_DEV_UNPAIRED_EVT: { #if (SMP_INCLUDED == TRUE) bt_bdaddr_t bd_addr; - rsp_app = true; BTC_TRACE_DEBUG("BTA_DM_DEV_UNPAIRED_EVT"); memcpy(bd_addr.address, p_data->link_down.bd_addr, sizeof(BD_ADDR)); btm_set_bond_type_dev(p_data->link_down.bd_addr, BOND_TYPE_UNKNOWN); + if (p_data->link_down.status == HCI_SUCCESS) { + //remove the bonded key in the config and nvs flash. + btc_storage_remove_bonded_device(&bd_addr); + } +#endif /* #if (SMP_INCLUDED == TRUE) */ + break; + } + case BTA_DM_BLE_DEV_UNPAIRED_EVT: { +#if (SMP_INCLUDED == TRUE) + bt_bdaddr_t bd_addr; + rsp_app = true; + BTC_TRACE_DEBUG("BTA_DM_BLE_DEV_UNPAIRED_EVT"); + memcpy(bd_addr.address, p_data->link_down.bd_addr, sizeof(BD_ADDR)); + btm_set_bond_type_dev(p_data->link_down.bd_addr, BOND_TYPE_UNKNOWN); param.remove_bond_dev_cmpl.status = ESP_BT_STATUS_FAIL; if (p_data->link_down.status == HCI_SUCCESS) { diff --git a/components/bt/bluedroid/btc/core/btc_task.c b/components/bt/bluedroid/btc/core/btc_task.c index b8afbb5814..1022e770d1 100644 --- a/components/bt/bluedroid/btc/core/btc_task.c +++ b/components/bt/bluedroid/btc/core/btc_task.c @@ -170,6 +170,9 @@ int btc_init(void) return BT_STATUS_NOMEM; } btc_gap_callback_init(); +#if SCAN_QUEUE_CONGEST_CHECK + btc_adv_list_init(); +#endif /* TODO: initial the profile_tab */ return BT_STATUS_SUCCESS; } @@ -178,7 +181,18 @@ void btc_deinit(void) { vTaskDelete(xBtcTaskHandle); vQueueDelete(xBtcQueue); - +#if SCAN_QUEUE_CONGEST_CHECK + btc_adv_list_deinit(); +#endif xBtcTaskHandle = NULL; xBtcQueue = 0; } + +bool btc_check_queue_is_congest(void) +{ + UBaseType_t wait_size = uxQueueMessagesWaiting(xBtcQueue); + if(wait_size >= QUEUE_CONGEST_SIZE) { + return true; + } + return false; +} diff --git a/components/bt/bluedroid/btc/include/btc/btc_task.h b/components/bt/bluedroid/btc/include/btc/btc_task.h index f644e865a6..5813c52178 100644 --- a/components/bt/bluedroid/btc/include/btc/btc_task.h +++ b/components/bt/bluedroid/btc/include/btc/btc_task.h @@ -28,6 +28,11 @@ typedef struct btc_msg { void *arg; //param for btc function or function param } btc_msg_t; +typedef struct btc_adv_packet { + uint8_t addr[6]; + uint8_t addr_type; +} btc_adv_packet_t; + typedef enum { BTC_SIG_API_CALL = 0, // APP TO STACK BTC_SIG_API_CB, // STACK TO APP @@ -72,5 +77,6 @@ bt_status_t btc_transfer_context(btc_msg_t *msg, void *arg, int arg_len, btc_arg int btc_init(void); void btc_deinit(void); +bool btc_check_queue_is_congest(void); #endif /* __BTC_TASK_H__ */ diff --git a/components/bt/bluedroid/btc/profile/std/a2dp/btc_a2dp_sink.c b/components/bt/bluedroid/btc/profile/std/a2dp/btc_a2dp_sink.c index 2722b3e9bd..faf23eefc7 100644 --- a/components/bt/bluedroid/btc/profile/std/a2dp/btc_a2dp_sink.c +++ b/components/bt/bluedroid/btc/profile/std/a2dp/btc_a2dp_sink.c @@ -87,8 +87,8 @@ enum { but due to link flow control or thread preemption in lower layers we might need to temporarily buffer up data */ -/* 5 frames is equivalent to 6.89*5*2.9 ~= 100 ms @ 44.1 khz, 20 ms mediatick */ -#define MAX_OUTPUT_A2DP_SNK_FRAME_QUEUE_SZ (5) +/* 18 frames is equivalent to 6.89*18*2.9 ~= 360 ms @ 44.1 khz, 20 ms mediatick */ +#define MAX_OUTPUT_A2DP_SNK_FRAME_QUEUE_SZ (18) typedef struct { UINT16 num_frames_to_be_processed; @@ -763,7 +763,7 @@ static void btc_a2dp_sink_thread_init(UNUSED_ATTR void *context) btc_a2dp_sink_state = BTC_A2DP_SINK_STATE_ON; - btc_aa_snk_cb.RxSbcQ = fixed_queue_new(SIZE_MAX); + btc_aa_snk_cb.RxSbcQ = fixed_queue_new(QUEUE_SIZE_MAX); btc_a2dp_control_init(); } diff --git a/components/bt/bluedroid/btc/profile/std/a2dp/btc_a2dp_source.c b/components/bt/bluedroid/btc/profile/std/a2dp/btc_a2dp_source.c index da5ff32b96..590c382ffe 100644 --- a/components/bt/bluedroid/btc/profile/std/a2dp/btc_a2dp_source.c +++ b/components/bt/bluedroid/btc/profile/std/a2dp/btc_a2dp_source.c @@ -1616,7 +1616,7 @@ static void btc_a2dp_source_thread_init(UNUSED_ATTR void *context) btc_a2dp_source_state = BTC_A2DP_SOURCE_STATE_ON; - btc_aa_src_cb.TxAaQ = fixed_queue_new(SIZE_MAX); + btc_aa_src_cb.TxAaQ = fixed_queue_new(QUEUE_SIZE_MAX); btc_a2dp_control_init(); } diff --git a/components/bt/bluedroid/btc/profile/std/gap/btc_gap_ble.c b/components/bt/bluedroid/btc/profile/std/gap/btc_gap_ble.c index c3937cf652..c8951db4c4 100644 --- a/components/bt/bluedroid/btc/profile/std/gap/btc_gap_ble.c +++ b/components/bt/bluedroid/btc/profile/std/gap/btc_gap_ble.c @@ -28,9 +28,23 @@ #include "btc/btc_ble_storage.h" #include "btc/btc_dm.h" #include "btc/btc_util.h" +#include "osi/mutex.h" static tBTA_BLE_ADV_DATA gl_bta_adv_data; static tBTA_BLE_ADV_DATA gl_bta_scan_rsp_data; +#if SCAN_QUEUE_CONGEST_CHECK +static list_t *adv_filter_list; +static osi_mutex_t adv_list_lock; +bool btc_check_adv_list(uint8_t * addr, uint8_t addr_type); +uint32_t btc_get_adv_list_length(void); +void btc_adv_list_refresh(void); +void btc_adv_list_lock(void); +void btc_adv_list_unlock(void); +static uint16_t btc_adv_list_count = 0; + +#define BTC_ADV_LIST_MAX_LENGTH 50 +#define BTC_ADV_LIST_MAX_COUNT 200 +#endif static inline void btc_gap_ble_cb_to_app(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param) { @@ -510,6 +524,19 @@ static void btc_search_callback(tBTA_DM_SEARCH_EVT event, tBTA_DM_SEARCH *p_data param.scan_rst.search_evt = event; switch (event) { case BTA_DM_INQ_RES_EVT: { +#if SCAN_QUEUE_CONGEST_CHECK + if(btc_check_queue_is_congest()) { + BTC_TRACE_DEBUG("BtcQueue is congested"); + if(btc_get_adv_list_length() > BTC_ADV_LIST_MAX_LENGTH || btc_adv_list_count > BTC_ADV_LIST_MAX_COUNT) { + btc_adv_list_refresh(); + btc_adv_list_count = 0; + } + if(btc_check_adv_list(p_data->inq_res.bd_addr, p_data->inq_res.ble_addr_type)) { + return; + } + } + btc_adv_list_count ++; +#endif bdcpy(param.scan_rst.bda, p_data->inq_res.bd_addr); param.scan_rst.dev_type = p_data->inq_res.device_type; param.scan_rst.rssi = p_data->inq_res.rssi; @@ -585,6 +612,9 @@ static void btc_stop_scan_callback(tBTA_STATUS status) if (ret != BT_STATUS_SUCCESS) { BTC_TRACE_ERROR("%s btc_transfer_context failed\n", __func__); } +#if SCAN_QUEUE_CONGEST_CHECK + btc_adv_list_refresh(); +#endif } void btc_update_conn_param_callback (UINT8 status, BD_ADDR bd_addr, tBTM_LE_UPDATE_CONN_PRAMS *update_conn_params) @@ -725,6 +755,9 @@ static void btc_ble_start_scanning(uint32_t duration, tBTA_START_STOP_SCAN_CMPL_CBACK *start_scan_cb) { if ((results_cb != NULL) && (start_scan_cb != NULL)) { +#if SCAN_QUEUE_CONGEST_CHECK + btc_adv_list_refresh(); +#endif //Start scan the device BTA_DmBleScan(true, duration, results_cb, start_scan_cb); } else { @@ -1018,7 +1051,7 @@ void btc_gap_ble_call_handler(btc_msg_t *msg) BTA_DmUpdateWhiteList(arg->update_white_list.add_remove, arg->update_white_list.remote_bda, btc_add_whitelist_complete_callback); break; case BTC_GAP_BLE_ACT_READ_RSSI: - BTA_DmBleReadRSSI(arg->read_rssi.remote_addr, btc_read_ble_rssi_cmpl_callback); + BTA_DmBleReadRSSI(arg->read_rssi.remote_addr, BTA_TRANSPORT_LE, btc_read_ble_rssi_cmpl_callback); break; case BTC_GAP_BLE_ACT_SET_CONN_PARAMS: BTA_DmSetBlePrefConnParams(arg->set_conn_params.bd_addr, arg->set_conn_params.min_conn_int, @@ -1108,7 +1141,7 @@ void btc_gap_ble_call_handler(btc_msg_t *msg) case BTC_GAP_BLE_REMOVE_BOND_DEV_EVT: { BD_ADDR bd_addr; memcpy(bd_addr, arg->remove_bond_device.bd_addr, sizeof(BD_ADDR)); - BTA_DmRemoveDevice(bd_addr); + BTA_DmRemoveDevice(bd_addr, BT_TRANSPORT_LE); break; } #endif ///SMP_INCLUDED == TRUE @@ -1134,3 +1167,99 @@ void btc_gap_ble_deinit(void) btc_cleanup_adv_data(&gl_bta_adv_data); btc_cleanup_adv_data(&gl_bta_scan_rsp_data); } + +#if SCAN_QUEUE_CONGEST_CHECK +void btc_adv_list_free(void *data) +{ + osi_free(data); +} + +void btc_adv_list_init(void) +{ + osi_mutex_new(&adv_list_lock); + adv_filter_list = list_new(btc_adv_list_free); +} + +void btc_adv_list_deinit(void) +{ + osi_mutex_free(&adv_list_lock); + if(adv_filter_list) { + list_free(adv_filter_list); + adv_filter_list = NULL; + } +} +void btc_adv_list_add_packet(void * data) +{ + if(!data) { + BTC_TRACE_ERROR("%s data is NULL", __func__); + return; + } + btc_adv_list_lock(); + list_prepend(adv_filter_list, data); + btc_adv_list_unlock(); +} + +uint32_t btc_get_adv_list_length(void) +{ + if(!adv_filter_list) { + BTC_TRACE_ERROR("%s adv_filter_list is NULL", __func__); + return 0; + } + btc_adv_list_lock(); + size_t length = list_length(adv_filter_list); + btc_adv_list_unlock(); + + return length; +} + +void btc_adv_list_refresh(void) +{ + if(!adv_filter_list) { + BTC_TRACE_ERROR("%s adv_filter_list is NULL", __func__); + return ; + } + btc_adv_list_lock(); + list_clear(adv_filter_list); + btc_adv_list_unlock(); +} + +bool btc_check_adv_list(uint8_t * addr, uint8_t addr_type) +{ + bool found = false; + if(!adv_filter_list || !addr) { + BTC_TRACE_ERROR("%s adv_filter_list is NULL", __func__); + return found; + } + + btc_adv_list_lock(); + for (const list_node_t *node = list_begin(adv_filter_list); node != list_end(adv_filter_list); node = list_next(node)) { + btc_adv_packet_t *packet = (btc_adv_packet_t *)list_node(node); + if(!bdcmp(addr, packet->addr) && packet->addr_type == addr_type) { + found = true; + break; + } + } + btc_adv_list_unlock(); + if(!found) { + btc_adv_packet_t *adv_packet = osi_malloc(sizeof(btc_adv_packet_t)); + if(adv_packet) { + adv_packet->addr_type = addr_type; + bdcpy(adv_packet->addr, addr); + btc_adv_list_add_packet(adv_packet); + } else { + BTC_TRACE_ERROR("%s adv_packet malloc failed", __func__); + } + } + return found; +} + +void btc_adv_list_lock(void) +{ + osi_mutex_lock(&adv_list_lock, OSI_MUTEX_MAX_TIMEOUT); +} + +void btc_adv_list_unlock(void) +{ + osi_mutex_unlock(&adv_list_lock); +} +#endif diff --git a/components/bt/bluedroid/btc/profile/std/gap/btc_gap_bt.c b/components/bt/bluedroid/btc/profile/std/gap/btc_gap_bt.c index c6a5a0894a..1730bf8b3e 100644 --- a/components/bt/bluedroid/btc/profile/std/gap/btc_gap_bt.c +++ b/components/bt/bluedroid/btc/profile/std/gap/btc_gap_bt.c @@ -151,7 +151,7 @@ static void search_devices_copy_cb(btc_msg_t *msg, void *p_dest, void *p_src) switch (p_dest_data->event) { case BTA_DM_INQ_RES_EVT: { if (p_src_data->p_data->inq_res.p_eir) { - p_dest_data->p_data->inq_res.p_eir = (UINT8 *)(p_dest_data->p_data + sizeof(tBTA_DM_SEARCH)); + p_dest_data->p_data->inq_res.p_eir = (UINT8 *)(p_dest_data->p_data) + sizeof(tBTA_DM_SEARCH); memcpy(p_dest_data->p_data->inq_res.p_eir, p_src_data->p_data->inq_res.p_eir, HCI_EXT_INQ_RESPONSE_LEN); } } @@ -159,7 +159,7 @@ static void search_devices_copy_cb(btc_msg_t *msg, void *p_dest, void *p_src) case BTA_DM_DISC_RES_EVT: { if (p_src_data->p_data->disc_res.raw_data_size && p_src_data->p_data->disc_res.p_raw_data) { - p_dest_data->p_data->disc_res.p_raw_data = (UINT8 *)(p_dest_data->p_data + sizeof(tBTA_DM_SEARCH)); + p_dest_data->p_data->disc_res.p_raw_data = (UINT8 *)(p_dest_data->p_data) + sizeof(tBTA_DM_SEARCH); memcpy(p_dest_data->p_data->disc_res.p_raw_data, p_src_data->p_data->disc_res.p_raw_data, p_src_data->p_data->disc_res.raw_data_size); @@ -194,7 +194,7 @@ static void search_service_record_copy_cb(btc_msg_t *msg, void *p_dest, void *p_ switch (p_dest_data->event) { case BTA_DM_DISC_RES_EVT: { if (p_src_data->p_data->disc_res.p_raw_data && p_src_data->p_data->disc_res.raw_data_size > 0) { - p_dest_data->p_data->disc_res.p_raw_data = (UINT8 *)(p_dest_data->p_data + sizeof(tBTA_DM_SEARCH)); + p_dest_data->p_data->disc_res.p_raw_data = (UINT8 *)(p_dest_data->p_data) + sizeof(tBTA_DM_SEARCH); memcpy(p_dest_data->p_data->disc_res.p_raw_data, p_src_data->p_data->disc_res.p_raw_data, p_src_data->p_data->disc_res.raw_data_size); @@ -566,7 +566,7 @@ static void search_services_copy_cb(btc_msg_t *msg, void *p_dest, void *p_src) case BTA_DM_DISC_RES_EVT: { if (p_src_data->p_data->disc_res.result == BTA_SUCCESS) { if (p_src_data->p_data->disc_res.num_uuids > 0) { - p_dest_data->p_data->disc_res.p_uuid_list = (UINT8 *)(p_dest_data->p_data + sizeof(tBTA_DM_SEARCH)); + p_dest_data->p_data->disc_res.p_uuid_list = (UINT8 *)(p_dest_data->p_data) + sizeof(tBTA_DM_SEARCH); memcpy(p_dest_data->p_data->disc_res.p_uuid_list, p_src_data->p_data->disc_res.p_uuid_list, p_src_data->p_data->disc_res.num_uuids * MAX_UUID_SIZE); osi_free(p_src_data->p_data->disc_res.p_uuid_list); @@ -632,15 +632,14 @@ static void btc_gap_bt_read_rssi_delta_cmpl_callback(void *p_data) static void btc_gap_bt_read_rssi_delta(btc_gap_bt_args_t *arg) { - BTA_DmBleReadRSSI(arg->read_rssi_delta.bda.address, btc_gap_bt_read_rssi_delta_cmpl_callback); + BTA_DmBleReadRSSI(arg->read_rssi_delta.bda.address, BTA_TRANSPORT_BR_EDR, btc_gap_bt_read_rssi_delta_cmpl_callback); } esp_err_t btc_gap_bt_remove_bond_device(btc_gap_bt_args_t *arg) { BD_ADDR bd_addr; memcpy(bd_addr, arg->rm_bond_device.bda.address, sizeof(BD_ADDR)); - if(BTA_DmRemoveDevice(bd_addr) == BTA_SUCCESS){ - btc_storage_remove_bonded_device(&(arg->rm_bond_device.bda)); + if(BTA_DmRemoveDevice(bd_addr, BT_TRANSPORT_BR_EDR) == BTA_SUCCESS){ return ESP_BT_STATUS_SUCCESS; } return ESP_BT_STATUS_FAIL; diff --git a/components/bt/bluedroid/btc/profile/std/gatt/btc_gattc.c b/components/bt/bluedroid/btc/profile/std/gatt/btc_gattc.c index 0694b990f0..bb7d6cbbdf 100644 --- a/components/bt/bluedroid/btc/profile/std/gatt/btc_gattc.c +++ b/components/bt/bluedroid/btc/profile/std/gatt/btc_gattc.c @@ -331,6 +331,7 @@ esp_gatt_status_t btc_ble_gattc_get_service(uint16_t conn_id, esp_bt_uuid_t *svc if (bta_uuid) { osi_free(bta_uuid); } + *count = 0; return status; } else { btc_gattc_fill_gatt_db_conversion(*count, (uint16_t)svc_num, ESP_GATT_DB_PRIMARY_SERVICE, offset, (void *)result, db); @@ -362,6 +363,7 @@ esp_gatt_status_t btc_ble_gattc_get_all_char(uint16_t conn_id, if (db) { osi_free(db); } + *count = 0; return status; } else { btc_gattc_fill_gatt_db_conversion(*count, (uint16_t)char_num, ESP_GATT_DB_CHARACTERISTIC, offset, (void *)result, db); @@ -389,6 +391,7 @@ esp_gatt_status_t btc_ble_gattc_get_all_descr(uint16_t conn_id, if (db) { osi_free(db); } + *count = 0; return status; } else { btc_gattc_fill_gatt_db_conversion(*count, (uint16_t)descr_num, ESP_GATT_DB_DESCRIPTOR, offset, (void *)result, db); @@ -420,6 +423,7 @@ esp_gatt_status_t btc_ble_gattc_get_char_by_uuid(uint16_t conn_id, if (db) { osi_free(db); } + *count = 0; return status; } else { btc_gattc_fill_gatt_db_conversion(*count, (uint16_t)char_num, ESP_GATT_DB_CHARACTERISTIC, 0, (void *)result, db); @@ -456,6 +460,7 @@ esp_gatt_status_t btc_ble_gattc_get_descr_by_uuid(uint16_t conn_id, if (db) { osi_free(db); } + *count = 0; return status; } else { btc_gattc_fill_gatt_db_conversion(*count, (uint16_t)descr_num, ESP_GATT_DB_DESCRIPTOR, 0, (void *)result, db); @@ -487,6 +492,7 @@ esp_gatt_status_t btc_ble_gattc_get_descr_by_char_handle(uint16_t conn_id, if (db) { osi_free(db); } + *count = 0; return status; } else { btc_gattc_fill_gatt_db_conversion(*count, (uint16_t)descr_num, ESP_GATT_DB_DESCRIPTOR, 0, (void *)result, db); @@ -524,6 +530,7 @@ esp_gatt_status_t btc_ble_gattc_get_include_service(uint16_t conn_id, if (db) { osi_free(db); } + *count = 0; return status; }else { btc_gattc_fill_gatt_db_conversion(*count, (uint16_t)incl_num, ESP_GATT_DB_INCLUDED_SERVICE, 0, (void *)result, db); @@ -566,6 +573,7 @@ esp_gatt_status_t btc_ble_gattc_get_db(uint16_t conn_id, uint16_t start_handle, if (get_db) { osi_free(get_db); } + *count = 0; return ESP_GATT_NOT_FOUND; } @@ -579,7 +587,7 @@ esp_gatt_status_t btc_ble_gattc_get_db(uint16_t conn_id, uint16_t start_handle, btc128_to_bta_uuid(&bta_uuid, get_db[i].uuid.uu); bta_to_btc_uuid(&db[i].uuid, &bta_uuid); } - *count = num; + *count = db_size; //don't forget to free the db buffer after used. if (get_db) { osi_free(get_db); @@ -738,7 +746,7 @@ void btc_gattc_call_handler(btc_msg_t *msg) btc_gattc_unreg_for_notify(arg); break; case BTC_GATTC_ACT_CACHE_REFRESH: - BTA_GATTC_Refresh(arg->cache_refresh.remote_bda); + BTA_GATTC_Refresh(arg->cache_refresh.remote_bda, true); break; case BTC_GATTC_ACT_CACHE_ASSOC: BTA_GATTC_CacheAssoc(arg->cache_assoc.gattc_if, diff --git a/components/bt/bluedroid/btc/profile/std/gatt/btc_gatts.c b/components/bt/bluedroid/btc/profile/std/gatt/btc_gatts.c index 74ae46a6ed..fc043914eb 100644 --- a/components/bt/bluedroid/btc/profile/std/gatt/btc_gatts.c +++ b/components/bt/bluedroid/btc/profile/std/gatt/btc_gatts.c @@ -506,6 +506,8 @@ static void btc_gatts_cb_param_copy_req(btc_msg_t *msg, void *p_dest, void *p_sr if (p_dest_data->req_data.p_data != NULL) { memcpy(p_dest_data->req_data.p_data, p_src_data->req_data.p_data, sizeof(tBTA_GATTS_REQ_DATA)); + } else { + BTC_TRACE_ERROR("%s %d no mem\n", __func__, msg->act); } break; @@ -759,6 +761,9 @@ void btc_gatts_cb_handler(btc_msg_t *msg) param.write.conn_id = BTC_GATT_GET_CONN_ID(p_data->req_data.conn_id); param.write.trans_id = p_data->req_data.trans_id; memcpy(param.write.bda, p_data->req_data.remote_bda, ESP_BD_ADDR_LEN); + if (p_data->req_data.p_data == NULL) { + break; + } param.write.handle = p_data->req_data.p_data->write_req.handle; param.write.offset = p_data->req_data.p_data->write_req.offset; param.write.need_rsp = p_data->req_data.p_data->write_req.need_rsp; @@ -775,6 +780,9 @@ void btc_gatts_cb_handler(btc_msg_t *msg) param.exec_write.conn_id = BTC_GATT_GET_CONN_ID(p_data->req_data.conn_id); param.exec_write.trans_id = p_data->req_data.trans_id; memcpy(param.exec_write.bda, p_data->req_data.remote_bda, ESP_BD_ADDR_LEN); + if (p_data->req_data.p_data == NULL) { + break; + } param.exec_write.exec_write_flag = p_data->req_data.p_data->exec_write; btc_gatts_cb_to_app(ESP_GATTS_EXEC_WRITE_EVT, gatts_if, ¶m); diff --git a/components/bt/bluedroid/btc/profile/std/include/btc_gap_ble.h b/components/bt/bluedroid/btc/profile/std/include/btc_gap_ble.h index 9ee03d4117..c9e0f5645a 100644 --- a/components/bt/bluedroid/btc/profile/std/include/btc_gap_ble.h +++ b/components/bt/bluedroid/btc/profile/std/include/btc_gap_ble.h @@ -166,5 +166,7 @@ void btc_gap_ble_cb_deep_free(btc_msg_t *msg); void btc_gap_ble_cb_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src); void btc_gap_callback_init(void); void btc_gap_ble_deinit(void); +void btc_adv_list_init(void); +void btc_adv_list_deinit(void); #endif /* __BTC_GAP_BLE_H__ */ diff --git a/components/bt/bluedroid/common/include/common/bt_defs.h b/components/bt/bluedroid/common/include/common/bt_defs.h index 51ba9a9de1..77719bc847 100644 --- a/components/bt/bluedroid/common/include/common/bt_defs.h +++ b/components/bt/bluedroid/common/include/common/bt_defs.h @@ -26,9 +26,6 @@ #define UNUSED(x) (void)(x) -#ifndef SIZE_MAX -#define SIZE_MAX 254 -#endif /*Timer Related Defination*/ //by Snake.T diff --git a/components/bt/bluedroid/common/include/common/bt_target.h b/components/bt/bluedroid/common/include/common/bt_target.h index fc12bde071..585249d67a 100644 --- a/components/bt/bluedroid/common/include/common/bt_target.h +++ b/components/bt/bluedroid/common/include/common/bt_target.h @@ -94,6 +94,10 @@ #define CLASSIC_BT_INCLUDED FALSE #endif /* CLASSIC_BT_INCLUDED */ +#ifndef CONFIG_GATTC_CACHE_NVS_FLASH +#define CONFIG_GATTC_CACHE_NVS_FLASH FALSE +#endif /* CONFIG_GATTC_CACHE_NVS_FLASH */ + /****************************************************************************** ** ** BLE features @@ -111,6 +115,12 @@ #define GATTC_INCLUDED FALSE #endif /* CONFIG_GATTC_ENABLE */ +#if (CONFIG_GATTC_ENABLE && CONFIG_GATTC_CACHE_NVS_FLASH) +#define GATTC_CACHE_NVS TRUE +#else +#define GATTC_CACHE_NVS FALSE +#endif /* CONFIG_GATTC_CACHE_NVS_FLASH */ + #if (CONFIG_SMP_ENABLE) #define SMP_INCLUDED TRUE #define BLE_PRIVACY_SPT TRUE @@ -297,6 +307,16 @@ #define BTA_AV_CO_CP_SCMS_T FALSE//FALSE #endif +#ifndef QUEUE_CONGEST_SIZE +#define QUEUE_CONGEST_SIZE 40 +#endif + +#ifndef CONFIG_BLE_HOST_QUEUE_CONGESTION_CHECK +#define SCAN_QUEUE_CONGEST_CHECK FALSE +#else +#define SCAN_QUEUE_CONGEST_CHECK CONFIG_BLE_HOST_QUEUE_CONGESTION_CHECK +#endif + /* This feature is used to eanble interleaved scan*/ #ifndef BTA_HOST_INTERLEAVE_SEARCH #define BTA_HOST_INTERLEAVE_SEARCH FALSE//FALSE @@ -571,7 +591,7 @@ #define BTM_DEFAULT_DISC_INTERVAL 0x0800 #endif -/* +/* * {SERVICE_CLASS, MAJOR_CLASS, MINOR_CLASS} * * SERVICE_CLASS:0x5A (Bit17 -Networking,Bit19 - Capturing,Bit20 -Object Transfer,Bit22 -Telephony) @@ -744,6 +764,14 @@ #define BTM_BLE_CONFORMANCE_TESTING FALSE #endif +/****************************************************************************** +** +** CONTROLLER TO HOST FLOW CONTROL +** +******************************************************************************/ + +#define C2H_FLOW_CONTROL_INCLUDED TRUE + /****************************************************************************** ** ** L2CAP diff --git a/components/bt/bluedroid/device/controller.c b/components/bt/bluedroid/device/controller.c index 06b8a52c7c..f0963b4695 100644 --- a/components/bt/bluedroid/device/controller.c +++ b/components/bt/bluedroid/device/controller.c @@ -95,6 +95,12 @@ static void start_up(void) response, &acl_data_size_classic, &acl_buffer_count_classic, &sco_data_size, &sco_buffer_count); +#if (C2H_FLOW_CONTROL_INCLUDED == TRUE) + // Enable controller to host flow control + response = AWAIT_COMMAND(packet_factory->make_set_c2h_flow_control(HCI_HOST_FLOW_CTRL_ACL_ON)); + packet_parser->parse_generic_command_complete(response); +#endif ///C2H_FLOW_CONTROL_INCLUDED == TRUE + // Tell the controller about our buffer sizes and buffer counts next // TODO(zachoverflow): factor this out. eww l2cap contamination. And why just a hardcoded 10? response = AWAIT_COMMAND( @@ -252,6 +258,9 @@ static void start_up(void) #if (BTM_SCO_HCI_INCLUDED == TRUE) response = AWAIT_COMMAND(packet_factory->make_write_sync_flow_control_enable(1)); packet_parser->parse_generic_command_complete(response); + + response = AWAIT_COMMAND(packet_factory->make_write_default_erroneous_data_report(1)); + packet_parser->parse_generic_command_complete(response); #endif readable = true; // return future_new_immediate(FUTURE_SUCCESS); diff --git a/components/bt/bluedroid/hci/hci_hal_h4.c b/components/bt/bluedroid/hci/hci_hal_h4.c index 8b87a6faa0..e910aa7b73 100644 --- a/components/bt/bluedroid/hci/hci_hal_h4.c +++ b/components/bt/bluedroid/hci/hci_hal_h4.c @@ -27,10 +27,16 @@ #include "osi/thread.h" #include "esp_bt.h" +#if (C2H_FLOW_CONTROL_INCLUDED == TRUE) +#include "l2c_int.h" +#include "stack/hcimsgs.h" +#endif ///C2H_FLOW_CONTROL_INCLUDED == TRUE + #define HCI_HAL_SERIAL_BUFFER_SIZE 1026 #define HCI_BLE_EVENT 0x3e #define PACKET_TYPE_TO_INBOUND_INDEX(type) ((type) - 2) #define PACKET_TYPE_TO_INDEX(type) ((type) - 1) +extern bool BTU_check_queue_is_congest(void); static const uint8_t preamble_sizes[] = { @@ -92,6 +98,7 @@ static void hci_hal_env_init( static void hci_hal_env_deinit(void) { fixed_queue_free(hci_hal_env.rx_q, hci_hal_env.allocator->free); + hci_hal_env.rx_q = NULL; } static bool hal_open(const hci_hal_callbacks_t *upper_callbacks) @@ -99,7 +106,7 @@ static bool hal_open(const hci_hal_callbacks_t *upper_callbacks) assert(upper_callbacks != NULL); callbacks = upper_callbacks; - hci_hal_env_init(HCI_HAL_SERIAL_BUFFER_SIZE, SIZE_MAX); + hci_hal_env_init(HCI_HAL_SERIAL_BUFFER_SIZE, QUEUE_SIZE_MAX); xHciH4Queue = xQueueCreate(HCI_H4_QUEUE_LEN, sizeof(BtTaskEvt_t)); xTaskCreatePinnedToCore(hci_hal_h4_rx_handler, HCI_H4_TASK_NAME, HCI_H4_TASK_STACK_SIZE, NULL, HCI_H4_TASK_PRIO, &xHciH4TaskHandle, HCI_H4_TASK_PINNED_TO_CORE); @@ -165,6 +172,7 @@ static void hci_hal_h4_rx_handler(void *arg) if (pdTRUE == xQueueReceive(xHciH4Queue, &e, (portTickType)portMAX_DELAY)) { if (e.sig == SIG_HCI_HAL_RECV_PACKET) { fixed_queue_process(hci_hal_env.rx_q); + } } } @@ -178,13 +186,51 @@ task_post_status_t hci_hal_h4_task_post(task_post_t timeout) evt.par = 0; if (xQueueSend(xHciH4Queue, &evt, timeout) != pdTRUE) { - HCI_TRACE_ERROR("xHciH4Queue failed\n"); return TASK_POST_SUCCESS; } return TASK_POST_FAIL; } +#if (C2H_FLOW_CONTROL_INCLUDED == TRUE) +static void hci_packet_complete(BT_HDR *packet){ + uint8_t type, num_handle; + uint16_t handle; + uint16_t handles[MAX_L2CAP_LINKS + 4]; + uint16_t num_packets[MAX_L2CAP_LINKS + 4]; + uint8_t *stream = packet->data + packet->offset; + tL2C_LCB *p_lcb = NULL; + + STREAM_TO_UINT8(type, stream); + if (type == DATA_TYPE_ACL/* || type == DATA_TYPE_SCO*/) { + STREAM_TO_UINT16(handle, stream); + handle = handle & HCI_DATA_HANDLE_MASK; + p_lcb = l2cu_find_lcb_by_handle(handle); + if (p_lcb) { + p_lcb->completed_packets++; + } + if (esp_vhci_host_check_send_available()){ + num_handle = l2cu_find_completed_packets(handles, num_packets); + if (num_handle > 0){ + btsnd_hcic_host_num_xmitted_pkts (num_handle, handles, num_packets); + } + } else { + //Send HCI_Host_Number_of_Completed_Packets next time. + } + + } +} +#endif ///C2H_FLOW_CONTROL_INCLUDED == TRUE + +bool host_recv_adv_packet(BT_HDR *packet) +{ + assert(packet); + if(packet->data[0] == DATA_TYPE_EVENT && packet->data[1] == HCI_BLE_EVENT && packet->data[3] == HCI_BLE_ADV_PKT_RPT_EVT) { + return true; + } + return false; +} + static void hci_hal_h4_hdl_rx_packet(BT_HDR *packet) { uint8_t type, hdr_size; @@ -194,6 +240,11 @@ static void hci_hal_h4_hdl_rx_packet(BT_HDR *packet) if (!packet) { return; } + +#if (C2H_FLOW_CONTROL_INCLUDED == TRUE) + hci_packet_complete(packet); +#endif ///C2H_FLOW_CONTROL_INCLUDED == TRUE + STREAM_TO_UINT8(type, stream); packet->offset++; packet->len--; @@ -233,6 +284,13 @@ static void hci_hal_h4_hdl_rx_packet(BT_HDR *packet) hci_hal_env.allocator->free(packet); return; } +#if SCAN_QUEUE_CONGEST_CHECK + if(BTU_check_queue_is_congest() && host_recv_adv_packet(packet)) { + HCI_TRACE_ERROR("BtuQueue is congested"); + hci_hal_env.allocator->free(packet); + return; + } +#endif packet->event = outbound_event_types[PACKET_TYPE_TO_INDEX(type)]; callbacks->packet_ready(packet); @@ -260,6 +318,10 @@ static int host_recv_pkt_cb(uint8_t *data, uint16_t len) BT_HDR *pkt; size_t pkt_size; + if (hci_hal_env.rx_q == NULL) { + return 0; + } + pkt_size = BT_HDR_SIZE + len; pkt = (BT_HDR *)hci_hal_env.allocator->alloc(pkt_size); if (!pkt) { @@ -271,7 +333,7 @@ static int host_recv_pkt_cb(uint8_t *data, uint16_t len) pkt->layer_specific = 0; memcpy(pkt->data, data, len); fixed_queue_enqueue(hci_hal_env.rx_q, pkt); - hci_hal_h4_task_post(TASK_POST_BLOCKING); + hci_hal_h4_task_post(100 / portTICK_PERIOD_MS); BTTRC_DUMP_BUFFER("Recv Pkt", pkt->data, len); diff --git a/components/bt/bluedroid/hci/hci_layer.c b/components/bt/bluedroid/hci/hci_layer.c index 59b08c4810..b2120593ab 100644 --- a/components/bt/bluedroid/hci/hci_layer.c +++ b/components/bt/bluedroid/hci/hci_layer.c @@ -158,7 +158,7 @@ static int hci_layer_init_env(void) // as per the Bluetooth spec, Volume 2, Part E, 4.4 (Command Flow Control) // This value can change when you get a command complete or command status event. hci_host_env.command_credits = 1; - hci_host_env.command_queue = fixed_queue_new(SIZE_MAX); + hci_host_env.command_queue = fixed_queue_new(QUEUE_SIZE_MAX); if (hci_host_env.command_queue) { fixed_queue_register_dequeue(hci_host_env.command_queue, event_command_ready); } else { @@ -166,7 +166,7 @@ static int hci_layer_init_env(void) return -1; } - hci_host_env.packet_queue = fixed_queue_new(SIZE_MAX); + hci_host_env.packet_queue = fixed_queue_new(QUEUE_SIZE_MAX); if (hci_host_env.packet_queue) { fixed_queue_register_dequeue(hci_host_env.packet_queue, event_packet_ready); } else { @@ -274,6 +274,7 @@ static void transmit_command( fixed_queue_enqueue(hci_host_env.command_queue, wait_entry); hci_host_task_post(TASK_POST_BLOCKING); + } static future_t *transmit_command_futured(BT_HDR *command) @@ -317,8 +318,14 @@ static void event_command_ready(fixed_queue_t *queue) command_waiting_response_t *cmd_wait_q = &hci_host_env.cmd_waiting_q; wait_entry = fixed_queue_dequeue(queue); - hci_host_env.command_credits--; + if(wait_entry->opcode == HCI_HOST_NUM_PACKETS_DONE){ + packet_fragmenter->fragment_and_dispatch(wait_entry->command); + buffer_allocator->free(wait_entry->command); + osi_free(wait_entry); + return; + } + hci_host_env.command_credits--; // Move it to the list of commands awaiting response osi_mutex_lock(&cmd_wait_q->commands_pending_response_lock, OSI_MUTEX_MAX_TIMEOUT); list_append(cmd_wait_q->commands_pending_response, wait_entry); @@ -435,7 +442,6 @@ static bool filter_incoming_event(BT_HDR *packet) if (event_code == HCI_COMMAND_COMPLETE_EVT) { STREAM_TO_UINT8(hci_host_env.command_credits, stream); STREAM_TO_UINT16(opcode, stream); - wait_entry = get_waiting_command(opcode); if (!wait_entry) { HCI_TRACE_WARNING("%s command complete event with no matching command. opcode: 0x%x.", __func__, opcode); diff --git a/components/bt/bluedroid/hci/hci_packet_factory.c b/components/bt/bluedroid/hci/hci_packet_factory.c index 2c88570e3d..45f3f687fc 100644 --- a/components/bt/bluedroid/hci/hci_packet_factory.c +++ b/components/bt/bluedroid/hci/hci_packet_factory.c @@ -45,6 +45,16 @@ static BT_HDR *make_read_buffer_size(void) return make_command_no_params(HCI_READ_BUFFER_SIZE); } +static BT_HDR *make_set_c2h_flow_control(uint8_t enable) +{ + uint8_t *stream; + const uint8_t parameter_size = 1; + BT_HDR *packet = make_command(HCI_SET_HC_TO_HOST_FLOW_CTRL, parameter_size, &stream); + + UINT8_TO_STREAM(stream, enable); + return packet; +} + static BT_HDR *make_host_buffer_size(uint16_t acl_size, uint8_t sco_size, uint16_t acl_count, uint16_t sco_count) { uint8_t *stream; @@ -184,6 +194,16 @@ static BT_HDR *make_write_sync_flow_control_enable(uint8_t enable) UINT8_TO_STREAM(stream, enable); return packet; } + +static BT_HDR *make_write_default_erroneous_data_report(uint8_t enable) +{ + uint8_t *stream; + const uint8_t parameter_size = 1; + BT_HDR *packet = make_command(HCI_WRITE_ERRONEOUS_DATA_RPT, parameter_size, &stream); + + UINT8_TO_STREAM(stream, enable); + return packet; +} // Internal functions static BT_HDR *make_command_no_params(uint16_t opcode) @@ -220,6 +240,7 @@ static BT_HDR *make_packet(size_t data_size) static const hci_packet_factory_t interface = { make_reset, make_read_buffer_size, + make_set_c2h_flow_control, make_host_buffer_size, make_read_local_version_info, make_read_bd_addr, @@ -237,7 +258,8 @@ static const hci_packet_factory_t interface = { make_ble_read_suggested_default_data_length, make_ble_write_suggested_default_data_length, make_ble_set_event_mask, - make_write_sync_flow_control_enable + make_write_sync_flow_control_enable, + make_write_default_erroneous_data_report, }; const hci_packet_factory_t *hci_packet_factory_get_interface() diff --git a/components/bt/bluedroid/hci/include/hci/hci_packet_factory.h b/components/bt/bluedroid/hci/include/hci/hci_packet_factory.h index 0cc4dc6849..21bd2c9a62 100644 --- a/components/bt/bluedroid/hci/include/hci/hci_packet_factory.h +++ b/components/bt/bluedroid/hci/include/hci/hci_packet_factory.h @@ -25,6 +25,7 @@ typedef struct { BT_HDR *(*make_reset)(void); BT_HDR *(*make_read_buffer_size)(void); + BT_HDR *(*make_set_c2h_flow_control)(uint8_t enable); BT_HDR *(*make_host_buffer_size)(uint16_t acl_size, uint8_t sco_size, uint16_t acl_count, uint16_t sco_count); BT_HDR *(*make_read_local_version_info)(void); BT_HDR *(*make_read_bd_addr)(void); @@ -43,6 +44,7 @@ typedef struct { BT_HDR *(*make_ble_write_suggested_default_data_length)(uint16_t SuggestedMaxTxOctets, uint16_t SuggestedMaxTxTime); BT_HDR *(*make_ble_set_event_mask)(const bt_event_mask_t *event_mask); BT_HDR *(*make_write_sync_flow_control_enable)(uint8_t enable); + BT_HDR *(*make_write_default_erroneous_data_report)(uint8_t enable); } hci_packet_factory_t; const hci_packet_factory_t *hci_packet_factory_get_interface(); diff --git a/components/bt/bluedroid/osi/include/osi/fixed_queue.h b/components/bt/bluedroid/osi/include/osi/fixed_queue.h index e3bf2f67b5..5ec0c07498 100644 --- a/components/bt/bluedroid/osi/include/osi/fixed_queue.h +++ b/components/bt/bluedroid/osi/include/osi/fixed_queue.h @@ -22,6 +22,10 @@ #include #include "osi/list.h" +#ifndef QUEUE_SIZE_MAX +#define QUEUE_SIZE_MAX 254 +#endif + struct fixed_queue_t; typedef struct fixed_queue_t fixed_queue_t; diff --git a/components/bt/bluedroid/osi/include/osi/thread.h b/components/bt/bluedroid/osi/include/osi/thread.h index 8bb2fdc7c0..1aa773c018 100644 --- a/components/bt/bluedroid/osi/include/osi/thread.h +++ b/components/bt/bluedroid/osi/include/osi/thread.h @@ -69,7 +69,7 @@ typedef enum { #define HCI_H4_TASK_STACK_SIZE (2048 + BT_TASK_EXTRA_STACK_SIZE) #define HCI_H4_TASK_PRIO (configMAX_PRIORITIES - 4) #define HCI_H4_TASK_NAME "hciH4T" -#define HCI_H4_QUEUE_LEN 60 +#define HCI_H4_QUEUE_LEN 1 #define BTU_TASK_PINNED_TO_CORE (TASK_PINNED_TO_CORE) #define BTU_TASK_STACK_SIZE (4096 + BT_TASK_EXTRA_STACK_SIZE) diff --git a/components/bt/bluedroid/stack/avct/avct_lcb.c b/components/bt/bluedroid/stack/avct/avct_lcb.c index 7d5ba3a16e..61f6c9a556 100644 --- a/components/bt/bluedroid/stack/avct/avct_lcb.c +++ b/components/bt/bluedroid/stack/avct/avct_lcb.c @@ -313,7 +313,7 @@ tAVCT_LCB *avct_lcb_alloc(BD_ADDR bd_addr) p_lcb->allocated = (UINT8)(i + 1); memcpy(p_lcb->peer_addr, bd_addr, BD_ADDR_LEN); AVCT_TRACE_DEBUG("avct_lcb_alloc %d", p_lcb->allocated); - p_lcb->tx_q = fixed_queue_new(SIZE_MAX); + p_lcb->tx_q = fixed_queue_new(QUEUE_SIZE_MAX); break; } } diff --git a/components/bt/bluedroid/stack/avdt/avdt_ccb.c b/components/bt/bluedroid/stack/avdt/avdt_ccb.c index 5e1a1f46de..035488f854 100644 --- a/components/bt/bluedroid/stack/avdt/avdt_ccb.c +++ b/components/bt/bluedroid/stack/avdt/avdt_ccb.c @@ -376,8 +376,8 @@ tAVDT_CCB *avdt_ccb_alloc(BD_ADDR bd_addr) if (!p_ccb->allocated) { p_ccb->allocated = TRUE; memcpy(p_ccb->peer_addr, bd_addr, BD_ADDR_LEN); - p_ccb->cmd_q = fixed_queue_new(SIZE_MAX); - p_ccb->rsp_q = fixed_queue_new(SIZE_MAX); + p_ccb->cmd_q = fixed_queue_new(QUEUE_SIZE_MAX); + p_ccb->rsp_q = fixed_queue_new(QUEUE_SIZE_MAX); p_ccb->timer_entry.param = (UINT32) p_ccb; AVDT_TRACE_DEBUG("avdt_ccb_alloc %d\n", i); break; diff --git a/components/bt/bluedroid/stack/avdt/avdt_l2c.c b/components/bt/bluedroid/stack/avdt/avdt_l2c.c index 92e3dcad9d..3227fa69b3 100644 --- a/components/bt/bluedroid/stack/avdt/avdt_l2c.c +++ b/components/bt/bluedroid/stack/avdt/avdt_l2c.c @@ -412,6 +412,7 @@ void avdt_l2c_disconnect_ind_cback(UINT16 lcid, BOOLEAN ack_needed) { tAVDT_TC_TBL *p_tbl; UINT16 disc_rsn = AVDT_DISC_RSN_NORMAL; + tAVDT_CCB *p_ccb; AVDT_TRACE_DEBUG("avdt_l2c_disconnect_ind_cback lcid: %d, ack_needed: %d\n", lcid, ack_needed); /* look up info for this channel */ @@ -420,7 +421,13 @@ void avdt_l2c_disconnect_ind_cback(UINT16 lcid, BOOLEAN ack_needed) /* send L2CAP disconnect response */ L2CA_DisconnectRsp(lcid); } else { - disc_rsn = AVDT_DISC_RSN_ABNORMAL; + if ((p_ccb = avdt_ccb_by_idx(p_tbl->ccb_idx)) != NULL) { + UINT16 rsn = L2CA_GetDisconnectReason(p_ccb->peer_addr, BT_TRANSPORT_BR_EDR); + if (rsn != 0 && rsn != HCI_ERR_PEER_USER) { + disc_rsn = AVDT_DISC_RSN_ABNORMAL; + AVDT_TRACE_EVENT("avdt link disc rsn 0x%x", rsn); + } + } } avdt_ad_tc_close_ind(p_tbl, disc_rsn); diff --git a/components/bt/bluedroid/stack/avdt/avdt_scb.c b/components/bt/bluedroid/stack/avdt/avdt_scb.c index cf3c1ad331..ac6cbce388 100644 --- a/components/bt/bluedroid/stack/avdt/avdt_scb.c +++ b/components/bt/bluedroid/stack/avdt/avdt_scb.c @@ -603,7 +603,7 @@ tAVDT_SCB *avdt_scb_alloc(tAVDT_CS *p_cs) memcpy(&p_scb->cs, p_cs, sizeof(tAVDT_CS)); #if AVDT_MULTIPLEXING == TRUE /* initialize fragments gueue */ - p_scb->frag_q = fixed_queue_new(SIZE_MAX); + p_scb->frag_q = fixed_queue_new(QUEUE_SIZE_MAX); if (p_cs->cfg.psc_mask & AVDT_PSC_MUX) { p_scb->cs.cfg.mux_tcid_media = avdt_ad_type_to_tcid(AVDT_CHAN_MEDIA, p_scb); diff --git a/components/bt/bluedroid/stack/btm/btm_acl.c b/components/bt/bluedroid/stack/btm/btm_acl.c index 84fa0d6b71..5bf59c895c 100644 --- a/components/bt/bluedroid/stack/btm/btm_acl.c +++ b/components/bt/bluedroid/stack/btm/btm_acl.c @@ -1905,14 +1905,10 @@ void btm_qos_setup_complete (UINT8 status, UINT16 handle, FLOW_SPEC *p_flow) ** Returns BTM_CMD_STARTED if successfully initiated or error code ** *******************************************************************************/ -tBTM_STATUS BTM_ReadRSSI (BD_ADDR remote_bda, tBTM_CMPL_CB *p_cb) +tBTM_STATUS BTM_ReadRSSI (BD_ADDR remote_bda, tBT_TRANSPORT transport, tBTM_CMPL_CB *p_cb) { tACL_CONN *p; - tBT_TRANSPORT transport = BT_TRANSPORT_BR_EDR; -#if BLE_INCLUDED == TRUE - tBT_DEVICE_TYPE dev_type; - tBLE_ADDR_TYPE addr_type; -#endif + BTM_TRACE_API ("BTM_ReadRSSI: RemBdAddr: %02x%02x%02x%02x%02x%02x\n", remote_bda[0], remote_bda[1], remote_bda[2], remote_bda[3], remote_bda[4], remote_bda[5]); @@ -1924,13 +1920,6 @@ tBTM_STATUS BTM_ReadRSSI (BD_ADDR remote_bda, tBTM_CMPL_CB *p_cb) return (BTM_BUSY); } -#if BLE_INCLUDED == TRUE - BTM_ReadDevInfo(remote_bda, &dev_type, &addr_type); - if (dev_type == BT_DEVICE_TYPE_BLE) { - transport = BT_TRANSPORT_LE; - } -#endif - p = btm_bda_to_acl(remote_bda, transport); if (p != (tACL_CONN *)NULL) { btu_start_timer (&btm_cb.devcb.rssi_timer, BTU_TTYPE_BTM_ACL, diff --git a/components/bt/bluedroid/stack/btm/btm_ble.c b/components/bt/bluedroid/stack/btm/btm_ble.c index 2d3c751724..0de41650c0 100644 --- a/components/bt/bluedroid/stack/btm/btm_ble.c +++ b/components/bt/bluedroid/stack/btm/btm_ble.c @@ -1225,7 +1225,7 @@ void btm_sec_save_le_key(BD_ADDR bd_addr, tBTM_LE_KEY_TYPE key_type, tBTM_LE_KEY /* Set that link key is known since this shares field with BTM_SEC_FLAG_LKEY_KNOWN flag in stack/btm_api.h*/ p_rec->sec_flags |= BTM_SEC_LE_LINK_KEY_KNOWN; - if ( p_keys->pcsrk_key.sec_level == SMP_SEC_AUTHENTICATED) { + if ( p_keys->lenc_key.sec_level == SMP_SEC_AUTHENTICATED) { p_rec->sec_flags |= BTM_SEC_LE_LINK_KEY_AUTHED; } else { p_rec->sec_flags &= ~BTM_SEC_LE_LINK_KEY_AUTHED; @@ -1948,14 +1948,6 @@ void btm_ble_conn_complete(UINT8 *p, UINT16 evt_len, BOOLEAN enhanced) handle = HCID_GET_HANDLE (handle); btm_ble_connected(bda, handle, HCI_ENCRYPT_MODE_DISABLED, role, bda_type, match); - if(role == HCI_ROLE_SLAVE) { - //clear p_cb->state, controller will stop adv when ble connected. - tBTM_BLE_INQ_CB *p_cb = &btm_cb.ble_ctr_cb.inq_var; - if(p_cb) { - p_cb->adv_mode = BTM_BLE_ADV_DISABLE; - p_cb->state = BTM_BLE_STOP_ADV; - } - } l2cble_conn_comp (handle, role, bda, bda_type, conn_interval, conn_latency, conn_timeout); diff --git a/components/bt/bluedroid/stack/btm/btm_ble_gap.c b/components/bt/bluedroid/stack/btm/btm_ble_gap.c index 109a816896..d36e32a111 100644 --- a/components/bt/bluedroid/stack/btm/btm_ble_gap.c +++ b/components/bt/bluedroid/stack/btm/btm_ble_gap.c @@ -3457,15 +3457,21 @@ tBTM_STATUS btm_ble_start_adv(void) btm_execute_wl_dev_operation(); btm_cb.ble_ctr_cb.wl_state |= BTM_BLE_WL_ADV; } - + /* The complete event comes up immediately after the 'btsnd_hcic_ble_set_adv_enable' being called in dual core, + this causes the 'adv_mode' and 'state' not be set yet, so we set the state first */ + tBTM_BLE_GAP_STATE temp_state = p_cb->state; + UINT8 adv_mode = p_cb->adv_mode; + p_cb->adv_mode = BTM_BLE_ADV_ENABLE; + p_cb->state = BTM_BLE_ADV_PENDING; + btm_ble_adv_states_operation(btm_ble_set_topology_mask, p_cb->evt_type); if (btsnd_hcic_ble_set_adv_enable (BTM_BLE_ADV_ENABLE)) { - p_cb->adv_mode = BTM_BLE_ADV_ENABLE; - p_cb->state = BTM_BLE_ADV_PENDING; - btm_ble_adv_states_operation(btm_ble_set_topology_mask, p_cb->evt_type); rt = BTM_SUCCESS; BTM_TRACE_EVENT ("BTM_SUCCESS\n"); } else { p_cb->adv_mode = BTM_BLE_ADV_DISABLE; + p_cb->state = temp_state; + p_cb->adv_mode = adv_mode; + btm_ble_adv_states_operation(btm_ble_clear_topology_mask, p_cb->evt_type); btm_cb.ble_ctr_cb.wl_state &= ~BTM_BLE_WL_ADV; } return rt; @@ -3486,15 +3492,30 @@ tBTM_STATUS btm_ble_stop_adv(void) tBTM_STATUS rt = BTM_SUCCESS; if (p_cb->adv_mode == BTM_BLE_ADV_ENABLE) { - if (btsnd_hcic_ble_set_adv_enable (BTM_BLE_ADV_DISABLE)) { - p_cb->fast_adv_on = FALSE; - p_cb->adv_mode = BTM_BLE_ADV_DISABLE; - p_cb->state = BTM_BLE_ADV_PENDING; - btm_cb.ble_ctr_cb.wl_state &= ~BTM_BLE_WL_ADV; + UINT8 temp_adv_mode = p_cb->adv_mode; + BOOLEAN temp_fast_adv_on = p_cb->fast_adv_on; + tBTM_BLE_GAP_STATE temp_state = p_cb->state; + tBTM_BLE_WL_STATE temp_wl_state = btm_cb.ble_ctr_cb.wl_state; + tBTM_BLE_STATE_MASK temp_mask = btm_ble_get_topology_mask (); + + p_cb->fast_adv_on = FALSE; + p_cb->adv_mode = BTM_BLE_ADV_DISABLE; + p_cb->state = BTM_BLE_ADV_PENDING; + btm_cb.ble_ctr_cb.wl_state &= ~BTM_BLE_WL_ADV; + + /* clear all adv states */ + btm_ble_clear_topology_mask (BTM_BLE_STATE_ALL_ADV_MASK); + + if (btsnd_hcic_ble_set_adv_enable (BTM_BLE_ADV_DISABLE)) { - /* clear all adv states */ - btm_ble_clear_topology_mask (BTM_BLE_STATE_ALL_ADV_MASK); } else { + // reset state + p_cb->fast_adv_on = temp_fast_adv_on; + p_cb->adv_mode = temp_adv_mode; + p_cb->state = temp_state; + btm_cb.ble_ctr_cb.wl_state = temp_wl_state; + btm_ble_set_topology_mask (temp_mask); + rt = BTM_NO_RESOURCES; } } @@ -3739,6 +3760,20 @@ BOOLEAN btm_ble_clear_topology_mask (tBTM_BLE_STATE_MASK request_state_mask) return TRUE; } +/******************************************************************************* +** +** Function btm_ble_get_topology_mask +** +** Description Get BLE topology bit mask +** +** Returns state mask. +** +*******************************************************************************/ +tBTM_BLE_STATE_MASK btm_ble_get_topology_mask (void) +{ + return btm_cb.ble_ctr_cb.cur_states; +} + /******************************************************************************* ** ** Function btm_ble_update_link_topology_mask @@ -3832,7 +3867,7 @@ void btm_ble_init (void) btm_cb.cmn_ble_vsc_cb.values_read = FALSE; p_cb->cur_states = 0; - p_cb->conn_pending_q = fixed_queue_new(SIZE_MAX); + p_cb->conn_pending_q = fixed_queue_new(QUEUE_SIZE_MAX); p_cb->inq_var.adv_mode = BTM_BLE_ADV_DISABLE; p_cb->inq_var.scan_type = BTM_BLE_SCAN_MODE_NONE; diff --git a/components/bt/bluedroid/stack/btm/btm_main.c b/components/bt/bluedroid/stack/btm/btm_main.c index d1ba6acba6..579e8d6453 100644 --- a/components/bt/bluedroid/stack/btm/btm_main.c +++ b/components/bt/bluedroid/stack/btm/btm_main.c @@ -56,8 +56,8 @@ void btm_init (void) #endif /* #if BTM_DYNAMIC_MEMORY */ /* All fields are cleared; nonzero fields are reinitialized in appropriate function */ memset(&btm_cb, 0, sizeof(tBTM_CB)); - btm_cb.page_queue = fixed_queue_new(SIZE_MAX); - btm_cb.sec_pending_q = fixed_queue_new(SIZE_MAX); + btm_cb.page_queue = fixed_queue_new(QUEUE_SIZE_MAX); + btm_cb.sec_pending_q = fixed_queue_new(QUEUE_SIZE_MAX); #if defined(BTM_INITIAL_TRACE_LEVEL) btm_cb.trace_level = BTM_INITIAL_TRACE_LEVEL; diff --git a/components/bt/bluedroid/stack/btm/btm_sco.c b/components/bt/bluedroid/stack/btm/btm_sco.c index e04209aab5..6b8a32befd 100644 --- a/components/bt/bluedroid/stack/btm/btm_sco.c +++ b/components/bt/bluedroid/stack/btm/btm_sco.c @@ -113,7 +113,7 @@ void btm_sco_init (void) #endif #if (BTM_SCO_HCI_INCLUDED == TRUE) for (int i = 0; i < BTM_MAX_SCO_LINKS; i++) { - btm_cb.sco_cb.sco_db[i].xmit_data_q = fixed_queue_new(SIZE_MAX); + btm_cb.sco_cb.sco_db[i].xmit_data_q = fixed_queue_new(QUEUE_SIZE_MAX); } #endif /* Initialize nonzero defaults */ @@ -319,9 +319,8 @@ void btm_sco_process_num_completed_pkts (UINT8 *p) STREAM_TO_UINT8 (num_handles, p); for (xx = 0; xx < num_handles; xx++) { STREAM_TO_UINT16 (handle, p); - handle &= 0x7ff; // walk around for bad handle bit mask from controller STREAM_TO_UINT16 (num_sent, p); - if ((sco_inx = btm_find_scb_by_handle(handle & 0x7ff)) == BTM_MAX_SCO_LINKS) { + if ((sco_inx = btm_find_scb_by_handle(handle)) == BTM_MAX_SCO_LINKS) { continue; } BTM_TRACE_DEBUG("%s, %d, %u", __FUNCTION__, handle, p_cb->xmit_window_size); //debug diff --git a/components/bt/bluedroid/stack/btm/btm_sec.c b/components/bt/bluedroid/stack/btm/btm_sec.c index 71d888902d..3b928abc8f 100644 --- a/components/bt/bluedroid/stack/btm/btm_sec.c +++ b/components/bt/bluedroid/stack/btm/btm_sec.c @@ -1361,7 +1361,7 @@ tBTM_STATUS BTM_SetEncryption (BD_ADDR bd_addr, tBT_TRANSPORT transport, tBTM_SE return (BTM_SUCCESS); } - + p_dev_rec->enc_init_by_we = TRUE; /* enqueue security request if security is active */ if (p_dev_rec->p_callback || (p_dev_rec->sec_state != BTM_SEC_STATE_IDLE)) { BTM_TRACE_WARNING ("Security Manager: BTM_SetEncryption busy, enqueue request\n"); @@ -2762,7 +2762,7 @@ void btm_sec_check_pending_reqs (void) /* Now, re-submit anything in the mux queue */ bq = btm_cb.sec_pending_q; if (!btm_cb.sec_pending_q) { - btm_cb.sec_pending_q = fixed_queue_new(SIZE_MAX); + btm_cb.sec_pending_q = fixed_queue_new(QUEUE_SIZE_MAX); } while ((p_e = (tBTM_SEC_QUEUE_ENTRY *)fixed_queue_try_dequeue(bq)) != NULL) { @@ -4018,7 +4018,6 @@ void btm_sec_encrypt_change (UINT16 handle, UINT8 status, UINT8 encr_enable) #if BLE_INCLUDED == TRUE && SMP_INCLUDED == TRUE tACL_CONN *p_acl = NULL; UINT8 acl_idx = btm_handle_to_acl_index(handle); - tGATT_TCB *p_tcb = NULL; #endif BTM_TRACE_EVENT ("Security Manager: encrypt_change status:%d State:%d, encr_enable = %d\n", status, (p_dev_rec) ? p_dev_rec->sec_state : 0, encr_enable); @@ -4046,11 +4045,6 @@ void btm_sec_encrypt_change (UINT16 handle, UINT8 status, UINT8 encr_enable) p_dev_rec->sec_flags |= BTM_SEC_16_DIGIT_PIN_AUTHED; } } else { -#if BLE_INCLUDED == TRUE && SMP_INCLUDED == TRUE - if ((p_tcb = gatt_find_tcb_by_addr(p_dev_rec->ble.pseudo_addr, BT_TRANSPORT_LE)) == NULL) { - //do nothing - } else -#endif p_dev_rec->sec_flags |= (BTM_SEC_LE_AUTHENTICATED | BTM_SEC_LE_ENCRYPTED); } } @@ -4540,7 +4534,7 @@ void btm_sec_disconnected (UINT16 handle, UINT8 reason) if (!p_dev_rec) { return; } - + p_dev_rec->enc_init_by_we = FALSE; transport = (handle == p_dev_rec->hci_handle) ? BT_TRANSPORT_BR_EDR : BT_TRANSPORT_LE; p_dev_rec->rs_disc_pending = BTM_SEC_RS_NOT_PENDING; /* reset flag */ diff --git a/components/bt/bluedroid/stack/btm/include/btm_ble_int.h b/components/bt/bluedroid/stack/btm/include/btm_ble_int.h index a9f0d8ff68..1a8aed28e4 100644 --- a/components/bt/bluedroid/stack/btm/include/btm_ble_int.h +++ b/components/bt/bluedroid/stack/btm/include/btm_ble_int.h @@ -481,6 +481,7 @@ void btm_ble_adv_filter_cleanup(void); BOOLEAN btm_ble_topology_check(tBTM_BLE_STATE_MASK request); BOOLEAN btm_ble_clear_topology_mask(tBTM_BLE_STATE_MASK request_state); BOOLEAN btm_ble_set_topology_mask(tBTM_BLE_STATE_MASK request_state); +tBTM_BLE_STATE_MASK btm_ble_get_topology_mask(void); #if BTM_BLE_CONFORMANCE_TESTING == TRUE void btm_ble_set_no_disc_if_pair_fail (BOOLEAN disble_disc); diff --git a/components/bt/bluedroid/stack/btm/include/btm_int.h b/components/bt/bluedroid/stack/btm/include/btm_int.h index bde7af9a2e..5b678af166 100644 --- a/components/bt/bluedroid/stack/btm/include/btm_int.h +++ b/components/bt/bluedroid/stack/btm/include/btm_int.h @@ -618,7 +618,7 @@ typedef struct { // btla-specific -- #define BTM_SEC_NO_LAST_SERVICE_ID 0 UINT8 last_author_service_id; /* ID of last serviced authorized: Reset after each l2cap connection */ - + BOOLEAN enc_init_by_we; } tBTM_SEC_DEV_REC; #define BTM_SEC_IS_SM4(sm) ((BOOLEAN)(BTM_SM4_TRUE == ((sm)&BTM_SM4_TRUE))) diff --git a/components/bt/bluedroid/stack/btu/btu_init.c b/components/bt/bluedroid/stack/btu/btu_init.c index bf04bd14dd..7014cfde00 100644 --- a/components/bt/bluedroid/stack/btu/btu_init.c +++ b/components/bt/bluedroid/stack/btu/btu_init.c @@ -236,3 +236,13 @@ UINT16 BTU_BleAclPktSize(void) return 0; #endif } +#if SCAN_QUEUE_CONGEST_CHECK +bool BTU_check_queue_is_congest(void) +{ + UBaseType_t wait_size = uxQueueMessagesWaiting(xBtuQueue); + if(wait_size >= QUEUE_CONGEST_SIZE ) { + return true; + } + return false; +} +#endif diff --git a/components/bt/bluedroid/stack/gap/gap_conn.c b/components/bt/bluedroid/stack/gap/gap_conn.c index ecb7b726f5..671ffa7427 100644 --- a/components/bt/bluedroid/stack/gap/gap_conn.c +++ b/components/bt/bluedroid/stack/gap/gap_conn.c @@ -1120,8 +1120,8 @@ static tGAP_CCB *gap_allocate_ccb (void) for (xx = 0, p_ccb = gap_cb.conn.ccb_pool; xx < GAP_MAX_CONNECTIONS; xx++, p_ccb++) { if (p_ccb->con_state == GAP_CCB_STATE_IDLE) { memset (p_ccb, 0, sizeof (tGAP_CCB)); - p_ccb->tx_queue = fixed_queue_new(SIZE_MAX); - p_ccb->rx_queue = fixed_queue_new(SIZE_MAX); + p_ccb->tx_queue = fixed_queue_new(QUEUE_SIZE_MAX); + p_ccb->rx_queue = fixed_queue_new(QUEUE_SIZE_MAX); p_ccb->gap_handle = xx; p_ccb->rem_mtu_size = L2CAP_MTU_SIZE; diff --git a/components/bt/bluedroid/stack/gatt/att_protocol.c b/components/bt/bluedroid/stack/gatt/att_protocol.c index 3adecfaef6..adbedab524 100644 --- a/components/bt/bluedroid/stack/gatt/att_protocol.c +++ b/components/bt/bluedroid/stack/gatt/att_protocol.c @@ -354,7 +354,7 @@ tGATT_STATUS attp_send_msg_to_l2cap(tGATT_TCB *p_tcb, BT_HDR *p_toL2CAP) } if (l2cap_ret == L2CAP_DW_FAILED) { - GATT_TRACE_ERROR("ATT failed to pass msg:0x%0x to L2CAP", + GATT_TRACE_DEBUG("ATT failed to pass msg:0x%0x to L2CAP", *((UINT8 *)(p_toL2CAP + 1) + p_toL2CAP->offset)); return GATT_INTERNAL_ERROR; } else if (l2cap_ret == L2CAP_DW_CONGESTED) { diff --git a/components/bt/bluedroid/stack/gatt/gatt_db.c b/components/bt/bluedroid/stack/gatt/gatt_db.c index 0a3a104a4b..46c5104c83 100644 --- a/components/bt/bluedroid/stack/gatt/gatt_db.c +++ b/components/bt/bluedroid/stack/gatt/gatt_db.c @@ -64,7 +64,7 @@ BOOLEAN gatts_init_service_db (tGATT_SVC_DB *p_db, tBT_UUID *p_service, BOOLEAN UINT16 s_hdl, UINT16 num_handle) { if (p_db->svc_buffer == NULL) { //in case already alloc - p_db->svc_buffer = fixed_queue_new(SIZE_MAX); + p_db->svc_buffer = fixed_queue_new(QUEUE_SIZE_MAX); } if (!allocate_svc_db_buf(p_db)) { diff --git a/components/bt/bluedroid/stack/gatt/gatt_main.c b/components/bt/bluedroid/stack/gatt/gatt_main.c index 82059afd31..add39455fe 100644 --- a/components/bt/bluedroid/stack/gatt/gatt_main.c +++ b/components/bt/bluedroid/stack/gatt/gatt_main.c @@ -108,9 +108,9 @@ void gatt_init (void) gatt_cb.trace_level = BT_TRACE_LEVEL_NONE; /* No traces */ #endif gatt_cb.def_mtu_size = GATT_DEF_BLE_MTU_SIZE; - gatt_cb.sign_op_queue = fixed_queue_new(SIZE_MAX); - gatt_cb.srv_chg_clt_q = fixed_queue_new(SIZE_MAX); - gatt_cb.pending_new_srv_start_q = fixed_queue_new(SIZE_MAX); + gatt_cb.sign_op_queue = fixed_queue_new(QUEUE_SIZE_MAX); + gatt_cb.srv_chg_clt_q = fixed_queue_new(QUEUE_SIZE_MAX); + gatt_cb.pending_new_srv_start_q = fixed_queue_new(QUEUE_SIZE_MAX); /* First, register fixed L2CAP channel for ATT over BLE */ fixed_reg.fixed_chnl_opts.mode = L2CAP_FCR_BASIC_MODE; fixed_reg.fixed_chnl_opts.max_transmit = 0xFF; @@ -179,7 +179,7 @@ void gatt_free(void) btu_free_timer(&gatt_cb.tcb[i].ind_ack_timer_ent); memset(&gatt_cb.tcb[i].ind_ack_timer_ent, 0, sizeof(TIMER_LIST_ENT)); - + #if (GATTS_INCLUDED == TRUE) fixed_queue_free(gatt_cb.tcb[i].sr_cmd.multi_rsp_q, NULL); gatt_cb.tcb[i].sr_cmd.multi_rsp_q = NULL; @@ -979,7 +979,12 @@ void gatt_data_process (tGATT_TCB *p_tcb, BT_HDR *p_buf) } } } else { - GATT_TRACE_ERROR ("ATT - Rcvd L2CAP data, unknown cmd: 0x%x\n", op_code); + if (op_code & GATT_COMMAND_FLAG) { + GATT_TRACE_ERROR ("ATT - Rcvd L2CAP data, unknown cmd: 0x%x\n", op_code); + } else { + GATT_TRACE_ERROR ("ATT - Rcvd L2CAP data, unknown req: 0x%x\n", op_code); + gatt_send_error_rsp (p_tcb, GATT_REQ_NOT_SUPPORTED, op_code, 0, FALSE); + } } } else { GATT_TRACE_ERROR ("invalid data length, ignore\n"); diff --git a/components/bt/bluedroid/stack/gatt/gatt_sr.c b/components/bt/bluedroid/stack/gatt/gatt_sr.c index 697540d4c1..24df5a4eb3 100644 --- a/components/bt/bluedroid/stack/gatt/gatt_sr.c +++ b/components/bt/bluedroid/stack/gatt/gatt_sr.c @@ -167,7 +167,7 @@ static BOOLEAN process_read_multi_rsp (tGATT_SR_CMD *p_cmd, tGATT_STATUS status, GATT_TRACE_DEBUG ("process_read_multi_rsp status=%d mtu=%d", status, mtu); if (p_cmd->multi_rsp_q == NULL) { - p_cmd->multi_rsp_q = fixed_queue_new(SIZE_MAX); + p_cmd->multi_rsp_q = fixed_queue_new(QUEUE_SIZE_MAX); } /* Enqueue the response */ @@ -1290,7 +1290,7 @@ void gatt_attr_process_prepare_write (tGATT_TCB *p_tcb, UINT8 i_rcb, UINT16 hand queue_data->offset = offset; memcpy(queue_data->value, p, len); if (prepare_record->queue == NULL) { - prepare_record->queue = fixed_queue_new(SIZE_MAX); + prepare_record->queue = fixed_queue_new(QUEUE_SIZE_MAX); } fixed_queue_enqueue(prepare_record->queue, queue_data); } diff --git a/components/bt/bluedroid/stack/gatt/gatt_utils.c b/components/bt/bluedroid/stack/gatt/gatt_utils.c index 95efcf6763..12a2e1dba3 100644 --- a/components/bt/bluedroid/stack/gatt/gatt_utils.c +++ b/components/bt/bluedroid/stack/gatt/gatt_utils.c @@ -337,7 +337,7 @@ tGATT_HDL_LIST_ELEM *gatt_alloc_hdl_buffer(void) if (!p_cb->hdl_list[i].in_use) { memset(p_elem, 0, sizeof(tGATT_HDL_LIST_ELEM)); p_elem->in_use = TRUE; - p_elem->svc_db.svc_buffer = fixed_queue_new(SIZE_MAX); + p_elem->svc_db.svc_buffer = fixed_queue_new(QUEUE_SIZE_MAX); return p_elem; } } @@ -1007,8 +1007,8 @@ tGATT_TCB *gatt_allocate_tcb_by_bdaddr(BD_ADDR bda, tBT_TRANSPORT transport) if (allocated) { memset(p_tcb, 0, sizeof(tGATT_TCB)); - p_tcb->pending_enc_clcb = fixed_queue_new(SIZE_MAX); - p_tcb->pending_ind_q = fixed_queue_new(SIZE_MAX); + p_tcb->pending_enc_clcb = fixed_queue_new(QUEUE_SIZE_MAX); + p_tcb->pending_ind_q = fixed_queue_new(QUEUE_SIZE_MAX); p_tcb->in_use = TRUE; p_tcb->tcb_idx = i; p_tcb->transport = transport; diff --git a/components/bt/bluedroid/stack/include/stack/btm_api.h b/components/bt/bluedroid/stack/include/stack/btm_api.h index 79ecba8c8f..067878a8e1 100644 --- a/components/bt/bluedroid/stack/include/stack/btm_api.h +++ b/components/bt/bluedroid/stack/include/stack/btm_api.h @@ -2811,8 +2811,8 @@ tBTM_STATUS BTM_SwitchRole (BD_ADDR remote_bd_addr, ** ** Function BTM_ReadRSSI ** -** Description This function is called to read the link policy settings. -** The address of link policy results are returned in the callback. +** Description This function is called to read the RSSI for a particular transport. +** The RSSI of results are returned in the callback. ** (tBTM_RSSI_RESULTS) ** ** Returns BTM_CMD_STARTED if command issued to controller. @@ -2822,7 +2822,7 @@ tBTM_STATUS BTM_SwitchRole (BD_ADDR remote_bd_addr, ** *******************************************************************************/ //extern -tBTM_STATUS BTM_ReadRSSI (BD_ADDR remote_bda, tBTM_CMPL_CB *p_cb); +tBTM_STATUS BTM_ReadRSSI (BD_ADDR remote_bda, tBT_TRANSPORT transport, tBTM_CMPL_CB *p_cb); /******************************************************************************* diff --git a/components/bt/bluedroid/stack/include/stack/gatt_api.h b/components/bt/bluedroid/stack/include/stack/gatt_api.h index 98cdcc7fa7..24a186ae71 100644 --- a/components/bt/bluedroid/stack/include/stack/gatt_api.h +++ b/components/bt/bluedroid/stack/include/stack/gatt_api.h @@ -64,7 +64,7 @@ #define GATT_NOT_ENCRYPTED 0x8e #define GATT_CONGESTED 0x8f -#define GATT_DUP_REG 0x90 +#define GATT_DUP_REG 0x90 #define GATT_ALREADY_OPEN 0x91 #define GATT_CANCEL 0x92 @@ -111,6 +111,7 @@ typedef UINT8 tGATT_STATUS; #define GATT_SIGN_CMD_WRITE 0xD2 /* changed in V4.0 1101-0010 (signed write) see write cmd above*/ #define GATT_OP_CODE_MAX GATT_HANDLE_VALUE_CONF + 1 /* 0x1E = 30 + 1 = 31*/ +#define GATT_COMMAND_FLAG 0x40 /* Command Flag: set to one means commond */ #define GATT_HANDLE_IS_VALID(x) ((x) != 0) @@ -766,7 +767,7 @@ extern UINT16 GATTS_AddIncludeService (UINT16 service_handle, ** *******************************************************************************/ extern UINT16 GATTS_AddCharacteristic (UINT16 service_handle, tBT_UUID *p_char_uuid, - tGATT_PERM perm, tGATT_CHAR_PROP property, + tGATT_PERM perm, tGATT_CHAR_PROP property, tGATT_ATTR_VAL *attr_val, tGATTS_ATTR_CONTROL *control); /******************************************************************************* diff --git a/components/bt/bluedroid/stack/include/stack/hcidefs.h b/components/bt/bluedroid/stack/include/stack/hcidefs.h index 09320b1f1a..0169ba8cc3 100644 --- a/components/bt/bluedroid/stack/include/stack/hcidefs.h +++ b/components/bt/bluedroid/stack/include/stack/hcidefs.h @@ -793,7 +793,7 @@ #define HCI_ERR_MAX_ERR 0x43 //ESP vendor error code -#define HCI_ERR_ESP_VENDOR_FAIL 0xE0 +#define HCI_ERR_ESP_VENDOR_FAIL 0xE0 #define HCI_HINT_TO_RECREATE_AMP_PHYS_LINK 0xFF diff --git a/components/bt/bluedroid/stack/l2cap/include/l2c_int.h b/components/bt/bluedroid/stack/l2cap/include/l2c_int.h index 3699e7f05b..e2c0ef6a76 100644 --- a/components/bt/bluedroid/stack/l2cap/include/l2c_int.h +++ b/components/bt/bluedroid/stack/l2cap/include/l2c_int.h @@ -376,6 +376,7 @@ typedef struct t_l2c_linkcb { TIMER_LIST_ENT timer_entry; /* Timer list entry for timeout evt */ UINT16 handle; /* The handle used with LM */ + UINT16 completed_packets; /* The number of conpleted packets */ tL2C_CCB_Q ccb_queue; /* Queue of CCBs on this LCB */ @@ -667,6 +668,10 @@ extern void l2cu_send_peer_ble_credit_based_disconn_req(tL2C_CCB *p_ccb); #endif +#if (C2H_FLOW_CONTROL_INCLUDED == TRUE) +extern UINT8 l2cu_find_completed_packets(UINT16 *handles, UINT16 *num_packets); +#endif ///C2H_FLOW_CONTROL_INCLUDED == TRUE + extern BOOLEAN l2cu_initialize_fixed_ccb (tL2C_LCB *p_lcb, UINT16 fixed_cid, tL2CAP_FCR_OPTS *p_fcr); extern void l2cu_no_dynamic_ccbs (tL2C_LCB *p_lcb); extern void l2cu_process_fixed_chnl_resp (tL2C_LCB *p_lcb); diff --git a/components/bt/bluedroid/stack/l2cap/l2c_api.c b/components/bt/bluedroid/stack/l2cap/l2c_api.c index 654a4df632..5637cac647 100644 --- a/components/bt/bluedroid/stack/l2cap/l2c_api.c +++ b/components/bt/bluedroid/stack/l2cap/l2c_api.c @@ -1816,7 +1816,7 @@ UINT16 L2CA_SendFixedChnlData (UINT16 fixed_cid, BD_ADDR rem_bda, BT_HDR *p_buf) // If already congested, do not accept any more packets if (p_lcb->p_fixed_ccbs[fixed_cid - L2CAP_FIRST_FIXED_CHNL]->cong_sent) { - L2CAP_TRACE_ERROR ("L2CAP - CID: 0x%04x cannot send, already congested\ + L2CAP_TRACE_DEBUG ("L2CAP - CID: 0x%04x cannot send, already congested\ xmit_hold_q.count: %u buff_quota: %u", fixed_cid, fixed_queue_length(p_lcb->p_fixed_ccbs[fixed_cid - L2CAP_FIRST_FIXED_CHNL]->xmit_hold_q), p_lcb->p_fixed_ccbs[fixed_cid - L2CAP_FIRST_FIXED_CHNL]->buff_quota); @@ -1887,7 +1887,7 @@ BOOLEAN L2CA_RemoveFixedChnl (UINT16 fixed_cid, BD_ADDR rem_bda) p_lcb = l2cu_find_lcb_by_bd_addr (rem_bda, transport); if ( ((p_lcb) == NULL) || (!p_lcb->p_fixed_ccbs[fixed_cid - L2CAP_FIRST_FIXED_CHNL]) ) { - L2CAP_TRACE_WARNING ("L2CA_RemoveFixedChnl() CID: 0x%04x BDA: %08x%04x not connected", fixed_cid, + L2CAP_TRACE_DEBUG ("L2CA_RemoveFixedChnl() CID: 0x%04x BDA: %08x%04x not connected", fixed_cid, (rem_bda[0] << 24) + (rem_bda[1] << 16) + (rem_bda[2] << 8) + rem_bda[3], (rem_bda[4] << 8) + rem_bda[5]); return (FALSE); } diff --git a/components/bt/bluedroid/stack/l2cap/l2c_ble.c b/components/bt/bluedroid/stack/l2cap/l2c_ble.c index b967295170..7329552106 100644 --- a/components/bt/bluedroid/stack/l2cap/l2c_ble.c +++ b/components/bt/bluedroid/stack/l2cap/l2c_ble.c @@ -261,6 +261,15 @@ void l2cble_notify_le_connection (BD_ADDR bda) tACL_CONN *p_acl = btm_bda_to_acl(bda, BT_TRANSPORT_LE) ; if (p_lcb != NULL && p_acl != NULL && p_lcb->link_state != LST_CONNECTED) { + + if(p_acl->link_role == HCI_ROLE_SLAVE) { + //clear p_cb->state, controller will stop adv when ble connected. + tBTM_BLE_INQ_CB *p_cb = &btm_cb.ble_ctr_cb.inq_var; + if(p_cb) { + p_cb->adv_mode = BTM_BLE_ADV_DISABLE; + p_cb->state = BTM_BLE_STOP_ADV; + } + } /* update link status */ btm_establish_continue(p_acl); /* update l2cap link status and send callback */ diff --git a/components/bt/bluedroid/stack/l2cap/l2c_fcr.c b/components/bt/bluedroid/stack/l2cap/l2c_fcr.c index cacdcc6f50..33bd0faf8d 100644 --- a/components/bt/bluedroid/stack/l2cap/l2c_fcr.c +++ b/components/bt/bluedroid/stack/l2cap/l2c_fcr.c @@ -750,7 +750,7 @@ void l2c_fcr_proc_pdu (tL2C_CCB *p_ccb, BT_HDR *p_buf) if ( (!p_ccb->fcrb.local_busy) && (!p_ccb->fcrb.srej_sent) && (!fixed_queue_is_empty(p_ccb->fcrb.srej_rcv_hold_q))) { fixed_queue_t *temp_q = p_ccb->fcrb.srej_rcv_hold_q; - p_ccb->fcrb.srej_rcv_hold_q = fixed_queue_new(SIZE_MAX); + p_ccb->fcrb.srej_rcv_hold_q = fixed_queue_new(QUEUE_SIZE_MAX); while ((p_buf = (BT_HDR *)fixed_queue_try_dequeue(temp_q)) != NULL) { if (p_ccb->in_use && (p_ccb->chnl_state == CST_OPEN)) { diff --git a/components/bt/bluedroid/stack/l2cap/l2c_main.c b/components/bt/bluedroid/stack/l2cap/l2c_main.c index c9f4c4d3b2..0178f4770d 100644 --- a/components/bt/bluedroid/stack/l2cap/l2c_main.c +++ b/components/bt/bluedroid/stack/l2cap/l2c_main.c @@ -966,7 +966,7 @@ UINT8 l2c_data_write (UINT16 cid, BT_HDR *p_data, UINT16 flags) /* If already congested, do not accept any more packets */ if (p_ccb->cong_sent) { - L2CAP_TRACE_ERROR ("L2CAP - CID: 0x%04x cannot send, already congested xmit_hold_q.count: %u buff_quota: %u", + L2CAP_TRACE_DEBUG ("L2CAP - CID: 0x%04x cannot send, already congested xmit_hold_q.count: %u buff_quota: %u", p_ccb->local_cid, fixed_queue_length(p_ccb->xmit_hold_q), p_ccb->buff_quota); diff --git a/components/bt/bluedroid/stack/l2cap/l2c_utils.c b/components/bt/bluedroid/stack/l2cap/l2c_utils.c index 358a57b5f4..978e020e65 100644 --- a/components/bt/bluedroid/stack/l2cap/l2c_utils.c +++ b/components/bt/bluedroid/stack/l2cap/l2c_utils.c @@ -57,7 +57,7 @@ tL2C_LCB *l2cu_allocate_lcb (BD_ADDR p_bd_addr, BOOLEAN is_bonding, tBT_TRANSPOR btu_free_timer(&p_lcb->timer_entry); btu_free_timer(&p_lcb->info_timer_entry); btu_free_timer(&p_lcb->upda_con_timer); - + memset (p_lcb, 0, sizeof (tL2C_LCB)); memcpy (p_lcb->remote_bd_addr, p_bd_addr, BD_ADDR_LEN); @@ -74,7 +74,7 @@ tL2C_LCB *l2cu_allocate_lcb (BD_ADDR p_bd_addr, BOOLEAN is_bonding, tBT_TRANSPOR #if (BLE_INCLUDED == TRUE) p_lcb->transport = transport; p_lcb->tx_data_len = controller_get_interface()->get_ble_default_data_packet_length(); - p_lcb->le_sec_pending_q = fixed_queue_new(SIZE_MAX); + p_lcb->le_sec_pending_q = fixed_queue_new(QUEUE_SIZE_MAX); if (transport == BT_TRANSPORT_LE) { l2cb.num_ble_links_active++; @@ -86,6 +86,9 @@ tL2C_LCB *l2cu_allocate_lcb (BD_ADDR p_bd_addr, BOOLEAN is_bonding, tBT_TRANSPOR l2c_link_adjust_allocation(); } p_lcb->link_xmit_data_q = list_new(NULL); +#if (C2H_FLOW_CONTROL_INCLUDED == TRUE) + p_lcb->completed_packets = 0; +#endif ///C2H_FLOW_CONTROL_INCLUDED == TRUE return (p_lcb); } } @@ -137,7 +140,7 @@ void l2cu_release_lcb (tL2C_LCB *p_lcb) memset(&p_lcb->info_timer_entry, 0, sizeof(TIMER_LIST_ENT)); btu_free_timer(&p_lcb->upda_con_timer); memset(&p_lcb->upda_con_timer, 0, sizeof(TIMER_LIST_ENT)); - + /* Release any unfinished L2CAP packet on this link */ if (p_lcb->p_hcit_rcv_acl) { osi_free(p_lcb->p_hcit_rcv_acl); @@ -250,6 +253,11 @@ void l2cu_release_lcb (tL2C_LCB *p_lcb) fixed_queue_free(p_lcb->le_sec_pending_q, NULL); p_lcb->le_sec_pending_q = NULL; } + +#if (C2H_FLOW_CONTROL_INCLUDED == TRUE) + p_lcb->completed_packets = 0; +#endif ///C2H_FLOW_CONTROL_INCLUDED == TRUE + } @@ -1488,7 +1496,7 @@ tL2C_CCB *l2cu_allocate_ccb (tL2C_LCB *p_lcb, UINT16 cid) btu_free_quick_timer(&p_ccb->fcrb.ack_timer); memset(&p_ccb->fcrb.ack_timer, 0, sizeof(TIMER_LIST_ENT)); p_ccb->fcrb.ack_timer.param = (TIMER_PARAM_TYPE)p_ccb; - + btu_free_quick_timer(&p_ccb->fcrb.mon_retrans_timer); memset(&p_ccb->fcrb.mon_retrans_timer, 0, sizeof(TIMER_LIST_ENT)); p_ccb->fcrb.mon_retrans_timer.param = (TIMER_PARAM_TYPE)p_ccb; @@ -1511,11 +1519,11 @@ tL2C_CCB *l2cu_allocate_ccb (tL2C_LCB *p_lcb, UINT16 cid) p_ccb->max_rx_mtu = L2CAP_MTU_SIZE; p_ccb->tx_mps = L2CAP_FCR_TX_BUF_SIZE - 32; - p_ccb->xmit_hold_q = fixed_queue_new(SIZE_MAX); + p_ccb->xmit_hold_q = fixed_queue_new(QUEUE_SIZE_MAX); #if (CLASSIC_BT_INCLUDED == TRUE) - p_ccb->fcrb.srej_rcv_hold_q = fixed_queue_new(SIZE_MAX); - p_ccb->fcrb.retrans_q = fixed_queue_new(SIZE_MAX); - p_ccb->fcrb.waiting_for_ack_q = fixed_queue_new(SIZE_MAX); + p_ccb->fcrb.srej_rcv_hold_q = fixed_queue_new(QUEUE_SIZE_MAX); + p_ccb->fcrb.retrans_q = fixed_queue_new(QUEUE_SIZE_MAX); + p_ccb->fcrb.waiting_for_ack_q = fixed_queue_new(QUEUE_SIZE_MAX); #endif ///CLASSIC_BT_INCLUDED == TRUE p_ccb->cong_sent = FALSE; @@ -3140,6 +3148,35 @@ void l2cu_send_peer_ble_credit_based_disconn_req(tL2C_CCB *p_ccb) #endif /* BLE_INCLUDED == TRUE */ +#if (C2H_FLOW_CONTROL_INCLUDED == TRUE) +/******************************************************************************* +** +** Function l2cu_find_completed_packets +** +** Description Find the completed packets, +** Then set it to zero +** +** Returns The num of handles +** +*******************************************************************************/ +UINT8 l2cu_find_completed_packets(UINT16 *handles, UINT16 *num_packets) +{ + int xx; + UINT8 num = 0; + tL2C_LCB *p_lcb = &l2cb.lcb_pool[0]; + + for (xx = 0; xx < MAX_L2CAP_LINKS; xx++, p_lcb++) { + if ((p_lcb->in_use) && (p_lcb->completed_packets > 0)) { + *(handles++) = p_lcb->handle; + *(num_packets++) = p_lcb->completed_packets; + num++; + p_lcb->completed_packets = 0; + } + } + + return num; +} +#endif ///C2H_FLOW_CONTROL_INCLUDED == TRUE /******************************************************************************* ** Functions used by both Full and Light Stack diff --git a/components/bt/bluedroid/stack/rfcomm/port_api.c b/components/bt/bluedroid/stack/rfcomm/port_api.c index b5e2c569fa..64ca9d7470 100644 --- a/components/bt/bluedroid/stack/rfcomm/port_api.c +++ b/components/bt/bluedroid/stack/rfcomm/port_api.c @@ -1459,30 +1459,6 @@ int PORT_WriteDataCO (UINT16 handle, int *p_len, int len, UINT8 *p_data) length = RFCOMM_DATA_BUF_SIZE - (UINT16)(sizeof(BT_HDR) + L2CAP_MIN_OFFSET + RFCOMM_DATA_OVERHEAD); - /* If there are buffers scheduled for transmission check if requested */ - /* data fits into the end of the queue */ - osi_mutex_global_lock(); - - if (((p_buf = (BT_HDR *)fixed_queue_try_peek_last(p_port->tx.queue)) != NULL) - && (((int)p_buf->len + available) <= (int)p_port->peer_mtu) - && (((int)p_buf->len + available) <= (int)length)) { - memcpy ((UINT8 *)(p_buf + 1) + p_buf->offset + p_buf->len, p_data, available); - p_port->tx.queue_size += (UINT16)available; - - *p_len = available; - p_buf->len += (UINT16)available; - - osi_mutex_global_unlock(); - - return (PORT_SUCCESS); - } - - osi_mutex_global_unlock(); - - //int max_read = length < p_port->peer_mtu ? length : p_port->peer_mtu; - - //max_read = available < max_read ? available : max_read; - while (available) { /* if we're over buffer high water mark, we're done */ if ((p_port->tx.queue_size > PORT_TX_HIGH_WM) @@ -1495,20 +1471,24 @@ int PORT_WriteDataCO (UINT16 handle, int *p_len, int len, UINT8 *p_data) } /* continue with rfcomm data write */ - p_buf = (BT_HDR *)osi_malloc(RFCOMM_DATA_BUF_SIZE); + if (p_port->peer_mtu < length) { + length = p_port->peer_mtu; + } + + if (available < (int)length) { + length = (UINT16)available; + } + + UINT16 alloc_size = (UINT16)(sizeof(BT_HDR) + L2CAP_MIN_OFFSET + RFCOMM_DATA_OVERHEAD+length); + p_buf = (BT_HDR *)osi_malloc(alloc_size); if (!p_buf) { + RFCOMM_TRACE_EVENT ("PORT_WriteDataCO: out of heap."); break; } p_buf->offset = L2CAP_MIN_OFFSET + RFCOMM_MIN_OFFSET; p_buf->layer_specific = handle; - if (p_port->peer_mtu < length) { - length = p_port->peer_mtu; - } - if (available < (int)length) { - length = (UINT16)available; - } p_buf->len = length; p_buf->event = BT_EVT_TO_BTU_SP_DATA; @@ -1518,7 +1498,7 @@ int PORT_WriteDataCO (UINT16 handle, int *p_len, int len, UINT8 *p_data) rc = port_write (p_port, p_buf); - /* If queue went below the threashold need to send flow control */ + /* If queue went below the threshold need to send flow control */ event |= port_flow_control_user (p_port); if (rc == PORT_SUCCESS) { @@ -1531,6 +1511,7 @@ int PORT_WriteDataCO (UINT16 handle, int *p_len, int len, UINT8 *p_data) *p_len += length; available -= (int)length; + p_data += length; } if (!available && (rc != PORT_CMD_PENDING) && (rc != PORT_TX_QUEUE_DISABLED)) { event |= PORT_EV_TXEMPTY; diff --git a/components/bt/bluedroid/stack/rfcomm/port_utils.c b/components/bt/bluedroid/stack/rfcomm/port_utils.c index a88ae016f8..0da8b3d76b 100644 --- a/components/bt/bluedroid/stack/rfcomm/port_utils.c +++ b/components/bt/bluedroid/stack/rfcomm/port_utils.c @@ -128,8 +128,8 @@ void port_set_defaults (tPORT *p_port) memset (&p_port->rx, 0, sizeof (p_port->rx)); memset (&p_port->tx, 0, sizeof (p_port->tx)); - p_port->tx.queue = fixed_queue_new(SIZE_MAX); - p_port->rx.queue = fixed_queue_new(SIZE_MAX); + p_port->tx.queue = fixed_queue_new(QUEUE_SIZE_MAX); + p_port->rx.queue = fixed_queue_new(QUEUE_SIZE_MAX); } /******************************************************************************* diff --git a/components/bt/bluedroid/stack/rfcomm/rfc_utils.c b/components/bt/bluedroid/stack/rfcomm/rfc_utils.c index 180632c048..8b1e043116 100644 --- a/components/bt/bluedroid/stack/rfcomm/rfc_utils.c +++ b/components/bt/bluedroid/stack/rfcomm/rfc_utils.c @@ -175,7 +175,7 @@ tRFC_MCB *rfc_alloc_multiplexer_channel (BD_ADDR bd_addr, BOOLEAN is_initiator) RFCOMM_TRACE_DEBUG("rfc_alloc_multiplexer_channel:is_initiator:%d, create new p_mcb:%p, index:%d", is_initiator, &rfc_cb.port.rfc_mcb[j], j); - p_mcb->cmd_q = fixed_queue_new(SIZE_MAX); + p_mcb->cmd_q = fixed_queue_new(QUEUE_SIZE_MAX); p_mcb->is_initiator = is_initiator; diff --git a/components/bt/bluedroid/stack/smp/include/p_256_ecc_pp.h b/components/bt/bluedroid/stack/smp/include/p_256_ecc_pp.h index 029a79ff16..f91d6056b2 100644 --- a/components/bt/bluedroid/stack/smp/include/p_256_ecc_pp.h +++ b/components/bt/bluedroid/stack/smp/include/p_256_ecc_pp.h @@ -58,6 +58,8 @@ extern elliptic_curve_t curve_p256; void ECC_PointMult_Bin_NAF(Point *q, Point *p, DWORD *n, uint32_t keyLength); +bool ECC_CheckPointIsInElliCur_P256(Point *p); + #define ECC_PointMult(q, p, n, keyLength) ECC_PointMult_Bin_NAF(q, p, n, keyLength) void p_256_init_curve(UINT32 keyLength); diff --git a/components/bt/bluedroid/stack/smp/p_256_ecc_pp.c b/components/bt/bluedroid/stack/smp/p_256_ecc_pp.c index 991b6fd757..0f7ab3ec41 100644 --- a/components/bt/bluedroid/stack/smp/p_256_ecc_pp.c +++ b/components/bt/bluedroid/stack/smp/p_256_ecc_pp.c @@ -240,4 +240,40 @@ void ECC_PointMult_Bin_NAF(Point *q, Point *p, DWORD *n, uint32_t keyLength) multiprecision_mersenns_mult_mod(q->y, q->y, q->z, keyLength); } +bool ECC_CheckPointIsInElliCur_P256(Point *p) +{ + /* y^2 % q */ + DWORD y_y_q[KEY_LENGTH_DWORDS_P256] = {0x0}; + /* x^2 % q */ + DWORD x_x_q[KEY_LENGTH_DWORDS_P256] = {0x0}; + /* x % q */ + DWORD x_q[KEY_LENGTH_DWORDS_P256] = {0x0}; + /* x^2, To prevent overflow, the length of the x square here needs to + be expanded to two times the original one. */ + DWORD x_x[2*KEY_LENGTH_DWORDS_P256] = {0x0}; + /* y_y_q =(p->y)^2(mod q) */ + multiprecision_mersenns_squa_mod(y_y_q, p->y, KEY_LENGTH_DWORDS_P256); + /* Calculate the value of p->x square, x_x = (p->x)^2 */ + multiprecision_mult(x_x, p->x, p->x, KEY_LENGTH_DWORDS_P256); + /* The function of the elliptic curve is y^2 = x^3 - 3x + b (mod q) ==> + y^2 = (x^2 - 3)*x + b (mod q), + so we calculate the x^2 - 3 value here */ + x_x[0] -= 3; + /* Using math relations. (a*b) % q = ((a%q)*(b%q)) % q ==> + (x^2 - 3)*x = (((x^2 - 3) % q) * x % q) % q */ + multiprecision_fast_mod_P256(x_x_q, x_x); + /* x_x = x_x_q * x_q */ + multiprecision_mult(x_x, x_x_q, p->x, KEY_LENGTH_DWORDS_P256); + /* x_q = x_x % q */ + multiprecision_fast_mod_P256(x_q, x_x); + /* Save the result in x_x_q */ + multiprecision_add_mod(x_x_q, x_q, curve_p256.b, KEY_LENGTH_DWORDS_P256); + /* compare the y_y_q and x_x_q, see if they are on a given elliptic curve. */ + if (multiprecision_compare(y_y_q, x_x_q, KEY_LENGTH_DWORDS_P256)) { + return false; + } else { + return true; + } +} + diff --git a/components/bt/bluedroid/stack/smp/smp_act.c b/components/bt/bluedroid/stack/smp/smp_act.c index 0b5d50be2e..bf3fe7def6 100644 --- a/components/bt/bluedroid/stack/smp/smp_act.c +++ b/components/bt/bluedroid/stack/smp/smp_act.c @@ -22,6 +22,7 @@ #include "btm_int.h" #include "stack/l2c_api.h" #include "smp_int.h" +#include "p_256_ecc_pp.h" //#include "utils/include/bt_utils.h" #if SMP_INCLUDED == TRUE @@ -668,6 +669,12 @@ void smp_process_pairing_public_key(tSMP_CB *p_cb, tSMP_INT_DATA *p_data) STREAM_TO_ARRAY(p_cb->peer_publ_key.x, p, BT_OCTET32_LEN); STREAM_TO_ARRAY(p_cb->peer_publ_key.y, p, BT_OCTET32_LEN); + /* In order to prevent the x and y coordinates of the public key from being modified, + we need to check whether the x and y coordinates are on the given elliptic curve. */ + if (!ECC_CheckPointIsInElliCur_P256((Point *)&p_cb->peer_publ_key)) { + SMP_TRACE_ERROR("%s, Invalid Public key.", __func__); + smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason); + } p_cb->flags |= SMP_PAIR_FLAG_HAVE_PEER_PUBL_KEY; smp_wait_for_both_public_keys(p_cb, NULL); @@ -1831,7 +1838,7 @@ void smp_set_local_oob_random_commitment(tSMP_CB *p_cb, tSMP_INT_DATA *p_data) void smp_link_encrypted(BD_ADDR bda, UINT8 encr_enable) { tSMP_CB *p_cb = &smp_cb; - + tBTM_SEC_DEV_REC *p_dev_rec = btm_find_dev (bda); SMP_TRACE_DEBUG("%s encr_enable=%d\n", __func__, encr_enable); if (memcmp(&smp_cb.pairing_bda[0], bda, BD_ADDR_LEN) == 0) { @@ -1842,6 +1849,18 @@ void smp_link_encrypted(BD_ADDR bda, UINT8 encr_enable) btm_ble_update_sec_key_size(bda, p_cb->loc_enc_size); } + smp_sm_event(&smp_cb, SMP_ENCRYPTED_EVT, &encr_enable); + } + else if(p_dev_rec && !p_dev_rec->enc_init_by_we){ + + /* + if enc_init_by_we is false, it means that client initiates encryption before slave calls esp_ble_set_encryption() + we need initiate pairing_bda and p_cb->role then encryption, for example iPhones + */ + memcpy(&smp_cb.pairing_bda[0], bda, BD_ADDR_LEN); + p_cb->state = SMP_STATE_ENCRYPTION_PENDING; + p_cb->role = HCI_ROLE_SLAVE; + p_dev_rec->enc_init_by_we = FALSE; smp_sm_event(&smp_cb, SMP_ENCRYPTED_EVT, &encr_enable); } } diff --git a/components/bt/bt.c b/components/bt/bt.c index f0640917c0..65f12a92fa 100644 --- a/components/bt/bt.c +++ b/components/bt/bt.c @@ -61,9 +61,9 @@ /* not for user call, so don't put to include file */ extern void btdm_osi_funcs_register(void *osi_funcs); extern int btdm_controller_init(uint32_t config_mask, esp_bt_controller_config_t *config_opts); -extern int btdm_controller_deinit(void); +extern void btdm_controller_deinit(void); extern int btdm_controller_enable(esp_bt_mode_t mode); -extern int btdm_controller_disable(esp_bt_mode_t mode); +extern void btdm_controller_disable(void); extern uint8_t btdm_controller_get_mode(void); extern const char *btdm_controller_get_compile_version(void); extern void btdm_rf_bb_init(void); @@ -254,12 +254,20 @@ bool IRAM_ATTR btdm_queue_generic_deregister(btdm_queue_item_t *queue) static void IRAM_ATTR interrupt_disable(void) { - portENTER_CRITICAL(&global_int_mux); + if (xPortInIsrContext()) { + portENTER_CRITICAL_ISR(&global_int_mux); + } else { + portENTER_CRITICAL(&global_int_mux); + } } static void IRAM_ATTR interrupt_restore(void) { - portEXIT_CRITICAL(&global_int_mux); + if (xPortInIsrContext()) { + portEXIT_CRITICAL_ISR(&global_int_mux); + } else { + portEXIT_CRITICAL(&global_int_mux); + } } static void IRAM_ATTR task_yield_from_isr(void) @@ -575,9 +583,7 @@ static int IRAM_ATTR rand_wrapper(void) static uint32_t IRAM_ATTR btdm_lpcycles_2_us(uint32_t cycles) { - // Sanity check. The number of lp cycles should not be too high to avoid overflow. Thrs: 100s (for 32kHz freq) - assert(cycles < 3200000); - + // The number of lp cycles should not lead to overflow. Thrs: 100s (for 32kHz freq) // clock measurement is conducted uint64_t us = (uint64_t)btdm_lpcycle_us * cycles; us = (us + (1 << (btdm_lpcycle_us_frac - 1))) >> btdm_lpcycle_us_frac; @@ -589,9 +595,7 @@ static uint32_t IRAM_ATTR btdm_lpcycles_2_us(uint32_t cycles) */ static uint32_t IRAM_ATTR btdm_us_2_lpcycles(uint32_t us) { - // Sanity check: the number of sleep duration(us) should not be too high to avoid overflow. Thrs: 100s - assert(us < 100000000); - + // The number of sleep duration(us) should not lead to overflow. Thrs: 100s // Compute the sleep duration in us to low power clock cycles, with calibration result applied // clock measurement is conducted uint64_t cycles = ((uint64_t)(us) << btdm_lpcycle_us_frac) / btdm_lpcycle_us; @@ -604,6 +608,8 @@ static bool IRAM_ATTR btdm_sleep_check_duration(uint32_t *slot_cnt) if (*slot_cnt < BTDM_MIN_SLEEP_DURATION) { return false; } + /* wake up 3 slots in advance */ + *slot_cnt = *slot_cnt -3; return true; } @@ -612,9 +618,6 @@ static void IRAM_ATTR btdm_sleep_enter_wrapper(void) if (btdm_controller_get_sleep_mode() == BTDM_MODEM_SLEEP_MODE_ORIG) { esp_modem_sleep_enter(MODEM_BLE_MODULE); esp_modem_sleep_enter(MODEM_CLASSIC_BT_MODULE); -#ifdef CONFIG_PM_ENABLE - esp_pm_lock_release(s_pm_lock); -#endif } else if (btdm_controller_get_sleep_mode() == BTDM_MODEM_SLEEP_MODE_EVED) { esp_modem_sleep_enter(MODEM_BLE_MODULE); // pause bluetooth baseband @@ -625,9 +628,6 @@ static void IRAM_ATTR btdm_sleep_enter_wrapper(void) static void IRAM_ATTR btdm_sleep_exit_wrapper(void) { if (btdm_controller_get_sleep_mode() == BTDM_MODEM_SLEEP_MODE_ORIG) { -#ifdef CONFIG_PM_ENABLE - esp_pm_lock_acquire(s_pm_lock); -#endif esp_modem_sleep_exit(MODEM_BLE_MODULE); esp_modem_sleep_exit(MODEM_CLASSIC_BT_MODULE); } else if (btdm_controller_get_sleep_mode() == BTDM_MODEM_SLEEP_MODE_EVED) { @@ -835,9 +835,9 @@ esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg) btdm_lpcycle_us_frac = RTC_CLK_CAL_FRACT; btdm_lpcycle_us = 32 << btdm_lpcycle_us_frac; +#if CONFIG_BTDM_MODEM_SLEEP_MODE_ORIG bool select_src_ret = false; bool set_div_ret = false; -#if CONFIG_BTDM_MODEM_SLEEP_MODE_ORIG #if CONFIG_BTDM_LPCLK_SEL_MAIN_XTAL select_src_ret = btdm_lpclk_select_src(BTDM_LPCLK_SEL_XTAL); set_div_ret = btdm_lpclk_set_div(rtc_clk_xtal_freq_get() * 32 - 1); @@ -880,9 +880,7 @@ esp_err_t esp_bt_controller_deinit(void) return ESP_ERR_INVALID_STATE; } - if (btdm_controller_deinit() != 0) { - return ESP_ERR_NO_MEM; - } + btdm_controller_deinit(); periph_module_disable(PERIPH_BT_MODULE); @@ -923,7 +921,14 @@ esp_err_t esp_bt_controller_enable(esp_bt_mode_t mode) esp_phy_load_cal_and_init(PHY_BT_MODULE); - if (btdm_controller_get_sleep_mode() == BTDM_MODEM_SLEEP_MODE_ORIG) { + if (btdm_controller_get_sleep_mode() == BTDM_MODEM_SLEEP_MODE_NONE) { + //Just register to sleep module, make the modem sleep modules check BT sleep status when sleep enter. + //Thus, it will prevent WIFI from disabling RF when BT is not in sleep but is using RF. + esp_modem_sleep_register(MODEM_BLE_MODULE); + esp_modem_sleep_register(MODEM_CLASSIC_BT_MODULE); + esp_modem_sleep_exit(MODEM_BLE_MODULE); + esp_modem_sleep_exit(MODEM_CLASSIC_BT_MODULE); + } else if (btdm_controller_get_sleep_mode() == BTDM_MODEM_SLEEP_MODE_ORIG) { esp_modem_sleep_register(MODEM_BLE_MODULE); esp_modem_sleep_register(MODEM_CLASSIC_BT_MODULE); } else if (btdm_controller_get_sleep_mode() == BTDM_MODEM_SLEEP_MODE_EVED) { @@ -941,13 +946,17 @@ esp_err_t esp_bt_controller_enable(esp_bt_mode_t mode) ret = btdm_controller_enable(mode); if (ret) { - if (btdm_controller_get_sleep_mode() == BTDM_MODEM_SLEEP_MODE_ORIG) { + if (btdm_controller_get_sleep_mode() == BTDM_MODEM_SLEEP_MODE_NONE + || btdm_controller_get_sleep_mode() == BTDM_MODEM_SLEEP_MODE_ORIG) { esp_modem_sleep_deregister(MODEM_BLE_MODULE); esp_modem_sleep_deregister(MODEM_CLASSIC_BT_MODULE); } else if (btdm_controller_get_sleep_mode() == BTDM_MODEM_SLEEP_MODE_EVED) { esp_modem_sleep_deregister(MODEM_BLE_MODULE); } esp_phy_rf_deinit(PHY_BT_MODULE); +#ifdef CONFIG_PM_ENABLE + esp_pm_lock_release(s_pm_lock); +#endif return ESP_ERR_INVALID_STATE; } @@ -958,8 +967,6 @@ esp_err_t esp_bt_controller_enable(esp_bt_mode_t mode) esp_err_t esp_bt_controller_disable(void) { - int ret; - if (btdm_controller_status != ESP_BT_CONTROLLER_STATUS_ENABLED) { return ESP_ERR_INVALID_STATE; } @@ -975,21 +982,17 @@ esp_err_t esp_bt_controller_disable(void) } } - ret = btdm_controller_disable(btdm_controller_get_mode()); - if (ret < 0) { - return ESP_ERR_INVALID_STATE; - } + btdm_controller_disable(); - if (ret == ESP_BT_MODE_IDLE) { - if (btdm_controller_get_sleep_mode() == BTDM_MODEM_SLEEP_MODE_ORIG) { - esp_modem_sleep_deregister(MODEM_BLE_MODULE); - esp_modem_sleep_deregister(MODEM_CLASSIC_BT_MODULE); - } else if (btdm_controller_get_sleep_mode() == BTDM_MODEM_SLEEP_MODE_EVED) { - esp_modem_sleep_deregister(MODEM_BLE_MODULE); - } - esp_phy_rf_deinit(PHY_BT_MODULE); - btdm_controller_status = ESP_BT_CONTROLLER_STATUS_INITED; + if (btdm_controller_get_sleep_mode() == BTDM_MODEM_SLEEP_MODE_NONE + || btdm_controller_get_sleep_mode() == BTDM_MODEM_SLEEP_MODE_ORIG) { + esp_modem_sleep_deregister(MODEM_BLE_MODULE); + esp_modem_sleep_deregister(MODEM_CLASSIC_BT_MODULE); + } else if (btdm_controller_get_sleep_mode() == BTDM_MODEM_SLEEP_MODE_EVED) { + esp_modem_sleep_deregister(MODEM_BLE_MODULE); } + esp_phy_rf_deinit(PHY_BT_MODULE); + btdm_controller_status = ESP_BT_CONTROLLER_STATUS_INITED; #ifdef CONFIG_PM_ENABLE esp_pm_lock_release(s_pm_lock); diff --git a/components/bt/include/esp_bt.h b/components/bt/include/esp_bt.h index 1fda81dad0..fe594b038e 100644 --- a/components/bt/include/esp_bt.h +++ b/components/bt/include/esp_bt.h @@ -46,7 +46,7 @@ typedef struct { /* While scanning, if the free memory value in controller is less than SCAN_SEND_ADV_RESERVED_SIZE, the adv packet will be discarded until the memory is restored. */ #define SCAN_SEND_ADV_RESERVED_SIZE 1000 -/* open controller log debug when adv lost */ +/* enable controller log debug when adv lost */ #define CONTROLLER_ADV_LOST_DEBUG_BIT (0<<0) #ifdef CONFIG_BT_HCI_UART_NO @@ -132,7 +132,7 @@ typedef enum { * ESP_BLE_PWR_TYPE_SCAN : for scan. * ESP_BLE_PWR_TYPE_DEFAULT : if each connection's TX power is not set, it will use this default value. * if neither in scan mode nor in adv mode, it will use this default value. - * If none of power type is set, system will use ESP_PWR_LVL_P1 as default for ADV/SCAN/CONN0-9. + * If none of power type is set, system will use ESP_PWR_LVL_P3 as default for ADV/SCAN/CONN0-9. */ typedef enum { ESP_BLE_PWR_TYPE_CONN_HDL0 = 0, /*!< For connection handle 0 */ @@ -154,14 +154,22 @@ typedef enum { * @brief Bluetooth TX power level(index), it's just a index corresponding to power(dbm). */ typedef enum { - ESP_PWR_LVL_N14 = 0, /*!< Corresponding to -14dbm */ - ESP_PWR_LVL_N11 = 1, /*!< Corresponding to -11dbm */ - ESP_PWR_LVL_N8 = 2, /*!< Corresponding to -8dbm */ - ESP_PWR_LVL_N5 = 3, /*!< Corresponding to -5dbm */ - ESP_PWR_LVL_N2 = 4, /*!< Corresponding to -2dbm */ - ESP_PWR_LVL_P1 = 5, /*!< Corresponding to 1dbm */ - ESP_PWR_LVL_P4 = 6, /*!< Corresponding to 4dbm */ - ESP_PWR_LVL_P7 = 7, /*!< Corresponding to 7dbm */ + ESP_PWR_LVL_N12 = 0, /*!< Corresponding to -12dbm */ + ESP_PWR_LVL_N9 = 1, /*!< Corresponding to -9dbm */ + ESP_PWR_LVL_N6 = 2, /*!< Corresponding to -6dbm */ + ESP_PWR_LVL_N3 = 3, /*!< Corresponding to -3dbm */ + ESP_PWR_LVL_N0 = 4, /*!< Corresponding to 0dbm */ + ESP_PWR_LVL_P3 = 5, /*!< Corresponding to +3dbm */ + ESP_PWR_LVL_P6 = 6, /*!< Corresponding to +6dbm */ + ESP_PWR_LVL_P9 = 7, /*!< Corresponding to +9dbm */ + ESP_PWR_LVL_N14 = ESP_PWR_LVL_N12, /*!< Backward compatibility! Setting to -14dbm will actually result to -12dbm */ + ESP_PWR_LVL_N11 = ESP_PWR_LVL_N9, /*!< Backward compatibility! Setting to -11dbm will actually result to -9dbm */ + ESP_PWR_LVL_N8 = ESP_PWR_LVL_N6, /*!< Backward compatibility! Setting to -8dbm will actually result to -6dbm */ + ESP_PWR_LVL_N5 = ESP_PWR_LVL_N3, /*!< Backward compatibility! Setting to -5dbm will actually result to -3dbm */ + ESP_PWR_LVL_N2 = ESP_PWR_LVL_N0, /*!< Backward compatibility! Setting to -2dbm will actually result to 0dbm */ + ESP_PWR_LVL_P1 = ESP_PWR_LVL_P3, /*!< Backward compatibility! Setting to +1dbm will actually result to +3dbm */ + ESP_PWR_LVL_P4 = ESP_PWR_LVL_P6, /*!< Backward compatibility! Setting to +4dbm will actually result to +6dbm */ + ESP_PWR_LVL_P7 = ESP_PWR_LVL_P9, /*!< Backward compatibility! Setting to +7dbm will actually result to +9dbm */ } esp_power_level_t; /** @@ -198,7 +206,7 @@ esp_power_level_t esp_ble_tx_power_get(esp_ble_power_type_t power_type); * For example, if you want BR/EDR use the new TX power to do inquire, you should call * this function before inquire. Another word, If call this function when BR/EDR is in inquire(ING), * please do inquire again after call this function. - * Default minimum power level is ESP_PWR_LVL_N2, and maximum power level is ESP_PWR_LVL_P1. + * Default minimum power level is ESP_PWR_LVL_N0, and maximum power level is ESP_PWR_LVL_P3. * @param min_power_level: The minimum power level * @param max_power_level: The maximum power level * @return ESP_OK - success, other - failed @@ -291,7 +299,7 @@ void esp_vhci_host_register_callback(const esp_vhci_host_callback_t *callback); /** @brief esp_bt_controller_mem_release * release the memory by mode, if never use the bluetooth mode - * it can release the .bbs, .data and other section to heap. + * it can release the .bss, .data and other section to heap. * The total size is about 70k bytes. * * esp_bt_controller_mem_release(mode) should be called only before esp_bt_controller_init() diff --git a/components/bt/lib b/components/bt/lib index cfd66eb9b7..d3c834d661 160000 --- a/components/bt/lib +++ b/components/bt/lib @@ -1 +1 @@ -Subproject commit cfd66eb9b77d6d98dae79ba505378f438b2ef095 +Subproject commit d3c834d66153b1acd6b4e5e744a66aaa55ae5c40 diff --git a/components/bt/test/component.mk b/components/bt/test/component.mk new file mode 100644 index 0000000000..5dd172bdb7 --- /dev/null +++ b/components/bt/test/component.mk @@ -0,0 +1,5 @@ +# +#Component Makefile +# + +COMPONENT_ADD_LDFLAGS = -Wl,--whole-archive -l$(COMPONENT_NAME) -Wl,--no-whole-archive diff --git a/components/bt/test/test_smp.c b/components/bt/test/test_smp.c new file mode 100644 index 0000000000..8758f9ccf4 --- /dev/null +++ b/components/bt/test/test_smp.c @@ -0,0 +1,107 @@ +/* + Tests for the BLE SMP implementation +*/ + +#include +#include +#include +#include +#include +#include + +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/semphr.h" +#include "freertos/queue.h" +#include "freertos/xtensa_api.h" +#include "unity.h" +#include "esp_heap_caps.h" +#include "esp_log.h" +#include "freertos/ringbuf.h" +#include "esp_system.h" +#include "nvs_flash.h" + +#include "esp_bt.h" +#include "esp_bt_main.h" +#include "esp_bt_device.h" +#include "esp_gap_ble_api.h" + +#define TAG "ble_smp_test" + +#define KEY_LENGTH_DWORDS_P256 8 + +typedef unsigned long DWORD; +typedef uint32_t UINT32; + +typedef struct { +DWORD x[KEY_LENGTH_DWORDS_P256]; + DWORD y[KEY_LENGTH_DWORDS_P256]; + DWORD z[KEY_LENGTH_DWORDS_P256]; +} Point; + +typedef struct { + // curve's coefficients + DWORD a[KEY_LENGTH_DWORDS_P256]; + DWORD b[KEY_LENGTH_DWORDS_P256]; + + //whether a is -3 + int a_minus3; + + // prime modulus + DWORD p[KEY_LENGTH_DWORDS_P256]; + + // Omega, p = 2^m -omega + DWORD omega[KEY_LENGTH_DWORDS_P256]; + + // base point, a point on E of order r + Point G; + +} elliptic_curve_t; + +extern void ECC_PointMult_Bin_NAF(Point *q, Point *p, DWORD *n, uint32_t keyLength); +extern bool ECC_CheckPointIsInElliCur_P256(Point *p); +extern void p_256_init_curve(UINT32 keyLength); +extern elliptic_curve_t curve_p256; + +static void bt_rand(void *buf, size_t len) +{ + if (!len) { + return; + } + // Reset the buf value to the fixed value. + memset(buf, 0x55, len); + + for (int i = 0; i < (int)(len / sizeof(uint32_t)); i++) { + uint32_t rand = esp_random(); + memcpy(buf + i*sizeof(uint32_t), &rand, sizeof(uint32_t)); + } + + return; +} + +TEST_CASE("ble_smp_public_key_check", "[ble_smp]") +{ + /* We wait init finish 200ms here */ + vTaskDelay(200 / portTICK_PERIOD_MS); + Point public_key; + DWORD private_key[KEY_LENGTH_DWORDS_P256] = {[0 ... (KEY_LENGTH_DWORDS_P256 - 1)] = 0x12345678}; + p_256_init_curve(KEY_LENGTH_DWORDS_P256); + ECC_PointMult_Bin_NAF(&public_key, &(curve_p256.G), private_key, KEY_LENGTH_DWORDS_P256); + /* Check Is the public key generated by the system on the given elliptic curve */ + TEST_ASSERT(ECC_CheckPointIsInElliCur_P256(&public_key)); + /* We simulate the attacker and set the y coordinate of the public key to 0. */ + for (int i = 0; i < KEY_LENGTH_DWORDS_P256; i++) { + public_key.y[i] = 0x0; + } + /* At this point the public key should not be on the given elliptic curve. */ + TEST_ASSERT(!ECC_CheckPointIsInElliCur_P256(&public_key)); + /* Test whether the G point on the protocol is on a given elliptic curve */ + TEST_ASSERT(ECC_CheckPointIsInElliCur_P256(&(curve_p256.G))); + /* test 100 times when the private key is generated by the random number. */ + for (int j = 0; j < 100; j++) { + bt_rand(private_key, sizeof(DWORD)*KEY_LENGTH_DWORDS_P256); + ECC_PointMult_Bin_NAF(&public_key, &(curve_p256.G), private_key, KEY_LENGTH_DWORDS_P256); + /* Check Is the public key generated by the system on the given elliptic curve */ + TEST_ASSERT(ECC_CheckPointIsInElliCur_P256(&public_key)); + } +} diff --git a/components/coap/CMakeLists.txt b/components/coap/CMakeLists.txt index faba933094..90b0c26e60 100644 --- a/components/coap/CMakeLists.txt +++ b/components/coap/CMakeLists.txt @@ -28,3 +28,15 @@ register_component() # TODO: find a way to move this to a port header target_compile_definitions(coap PUBLIC WITH_POSIX) +set_source_files_properties( + libcoap/src/debug.c + libcoap/src/pdu.c + PROPERTIES COMPILE_FLAGS + -Wno-write-strings) + +# Temporary suppress "fallthrough" warnings until they are fixed in libcoap repo +set_source_files_properties( + libcoap/src/option.c + PROPERTIES COMPILE_FLAGS + -Wno-implicit-fallthrough) + diff --git a/components/coap/component.mk b/components/coap/component.mk index 012188d7ab..4b3d56f567 100644 --- a/components/coap/component.mk +++ b/components/coap/component.mk @@ -12,3 +12,5 @@ COMPONENT_SUBMODULES += libcoap libcoap/src/debug.o: CFLAGS += -Wno-write-strings libcoap/src/pdu.o: CFLAGS += -Wno-write-strings +# Temporary suppress "fallthrough" warnings until they are fixed in libcoap repo +libcoap/src/option.o: CFLAGS += -Wno-implicit-fallthrough diff --git a/components/coap/port/coap_io_socket.c b/components/coap/port/coap_io_socket.c index eec8cc1319..4c3f85b458 100644 --- a/components/coap/port/coap_io_socket.c +++ b/components/coap/port/coap_io_socket.c @@ -374,8 +374,8 @@ coap_network_read(coap_endpoint_t *ep, coap_packet_t **packet) { } /* local interface for IPv4 */ - (*packet)->src.size = sizeof((*packet)->src.addr); - memcpy(&(*packet)->src.addr.sa, &soc_srcipaddr, (*packet)->src.size); + (*packet)->src.size = sizeof((*packet)->src.addr.sa); + memcpy(&((*packet)->src.addr.sa), &soc_srcipaddr, (*packet)->src.size); if (len > coap_get_max_packetlength(*packet)) { /* FIXME: we might want to send back a response */ diff --git a/components/console/argtable3/argtable3.c b/components/console/argtable3/argtable3.c index 3fdda9068d..282869f9c0 100644 --- a/components/console/argtable3/argtable3.c +++ b/components/console/argtable3/argtable3.c @@ -3071,6 +3071,7 @@ static int trex_charnode(TRex *exp,TRexBool isclass) exp->_p++; return node; } //else default + /* falls through */ default: t = *exp->_p; exp->_p++; return trex_newnode(exp,t); diff --git a/components/cxx/component.mk b/components/cxx/component.mk index 00e05e0db2..7d819675a8 100644 --- a/components/cxx/component.mk +++ b/components/cxx/component.mk @@ -9,3 +9,4 @@ ifndef CONFIG_CXX_EXCEPTIONS COMPONENT_ADD_LDFLAGS += -u __cxx_fatal_exception endif +COMPONENT_ADD_INCLUDEDIRS = diff --git a/components/cxx/cxx_exception_stubs.cpp b/components/cxx/cxx_exception_stubs.cpp index 3f7632c6d5..b67bc2ad34 100644 --- a/components/cxx/cxx_exception_stubs.cpp +++ b/components/cxx/cxx_exception_stubs.cpp @@ -13,12 +13,23 @@ extern "C" void __cxx_fatal_exception(void) abort(); } +extern "C" bool __cxx_fatal_exception_bool(void) +{ + __cxx_fatal_exception(); + return false; +} + extern "C" void __cxx_fatal_exception_message(const char *msg) { printf("%s%s\n", FATAL_EXCEPTION, msg); abort(); } +extern "C" void __cxx_fatal_exception_message_va(const char *msg, ...) +{ + __cxx_fatal_exception_message(msg); +} + extern "C" void __cxx_fatal_exception_int(int i) { printf("%s (%d)\n", FATAL_EXCEPTION, i); @@ -43,7 +54,7 @@ void std::__throw_length_error(const char*) __attribute__((alias("__cxx_fatal_ex void std::__throw_out_of_range(const char*) __attribute__((alias("__cxx_fatal_exception_message"))); -void std::__throw_out_of_range_fmt(const char*, ...) __attribute__((alias("__cxx_fatal_exception_message"))); +void std::__throw_out_of_range_fmt(const char*, ...) __attribute__((alias("__cxx_fatal_exception_message_va"))); void std::__throw_runtime_error(const char*) __attribute__((alias("__cxx_fatal_exception_message"))); @@ -84,6 +95,6 @@ extern "C" void __cxa_rethrow(void) __attribute__((alias("__cxx_fatal_exception" extern "C" void __cxa_throw(void) __attribute__((alias("__cxx_fatal_exception"))); extern "C" void __cxa_call_terminate(void) __attribute__((alias("__cxx_fatal_exception"))); -bool std::uncaught_exception() __attribute__((alias("__cxx_fatal_exception"))); +bool std::uncaught_exception() __attribute__((alias("__cxx_fatal_exception_bool"))); #endif // CONFIG_CXX_EXCEPTIONS diff --git a/components/cxx/cxx_guards.cpp b/components/cxx/cxx_guards.cpp index 288ff3ea03..48819a7ab5 100644 --- a/components/cxx/cxx_guards.cpp +++ b/components/cxx/cxx_guards.cpp @@ -33,6 +33,10 @@ static size_t s_static_init_waiting_count = 0; //!< number of tasks static size_t s_static_init_max_waiting_count = 0; //!< maximum ever value of the above; can be inspected using GDB for debugging purposes #endif +extern "C" int __cxa_guard_acquire(__guard* pg); +extern "C" void __cxa_guard_release(__guard* pg); +extern "C" void __cxa_guard_abort(__guard* pg); +extern "C" void __cxa_guard_dummy(); /** * Layout of the guard object (defined by the ABI). diff --git a/components/driver/Kconfig b/components/driver/Kconfig index a327a4e867..bff45a46bf 100644 --- a/components/driver/Kconfig +++ b/components/driver/Kconfig @@ -1,4 +1,4 @@ -#menu "Driver configurations" +menu "Driver configurations" menu "ADC configuration" @@ -20,5 +20,30 @@ config ADC2_DISABLE_DAC endmenu # ADC Configuration -#endmenu # Driver configurations +menu "SPI master configuration" +config SPI_MASTER_IN_IRAM + bool "Place transmitting functions of SPI master into IRAM" + default n + select SPI_MASTER_ISR_IN_IRAM + help + Normally only the ISR of SPI master is placed in the IRAM, so that it + can work without the flash when interrupt is triggered. + For other functions, there's some possibility that the flash cache + miss when running inside and out of SPI functions, which may increase + the interval of SPI transactions. + Enable this to put ``queue_trans``, ``get_trans_result`` and + ``transmit`` functions into the IRAM to avoid possible cache miss. + + During unit test, this is enabled to measure the ideal case of api. + +config SPI_MASTER_ISR_IN_IRAM + bool "Place SPI master ISR function into IRAM" + default y + help + Place the SPI master ISR in to IRAM to avoid possibly cache miss, or + being disabled during flash writing access. + +endmenu # SPI Master Configuration + +endmenu # Driver configurations diff --git a/components/driver/gpio.c b/components/driver/gpio.c index e017cd87df..d81d2c25c3 100644 --- a/components/driver/gpio.c +++ b/components/driver/gpio.c @@ -21,6 +21,7 @@ #include "driver/rtc_io.h" #include "soc/soc.h" #include "esp_log.h" +#include "soc/gpio_periph.h" static const char* GPIO_TAG = "gpio"; #define GPIO_CHECK(a, str, ret_val) \ @@ -29,49 +30,6 @@ static const char* GPIO_TAG = "gpio"; return (ret_val); \ } -const uint32_t GPIO_PIN_MUX_REG[GPIO_PIN_COUNT] = { - IO_MUX_GPIO0_REG, - IO_MUX_GPIO1_REG, - IO_MUX_GPIO2_REG, - IO_MUX_GPIO3_REG, - IO_MUX_GPIO4_REG, - IO_MUX_GPIO5_REG, - IO_MUX_GPIO6_REG, - IO_MUX_GPIO7_REG, - IO_MUX_GPIO8_REG, - IO_MUX_GPIO9_REG, - IO_MUX_GPIO10_REG, - IO_MUX_GPIO11_REG, - IO_MUX_GPIO12_REG, - IO_MUX_GPIO13_REG, - IO_MUX_GPIO14_REG, - IO_MUX_GPIO15_REG, - IO_MUX_GPIO16_REG, - IO_MUX_GPIO17_REG, - IO_MUX_GPIO18_REG, - IO_MUX_GPIO19_REG, - 0, - IO_MUX_GPIO21_REG, - IO_MUX_GPIO22_REG, - IO_MUX_GPIO23_REG, - 0, - IO_MUX_GPIO25_REG, - IO_MUX_GPIO26_REG, - IO_MUX_GPIO27_REG, - 0, - 0, - 0, - 0, - IO_MUX_GPIO32_REG, - IO_MUX_GPIO33_REG, - IO_MUX_GPIO34_REG, - IO_MUX_GPIO35_REG, - IO_MUX_GPIO36_REG, - IO_MUX_GPIO37_REG, - IO_MUX_GPIO38_REG, - IO_MUX_GPIO39_REG, -}; - typedef struct { gpio_isr_t fn; /*!< isr function */ void* args; /*!< isr function args */ @@ -133,9 +91,19 @@ esp_err_t gpio_set_intr_type(gpio_num_t gpio_num, gpio_int_type_t intr_type) return ESP_OK; } +static void gpio_intr_status_clr(gpio_num_t gpio_num) +{ + if (gpio_num < 32) { + GPIO.status_w1tc = BIT(gpio_num); + } else { + GPIO.status1_w1tc.intr_st = BIT(gpio_num - 32); + } +} + static esp_err_t gpio_intr_enable_on_core (gpio_num_t gpio_num, uint32_t core_id) { GPIO_CHECK(GPIO_IS_VALID_GPIO(gpio_num), "GPIO number error", ESP_ERR_INVALID_ARG); + gpio_intr_status_clr(gpio_num); if (core_id == 0) { GPIO.pin[gpio_num].int_ena = GPIO_PRO_CPU_INTR_ENA; //enable pro cpu intr } else { @@ -153,6 +121,7 @@ esp_err_t gpio_intr_disable(gpio_num_t gpio_num) { GPIO_CHECK(GPIO_IS_VALID_GPIO(gpio_num), "GPIO number error", ESP_ERR_INVALID_ARG); GPIO.pin[gpio_num].int_ena = 0; //disable GPIO intr + gpio_intr_status_clr(gpio_num); return ESP_OK; } @@ -291,7 +260,11 @@ esp_err_t gpio_config(const gpio_config_t *pGPIOConfig) } do { io_reg = GPIO_PIN_MUX_REG[io_num]; - if (((gpio_pin_mask >> io_num) & BIT(0)) && io_reg) { + if (((gpio_pin_mask >> io_num) & BIT(0))) { + if (!io_reg) { + ESP_LOGE(GPIO_TAG, "IO%d is not a valid GPIO",io_num); + return ESP_ERR_INVALID_ARG; + } if(RTC_GPIO_IS_VALID_GPIO(io_num)){ rtc_gpio_deinit(io_num); } @@ -339,6 +312,21 @@ esp_err_t gpio_config(const gpio_config_t *pGPIOConfig) return ESP_OK; } +esp_err_t gpio_reset_pin(gpio_num_t gpio_num) +{ + assert(gpio_num >= 0 && GPIO_IS_VALID_GPIO(gpio_num)); + gpio_config_t cfg = { + .pin_bit_mask = BIT64(gpio_num), + .mode = GPIO_MODE_DISABLE, + //for powersave reasons, the GPIO should not be floating, select pullup + .pull_up_en = true, + .pull_down_en = false, + .intr_type = GPIO_INTR_DISABLE, + }; + gpio_config(&cfg); + return ESP_OK; +} + void IRAM_ATTR gpio_intr_service(void* arg) { //GPIO intr process diff --git a/components/driver/include/driver/gpio.h b/components/driver/include/driver/gpio.h index f8aa33abf9..bc8436491d 100644 --- a/components/driver/include/driver/gpio.h +++ b/components/driver/include/driver/gpio.h @@ -24,6 +24,7 @@ #include "rom/gpio.h" #include "esp_attr.h" #include "esp_intr_alloc.h" +#include "soc/gpio_periph.h" #ifdef __cplusplus extern "C" { @@ -121,10 +122,8 @@ extern "C" { #define GPIO_MODE_DEF_OD (BIT2) -#define GPIO_PIN_COUNT 40 /** @endcond */ -extern const uint32_t GPIO_PIN_MUX_REG[GPIO_PIN_COUNT]; #define GPIO_IS_VALID_GPIO(gpio_num) ((gpio_num < GPIO_PIN_COUNT && GPIO_PIN_MUX_REG[gpio_num] != 0)) /*!< Check whether it is a valid GPIO number */ #define GPIO_IS_VALID_OUTPUT_GPIO(gpio_num) ((GPIO_IS_VALID_GPIO(gpio_num)) && (gpio_num < 34)) /*!< Check whether it can be a valid GPIO number of output mode */ @@ -248,6 +247,18 @@ typedef intr_handle_t gpio_isr_handle_t; */ esp_err_t gpio_config(const gpio_config_t *pGPIOConfig); +/** + * @brief Reset an gpio to default state (select gpio function, enable pullup and disable input and output). + * + * @param gpio_num GPIO number. + * + * @note This function also configures the IOMUX for this pin to the GPIO + * function, and disconnects any other peripheral output configured via GPIO + * Matrix. + * + * @return Always return ESP_OK. + */ +esp_err_t gpio_reset_pin(gpio_num_t gpio_num); /** * @brief GPIO set interrupt trigger type diff --git a/components/driver/include/driver/ledc.h b/components/driver/include/driver/ledc.h index 8f70b1c003..6a82c19a2f 100644 --- a/components/driver/include/driver/ledc.h +++ b/components/driver/include/driver/ledc.h @@ -455,7 +455,7 @@ void ledc_fade_func_uninstall(); esp_err_t ledc_fade_start(ledc_mode_t speed_mode, ledc_channel_t channel, ledc_fade_mode_t fade_mode); /** - * @brief A thread-safe API to set duty for LEDC channel and update the settings immediately + * @brief A thread-safe API to set duty for LEDC channel and return when duty updated. * @note If a fade operation is running in progress on that channel, the driver would not allow it to be stopped. * Other duty operations will have to wait until the fade operation has finished. * diff --git a/components/driver/include/driver/pcnt.h b/components/driver/include/driver/pcnt.h index c751473baa..e96450d0b9 100644 --- a/components/driver/include/driver/pcnt.h +++ b/components/driver/include/driver/pcnt.h @@ -98,6 +98,8 @@ typedef intr_handle_t pcnt_isr_handle_t; /** * @brief Configure Pulse Counter unit + * @note + * This function will disable three events: PCNT_EVT_L_LIM, PCNT_EVT_H_LIM, PCNT_EVT_ZERO. * * @param pcnt_config Pointer of Pulse Counter unit configure parameter * @@ -233,16 +235,19 @@ esp_err_t pcnt_get_event_value(pcnt_unit_t unit, pcnt_evt_type_t evt_type, int16 /** * @brief Register PCNT interrupt handler, the handler is an ISR. * The handler will be attached to the same CPU core that this function is running on. + * Please do not use pcnt_isr_service_install if this function was called. * * @param fn Interrupt handler function. * @param arg Parameter for handler function * @param 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. * @param handle Pointer to return handle. If non-NULL, a handle for the interrupt will - * be returned here. + * be returned here. Calling esp_intr_free to unregister this ISR service if needed, + * but only if the handle is not NULL. * * @return * - ESP_OK Success + * - ESP_ERR_NOT_FOUND Can not find the interrupt that matches the flags. * - ESP_ERR_INVALID_ARG Function pointer error. */ esp_err_t pcnt_isr_register(void (*fn)(void*), void * arg, int intr_alloc_flags, pcnt_isr_handle_t *handle); @@ -358,7 +363,8 @@ esp_err_t pcnt_isr_handler_add(pcnt_unit_t unit, void(*isr_handler)(void *), voi /** * @brief Install PCNT ISR service. * @note We can manage different interrupt service for each unit. - * Please do not use pcnt_isr_register if this function was called. + * This function will use the default ISR handle service, Calling pcnt_isr_service_uninstall to + * uninstall the default service if needed. Please do not use pcnt_isr_register if this function was called. * * @param 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. diff --git a/components/driver/include/driver/periph_ctrl.h b/components/driver/include/driver/periph_ctrl.h index 82a328d679..9689a8cb21 100644 --- a/components/driver/include/driver/periph_ctrl.h +++ b/components/driver/include/driver/periph_ctrl.h @@ -1,4 +1,4 @@ -// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// 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. @@ -14,49 +14,16 @@ #ifndef _DRIVER_PERIPH_CTRL_H_ #define _DRIVER_PERIPH_CTRL_H_ + #include "esp_err.h" #include "soc/soc.h" #include "soc/dport_reg.h" +#include "soc/periph_defs.h" #ifdef __cplusplus extern "C" { #endif -typedef enum { - PERIPH_LEDC_MODULE = 0, - PERIPH_UART0_MODULE, - PERIPH_UART1_MODULE, - PERIPH_UART2_MODULE, - PERIPH_I2C0_MODULE, - PERIPH_I2C1_MODULE, - PERIPH_I2S0_MODULE, - PERIPH_I2S1_MODULE, - PERIPH_TIMG0_MODULE, - PERIPH_TIMG1_MODULE, - PERIPH_PWM0_MODULE, - PERIPH_PWM1_MODULE, - PERIPH_PWM2_MODULE, - PERIPH_PWM3_MODULE, - PERIPH_UHCI0_MODULE, - PERIPH_UHCI1_MODULE, - PERIPH_RMT_MODULE, - PERIPH_PCNT_MODULE, - PERIPH_SPI_MODULE, - PERIPH_HSPI_MODULE, - PERIPH_VSPI_MODULE, - PERIPH_SPI_DMA_MODULE, - PERIPH_SDMMC_MODULE, - PERIPH_SDIO_SLAVE_MODULE, - PERIPH_CAN_MODULE, - PERIPH_EMAC_MODULE, - PERIPH_RNG_MODULE, - PERIPH_WIFI_MODULE, - PERIPH_BT_MODULE, - PERIPH_WIFI_BT_COMMON_MODULE, - PERIPH_BT_BASEBAND_MODULE, - PERIPH_BT_LC_MODULE, -} periph_module_t; - /** * @brief enable peripheral module * diff --git a/components/driver/include/driver/rtc_io.h b/components/driver/include/driver/rtc_io.h index 522a9f9b6e..710c040e52 100644 --- a/components/driver/include/driver/rtc_io.h +++ b/components/driver/include/driver/rtc_io.h @@ -19,33 +19,11 @@ #include "esp_err.h" #include "driver/gpio.h" #include "soc/rtc_gpio_channel.h" - +#include "soc/rtc_periph.h" #ifdef __cplusplus extern "C" { #endif -/** - * @brief Pin function information for a single GPIO pad's RTC functions. - * - * This is an internal function of the driver, and is not usually useful - * for external use. - */ -typedef struct { - uint32_t reg; /*!< Register of RTC pad, or 0 if not an RTC GPIO */ - uint32_t mux; /*!< Bit mask for selecting digital pad or RTC pad */ - uint32_t func; /*!< Shift of pad function (FUN_SEL) field */ - uint32_t ie; /*!< Mask of input enable */ - uint32_t pullup; /*!< Mask of pullup enable */ - uint32_t pulldown; /*!< Mask of pulldown enable */ - uint32_t slpsel; /*!< If slpsel bit is set, slpie will be used as pad input enabled signal in sleep mode */ - uint32_t slpie; /*!< Mask of input enable in sleep mode */ - uint32_t hold; /*!< Mask of hold enable */ - uint32_t hold_force;/*!< Mask of hold_force bit for RTC IO in RTC_CNTL_HOLD_FORCE_REG */ - uint32_t drv_v; /*!< Mask of drive capability */ - uint32_t drv_s; /*!< Offset of drive capability */ - int rtc_num; /*!< RTC IO number, or -1 if not an RTC GPIO */ -} rtc_gpio_desc_t; - typedef enum { RTC_GPIO_MODE_INPUT_ONLY , /*!< Pad input */ RTC_GPIO_MODE_OUTPUT_ONLY, /*!< Pad output */ @@ -53,15 +31,6 @@ typedef enum { RTC_GPIO_MODE_DISABLED, /*!< Pad (output + input) disable */ } rtc_gpio_mode_t; -/** - * @brief Provides access to a constant table of RTC I/O pin - * function information. - * - * This is an internal function of the driver, and is not usually useful - * for external use. - */ -extern const rtc_gpio_desc_t rtc_gpio_desc[GPIO_PIN_COUNT]; - /** * @brief Determine if the specified GPIO is a valid RTC GPIO. * diff --git a/components/driver/include/driver/sdio_slave.h b/components/driver/include/driver/sdio_slave.h index 66b3bc5e21..05f08102ae 100644 --- a/components/driver/include/driver/sdio_slave.h +++ b/components/driver/include/driver/sdio_slave.h @@ -47,10 +47,12 @@ typedef enum { /// Timing of SDIO slave typedef enum { - SDIO_SLAVE_TIMING_NSEND_PSAMPLE = 0,///< Send at negedge, and sample at posedge. Default value for SD protocol. - SDIO_SLAVE_TIMING_NSEND_NSAMPLE, ///< Send at negedge, and sample at negedge - SDIO_SLAVE_TIMING_PSEND_PSAMPLE, ///< Send at posedge, and sample at posedge + SDIO_SLAVE_TIMING_PSEND_PSAMPLE = 0,/**< Send at posedge, and sample at posedge. Default value for HS mode. + * Normally there's no problem using this to work in DS mode. + */ + SDIO_SLAVE_TIMING_NSEND_PSAMPLE ,///< Send at negedge, and sample at posedge. Default value for DS mode and below. SDIO_SLAVE_TIMING_PSEND_NSAMPLE, ///< Send at posedge, and sample at negedge + SDIO_SLAVE_TIMING_NSEND_NSAMPLE, ///< Send at negedge, and sample at negedge } sdio_slave_timing_t; /// Configuration of SDIO slave mode @@ -197,12 +199,12 @@ uint8_t* sdio_slave_recv_get_buf( sdio_slave_buf_handle_t handle, size_t *len_o) esp_err_t sdio_slave_send_queue(uint8_t* addr, size_t len, void* arg, TickType_t wait); /** Return the ownership of a finished transaction. - * @param arg_o Argument of the finished transaction. + * @param out_arg Argument of the finished transaction. Set to NULL if unused. * @param wait Time to wait if there's no finished sending transaction. * * @return ESP_ERR_TIMEOUT if no transaction finished, or ESP_OK if succeed. */ -esp_err_t sdio_slave_send_get_finished(void** arg_o, TickType_t wait); +esp_err_t sdio_slave_send_get_finished(void** out_arg, TickType_t wait); /** Start a new sending transfer, and wait for it (blocked) to be finished. * diff --git a/components/driver/include/driver/sdmmc_defs.h b/components/driver/include/driver/sdmmc_defs.h index b9b13680dd..c3a63bd8d6 100644 --- a/components/driver/include/driver/sdmmc_defs.h +++ b/components/driver/include/driver/sdmmc_defs.h @@ -31,11 +31,13 @@ #define MMC_SEND_EXT_CSD 8 /* R1 */ #define MMC_SEND_CSD 9 /* R2 */ #define MMC_SEND_CID 10 /* R1 */ +#define MMC_READ_DAT_UNTIL_STOP 11 /* R1 */ #define MMC_STOP_TRANSMISSION 12 /* R1B */ #define MMC_SEND_STATUS 13 /* R1 */ #define MMC_SET_BLOCKLEN 16 /* R1 */ #define MMC_READ_BLOCK_SINGLE 17 /* R1 */ #define MMC_READ_BLOCK_MULTIPLE 18 /* R1 */ +#define MMC_WRITE_DAT_UNTIL_STOP 20 /* R1 */ #define MMC_SET_BLOCK_COUNT 23 /* R1 */ #define MMC_WRITE_BLOCK_SINGLE 24 /* R1 */ #define MMC_WRITE_BLOCK_MULTIPLE 25 /* R1 */ diff --git a/components/driver/include/driver/spi_common.h b/components/driver/include/driver/spi_common.h index 9f014d2792..cc029db2b9 100644 --- a/components/driver/include/driver/spi_common.h +++ b/components/driver/include/driver/spi_common.h @@ -1,4 +1,4 @@ -// Copyright 2010-2017 Espressif Systems (Shanghai) PTE LTD +// Copyright 2010-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. @@ -19,9 +19,8 @@ #include #include #include "esp_err.h" -#include "soc/spi_struct.h" #include "rom/lldesc.h" - +#include "soc/spi_periph.h" #ifdef __cplusplus extern "C" @@ -100,11 +99,9 @@ bool spicommon_dma_chan_claim(int dma_chan); */ bool spicommon_dma_chan_free(int dma_chan); - - #define SPICOMMON_BUSFLAG_SLAVE 0 ///< Initialize I/O in slave mode #define SPICOMMON_BUSFLAG_MASTER (1<<0) ///< Initialize I/O in master mode -#define SPICOMMON_BUSFLAG_NATIVE_PINS (1<<1) ///< Check using native pins. Or indicates the pins are configured through the IO mux rather than GPIO matrix. +#define SPICOMMON_BUSFLAG_NATIVE_PINS (1<<1) ///< Check using iomux pins. Or indicates the pins are configured through the IO mux rather than GPIO matrix. #define SPICOMMON_BUSFLAG_SCLK (1<<2) ///< Check existing of SCLK pin. Or indicates CLK line initialized. #define SPICOMMON_BUSFLAG_MISO (1<<3) ///< Check existing of MISO pin. Or indicates MISO line initialized. #define SPICOMMON_BUSFLAG_MOSI (1<<4) ///< Check existing of MOSI pin. Or indicates CLK line initialized. @@ -125,7 +122,7 @@ bool spicommon_dma_chan_free(int dma_chan); * @param flags Combination of SPICOMMON_BUSFLAG_* flags, set to ensure the pins set are capable with some functions: * - ``SPICOMMON_BUSFLAG_MASTER``: Initialize I/O in master mode * - ``SPICOMMON_BUSFLAG_SLAVE``: Initialize I/O in slave mode - * - ``SPICOMMON_BUSFLAG_NATIVE_PINS``: Pins set should match the native pins of the controller. + * - ``SPICOMMON_BUSFLAG_NATIVE_PINS``: Pins set should match the iomux pins of the controller. * - ``SPICOMMON_BUSFLAG_SCLK``, ``SPICOMMON_BUSFLAG_MISO``, ``SPICOMMON_BUSFLAG_MOSI``: * Make sure SCLK/MISO/MOSI is/are set to a valid GPIO. Also check output capability according to the mode. * - ``SPICOMMON_BUSFLAG_DUAL``: Make sure both MISO and MOSI are output capable so that DIO mode is capable. @@ -133,7 +130,7 @@ bool spicommon_dma_chan_free(int dma_chan); * - ``SPICOMMON_BUSFLAG_QUAD``: Combination of ``SPICOMMON_BUSFLAG_DUAL`` and ``SPICOMMON_BUSFLAG_WPHD``. * @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_NATIVE_PINS``: The bus is connected to native pins. + * - ``SPICOMMON_BUSFLAG_NATIVE_PINS``: The bus is connected to iomux pins. * - ``SPICOMMON_BUSFLAG_SCLK``, ``SPICOMMON_BUSFLAG_MISO``, ``SPICOMMON_BUSFLAG_MOSI``: The bus has * CLK/MISO/MOSI connected. * - ``SPICOMMON_BUSFLAG_DUAL``: The bus is capable with DIO mode. @@ -147,14 +144,26 @@ esp_err_t spicommon_bus_initialize_io(spi_host_device_t host, const spi_bus_conf /** * @brief Free the IO used by a SPI peripheral - * + * @deprecated Use spicommon_bus_free_io_cfg instead. + * * @param host SPI peripheral to be freed + * * @return * - ESP_ERR_INVALID_ARG if parameter is invalid * - ESP_OK on success */ +esp_err_t spicommon_bus_free_io(spi_host_device_t host) __attribute__((deprecated)); -esp_err_t spicommon_bus_free_io(spi_host_device_t host); +/** + * @brief Free the IO used by a SPI peripheral + * + * @param bus_cfg Bus config struct which defines which pins to be used. + * + * @return + * - ESP_ERR_INVALID_ARG if parameter is invalid + * - ESP_OK on success + */ +esp_err_t spicommon_bus_free_io_cfg(const spi_bus_config_t *bus_cfg); /** * @brief Initialize a Chip Select pin for a specific SPI peripheral @@ -171,12 +180,19 @@ void spicommon_cs_initialize(spi_host_device_t host, int cs_io_num, int cs_num, /** * @brief Free a chip select line + * @deprecated Use spicommon_cs_io, which inputs the gpio num rather than the cs id instead. * * @param host SPI peripheral * @param cs_num CS id to free */ -void spicommon_cs_free(spi_host_device_t host, int cs_num); +void spicommon_cs_free(spi_host_device_t host, int cs_num) __attribute__((deprecated)); +/** + * @brief Free a chip select line + * + * @param cs_gpio_num CS gpio num to free + */ +void spicommon_cs_free_io(int cs_gpio_num); /** * @brief Setup a DMA link chain diff --git a/components/driver/include/driver/spi_master.h b/components/driver/include/driver/spi_master.h index 232ad36eb7..4e64c404ed 100644 --- a/components/driver/include/driver/spi_master.h +++ b/components/driver/include/driver/spi_master.h @@ -1,4 +1,4 @@ -// Copyright 2010-2016 Espressif Systems (Shanghai) PTE LTD +// Copyright 2010-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. @@ -22,6 +22,19 @@ #include "driver/spi_common.h" +/** SPI master clock is divided by 80MHz apb clock. Below defines are example frequencies, and are accurate. Be free to specify a random frequency, it will be rounded to closest frequency (to macros below if above 8MHz). + * 8MHz + */ +#define SPI_MASTER_FREQ_8M (APB_CLK_FREQ/10) +#define SPI_MASTER_FREQ_9M (APB_CLK_FREQ/9) ///< 8.89MHz +#define SPI_MASTER_FREQ_10M (APB_CLK_FREQ/8) ///< 10MHz +#define SPI_MASTER_FREQ_11M (APB_CLK_FREQ/7) ///< 11.43MHz +#define SPI_MASTER_FREQ_13M (APB_CLK_FREQ/6) ///< 13.33MHz +#define SPI_MASTER_FREQ_16M (APB_CLK_FREQ/5) ///< 16MHz +#define SPI_MASTER_FREQ_20M (APB_CLK_FREQ/4) ///< 20MHz +#define SPI_MASTER_FREQ_26M (APB_CLK_FREQ/3) ///< 26.67MHz +#define SPI_MASTER_FREQ_40M (APB_CLK_FREQ/2) ///< 40MHz +#define SPI_MASTER_FREQ_80M (APB_CLK_FREQ/1) ///< 80MHz #ifdef __cplusplus extern "C" @@ -35,12 +48,12 @@ extern "C" #define SPI_DEVICE_POSITIVE_CS (1<<3) ///< Make CS positive during a transaction instead of negative #define SPI_DEVICE_HALFDUPLEX (1<<4) ///< Transmit data before receiving it, instead of simultaneously #define SPI_DEVICE_CLK_AS_CS (1<<5) ///< Output clock on CS line if CS is active -/** There are timing issue when reading at high frequency (the frequency is related to whether native pins are used, valid time after slave sees the clock). +/** There are timing issue when reading at high frequency (the frequency is related to whether iomux pins are used, valid time after slave sees the clock). * - In half-duplex mode, the driver automatically inserts dummy bits before reading phase to fix the timing issue. Set this flag to disable this feature. * - In full-duplex mode, however, the hardware cannot use dummy bits, so there is no way to prevent data being read from getting corrupted. * Set this flag to confirm that you're going to work with output only, or read without dummy bits at your own risk. */ -#define SPI_DEVICE_NO_DUMMY (1<<6) +#define SPI_DEVICE_NO_DUMMY (1<<6) typedef struct spi_transaction_t spi_transaction_t; @@ -57,7 +70,12 @@ typedef struct { uint8_t duty_cycle_pos; ///< Duty cycle of positive clock, in 1/256th increments (128 = 50%/50% duty). Setting this to 0 (=not setting it) is equivalent to setting this to 128. uint8_t cs_ena_pretrans; ///< Amount of SPI bit-cycles the cs should be activated before the transmission (0-16). This only works on half-duplex transactions. uint8_t cs_ena_posttrans; ///< Amount of SPI bit-cycles the cs should stay active after the transmission (0-16) - int clock_speed_hz; ///< Clock speed, in Hz + int clock_speed_hz; ///< Clock speed, divisors of 80MHz, in Hz. See ``SPI_MASTER_FREQ_*``. + int input_delay_ns; /**< Maximum data valid time of slave. The time required between SCLK and MISO + valid, including the possible clock delay from slave to master. The driver uses this value to give an extra + delay before the MISO is ready on the line. Leave at 0 unless you know you need a delay. For better timing + performance at high frequency (over 8MHz), it's suggest to have the right value. + */ int spics_io_num; ///< CS GPIO pin for this device, or -1 if not used uint32_t flags; ///< Bitwise OR of SPI_DEVICE_* flags int queue_size; ///< Transaction queue size. This sets how many transactions can be 'in the air' (queued using spi_device_queue_trans but not yet finished using spi_device_get_trans_result) at the same time @@ -87,9 +105,9 @@ struct spi_transaction_t { */ uint64_t addr; /**< Address data, of which the length is set in the ``address_bits`` of spi_device_interface_config_t. * - * NOTE: this field, used to be "address" in ESP-IDF 2.1 and before, is re-written to be used in a new way in ESP-IDF3.0. + * NOTE: this field, used to be "address" in ESP-IDF 2.1 and before, is re-written to be used in a new way in ESP-IDF3.0. * - * Example: write 0x123400 and address_bits=24 to send address of 0x12, 0x34, 0x00 (in previous version, you may have to write 0x12340000). + * Example: write 0x123400 and address_bits=24 to send address of 0x12, 0x34, 0x00 (in previous version, you may have to write 0x12340000). */ size_t length; ///< Total data length, in bits size_t rxlength; ///< Total data length received, should be not greater than ``length`` in full-duplex mode (0 defaults this to the value of ``length``). @@ -125,14 +143,14 @@ typedef struct spi_device_t* spi_device_handle_t; ///< Handle for a device on a * @param host SPI peripheral that controls this bus * @param bus_config Pointer to a spi_bus_config_t struct specifying how the host should be initialized * @param dma_chan Either channel 1 or 2, or 0 in the case when no DMA is required. Selecting a DMA channel - * for a SPI bus allows transfers on the bus to have sizes only limited by the amount of + * for a SPI bus allows transfers on the bus to have sizes only limited by the amount of * internal memory. Selecting no DMA channel (by passing the value 0) limits the amount of * bytes transfered to a maximum of 32. * - * @warning If a DMA channel is selected, any transmit and receive buffer used should be allocated in + * @warning If a DMA channel is selected, any transmit and receive buffer used should be allocated in * DMA-capable memory. * - * @return + * @return * - ESP_ERR_INVALID_ARG if configuration is invalid * - ESP_ERR_INVALID_STATE if host already is in use * - ESP_ERR_NO_MEM if out of memory @@ -146,7 +164,7 @@ esp_err_t spi_bus_initialize(spi_host_device_t host, const spi_bus_config_t *bus * @warning In order for this to succeed, all devices have to be removed first. * * @param host SPI peripheral to free - * @return + * @return * - ESP_ERR_INVALID_ARG if parameter is invalid * - ESP_ERR_INVALID_STATE if not all devices on the bus are freed * - ESP_OK on success @@ -166,12 +184,12 @@ esp_err_t spi_bus_free(spi_host_device_t host); * @param host SPI peripheral to allocate device on * @param dev_config SPI interface protocol config for the device * @param handle Pointer to variable to hold the device handle - * @return + * @return * - ESP_ERR_INVALID_ARG if parameter is invalid * - ESP_ERR_NOT_FOUND if host doesn't have any free CS slots * - ESP_ERR_NO_MEM if out of memory * - ESP_OK on success - */ + */ esp_err_t spi_bus_add_device(spi_host_device_t host, const spi_device_interface_config_t *dev_config, spi_device_handle_t *handle); @@ -179,7 +197,7 @@ esp_err_t spi_bus_add_device(spi_host_device_t host, const spi_device_interface_ * @brief Remove a device from the SPI bus * * @param handle Device handle to free - * @return + * @return * - ESP_ERR_INVALID_ARG if parameter is invalid * - ESP_ERR_INVALID_STATE if device already is freed * - ESP_OK on success @@ -206,18 +224,18 @@ esp_err_t spi_device_queue_trans(spi_device_handle_t handle, spi_transaction_t * /** * @brief Get the result of a SPI transaction queued earlier * - * This routine will wait until a transaction to the given device (queued earlier with + * This routine will wait until a transaction to the given device (queued earlier with * spi_device_queue_trans) has succesfully completed. It will then return the description of the - * completed transaction so software can inspect the result and e.g. free the memory or + * completed transaction so software can inspect the result and e.g. free the memory or * re-use the buffers. * * @param handle Device handle obtained using spi_host_add_dev - * @param trans_desc Pointer to variable able to contain a pointer to the description of the transaction - that is executed. The descriptor should not be modified until the descriptor is returned by + * @param trans_desc Pointer to variable able to contain a pointer to the description of the transaction + that is executed. The descriptor should not be modified until the descriptor is returned by spi_device_get_trans_result. * @param ticks_to_wait Ticks to wait until there's a returned item; use portMAX_DELAY to never time out. - * @return + * @return * - ESP_ERR_INVALID_ARG if parameter is invalid * - ESP_ERR_TIMEOUT if there was no completed transaction before ticks_to_wait expired * - ESP_OK on success @@ -253,6 +271,30 @@ esp_err_t spi_device_transmit(spi_device_handle_t handle, spi_transaction_t *tra */ int spi_cal_clock(int fapb, int hz, int duty_cycle, uint32_t* reg_o); +/** + * @brief Calculate the timing settings of specified frequency and settings. + * + * @param gpio_is_used True if using GPIO matrix, or False if iomux pins are used. + * @param input_delay_ns Input delay from SCLK launch edge to MISO data valid. + * @param eff_clk Effective clock frequency (in Hz) from spi_cal_clock. + * @param dummy_o Address of dummy bits used output. Set to NULL if not needed. + * @param cycles_remain_o Address of cycles remaining (after dummy bits are used) output. + * - -1 If too many cycles remaining, suggest to compensate half a clock. + * - 0 If no remaining cycles or dummy bits are not used. + * - positive value: cycles suggest to compensate. + * @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); + +/** + * @brief Get the frequency limit of current configurations. + * SPI master working at this limit is OK, while above the limit, full duplex mode and DMA will not work, + * and dummy bits will be aplied in the half duplex mode. + * @param gpio_is_used True if using GPIO matrix, or False if native pins are used. + * @param input_delay_ns Input delay from SCLK launch edge to MISO data valid. + * @return Frequency limit of current configurations. + */ +int spi_get_freq_limit(bool gpio_is_used, int input_delay_ns); #ifdef __cplusplus } diff --git a/components/driver/include/driver/spi_slave.h b/components/driver/include/driver/spi_slave.h index 1d5ea34029..9ad4b9126d 100644 --- a/components/driver/include/driver/spi_slave.h +++ b/components/driver/include/driver/spi_slave.h @@ -1,4 +1,4 @@ -// Copyright 2010-2017 Espressif Systems (Shanghai) PTE LTD +// Copyright 2010-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. diff --git a/components/driver/include/driver/touch_pad.h b/components/driver/include/driver/touch_pad.h index f18069ab3c..21e2e2ec7c 100644 --- a/components/driver/include/driver/touch_pad.h +++ b/components/driver/include/driver/touch_pad.h @@ -122,6 +122,7 @@ esp_err_t touch_pad_init(); /** * @brief Un-install touch pad driver. + * @note After this function is called, other touch functions are prohibited from being called. * @return * - ESP_OK Success * - ESP_FAIL Touch pad driver not initialized @@ -130,8 +131,12 @@ esp_err_t touch_pad_deinit(); /** * @brief Configure touch pad interrupt threshold. + * + * @note If FSM mode is set to TOUCH_FSM_MODE_TIMER, this function will be blocked for one measurement cycle and wait for data to be valid. + * * @param touch_num touch pad index * @param threshold interrupt threshold, + * * @return * - ESP_OK Success * - ESP_ERR_INVALID_ARG if argument wrong @@ -144,28 +149,34 @@ esp_err_t touch_pad_config(touch_pad_t touch_num, uint16_t threshold); * Each touch sensor has a counter to count the number of charge/discharge cycles. * When the pad is not 'touched', we can get a number of the counter. * When the pad is 'touched', the value in counter will get smaller because of the larger equivalent capacitance. - * @note This API requests hardware measurement once. If IIR filter mode is enabled,, + * + * @note This API requests hardware measurement once. If IIR filter mode is enabled, * please use 'touch_pad_read_raw_data' interface instead. + * * @param touch_num touch pad index * @param touch_value pointer to accept touch sensor value + * * @return * - ESP_OK Success - * - ESP_ERR_INVALID_ARG Touch pad error + * - ESP_ERR_INVALID_ARG Touch pad parameter error + * - ESP_ERR_INVALID_STATE This touch pad hardware connection is error, the value of "touch_value" is 0. * - ESP_FAIL Touch pad not initialized */ esp_err_t touch_pad_read(touch_pad_t touch_num, uint16_t * touch_value); /** * @brief get filtered touch sensor counter value by IIR filter. + * * @note touch_pad_filter_start has to be called before calling touch_pad_read_filtered. * This function can be called from ISR * * @param touch_num touch pad index * @param touch_value pointer to accept touch sensor value + * * @return * - ESP_OK Success - * - ESP_ERR_INVALID_ARG Touch pad error - * - ESP_ERR_INVALID_STATE Touch pad not initialized + * - ESP_ERR_INVALID_ARG Touch pad parameter error + * - ESP_ERR_INVALID_STATE This touch pad hardware connection is error, the value of "touch_value" is 0. * - ESP_FAIL Touch pad not initialized */ esp_err_t touch_pad_read_filtered(touch_pad_t touch_num, uint16_t *touch_value); @@ -173,6 +184,7 @@ esp_err_t touch_pad_read_filtered(touch_pad_t touch_num, uint16_t *touch_value); /** * @brief get raw data (touch sensor counter value) from IIR filter process. * Need not request hardware measurements. + * * @note touch_pad_filter_start has to be called before calling touch_pad_read_raw_data. * This function can be called from ISR * @@ -180,10 +192,10 @@ esp_err_t touch_pad_read_filtered(touch_pad_t touch_num, uint16_t *touch_value); * @param touch_value pointer to accept touch sensor value * * @return - * - ESP_OK Success - * - ESP_ERR_INVALID_ARG Touch pad error - * - ESP_ERR_INVALID_STATE Touch pad not initialized - * - ESP_FAIL Touch pad not initialized + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Touch pad parameter error + * - ESP_ERR_INVALID_STATE This touch pad hardware connection is error, the value of "touch_value" is 0. + * - ESP_FAIL Touch pad not initialized */ esp_err_t touch_pad_read_raw_data(touch_pad_t touch_num, uint16_t *touch_value); @@ -508,8 +520,6 @@ esp_err_t touch_pad_get_filter_period(uint32_t* p_period_ms); * when detecting slight change of capacitance. * Need to call touch_pad_filter_start before all touch filter APIs * - * If filter is not initialized, this API will initialize the filter with given period. - * If filter is already initialized, this API will update the filter period. * @note This filter uses FreeRTOS timer, which is dispatched from a task with * priority 1 by default on CPU 0. So if some application task with higher priority * takes a lot of CPU0 time, then the quality of data obtained from this filter will be affected. @@ -541,6 +551,15 @@ esp_err_t touch_pad_filter_stop(); */ esp_err_t touch_pad_filter_delete(); +/** + * @brief Get the touch pad which caused wakeup from sleep + * @param pad_num pointer to touch pad which caused wakeup + * @return + * - ESP_OK Success + * - ESP_FAIL get status err + */ +esp_err_t touch_pad_get_wakeup_status(touch_pad_t *pad_num); + #ifdef __cplusplus } #endif diff --git a/components/driver/ledc.c b/components/driver/ledc.c index 6891877c86..c2cb94e591 100644 --- a/components/driver/ledc.c +++ b/components/driver/ledc.c @@ -449,6 +449,7 @@ esp_err_t ledc_set_freq(ledc_mode_t speed_mode, ledc_timer_t timer_num, uint32_t ret = ESP_FAIL; } LEDC.timer_group[speed_mode].timer[timer_num].conf.clock_divider = clock_divider; + ledc_ls_timer_update(speed_mode, timer_num); portEXIT_CRITICAL(&ledc_spinlock); return ret; } @@ -587,7 +588,7 @@ static esp_err_t _ledc_set_fade_with_step(ledc_mode_t speed_mode, ledc_channel_t { portENTER_CRITICAL(&ledc_spinlock); uint32_t duty_cur = LEDC.channel_group[speed_mode].channel[channel].duty_rd.duty_read >> LEDC_DUTY_DECIMAL_BIT_NUM; - // if duty == max_duty and scale and fade_down == 1, counter would overflow. + // When duty == max_duty, meanwhile, if scale == 1 and fade_down == 1, counter would overflow. if (duty_cur == ledc_get_max_duty(speed_mode, channel)) { duty_cur -= 1; } @@ -609,6 +610,7 @@ static esp_err_t _ledc_set_fade_with_step(ledc_mode_t speed_mode, ledc_channel_t step_num = step_num > LEDC_STEP_NUM_MAX ? LEDC_STEP_NUM_MAX : step_num; } } + portEXIT_CRITICAL(&ledc_spinlock); if (scale > 0 && step_num > 0) { ledc_duty_config(speed_mode, channel, LEDC_VAL_NO_CHANGE, duty_cur << 4, dir, step_num, cycle_num, scale); @@ -736,18 +738,16 @@ esp_err_t ledc_set_duty_and_update(ledc_mode_t speed_mode, ledc_channel_t channe LEDC_ARG_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, "speed_mode"); LEDC_ARG_CHECK(channel < LEDC_CHANNEL_MAX, "channel"); LEDC_ARG_CHECK(duty <= ledc_get_max_duty(speed_mode, channel), "target_duty"); + LEDC_CHECK(ledc_fade_channel_init_check(speed_mode, channel) == ESP_OK , LEDC_FADE_INIT_ERROR_STR, ESP_FAIL); + uint32_t cur_duty = ledc_get_duty(speed_mode, channel); + if (duty == cur_duty) { + return ESP_OK; + } _ledc_op_lock_acquire(speed_mode, channel); _ledc_fade_hw_acquire(speed_mode, channel); - ledc_duty_config(speed_mode, - channel, //uint32_t chan_num, - hpoint, //uint32_t hpoint_val, - duty << 4, //uint32_t duty_val,the least 4 bits are decimal part - 1, //uint32_t increase, - 1, //uint32_t duty_num, - 1, //uint32_t duty_cycle, - 0 //uint32_t duty_scale - ); - ledc_update_duty(speed_mode, channel); + int scale = cur_duty > duty ? cur_duty - duty : duty - cur_duty; + _ledc_set_fade_with_step(speed_mode, channel, duty, scale, 1); + _ledc_fade_start(speed_mode, channel, LEDC_FADE_WAIT_DONE); _ledc_fade_hw_release(speed_mode, channel); _ledc_op_lock_release(speed_mode, channel); return ESP_OK; diff --git a/components/driver/pcnt.c b/components/driver/pcnt.c index b859b495b1..6fcc2b5525 100644 --- a/components/driver/pcnt.c +++ b/components/driver/pcnt.c @@ -24,6 +24,7 @@ #define PCNT_COUNT_MODE_ERR_STR "PCNT COUNTER MODE ERROR" #define PCNT_CTRL_MODE_ERR_STR "PCNT CTRL MODE ERROR" #define PCNT_EVT_TYPE_ERR_STR "PCNT value type error" +#define PCNT_LIMT_VAL_ERR_STR "PCNT limit value error" #define PCNT_ENTER_CRITICAL(mux) portENTER_CRITICAL(mux) #define PCNT_EXIT_CRITICAL(mux) portEXIT_CRITICAL(mux) @@ -221,6 +222,8 @@ esp_err_t pcnt_set_event_value(pcnt_unit_t unit, pcnt_evt_type_t evt_type, int16 { 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_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); if(evt_type == PCNT_EVT_L_LIM) { PCNT.conf_unit[unit].conf2.cnt_l_lim = value; } else if(evt_type == PCNT_EVT_H_LIM) { diff --git a/components/driver/rmt.c b/components/driver/rmt.c index 9460cefa71..8ee1640c0b 100644 --- a/components/driver/rmt.c +++ b/components/driver/rmt.c @@ -137,7 +137,7 @@ esp_err_t rmt_get_rx_idle_thresh(rmt_channel_t channel, uint16_t *thresh) esp_err_t rmt_set_mem_block_num(rmt_channel_t channel, uint8_t rmt_mem_num) { RMT_CHECK(channel < RMT_CHANNEL_MAX, RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG); - RMT_CHECK(rmt_mem_num < 16, RMT_MEM_CNT_ERROR_STR, ESP_ERR_INVALID_ARG); + RMT_CHECK(rmt_mem_num <= RMT_CHANNEL_MAX - channel, RMT_MEM_CNT_ERROR_STR, ESP_ERR_INVALID_ARG); RMT.conf_ch[channel].conf0.mem_size = rmt_mem_num; return ESP_OK; } @@ -669,7 +669,7 @@ esp_err_t rmt_driver_uninstall(rmt_channel_t channel) } //Avoid blocking here(when the interrupt is disabled and do not wait tx done). if(p_rmt_obj[channel]->wait_done) { - xSemaphoreTake(p_rmt_obj[channel]->tx_sem, portMAX_DELAY); + xSemaphoreTake(p_rmt_obj[channel]->tx_sem, portMAX_DELAY); } rmt_set_rx_intr_en(channel, 0); rmt_set_err_intr_en(channel, 0); @@ -929,4 +929,4 @@ esp_err_t rmt_write_sample(rmt_channel_t channel, const uint8_t *src, size_t src xSemaphoreGive(p_rmt->tx_sem); } return ESP_OK; -} \ No newline at end of file +} diff --git a/components/driver/rtc_module.c b/components/driver/rtc_module.c index d08cbd1357..a7124a1bfe 100644 --- a/components/driver/rtc_module.c +++ b/components/driver/rtc_module.c @@ -1,6 +1,9 @@ +// Copyright 2016-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 @@ -22,6 +25,7 @@ #include "soc/rtc_cntl_struct.h" #include "soc/syscon_reg.h" #include "soc/syscon_struct.h" +#include "soc/rtc.h" #include "rtc_io.h" #include "touch_pad.h" #include "adc.h" @@ -97,12 +101,12 @@ In ADC2, there're two locks used for different cases: adc2_spinlock should be acquired first, then adc2_wifi_lock or rtc_spinlock. */ //prevent ADC2 being used by wifi and other tasks at the same time. -static _lock_t adc2_wifi_lock = NULL; +static _lock_t adc2_wifi_lock; //prevent ADC2 being used by tasks (regardless of WIFI) portMUX_TYPE adc2_spinlock = portMUX_INITIALIZER_UNLOCKED; //prevent ADC1 being used by I2S dma and other tasks at the same time. -static _lock_t adc1_i2s_lock = NULL; +static _lock_t adc1_i2s_lock; typedef struct { TimerHandle_t timer; @@ -117,50 +121,6 @@ static touch_pad_filter_t *s_touch_pad_filter = NULL; static uint16_t s_touch_pad_init_bit = 0x0000; static filter_cb_t s_filter_cb = NULL; -//Reg,Mux,Fun,IE,Up,Down,Rtc_number -const rtc_gpio_desc_t rtc_gpio_desc[GPIO_PIN_COUNT] = { - {RTC_IO_TOUCH_PAD1_REG, RTC_IO_TOUCH_PAD1_MUX_SEL_M, RTC_IO_TOUCH_PAD1_FUN_SEL_S, RTC_IO_TOUCH_PAD1_FUN_IE_M, RTC_IO_TOUCH_PAD1_RUE_M, RTC_IO_TOUCH_PAD1_RDE_M, RTC_IO_TOUCH_PAD1_SLP_SEL_M, RTC_IO_TOUCH_PAD1_SLP_IE_M, RTC_IO_TOUCH_PAD1_HOLD_M, RTC_CNTL_TOUCH_PAD1_HOLD_FORCE_M, RTC_IO_TOUCH_PAD1_DRV_V, RTC_IO_TOUCH_PAD1_DRV_S, RTCIO_GPIO0_CHANNEL}, //0 - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1}, //1 - {RTC_IO_TOUCH_PAD2_REG, RTC_IO_TOUCH_PAD2_MUX_SEL_M, RTC_IO_TOUCH_PAD2_FUN_SEL_S, RTC_IO_TOUCH_PAD2_FUN_IE_M, RTC_IO_TOUCH_PAD2_RUE_M, RTC_IO_TOUCH_PAD2_RDE_M, RTC_IO_TOUCH_PAD2_SLP_SEL_M, RTC_IO_TOUCH_PAD2_SLP_IE_M, RTC_IO_TOUCH_PAD2_HOLD_M, RTC_CNTL_TOUCH_PAD2_HOLD_FORCE_M, RTC_IO_TOUCH_PAD2_DRV_V, RTC_IO_TOUCH_PAD2_DRV_S, RTCIO_GPIO2_CHANNEL}, //2 - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1}, //3 - {RTC_IO_TOUCH_PAD0_REG, RTC_IO_TOUCH_PAD0_MUX_SEL_M, RTC_IO_TOUCH_PAD0_FUN_SEL_S, RTC_IO_TOUCH_PAD0_FUN_IE_M, RTC_IO_TOUCH_PAD0_RUE_M, RTC_IO_TOUCH_PAD0_RDE_M, RTC_IO_TOUCH_PAD0_SLP_SEL_M, RTC_IO_TOUCH_PAD0_SLP_IE_M, RTC_IO_TOUCH_PAD0_HOLD_M, RTC_CNTL_TOUCH_PAD0_HOLD_FORCE_M, RTC_IO_TOUCH_PAD0_DRV_V, RTC_IO_TOUCH_PAD0_DRV_S, RTCIO_GPIO4_CHANNEL}, //4 - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1}, //5 - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1}, //6 - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1}, //7 - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1}, //8 - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1}, //9 - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1}, //10 - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1}, //11 - {RTC_IO_TOUCH_PAD5_REG, RTC_IO_TOUCH_PAD5_MUX_SEL_M, RTC_IO_TOUCH_PAD5_FUN_SEL_S, RTC_IO_TOUCH_PAD5_FUN_IE_M, RTC_IO_TOUCH_PAD5_RUE_M, RTC_IO_TOUCH_PAD5_RDE_M, RTC_IO_TOUCH_PAD5_SLP_SEL_M, RTC_IO_TOUCH_PAD5_SLP_IE_M, RTC_IO_TOUCH_PAD5_HOLD_M, RTC_CNTL_TOUCH_PAD5_HOLD_FORCE_M, RTC_IO_TOUCH_PAD5_DRV_V, RTC_IO_TOUCH_PAD5_DRV_S, RTCIO_GPIO12_CHANNEL}, //12 - {RTC_IO_TOUCH_PAD4_REG, RTC_IO_TOUCH_PAD4_MUX_SEL_M, RTC_IO_TOUCH_PAD4_FUN_SEL_S, RTC_IO_TOUCH_PAD4_FUN_IE_M, RTC_IO_TOUCH_PAD4_RUE_M, RTC_IO_TOUCH_PAD4_RDE_M, RTC_IO_TOUCH_PAD4_SLP_SEL_M, RTC_IO_TOUCH_PAD4_SLP_IE_M, RTC_IO_TOUCH_PAD4_HOLD_M, RTC_CNTL_TOUCH_PAD4_HOLD_FORCE_M, RTC_IO_TOUCH_PAD4_DRV_V, RTC_IO_TOUCH_PAD4_DRV_S, RTCIO_GPIO13_CHANNEL}, //13 - {RTC_IO_TOUCH_PAD6_REG, RTC_IO_TOUCH_PAD6_MUX_SEL_M, RTC_IO_TOUCH_PAD6_FUN_SEL_S, RTC_IO_TOUCH_PAD6_FUN_IE_M, RTC_IO_TOUCH_PAD6_RUE_M, RTC_IO_TOUCH_PAD6_RDE_M, RTC_IO_TOUCH_PAD6_SLP_SEL_M, RTC_IO_TOUCH_PAD6_SLP_IE_M, RTC_IO_TOUCH_PAD6_HOLD_M, RTC_CNTL_TOUCH_PAD6_HOLD_FORCE_M, RTC_IO_TOUCH_PAD6_DRV_V, RTC_IO_TOUCH_PAD6_DRV_S, RTCIO_GPIO14_CHANNEL}, //14 - {RTC_IO_TOUCH_PAD3_REG, RTC_IO_TOUCH_PAD3_MUX_SEL_M, RTC_IO_TOUCH_PAD3_FUN_SEL_S, RTC_IO_TOUCH_PAD3_FUN_IE_M, RTC_IO_TOUCH_PAD3_RUE_M, RTC_IO_TOUCH_PAD3_RDE_M, RTC_IO_TOUCH_PAD3_SLP_SEL_M, RTC_IO_TOUCH_PAD3_SLP_IE_M, RTC_IO_TOUCH_PAD3_HOLD_M, RTC_CNTL_TOUCH_PAD3_HOLD_FORCE_M, RTC_IO_TOUCH_PAD3_DRV_V, RTC_IO_TOUCH_PAD3_DRV_S, RTCIO_GPIO15_CHANNEL}, //15 - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1}, //16 - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1}, //17 - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1}, //18 - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1}, //19 - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1}, //20 - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1}, //21 - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1}, //22 - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1}, //23 - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1}, //24 - {RTC_IO_PAD_DAC1_REG, RTC_IO_PDAC1_MUX_SEL_M, RTC_IO_PDAC1_FUN_SEL_S, RTC_IO_PDAC1_FUN_IE_M, RTC_IO_PDAC1_RUE_M, RTC_IO_PDAC1_RDE_M, RTC_IO_PDAC1_SLP_SEL_M, RTC_IO_PDAC1_SLP_IE_M, RTC_IO_PDAC1_HOLD_M, RTC_CNTL_PDAC1_HOLD_FORCE_M, RTC_IO_PDAC1_DRV_V, RTC_IO_PDAC1_DRV_S, RTCIO_GPIO25_CHANNEL}, //25 - {RTC_IO_PAD_DAC2_REG, RTC_IO_PDAC2_MUX_SEL_M, RTC_IO_PDAC2_FUN_SEL_S, RTC_IO_PDAC2_FUN_IE_M, RTC_IO_PDAC2_RUE_M, RTC_IO_PDAC2_RDE_M, RTC_IO_PDAC2_SLP_SEL_M, RTC_IO_PDAC2_SLP_IE_M, RTC_IO_PDAC2_HOLD_M, RTC_CNTL_PDAC2_HOLD_FORCE_M, RTC_IO_PDAC2_DRV_V, RTC_IO_PDAC2_DRV_S, RTCIO_GPIO26_CHANNEL}, //26 - {RTC_IO_TOUCH_PAD7_REG, RTC_IO_TOUCH_PAD7_MUX_SEL_M, RTC_IO_TOUCH_PAD7_FUN_SEL_S, RTC_IO_TOUCH_PAD7_FUN_IE_M, RTC_IO_TOUCH_PAD7_RUE_M, RTC_IO_TOUCH_PAD7_RDE_M, RTC_IO_TOUCH_PAD7_SLP_SEL_M, RTC_IO_TOUCH_PAD7_SLP_IE_M, RTC_IO_TOUCH_PAD7_HOLD_M, RTC_CNTL_TOUCH_PAD7_HOLD_FORCE_M, RTC_IO_TOUCH_PAD7_DRV_V, RTC_IO_TOUCH_PAD7_DRV_S, RTCIO_GPIO27_CHANNEL}, //27 - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1}, //28 - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1}, //29 - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1}, //30 - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1}, //31 - {RTC_IO_XTAL_32K_PAD_REG, RTC_IO_X32P_MUX_SEL_M, RTC_IO_X32P_FUN_SEL_S, RTC_IO_X32P_FUN_IE_M, RTC_IO_X32P_RUE_M, RTC_IO_X32P_RDE_M, RTC_IO_X32P_SLP_SEL_M, RTC_IO_X32P_SLP_IE_M, RTC_IO_X32P_HOLD_M, RTC_CNTL_X32P_HOLD_FORCE_M, RTC_IO_X32P_DRV_V, RTC_IO_X32P_DRV_S, RTCIO_GPIO32_CHANNEL}, //32 - {RTC_IO_XTAL_32K_PAD_REG, RTC_IO_X32N_MUX_SEL_M, RTC_IO_X32N_FUN_SEL_S, RTC_IO_X32N_FUN_IE_M, RTC_IO_X32N_RUE_M, RTC_IO_X32N_RDE_M, RTC_IO_X32N_SLP_SEL_M, RTC_IO_X32N_SLP_IE_M, RTC_IO_X32N_HOLD_M, RTC_CNTL_X32N_HOLD_FORCE_M, RTC_IO_X32N_DRV_V, RTC_IO_X32N_DRV_S, RTCIO_GPIO33_CHANNEL}, //33 - {RTC_IO_ADC_PAD_REG, RTC_IO_ADC1_MUX_SEL_M, RTC_IO_ADC1_FUN_SEL_S, RTC_IO_ADC1_FUN_IE_M, 0, 0, RTC_IO_ADC1_SLP_SEL_M, RTC_IO_ADC1_SLP_IE_M, RTC_IO_ADC1_HOLD_M, RTC_CNTL_ADC1_HOLD_FORCE_M, 0, 0, RTCIO_GPIO34_CHANNEL}, //34 - {RTC_IO_ADC_PAD_REG, RTC_IO_ADC2_MUX_SEL_M, RTC_IO_ADC2_FUN_SEL_S, RTC_IO_ADC2_FUN_IE_M, 0, 0, RTC_IO_ADC2_SLP_SEL_M, RTC_IO_ADC2_SLP_IE_M, RTC_IO_ADC1_HOLD_M, RTC_CNTL_ADC2_HOLD_FORCE_M, 0, 0, RTCIO_GPIO35_CHANNEL}, //35 - {RTC_IO_SENSOR_PADS_REG, RTC_IO_SENSE1_MUX_SEL_M, RTC_IO_SENSE1_FUN_SEL_S, RTC_IO_SENSE1_FUN_IE_M, 0, 0, RTC_IO_SENSE1_SLP_SEL_M, RTC_IO_SENSE1_SLP_IE_M, RTC_IO_SENSE1_HOLD_M, RTC_CNTL_SENSE1_HOLD_FORCE_M, 0, 0, RTCIO_GPIO36_CHANNEL}, //36 - {RTC_IO_SENSOR_PADS_REG, RTC_IO_SENSE2_MUX_SEL_M, RTC_IO_SENSE2_FUN_SEL_S, RTC_IO_SENSE2_FUN_IE_M, 0, 0, RTC_IO_SENSE2_SLP_SEL_M, RTC_IO_SENSE2_SLP_IE_M, RTC_IO_SENSE1_HOLD_M, RTC_CNTL_SENSE2_HOLD_FORCE_M, 0, 0, RTCIO_GPIO37_CHANNEL}, //37 - {RTC_IO_SENSOR_PADS_REG, RTC_IO_SENSE3_MUX_SEL_M, RTC_IO_SENSE3_FUN_SEL_S, RTC_IO_SENSE3_FUN_IE_M, 0, 0, RTC_IO_SENSE3_SLP_SEL_M, RTC_IO_SENSE3_SLP_IE_M, RTC_IO_SENSE1_HOLD_M, RTC_CNTL_SENSE3_HOLD_FORCE_M, 0, 0, RTCIO_GPIO38_CHANNEL}, //38 - {RTC_IO_SENSOR_PADS_REG, RTC_IO_SENSE4_MUX_SEL_M, RTC_IO_SENSE4_FUN_SEL_S, RTC_IO_SENSE4_FUN_IE_M, 0, 0, RTC_IO_SENSE4_SLP_SEL_M, RTC_IO_SENSE4_SLP_IE_M, RTC_IO_SENSE1_HOLD_M, RTC_CNTL_SENSE4_HOLD_FORCE_M, 0, 0, RTCIO_GPIO39_CHANNEL}, //39 -}; - typedef enum { ADC_CTRL_RTC = 0, ADC_CTRL_ULP = 1, @@ -519,7 +479,7 @@ static void touch_pad_filter_cb(void *arg) { static uint32_t s_filtered_temp[TOUCH_PAD_MAX] = {0}; - if (s_touch_pad_filter == NULL) { + if (s_touch_pad_filter == NULL || rtc_touch_mux == NULL) { return; } uint16_t val = 0; @@ -820,16 +780,28 @@ esp_err_t touch_pad_config(touch_pad_t touch_num, uint16_t threshold) { RTC_MODULE_CHECK(rtc_touch_mux != NULL, "Touch pad not initialized", ESP_FAIL); RTC_MODULE_CHECK(touch_num < TOUCH_PAD_MAX, "Touch_Pad Num Err", ESP_ERR_INVALID_ARG); - s_touch_pad_init_bit |= (1 << touch_num); + touch_fsm_mode_t mode; touch_pad_set_thresh(touch_num, threshold); touch_pad_io_init(touch_num); touch_pad_set_cnt_mode(touch_num, TOUCH_PAD_SLOPE_7, TOUCH_PAD_TIE_OPT_LOW); - touch_fsm_mode_t mode; touch_pad_get_fsm_mode(&mode); if (TOUCH_FSM_MODE_SW == mode) { touch_pad_clear_group_mask((1 << touch_num), (1 << touch_num), (1 << touch_num)); + s_touch_pad_init_bit |= (1 << touch_num); } else if (TOUCH_FSM_MODE_TIMER == mode){ + uint16_t sleep_time = 0; + uint16_t meas_cycle = 0; + uint32_t wait_time_ms = 0; + uint32_t wait_tick = 0; + uint32_t rtc_clk = rtc_clk_slow_freq_get_hz(); touch_pad_set_group_mask((1 << touch_num), (1 << touch_num), (1 << touch_num)); + touch_pad_get_meas_time(&sleep_time, &meas_cycle); + //If the FSM mode is 'TOUCH_FSM_MODE_TIMER', The data will be ready after one measurement cycle + //after this function is executed, otherwise, the "touch_value" by "touch_pad_read" is 0. + wait_time_ms = sleep_time/(rtc_clk/1000) + meas_cycle/(RTC_FAST_CLK_FREQ_APPROX/1000); + wait_tick = wait_time_ms/portTICK_RATE_MS; + vTaskDelay(wait_tick ? wait_tick : 1); + s_touch_pad_init_bit |= (1 << touch_num); } else { return ESP_FAIL; } @@ -846,25 +818,25 @@ esp_err_t touch_pad_init() } touch_pad_intr_disable(); touch_pad_clear_group_mask(TOUCH_PAD_BIT_MASK_MAX, TOUCH_PAD_BIT_MASK_MAX, TOUCH_PAD_BIT_MASK_MAX); - touch_pad_set_fsm_mode(TOUCH_FSM_MODE_DEFAULT); touch_pad_set_trigger_mode(TOUCH_TRIGGER_MODE_DEFAULT); touch_pad_set_trigger_source(TOUCH_TRIGGER_SOURCE_DEFAULT); touch_pad_clear_status(); touch_pad_set_meas_time(TOUCH_PAD_SLEEP_CYCLE_DEFAULT, TOUCH_PAD_MEASURE_CYCLE_DEFAULT); + touch_pad_set_fsm_mode(TOUCH_FSM_MODE_DEFAULT); return ESP_OK; } esp_err_t touch_pad_deinit() { - if (rtc_touch_mux == NULL) { - return ESP_FAIL; + RTC_MODULE_CHECK(rtc_touch_mux != NULL, "Touch pad not initialized", ESP_FAIL); + if (s_touch_pad_filter != NULL) { + touch_pad_filter_stop(); + touch_pad_filter_delete(); } s_touch_pad_init_bit = 0x0000; - touch_pad_filter_delete(); touch_pad_set_fsm_mode(TOUCH_FSM_MODE_SW); touch_pad_clear_status(); touch_pad_intr_disable(); - vSemaphoreDelete(rtc_touch_mux); rtc_touch_mux = NULL; return ESP_OK; } @@ -890,6 +862,9 @@ static esp_err_t _touch_pad_read(touch_pad_t touch_num, uint16_t *touch_value, t } else { res = ESP_FAIL; } + if (*touch_value == 0) { + res = ESP_ERR_INVALID_STATE; + } return res; } @@ -913,8 +888,11 @@ IRAM_ATTR esp_err_t touch_pad_read_raw_data(touch_pad_t touch_num, uint16_t *tou RTC_MODULE_CHECK(rtc_touch_mux != NULL, "Touch pad not initialized", ESP_FAIL); RTC_MODULE_CHECK(touch_num < TOUCH_PAD_MAX, "Touch_Pad Num Err", ESP_ERR_INVALID_ARG); RTC_MODULE_CHECK(touch_value != NULL, "touch_value", ESP_ERR_INVALID_ARG); - RTC_MODULE_CHECK(s_touch_pad_filter != NULL, "Touch pad filter not initialized", ESP_ERR_INVALID_STATE); + RTC_MODULE_CHECK(s_touch_pad_filter != NULL, "Touch pad filter not initialized", ESP_FAIL); *touch_value = s_touch_pad_filter->raw_val[touch_num]; + if (*touch_value == 0) { + return ESP_ERR_INVALID_STATE; + } return ESP_OK; } @@ -923,8 +901,11 @@ IRAM_ATTR esp_err_t touch_pad_read_filtered(touch_pad_t touch_num, uint16_t *tou RTC_MODULE_CHECK(rtc_touch_mux != NULL, "Touch pad not initialized", ESP_FAIL); RTC_MODULE_CHECK(touch_num < TOUCH_PAD_MAX, "Touch_Pad Num Err", ESP_ERR_INVALID_ARG); RTC_MODULE_CHECK(touch_value != NULL, "touch_value", ESP_ERR_INVALID_ARG); - RTC_MODULE_CHECK(s_touch_pad_filter != NULL, "Touch pad filter not initialized", ESP_ERR_INVALID_STATE); + RTC_MODULE_CHECK(s_touch_pad_filter != NULL, "Touch pad filter not initialized", ESP_FAIL); *touch_value = (s_touch_pad_filter->filtered_val[touch_num]); + if (*touch_value == 0) { + return ESP_ERR_INVALID_STATE; + } return ESP_OK; } @@ -984,20 +965,17 @@ esp_err_t touch_pad_filter_start(uint32_t filter_period_ms) if (s_touch_pad_filter->timer == NULL) { ret = ESP_ERR_NO_MEM; } - xTimerStart(s_touch_pad_filter->timer, portMAX_DELAY); - } else { - xTimerChangePeriod(s_touch_pad_filter->timer, filter_period_ms / portTICK_PERIOD_MS, portMAX_DELAY); s_touch_pad_filter->period = filter_period_ms; - xTimerStart(s_touch_pad_filter->timer, portMAX_DELAY); } xSemaphoreGive(rtc_touch_mux); + touch_pad_filter_cb(NULL); return ret; } esp_err_t touch_pad_filter_stop() { RTC_MODULE_CHECK(s_touch_pad_filter != NULL, "Touch pad filter not initialized", ESP_ERR_INVALID_STATE); - + RTC_MODULE_CHECK(rtc_touch_mux != NULL, "Touch pad not initialized", ESP_ERR_INVALID_STATE); esp_err_t ret = ESP_OK; xSemaphoreTake(rtc_touch_mux, portMAX_DELAY); if (s_touch_pad_filter != NULL) { @@ -1013,6 +991,7 @@ esp_err_t touch_pad_filter_stop() esp_err_t touch_pad_filter_delete() { RTC_MODULE_CHECK(s_touch_pad_filter != NULL, "Touch pad filter not initialized", ESP_ERR_INVALID_STATE); + RTC_MODULE_CHECK(rtc_touch_mux != NULL, "Touch pad not initialized", ESP_ERR_INVALID_STATE); xSemaphoreTake(rtc_touch_mux, portMAX_DELAY); if (s_touch_pad_filter != NULL) { if (s_touch_pad_filter->timer != NULL) { @@ -1027,6 +1006,16 @@ esp_err_t touch_pad_filter_delete() return ESP_OK; } +esp_err_t touch_pad_get_wakeup_status(touch_pad_t *pad_num) +{ + uint32_t touch_mask = SENS.sar_touch_ctrl2.touch_meas_en; + if(touch_mask == 0) { + return ESP_FAIL; + } + *pad_num = touch_pad_num_wrap((touch_pad_t)(__builtin_ffs(touch_mask) - 1)); + return ESP_OK; +} + /*--------------------------------------------------------------- ADC Common ---------------------------------------------------------------*/ diff --git a/components/driver/sdio_slave.c b/components/driver/sdio_slave.c index b63b5c677a..3e994b527d 100644 --- a/components/driver/sdio_slave.c +++ b/components/driver/sdio_slave.c @@ -96,6 +96,7 @@ The driver of FIFOs works as below: #include "freertos/FreeRTOS.h" #include "soc/dport_access.h" #include "soc/dport_reg.h" +#include "soc/io_mux_reg.h" #include "freertos/semphr.h" #include "xtensa/core-macros.h" #include "driver/periph_ctrl.h" @@ -119,12 +120,12 @@ typedef enum { } send_state_t; typedef struct { - uint32_t clk; - uint32_t cmd; - uint32_t d0; - uint32_t d1; - uint32_t d2; - uint32_t d3; + uint32_t clk_gpio; + uint32_t cmd_gpio; + uint32_t d0_gpio; + uint32_t d1_gpio; + uint32_t d2_gpio; + uint32_t d3_gpio; int func; } sdio_slave_slot_info_t ; @@ -135,20 +136,20 @@ typedef struct { // currently slot 0 is occupied by SPI for flash static const sdio_slave_slot_info_t s_slot_info[2] = { { - .clk = PERIPHS_IO_MUX_SD_CLK_U, - .cmd = PERIPHS_IO_MUX_SD_CMD_U, - .d0 = PERIPHS_IO_MUX_SD_DATA0_U, - .d1 = PERIPHS_IO_MUX_SD_DATA1_U, - .d2 = PERIPHS_IO_MUX_SD_DATA2_U, - .d3 = PERIPHS_IO_MUX_SD_DATA3_U, + .clk_gpio = 6, + .cmd_gpio = 11, + .d0_gpio = 7, + .d1_gpio = 8, + .d2_gpio = 9, + .d3_gpio = 10, .func = 0, }, { - .clk = PERIPHS_IO_MUX_MTMS_U, - .cmd = PERIPHS_IO_MUX_MTDO_U, - .d0 = PERIPHS_IO_MUX_GPIO2_U, - .d1 = PERIPHS_IO_MUX_GPIO4_U, - .d2 = PERIPHS_IO_MUX_MTDI_U, - .d3 = PERIPHS_IO_MUX_MTCK_U, + .clk_gpio = 14, + .cmd_gpio = 15, + .d0_gpio = 2, + .d1_gpio = 4, + .d2_gpio = 12, + .d3_gpio = 13, .func = 4, }, }; @@ -192,7 +193,7 @@ typedef struct { SemaphoreHandle_t remain_cnt; } sdio_ringbuf_t; -#define offset_of(type, field) ( (unsigned int)&(((type *)(0))->field) ) +#define offset_of(type, field) ( (unsigned int)&(((type *)(0))->field) ) typedef enum { ringbuf_write_ptr = offset_of(sdio_ringbuf_t, write_ptr), ringbuf_read_ptr = offset_of(sdio_ringbuf_t, read_ptr), @@ -224,7 +225,7 @@ typedef struct { /*------- receiving ---------------*/ buf_stailq_t recv_link_list; // now ready to/already hold data buf_tailq_t recv_reg_list; // removed from the link list, registered but not used now - buf_desc_t* recv_cur_ret; + volatile buf_desc_t* recv_cur_ret; // next desc to return, NULL if all loaded descriptors are returned portMUX_TYPE recv_spinlock; } sdio_context_t; @@ -303,7 +304,7 @@ no_mem: } //calculate a pointer with offset to a original pointer of the specific ringbuffer -static inline uint8_t* sdio_ringbuf_offset_ptr( sdio_ringbuf_t *buf, sdio_ringbuf_pointer_t ptr, uint32_t offset ) +static inline uint8_t* sdio_ringbuf_offset_ptr( sdio_ringbuf_t *buf, sdio_ringbuf_pointer_t ptr, uint32_t offset ) { uint8_t *buf_ptr = (uint8_t*)*(uint32_t*)(((uint8_t*)buf)+ptr); //get the specific pointer of the buffer uint8_t *offset_ptr=buf_ptr+offset; @@ -314,7 +315,7 @@ static inline uint8_t* sdio_ringbuf_offset_ptr( sdio_ringbuf_t *buf, sdio_ringbu static esp_err_t sdio_ringbuf_send( sdio_ringbuf_t* buf, esp_err_t (*copy_callback)(uint8_t*, void*), void* arg, TickType_t wait ) { portBASE_TYPE ret = xSemaphoreTake(buf->remain_cnt, wait); - if ( ret != pdTRUE ) return NULL; + if (ret != pdTRUE) return ESP_ERR_TIMEOUT; portENTER_CRITICAL( &buf->write_spinlock ); uint8_t* get_ptr = sdio_ringbuf_offset_ptr( buf, ringbuf_write_ptr, buf->item_size ); @@ -498,13 +499,18 @@ no_mem: return ESP_ERR_NO_MEM; } -static inline void configure_pin(uint32_t io_mux_reg, uint32_t func) +static void configure_pin(int pin, uint32_t func, bool pullup) { const int sdmmc_func = func; const int drive_strength = 3; - PIN_INPUT_ENABLE(io_mux_reg); - PIN_FUNC_SELECT(io_mux_reg, sdmmc_func); - PIN_SET_DRV(io_mux_reg, drive_strength); + assert(pin!=-1); + uint32_t reg = GPIO_PIN_MUX_REG[pin]; + assert(reg!=0); + + PIN_INPUT_ENABLE(reg); + PIN_FUNC_SELECT(reg, sdmmc_func); + PIN_SET_DRV(reg, drive_strength); + gpio_pulldown_dis(pin); } static inline esp_err_t sdio_slave_hw_init(sdio_slave_config_t *config) @@ -514,12 +520,13 @@ static inline esp_err_t sdio_slave_hw_init(sdio_slave_config_t *config) //initialize pin const sdio_slave_slot_info_t *slot = &s_slot_info[1]; - configure_pin(slot->clk, slot->func); - configure_pin(slot->cmd, slot->func); - configure_pin(slot->d0, slot->func); - configure_pin(slot->d1, slot->func); - configure_pin(slot->d2, slot->func); - configure_pin(slot->d3, slot->func); + configure_pin(slot->clk_gpio, slot->func, false); //clk doesn't need a pullup + configure_pin(slot->cmd_gpio, slot->func, false); + configure_pin(slot->d0_gpio, slot->func, false); + configure_pin(slot->d1_gpio, slot->func, false); + configure_pin(slot->d2_gpio, slot->func, false); + configure_pin(slot->d3_gpio, slot->func, false); + //enable module and config periph_module_reset(PERIPH_SDIO_SLAVE_MODULE); periph_module_enable(PERIPH_SDIO_SLAVE_MODULE); @@ -538,28 +545,28 @@ static inline esp_err_t sdio_slave_hw_init(sdio_slave_config_t *config) switch( config->timing ) { case SDIO_SLAVE_TIMING_PSEND_PSAMPLE: - HOST.conf.frc_sdio20 = 0xf; + HOST.conf.frc_sdio20 = 0x1f; HOST.conf.frc_sdio11 = 0; - HOST.conf.frc_pos_samp = 0xf; + HOST.conf.frc_pos_samp = 0x1f; HOST.conf.frc_neg_samp = 0; break; case SDIO_SLAVE_TIMING_PSEND_NSAMPLE: - HOST.conf.frc_sdio20 = 0xf; + HOST.conf.frc_sdio20 = 0x1f; HOST.conf.frc_sdio11 = 0; HOST.conf.frc_pos_samp = 0; - HOST.conf.frc_neg_samp = 0xf; + HOST.conf.frc_neg_samp = 0x1f; break; case SDIO_SLAVE_TIMING_NSEND_PSAMPLE: HOST.conf.frc_sdio20 = 0; - HOST.conf.frc_sdio11 = 0xf; - HOST.conf.frc_pos_samp = 0xf; + HOST.conf.frc_sdio11 = 0x1f; + HOST.conf.frc_pos_samp = 0x1f; HOST.conf.frc_neg_samp = 0; break; case SDIO_SLAVE_TIMING_NSEND_NSAMPLE: HOST.conf.frc_sdio20 = 0; - HOST.conf.frc_sdio11 = 0xf; + HOST.conf.frc_sdio11 = 0x1f; HOST.conf.frc_pos_samp = 0; - HOST.conf.frc_neg_samp = 0xf; + HOST.conf.frc_neg_samp = 0x1f; break; } @@ -951,9 +958,11 @@ esp_err_t sdio_slave_send_queue(uint8_t* addr, size_t len, void* arg, TickType_t return ESP_OK; } -esp_err_t sdio_slave_send_get_finished(void** arg, TickType_t wait) +esp_err_t sdio_slave_send_get_finished(void** out_arg, TickType_t wait) { - portBASE_TYPE err = xQueueReceive( context.ret_queue, arg, wait ); + void* arg = NULL; + portBASE_TYPE err = xQueueReceive(context.ret_queue, &arg, wait); + if (out_arg) *out_arg = arg; if ( err != pdTRUE ) return ESP_ERR_TIMEOUT; return ESP_OK; } @@ -1159,8 +1168,6 @@ static void sdio_intr_recv(void* arg) portBASE_TYPE yield = 0; if ( SLC.slc0_int_raw.tx_done ) { SLC.slc0_int_clr.tx_done = 1; - assert( context.recv_cur_ret != NULL ); - while ( context.recv_cur_ret && context.recv_cur_ret->owner == 0 ) { // This may cause the ``cur_ret`` pointer to be NULL, indicating the list is empty, // in this case the ``tx_done`` should happen no longer until new desc is appended. @@ -1185,15 +1192,24 @@ esp_err_t sdio_slave_recv_load_buf(sdio_slave_buf_handle_t handle) desc->owner = 1; desc->not_receiving = 0; //manually remove the prev link (by set not_receiving=0), to indicate this is in the queue - // 1. If all desc are returned in the ISR, the pointer is moved to NULL. The pointer is set to the newly appended desc here. - // 2. If the pointer is move to some not-returned desc (maybe the one appended here), do nothing. - // The ``cur_ret`` pointer must be checked and set after new desc appended to the list, or the pointer setting may fail. + buf_desc_t *const tail = STAILQ_LAST(queue, buf_desc_s, qe); + STAILQ_INSERT_TAIL( queue, desc, qe ); - if ( context.recv_cur_ret == NULL ) { + if (tail == NULL || (tail->owner == 0)) { + //in this case we have to set the ret pointer + if (tail != NULL) { + /* if the owner of the tail is returned to the software, the ISR is + * expect to write this pointer to NULL in a short time, wait until + * that and set new value for this pointer + */ + while (context.recv_cur_ret != NULL) {} + } + assert(context.recv_cur_ret == NULL); context.recv_cur_ret = desc; } + assert(context.recv_cur_ret != NULL); - if ( desc == STAILQ_FIRST(queue) ) { + if (tail == NULL) { //no one in the ll, start new ll operation. SLC.slc0_tx_link.addr = (uint32_t)desc; SLC.slc0_tx_link.start = 1; diff --git a/components/driver/sdmmc_host.c b/components/driver/sdmmc_host.c index 95cb81fdcf..8173bc8d3c 100644 --- a/components/driver/sdmmc_host.c +++ b/components/driver/sdmmc_host.c @@ -31,18 +31,16 @@ #define SDMMC_EVENT_QUEUE_LENGTH 32 typedef struct { - uint32_t clk; - uint32_t cmd; - uint32_t d0; - uint32_t d1; - uint32_t d2; - uint32_t d3; - uint32_t d4; - uint32_t d5; - uint32_t d6; - uint32_t d7; + uint8_t clk_gpio; + uint8_t cmd_gpio; + uint8_t d0_gpio; uint8_t d1_gpio; + uint8_t d2_gpio; uint8_t d3_gpio; + uint8_t d4_gpio; + uint8_t d5_gpio; + uint8_t d6_gpio; + uint8_t d7_gpio; uint8_t card_detect; uint8_t write_protect; uint8_t card_int; @@ -55,32 +53,32 @@ static void sdmmc_host_dma_init(); static const sdmmc_slot_info_t s_slot_info[2] = { { - .clk = PERIPHS_IO_MUX_SD_CLK_U, - .cmd = PERIPHS_IO_MUX_SD_CMD_U, - .d0 = PERIPHS_IO_MUX_SD_DATA0_U, - .d1 = PERIPHS_IO_MUX_SD_DATA1_U, - .d2 = PERIPHS_IO_MUX_SD_DATA2_U, - .d3 = PERIPHS_IO_MUX_SD_DATA3_U, + .clk_gpio = 6, + .cmd_gpio = 11, + .d0_gpio = 7, .d1_gpio = 8, + .d2_gpio = 9, .d3_gpio = 10, - .d4 = PERIPHS_IO_MUX_GPIO16_U, - .d5 = PERIPHS_IO_MUX_GPIO17_U, - .d6 = PERIPHS_IO_MUX_GPIO5_U, - .d7 = PERIPHS_IO_MUX_GPIO18_U, + .d4_gpio = 16, + .d5_gpio = 17, + .d6_gpio = 5, + .d7_gpio = 18, .card_detect = HOST_CARD_DETECT_N_1_IDX, .write_protect = HOST_CARD_WRITE_PRT_1_IDX, .card_int = HOST_CARD_INT_N_1_IDX, .width = 8 }, { - .clk = PERIPHS_IO_MUX_MTMS_U, - .cmd = PERIPHS_IO_MUX_MTDO_U, - .d0 = PERIPHS_IO_MUX_GPIO2_U, - .d1 = PERIPHS_IO_MUX_GPIO4_U, - .d2 = PERIPHS_IO_MUX_MTDI_U, - .d3 = PERIPHS_IO_MUX_MTCK_U, + .clk_gpio = 14, + .cmd_gpio = 15, + .d0_gpio = 2, .d1_gpio = 4, + .d2_gpio = 12, .d3_gpio = 13, + .d4_gpio = -1, //slot1 has no D4-7 + .d5_gpio = -1, + .d6_gpio = -1, + .d7_gpio = -1, .card_detect = HOST_CARD_DETECT_N_2_IDX, .write_protect = HOST_CARD_WRITE_PRT_2_IDX, .card_int = HOST_CARD_INT_N_2_IDX, @@ -340,14 +338,18 @@ esp_err_t sdmmc_host_init() return ESP_OK; } - -static inline void configure_pin(uint32_t io_mux_reg) +static void configure_pin(int pin) { const int sdmmc_func = 3; const int drive_strength = 3; - PIN_INPUT_ENABLE(io_mux_reg); - PIN_FUNC_SELECT(io_mux_reg, sdmmc_func); - PIN_SET_DRV(io_mux_reg, drive_strength); + assert(pin!=-1); + gpio_pulldown_dis(pin); + + uint32_t reg = GPIO_PIN_MUX_REG[pin]; + assert(reg != 0); + PIN_INPUT_ENABLE(reg); + PIN_FUNC_SELECT(reg, sdmmc_func); + PIN_SET_DRV(reg, drive_strength); } esp_err_t sdmmc_host_init_slot(int slot, const sdmmc_slot_config_t* slot_config) @@ -376,13 +378,13 @@ esp_err_t sdmmc_host_init_slot(int slot, const sdmmc_slot_config_t* slot_config) } s_slot_width[slot] = slot_width; - configure_pin(pslot->clk); - configure_pin(pslot->cmd); - configure_pin(pslot->d0); + configure_pin(pslot->clk_gpio); + configure_pin(pslot->cmd_gpio); + configure_pin(pslot->d0_gpio); if (slot_width >= 4) { - configure_pin(pslot->d1); - configure_pin(pslot->d2); + configure_pin(pslot->d1_gpio); + configure_pin(pslot->d2_gpio); //force pull-up D3 to make slave detect SD mode. connect to peripheral after width configuration. gpio_config_t gpio_conf = { .pin_bit_mask = BIT(pslot->d3_gpio), @@ -394,10 +396,10 @@ esp_err_t sdmmc_host_init_slot(int slot, const sdmmc_slot_config_t* slot_config) gpio_config( &gpio_conf ); gpio_set_level( pslot->d3_gpio, 1 ); if (slot_width == 8) { - configure_pin(pslot->d4); - configure_pin(pslot->d5); - configure_pin(pslot->d6); - configure_pin(pslot->d7); + configure_pin(pslot->d4_gpio); + configure_pin(pslot->d5_gpio); + configure_pin(pslot->d6_gpio); + configure_pin(pslot->d7_gpio); } } @@ -492,10 +494,10 @@ esp_err_t sdmmc_host_set_bus_width(int slot, size_t width) } else if (width == 4) { SDMMC.ctype.card_width_8 &= ~mask; SDMMC.ctype.card_width |= mask; - configure_pin(s_slot_info[slot].d3); // D3 was set to GPIO high to force slave into SD 1-bit mode, until 4-bit mode is set + configure_pin(s_slot_info[slot].d3_gpio); // D3 was set to GPIO high to force slave into SD 1-bit mode, until 4-bit mode is set } else if (width == 8){ SDMMC.ctype.card_width_8 |= mask; - configure_pin(s_slot_info[slot].d3); // D3 was set to GPIO high to force slave into SD 1-bit mode, until 4-bit mode is set + configure_pin(s_slot_info[slot].d3_gpio); // D3 was set to GPIO high to force slave into SD 1-bit mode, until 4-bit mode is set } else { return ESP_ERR_INVALID_ARG; } @@ -550,12 +552,12 @@ void sdmmc_host_dma_resume() esp_err_t sdmmc_host_io_int_enable(int slot) { - configure_pin(s_slot_info[slot].d1); + configure_pin(s_slot_info[slot].d1_gpio); return ESP_OK; } esp_err_t sdmmc_host_io_int_wait(int slot, TickType_t timeout_ticks) -{ +{ /* SDIO interrupts are negedge sensitive ones: the status bit is only set * when first interrupt triggered. * @@ -574,7 +576,7 @@ esp_err_t sdmmc_host_io_int_wait(int slot, TickType_t timeout_ticks) */ xSemaphoreTake(s_io_intr_event, 0); SDMMC.intmask.sdio |= BIT(slot); /* Re-enable SDIO interrupt */ - + if (xSemaphoreTake(s_io_intr_event, timeout_ticks) == pdTRUE) { return ESP_OK; } else { diff --git a/components/driver/sdmmc_transaction.c b/components/driver/sdmmc_transaction.c index 8abf9bb923..114a2f8969 100644 --- a/components/driver/sdmmc_transaction.c +++ b/components/driver/sdmmc_transaction.c @@ -272,6 +272,16 @@ static esp_err_t handle_event(sdmmc_command_t* cmd, sdmmc_req_state_t* state, return ESP_OK; } +static bool cmd_needs_auto_stop(const sdmmc_command_t* cmd) +{ + /* SDMMC host needs an "auto stop" flag for the following commands: */ + return cmd->datalen > 0 && + (cmd->opcode == MMC_WRITE_BLOCK_MULTIPLE || + cmd->opcode == MMC_READ_BLOCK_MULTIPLE || + cmd->opcode == MMC_WRITE_DAT_UNTIL_STOP || + cmd->opcode == MMC_READ_DAT_UNTIL_STOP); +} + static sdmmc_hw_cmd_t make_hw_cmd(sdmmc_command_t* cmd) { sdmmc_hw_cmd_t res = { 0 }; @@ -303,12 +313,11 @@ static sdmmc_hw_cmd_t make_hw_cmd(sdmmc_command_t* cmd) res.rw = 1; } assert(cmd->datalen % cmd->blklen == 0); - if ((cmd->datalen / cmd->blklen) > 1) { - res.send_auto_stop = 1; - } + res.send_auto_stop = cmd_needs_auto_stop(cmd) ? 1 : 0; } - ESP_LOGV(TAG, "%s: opcode=%d, rexp=%d, crc=%d", __func__, - res.cmd_index, res.response_expect, res.check_response_crc); + ESP_LOGV(TAG, "%s: opcode=%d, rexp=%d, crc=%d, auto_stop=%d", __func__, + res.cmd_index, res.response_expect, res.check_response_crc, + res.send_auto_stop); return res; } diff --git a/components/driver/spi_common.c b/components/driver/spi_common.c index 52f239af3b..aa5495a8cf 100644 --- a/components/driver/spi_common.c +++ b/components/driver/spi_common.c @@ -1,4 +1,4 @@ -// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// 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. @@ -15,10 +15,8 @@ #include #include "driver/spi_master.h" -#include "soc/gpio_sig_map.h" -#include "soc/spi_reg.h" #include "soc/dport_reg.h" -#include "soc/spi_struct.h" +#include "soc/spi_periph.h" #include "rom/ets_sys.h" #include "esp_types.h" #include "esp_attr.h" @@ -32,7 +30,6 @@ #include "driver/gpio.h" #include "driver/periph_ctrl.h" #include "esp_heap_caps.h" - #include "driver/spi_common.h" static const char *SPI_TAG = "spi"; @@ -49,109 +46,6 @@ typedef struct spi_device_t spi_device_t; #define FUNC_SPI 1 //all pins of HSPI and VSPI shares this function number #define FUNC_GPIO PIN_FUNC_GPIO -/* - Stores a bunch of per-spi-peripheral data. -*/ -typedef struct { - const uint8_t spiclk_out; //GPIO mux output signals - const uint8_t spiclk_in; - const uint8_t spid_out; - const uint8_t spiq_out; - const uint8_t spiwp_out; - const uint8_t spihd_out; - const uint8_t spid_in; //GPIO mux input signals - const uint8_t spiq_in; - const uint8_t spiwp_in; - const uint8_t spihd_in; - const uint8_t spics_out[3]; // /CS GPIO output mux signals - const uint8_t spics_in; - const uint8_t spiclk_native; //IO pins of IO_MUX muxed signals - const uint8_t spid_native; - const uint8_t spiq_native; - const uint8_t spiwp_native; - const uint8_t spihd_native; - const uint8_t spics0_native; - const uint8_t irq; //irq source for interrupt mux - const uint8_t irq_dma; //dma irq source for interrupt mux - const periph_module_t module; //peripheral module, for enabling clock etc - spi_dev_t *hw; //Pointer to the hardware registers -} spi_signal_conn_t; - -/* - Bunch of constants for every SPI peripheral: GPIO signals, irqs, hw addr of registers etc -*/ -static const spi_signal_conn_t io_signal[3] = { - { - .spiclk_out = SPICLK_OUT_IDX, - .spiclk_in = SPICLK_IN_IDX, - .spid_out = SPID_OUT_IDX, - .spiq_out = SPIQ_OUT_IDX, - .spiwp_out = SPIWP_OUT_IDX, - .spihd_out = SPIHD_OUT_IDX, - .spid_in = SPID_IN_IDX, - .spiq_in = SPIQ_IN_IDX, - .spiwp_in = SPIWP_IN_IDX, - .spihd_in = SPIHD_IN_IDX, - .spics_out = {SPICS0_OUT_IDX, SPICS1_OUT_IDX, SPICS2_OUT_IDX}, - .spics_in = SPICS0_IN_IDX, - .spiclk_native = 6, - .spid_native = 8, - .spiq_native = 7, - .spiwp_native = 10, - .spihd_native = 9, - .spics0_native = 11, - .irq = ETS_SPI1_INTR_SOURCE, - .irq_dma = ETS_SPI1_DMA_INTR_SOURCE, - .module = PERIPH_SPI_MODULE, - .hw = &SPI1 - }, { - .spiclk_out = HSPICLK_OUT_IDX, - .spiclk_in = HSPICLK_IN_IDX, - .spid_out = HSPID_OUT_IDX, - .spiq_out = HSPIQ_OUT_IDX, - .spiwp_out = HSPIWP_OUT_IDX, - .spihd_out = HSPIHD_OUT_IDX, - .spid_in = HSPID_IN_IDX, - .spiq_in = HSPIQ_IN_IDX, - .spiwp_in = HSPIWP_IN_IDX, - .spihd_in = HSPIHD_IN_IDX, - .spics_out = {HSPICS0_OUT_IDX, HSPICS1_OUT_IDX, HSPICS2_OUT_IDX}, - .spics_in = HSPICS0_IN_IDX, - .spiclk_native = 14, - .spid_native = 13, - .spiq_native = 12, - .spiwp_native = 2, - .spihd_native = 4, - .spics0_native = 15, - .irq = ETS_SPI2_INTR_SOURCE, - .irq_dma = ETS_SPI2_DMA_INTR_SOURCE, - .module = PERIPH_HSPI_MODULE, - .hw = &SPI2 - }, { - .spiclk_out = VSPICLK_OUT_IDX, - .spiclk_in = VSPICLK_IN_IDX, - .spid_out = VSPID_OUT_IDX, - .spiq_out = VSPIQ_OUT_IDX, - .spiwp_out = VSPIWP_OUT_IDX, - .spihd_out = VSPIHD_OUT_IDX, - .spid_in = VSPID_IN_IDX, - .spiq_in = VSPIQ_IN_IDX, - .spiwp_in = VSPIWP_IN_IDX, - .spihd_in = VSPIHD_IN_IDX, - .spics_out = {VSPICS0_OUT_IDX, VSPICS1_OUT_IDX, VSPICS2_OUT_IDX}, - .spics_in = VSPICS0_IN_IDX, - .spiclk_native = 18, - .spid_native = 23, - .spiq_native = 19, - .spiwp_native = 22, - .spihd_native = 21, - .spics0_native = 5, - .irq = ETS_SPI3_INTR_SOURCE, - .irq_dma = ETS_SPI3_DMA_INTR_SOURCE, - .module = PERIPH_VSPI_MODULE, - .hw = &SPI3 - } -}; #define DMA_CHANNEL_ENABLED(dma_chan) (BIT(dma_chan-1)) @@ -165,7 +59,7 @@ static portMUX_TYPE spi_dma_spinlock = portMUX_INITIALIZER_UNLOCKED; bool spicommon_periph_claim(spi_host_device_t host) { bool ret = __sync_bool_compare_and_swap(&spi_periph_claimed[host], false, true); - if (ret) periph_module_enable(io_signal[host].module); + if (ret) periph_module_enable(spi_periph_signal[host].module); return ret; } @@ -173,19 +67,19 @@ bool spicommon_periph_claim(spi_host_device_t host) bool spicommon_periph_free(spi_host_device_t host) { bool ret = __sync_bool_compare_and_swap(&spi_periph_claimed[host], true, false); - if (ret) periph_module_disable(io_signal[host].module); + if (ret) periph_module_disable(spi_periph_signal[host].module); return ret; } int spicommon_irqsource_for_host(spi_host_device_t host) { - return io_signal[host].irq; + return spi_periph_signal[host].irq; } spi_dev_t *spicommon_hw_for_host(spi_host_device_t host) { - return io_signal[host].hw; + return spi_periph_signal[host].hw; } bool spicommon_dma_chan_claim (int dma_chan) @@ -228,7 +122,7 @@ 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, int dma_chan, uint32_t flags, uint32_t* flags_o) { - bool native = true; + bool use_iomux = true; uint32_t temp_flag=0; bool quad_pins_exist = true; //the MISO should be output capable in slave mode, or in DIO/QIO mode. @@ -236,24 +130,24 @@ esp_err_t spicommon_bus_initialize_io(spi_host_device_t host, const spi_bus_conf //the MOSI should be output capble in master mode, or in DIO/QIO mode. bool mosi_output = (flags&SPICOMMON_BUSFLAG_MASTER)!=0 || flags&SPICOMMON_BUSFLAG_DUAL; - //check pins existence and if the selected pins correspond to the native pins of the peripheral + //check pins existence and if the selected pins correspond to the iomux pins of the peripheral if (bus_config->sclk_io_num>=0) { temp_flag |= SPICOMMON_BUSFLAG_SCLK; SPI_CHECK(GPIO_IS_VALID_OUTPUT_GPIO(bus_config->sclk_io_num), "sclk not valid", ESP_ERR_INVALID_ARG); - if (bus_config->sclk_io_num != io_signal[host].spiclk_native) native = false; + if (bus_config->sclk_io_num != spi_periph_signal[host].spiclk_iomux_pin) use_iomux = false; } else { SPI_CHECK((flags&SPICOMMON_BUSFLAG_SCLK)==0, "sclk pin required.", ESP_ERR_INVALID_ARG); } if (bus_config->quadwp_io_num>=0) { SPI_CHECK(GPIO_IS_VALID_OUTPUT_GPIO(bus_config->quadwp_io_num), "spiwp not valid", ESP_ERR_INVALID_ARG); - if (bus_config->quadwp_io_num != io_signal[host].spiwp_native) native = false; + if (bus_config->quadwp_io_num != spi_periph_signal[host].spiwp_iomux_pin) use_iomux = false; } else { quad_pins_exist = false; SPI_CHECK((flags&SPICOMMON_BUSFLAG_WPHD)==0, "spiwp pin required.", ESP_ERR_INVALID_ARG); } if (bus_config->quadhd_io_num>=0) { SPI_CHECK(GPIO_IS_VALID_OUTPUT_GPIO(bus_config->quadhd_io_num), "spihd not valid", ESP_ERR_INVALID_ARG); - if (bus_config->quadhd_io_num != io_signal[host].spihd_native) native = false; + if (bus_config->quadhd_io_num != spi_periph_signal[host].spihd_iomux_pin) use_iomux = false; } else { quad_pins_exist = false; SPI_CHECK((flags&SPICOMMON_BUSFLAG_WPHD)==0, "spihd pin required.", ESP_ERR_INVALID_ARG); @@ -265,7 +159,7 @@ esp_err_t spicommon_bus_initialize_io(spi_host_device_t host, const spi_bus_conf } else { SPI_CHECK(GPIO_IS_VALID_GPIO(bus_config->mosi_io_num), "mosi not valid", ESP_ERR_INVALID_ARG); } - if (bus_config->mosi_io_num != io_signal[host].spid_native) native = false; + if (bus_config->mosi_io_num != spi_periph_signal[host].spid_iomux_pin) use_iomux = false; } else { SPI_CHECK((flags&SPICOMMON_BUSFLAG_MOSI)==0, "mosi pin required.", ESP_ERR_INVALID_ARG); } @@ -276,7 +170,7 @@ esp_err_t spicommon_bus_initialize_io(spi_host_device_t host, const spi_bus_conf } else { SPI_CHECK(GPIO_IS_VALID_GPIO(bus_config->miso_io_num), "miso not valid", ESP_ERR_INVALID_ARG); } - if (bus_config->miso_io_num != io_signal[host].spiq_native) native = false; + if (bus_config->miso_io_num != spi_periph_signal[host].spiq_iomux_pin) use_iomux = false; } else { SPI_CHECK((flags&SPICOMMON_BUSFLAG_MISO)==0, "miso pin required.", ESP_ERR_INVALID_ARG); } @@ -287,31 +181,31 @@ esp_err_t spicommon_bus_initialize_io(spi_host_device_t host, const spi_bus_conf } //set flags for QUAD mode according to the existence of wp and hd if (quad_pins_exist) temp_flag |= SPICOMMON_BUSFLAG_WPHD; - //check native pins if required. - SPI_CHECK((flags&SPICOMMON_BUSFLAG_NATIVE_PINS)==0 || native, "not using native pins", ESP_ERR_INVALID_ARG); + //check iomux pins if required. + SPI_CHECK((flags&SPICOMMON_BUSFLAG_NATIVE_PINS)==0 || use_iomux, "not using iomux pins", ESP_ERR_INVALID_ARG); - if (native) { - //All SPI native pin selections resolve to 1, so we put that here instead of trying to figure + if (use_iomux) { + //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 native pins.", host ); + ESP_LOGD(SPI_TAG, "SPI%d use iomux pins.", host ); if (bus_config->mosi_io_num >= 0) { - gpio_iomux_in(bus_config->mosi_io_num, io_signal[host].spid_in); + gpio_iomux_in(bus_config->mosi_io_num, spi_periph_signal[host].spid_in); gpio_iomux_out(bus_config->mosi_io_num, FUNC_SPI, false); } if (bus_config->miso_io_num >= 0) { - gpio_iomux_in(bus_config->miso_io_num, io_signal[host].spiq_in); + gpio_iomux_in(bus_config->miso_io_num, spi_periph_signal[host].spiq_in); gpio_iomux_out(bus_config->miso_io_num, FUNC_SPI, false); } if (bus_config->quadwp_io_num >= 0) { - gpio_iomux_in(bus_config->quadwp_io_num, io_signal[host].spiwp_in); + gpio_iomux_in(bus_config->quadwp_io_num, spi_periph_signal[host].spiwp_in); gpio_iomux_out(bus_config->quadwp_io_num, FUNC_SPI, false); } if (bus_config->quadhd_io_num >= 0) { - gpio_iomux_in(bus_config->quadhd_io_num, io_signal[host].spihd_in); + gpio_iomux_in(bus_config->quadhd_io_num, spi_periph_signal[host].spihd_in); gpio_iomux_out(bus_config->quadhd_io_num, FUNC_SPI, false); } if (bus_config->sclk_io_num >= 0) { - gpio_iomux_in(bus_config->sclk_io_num, io_signal[host].spiclk_in); + gpio_iomux_in(bus_config->sclk_io_num, spi_periph_signal[host].spiclk_in); gpio_iomux_out(bus_config->sclk_io_num, FUNC_SPI, false); } temp_flag |= SPICOMMON_BUSFLAG_NATIVE_PINS; @@ -319,42 +213,42 @@ esp_err_t spicommon_bus_initialize_io(spi_host_device_t host, const spi_bus_conf //Use GPIO matrix ESP_LOGD(SPI_TAG, "SPI%d use gpio matrix.", host ); if (bus_config->mosi_io_num >= 0) { - PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[bus_config->mosi_io_num], FUNC_GPIO); if (mosi_output || (temp_flag&SPICOMMON_BUSFLAG_DUAL)) { gpio_set_direction(bus_config->mosi_io_num, GPIO_MODE_INPUT_OUTPUT); - gpio_matrix_out(bus_config->mosi_io_num, io_signal[host].spid_out, false, false); + gpio_matrix_out(bus_config->mosi_io_num, spi_periph_signal[host].spid_out, false, false); } else { gpio_set_direction(bus_config->mosi_io_num, GPIO_MODE_INPUT); } - gpio_matrix_in(bus_config->mosi_io_num, io_signal[host].spid_in, false); + gpio_matrix_in(bus_config->mosi_io_num, spi_periph_signal[host].spid_in, false); + PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[bus_config->mosi_io_num], FUNC_GPIO); } if (bus_config->miso_io_num >= 0) { - PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[bus_config->miso_io_num], FUNC_GPIO); if (miso_output || (temp_flag&SPICOMMON_BUSFLAG_DUAL)) { gpio_set_direction(bus_config->miso_io_num, GPIO_MODE_INPUT_OUTPUT); - gpio_matrix_out(bus_config->miso_io_num, io_signal[host].spiq_out, false, false); + gpio_matrix_out(bus_config->miso_io_num, spi_periph_signal[host].spiq_out, false, false); } else { gpio_set_direction(bus_config->miso_io_num, GPIO_MODE_INPUT); } - gpio_matrix_in(bus_config->miso_io_num, io_signal[host].spiq_in, false); + gpio_matrix_in(bus_config->miso_io_num, spi_periph_signal[host].spiq_in, false); + PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[bus_config->miso_io_num], FUNC_GPIO); } if (bus_config->quadwp_io_num >= 0) { - PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[bus_config->quadwp_io_num], FUNC_GPIO); gpio_set_direction(bus_config->quadwp_io_num, GPIO_MODE_INPUT_OUTPUT); - gpio_matrix_out(bus_config->quadwp_io_num, io_signal[host].spiwp_out, false, false); - gpio_matrix_in(bus_config->quadwp_io_num, io_signal[host].spiwp_in, false); + gpio_matrix_out(bus_config->quadwp_io_num, spi_periph_signal[host].spiwp_out, false, false); + gpio_matrix_in(bus_config->quadwp_io_num, spi_periph_signal[host].spiwp_in, false); + PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[bus_config->quadwp_io_num], FUNC_GPIO); } if (bus_config->quadhd_io_num >= 0) { - PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[bus_config->quadhd_io_num], FUNC_GPIO); gpio_set_direction(bus_config->quadhd_io_num, GPIO_MODE_INPUT_OUTPUT); - gpio_matrix_out(bus_config->quadhd_io_num, io_signal[host].spihd_out, false, false); - gpio_matrix_in(bus_config->quadhd_io_num, io_signal[host].spihd_in, false); + gpio_matrix_out(bus_config->quadhd_io_num, spi_periph_signal[host].spihd_out, false, false); + gpio_matrix_in(bus_config->quadhd_io_num, spi_periph_signal[host].spihd_in, false); + PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[bus_config->quadhd_io_num], FUNC_GPIO); } if (bus_config->sclk_io_num >= 0) { - PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[bus_config->sclk_io_num], FUNC_GPIO); gpio_set_direction(bus_config->sclk_io_num, GPIO_MODE_INPUT_OUTPUT); - gpio_matrix_out(bus_config->sclk_io_num, io_signal[host].spiclk_out, false, false); - gpio_matrix_in(bus_config->sclk_io_num, io_signal[host].spiclk_in, false); + gpio_matrix_out(bus_config->sclk_io_num, spi_periph_signal[host].spiclk_out, false, false); + gpio_matrix_in(bus_config->sclk_io_num, spi_periph_signal[host].spiclk_in, false); + PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[bus_config->sclk_io_num], FUNC_GPIO); } } @@ -378,39 +272,61 @@ static void reset_func_to_gpio(int func) esp_err_t spicommon_bus_free_io(spi_host_device_t host) { - if (REG_GET_FIELD(GPIO_PIN_MUX_REG[io_signal[host].spid_native], MCU_SEL) == 1) PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[io_signal[host].spid_native], PIN_FUNC_GPIO); - if (REG_GET_FIELD(GPIO_PIN_MUX_REG[io_signal[host].spiq_native], MCU_SEL) == 1) PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[io_signal[host].spiq_native], PIN_FUNC_GPIO); - if (REG_GET_FIELD(GPIO_PIN_MUX_REG[io_signal[host].spiclk_native], MCU_SEL) == 1) PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[io_signal[host].spiclk_native], PIN_FUNC_GPIO); - if (REG_GET_FIELD(GPIO_PIN_MUX_REG[io_signal[host].spiwp_native], MCU_SEL) == 1) PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[io_signal[host].spiwp_native], PIN_FUNC_GPIO); - if (REG_GET_FIELD(GPIO_PIN_MUX_REG[io_signal[host].spihd_native], MCU_SEL) == 1) PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[io_signal[host].spihd_native], PIN_FUNC_GPIO); - reset_func_to_gpio(io_signal[host].spid_out); - reset_func_to_gpio(io_signal[host].spiq_out); - reset_func_to_gpio(io_signal[host].spiclk_out); - reset_func_to_gpio(io_signal[host].spiwp_out); - reset_func_to_gpio(io_signal[host].spihd_out); + if (REG_GET_FIELD(GPIO_PIN_MUX_REG[spi_periph_signal[host].spid_iomux_pin], MCU_SEL) == 1) PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[spi_periph_signal[host].spid_iomux_pin], PIN_FUNC_GPIO); + if (REG_GET_FIELD(GPIO_PIN_MUX_REG[spi_periph_signal[host].spiq_iomux_pin], MCU_SEL) == 1) PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[spi_periph_signal[host].spiq_iomux_pin], PIN_FUNC_GPIO); + if (REG_GET_FIELD(GPIO_PIN_MUX_REG[spi_periph_signal[host].spiclk_iomux_pin], MCU_SEL) == 1) PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[spi_periph_signal[host].spiclk_iomux_pin], PIN_FUNC_GPIO); + if (REG_GET_FIELD(GPIO_PIN_MUX_REG[spi_periph_signal[host].spiwp_iomux_pin], MCU_SEL) == 1) PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[spi_periph_signal[host].spiwp_iomux_pin], PIN_FUNC_GPIO); + if (REG_GET_FIELD(GPIO_PIN_MUX_REG[spi_periph_signal[host].spihd_iomux_pin], MCU_SEL) == 1) PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[spi_periph_signal[host].spihd_iomux_pin], PIN_FUNC_GPIO); + reset_func_to_gpio(spi_periph_signal[host].spid_out); + reset_func_to_gpio(spi_periph_signal[host].spiq_out); + reset_func_to_gpio(spi_periph_signal[host].spiclk_out); + reset_func_to_gpio(spi_periph_signal[host].spiwp_out); + reset_func_to_gpio(spi_periph_signal[host].spihd_out); + return ESP_OK; +} + +esp_err_t spicommon_bus_free_io_cfg(const spi_bus_config_t *bus_cfg) +{ + int pin_array[] = { + bus_cfg->mosi_io_num, + bus_cfg->miso_io_num, + bus_cfg->sclk_io_num, + bus_cfg->quadwp_io_num, + bus_cfg->quadhd_io_num, + }; + for (int i = 0; i < sizeof(pin_array)/sizeof(int); i ++) { + const int io = pin_array[i]; + if (io >= 0 && GPIO_IS_VALID_GPIO(io)) gpio_reset_pin(io); + } return ESP_OK; } void spicommon_cs_initialize(spi_host_device_t host, int cs_io_num, int cs_num, int force_gpio_matrix) { - if (!force_gpio_matrix && cs_io_num == io_signal[host].spics0_native && cs_num == 0) { + if (!force_gpio_matrix && cs_io_num == spi_periph_signal[host].spics0_iomux_pin && cs_num == 0) { //The cs0s for all SPI peripherals map to pin mux source 1, so we use that instead of a define. - gpio_iomux_in(cs_io_num, io_signal[host].spics_in); + gpio_iomux_in(cs_io_num, spi_periph_signal[host].spics_in); gpio_iomux_out(cs_io_num, FUNC_SPI, false); } else { //Use GPIO matrix + gpio_matrix_out(cs_io_num, spi_periph_signal[host].spics_out[cs_num], false, false); + if (cs_num == 0) gpio_matrix_in(cs_io_num, spi_periph_signal[host].spics_in, false); PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[cs_io_num], FUNC_GPIO); - gpio_matrix_out(cs_io_num, io_signal[host].spics_out[cs_num], false, false); - if (cs_num == 0) gpio_matrix_in(cs_io_num, io_signal[host].spics_in, false); } } void spicommon_cs_free(spi_host_device_t host, int cs_io_num) { - if (cs_io_num == 0 && REG_GET_FIELD(GPIO_PIN_MUX_REG[io_signal[host].spics0_native], MCU_SEL) == 1) { - PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[io_signal[host].spics0_native], PIN_FUNC_GPIO); + if (cs_io_num == 0 && REG_GET_FIELD(GPIO_PIN_MUX_REG[spi_periph_signal[host].spics0_iomux_pin], MCU_SEL) == 1) { + PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[spi_periph_signal[host].spics0_iomux_pin], PIN_FUNC_GPIO); } - reset_func_to_gpio(io_signal[host].spics_out[cs_io_num]); + reset_func_to_gpio(spi_periph_signal[host].spics_out[cs_io_num]); +} + +void spicommon_cs_free_io(int cs_gpio_num) +{ + assert(cs_gpio_num>=0 && GPIO_IS_VALID_GPIO(cs_gpio_num)); + gpio_reset_pin(cs_gpio_num); } //Set up a list of dma descriptors. dmadesc is an array of descriptors. Data is the buffer to point to. diff --git a/components/driver/spi_master.c b/components/driver/spi_master.c index 4e6a51a5e5..4641e4bca0 100644 --- a/components/driver/spi_master.c +++ b/components/driver/spi_master.c @@ -1,4 +1,4 @@ -// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// 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. @@ -21,13 +21,13 @@ is a combination of SPI port and CS pin, plus some information about the specifi The essence of the interface to a device is a set of queues; one per device. The idea is that to send something to a SPI device, you allocate a transaction descriptor. It contains some information about the transfer like the lenghth, address, -command etc, plus pointers to transmit and receive buffer. The address of this block gets pushed into the transmit queue. -The SPI driver does its magic, and sends and retrieves the data eventually. The data gets written to the receive buffers, +command etc, plus pointers to transmit and receive buffer. The address of this block gets pushed into the transmit queue. +The SPI driver does its magic, and sends and retrieves the data eventually. The data gets written to the receive buffers, if needed the transaction descriptor is modified to indicate returned parameters and the entire thing goes into the return queue, where whatever software initiated the transaction can retrieve it. -The entire thing is run from the SPI interrupt handler. If SPI is done transmitting/receiving but nothing is in the queue, -it will not clear the SPI interrupt but just disable it. This way, when a new thing is sent, pushing the packet into the send +The entire thing is run from the SPI interrupt handler. If SPI is done transmitting/receiving but nothing is in the queue, +it will not clear the SPI interrupt but just disable it. This way, when a new thing is sent, pushing the packet into the send queue and re-enabling the interrupt will trigger the interrupt again, which can then take care of the sending. */ @@ -36,10 +36,8 @@ queue and re-enabling the interrupt will trigger the interrupt again, which can #include #include "driver/spi_common.h" #include "driver/spi_master.h" -#include "soc/gpio_sig_map.h" -#include "soc/spi_reg.h" #include "soc/dport_reg.h" -#include "soc/spi_struct.h" +#include "soc/spi_periph.h" #include "rom/ets_sys.h" #include "esp_types.h" #include "esp_attr.h" @@ -66,10 +64,22 @@ typedef typeof(SPI1.clock) spi_clock_reg_t; #define NO_CS 3 //Number of CS pins per SPI host +#ifdef CONFIG_SPI_MASTER_ISR_IN_IRAM +#define SPI_MASTER_ISR_ATTR IRAM_ATTR +#else +#define SPI_MASTER_ISR_ATTR +#endif + +#ifdef CONFIG_SPI_MASTER_IN_IRAM +#define SPI_MASTER_ATTR IRAM_ATTR +#else +#define SPI_MASTER_ATTR +#endif + /// struct to hold private transaction data (like tx and rx buffer for DMA). -typedef struct { - spi_transaction_t *trans; +typedef struct { + spi_transaction_t *trans; uint32_t *buffer_to_send; //equals to tx_data, if SPI_TRANS_USE_RXDATA is applied; otherwise if original buffer wasn't in DMA-capable memory, this gets the address of a temporary buffer that is; //otherwise sets to the original buffer or NULL if no buffer is assigned. uint32_t *buffer_to_rcv; // similar to buffer_to_send @@ -87,6 +97,7 @@ typedef struct { uint32_t flags; int dma_chan; int max_transfer_sz; + spi_bus_config_t bus_cfg; #ifdef CONFIG_PM_ENABLE esp_pm_lock_handle_t pm_lock; #endif @@ -96,6 +107,7 @@ typedef struct { spi_clock_reg_t reg; int eff_clk; int dummy_num; + int miso_delay; } clock_config_t; struct spi_device_t { @@ -110,9 +122,9 @@ static spi_host_t *spihost[3]; static const char *SPI_TAG = "spi_master"; -#define SPI_CHECK(a, str, ret_val) \ +#define SPI_CHECK(a, str, ret_val, ...) \ if (!(a)) { \ - ESP_LOGE(SPI_TAG,"%s(%d): %s", __FUNCTION__, __LINE__, str); \ + ESP_LOGE(SPI_TAG,"%s(%d): "str, __FUNCTION__, __LINE__, ##__VA_ARGS__); \ return (ret_val); \ } @@ -147,6 +159,7 @@ esp_err_t spi_bus_initialize(spi_host_device_t host, const spi_bus_config_t *bus goto cleanup; } memset(spihost[host], 0, sizeof(spi_host_t)); + memcpy( &spihost[host]->bus_cfg, bus_config, sizeof(spi_bus_config_t)); #ifdef CONFIG_PM_ENABLE err = esp_pm_lock_create(ESP_PM_APB_FREQ_MAX, 0, "spi_master", &spihost[host]->pm_lock); @@ -177,8 +190,12 @@ esp_err_t spi_bus_initialize(spi_host_device_t host, const spi_bus_config_t *bus goto cleanup; } } - - err = esp_intr_alloc(spicommon_irqsource_for_host(host), ESP_INTR_FLAG_INTRDISABLED, spi_intr, (void*)spihost[host], &spihost[host]->intr); + + int flags = ESP_INTR_FLAG_INTRDISABLED; +#ifdef CONFIG_SPI_MASTER_ISR_IN_IRAM + flags |= ESP_INTR_FLAG_IRAM; +#endif + err = esp_intr_alloc(spicommon_irqsource_for_host(host), flags, spi_intr, (void*)spihost[host], &spihost[host]->intr); if (err != ESP_OK) { ret = err; goto cleanup; @@ -207,7 +224,7 @@ esp_err_t spi_bus_initialize(spi_host_device_t host, const spi_bus_config_t *bus spihost[host]->hw->slave.wr_sta_inten=0; //Force a transaction done interrupt. This interrupt won't fire yet because we initialized the SPI interrupt as - //disabled. This way, we can just enable the SPI interrupt and the interrupt handler will kick in, handling + //disabled. This way, we can just enable the SPI interrupt and the interrupt handler will kick in, handling //any transactions that are queued. spihost[host]->hw->slave.trans_inten=1; spihost[host]->hw->slave.trans_done=1; @@ -238,6 +255,7 @@ esp_err_t spi_bus_free(spi_host_device_t host) for (x=0; xdevice[x]==NULL, "not all CSses freed", ESP_ERR_INVALID_STATE); } + spicommon_bus_free_io_cfg(&spihost[host]->bus_cfg); if ( spihost[host]->dma_chan > 0 ) { spicommon_dma_chan_free ( spihost[host]->dma_chan ); @@ -256,14 +274,38 @@ esp_err_t spi_bus_free(spi_host_device_t host) return ESP_OK; } -static inline uint32_t spi_dummy_limit(bool gpio_is_used) +void spi_get_timing(bool gpio_is_used, int input_delay_ns, int eff_clk, int* dummy_o, int* cycles_remain_o) { - const int apbclk=APB_CLK_FREQ; - if (!gpio_is_used) { - return apbclk; //dummy bit workaround is not used when native pins are used + const int apbclk_kHz = APB_CLK_FREQ/1000; + const int apbclk_n = APB_CLK_FREQ/eff_clk; + const int gpio_delay_ns=(gpio_is_used?25:0); + + //calculate how many apb clocks a period has, the 1 is to compensate in case ``input_delay_ns`` is rounded off. + int apb_period_n = (1 + input_delay_ns + gpio_delay_ns)*apbclk_kHz/1000/1000; + int dummy_required = apb_period_n/apbclk_n; + + int miso_delay = 0; + if (dummy_required > 0) { + //due to the clock delay between master and slave, there's a range in which data is random + //give MISO a delay if needed to make sure we sample at the time MISO is stable + miso_delay = (dummy_required+1)*apbclk_n-apb_period_n-1; } else { - return apbclk/2; //the dummy bit workaround is used when freq is 40MHz and GPIO matrix is used. + //if the dummy is not required, maybe we should also delay half a SPI clock if the data comes too early + if (apb_period_n*4 <= apbclk_n) miso_delay = -1; } + if (dummy_o!=NULL) *dummy_o = dummy_required; + if (cycles_remain_o!=NULL) *cycles_remain_o = miso_delay; + ESP_LOGD(SPI_TAG,"eff: %d, limit: %dk(/%d), %d dummy, %d delay", eff_clk/1000, apbclk_kHz/(apb_period_n+1), apb_period_n, dummy_required, miso_delay); +} + +int spi_get_freq_limit(bool gpio_is_used, int input_delay_ns) +{ + const int apbclk_kHz = APB_CLK_FREQ/1000; + const int gpio_delay_ns=(gpio_is_used?25:0); + + //calculate how many apb clocks a period has, the 1 is to compensate in case ``input_delay_ns`` is rounded off. + int apb_period_n = (1 + input_delay_ns + gpio_delay_ns)*apbclk_kHz/1000/1000; + return APB_CLK_FREQ/(apb_period_n+1); } /* @@ -276,6 +318,9 @@ esp_err_t spi_bus_add_device(spi_host_device_t host, const spi_device_interface_ int apbclk=APB_CLK_FREQ; int eff_clk; int duty_cycle; + int dummy_required; + int miso_delay; + spi_clock_reg_t clk_reg; SPI_CHECK(host>=SPI_HOST && host<=VSPI_HOST, "invalid host", ESP_ERR_INVALID_ARG); SPI_CHECK(spihost[host]!=NULL, "host not initialized", ESP_ERR_INVALID_STATE); @@ -288,18 +333,23 @@ esp_err_t spi_bus_add_device(spi_host_device_t host, const spi_device_interface_ SPI_CHECK(freecs!=NO_CS, "no free cs pins for host", ESP_ERR_NOT_FOUND); //The hardware looks like it would support this, but actually setting cs_ena_pretrans when transferring in full //duplex mode does absolutely nothing on the ESP32. - SPI_CHECK(dev_config->cs_ena_pretrans==0 || (dev_config->flags & SPI_DEVICE_HALFDUPLEX), "cs pretrans delay incompatible with full-duplex", ESP_ERR_INVALID_ARG); - - //Speeds >=40MHz over GPIO matrix needs a dummy cycle, but these don't work for full-duplex connections. + SPI_CHECK(dev_config->cs_ena_pretrans <= 1 || (dev_config->flags & SPI_DEVICE_HALFDUPLEX), "cs pretrans delay > 1 incompatible with full-duplex", ESP_ERR_INVALID_ARG); + SPI_CHECK( dev_config->cs_ena_pretrans != 1 || (dev_config->address_bits == 0 && dev_config->command_bits == 0) || + (dev_config->flags & SPI_DEVICE_HALFDUPLEX), "In full-duplex mode, only support cs pretrans delay = 1 and without address_bits and command_bits", ESP_ERR_INVALID_ARG); + duty_cycle = (dev_config->duty_cycle_pos==0? 128: dev_config->duty_cycle_pos); - eff_clk = spi_cal_clock(apbclk, dev_config->clock_speed_hz, duty_cycle, (uint32_t*)&clk_reg); - uint32_t dummy_limit = spi_dummy_limit(!(spihost[host]->flags&SPICOMMON_BUSFLAG_NATIVE_PINS)); - SPI_CHECK( dev_config->flags & SPI_DEVICE_HALFDUPLEX || (eff_clk/1000/1000) < (dummy_limit/1000/1000) || + eff_clk = spi_cal_clock(apbclk, dev_config->clock_speed_hz, duty_cycle, (uint32_t*)&clk_reg); + int freq_limit = spi_get_freq_limit(!(spihost[host]->flags&SPICOMMON_BUSFLAG_NATIVE_PINS), dev_config->input_delay_ns); + //GPIO matrix can only change data at 80Mhz rate, which only allows 40MHz SPI clock. + SPI_CHECK(eff_clk <= 40*1000*1000 || spihost[host]->flags&SPICOMMON_BUSFLAG_NATIVE_PINS, "80MHz only supported on iomux pins", ESP_ERR_INVALID_ARG); + //Speed >=40MHz over GPIO matrix needs a dummy cycle, but these don't work for full-duplex connections. + spi_get_timing(!(spihost[host]->flags&SPICOMMON_BUSFLAG_NATIVE_PINS), dev_config->input_delay_ns, eff_clk, &dummy_required, &miso_delay); + SPI_CHECK( dev_config->flags & SPI_DEVICE_HALFDUPLEX || dummy_required == 0 || dev_config->flags & SPI_DEVICE_NO_DUMMY, -"When GPIO matrix is used in full-duplex mode at frequency > 26MHz, device cannot read correct data.\n\ +"When GPIO matrix is used in full-duplex mode at frequency > %.1fMHz, device cannot read correct data.\n\ Please note the SPI can only work at divisors of 80MHz, and the driver always tries to find the closest frequency to your configuration.\n\ -Specify ``SPI_DEVICE_NO_DUMMY`` to ignore this checking. Then you can output data at higher speed, or read data at your own risk.", - ESP_ERR_INVALID_ARG ); +Specify ``SPI_DEVICE_NO_DUMMY`` to ignore this checking. Then you can output data at higher speed, or read data at your own risk.", + ESP_ERR_INVALID_ARG, freq_limit/1000./1000 ); //Allocate memory for device spi_device_t *dev=malloc(sizeof(spi_device_t)); @@ -310,17 +360,18 @@ Specify ``SPI_DEVICE_NO_DUMMY`` to ignore this checking. Then you can output dat //Allocate queues, set defaults dev->trans_queue=xQueueCreate(dev_config->queue_size, sizeof(spi_trans_priv)); dev->ret_queue=xQueueCreate(dev_config->queue_size, sizeof(spi_trans_priv)); - if (!dev->trans_queue || !dev->ret_queue) goto nomem; + if (!dev->trans_queue || !dev->ret_queue) goto nomem; dev->host=spihost[host]; //We want to save a copy of the dev config in the dev struct. memcpy(&dev->cfg, dev_config, sizeof(spi_device_interface_config_t)); dev->cfg.duty_cycle_pos = duty_cycle; - // TODO: if we have to change the apb clock among transactions, re-calculate this each time the apb clock lock is acquired. + // TODO: if we have to change the apb clock among transactions, re-calculate this each time the apb clock lock is acquired. dev->clk_cfg= (clock_config_t) { .eff_clk = eff_clk, - .dummy_num = (dev->clk_cfg.eff_clk >= dummy_limit? 1: 0), + .dummy_num = dummy_required, .reg = clk_reg, + .miso_delay = miso_delay, }; //Set CS pin, CS options @@ -338,6 +389,8 @@ Specify ``SPI_DEVICE_NO_DUMMY`` to ignore this checking. Then you can output dat } else { spihost[host]->hw->pin.master_cs_pol &= (1<hw->ctrl2.mosi_delay_mode = 0; + spihost[host]->hw->ctrl2.mosi_delay_num = 0; *handle=dev; ESP_LOGD(SPI_TAG, "SPI%d: New device added to CS%d, effective clock: %dkHz", host, freecs, dev->clk_cfg.eff_clk/1000); return ESP_OK; @@ -361,6 +414,10 @@ esp_err_t spi_bus_remove_device(spi_device_handle_t handle) SPI_CHECK(handle->host->cur_cs == NO_CS || handle->host->device[handle->host->cur_cs]!=handle, "Have unfinished transactions", ESP_ERR_INVALID_STATE); SPI_CHECK(uxQueueMessagesWaiting(handle->ret_queue)==0, "Have unfinished transactions", ESP_ERR_INVALID_STATE); + //return + int spics_io_num = handle->cfg.spics_io_num; + if (spics_io_num >= 0) spicommon_cs_free_io(spics_io_num); + //Kill queues vQueueDelete(handle->trans_queue); vQueueDelete(handle->ret_queue); @@ -445,7 +502,7 @@ static inline void spi_set_clock(spi_dev_t *hw, spi_clock_reg_t reg) { //This is run in interrupt context and apart from initialization and destruction, this is the only code //touching the host (=spihost[x]) variable. The rest of the data arrives in queues. That is why there are //no muxes in this code. -static void IRAM_ATTR spi_intr(void *arg) +static void SPI_MASTER_ISR_ATTR spi_intr(void *arg) { int i; BaseType_t r; @@ -460,7 +517,7 @@ static void IRAM_ATTR spi_intr(void *arg) /*------------ deal with the in-flight transaction -----------------*/ if (host->cur_cs != NO_CS) { spi_transaction_t *cur_trans = host->cur_trans_buf.trans; - //Okay, transaction is done. + //Okay, transaction is done. if (host->cur_trans_buf.buffer_to_rcv && host->dma_chan == 0 ) { //Need to copy from SPI regs to result buffer. for (int x=0; x < cur_trans->rxlength; x+=32) { @@ -474,7 +531,7 @@ static void IRAM_ATTR spi_intr(void *arg) //Call post-transaction callback, if any if (host->device[host->cur_cs]->cfg.post_cb) host->device[host->cur_cs]->cfg.post_cb(cur_trans); //Return transaction descriptor. - xQueueSendFromISR(host->device[host->cur_cs]->ret_queue, &host->cur_trans_buf, &do_yield); + xQueueSendFromISR(host->device[host->cur_cs]->ret_queue, &host->cur_trans_buf, &do_yield); host->cur_cs = NO_CS; } //Tell common code DMA workaround that our DMA channel is idle. If needed, the code will do a DMA reset. @@ -505,46 +562,27 @@ static void IRAM_ATTR spi_intr(void *arg) host->cur_cs=i; //We should be done with the transmission. assert(host->hw->cmd.usr == 0); - + //Reconfigure according to device settings, but only if we change CSses. if (i!=host->prev_cs) { - const int apbclk=APB_CLK_FREQ; - int effclk=dev->clk_cfg.eff_clk; spi_set_clock(host->hw, dev->clk_cfg.reg); //Configure bit order host->hw->ctrl.rd_bit_order=(dev->cfg.flags & SPI_DEVICE_RXBIT_LSBFIRST)?1:0; host->hw->ctrl.wr_bit_order=(dev->cfg.flags & SPI_DEVICE_TXBIT_LSBFIRST)?1:0; - - //Configure polarity - //SPI iface needs to be configured for a delay in some cases. - int nodelay=0; - if ((host->flags&SPICOMMON_BUSFLAG_NATIVE_PINS)!=0) { - if (effclk >= apbclk/2) { - nodelay=1; - } - } else { - uint32_t delay_limit = apbclk/4; - if (effclk >= delay_limit) { - nodelay=1; - } - } + //Configure polarity if (dev->cfg.mode==0) { host->hw->pin.ck_idle_edge=0; host->hw->user.ck_out_edge=0; - host->hw->ctrl2.miso_delay_mode=nodelay?0:2; } else if (dev->cfg.mode==1) { host->hw->pin.ck_idle_edge=0; host->hw->user.ck_out_edge=1; - host->hw->ctrl2.miso_delay_mode=nodelay?0:1; } else if (dev->cfg.mode==2) { host->hw->pin.ck_idle_edge=1; host->hw->user.ck_out_edge=1; - host->hw->ctrl2.miso_delay_mode=nodelay?0:1; } else if (dev->cfg.mode==3) { host->hw->pin.ck_idle_edge=1; host->hw->user.ck_out_edge=0; - host->hw->ctrl2.miso_delay_mode=nodelay?0:2; } //Configure misc stuff host->hw->user.doutdin=(dev->cfg.flags & SPI_DEVICE_HALFDUPLEX)?0:1; @@ -552,8 +590,11 @@ static void IRAM_ATTR spi_intr(void *arg) host->hw->ctrl2.setup_time=dev->cfg.cs_ena_pretrans-1; host->hw->user.cs_setup=dev->cfg.cs_ena_pretrans?1:0; - host->hw->ctrl2.hold_time=dev->cfg.cs_ena_posttrans-1; - host->hw->user.cs_hold=(dev->cfg.cs_ena_posttrans)?1:0; + //set hold_time to 0 will not actually append delay to CS + //set it to 1 since we do need at least one clock of hold time in most cases + host->hw->ctrl2.hold_time=dev->cfg.cs_ena_posttrans; + if ( host->hw->ctrl2.hold_time == 0 ) host->hw->ctrl2.hold_time = 1; + host->hw->user.cs_hold=1; //Configure CS pin host->hw->pin.cs0_dis=(i==0)?0:1; @@ -607,13 +648,14 @@ static void IRAM_ATTR spi_intr(void *arg) extra_dummy=dev->clk_cfg.dummy_num; } } else { - //DMA temporary workaround: let RX DMA work somehow to avoid the issue in ESP32 v0/v1 silicon + //DMA temporary workaround: let RX DMA work somehow to avoid the issue in ESP32 v0/v1 silicon if (host->dma_chan != 0 ) { host->hw->dma_in_link.addr=0; host->hw->dma_in_link.start=1; } } + if (trans_buf->buffer_to_send) { if (host->dma_chan == 0) { //Need to copy data to registers manually @@ -634,10 +676,31 @@ static void IRAM_ATTR spi_intr(void *arg) } } + //SPI iface needs to be configured for a delay in some cases. //configure dummy bits host->hw->user.usr_dummy=(dev->cfg.dummy_bits+extra_dummy)?1:0; host->hw->user1.usr_dummy_cyclelen=dev->cfg.dummy_bits+extra_dummy-1; + int miso_long_delay = 0; + if (dev->clk_cfg.miso_delay<0) { + //if the data comes too late, delay half a SPI clock to improve reading + miso_long_delay = 1; + host->hw->ctrl2.miso_delay_num = 0; + } else { + //if the data is so fast that dummy_bit is used, delay some apb clocks to meet the timing + host->hw->ctrl2.miso_delay_num = (extra_dummy? dev->clk_cfg.miso_delay: 0); + } + + if (dev->cfg.mode==0) { + host->hw->ctrl2.miso_delay_mode=miso_long_delay?2:0; + } else if (dev->cfg.mode==1) { + host->hw->ctrl2.miso_delay_mode=miso_long_delay?1:0; + } else if (dev->cfg.mode==2) { + host->hw->ctrl2.miso_delay_mode=miso_long_delay?1:0; + } else if (dev->cfg.mode==3) { + host->hw->ctrl2.miso_delay_mode=miso_long_delay?2:0; + } + host->hw->mosi_dlen.usr_mosi_dbitlen=trans->length-1; if ( dev->cfg.flags & SPI_DEVICE_HALFDUPLEX ) { host->hw->miso_dlen.usr_miso_dbitlen=trans->rxlength-1; @@ -667,8 +730,8 @@ static void IRAM_ATTR spi_intr(void *arg) // output command will be sent from bit 7 to 0 of command_value, and then bit 15 to 8 of the same register field. uint16_t command = trans->cmd << (16-cmdlen); //shift to MSB host->hw->user2.usr_command_value = (command>>8)|(command<<8); //swap the first and second byte - // shift the address to MSB of addr (and maybe slv_wr_status) register. - // output address will be sent from MSB to LSB of addr register, then comes the MSB to LSB of slv_wr_status register. + // shift the address to MSB of addr (and maybe slv_wr_status) register. + // output address will be sent from MSB to LSB of addr register, then comes the MSB to LSB of slv_wr_status register. if (addrlen>32) { host->hw->addr = trans->addr >> (addrlen- 32); host->hw->slv_wr_status = trans->addr << (64 - addrlen); @@ -688,18 +751,18 @@ static void IRAM_ATTR spi_intr(void *arg) } -esp_err_t spi_device_queue_trans(spi_device_handle_t handle, spi_transaction_t *trans_desc, TickType_t ticks_to_wait) +esp_err_t SPI_MASTER_ATTR spi_device_queue_trans(spi_device_handle_t handle, spi_transaction_t *trans_desc, TickType_t ticks_to_wait) { esp_err_t ret = ESP_OK; BaseType_t r; SPI_CHECK(handle!=NULL, "invalid dev handle", ESP_ERR_INVALID_ARG); - //check transmission length + //check transmission length SPI_CHECK((trans_desc->flags & SPI_TRANS_USE_RXDATA)==0 ||trans_desc->rxlength <= 32, "rxdata transfer > 32 bits without configured DMA", ESP_ERR_INVALID_ARG); SPI_CHECK((trans_desc->flags & SPI_TRANS_USE_TXDATA)==0 ||trans_desc->length <= 32, "txdata transfer > 32 bits without configured DMA", ESP_ERR_INVALID_ARG); SPI_CHECK(trans_desc->length <= handle->host->max_transfer_sz*8, "txdata transfer > host maximum", ESP_ERR_INVALID_ARG); SPI_CHECK(trans_desc->rxlength <= handle->host->max_transfer_sz*8, "rxdata transfer > host maximum", ESP_ERR_INVALID_ARG); SPI_CHECK((handle->cfg.flags & SPI_DEVICE_HALFDUPLEX) || trans_desc->rxlength <= trans_desc->length, "rx length > tx length in full duplex mode", ESP_ERR_INVALID_ARG); - //check working mode + //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)) && (!(handle->cfg.flags & SPI_DEVICE_HALFDUPLEX))), "incompatible iface params", ESP_ERR_INVALID_ARG); SPI_CHECK( !(handle->cfg.flags & SPI_DEVICE_HALFDUPLEX) || handle->host->dma_chan == 0 || !(trans_desc->flags & SPI_TRANS_USE_RXDATA || trans_desc->rx_buffer != NULL) @@ -717,7 +780,7 @@ esp_err_t spi_device_queue_trans(spi_device_handle_t handle, spi_transaction_t * // rx memory assign if ( trans_desc->flags & SPI_TRANS_USE_RXDATA ) { trans_buf.buffer_to_rcv = (uint32_t*)&trans_desc->rx_data[0]; - } else { + } else { //if not use RXDATA neither rx_buffer, buffer_to_rcv assigned to NULL trans_buf.buffer_to_rcv = trans_desc->rx_buffer; } @@ -730,12 +793,12 @@ esp_err_t spi_device_queue_trans(spi_device_handle_t handle, spi_transaction_t * goto clean_up; } } - + const uint32_t *txdata; // tx memory assign if ( trans_desc->flags & SPI_TRANS_USE_TXDATA ) { txdata = (uint32_t*)&trans_desc->tx_data[0]; - } else { + } else { //if not use TXDATA neither tx_buffer, tx data assigned to NULL txdata = trans_desc->tx_buffer ; } @@ -748,11 +811,11 @@ esp_err_t spi_device_queue_trans(spi_device_handle_t handle, spi_transaction_t * goto clean_up; } memcpy( trans_buf.buffer_to_send, txdata, (trans_desc->length+7)/8 ); - } else { + } else { // else use the original buffer (forced-conversion) or assign to NULL trans_buf.buffer_to_send = (uint32_t*)txdata; } - + #ifdef CONFIG_PM_ENABLE esp_pm_lock_acquire(handle->host->pm_lock); #endif @@ -772,24 +835,24 @@ clean_up: // free malloc-ed buffer (if needed) before return. if ( (void*)trans_buf.buffer_to_rcv != trans_desc->rx_buffer && (void*)trans_buf.buffer_to_rcv != &trans_desc->rx_data[0] ) { free( trans_buf.buffer_to_rcv ); - } + } if ( (void*)trans_buf.buffer_to_send!= trans_desc->tx_buffer && (void*)trans_buf.buffer_to_send != &trans_desc->tx_data[0] ) { free( trans_buf.buffer_to_send ); - } + } assert( ret != ESP_OK ); return ret; } -esp_err_t spi_device_get_trans_result(spi_device_handle_t handle, spi_transaction_t **trans_desc, TickType_t ticks_to_wait) +esp_err_t SPI_MASTER_ATTR spi_device_get_trans_result(spi_device_handle_t handle, spi_transaction_t **trans_desc, TickType_t ticks_to_wait) { BaseType_t r; spi_trans_priv trans_buf; - + SPI_CHECK(handle!=NULL, "invalid dev handle", ESP_ERR_INVALID_ARG); r=xQueueReceive(handle->ret_queue, (void*)&trans_buf, ticks_to_wait); if (!r) { // The memory occupied by rx and tx DMA buffer destroyed only when receiving from the queue (transaction finished). - // If timeout, wait and retry. + // If timeout, wait and retry. // Every on-flight transaction request occupies internal memory as DMA buffer if needed. return ESP_ERR_TIMEOUT; } @@ -798,12 +861,12 @@ esp_err_t spi_device_get_trans_result(spi_device_handle_t handle, spi_transactio if ( (void*)trans_buf.buffer_to_send != &(*trans_desc)->tx_data[0] && trans_buf.buffer_to_send != (*trans_desc)->tx_buffer ) { free( trans_buf.buffer_to_send ); - } + } //copy data from temporary DMA-capable buffer back to IRAM buffer and free the temporary one. if ( (void*)trans_buf.buffer_to_rcv != &(*trans_desc)->rx_data[0] && trans_buf.buffer_to_rcv != (*trans_desc)->rx_buffer ) { if ( (*trans_desc)->flags & SPI_TRANS_USE_RXDATA ) { - memcpy( (uint8_t*)&(*trans_desc)->rx_data[0], trans_buf.buffer_to_rcv, ((*trans_desc)->rxlength+7)/8 ); + memcpy( (uint8_t*)&(*trans_desc)->rx_data[0], trans_buf.buffer_to_rcv, ((*trans_desc)->rxlength+7)/8 ); } else { memcpy( (*trans_desc)->rx_buffer, trans_buf.buffer_to_rcv, ((*trans_desc)->rxlength+7)/8 ); } @@ -814,7 +877,7 @@ esp_err_t spi_device_get_trans_result(spi_device_handle_t handle, spi_transactio } //Porcelain to do one blocking transmission. -esp_err_t spi_device_transmit(spi_device_handle_t handle, spi_transaction_t *trans_desc) +esp_err_t SPI_MASTER_ATTR spi_device_transmit(spi_device_handle_t handle, spi_transaction_t *trans_desc) { esp_err_t ret; spi_transaction_t *ret_trans; diff --git a/components/driver/spi_slave.c b/components/driver/spi_slave.c index 7ee2222e20..7ff89e6c8a 100644 --- a/components/driver/spi_slave.c +++ b/components/driver/spi_slave.c @@ -1,4 +1,4 @@ -// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// 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. @@ -15,10 +15,8 @@ #include #include "driver/spi_common.h" #include "driver/spi_slave.h" -#include "soc/gpio_sig_map.h" -#include "soc/spi_reg.h" #include "soc/dport_reg.h" -#include "soc/spi_struct.h" +#include "soc/spi_periph.h" #include "rom/ets_sys.h" #include "esp_types.h" #include "esp_attr.h" diff --git a/components/driver/test/test_adc2.c b/components/driver/test/test_adc2.c index 815f5c79a9..ec6e2ff4f6 100644 --- a/components/driver/test/test_adc2.c +++ b/components/driver/test/test_adc2.c @@ -56,8 +56,8 @@ TEST_CASE("adc2 work with wifi","[adc]") //init wifi printf("nvs init\n"); esp_err_t r = nvs_flash_init(); - if (r == ESP_ERR_NVS_NO_FREE_PAGES) { - printf("no free pages, erase..\n"); + if (r == ESP_ERR_NVS_NO_FREE_PAGES || r == ESP_ERR_NVS_NEW_VERSION_FOUND) { + printf("no free pages or nvs version mismatch, erase..\n"); TEST_ESP_OK(nvs_flash_erase()); r = nvs_flash_init(); } diff --git a/components/driver/test/test_gpio.c b/components/driver/test/test_gpio.c new file mode 100644 index 0000000000..20962e36f8 --- /dev/null +++ b/components/driver/test/test_gpio.c @@ -0,0 +1,593 @@ +/** + * About test environment UT_T1_GPIO: + * Please connect GPIO18 and GPIO19 + */ +#include +#include +#include "rom/uart.h" +#include "esp_system.h" +#include "esp_sleep.h" +#include "unity.h" +#include "driver/gpio.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/queue.h" + +#define WAKE_UP_IGNORE 1 // gpio_wakeup function development is not completed yet, set it deprecated. +#define GPIO_OUTPUT_IO 18 // default output GPIO +#define GPIO_INPUT_IO 19 // default input GPIO +#define GPIO_OUTPUT_MAX GPIO_NUM_34 +static volatile int disable_intr_times = 0; // use this to calculate how many times it go into interrupt +static volatile int level_intr_times = 0; // use this to get how many times the level interrupt happened +static volatile int edge_intr_times = 0; // use this to get how many times the edge interrupt happened +#if !WAKE_UP_IGNORE +static bool wake_up_result = false; // use this to judge the wake up event happen or not +#endif + +/** + * do some initialization operation in this function + * @param num: it is the destination GPIO wanted to be initialized + * + */ +static gpio_config_t init_io(gpio_num_t num) +{ + TEST_ASSERT(num < GPIO_OUTPUT_MAX); + gpio_config_t io_conf; + io_conf.intr_type = GPIO_PIN_INTR_DISABLE; + io_conf.mode = GPIO_MODE_OUTPUT; + io_conf.pin_bit_mask = (1ULL << num); + io_conf.pull_down_en = 0; + io_conf.pull_up_en = 0; + return io_conf; +} + +// edge interrupt event +static void gpio_isr_edge_handler(void* arg) +{ + uint32_t gpio_num = (uint32_t) arg; + ets_printf("GPIO[%d] intr, val: %d\n", gpio_num, gpio_get_level(gpio_num)); + edge_intr_times++; +} + +// level interrupt event with "gpio_intr_disable" +static void gpio_isr_level_handler(void* arg) +{ + uint32_t gpio_num = (uint32_t) arg; + disable_intr_times++; + ets_printf("GPIO[%d] intr, val: %d, disable_intr_times = %d\n", gpio_num, gpio_get_level(gpio_num), disable_intr_times); + gpio_intr_disable(gpio_num); +} + +// level interrupt event +static void gpio_isr_level_handler2(void* arg) +{ + uint32_t gpio_num = (uint32_t) arg; + level_intr_times++; + ets_printf("GPIO[%d] intr, val: %d\n", gpio_num, gpio_get_level(gpio_num)); + if(gpio_get_level(gpio_num)) { + gpio_set_level(GPIO_OUTPUT_IO, 0); + }else{ + gpio_set_level(GPIO_OUTPUT_IO, 1); + } + ets_printf("GPIO[%d] intr, val: %d, level_intr_times = %d\n", GPIO_OUTPUT_IO, gpio_get_level(GPIO_OUTPUT_IO), level_intr_times); + ets_printf("GPIO[%d] intr, val: %d, level_intr_times = %d\n", gpio_num, gpio_get_level(gpio_num), level_intr_times); +} + +#if !WAKE_UP_IGNORE +// get result of waking up or not +static void sleep_wake_up(void *arg) +{ + gpio_config_t io_config = init_io(GPIO_INPUT_IO); + io_config.mode = GPIO_MODE_INPUT; + gpio_config(&io_config); + TEST_ESP_OK(gpio_wakeup_enable(GPIO_INPUT_IO, GPIO_INTR_HIGH_LEVEL)); + esp_light_sleep_start(); + wake_up_result = true; +} + +// wake up light sleep event +static void trigger_wake_up(void *arg) +{ + gpio_config_t io_config = init_io(GPIO_OUTPUT_IO); + gpio_config(&io_config); + gpio_set_level(GPIO_OUTPUT_IO, 0); + gpio_install_isr_service(0); + gpio_isr_handler_add(GPIO_OUTPUT_IO, gpio_isr_level_handler, (void*) GPIO_INPUT_IO); + gpio_set_level(GPIO_OUTPUT_IO, 1); + vTaskDelay(100 / portTICK_RATE_MS); +} +#endif + +static void prompt_to_continue(const char* str) +{ + printf("%s , please press \"Enter\" to go on!\n", str); + char sign[5] = {0}; + while(strlen(sign) == 0) { + /* Flush anything already in the RX buffer */ + while(uart_rx_one_char((uint8_t *) sign) == OK) { + } + /* Read line */ + UartRxString((uint8_t*) sign, sizeof(sign) - 1); + } +} + +static void drive_capability_set_get(gpio_num_t num, gpio_drive_cap_t capability) +{ + gpio_config_t pad_io = init_io(num); + TEST_ESP_OK(gpio_config(&pad_io)); + TEST_ASSERT(gpio_set_drive_capability(num, GPIO_DRIVE_CAP_MAX) == ESP_ERR_INVALID_ARG); + + gpio_drive_cap_t cap; + TEST_ESP_OK(gpio_set_drive_capability(num, capability)); + TEST_ESP_OK(gpio_get_drive_capability(num, &cap)); + TEST_ASSERT_EQUAL_INT(cap, capability); +} + + +// test the basic configuration function with right parameters and error parameters +TEST_CASE("GPIO config parameters test", "[gpio]") +{ + //error param test + //test 41 bit + gpio_config_t io_config; + io_config.pin_bit_mask = ((uint64_t)1<<(GPIO_NUM_MAX+1)); + TEST_ASSERT(gpio_config(&io_config) == ESP_ERR_INVALID_ARG); + + // test 0 + io_config.pin_bit_mask = 0; + TEST_ASSERT(gpio_config(&io_config) == ESP_ERR_INVALID_ARG); + + //test 40 bit + io_config.pin_bit_mask = ((uint64_t)1< 10) { + break; + } + vTaskDelay(100 / portTICK_RATE_MS); + } + vTaskDelay(100 / portTICK_RATE_MS); + // for falling rdge in GPIO_INTR_ANYEDGE + while(1) { + level = level - 1; + gpio_set_level(GPIO_OUTPUT_IO, level/5); + if(level < 0) { + break; + } + vTaskDelay(100 / portTICK_RATE_MS); + } + vTaskDelay(100 / portTICK_RATE_MS); + TEST_ASSERT_EQUAL_INT(edge_intr_times, 2); + vTaskDelay(100 / portTICK_RATE_MS); + gpio_isr_handler_remove(GPIO_INPUT_IO); + gpio_uninstall_isr_service(); +} + +TEST_CASE("GPIO input high level trigger, cut the interrupt source exit interrupt test", "[gpio][test_env=UT_T1_GPIO]") +{ + level_intr_times=0; + gpio_config_t output_io = init_io(GPIO_OUTPUT_IO); + gpio_config_t input_io = init_io(GPIO_INPUT_IO); + input_io.intr_type = GPIO_INTR_POSEDGE; + input_io.mode = GPIO_MODE_INPUT; + input_io.pull_up_en = 1; + TEST_ESP_OK(gpio_config(&output_io)); + TEST_ESP_OK(gpio_config(&input_io)); + TEST_ESP_OK(gpio_set_level(GPIO_OUTPUT_IO, 0)); + + gpio_set_intr_type(GPIO_INPUT_IO, GPIO_INTR_HIGH_LEVEL); + gpio_install_isr_service(0); + gpio_isr_handler_add(GPIO_INPUT_IO, gpio_isr_level_handler2, (void*) GPIO_INPUT_IO); + gpio_set_level(GPIO_OUTPUT_IO, 1); + vTaskDelay(100 / portTICK_RATE_MS); + TEST_ASSERT_EQUAL_INT_MESSAGE(level_intr_times, 1, "go into high-level interrupt more than once with cur interrupt source way"); + gpio_isr_handler_remove(GPIO_INPUT_IO); + gpio_uninstall_isr_service(); + +} + +TEST_CASE("GPIO low level interrupt test", "[gpio][test_env=UT_T1_GPIO]") +{ + disable_intr_times=0; + gpio_config_t output_io = init_io(GPIO_OUTPUT_IO); + gpio_config_t input_io = init_io(GPIO_INPUT_IO); + input_io.intr_type = GPIO_INTR_POSEDGE; + input_io.mode = GPIO_MODE_INPUT; + input_io.pull_up_en = 1; + TEST_ESP_OK(gpio_config(&output_io)); + TEST_ESP_OK(gpio_config(&input_io)); + TEST_ESP_OK(gpio_set_level(GPIO_OUTPUT_IO, 1)); + + gpio_set_intr_type(GPIO_INPUT_IO, GPIO_INTR_LOW_LEVEL); + gpio_install_isr_service(0); + gpio_isr_handler_add(GPIO_INPUT_IO, gpio_isr_level_handler, (void*) GPIO_INPUT_IO); + gpio_set_level(GPIO_OUTPUT_IO, 0); + printf("get level:%d\n",gpio_get_level(GPIO_INPUT_IO)); + vTaskDelay(100 / portTICK_RATE_MS); + TEST_ASSERT_EQUAL_INT_MESSAGE(disable_intr_times, 1, "go into low-level interrupt more than once with disable way"); + gpio_isr_handler_remove(GPIO_INPUT_IO); + gpio_uninstall_isr_service(); +} + +TEST_CASE("GPIO enable and disable interrupt test", "[gpio][test_env=UT_T1_GPIO]") +{ + gpio_config_t output_io = init_io(GPIO_OUTPUT_IO); + gpio_config_t input_io = init_io(GPIO_INPUT_IO); + input_io.intr_type = GPIO_INTR_POSEDGE; + input_io.mode = GPIO_MODE_INPUT; + input_io.pull_up_en = 1; + TEST_ESP_OK(gpio_config(&output_io)); + TEST_ESP_OK(gpio_config(&input_io)); + + TEST_ESP_OK(gpio_set_intr_type(GPIO_INPUT_IO, GPIO_INTR_HIGH_LEVEL)); + TEST_ESP_OK(gpio_install_isr_service(0)); + TEST_ESP_OK(gpio_isr_handler_add(GPIO_INPUT_IO, gpio_isr_level_handler, (void*) GPIO_INPUT_IO)); + TEST_ESP_OK(gpio_set_level(GPIO_OUTPUT_IO, 1)); + TEST_ESP_OK(gpio_isr_handler_remove(GPIO_INPUT_IO)); + TEST_ESP_OK(gpio_set_level(GPIO_OUTPUT_IO, 0)); + TEST_ASSERT_EQUAL_INT_MESSAGE(disable_intr_times, 1, "go into high-level interrupt more than once with disable way"); + + // not install service now + vTaskDelay(100 / portTICK_RATE_MS); + TEST_ESP_OK(gpio_intr_disable(GPIO_INPUT_IO)); + TEST_ESP_OK(gpio_set_level(GPIO_OUTPUT_IO, 1)); + TEST_ASSERT_EQUAL_INT_MESSAGE(disable_intr_times, 1, "disable interrupt does not work, still go into interrupt!"); + + gpio_uninstall_isr_service(); //uninstall the service + TEST_ASSERT(gpio_isr_handler_add(GPIO_INPUT_IO, gpio_isr_level_handler, (void*) GPIO_INPUT_IO) == ESP_ERR_INVALID_STATE); + TEST_ASSERT(gpio_isr_handler_remove(GPIO_INPUT_IO) == ESP_ERR_INVALID_STATE); +} + +// Connect GPIO18 with GPIO19 +// use multimeter to test the voltage, so it is ignored in CI +TEST_CASE("GPIO set gpio output level test", "[gpio][ignore]") +{ + gpio_config_t io_conf; + io_conf.intr_type = GPIO_PIN_INTR_DISABLE; + io_conf.mode = GPIO_MODE_OUTPUT; + io_conf.pin_bit_mask = (1< +#include +#include +#include +#include +#include "rom/ets_sys.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/semphr.h" +#include "freertos/queue.h" +#include "freertos/xtensa_api.h" +#include "unity.h" +#include "soc/ledc_reg.h" +#include "soc/ledc_struct.h" +#include "esp_system.h" +#include "driver/pcnt.h" +#include "driver/ledc.h" +#include "driver/gpio.h" + +#define PULSE_IO 18 +#define PCNT_INPUT_IO 4 +#define PCNT_CTRL_FLOATING_IO 5 +#define HIGHEST_LIMIT 10000 +#define LOWEST_LIMIT -10000 + +// use PCNT to test the waveform of LEDC +static int16_t wave_count(int last_time) +{ + int16_t test_counter; + pcnt_config_t pcnt_config = { + .pulse_gpio_num = PCNT_INPUT_IO, + .ctrl_gpio_num = PCNT_CTRL_FLOATING_IO, + .channel = PCNT_CHANNEL_0, + .unit = PCNT_UNIT_0, + .pos_mode = PCNT_COUNT_INC, + .neg_mode = PCNT_COUNT_DIS, + .lctrl_mode = PCNT_MODE_REVERSE, + .hctrl_mode = PCNT_MODE_KEEP, + .counter_h_lim = HIGHEST_LIMIT, + .counter_l_lim = LOWEST_LIMIT, + }; + TEST_ESP_OK(pcnt_unit_config(&pcnt_config)); + + // initialize first + TEST_ESP_OK(pcnt_counter_pause(PCNT_UNIT_0)); + TEST_ESP_OK(pcnt_counter_clear(PCNT_UNIT_0)); + TEST_ESP_OK(pcnt_counter_resume(PCNT_UNIT_0)); + TEST_ESP_OK(pcnt_get_counter_value(PCNT_UNIT_0, &test_counter)); + + vTaskDelay(last_time / portTICK_RATE_MS); + TEST_ESP_OK(pcnt_get_counter_value(PCNT_UNIT_0, &test_counter)); + return test_counter; +} + +// the PCNT will count the frequency of it +static void frequency_set_get(ledc_mode_t speed_mode, ledc_timer_t timer, uint32_t freq_hz, int16_t real_freq, int16_t error) +{ + int16_t count; + TEST_ESP_OK(ledc_set_freq(speed_mode, timer, freq_hz)); + count = wave_count(1000); + TEST_ASSERT_INT16_WITHIN(error, count, real_freq); + TEST_ASSERT_EQUAL_INT32(ledc_get_freq(speed_mode, timer), real_freq); +} + +static void timer_frequency_test(ledc_channel_t channel, ledc_timer_bit_t timer_bit, ledc_timer_t timer, ledc_mode_t speed_mode) +{ + ledc_channel_config_t ledc_ch_config = { + .gpio_num = PULSE_IO, + .speed_mode = speed_mode, + .channel = channel, + .intr_type = LEDC_INTR_DISABLE, + .timer_sel = timer, + .duty = 4000, + }; + ledc_timer_config_t ledc_time_config = { + .speed_mode = speed_mode, + .bit_num = timer_bit, + .timer_num = timer, + .freq_hz = 5000, + }; + TEST_ESP_OK(ledc_channel_config(&ledc_ch_config)); + TEST_ESP_OK(ledc_timer_config(&ledc_time_config)); + + if(ledc_ch_config.speed_mode == LEDC_HIGH_SPEED_MODE) { + frequency_set_get(ledc_ch_config.speed_mode, ledc_ch_config.timer_sel, 100, 100, 2); + frequency_set_get(ledc_ch_config.speed_mode, ledc_ch_config.timer_sel, 5000, 5000, 5); + frequency_set_get(ledc_ch_config.speed_mode, ledc_ch_config.timer_sel, 9000, 9025, 5); + } else { + frequency_set_get(ledc_ch_config.speed_mode, ledc_ch_config.timer_sel, 10, 10, 1); +// comment it because this is a bug that when ledc in low speed mode, its frequency can't be changed +// frequency_set_get(ledc_ch_config.speed_mode, ledc_ch_config.timer_sel, 50, 50, 2); +// frequency_set_get(ledc_ch_config.speed_mode, ledc_ch_config.timer_sel, 100, 100, 2); + } +} + +static void timer_duty_set_get(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t duty) +{ + TEST_ESP_OK(ledc_set_duty(speed_mode, channel, duty)); + TEST_ESP_OK(ledc_update_duty(speed_mode, channel)); + vTaskDelay(1000 / portTICK_RATE_MS); + TEST_ASSERT_EQUAL_INT32(ledc_get_duty(speed_mode, channel), duty); +} + +// use logic analyzer to view +static void timer_duty_test(ledc_channel_t channel, ledc_timer_bit_t timer_bit, ledc_timer_t timer, ledc_mode_t speed_mode) +{ + ledc_channel_config_t ledc_ch_config = { + .gpio_num = PULSE_IO, + .speed_mode = speed_mode, + .channel = channel, + .intr_type = LEDC_INTR_DISABLE, + .timer_sel = timer, + .duty = 4000, + }; + ledc_timer_config_t ledc_time_config = { + .speed_mode = speed_mode, + .bit_num = timer_bit, + .timer_num = timer, + .freq_hz = 5000, + }; + TEST_ESP_OK(ledc_channel_config(&ledc_ch_config)); + TEST_ESP_OK(ledc_timer_config(&ledc_time_config)); + + // duty ratio: (2^duty)/(2^timer_bit) + timer_duty_set_get(ledc_ch_config.speed_mode, ledc_ch_config.channel, 0); + timer_duty_set_get(ledc_ch_config.speed_mode, ledc_ch_config.channel, 1); + timer_duty_set_get(ledc_ch_config.speed_mode, ledc_ch_config.channel, 1 << 12); // 50% duty + timer_duty_set_get(ledc_ch_config.speed_mode, ledc_ch_config.channel, (1 << 13) - 1); + timer_duty_set_get(ledc_ch_config.speed_mode, ledc_ch_config.channel, (1 << 13) - 2); +} + +TEST_CASE("LEDC error log channel and timer config", "[ledc][test_env=UT_T1_LEDC]") +{ + //channel configuration test + ledc_channel_config_t ledc_ch_config = { + .gpio_num = PULSE_IO, + .speed_mode = LEDC_HIGH_SPEED_MODE, + .channel = LEDC_CHANNEL_0, + .intr_type = LEDC_INTR_DISABLE, + .timer_sel = LEDC_TIMER_0, + .duty = 4000, + }; + + // basic right parameter test + ledc_channel_config_t temp_ch_config = ledc_ch_config; + TEST_ESP_OK(ledc_channel_config(&ledc_ch_config)); + + // with wrong GPIO using + ledc_ch_config.gpio_num = 41; + TEST_ASSERT(ledc_channel_config(&ledc_ch_config) == ESP_ERR_INVALID_ARG); + + // with wrong speed + ledc_ch_config = temp_ch_config; + ledc_ch_config.speed_mode = LEDC_SPEED_MODE_MAX; + TEST_ASSERT(ledc_channel_config(&ledc_ch_config) == ESP_ERR_INVALID_ARG); + + // with wrong channel + ledc_ch_config = temp_ch_config; + ledc_ch_config.channel = LEDC_CHANNEL_MAX; + TEST_ASSERT(ledc_channel_config(&ledc_ch_config) == ESP_ERR_INVALID_ARG); + + // with wrong interruption type + ledc_ch_config = temp_ch_config; + ledc_ch_config.intr_type = 2; + TEST_ASSERT_FALSE((void *)ledc_channel_config(&ledc_ch_config)); + + // with wrong timer + ledc_ch_config = temp_ch_config; + ledc_ch_config.timer_sel = 4; + TEST_ASSERT(ledc_channel_config(&ledc_ch_config) == ESP_ERR_INVALID_ARG); + + ledc_ch_config = temp_ch_config; + ledc_ch_config.duty = 12000; + TEST_ASSERT_FALSE((void *)ledc_channel_config(&ledc_ch_config)); + + // timer configuration test + ledc_timer_config_t ledc_time_config; + ledc_time_config.speed_mode = LEDC_HIGH_SPEED_MODE; + ledc_time_config.duty_resolution = LEDC_TIMER_13_BIT; + ledc_time_config.timer_num = LEDC_TIMER_0; + ledc_time_config.freq_hz = 5000; + + ledc_timer_config_t temp_timer_config = ledc_time_config; + TEST_ESP_OK(ledc_timer_config(&ledc_time_config)); + + ledc_time_config.speed_mode = LEDC_SPEED_MODE_MAX; + TEST_ASSERT(ledc_timer_config(&ledc_time_config) == ESP_ERR_INVALID_ARG); + + // wrong duty_resolution + ledc_time_config = temp_timer_config; + ledc_time_config.duty_resolution = LEDC_TIMER_BIT_MAX; + TEST_ASSERT(ledc_timer_config(&ledc_time_config) == ESP_ERR_INVALID_ARG); + + // wrong timer + ledc_time_config = temp_timer_config; + ledc_time_config.timer_num = 4; + TEST_ASSERT(ledc_timer_config(&ledc_time_config) == ESP_ERR_INVALID_ARG); + + uint32_t current_level = LEDC.channel_group[LEDC_HIGH_SPEED_MODE].channel[LEDC_CHANNEL_0].conf0.idle_lv; + TEST_ESP_OK(ledc_stop(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_0, !current_level)); + vTaskDelay(1000 / portTICK_RATE_MS); + TEST_ASSERT_EQUAL_INT32( LEDC.channel_group[LEDC_HIGH_SPEED_MODE].channel[LEDC_CHANNEL_0].conf0.idle_lv, !current_level); +} + +TEST_CASE("LEDC normal channel and timer config", "[ledc][test_env=UT_T1_LEDC]") +{ + ledc_channel_config_t ledc_ch_config = { + .gpio_num = PULSE_IO, + .speed_mode = LEDC_HIGH_SPEED_MODE, + .channel = LEDC_CHANNEL_0, + .intr_type = LEDC_INTR_DISABLE, + .timer_sel = LEDC_TIMER_0, + .duty = 4000, + }; + ledc_channel_config_t temp_ch_config = ledc_ch_config; + + ledc_timer_config_t ledc_time_config = { + .speed_mode = LEDC_HIGH_SPEED_MODE, + .bit_num = LEDC_TIMER_13_BIT, + .timer_num = LEDC_TIMER_0, + .freq_hz = 5000, + }; + ledc_timer_config_t temp_time_config = ledc_time_config; + + // use all kinds of speed mode, channel, timer combination to test all of possible configuration + ledc_mode_t speed_mode[2] = {LEDC_HIGH_SPEED_MODE, LEDC_LOW_SPEED_MODE}; + ledc_channel_t channel_type[8] = {LEDC_CHANNEL_0, LEDC_CHANNEL_1, LEDC_CHANNEL_2, LEDC_CHANNEL_3, LEDC_CHANNEL_4, LEDC_CHANNEL_5, LEDC_CHANNEL_6, LEDC_CHANNEL_7}; + ledc_timer_t timer_select[4] = {LEDC_TIMER_0, LEDC_TIMER_1, LEDC_TIMER_2, LEDC_TIMER_3}; + + for (int i = 0; i < 2; i++) { + ledc_ch_config.speed_mode = speed_mode[i]; + ledc_time_config.speed_mode = speed_mode[i]; + for (int j = 0; j < 8; j++) { + ledc_ch_config.channel = channel_type[j]; + for (int k = 0; k < 4; k++) { + ledc_ch_config.timer_sel = timer_select[k]; + ledc_time_config.timer_num = timer_select[k]; + TEST_ESP_OK(ledc_channel_config(&ledc_ch_config)); + TEST_ESP_OK(ledc_timer_config(&ledc_time_config)); + ledc_ch_config = temp_ch_config; + ledc_time_config = temp_time_config; + } + } + } +} + +TEST_CASE("LEDC set and get frequency", "[ledc][test_env=UT_T1_LEDC][timeout=60]") +{ + timer_frequency_test(LEDC_CHANNEL_0, LEDC_TIMER_13_BIT, LEDC_TIMER_0, LEDC_HIGH_SPEED_MODE); + timer_frequency_test(LEDC_CHANNEL_0, LEDC_TIMER_13_BIT, LEDC_TIMER_1, LEDC_HIGH_SPEED_MODE); + timer_frequency_test(LEDC_CHANNEL_0, LEDC_TIMER_13_BIT, LEDC_TIMER_2, LEDC_HIGH_SPEED_MODE); + timer_frequency_test(LEDC_CHANNEL_0, LEDC_TIMER_13_BIT, LEDC_TIMER_3, LEDC_HIGH_SPEED_MODE); +// comment it because this is a bug that when ledc in low speed mode, its frequency can't be changed +// timer_frequency_test(LEDC_CHANNEL_0, LEDC_TIMER_13_BIT, LEDC_TIMER_0, LEDC_LOW_SPEED_MODE); +// timer_frequency_test(LEDC_CHANNEL_0, LEDC_TIMER_13_BIT, LEDC_TIMER_1, LEDC_LOW_SPEED_MODE); +// timer_frequency_test(LEDC_CHANNEL_0, LEDC_TIMER_13_BIT, LEDC_TIMER_2, LEDC_LOW_SPEED_MODE); +// timer_frequency_test(LEDC_CHANNEL_0, LEDC_TIMER_13_BIT, LEDC_TIMER_3, LEDC_LOW_SPEED_MODE); +} + +// the duty need to be detected by waveform given by the logic analyzer +// can't get it directly, so set it "ignore" +TEST_CASE("LEDC set and get dut(with logic analyzer)", "[ledc][ignore]") +{ + ledc_timer_t timer_list[4] = {LEDC_TIMER_0, LEDC_TIMER_1, LEDC_TIMER_2, LEDC_TIMER_3}; + ledc_mode_t speed_mode_list[2] = {LEDC_HIGH_SPEED_MODE, LEDC_LOW_SPEED_MODE}; + for(int i=0; i +#include "driver/rmt.h" +#include "unity.h" +#include "test_utils.h" +#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 "driver/periph_ctrl.h" +#include "soc/rmt_reg.h" + +static const char* TAG = "RMT"; + + +#define RMT_RX_ACTIVE_LEVEL 1 /*!< Data bit is active high for self test mode */ +#define RMT_TX_CARRIER_EN 0 /*!< Disable carrier for self test mode */ + +#define RMT_TX_CHANNEL 1 /*!< RMT channel for transmitter */ +#define RMT_TX_GPIO_NUM 18 /*!< GPIO number for transmitter signal */ +#define RMT_RX_CHANNEL 0 /*!< RMT channel for receiver */ +#define RMT_RX_GPIO_NUM 19 /*!< GPIO number for receiver */ +#define RMT_CLK_DIV 100 /*!< RMT counter clock divider */ +#define RMT_TICK_10_US (80000000/RMT_CLK_DIV/100000) /*!< RMT counter value for 10 us.(Source clock is APB clock) */ + +#define HEADER_HIGH_US 9000 /*!< NEC protocol header: positive 9ms */ +#define HEADER_LOW_US 4500 /*!< NEC protocol header: negative 4.5ms*/ +#define BIT_ONE_HIGH_US 560 /*!< NEC protocol data bit 1: positive 0.56ms */ +#define BIT_ONE_LOW_US (2250-BIT_ONE_HIGH_US) /*!< NEC protocol data bit 1: negative 1.69ms */ +#define BIT_ZERO_HIGH_US 560 /*!< NEC protocol data bit 0: positive 0.56ms */ +#define BIT_ZERO_LOW_US (1120-BIT_ZERO_HIGH_US) /*!< NEC protocol data bit 0: negative 0.56ms */ +#define BIT_END 560 /*!< NEC protocol end: positive 0.56ms */ +#define BIT_MARGIN 20 /*!< NEC parse margin time */ + +#define ITEM_DURATION(d) ((d & 0x7fff)*10/RMT_TICK_10_US) /*!< Parse duration time from memory register value */ +#define DATA_ITEM_NUM 34 /*!< NEC code item number: header + 32bit data + end */ +#define RMT_TX_DATA_NUM 100 /*!< NEC tx test data number */ +#define RMT_ITEM32_TIMEOUT_US 9500 /*!< RMT receiver timeout value(us) */ + +/** + * @brief Build register value of waveform for NEC one data bit + */ +static inline void fill_item_level(rmt_item32_t* item, int high_us, int low_us) +{ + item->level0 = 1; + item->duration0 = (high_us) / 10 * RMT_TICK_10_US; + item->level1 = 0; + item->duration1 = (low_us) / 10 * RMT_TICK_10_US; +} + +/** + * @brief Generate NEC header value: active 9ms + negative 4.5ms + */ +static void fill_item_header(rmt_item32_t* item) +{ + fill_item_level(item, HEADER_HIGH_US, HEADER_LOW_US); +} + +/* + * @brief Generate NEC data bit 1: positive 0.56ms + negative 1.69ms + */ +static void fill_item_bit_one(rmt_item32_t* item) +{ + fill_item_level(item, BIT_ONE_HIGH_US, BIT_ONE_LOW_US); +} + +/** + * @brief Generate NEC data bit 0: positive 0.56ms + negative 0.56ms + */ +static void fill_item_bit_zero(rmt_item32_t* item) +{ + fill_item_level(item, BIT_ZERO_HIGH_US, BIT_ZERO_LOW_US); +} + +/** + * @brief Generate NEC end signal: positive 0.56ms + */ +static void fill_item_end(rmt_item32_t* item) +{ + fill_item_level(item, BIT_END, 0x7fff); +} + +/** + * @brief Check whether duration is around target_us + */ +inline bool check_in_range(int duration_ticks, int target_us, int margin_us) +{ + if(( ITEM_DURATION(duration_ticks) < (target_us + margin_us)) + && ( ITEM_DURATION(duration_ticks) > (target_us - margin_us))) { + return true; + } else { + return false; + } +} + +/** + * @brief Check whether this value represents an NEC header + */ +static bool header_if(rmt_item32_t* item) +{ + if((item->level0 == RMT_RX_ACTIVE_LEVEL && item->level1 != RMT_RX_ACTIVE_LEVEL) + && check_in_range(item->duration0, HEADER_HIGH_US, BIT_MARGIN) + && check_in_range(item->duration1, HEADER_LOW_US, BIT_MARGIN)) { + return true; + } + return false; +} + +/** + * @brief Check whether this value represents an NEC data bit 1 + */ +static bool bit_one_if(rmt_item32_t* item) +{ + if((item->level0 == RMT_RX_ACTIVE_LEVEL && item->level1 != RMT_RX_ACTIVE_LEVEL) + && check_in_range(item->duration0, BIT_ONE_HIGH_US, BIT_MARGIN) + && check_in_range(item->duration1, BIT_ONE_LOW_US, BIT_MARGIN)) { + return true; + } + return false; +} + +/** + * @brief Check whether this value represents an NEC data bit 0 + */ +static bool bit_zero_if(rmt_item32_t* item) +{ + if((item->level0 == RMT_RX_ACTIVE_LEVEL && item->level1 != RMT_RX_ACTIVE_LEVEL) + && check_in_range(item->duration0, BIT_ZERO_HIGH_US, BIT_MARGIN) + && check_in_range(item->duration1, BIT_ZERO_LOW_US, BIT_MARGIN)) { + return true; + } + return false; +} + + +/** + * @brief Parse NEC 32 bit waveform to address and command. + */ +static int parse_items(rmt_item32_t* item, int item_num, uint16_t* addr, uint16_t* data) +{ + int w_len = item_num; + if(w_len < DATA_ITEM_NUM) { + return -1; + } + int i = 0, j = 0; + if(!header_if(item++)) { + return -1; + } + uint16_t addr_t = 0; + for(j = 0; j < 16; j++) { + if(bit_one_if(item)) { + addr_t |= (1 << j); + } else if(bit_zero_if(item)) { + addr_t |= (0 << j); + } else { + return -1; + } + item++; + i++; + } + uint16_t data_t = 0; + for(j = 0; j < 16; j++) { + if(bit_one_if(item)) { + data_t |= (1 << j); + } else if(bit_zero_if(item)) { + data_t |= (0 << j); + } else { + return -1; + } + item++; + i++; + } + *addr = addr_t; + *data = data_t; + return i; +} + +/** + * @brief Build NEC 32bit waveform. + */ +static int build_items(int channel, rmt_item32_t* item, int item_num, uint16_t addr, uint16_t cmd_data) +{ + int i = 0, j = 0; + if(item_num < DATA_ITEM_NUM) { + return -1; + } + fill_item_header(item++); + i++; + for(j = 0; j < 16; j++) { + if(addr & 0x1) { + fill_item_bit_one(item); + } else { + fill_item_bit_zero(item); + } + item++; + i++; + addr >>= 1; + } + for(j = 0; j < 16; j++) { + if(cmd_data & 0x1) { + fill_item_bit_one(item); + } else { + fill_item_bit_zero(item); + } + item++; + i++; + cmd_data >>= 1; + } + fill_item_end(item); + i++; + return i; +} + +static void set_tx_data(int tx_channel, uint16_t cmd, uint16_t addr, int item_num, rmt_item32_t* item, int offset) +{ + while(1) { + int i = build_items(tx_channel, item + offset, item_num - offset, ((~addr) << 8) | addr, cmd); + printf("cmd :%d\n", cmd); + if(i < 0) { + break; + } + cmd++; + addr++; + offset += i; + } +} + +static int get_rx_data(RingbufHandle_t rb) +{ + uint16_t tmp = 0; + while(rb) { + size_t rx_size = 0; + rmt_item32_t* rx_item = (rmt_item32_t*) xRingbufferReceive(rb, &rx_size, 1000); + if(rx_item) { + uint16_t rmt_addr; + uint16_t rmt_cmd; + int rx_offset = 0; + while(1) { + int res = parse_items(rx_item + rx_offset, rx_size / 4 - rx_offset, &rmt_addr, &rmt_cmd); + if(res > 0) { + rx_offset += res + 1; + ESP_LOGI(TAG, "RMT RCV --- addr: 0x%04x cmd: 0x%04x", rmt_addr, rmt_cmd); + TEST_ASSERT(rmt_cmd == tmp); + tmp++; + } else { + break; + } + } + vRingbufferReturnItem(rb, (void*) rx_item); + } else { + break; + } + } + return tmp; +} + +/** + * @brief RMT transmitter initialization + */ +static void tx_init() +{ + // the sender once it send something, its frq is 38kHz, and the duty cycle is 50% + rmt_tx_config_t tx_cfg = { + .loop_en = false, + .carrier_duty_percent = 50, + .carrier_freq_hz = 38000, + .carrier_level = 1, + .carrier_en = RMT_TX_CARRIER_EN, + .idle_level = 0, + .idle_output_en = true, + }; + rmt_config_t rmt_tx = { + .channel = RMT_TX_CHANNEL, + .gpio_num = RMT_TX_GPIO_NUM, + .mem_block_num = 1, + .clk_div = RMT_CLK_DIV, + .tx_config = tx_cfg, + .rmt_mode = 0, + }; + rmt_config(&rmt_tx); + rmt_driver_install(rmt_tx.channel, 0, 0); +} + +/** + * @brief RMT receiver initialization + */ +static void rx_init() +{ + rmt_rx_config_t rx_cfg = { + .filter_en = true, + .filter_ticks_thresh = 100, + .idle_threshold = RMT_ITEM32_TIMEOUT_US / 10 * (RMT_TICK_10_US), + }; + rmt_config_t rmt_rx = { + .channel = RMT_RX_CHANNEL, + .gpio_num = RMT_RX_GPIO_NUM, + .clk_div = RMT_CLK_DIV, + .mem_block_num = 1, + .rmt_mode = RMT_MODE_RX, + .rx_config = rx_cfg, + }; + rmt_config(&rmt_rx); + rmt_driver_install(rmt_rx.channel, (sizeof(rmt_item32_t) * DATA_ITEM_NUM * (RMT_TX_DATA_NUM+6)), 0); +} + +TEST_CASE("RMT init config", "[rmt][test_env=UT_T1_RMT]") +{ + // tx settings + rmt_tx_config_t tx_cfg = { + .loop_en = false, + .carrier_duty_percent = 50, + .carrier_freq_hz = 38000, + .carrier_level = 1, + .carrier_en = RMT_TX_CARRIER_EN, + .idle_level = 0, + .idle_output_en = true, + }; + rmt_config_t rmt_tx = { + .channel = RMT_TX_CHANNEL, + .gpio_num = RMT_TX_GPIO_NUM, + .mem_block_num = 1, + .clk_div = RMT_CLK_DIV, + .tx_config = tx_cfg, + }; + TEST_ESP_OK(rmt_config(&rmt_tx)); + TEST_ESP_OK(rmt_driver_install(rmt_tx.channel, 0, 0)); + TEST_ESP_OK(rmt_driver_uninstall(rmt_tx.channel)); + + //rx settings + rmt_rx_config_t rx_cfg = { + .filter_en = true, + .filter_ticks_thresh = 100, + .idle_threshold = RMT_ITEM32_TIMEOUT_US / 10 * (RMT_TICK_10_US), + }; + rmt_config_t rmt_rx = { + .channel = RMT_RX_CHANNEL, + .gpio_num = RMT_RX_GPIO_NUM, + .clk_div = RMT_CLK_DIV, + .mem_block_num = 1, + .rmt_mode = RMT_MODE_RX, + .rx_config = rx_cfg, + }; + TEST_ESP_OK(rmt_config(&rmt_rx)); + TEST_ESP_OK(rmt_driver_install(rmt_rx.channel, 1000, 0)); + TEST_ESP_OK(rmt_driver_uninstall(rmt_rx.channel)); + + //error param setting + rmt_config_t temp_rmt_rx1 = { + .channel = 2, + .gpio_num = 15, + .clk_div = RMT_CLK_DIV, + .mem_block_num = 1, + .rmt_mode = RMT_MODE_RX, + .rx_config = rx_cfg, + }; + rmt_config_t temp_rmt_rx2 = temp_rmt_rx1; + + temp_rmt_rx2.clk_div = 0; // only invalid parameter to test + TEST_ASSERT(rmt_config(&temp_rmt_rx2) == ESP_ERR_INVALID_ARG); + + temp_rmt_rx2 = temp_rmt_rx1; + temp_rmt_rx2.channel = RMT_CHANNEL_MAX; + TEST_ASSERT(rmt_config(&temp_rmt_rx2) == ESP_ERR_INVALID_ARG); + + temp_rmt_rx2 = temp_rmt_rx1; + temp_rmt_rx2.channel = 2; + temp_rmt_rx2.mem_block_num = 8; + TEST_ASSERT(rmt_config(&temp_rmt_rx2) == ESP_ERR_INVALID_ARG); +} + +TEST_CASE("RMT init set function", "[rmt][test_env=UT_T1_RMT]") +{ + rmt_channel_t channel = 7; + TEST_ESP_OK(rmt_set_pin(channel, RMT_MODE_RX, RMT_RX_GPIO_NUM)); + TEST_ESP_OK(rmt_set_clk_div(channel, RMT_CLK_DIV*2)); + TEST_ESP_OK(rmt_set_mem_block_num(channel, 1)); + TEST_ESP_OK(rmt_set_rx_filter(channel, 1, 100)); + TEST_ESP_OK(rmt_set_rx_idle_thresh(channel, RMT_ITEM32_TIMEOUT_US / 10 * (RMT_TICK_10_US)*2)); + TEST_ESP_OK(rmt_driver_install(channel, 0, 0)); + TEST_ESP_OK(rmt_driver_uninstall(channel)); +} + +// need to make sure its phenomenon by logic analyzer, can't run in CI +TEST_CASE("RMT clock devider, clock source set(logic analyzer)", "[rmt][ignore]") +{ + uint8_t div_cnt; + rmt_source_clk_t src_clk; + rmt_config_t rmt_tx; + rmt_tx.channel = RMT_TX_CHANNEL; + rmt_tx.mem_block_num = 1; + rmt_tx.gpio_num = RMT_TX_GPIO_NUM; + rmt_tx.clk_div = RMT_CLK_DIV; + rmt_tx.tx_config.loop_en = true; + rmt_tx.tx_config.carrier_duty_percent = 50; + rmt_tx.tx_config.carrier_freq_hz = 38000; + rmt_tx.tx_config.carrier_level = 1; + rmt_tx.tx_config.carrier_en = RMT_TX_CARRIER_EN; + rmt_tx.tx_config.idle_level = 0; + rmt_tx.tx_config.idle_output_en = true; + rmt_tx.rmt_mode = RMT_MODE_TX; + + TEST_ESP_OK(rmt_config(&rmt_tx)); + TEST_ESP_OK(rmt_get_clk_div(RMT_TX_CHANNEL, &div_cnt)); + TEST_ESP_OK(rmt_driver_install(rmt_tx.channel, 0, 0)); + TEST_ASSERT_EQUAL_UINT8(div_cnt, RMT_CLK_DIV); + vTaskDelay(1000 / portTICK_PERIOD_MS); + + // reset it and check it + TEST_ESP_OK(rmt_set_clk_div(RMT_TX_CHANNEL, 160)); + TEST_ESP_OK(rmt_get_clk_div(RMT_TX_CHANNEL, &div_cnt)); + vTaskDelay(1000 / portTICK_PERIOD_MS); + + TEST_ESP_OK(rmt_set_source_clk(RMT_TX_CHANNEL, RMT_BASECLK_APB)); + TEST_ESP_OK(rmt_get_source_clk(RMT_TX_CHANNEL, &src_clk)); + TEST_ASSERT_EQUAL_UINT8(div_cnt, 160); + TEST_ASSERT_EQUAL_INT(src_clk, RMT_BASECLK_APB); + TEST_ESP_OK(rmt_driver_uninstall(rmt_tx.channel)); +} + +TEST_CASE("RMT rx set and get properties", "[rmt][test_env=UT_T1_RMT]") +{ + rmt_channel_t channel = RMT_RX_CHANNEL; + uint8_t memNum; + uint8_t div_cnt; + uint16_t idleThreshold; + rmt_mem_owner_t owner; + + rx_init(); + + TEST_ESP_OK(rmt_get_clk_div(channel, &div_cnt)); + TEST_ESP_OK(rmt_get_mem_block_num(channel, &memNum)); + TEST_ESP_OK(rmt_get_rx_idle_thresh(channel, &idleThreshold)); + TEST_ESP_OK(rmt_get_memory_owner(channel, &owner)); + + TEST_ASSERT_EQUAL_UINT8(div_cnt, RMT_CLK_DIV); + TEST_ASSERT_EQUAL_UINT8(memNum, 1); + TEST_ASSERT_EQUAL_UINT16(idleThreshold, RMT_ITEM32_TIMEOUT_US / 10 * (RMT_TICK_10_US)); + TEST_ASSERT_EQUAL_INT(owner, RMT_MEM_OWNER_RX); + + //eRR + TEST_ESP_OK(rmt_set_pin(channel, RMT_MODE_RX, 22)); + TEST_ESP_OK(rmt_set_clk_div(channel, RMT_CLK_DIV*2)); + TEST_ESP_OK(rmt_set_mem_block_num(channel, 2)); + TEST_ESP_OK(rmt_set_rx_filter(channel, 1, 100)); + TEST_ESP_OK(rmt_set_rx_idle_thresh(channel, RMT_ITEM32_TIMEOUT_US / 10 * (RMT_TICK_10_US)*2)); + TEST_ESP_OK(rmt_set_memory_owner(channel, RMT_MEM_OWNER_RX)); + + TEST_ESP_OK(rmt_get_clk_div(channel, &div_cnt)); + TEST_ESP_OK(rmt_get_mem_block_num(channel, &memNum)); + TEST_ESP_OK(rmt_get_rx_idle_thresh(channel, &idleThreshold)); + TEST_ESP_OK(rmt_get_memory_owner(channel, &owner)); + + TEST_ASSERT_EQUAL_UINT8(div_cnt, RMT_CLK_DIV*2); + TEST_ASSERT_EQUAL_UINT8(memNum, 2); + TEST_ASSERT_EQUAL_UINT16(idleThreshold, RMT_ITEM32_TIMEOUT_US / 10 * (RMT_TICK_10_US)*2); + TEST_ASSERT_EQUAL_INT(owner, RMT_MEM_OWNER_RX); + + TEST_ESP_OK(rmt_driver_uninstall(channel)); +} + +TEST_CASE("RMT tx set and get properties", "[rmt][test_env=UT_T1_RMT]") +{ + rmt_channel_t channel = RMT_TX_CHANNEL; + uint8_t memNum; + uint8_t div_cnt; + bool loop_en; + rmt_mem_owner_t owner; + + tx_init(); + TEST_ESP_OK(rmt_get_clk_div(channel, &div_cnt)); + TEST_ESP_OK(rmt_get_mem_block_num(channel, &memNum)); + TEST_ESP_OK(rmt_get_tx_loop_mode(channel, &loop_en)); + TEST_ESP_OK(rmt_get_memory_owner(channel, &owner)); + + TEST_ASSERT_EQUAL_INT8(loop_en, 0); + TEST_ASSERT_EQUAL_UINT8(div_cnt, RMT_CLK_DIV); + TEST_ASSERT_EQUAL_UINT8(memNum, 1); + TEST_ASSERT_EQUAL_INT(owner, RMT_MEM_OWNER_TX); + + //reset by "set" + TEST_ESP_OK(rmt_set_pin(channel, RMT_MODE_TX, RMT_TX_GPIO_NUM)); + TEST_ESP_OK(rmt_set_clk_div(channel, RMT_CLK_DIV*2)); + TEST_ESP_OK(rmt_set_mem_block_num(channel, 2)); + TEST_ESP_OK(rmt_set_tx_loop_mode(channel, 1)); + TEST_ESP_OK(rmt_set_tx_carrier(channel, 0, 1, 0, 1)); + TEST_ESP_OK(rmt_set_idle_level(channel, 1, 0)); + TEST_ESP_OK(rmt_set_memory_owner(channel, RMT_MEM_OWNER_TX)); + + TEST_ESP_OK(rmt_get_clk_div(channel, &div_cnt)); + TEST_ESP_OK(rmt_get_mem_block_num(channel, &memNum)); + TEST_ESP_OK(rmt_get_tx_loop_mode(channel, &loop_en)); + TEST_ESP_OK(rmt_get_memory_owner(channel, &owner)); + + TEST_ASSERT_EQUAL_INT8(loop_en, 1); + TEST_ASSERT_EQUAL_UINT8(div_cnt, RMT_CLK_DIV*2); + TEST_ASSERT_EQUAL_UINT8(memNum, 2); + TEST_ASSERT_EQUAL_INT(owner, RMT_MEM_OWNER_TX); + + rmt_item32_t items[1]; + items[0].duration0 = 300 / 10 * RMT_TICK_10_US; //300us + items[0].level0 = 1; + items[0].duration1 = 0; + items[0].level1 = 0; + for(int i=0; i<100; i++) { + TEST_ESP_OK(rmt_write_items(RMT_TX_CHANNEL, items, + 1, /* Number of items */ + 1 /* wait till done */)); + vTaskDelay(10/portTICK_PERIOD_MS); //every 10ms to write the item + } + TEST_ESP_OK(rmt_driver_uninstall(channel)); +} + +TEST_CASE("RMT memory test", "[rmt][test_env=UT_T1_RMT]") +{ + rmt_config_t rmt_rx; + rmt_rx.channel = RMT_RX_CHANNEL; + rmt_rx.gpio_num = RMT_RX_GPIO_NUM; + rmt_rx.clk_div = RMT_CLK_DIV; + rmt_rx.mem_block_num = 1; + rmt_rx.rmt_mode = RMT_MODE_RX; + rmt_rx.rx_config.filter_en = true; + rmt_rx.rx_config.filter_ticks_thresh = 100; + rmt_rx.rx_config.idle_threshold = RMT_ITEM32_TIMEOUT_US / 10 * (RMT_TICK_10_US); + TEST_ESP_OK(rmt_config(&rmt_rx)); + + for(int i = 0; i<100; i++) { + TEST_ESP_OK(rmt_driver_install(rmt_rx.channel, 1000, 0)); + TEST_ESP_OK(rmt_driver_uninstall(rmt_rx.channel)); + } +} + +TEST_CASE("RMT send waveform(logic analyzer)", "[rmt][test_env=UT_T1_RMT][ignore]") +{ + tx_init(); + rmt_item32_t items[1]; + items[0].duration0 = 300 / 10 * RMT_TICK_10_US; //300us + items[0].level0 = 1; + for(int i=0; i<500; i++) { + TEST_ESP_OK(rmt_write_items(RMT_TX_CHANNEL, items, + 1, /* Number of items */ + 1 /* wait till done */)); + vTaskDelay(10/portTICK_PERIOD_MS); //every 10ms to write the item + } + TEST_ESP_OK(rmt_driver_uninstall(RMT_TX_CHANNEL)); +} + +TEST_CASE("RMT basic TX and RX", "[rmt][test_env=UT_T1_RMT]") +{ + tx_init(); + int tx_channel = RMT_TX_CHANNEL; + uint16_t cmd = 0x0; + uint16_t addr = 0x11; + int tx_num = RMT_TX_DATA_NUM; + ESP_LOGI(TAG, "RMT TX DATA"); + size_t size = (sizeof(rmt_item32_t) * DATA_ITEM_NUM * tx_num); + rmt_item32_t* item = (rmt_item32_t*) malloc(size); + int item_num = DATA_ITEM_NUM * tx_num; + memset((void*) item, 0, size); + int offset = 0; + + int rx_channel = RMT_RX_CHANNEL; + rx_init(); + RingbufHandle_t rb = NULL; + rmt_get_ringbuf_handle(rx_channel, &rb); + rmt_rx_start(rx_channel, 1); + // send data + set_tx_data(tx_channel, cmd, addr, item_num, item, offset); + rmt_write_items(tx_channel, item, item_num, 1); + free(item); + // receive data + uint16_t tmp = get_rx_data(rb); + TEST_ASSERT(tmp == 100); + TEST_ESP_OK(rmt_driver_uninstall(RMT_TX_CHANNEL)); + TEST_ESP_OK(rmt_driver_uninstall(RMT_RX_CHANNEL)); +} + +TEST_CASE("RMT TX write item not wait", "[rmt][test_env=UT_T1_RMT]") +{ + tx_init(); + int tx_channel = RMT_TX_CHANNEL; + uint16_t cmd = 0x0; + uint16_t addr = 0x11; + int tx_num = RMT_TX_DATA_NUM; + ESP_LOGI(TAG, "RMT TX DATA"); + size_t size = (sizeof(rmt_item32_t) * DATA_ITEM_NUM * tx_num); + rmt_item32_t* item = (rmt_item32_t*) malloc(size); + int item_num = DATA_ITEM_NUM * tx_num; + memset((void*) item, 0, size); + int offset = 0; + + int rx_channel = RMT_RX_CHANNEL; + rx_init(); + RingbufHandle_t rb = NULL; + rmt_get_ringbuf_handle(rx_channel, &rb); + rmt_rx_start(rx_channel, 1); + + // send data + set_tx_data(tx_channel, cmd, addr, item_num, item, offset); + rmt_write_items(tx_channel, item, item_num, 0); + free(item); + + // receive data + uint16_t tmp = get_rx_data(rb); + TEST_ASSERT(tmp < 100); + TEST_ESP_OK(rmt_driver_uninstall(RMT_TX_CHANNEL)); + TEST_ESP_OK(rmt_driver_uninstall(RMT_RX_CHANNEL)); +} + +TEST_CASE("RMT TX write item wait some ticks", "[rmt][test_env=UT_T1_RMT]") +{ + tx_init(); + int tx_channel = RMT_TX_CHANNEL; + uint16_t cmd = 0x0; + uint16_t addr = 0x11; + int tx_num = RMT_TX_DATA_NUM; + ESP_LOGI(TAG, "RMT TX DATA"); + size_t size = (sizeof(rmt_item32_t) * DATA_ITEM_NUM * tx_num); + rmt_item32_t* item = (rmt_item32_t*) malloc(size); + int item_num = DATA_ITEM_NUM * tx_num; + memset((void*) item, 0, size); + int offset = 0; + + int rx_channel = RMT_RX_CHANNEL; + rx_init(); + RingbufHandle_t rb = NULL; + rmt_get_ringbuf_handle(rx_channel, &rb); + rmt_rx_start(rx_channel, 1); + + // send data + set_tx_data(tx_channel, cmd, addr, item_num, item, offset); + rmt_write_items(tx_channel, item, item_num, 0); + rmt_wait_tx_done(tx_channel, portMAX_DELAY); + free(item); + + // receive data + uint16_t tmp = get_rx_data(rb); + TEST_ASSERT(tmp == 100); + TEST_ESP_OK(rmt_driver_uninstall(RMT_TX_CHANNEL)); + TEST_ESP_OK(rmt_driver_uninstall(RMT_RX_CHANNEL)); +} + +TEST_CASE("RMT TX stop test", "[rmt][test_env=UT_T1_RMT]") +{ + int rx_channel = RMT_RX_CHANNEL; + rx_init(); + RingbufHandle_t rb = NULL; + rmt_get_ringbuf_handle(rx_channel, &rb); + rmt_rx_start(rx_channel, 1); + + vTaskDelay(10); + tx_init(); + int tx_channel = RMT_TX_CHANNEL; + int tx_num = RMT_TX_DATA_NUM; + + ESP_LOGI(TAG, "RMT TX DATA"); + size_t size = (sizeof(rmt_item32_t) * DATA_ITEM_NUM * tx_num); + rmt_item32_t* item = (rmt_item32_t*) malloc(size); + int item_num = DATA_ITEM_NUM * tx_num; + memset((void*) item, 0, size); + int offset = 0; + uint16_t cmd = 0x0; + uint16_t addr = 0x11; + + // send data + set_tx_data(tx_channel, cmd, addr, item_num, item, offset); + rmt_write_items(tx_channel, item, item_num, 0); + vTaskDelay(1000 / portTICK_PERIOD_MS); + rmt_tx_stop(tx_channel); + free(item); + + // receive data + uint16_t tmp = get_rx_data(rb); + TEST_ASSERT(tmp < 100); + + TEST_ESP_OK(rmt_driver_uninstall(RMT_TX_CHANNEL)); + TEST_ESP_OK(rmt_driver_uninstall(RMT_RX_CHANNEL)); +} diff --git a/components/driver/test/test_sigmadelta.c b/components/driver/test/test_sigmadelta.c new file mode 100644 index 0000000000..fa1088186c --- /dev/null +++ b/components/driver/test/test_sigmadelta.c @@ -0,0 +1,87 @@ +/* + * Sigamadelta Test: + * 1. basic configuration test + * 2. pin, duty, prescale test + */ +#include "unity.h" +#include "test_utils.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "driver/sigmadelta.h" + +TEST_CASE("SigmaDelta config test", "[sigma_delta]") +{ + sigmadelta_config_t sigmadelta_cfg = { + .channel = SIGMADELTA_CHANNEL_0, + .sigmadelta_prescale = 80, + .sigmadelta_duty = 45, + .sigmadelta_gpio = 4, + }; + TEST_ESP_OK(sigmadelta_config(&sigmadelta_cfg)); + + sigmadelta_cfg.channel = SIGMADELTA_CHANNEL_1; + TEST_ESP_OK(sigmadelta_config(&sigmadelta_cfg)); + + sigmadelta_cfg.channel = SIGMADELTA_CHANNEL_2; + TEST_ESP_OK(sigmadelta_config(&sigmadelta_cfg)); + + sigmadelta_cfg.channel = SIGMADELTA_CHANNEL_3; + TEST_ESP_OK(sigmadelta_config(&sigmadelta_cfg)); + + sigmadelta_cfg.channel = SIGMADELTA_CHANNEL_4; + TEST_ESP_OK(sigmadelta_config(&sigmadelta_cfg)); + + sigmadelta_cfg.channel = SIGMADELTA_CHANNEL_5; + TEST_ESP_OK(sigmadelta_config(&sigmadelta_cfg)); + + sigmadelta_cfg.channel = SIGMADELTA_CHANNEL_6; + TEST_ESP_OK(sigmadelta_config(&sigmadelta_cfg)); + + sigmadelta_cfg.channel = SIGMADELTA_CHANNEL_7; + TEST_ESP_OK(sigmadelta_config(&sigmadelta_cfg)); + + //ERROR PARAM + sigmadelta_cfg.channel = SIGMADELTA_CHANNEL_MAX; + TEST_ASSERT(sigmadelta_config(&sigmadelta_cfg) == ESP_ERR_INVALID_ARG); + +} + +// connect GPIO4 with LED positive pin, and the GND pin connect LED negative pin +// logic analyzer help also to see the wave form(more standard and accurate) +// can't test it in CI, ignore +TEST_CASE("SigmaDelta pin, duty, prescale set", "[sigma_delta][ignore]") +{ + sigmadelta_config_t sigmadelta_cfg = { + .channel = SIGMADELTA_CHANNEL_0, + .sigmadelta_prescale = 80, + .sigmadelta_duty = 0, + .sigmadelta_gpio = 4, + }; + TEST_ESP_OK(sigmadelta_config(&sigmadelta_cfg)); + + int8_t duty = 0; + int inc = 1; + for(int i=0; i<1000; i++) { + sigmadelta_set_duty(SIGMADELTA_CHANNEL_0, duty); + vTaskDelay(10 / portTICK_PERIOD_MS); + + duty += inc; + if (duty == 127 || duty == -127) { + inc = (-1) * inc; + } + } + + TEST_ESP_OK(sigmadelta_set_prescale(SIGMADELTA_CHANNEL_0, 200)); + for(int i=0; i<1000; i++) { + sigmadelta_set_duty(SIGMADELTA_CHANNEL_0, duty); + vTaskDelay(10 / portTICK_PERIOD_MS); + + duty += inc; + if (duty == 127 || duty == -127) { + inc = (-1) * inc; + } + } + + TEST_ESP_OK(sigmadelta_set_pin(SIGMADELTA_CHANNEL_0, 5)); + vTaskDelay(3000 / portTICK_PERIOD_MS); +} diff --git a/components/driver/test/test_spi_master.c b/components/driver/test/test_spi_master.c index da6d5a5961..5a7b490109 100644 --- a/components/driver/test/test_spi_master.c +++ b/components/driver/test/test_spi_master.c @@ -17,14 +17,42 @@ #include "driver/spi_master.h" #include "driver/spi_slave.h" #include "soc/dport_reg.h" -#include "soc/spi_reg.h" -#include "soc/spi_struct.h" #include "esp_heap_caps.h" #include "esp_log.h" +#include "soc/spi_periph.h" #include "freertos/ringbuf.h" +#include "soc/gpio_periph.h" const static char TAG[] = "test_spi"; +#define SPI_BUS_TEST_DEFAULT_CONFIG() {\ + .miso_io_num=PIN_NUM_MISO, \ + .mosi_io_num=PIN_NUM_MOSI,\ + .sclk_io_num=PIN_NUM_CLK,\ + .quadwp_io_num=-1,\ + .quadhd_io_num=-1\ +} + +#define SPI_DEVICE_TEST_DEFAULT_CONFIG() {\ + .clock_speed_hz=10*1000*1000,\ + .mode=0,\ + .spics_io_num=PIN_NUM_CS,\ + .queue_size=16,\ + .pre_cb=NULL, \ + .cs_ena_pretrans = 0,\ + .cs_ena_posttrans = 0,\ + .input_delay_ns = 62.5,\ +} + +#define FUNC_SPI 1 +#define FUNC_GPIO 2 + +void gpio_output_sel(uint32_t gpio_num, int func, uint32_t signal_idx) +{ + PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[gpio_num], func); + GPIO.func_out_sel_cfg[gpio_num].func_sel=signal_idx; +} + static void check_spi_pre_n_for(int clk, int pre, int n) { esp_err_t ret; @@ -231,7 +259,7 @@ TEST_CASE("SPI Master test, interaction of multiple devs", "[spi][ignore]") { .clock_speed_hz=1000000, .duty_cycle_pos=128, .mode=0, - .spics_io_num=23, + .spics_io_num=23, .queue_size=3, }; spi_device_handle_t handle1=setup_spi_bus(80000, true); @@ -263,30 +291,24 @@ TEST_CASE("SPI Master test, interaction of multiple devs", "[spi][ignore]") { destroy_spi_bus(handle1); } -#define NATIVE_SCLK 14 -#define NATIVE_MISO 12 -#define NATIVE_MOSI 13 -#define NATIVE_WP 2 -#define NATIVE_HD 4 - TEST_CASE("spi bus setting with different pin configs", "[spi]") { spi_bus_config_t cfg; uint32_t flags_o; uint32_t flags_expected; - - ESP_LOGI(TAG, "test 6 native output pins..."); + + ESP_LOGI(TAG, "test 6 iomux output pins..."); flags_expected = SPICOMMON_BUSFLAG_SCLK | SPICOMMON_BUSFLAG_MOSI | SPICOMMON_BUSFLAG_MISO | SPICOMMON_BUSFLAG_NATIVE_PINS | SPICOMMON_BUSFLAG_QUAD; - cfg = (spi_bus_config_t){.mosi_io_num = NATIVE_MOSI, .miso_io_num = NATIVE_MISO, .sclk_io_num = NATIVE_SCLK, .quadhd_io_num = NATIVE_HD, .quadwp_io_num = NATIVE_WP, + cfg = (spi_bus_config_t){.mosi_io_num = HSPI_IOMUX_PIN_NUM_MOSI, .miso_io_num = HSPI_IOMUX_PIN_NUM_MISO, .sclk_io_num = HSPI_IOMUX_PIN_NUM_CLK, .quadhd_io_num = HSPI_IOMUX_PIN_NUM_HD, .quadwp_io_num = HSPI_IOMUX_PIN_NUM_WP, .max_transfer_sz = 8, .flags = flags_expected}; TEST_ESP_OK(spicommon_bus_initialize_io(HSPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_MASTER, &flags_o)); TEST_ASSERT_EQUAL_HEX32( flags_expected, flags_o ); TEST_ESP_OK(spicommon_bus_initialize_io(HSPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_SLAVE, &flags_o)); TEST_ASSERT_EQUAL_HEX32( flags_expected, flags_o ); - ESP_LOGI(TAG, "test 4 native output pins..."); + ESP_LOGI(TAG, "test 4 iomux output pins..."); flags_expected = SPICOMMON_BUSFLAG_SCLK | SPICOMMON_BUSFLAG_MOSI | SPICOMMON_BUSFLAG_MISO | SPICOMMON_BUSFLAG_NATIVE_PINS | SPICOMMON_BUSFLAG_DUAL; - cfg = (spi_bus_config_t){.mosi_io_num = NATIVE_MOSI, .miso_io_num = NATIVE_MISO, .sclk_io_num = NATIVE_SCLK, .quadhd_io_num = -1, .quadwp_io_num = -1, + cfg = (spi_bus_config_t){.mosi_io_num = HSPI_IOMUX_PIN_NUM_MOSI, .miso_io_num = HSPI_IOMUX_PIN_NUM_MISO, .sclk_io_num = HSPI_IOMUX_PIN_NUM_CLK, .quadhd_io_num = -1, .quadwp_io_num = -1, .max_transfer_sz = 8, .flags = flags_expected}; TEST_ESP_OK(spicommon_bus_initialize_io(HSPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_MASTER, &flags_o)); TEST_ASSERT_EQUAL_HEX32( flags_expected, flags_o ); @@ -296,7 +318,7 @@ TEST_CASE("spi bus setting with different pin configs", "[spi]") ESP_LOGI(TAG, "test 6 output pins..."); flags_expected = SPICOMMON_BUSFLAG_SCLK | SPICOMMON_BUSFLAG_MOSI | SPICOMMON_BUSFLAG_MISO | SPICOMMON_BUSFLAG_QUAD; //swap MOSI and MISO - cfg = (spi_bus_config_t){.mosi_io_num = NATIVE_MISO, .miso_io_num = NATIVE_MOSI, .sclk_io_num = NATIVE_SCLK, .quadhd_io_num = NATIVE_HD, .quadwp_io_num = NATIVE_WP, + cfg = (spi_bus_config_t){.mosi_io_num = HSPI_IOMUX_PIN_NUM_MISO, .miso_io_num = HSPI_IOMUX_PIN_NUM_MOSI, .sclk_io_num = HSPI_IOMUX_PIN_NUM_CLK, .quadhd_io_num = HSPI_IOMUX_PIN_NUM_HD, .quadwp_io_num = HSPI_IOMUX_PIN_NUM_WP, .max_transfer_sz = 8, .flags = flags_expected}; TEST_ESP_OK(spicommon_bus_initialize_io(HSPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_MASTER, &flags_o)); TEST_ASSERT_EQUAL_HEX32( flags_expected, flags_o ); @@ -306,7 +328,7 @@ TEST_CASE("spi bus setting with different pin configs", "[spi]") ESP_LOGI(TAG, "test 4 output pins..."); flags_expected = SPICOMMON_BUSFLAG_SCLK | SPICOMMON_BUSFLAG_MOSI | SPICOMMON_BUSFLAG_MISO | SPICOMMON_BUSFLAG_DUAL; //swap MOSI and MISO - cfg = (spi_bus_config_t){.mosi_io_num = NATIVE_MISO, .miso_io_num = NATIVE_MOSI, .sclk_io_num = NATIVE_SCLK, .quadhd_io_num = -1, .quadwp_io_num = -1, + cfg = (spi_bus_config_t){.mosi_io_num = HSPI_IOMUX_PIN_NUM_MISO, .miso_io_num = HSPI_IOMUX_PIN_NUM_MOSI, .sclk_io_num = HSPI_IOMUX_PIN_NUM_CLK, .quadhd_io_num = -1, .quadwp_io_num = -1, .max_transfer_sz = 8, .flags = flags_expected}; TEST_ESP_OK(spicommon_bus_initialize_io(HSPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_MASTER, &flags_o)); TEST_ASSERT_EQUAL_HEX32( flags_expected, flags_o ); @@ -315,37 +337,37 @@ TEST_CASE("spi bus setting with different pin configs", "[spi]") ESP_LOGI(TAG, "test master 5 output pins and MOSI on input-only pin..."); flags_expected = SPICOMMON_BUSFLAG_SCLK | SPICOMMON_BUSFLAG_MOSI | SPICOMMON_BUSFLAG_MISO | SPICOMMON_BUSFLAG_WPHD; - cfg = (spi_bus_config_t){.mosi_io_num = NATIVE_MOSI, .miso_io_num = 34, .sclk_io_num = NATIVE_SCLK, .quadhd_io_num = NATIVE_HD, .quadwp_io_num = NATIVE_WP, + cfg = (spi_bus_config_t){.mosi_io_num = HSPI_IOMUX_PIN_NUM_MOSI, .miso_io_num = 34, .sclk_io_num = HSPI_IOMUX_PIN_NUM_CLK, .quadhd_io_num = HSPI_IOMUX_PIN_NUM_HD, .quadwp_io_num = HSPI_IOMUX_PIN_NUM_WP, .max_transfer_sz = 8, .flags = flags_expected}; TEST_ESP_OK(spicommon_bus_initialize_io(HSPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_MASTER, &flags_o)); TEST_ASSERT_EQUAL_HEX32( flags_expected, flags_o ); ESP_LOGI(TAG, "test slave 5 output pins and MISO on input-only pin..."); flags_expected = SPICOMMON_BUSFLAG_SCLK | SPICOMMON_BUSFLAG_MOSI | SPICOMMON_BUSFLAG_MISO | SPICOMMON_BUSFLAG_WPHD; - cfg = (spi_bus_config_t){.mosi_io_num = 34, .miso_io_num = NATIVE_MISO, .sclk_io_num = NATIVE_SCLK, .quadhd_io_num = NATIVE_HD, .quadwp_io_num = NATIVE_WP, - .max_transfer_sz = 8, .flags = flags_expected}; + cfg = (spi_bus_config_t){.mosi_io_num = 34, .miso_io_num = HSPI_IOMUX_PIN_NUM_MISO, .sclk_io_num = HSPI_IOMUX_PIN_NUM_CLK, .quadhd_io_num = HSPI_IOMUX_PIN_NUM_HD, .quadwp_io_num = HSPI_IOMUX_PIN_NUM_WP, + .max_transfer_sz = 8, .flags = flags_expected}; TEST_ESP_OK(spicommon_bus_initialize_io(HSPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_SLAVE, &flags_o)); TEST_ASSERT_EQUAL_HEX32( flags_expected, flags_o ); ESP_LOGI(TAG, "test master 3 output pins and MOSI on input-only pin..."); flags_expected = SPICOMMON_BUSFLAG_SCLK | SPICOMMON_BUSFLAG_MOSI | SPICOMMON_BUSFLAG_MISO; - cfg = (spi_bus_config_t){.mosi_io_num = NATIVE_MOSI, .miso_io_num = 34, .sclk_io_num = NATIVE_SCLK, .quadhd_io_num = -1, .quadwp_io_num = -1, + cfg = (spi_bus_config_t){.mosi_io_num = HSPI_IOMUX_PIN_NUM_MOSI, .miso_io_num = 34, .sclk_io_num = HSPI_IOMUX_PIN_NUM_CLK, .quadhd_io_num = -1, .quadwp_io_num = -1, .max_transfer_sz = 8, .flags = flags_expected}; TEST_ESP_OK(spicommon_bus_initialize_io(HSPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_MASTER, &flags_o)); TEST_ASSERT_EQUAL_HEX32( flags_expected, flags_o ); ESP_LOGI(TAG, "test slave 3 output pins and MISO on input-only pin..."); flags_expected = SPICOMMON_BUSFLAG_SCLK | SPICOMMON_BUSFLAG_MOSI | SPICOMMON_BUSFLAG_MISO; - cfg = (spi_bus_config_t){.mosi_io_num = 34, .miso_io_num = NATIVE_MISO, .sclk_io_num = NATIVE_SCLK, .quadhd_io_num = -1, .quadwp_io_num = -1, - .max_transfer_sz = 8, .flags = flags_expected}; + cfg = (spi_bus_config_t){.mosi_io_num = 34, .miso_io_num = HSPI_IOMUX_PIN_NUM_MISO, .sclk_io_num = HSPI_IOMUX_PIN_NUM_CLK, .quadhd_io_num = -1, .quadwp_io_num = -1, + .max_transfer_sz = 8, .flags = flags_expected}; TEST_ESP_OK(spicommon_bus_initialize_io(HSPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_SLAVE, &flags_o)); TEST_ASSERT_EQUAL_HEX32( flags_expected, flags_o ); ESP_LOGI(TAG, "check native flag for 6 output pins..."); flags_expected = SPICOMMON_BUSFLAG_NATIVE_PINS; //swap MOSI and MISO - cfg = (spi_bus_config_t){.mosi_io_num = NATIVE_MISO, .miso_io_num = NATIVE_MOSI, .sclk_io_num = NATIVE_SCLK, .quadhd_io_num = NATIVE_HD, .quadwp_io_num = NATIVE_WP, + cfg = (spi_bus_config_t){.mosi_io_num = HSPI_IOMUX_PIN_NUM_MISO, .miso_io_num = HSPI_IOMUX_PIN_NUM_MOSI, .sclk_io_num = HSPI_IOMUX_PIN_NUM_CLK, .quadhd_io_num = HSPI_IOMUX_PIN_NUM_HD, .quadwp_io_num = HSPI_IOMUX_PIN_NUM_WP, .max_transfer_sz = 8, .flags = flags_expected}; TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, spicommon_bus_initialize_io(HSPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_MASTER, &flags_o)); TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, spicommon_bus_initialize_io(HSPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_SLAVE, &flags_o)); @@ -353,61 +375,61 @@ TEST_CASE("spi bus setting with different pin configs", "[spi]") ESP_LOGI(TAG, "check native flag for 4 output pins..."); flags_expected = SPICOMMON_BUSFLAG_NATIVE_PINS; //swap MOSI and MISO - cfg = (spi_bus_config_t){.mosi_io_num = NATIVE_MISO, .miso_io_num = NATIVE_MOSI, .sclk_io_num = NATIVE_SCLK, .quadhd_io_num = -1, .quadwp_io_num = -1, + cfg = (spi_bus_config_t){.mosi_io_num = HSPI_IOMUX_PIN_NUM_MISO, .miso_io_num = HSPI_IOMUX_PIN_NUM_MOSI, .sclk_io_num = HSPI_IOMUX_PIN_NUM_CLK, .quadhd_io_num = -1, .quadwp_io_num = -1, .max_transfer_sz = 8, .flags = flags_expected}; TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, spicommon_bus_initialize_io(HSPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_MASTER, &flags_o)); TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, spicommon_bus_initialize_io(HSPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_SLAVE, &flags_o)); ESP_LOGI(TAG, "check dual flag for master 5 output pins and MISO/MOSI on input-only pin..."); flags_expected = SPICOMMON_BUSFLAG_DUAL; - cfg = (spi_bus_config_t){.mosi_io_num = NATIVE_MOSI, .miso_io_num = 34, .sclk_io_num = NATIVE_SCLK, .quadhd_io_num = NATIVE_HD, .quadwp_io_num = NATIVE_WP, + cfg = (spi_bus_config_t){.mosi_io_num = HSPI_IOMUX_PIN_NUM_MOSI, .miso_io_num = 34, .sclk_io_num = HSPI_IOMUX_PIN_NUM_CLK, .quadhd_io_num = HSPI_IOMUX_PIN_NUM_HD, .quadwp_io_num = HSPI_IOMUX_PIN_NUM_WP, .max_transfer_sz = 8, .flags = flags_expected}; TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, spicommon_bus_initialize_io(HSPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_MASTER, &flags_o)); TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, spicommon_bus_initialize_io(HSPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_SLAVE, &flags_o)); - cfg = (spi_bus_config_t){.mosi_io_num = 34, .miso_io_num = NATIVE_MISO, .sclk_io_num = NATIVE_SCLK, .quadhd_io_num = NATIVE_HD, .quadwp_io_num = NATIVE_WP, + cfg = (spi_bus_config_t){.mosi_io_num = 34, .miso_io_num = HSPI_IOMUX_PIN_NUM_MISO, .sclk_io_num = HSPI_IOMUX_PIN_NUM_CLK, .quadhd_io_num = HSPI_IOMUX_PIN_NUM_HD, .quadwp_io_num = HSPI_IOMUX_PIN_NUM_WP, .max_transfer_sz = 8, .flags = flags_expected}; TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, spicommon_bus_initialize_io(HSPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_MASTER, &flags_o)); TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, spicommon_bus_initialize_io(HSPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_SLAVE, &flags_o)); ESP_LOGI(TAG, "check dual flag for master 3 output pins and MISO/MOSI on input-only pin..."); flags_expected = SPICOMMON_BUSFLAG_DUAL; - cfg = (spi_bus_config_t){.mosi_io_num = NATIVE_MOSI, .miso_io_num = 34, .sclk_io_num = NATIVE_SCLK, .quadhd_io_num = -1, .quadwp_io_num = -1, + cfg = (spi_bus_config_t){.mosi_io_num = HSPI_IOMUX_PIN_NUM_MOSI, .miso_io_num = 34, .sclk_io_num = HSPI_IOMUX_PIN_NUM_CLK, .quadhd_io_num = -1, .quadwp_io_num = -1, .max_transfer_sz = 8, .flags = flags_expected}; TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, spicommon_bus_initialize_io(HSPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_MASTER, &flags_o)); TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, spicommon_bus_initialize_io(HSPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_SLAVE, &flags_o)); - cfg = (spi_bus_config_t){.mosi_io_num = 34, .miso_io_num = NATIVE_MISO, .sclk_io_num = NATIVE_SCLK, .quadhd_io_num = -1, .quadwp_io_num = -1, + cfg = (spi_bus_config_t){.mosi_io_num = 34, .miso_io_num = HSPI_IOMUX_PIN_NUM_MISO, .sclk_io_num = HSPI_IOMUX_PIN_NUM_CLK, .quadhd_io_num = -1, .quadwp_io_num = -1, .max_transfer_sz = 8, .flags = flags_expected}; TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, spicommon_bus_initialize_io(HSPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_MASTER, &flags_o)); TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, spicommon_bus_initialize_io(HSPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_SLAVE, &flags_o)); ESP_LOGI(TAG, "check sclk flag..."); flags_expected = SPICOMMON_BUSFLAG_SCLK; - cfg = (spi_bus_config_t){.mosi_io_num = NATIVE_MOSI, .miso_io_num = NATIVE_MISO, .sclk_io_num = -1, .quadhd_io_num = NATIVE_HD, .quadwp_io_num = NATIVE_WP, + cfg = (spi_bus_config_t){.mosi_io_num = HSPI_IOMUX_PIN_NUM_MOSI, .miso_io_num = HSPI_IOMUX_PIN_NUM_MISO, .sclk_io_num = -1, .quadhd_io_num = HSPI_IOMUX_PIN_NUM_HD, .quadwp_io_num = HSPI_IOMUX_PIN_NUM_WP, .max_transfer_sz = 8, .flags = flags_expected}; TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, spicommon_bus_initialize_io(HSPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_MASTER, &flags_o)); TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, spicommon_bus_initialize_io(HSPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_SLAVE, &flags_o)); - + ESP_LOGI(TAG, "check mosi flag..."); flags_expected = SPICOMMON_BUSFLAG_MOSI; - cfg = (spi_bus_config_t){.mosi_io_num = -1, .miso_io_num = NATIVE_MISO, .sclk_io_num = NATIVE_SCLK, .quadhd_io_num = NATIVE_HD, .quadwp_io_num = NATIVE_WP, + cfg = (spi_bus_config_t){.mosi_io_num = -1, .miso_io_num = HSPI_IOMUX_PIN_NUM_MISO, .sclk_io_num = HSPI_IOMUX_PIN_NUM_CLK, .quadhd_io_num = HSPI_IOMUX_PIN_NUM_HD, .quadwp_io_num = HSPI_IOMUX_PIN_NUM_WP, .max_transfer_sz = 8, .flags = flags_expected}; TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, spicommon_bus_initialize_io(HSPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_MASTER, &flags_o)); TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, spicommon_bus_initialize_io(HSPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_SLAVE, &flags_o)); - + ESP_LOGI(TAG, "check miso flag..."); flags_expected = SPICOMMON_BUSFLAG_MISO; - cfg = (spi_bus_config_t){.mosi_io_num = NATIVE_MOSI, .miso_io_num = -1, .sclk_io_num = NATIVE_SCLK, .quadhd_io_num = NATIVE_HD, .quadwp_io_num = NATIVE_WP, + cfg = (spi_bus_config_t){.mosi_io_num = HSPI_IOMUX_PIN_NUM_MOSI, .miso_io_num = -1, .sclk_io_num = HSPI_IOMUX_PIN_NUM_CLK, .quadhd_io_num = HSPI_IOMUX_PIN_NUM_HD, .quadwp_io_num = HSPI_IOMUX_PIN_NUM_WP, .max_transfer_sz = 8, .flags = flags_expected}; TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, spicommon_bus_initialize_io(HSPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_MASTER, &flags_o)); TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, spicommon_bus_initialize_io(HSPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_SLAVE, &flags_o)); ESP_LOGI(TAG, "check quad flag..."); flags_expected = SPICOMMON_BUSFLAG_QUAD; - cfg = (spi_bus_config_t){.mosi_io_num = NATIVE_MOSI, .miso_io_num = NATIVE_MISO, .sclk_io_num = NATIVE_SCLK, .quadhd_io_num = -1, .quadwp_io_num = NATIVE_WP, + cfg = (spi_bus_config_t){.mosi_io_num = HSPI_IOMUX_PIN_NUM_MOSI, .miso_io_num = HSPI_IOMUX_PIN_NUM_MISO, .sclk_io_num = HSPI_IOMUX_PIN_NUM_CLK, .quadhd_io_num = -1, .quadwp_io_num = HSPI_IOMUX_PIN_NUM_WP, .max_transfer_sz = 8, .flags = flags_expected}; TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, spicommon_bus_initialize_io(HSPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_MASTER, &flags_o)); TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, spicommon_bus_initialize_io(HSPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_SLAVE, &flags_o)); - cfg = (spi_bus_config_t){.mosi_io_num = NATIVE_MOSI, .miso_io_num = NATIVE_MISO, .sclk_io_num = NATIVE_SCLK, .quadhd_io_num = NATIVE_HD, .quadwp_io_num = -1, + cfg = (spi_bus_config_t){.mosi_io_num = HSPI_IOMUX_PIN_NUM_MOSI, .miso_io_num = HSPI_IOMUX_PIN_NUM_MISO, .sclk_io_num = HSPI_IOMUX_PIN_NUM_CLK, .quadhd_io_num = HSPI_IOMUX_PIN_NUM_HD, .quadwp_io_num = -1, .max_transfer_sz = 8, .flags = flags_expected}; TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, spicommon_bus_initialize_io(HSPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_MASTER, &flags_o)); TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, spicommon_bus_initialize_io(HSPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_SLAVE, &flags_o)); @@ -474,14 +496,21 @@ TEST_CASE("SPI Master no response when switch from host1 (HSPI) to host2 (VSPI)" } IRAM_ATTR static uint32_t data_iram[320]; -DRAM_ATTR static uint32_t data_dram[320]; +DRAM_ATTR static uint32_t data_dram[320]={0}; //force to place in code area. static const uint32_t data_drom[320] = {0}; -#define PIN_NUM_MISO 25 -#define PIN_NUM_MOSI 23 -#define PIN_NUM_CLK 19 -#define PIN_NUM_CS 22 +#if 1 //HSPI +#define PIN_NUM_MISO HSPI_IOMUX_PIN_NUM_MISO +#define PIN_NUM_MOSI HSPI_IOMUX_PIN_NUM_MOSI +#define PIN_NUM_CLK HSPI_IOMUX_PIN_NUM_CLK +#define PIN_NUM_CS HSPI_IOMUX_PIN_NUM_CS +#elif 1 //VSPI +#define PIN_NUM_MISO VSPI_IOMUX_PIN_NUM_MISO +#define PIN_NUM_MOSI VSPI_IOMUX_PIN_NUM_MOSI +#define PIN_NUM_CLK VSPI_IOMUX_PIN_NUM_CLK +#define PIN_NUM_CS VSPI_IOMUX_PIN_NUM_CS +#endif #define PIN_NUM_DC 21 #define PIN_NUM_RST 18 @@ -541,7 +570,7 @@ TEST_CASE("SPI Master DMA test, TX and RX in different regions", "[spi]") trans[4].rxlength = 8*4; trans[4].tx_buffer = data_drom; trans[4].flags = SPI_TRANS_USE_RXDATA; - + trans[5].length = 8*4; trans[5].flags = SPI_TRANS_USE_RXDATA | SPI_TRANS_USE_TXDATA; @@ -562,13 +591,6 @@ TEST_CASE("SPI Master DMA test, TX and RX in different regions", "[spi]") TEST_ASSERT(spi_bus_free(HSPI_HOST) == ESP_OK); } - -static inline void int_connect( uint32_t gpio, uint32_t sigo, uint32_t sigi ) -{ - gpio_matrix_out( gpio, sigo, false, false ); - gpio_matrix_in( gpio, sigi, false ); -} - //this part tests 3 DMA issues in master mode, full-duplex in IDF2.1 // 1. RX buffer not aligned (start and end) // 2. not setting rx_buffer @@ -581,7 +603,7 @@ TEST_CASE("SPI Master DMA test: length, start, not aligned", "[spi]") esp_err_t ret; spi_device_handle_t spi; spi_bus_config_t buscfg={ - .miso_io_num=PIN_NUM_MISO, + .miso_io_num=PIN_NUM_MOSI, .mosi_io_num=PIN_NUM_MOSI, .sclk_io_num=PIN_NUM_CLK, .quadwp_io_num=-1, @@ -592,7 +614,7 @@ TEST_CASE("SPI Master DMA test: length, start, not aligned", "[spi]") .mode=0, //SPI mode 0 .spics_io_num=PIN_NUM_CS, //CS pin .queue_size=7, //We want to be able to queue 7 transactions at a time - .pre_cb=NULL, + .pre_cb=NULL, }; //Initialize the SPI bus ret=spi_bus_initialize(HSPI_HOST, &buscfg, 1); @@ -601,18 +623,18 @@ TEST_CASE("SPI Master DMA test: length, start, not aligned", "[spi]") ret=spi_bus_add_device(HSPI_HOST, &devcfg, &spi); TEST_ASSERT(ret==ESP_OK); - //do internal connection - int_connect( PIN_NUM_MOSI, HSPID_OUT_IDX, HSPIQ_IN_IDX ); + //connect MOSI to two devices breaks the output, fix it. + gpio_output_sel(buscfg.mosi_io_num, FUNC_GPIO, HSPID_OUT_IDX); memset(rx_buf, 0x66, 320); - + for ( int i = 0; i < 8; i ++ ) { memset( rx_buf, 0x66, sizeof(rx_buf)); spi_transaction_t t = {}; t.length = 8*(i+1); t.rxlength = 0; - t.tx_buffer = tx_buf+2*i; + t.tx_buffer = tx_buf+2*i; t.rx_buffer = rx_buf + i; if ( i == 1 ) { @@ -621,7 +643,7 @@ TEST_CASE("SPI Master DMA test: length, start, not aligned", "[spi]") } else if ( i == 2 ) { //test rx length != tx_length t.rxlength = t.length - 8; - } + } spi_device_transmit( spi, &t ); for( int i = 0; i < 16; i ++ ) { @@ -633,11 +655,11 @@ TEST_CASE("SPI Master DMA test: length, start, not aligned", "[spi]") // no rx, skip check } else if ( i == 2 ) { //test rx length = tx length-1 - TEST_ASSERT( memcmp(t.tx_buffer, t.rx_buffer, t.length/8-1)==0 ); + TEST_ASSERT_EQUAL_HEX8_ARRAY(t.tx_buffer, t.rx_buffer, t.length/8-1 ); } else { //normal check - TEST_ASSERT( memcmp(t.tx_buffer, t.rx_buffer, t.length/8)==0 ); - } + TEST_ASSERT_EQUAL_HEX8_ARRAY(t.tx_buffer, t.rx_buffer, t.length/8 ); + } } TEST_ASSERT(spi_bus_remove_device(spi) == ESP_OK); @@ -649,53 +671,25 @@ static const char SLAVE_TAG[] = "test_slave"; DRAM_ATTR static uint8_t master_send[] = {0x93, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0xaa, 0xcc, 0xff, 0xee, 0x55, 0x77, 0x88, 0x43}; DRAM_ATTR static uint8_t slave_send[] = { 0xaa, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, 0x13, 0x57, 0x9b, 0xdf, 0x24, 0x68, 0xac, 0xe0 }; -static void master_init( spi_device_handle_t* spi, int mode, uint32_t speed) + +static void master_deinit(spi_device_handle_t spi) { - esp_err_t ret; - spi_bus_config_t buscfg={ - .miso_io_num=PIN_NUM_MISO, - .mosi_io_num=PIN_NUM_MOSI, - .sclk_io_num=PIN_NUM_CLK, - .quadwp_io_num=-1, - .quadhd_io_num=-1 - }; - spi_device_interface_config_t devcfg={ - .clock_speed_hz=speed, //currently only up to 4MHz for internel connect - .mode=mode, //SPI mode 0 - .spics_io_num=PIN_NUM_CS, //CS pin - .queue_size=16, //We want to be able to queue 7 transactions at a time - .pre_cb=NULL, - .cs_ena_pretrans = 0, - }; - //Initialize the SPI bus - ret=spi_bus_initialize(HSPI_HOST, &buscfg, 1); - TEST_ASSERT(ret==ESP_OK); - //Attach the LCD to the SPI bus - ret=spi_bus_add_device(HSPI_HOST, &devcfg, spi); - TEST_ASSERT(ret==ESP_OK); + TEST_ESP_OK( spi_bus_remove_device(spi) ); + TEST_ESP_OK( spi_bus_free(HSPI_HOST) ); } -static void slave_init(int mode, int dma_chan) +#define SPI_SLAVE_TEST_DEFAULT_CONFIG() {\ + .mode=0,\ + .spics_io_num=PIN_NUM_CS,\ + .queue_size=3,\ + .flags=0,\ +} + +static void slave_pull_up(const spi_bus_config_t* cfg, int spics_io_num) { - //Configuration for the SPI bus - spi_bus_config_t buscfg={ - .mosi_io_num=PIN_NUM_MOSI, - .miso_io_num=PIN_NUM_MISO, - .sclk_io_num=PIN_NUM_CLK - }; - //Configuration for the SPI slave interface - spi_slave_interface_config_t slvcfg={ - .mode=mode, - .spics_io_num=PIN_NUM_CS, - .queue_size=3, - .flags=0, - }; - //Enable pull-ups on SPI lines so we don't detect rogue pulses when no master is connected. - gpio_set_pull_mode(PIN_NUM_MOSI, GPIO_PULLUP_ONLY); - gpio_set_pull_mode(PIN_NUM_CLK, GPIO_PULLUP_ONLY); - gpio_set_pull_mode(PIN_NUM_CS, GPIO_PULLUP_ONLY); - //Initialize SPI slave interface - TEST_ESP_OK( spi_slave_initialize(VSPI_HOST, &buscfg, &slvcfg, dma_chan) ); + gpio_set_pull_mode(cfg->mosi_io_num, GPIO_PULLUP_ENABLE); + gpio_set_pull_mode(cfg->sclk_io_num, GPIO_PULLUP_ENABLE); + gpio_set_pull_mode(spics_io_num, GPIO_PULLUP_ENABLE); } typedef struct { @@ -705,10 +699,12 @@ typedef struct { typedef struct { uint32_t len; + uint8_t* tx_start; uint8_t data[1]; } slave_rxdata_t; typedef struct { + spi_host_device_t spi; RingbufHandle_t data_received; QueueHandle_t data_to_send; } spi_slave_task_context_t; @@ -723,6 +719,7 @@ esp_err_t init_slave_context(spi_slave_task_context_t *context) if ( context->data_received == NULL ) { return ESP_ERR_NO_MEM; } + context->spi=VSPI_HOST; return ESP_OK; } @@ -736,12 +733,16 @@ void deinit_slave_context(spi_slave_task_context_t *context) context->data_received = NULL; } +/* The task requires a queue and a ringbuf, which should be initialized before task starts. + Send ``slave_txdata_t`` to the queue to make the task send data; + the task returns data got to the ringbuf, which should have sufficient size. +*/ static void task_slave(void* arg) { spi_slave_task_context_t* context = (spi_slave_task_context_t*) arg; QueueHandle_t queue = context->data_to_send; RingbufHandle_t ringbuf = context->data_received; - uint8_t recvbuf[320+4]; + uint8_t recvbuf[320+8]; slave_txdata_t txdata; ESP_LOGI( SLAVE_TAG, "slave up" ); @@ -749,18 +750,19 @@ static void task_slave(void* arg) while( 1 ) { xQueueReceive( queue, &txdata, portMAX_DELAY ); - ESP_LOGI( "test", "received: %p", txdata.start ); + ESP_LOGI( "test", "to send: %p", txdata.start ); spi_slave_transaction_t t = {}; t.length = txdata.len; t.tx_buffer = txdata.start; - t.rx_buffer = recvbuf+4; + t.rx_buffer = recvbuf+8; //loop until trans_len != 0 to skip glitches do { - TEST_ESP_OK( spi_slave_transmit( VSPI_HOST, &t, portMAX_DELAY ) ); + TEST_ESP_OK( spi_slave_transmit( context->spi, &t, portMAX_DELAY ) ); } while ( t.trans_len == 0 ); - *(uint32_t*)recvbuf = t.trans_len; + memcpy(recvbuf, &t.trans_len, sizeof(uint32_t)); + *(uint8_t**)(recvbuf+4) = txdata.start; ESP_LOGI( SLAVE_TAG, "received: %d", t.trans_len ); - xRingbufferSend( ringbuf, recvbuf, 4+(t.trans_len+7)/8, portMAX_DELAY ); + xRingbufferSend( ringbuf, recvbuf, 8+(t.trans_len+7)/8, portMAX_DELAY ); } } @@ -775,16 +777,33 @@ TEST_CASE("SPI master variable cmd & addr test","[spi]") TEST_ASSERT( err == ESP_OK ); spi_device_handle_t spi; - //initial master, mode 0, 1MHz - master_init( &spi, 0, 1*1000*1000 ); - //initial slave, mode 0, no dma - slave_init(0, 0); - //do internal connection - int_connect( PIN_NUM_MOSI, HSPID_OUT_IDX, VSPIQ_IN_IDX ); - int_connect( PIN_NUM_MISO, VSPIQ_OUT_IDX, HSPID_IN_IDX ); - int_connect( PIN_NUM_CS, HSPICS0_OUT_IDX, VSPICS0_IN_IDX ); - int_connect( PIN_NUM_CLK, HSPICLK_OUT_IDX, VSPICLK_IN_IDX ); + //initial master, mode 0, 1MHz + spi_bus_config_t buscfg=SPI_BUS_TEST_DEFAULT_CONFIG(); + TEST_ESP_OK(spi_bus_initialize(HSPI_HOST, &buscfg, 1)); + spi_device_interface_config_t devcfg=SPI_DEVICE_TEST_DEFAULT_CONFIG(); + devcfg.clock_speed_hz = 1*1000*1000; //currently only up to 4MHz for internel connect + devcfg.mode = 0; + devcfg.cs_ena_posttrans = 2; + TEST_ESP_OK(spi_bus_add_device(HSPI_HOST, &devcfg, &spi)); + + //initial slave, mode 0, no dma + int dma_chan = 0; + int slave_mode = 0; + spi_bus_config_t slv_buscfg=SPI_BUS_TEST_DEFAULT_CONFIG(); + spi_slave_interface_config_t slvcfg=SPI_SLAVE_TEST_DEFAULT_CONFIG(); + slvcfg.mode = slave_mode; + //Enable pull-ups on SPI lines so we don't detect rogue pulses when no master is connected. + slave_pull_up(&buscfg, slvcfg.spics_io_num); + //Initialize SPI slave interface + TEST_ESP_OK( spi_slave_initialize(VSPI_HOST, &slv_buscfg, &slvcfg, dma_chan) ); + + + //connecting pins to two peripherals breaks the output, fix it. + gpio_output_sel(PIN_NUM_MOSI, FUNC_GPIO, HSPID_OUT_IDX); + gpio_output_sel(PIN_NUM_MISO, FUNC_GPIO, VSPIQ_OUT_IDX); + gpio_output_sel(PIN_NUM_CS, FUNC_GPIO, HSPICS0_OUT_IDX); + gpio_output_sel(PIN_NUM_CLK, FUNC_GPIO, HSPICLK_OUT_IDX); TaskHandle_t handle_slave; xTaskCreate( task_slave, "spi_slave", 4096, &slave_context, 0, &handle_slave); @@ -871,7 +890,7 @@ TEST_CASE("SPI master variable cmd & addr test","[spi]") handle_slave = 0; deinit_slave_context(&slave_context); - + TEST_ASSERT(spi_slave_free(VSPI_HOST) == ESP_OK); TEST_ASSERT(spi_bus_remove_device(spi) == ESP_OK); @@ -879,7 +898,355 @@ TEST_CASE("SPI master variable cmd & addr test","[spi]") ESP_LOGI(MASTER_TAG, "test passed."); } +/******************************************************************************** + * Test Timing By Internal Connections + ********************************************************************************/ +typedef enum { + FULL_DUPLEX = 0, + HALF_DUPLEX_MISO = 1, + HALF_DUPLEX_MOSI = 2, +} spi_dup_t; +static int timing_speed_array[]={/**/ + SPI_MASTER_FREQ_8M , + SPI_MASTER_FREQ_9M , + SPI_MASTER_FREQ_10M, + SPI_MASTER_FREQ_11M, + SPI_MASTER_FREQ_13M, + SPI_MASTER_FREQ_16M, + SPI_MASTER_FREQ_20M, + SPI_MASTER_FREQ_26M, + SPI_MASTER_FREQ_40M, + SPI_MASTER_FREQ_80M, +}; + +typedef struct { + uint8_t master_rxbuf[320]; + spi_transaction_t master_trans[16]; + TaskHandle_t handle_slave; + spi_slave_task_context_t slave_context; + slave_txdata_t slave_trans[16]; +} timing_context_t; + +void master_print_data(spi_transaction_t *t, spi_dup_t dup) +{ + if (t->tx_buffer) { + ESP_LOG_BUFFER_HEX( "master tx", t->tx_buffer, t->length/8 ); + } else { + ESP_LOGI( "master tx", "no data" ); + } + + int rxlength; + if (dup!=HALF_DUPLEX_MISO) { + rxlength = t->length/8; + } else { + rxlength = t->rxlength/8; + } + if (t->rx_buffer) { + ESP_LOG_BUFFER_HEX( "master rx", t->rx_buffer, rxlength ); + } else { + ESP_LOGI( "master rx", "no data" ); + } +} + +void slave_print_data(slave_rxdata_t *t) +{ + int rcv_len = (t->len+7)/8; + ESP_LOGI(SLAVE_TAG, "trans_len: %d", t->len); + ESP_LOG_BUFFER_HEX( "slave tx", t->tx_start, rcv_len); + ESP_LOG_BUFFER_HEX( "slave rx", t->data, rcv_len); +} + +esp_err_t check_data(spi_transaction_t *t, spi_dup_t dup, slave_rxdata_t *slave_t) +{ + int length; + if (dup!=HALF_DUPLEX_MISO) { + length = t->length; + } else { + length = t->rxlength; + } + TEST_ASSERT(length!=0); + + //currently the rcv_len can be in range of [t->length-1, t->length+3] + uint32_t rcv_len = slave_t->len; + TEST_ASSERT(rcv_len >= length-1 && rcv_len <= length+3); + + //the timing speed is temporarily only for master + if (dup!=HALF_DUPLEX_MISO) { +// TEST_ASSERT_EQUAL_HEX8_ARRAY(t->tx_buffer, slave_t->data, (t->length+7)/8); + } + if (dup!=HALF_DUPLEX_MOSI) { + TEST_ASSERT_EQUAL_HEX8_ARRAY(slave_t->tx_start, t->rx_buffer, (length+7)/8); + } + return ESP_OK; +} + +static void timing_init_transactions(spi_dup_t dup, timing_context_t* context) +{ + spi_transaction_t* trans = context->master_trans; + uint8_t *rx_buf_ptr = context->master_rxbuf; + if (dup==HALF_DUPLEX_MISO) { + for (int i = 0; i < 8; i++ ) { + trans[i] = (spi_transaction_t) { + .flags = 0, + .rxlength = 8*(i*2+1), + .rx_buffer = rx_buf_ptr, + }; + rx_buf_ptr += ((context->master_trans[i].rxlength + 31)/8)&(~3); + } + } else if (dup==HALF_DUPLEX_MOSI) { + for (int i = 0; i < 8; i++ ) { + trans[i] = (spi_transaction_t) { + .flags = 0, + .length = 8*(i*2+1), + .tx_buffer = master_send+i, + }; + } + } else { + for (int i = 0; i < 8; i++ ) { + trans[i] = (spi_transaction_t) { + .flags = 0, + .length = 8*(i*2+1), + .tx_buffer = master_send+i, + .rx_buffer = rx_buf_ptr, + }; + rx_buf_ptr += ((context->master_trans[i].length + 31)/8)&(~3); + } + } + //prepare slave tx data + for (int i = 0; i < 8; i ++) { + context->slave_trans[i] = (slave_txdata_t) { + .start = slave_send + 4*(i%3), + .len = 256, + }; + } +} + +typedef struct { + const char cfg_name[30]; + /*The test work till the frequency below, + *set the frequency to higher and remove checks in the driver to know how fast the system can run. + */ + int freq_limit; + spi_dup_t dup; + bool master_iomux; + bool slave_iomux; + int slave_tv_ns; +} test_timing_config_t; + +#define ESP_SPI_SLAVE_TV (12.5*3) +#define GPIO_DELAY (12.5*2) +#define SAMPLE_DELAY 12.5 + +#define TV_INT_CONNECT_GPIO (ESP_SPI_SLAVE_TV+GPIO_DELAY) +#define TV_INT_CONNECT (ESP_SPI_SLAVE_TV) +#define TV_WITH_ESP_SLAVE_GPIO (ESP_SPI_SLAVE_TV+SAMPLE_DELAY+GPIO_DELAY) +#define TV_WITH_ESP_SLAVE (ESP_SPI_SLAVE_TV+SAMPLE_DELAY) + +//currently ESP32 slave only supports up to 20MHz, but 40MHz on the same board +#define ESP_SPI_SLAVE_MAX_FREQ SPI_MASTER_FREQ_20M +#define ESP_SPI_SLAVE_MAX_FREQ_SYNC SPI_MASTER_FREQ_40M + + +static test_timing_config_t timing_master_conf_t[] = {/**/ + { .cfg_name = "FULL_DUP, MASTER IOMUX", + .freq_limit = SPI_MASTER_FREQ_13M, + .dup = FULL_DUPLEX, + .master_iomux = true, + .slave_iomux = false, + .slave_tv_ns = TV_INT_CONNECT_GPIO, + }, + { .cfg_name = "FULL_DUP, SLAVE IOMUX", + .freq_limit = SPI_MASTER_FREQ_13M, + .dup = FULL_DUPLEX, + .master_iomux = false, + .slave_iomux = true, + .slave_tv_ns = TV_INT_CONNECT, + }, + { .cfg_name = "FULL_DUP, BOTH GPIO", + .freq_limit = SPI_MASTER_FREQ_10M, + .dup = FULL_DUPLEX, + .master_iomux = false, + .slave_iomux = false, + .slave_tv_ns = TV_INT_CONNECT_GPIO, + }, + { .cfg_name = "HALF_DUP, MASTER IOMUX", + .freq_limit = ESP_SPI_SLAVE_MAX_FREQ_SYNC, + .dup = HALF_DUPLEX_MISO, + .master_iomux = true, + .slave_iomux = false, + .slave_tv_ns = TV_INT_CONNECT_GPIO, + }, + { .cfg_name = "HALF_DUP, SLAVE IOMUX", + .freq_limit = ESP_SPI_SLAVE_MAX_FREQ_SYNC, + .dup = HALF_DUPLEX_MISO, + .master_iomux = false, + .slave_iomux = true, + .slave_tv_ns = TV_INT_CONNECT, + }, + { .cfg_name = "HALF_DUP, BOTH GPIO", + .freq_limit = ESP_SPI_SLAVE_MAX_FREQ_SYNC, + .dup = HALF_DUPLEX_MISO, + .master_iomux = false, + .slave_iomux = false, + .slave_tv_ns = TV_INT_CONNECT_GPIO, + }, + { .cfg_name = "MOSI_DUP, MASTER IOMUX", + .freq_limit = ESP_SPI_SLAVE_MAX_FREQ_SYNC, + .dup = HALF_DUPLEX_MOSI, + .master_iomux = true, + .slave_iomux = false, + .slave_tv_ns = TV_INT_CONNECT_GPIO, + }, + { .cfg_name = "MOSI_DUP, SLAVE IOMUX", + .freq_limit = ESP_SPI_SLAVE_MAX_FREQ_SYNC, + .dup = HALF_DUPLEX_MOSI, + .master_iomux = false, + .slave_iomux = true, + .slave_tv_ns = TV_INT_CONNECT, + }, + { .cfg_name = "MOSI_DUP, BOTH GPIO", + .freq_limit = ESP_SPI_SLAVE_MAX_FREQ_SYNC, + .dup = HALF_DUPLEX_MOSI, + .master_iomux = false, + .slave_iomux = false, + .slave_tv_ns = TV_INT_CONNECT_GPIO, + }, +}; + +//this case currently only checks master read +TEST_CASE("test timing_master","[spi][timeout=120]") +{ + timing_context_t context; + + //Enable pull-ups on SPI lines so we don't detect rogue pulses when no master is connected. + //slave_pull_up(&slv_buscfg, slvcfg.spics_io_num); + + context.slave_context = (spi_slave_task_context_t){}; + esp_err_t err = init_slave_context( &context.slave_context ); + TEST_ASSERT( err == ESP_OK ); + + xTaskCreate( task_slave, "spi_slave", 4096, &context.slave_context, 0, &context.handle_slave); + + const int test_size = sizeof(timing_master_conf_t)/sizeof(test_timing_config_t); + for (int i = 0; i < test_size; i++) { + test_timing_config_t* conf = &timing_master_conf_t[i]; + + spi_device_handle_t spi; + + timing_init_transactions(conf->dup, &context); + + ESP_LOGI(MASTER_TAG, "****************** %s ***************", conf->cfg_name); + for (int j=0; j conf->freq_limit) break; + ESP_LOGI(MASTER_TAG, "======> %dk", timing_speed_array[j]/1000); + + //master config + const int master_mode = 0; + spi_bus_config_t buscfg=SPI_BUS_TEST_DEFAULT_CONFIG(); + spi_device_interface_config_t devcfg=SPI_DEVICE_TEST_DEFAULT_CONFIG(); + devcfg.mode = master_mode; + if (conf->dup==HALF_DUPLEX_MISO||conf->dup==HALF_DUPLEX_MOSI) { + devcfg.cs_ena_pretrans = 20; + devcfg.flags |= SPI_DEVICE_HALFDUPLEX; + } else { + devcfg.cs_ena_pretrans = 1; + } + devcfg.cs_ena_posttrans = 20; + devcfg.input_delay_ns = conf->slave_tv_ns; + devcfg.clock_speed_hz = timing_speed_array[j]; + + //slave config + int slave_mode = 0; + spi_slave_interface_config_t slvcfg=SPI_SLAVE_TEST_DEFAULT_CONFIG(); + slvcfg.mode = slave_mode; + + //pin config & initialize + //we can't have two sets of iomux pins on the same pins + assert(!conf->master_iomux || !conf->slave_iomux); + if (conf->slave_iomux) { + //only in this case, use VSPI iomux pins + buscfg.miso_io_num = VSPI_IOMUX_PIN_NUM_MISO; + buscfg.mosi_io_num = VSPI_IOMUX_PIN_NUM_MOSI; + buscfg.sclk_io_num = VSPI_IOMUX_PIN_NUM_CLK; + devcfg.spics_io_num = VSPI_IOMUX_PIN_NUM_CS; + slvcfg.spics_io_num = VSPI_IOMUX_PIN_NUM_CS; + } else { + buscfg.miso_io_num = HSPI_IOMUX_PIN_NUM_MISO; + buscfg.mosi_io_num = HSPI_IOMUX_PIN_NUM_MOSI; + buscfg.sclk_io_num = HSPI_IOMUX_PIN_NUM_CLK; + devcfg.spics_io_num = HSPI_IOMUX_PIN_NUM_CS; + slvcfg.spics_io_num = HSPI_IOMUX_PIN_NUM_CS; + } + slave_pull_up(&buscfg, slvcfg.spics_io_num); + + //this does nothing, but avoid the driver from using iomux pins if required + buscfg.quadhd_io_num = (!conf->master_iomux && !conf->slave_iomux? VSPI_IOMUX_PIN_NUM_MISO: -1); + TEST_ESP_OK(spi_bus_initialize(HSPI_HOST, &buscfg, 0)); + TEST_ESP_OK(spi_bus_add_device(HSPI_HOST, &devcfg, &spi)); + //slave automatically use iomux pins if pins are on VSPI_* pins + buscfg.quadhd_io_num = -1; + TEST_ESP_OK( spi_slave_initialize(VSPI_HOST, &buscfg, &slvcfg, 0) ); + + //initialize master and slave on the same pins break some of the output configs, fix them + if (conf->master_iomux) { + gpio_output_sel(buscfg.mosi_io_num, FUNC_SPI, HSPID_OUT_IDX); + gpio_output_sel(buscfg.miso_io_num, FUNC_GPIO, VSPIQ_OUT_IDX); + gpio_output_sel(devcfg.spics_io_num, FUNC_SPI, HSPICS0_OUT_IDX); + gpio_output_sel(buscfg.sclk_io_num, FUNC_SPI, HSPICLK_OUT_IDX); + } else if (conf->slave_iomux) { + gpio_output_sel(buscfg.mosi_io_num, FUNC_GPIO, HSPID_OUT_IDX); + gpio_output_sel(buscfg.miso_io_num, FUNC_SPI, VSPIQ_OUT_IDX); + gpio_output_sel(devcfg.spics_io_num, FUNC_GPIO, HSPICS0_OUT_IDX); + gpio_output_sel(buscfg.sclk_io_num, FUNC_GPIO, HSPICLK_OUT_IDX); + } else { + gpio_output_sel(buscfg.mosi_io_num, FUNC_GPIO, HSPID_OUT_IDX); + gpio_output_sel(buscfg.miso_io_num, FUNC_GPIO, VSPIQ_OUT_IDX); + gpio_output_sel(devcfg.spics_io_num, FUNC_GPIO, HSPICS0_OUT_IDX); + gpio_output_sel(buscfg.sclk_io_num, FUNC_GPIO, HSPICLK_OUT_IDX); + } + + //clear master receive buffer + memset(context.master_rxbuf, 0x66, sizeof(context.master_rxbuf)); + + //prepare slave tx data + for (int k = 0; k < 8; k ++) xQueueSend( context.slave_context.data_to_send, &context.slave_trans[k], portMAX_DELAY ); + + for( int k= 0; k < 8; k ++ ) { + //wait for both master and slave end + ESP_LOGI( MASTER_TAG, "=> test%d", k ); + //send master tx data + vTaskDelay(9); + + spi_transaction_t *t = &context.master_trans[k]; + TEST_ESP_OK (spi_device_transmit( spi, t) ); + master_print_data(t, conf->dup); + + size_t rcv_len; + slave_rxdata_t *rcv_data = xRingbufferReceive( context.slave_context.data_received, &rcv_len, portMAX_DELAY ); + slave_print_data(rcv_data); + + //check result + TEST_ESP_OK(check_data(t, conf->dup, rcv_data)); + //clean + vRingbufferReturnItem(context.slave_context.data_received, rcv_data); + } + master_deinit(spi); + TEST_ASSERT(spi_slave_free(VSPI_HOST) == ESP_OK); + } + } + + vTaskDelete( context.handle_slave ); + context.handle_slave = 0; + + deinit_slave_context(&context.slave_context); + + ESP_LOGI(MASTER_TAG, "test passed."); +} + +/******************************************************************************** + * Test SPI transaction interval + ********************************************************************************/ #define RECORD_TIME_PREPARE() uint32_t __t1, __t2 #define RECORD_TIME_START() do {__t1 = xthal_get_ccount();}while(0) #define RECORD_TIME_END(p_time) do{__t2 = xthal_get_ccount(); *p_time = (__t2-__t1)/240;}while(0) @@ -887,21 +1254,10 @@ TEST_CASE("SPI master variable cmd & addr test","[spi]") static void speed_setup(spi_device_handle_t* spi, bool use_dma) { esp_err_t ret; - spi_bus_config_t buscfg={ - .miso_io_num=PIN_NUM_MISO, - .mosi_io_num=PIN_NUM_MOSI, - .sclk_io_num=PIN_NUM_CLK, - .quadwp_io_num=-1, - .quadhd_io_num=-1 - }; - spi_device_interface_config_t devcfg={ - .clock_speed_hz=10*1000*1000, //currently only up to 4MHz for internel connect - .mode=0, //SPI mode 0 - .spics_io_num=PIN_NUM_CS, //CS pin - .queue_size=8, //We want to be able to queue 7 transactions at a time - .pre_cb=NULL, - .cs_ena_pretrans = 0, - }; + spi_bus_config_t buscfg=SPI_BUS_TEST_DEFAULT_CONFIG(); + spi_device_interface_config_t devcfg=SPI_DEVICE_TEST_DEFAULT_CONFIG(); + devcfg.queue_size=8; //We want to be able to queue 7 transactions at a time + //Initialize the SPI bus and the device to test ret=spi_bus_initialize(HSPI_HOST, &buscfg, (use_dma?1:0)); TEST_ASSERT(ret==ESP_OK); @@ -930,12 +1286,12 @@ static void sorted_array_insert(uint32_t* array, int* size, uint32_t item) TEST_CASE("spi_speed","[spi]") { - RECORD_TIME_PREPARE(); + RECORD_TIME_PREPARE(); uint32_t t_flight; //to get rid of the influence of randomly interrupts, we measured the performance by median value uint32_t t_flight_sorted[TEST_TIMES]; int t_flight_num = 0; - + spi_device_handle_t spi; const bool use_dma = true; WORD_ALIGNED_ATTR spi_transaction_t trans = { @@ -948,37 +1304,39 @@ TEST_CASE("spi_speed","[spi]") //first time introduces a device switch, which costs more time. we skip this spi_device_transmit(spi, &trans); - + //record flight time by isr, with DMA t_flight_num = 0; for (int i = 0; i < TEST_TIMES; i++) { + spi_device_transmit(spi, &trans); // prime the flash cache RECORD_TIME_START(); spi_device_transmit(spi, &trans); - RECORD_TIME_END(&t_flight); + RECORD_TIME_END(&t_flight); sorted_array_insert(t_flight_sorted, &t_flight_num, t_flight); } TEST_PERFORMANCE_LESS_THAN(SPI_PER_TRANS_NO_POLLING, "%d us", t_flight_sorted[(TEST_TIMES+1)/2]); for (int i = 0; i < TEST_TIMES; i++) { ESP_LOGI(TAG, "%d", t_flight_sorted[i]); } - + speed_deinit(spi); speed_setup(&spi, !use_dma); - + //first time introduces a device switch, which costs more time. we skip this spi_device_transmit(spi, &trans); - + //record flight time by isr, without DMA t_flight_num = 0; for (int i = 0; i < TEST_TIMES; i++) { RECORD_TIME_START(); spi_device_transmit(spi, &trans); - RECORD_TIME_END(&t_flight); + RECORD_TIME_END(&t_flight); sorted_array_insert(t_flight_sorted, &t_flight_num, t_flight); } TEST_PERFORMANCE_LESS_THAN( SPI_PER_TRANS_NO_POLLING_NO_DMA, "%d us", t_flight_sorted[(TEST_TIMES+1)/2]); for (int i = 0; i < TEST_TIMES; i++) { ESP_LOGI(TAG, "%d", t_flight_sorted[i]); - } - speed_deinit(spi); + } + speed_deinit(spi); } + diff --git a/components/driver/test/test_timer.c b/components/driver/test/test_timer.c new file mode 100644 index 0000000000..7f1d3c37fb --- /dev/null +++ b/components/driver/test/test_timer.c @@ -0,0 +1,870 @@ +#include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "esp_system.h" +#include "unity.h" +#include "nvs_flash.h" +#include "driver/timer.h" + +#define TIMER_DIVIDER 16 +#define TIMER_SCALE (TIMER_BASE_CLK / TIMER_DIVIDER) /*!< used to calculate counter value */ +#define TIMER_DELTA 0.001 +static bool alarm_flag; + +// group0 interruption +static void test_timer_group0_isr(void *para) +{ + int timer_idx = (int) para; + uint64_t timer_val; + double time; + uint64_t alarm_value; + alarm_flag = true; + if (TIMERG0.hw_timer[timer_idx].config.autoreload == 1) { + if (timer_idx == 0) { + TIMERG0.int_clr_timers.t0 = 1; + } else { + TIMERG0.int_clr_timers.t1 = 1; + } + ets_printf("This is TG0 timer[%d] reload-timer alarm!\n", timer_idx); + timer_get_counter_value(TIMER_GROUP_0, timer_idx, &timer_val); + timer_get_counter_time_sec(TIMER_GROUP_0, timer_idx, &time); + ets_printf("time: %.8f S\n", time); + } else { + if (timer_idx == 0) { + TIMERG0.int_clr_timers.t0 = 1; + } else { + TIMERG0.int_clr_timers.t1 = 1; + } + ets_printf("This is TG0 timer[%d] count-up-timer alarm!\n", timer_idx); + timer_get_counter_value(TIMER_GROUP_0, timer_idx, &timer_val); + timer_get_counter_time_sec(TIMER_GROUP_0, timer_idx, &time); + timer_get_alarm_value(TIMER_GROUP_0, timer_idx, &alarm_value); + ets_printf("time: %.8f S\n", time); + double alarm_time = (double) alarm_value / TIMER_SCALE; + ets_printf("alarm_time: %.8f S\n", alarm_time); + } +} + +// group1 interruption +static void test_timer_group1_isr(void *para) +{ + int timer_idx = (int) para; + uint64_t timer_val; + double time; + uint64_t alarm_value; + alarm_flag = true; + if (TIMERG1.hw_timer[timer_idx].config.autoreload == 1) { + if (timer_idx == 0) { + TIMERG1.int_clr_timers.t0 = 1; + } else { + TIMERG1.int_clr_timers.t1 = 1; + } + ets_printf("This is TG1 timer[%d] reload-timer alarm!\n", timer_idx); + timer_get_counter_value(TIMER_GROUP_1, timer_idx, &timer_val); + timer_get_counter_time_sec(TIMER_GROUP_1, timer_idx, &time); + ets_printf("time: %.8f S\n", time); + } else { + if (timer_idx == 0) { + TIMERG1.int_clr_timers.t0 = 1; + } else { + TIMERG1.int_clr_timers.t1 = 1; + } + ets_printf("This is TG1 timer[%d] count-up-timer alarm!\n", timer_idx); + timer_get_counter_value(TIMER_GROUP_1, timer_idx, &timer_val); + timer_get_counter_time_sec(TIMER_GROUP_1, timer_idx, &time); + timer_get_alarm_value(TIMER_GROUP_1, timer_idx, &alarm_value); + ets_printf("time: %.8f S\n", time); + double alarm_time = (double) alarm_value / TIMER_SCALE; + ets_printf("alarm_time: %.8f S\n", alarm_time); + } +} + +// initialize exact timer group +static void tg_timer_init(int timer_group, int timer_idx, double alarm_time) +{ + timer_pause(timer_group, timer_idx); + timer_set_counter_value(timer_group, timer_idx, 0x0); + timer_set_alarm_value(timer_group, timer_idx, alarm_time * TIMER_SCALE); + timer_enable_intr(timer_group, timer_idx); + if (timer_group == 0) { + timer_isr_register(timer_group, timer_idx, test_timer_group0_isr, + (void *) timer_idx, ESP_INTR_FLAG_LOWMED, NULL); + } else { + timer_isr_register(timer_group, timer_idx, test_timer_group1_isr, + (void *) timer_idx, ESP_INTR_FLAG_LOWMED, NULL); + } + timer_start(timer_group, timer_idx); +} + +// initialize all timer +static void all_timer_init(timer_config_t config, bool flag) +{ + esp_err_t ret; + ret = timer_init(TIMER_GROUP_0, TIMER_0, &config); + if (flag) { + TEST_ASSERT(ret == ESP_OK); + } else { + TEST_ASSERT(ret == ESP_ERR_INVALID_ARG); + } + ret = timer_init(TIMER_GROUP_0, TIMER_1, &config); + if (flag) { + TEST_ASSERT(ret == ESP_OK); + } else { + TEST_ASSERT(ret == ESP_ERR_INVALID_ARG); + } + ret = timer_init(TIMER_GROUP_1, TIMER_0, &config); + if (flag) { + TEST_ASSERT(ret == ESP_OK); + } else { + TEST_ASSERT(ret == ESP_ERR_INVALID_ARG); + } + ret = timer_init(TIMER_GROUP_1, TIMER_1, &config); + if (flag) { + TEST_ASSERT(ret == ESP_OK); + } else { + TEST_ASSERT(ret == ESP_ERR_INVALID_ARG); + } +} + +// start all of timer +static void all_timer_start() +{ + esp_err_t ret; + ret = timer_start(TIMER_GROUP_0, TIMER_0); + TEST_ASSERT(ret == ESP_OK); + ret = timer_start(TIMER_GROUP_0, TIMER_1); + TEST_ASSERT(ret == ESP_OK); + ret = timer_start(TIMER_GROUP_1, TIMER_0); + TEST_ASSERT(ret == ESP_OK); + ret = timer_start(TIMER_GROUP_1, TIMER_1); + TEST_ASSERT(ret == ESP_OK); +} + +static void all_timer_set_counter_value(uint64_t set_timer_val) +{ + esp_err_t ret; + ret = timer_set_counter_value(TIMER_GROUP_0, TIMER_0, set_timer_val); + TEST_ASSERT(ret == ESP_OK); + ret = timer_set_counter_value(TIMER_GROUP_0, TIMER_1, set_timer_val); + TEST_ASSERT(ret == ESP_OK); + ret = timer_set_counter_value(TIMER_GROUP_1, TIMER_0, set_timer_val); + TEST_ASSERT(ret == ESP_OK); + ret = timer_set_counter_value(TIMER_GROUP_1, TIMER_1, set_timer_val); + TEST_ASSERT(ret == ESP_OK); +} + +static void all_timer_pause() +{ + esp_err_t ret; + ret = timer_pause(TIMER_GROUP_0, TIMER_0); + TEST_ASSERT(ret == ESP_OK); + ret = timer_pause(TIMER_GROUP_0, TIMER_1); + TEST_ASSERT(ret == ESP_OK); + ret = timer_pause(TIMER_GROUP_1, TIMER_0); + TEST_ASSERT(ret == ESP_OK); + ret = timer_pause(TIMER_GROUP_1, TIMER_1); + TEST_ASSERT(ret == ESP_OK); +} + +static void all_timer_get_counter_value(uint64_t set_timer_val, bool flag, + uint64_t *counter_val) +{ + esp_err_t ret; + uint64_t time_val; + ret = timer_get_counter_value(TIMER_GROUP_0, TIMER_0, &time_val); + TEST_ASSERT(ret == ESP_OK); + if (flag == true) { + TEST_ASSERT(set_timer_val == time_val); + } else { + TEST_ASSERT(set_timer_val != time_val); + if (counter_val != NULL) { + counter_val[0] = time_val; + } + } + ret = timer_get_counter_value(TIMER_GROUP_0, TIMER_1, &time_val); + TEST_ASSERT(ret == ESP_OK); + if (flag) { + TEST_ASSERT(set_timer_val == time_val); + } else { + TEST_ASSERT(set_timer_val != time_val); + if (counter_val != NULL) { + counter_val[1] = time_val; + } + } + ret = timer_get_counter_value(TIMER_GROUP_1, TIMER_0, &time_val); + TEST_ASSERT(ret == ESP_OK); + if (flag) { + TEST_ASSERT(set_timer_val == time_val); + } else { + TEST_ASSERT(set_timer_val != time_val); + if (counter_val != NULL) { + counter_val[2] = time_val; + } + } + ret = timer_get_counter_value(TIMER_GROUP_1, TIMER_1, &time_val); + TEST_ASSERT(ret == ESP_OK); + if (flag) { + TEST_ASSERT(set_timer_val == time_val); + } else { + TEST_ASSERT(set_timer_val != time_val); + if (counter_val != NULL) { + counter_val[3] = time_val; + } + } +} + +static void all_timer_get_counter_time_sec(bool flag, int delay_time) +{ + double time; + esp_err_t ret; + ret = timer_get_counter_time_sec(TIMER_GROUP_0, TIMER_0, &time); + TEST_ASSERT(ret == ESP_OK); + if (!flag) { + TEST_ASSERT_FLOAT_WITHIN(TIMER_DELTA, delay_time, time); + } + ret = timer_get_counter_time_sec(TIMER_GROUP_0, TIMER_1, &time); + TEST_ASSERT(ret == ESP_OK); + if (!flag) { + TEST_ASSERT_FLOAT_WITHIN(TIMER_DELTA, delay_time, time); + } + ret = timer_get_counter_time_sec(TIMER_GROUP_1, TIMER_0, &time); + TEST_ASSERT(ret == ESP_OK); + if (!flag) { + TEST_ASSERT_FLOAT_WITHIN(TIMER_DELTA, delay_time, time); + } + ret = timer_get_counter_time_sec(TIMER_GROUP_1, TIMER_1, &time); + TEST_ASSERT(ret == ESP_OK); + if (!flag) { + TEST_ASSERT_FLOAT_WITHIN(TIMER_DELTA, delay_time, time); + } +} + +static void all_timer_set_counter_mode(timer_count_dir_t counter_dir) +{ + esp_err_t ret; + ret = timer_set_counter_mode(TIMER_GROUP_0, TIMER_0, counter_dir); + TEST_ASSERT(ret == ESP_OK); + ret = timer_set_counter_mode(TIMER_GROUP_0, TIMER_1, counter_dir); + TEST_ASSERT(ret == ESP_OK); + ret = timer_set_counter_mode(TIMER_GROUP_1, TIMER_0, counter_dir); + TEST_ASSERT(ret == ESP_OK); + ret = timer_set_counter_mode(TIMER_GROUP_1, TIMER_1, counter_dir); + TEST_ASSERT(ret == ESP_OK); +} + +static void all_timer_set_divider(uint32_t divider) +{ + esp_err_t ret; + ret = timer_set_divider(TIMER_GROUP_0, TIMER_0, divider); + TEST_ASSERT(ret == ESP_OK); + ret = timer_set_divider(TIMER_GROUP_0, TIMER_1, divider); + TEST_ASSERT(ret == ESP_OK); + ret = timer_set_divider(TIMER_GROUP_1, TIMER_0, divider); + TEST_ASSERT(ret == ESP_OK); + ret = timer_set_divider(TIMER_GROUP_1, TIMER_1, divider); + TEST_ASSERT(ret == ESP_OK); +} + +static void all_timer_set_alarm_value(double alarm_time) +{ + esp_err_t ret; + ret = timer_set_alarm_value(TIMER_GROUP_0, TIMER_0, + alarm_time * TIMER_SCALE); + TEST_ASSERT(ret == ESP_OK); + ret = timer_set_alarm_value(TIMER_GROUP_0, TIMER_1, + alarm_time * TIMER_SCALE); + TEST_ASSERT(ret == ESP_OK); + ret = timer_set_alarm_value(TIMER_GROUP_1, TIMER_0, + alarm_time * TIMER_SCALE); + TEST_ASSERT(ret == ESP_OK); + ret = timer_set_alarm_value(TIMER_GROUP_1, TIMER_1, + alarm_time * TIMER_SCALE); + TEST_ASSERT(ret == ESP_OK); +} + +TEST_CASE("Timer init", "[hw_timer]") +{ + esp_err_t ret; + + // Test init 1:config para + // empty para + timer_config_t config0 = { }; + all_timer_init(config0, false); + + // only one para + timer_config_t config1 = { + .auto_reload = 1 + }; + all_timer_init(config1, false); + + // lack one para + timer_config_t config2 = { + .auto_reload = 1, + .counter_dir = TIMER_COUNT_UP, + .divider = TIMER_DIVIDER, + .counter_en = 1, + .intr_type = TIMER_INTR_LEVEL + }; + all_timer_init(config2, true); + + config2.counter_en = 0; + all_timer_init(config2, true); + + + // error config para + timer_config_t config3 = { + .alarm_en = 3, //error para + .auto_reload = 1, + .counter_dir = TIMER_COUNT_UP, + .divider = TIMER_DIVIDER, + .counter_en = 1, + .intr_type = TIMER_INTR_LEVEL + }; + all_timer_init(config3, true); + timer_config_t get_config; + timer_get_config(TIMER_GROUP_1, TIMER_1, &get_config); + printf("Error config alarm_en is %d\n", get_config.alarm_en); + TEST_ASSERT(config3.alarm_en != get_config.alarm_en); + + // Test init 2: init + uint64_t set_timer_val = 0x0; + timer_config_t config = { + .alarm_en = 0, + .auto_reload = 1, + .counter_dir = TIMER_COUNT_UP, + .divider = TIMER_DIVIDER, + .counter_en = 1, + .intr_type = TIMER_INTR_LEVEL + }; + + // judge get config parameters + timer_init(TIMER_GROUP_0, TIMER_0, &config); + timer_get_config(TIMER_GROUP_0, TIMER_0, &get_config); + TEST_ASSERT(config.alarm_en == get_config.alarm_en); + TEST_ASSERT(config.auto_reload == get_config.auto_reload); + TEST_ASSERT(config.counter_dir == get_config.counter_dir); + TEST_ASSERT(config.counter_en == get_config.counter_en); + TEST_ASSERT(config.intr_type == get_config.intr_type); + TEST_ASSERT(config.divider == get_config.divider); + + all_timer_init(config, true); + all_timer_pause(); + all_timer_set_counter_value(set_timer_val); + all_timer_start(); + all_timer_get_counter_value(set_timer_val, false, NULL); + + // Test init 3: wrong para + ret = timer_init(-1, TIMER_1, &config); + TEST_ASSERT(ret == ESP_ERR_INVALID_ARG); + ret = timer_init(TIMER_GROUP_1, 2, &config); + TEST_ASSERT(ret == ESP_ERR_INVALID_ARG); + ret = timer_init(TIMER_GROUP_1, -1, &config); + TEST_ASSERT(ret == ESP_ERR_INVALID_ARG); + ret = timer_init(2, TIMER_1, &config); + TEST_ASSERT(ret == ESP_ERR_INVALID_ARG); + +} + +/** + * read count case: + * 1. start timer compare value + * 2. pause timer compare value + * 3. delay some time */ +TEST_CASE("Timer read counter value", "[hw_timer]") +{ + timer_config_t config = { + .alarm_en = 1, + .auto_reload = 1, + .counter_dir = TIMER_COUNT_UP, + .divider = TIMER_DIVIDER, + .counter_en = 1, + .intr_type = TIMER_INTR_LEVEL + }; + uint64_t set_timer_val = 0x0; + + all_timer_init(config, true); + + // Test read value 1: start timer get counter value + all_timer_set_counter_value(set_timer_val); + all_timer_start(); + all_timer_get_counter_value(set_timer_val, false, NULL); + + // Test read value 2: pause timer get counter value + all_timer_pause(); + set_timer_val = 0x30405000ULL; + all_timer_set_counter_value(set_timer_val); + all_timer_get_counter_value(set_timer_val, true, NULL); + + // Test read value 3:delay 1s get counter value + set_timer_val = 0x0; + all_timer_set_counter_value(set_timer_val); + all_timer_start(); + vTaskDelay(1000 / portTICK_PERIOD_MS); + all_timer_get_counter_time_sec(true, 1); +} + +/** + * start timer case: + * 1. normal start + * 2. error start para + * */ +TEST_CASE("Timer start", "[hw_timer]") +{ + esp_err_t ret; + timer_config_t config = { + .alarm_en = 1, + .auto_reload = 1, + .counter_dir = TIMER_COUNT_UP, + .divider = TIMER_DIVIDER, + .counter_en = 1, + .intr_type = TIMER_INTR_LEVEL + }; + uint64_t set_timer_val = 0x0; + all_timer_init(config, true); + + //Test start 1: normal start + all_timer_start(); + all_timer_set_counter_value(set_timer_val); + all_timer_get_counter_value(set_timer_val, false, NULL); + + //Test start 2:wrong para + ret = timer_start(2, TIMER_1); + TEST_ASSERT(ret == ESP_ERR_INVALID_ARG); + ret = timer_start(-1, TIMER_1); + TEST_ASSERT(ret == ESP_ERR_INVALID_ARG); + ret = timer_start(TIMER_GROUP_1, 2); + TEST_ASSERT(ret == ESP_ERR_INVALID_ARG); + ret = timer_start(TIMER_GROUP_1, -1); + TEST_ASSERT(ret == ESP_ERR_INVALID_ARG); +} + +/** + * pause timer case: + * 1. normal pause, read value + * 2. error pause error + */ +TEST_CASE("Timer pause", "[hw_timer]") +{ + esp_err_t ret; + timer_config_t config = { + .alarm_en = 1, + .auto_reload = 1, + .counter_dir = TIMER_COUNT_UP, + .divider = TIMER_DIVIDER, + .counter_en = 1, + .intr_type = TIMER_INTR_LEVEL + }; + uint64_t set_timer_val = 0x0; + all_timer_init(config, true); + + //Test pause 1: right para + all_timer_pause(); + all_timer_set_counter_value(set_timer_val); + all_timer_get_counter_value(set_timer_val, true, NULL); + + //Test pause 2: wrong para + ret = timer_pause(-1, TIMER_0); + TEST_ASSERT(ret == ESP_ERR_INVALID_ARG); + ret = timer_pause(TIMER_GROUP_0, -1); + TEST_ASSERT(ret == ESP_ERR_INVALID_ARG); + ret = timer_pause(2, TIMER_0); + TEST_ASSERT(ret == ESP_ERR_INVALID_ARG); + ret = timer_pause(TIMER_GROUP_1, 2); + TEST_ASSERT(ret == ESP_ERR_INVALID_ARG); +} + +// positive mode and negative mode +TEST_CASE("Timer counter mode (up / down)", "[hw_timer]") +{ + esp_err_t ret; + timer_config_t config = { + .alarm_en = 1, + .auto_reload = 1, + .counter_dir = TIMER_COUNT_UP, + .divider = TIMER_DIVIDER, + .counter_en = 1, + .intr_type = TIMER_INTR_LEVEL + }; + uint64_t set_timer_val = 0x0; + all_timer_init(config, true); + all_timer_pause(); + + // Test counter mode 1: TIMER_COUNT_UP + all_timer_set_counter_mode(TIMER_COUNT_UP); + all_timer_set_counter_value(set_timer_val); + all_timer_start(); + vTaskDelay(1000 / portTICK_PERIOD_MS); + all_timer_get_counter_time_sec(true, 1); + + // Test counter mode 2: TIMER_COUNT_DOWN + all_timer_pause(); + set_timer_val = 0x00E4E1C0ULL; // 3s clock counter value + all_timer_set_counter_mode(TIMER_COUNT_DOWN); + all_timer_set_counter_value(set_timer_val); + all_timer_start(); + vTaskDelay(1000 / portTICK_PERIOD_MS); + all_timer_get_counter_time_sec(true, 2); + + // Test counter mode 3 : wrong para + ret = timer_set_counter_mode(TIMER_GROUP_0, TIMER_0, -1); + TEST_ASSERT(ret == ESP_ERR_INVALID_ARG); + ret = timer_set_counter_mode(TIMER_GROUP_0, TIMER_0, 2); + TEST_ASSERT(ret == ESP_ERR_INVALID_ARG); +} + +/** + * divider case: + * 1. different divider, read value + * Note: divide 0 = divide max, divide 1 = divide 2 + * 2. error para + * + * the frequency(timer counts in one sec): + * 80M/divider = 800*100000 + * max divider value is 65536, its frequency is 1220 (nearly about 1KHz) + */ +TEST_CASE("Timer divider", "[hw_timer]") +{ + int i; + timer_config_t config = { + .alarm_en = 1, + .auto_reload = 1, + .counter_dir = TIMER_COUNT_UP, + .divider = TIMER_DIVIDER, + .counter_en = 1, + .intr_type = TIMER_INTR_LEVEL + }; + uint64_t set_timer_val = 0; + uint64_t time_val[4]; + uint64_t comp_time_val[4]; + all_timer_init(config, true); + + all_timer_pause(); + all_timer_set_counter_value(set_timer_val); + + all_timer_start(); + vTaskDelay(1000 / portTICK_PERIOD_MS); + all_timer_get_counter_value(set_timer_val, false, time_val); + + // compare divider 16 and 8, value should be double + all_timer_pause(); + all_timer_set_divider(8); + all_timer_set_counter_value(set_timer_val); + + all_timer_start(); + vTaskDelay(1000 / portTICK_PERIOD_MS); //delay the same time + all_timer_get_counter_value(set_timer_val, false, comp_time_val); + for (i = 0; i < 4; i++) { + TEST_ASSERT_INT_WITHIN(5000, 5000000, time_val[i]); + TEST_ASSERT_INT_WITHIN(10000, 10000000, comp_time_val[i]); + } + + // divider is 256, value should be 2^4 + all_timer_pause(); + all_timer_set_divider(256); + all_timer_set_counter_value(set_timer_val); + all_timer_start(); + vTaskDelay(1000 / portTICK_PERIOD_MS); //delay the same time + all_timer_get_counter_value(set_timer_val, false, comp_time_val); + for (i = 0; i < 4; i++) { + TEST_ASSERT_INT_WITHIN(5000, 5000000, time_val[i]); + TEST_ASSERT_INT_WITHIN(3126, 312500, comp_time_val[i]); + } + + // extrem value test + all_timer_pause(); + all_timer_set_divider(2); + all_timer_set_counter_value(set_timer_val); + all_timer_start(); + vTaskDelay(1000 / portTICK_PERIOD_MS); + all_timer_get_counter_value(set_timer_val, false, comp_time_val); + for (i = 0; i < 4; i++) { + TEST_ASSERT_INT_WITHIN(5000, 5000000, time_val[i]); + TEST_ASSERT_INT_WITHIN(40000 , 40000000, comp_time_val[i]); + } + + all_timer_pause(); + all_timer_set_divider(65536); + all_timer_set_counter_value(set_timer_val); + all_timer_start(); + vTaskDelay(1000 / portTICK_PERIOD_MS); //delay the same time + all_timer_get_counter_value(set_timer_val, false, comp_time_val); + for (i = 0; i < 4; i++) { + TEST_ASSERT_INT_WITHIN(5000, 5000000, time_val[i]); + TEST_ASSERT_INT_WITHIN(2 , 1220, comp_time_val[i]); + } + + // divider is 1 should be equal with 2 + all_timer_pause(); + TEST_ASSERT(timer_set_divider(TIMER_GROUP_0, TIMER_0, 1) == ESP_ERR_INVALID_ARG) ; + TEST_ASSERT(timer_set_divider(TIMER_GROUP_1, TIMER_0, 1) == ESP_ERR_INVALID_ARG) ; + TEST_ASSERT(timer_set_divider(TIMER_GROUP_0, TIMER_1, 1) == ESP_ERR_INVALID_ARG) ; + TEST_ASSERT(timer_set_divider(TIMER_GROUP_1, TIMER_1, 1) == ESP_ERR_INVALID_ARG) ; + + all_timer_pause(); + TEST_ASSERT(timer_set_divider(TIMER_GROUP_0, TIMER_0, 65537) == ESP_ERR_INVALID_ARG) ; + TEST_ASSERT(timer_set_divider(TIMER_GROUP_1, TIMER_0, 65537) == ESP_ERR_INVALID_ARG) ; + TEST_ASSERT(timer_set_divider(TIMER_GROUP_0, TIMER_1, 65537) == ESP_ERR_INVALID_ARG) ; + TEST_ASSERT(timer_set_divider(TIMER_GROUP_1, TIMER_1, 65537) == ESP_ERR_INVALID_ARG) ; +} + +/** + * enable alarm case: + * 1. enable alarm ,set alarm value and get value + * 2. disable alarm ,set alarm value and get value + */ +TEST_CASE("Timer enable alarm", "[hw_timer]") +{ + timer_config_t config_test = { + .alarm_en = 1, + .auto_reload = 1, + .counter_dir = TIMER_COUNT_UP, + .divider = TIMER_DIVIDER, + .counter_en = 1, + .intr_type = TIMER_INTR_LEVEL + }; + all_timer_init(config_test, true); + + // enable alarm + alarm_flag = false; + tg_timer_init(TIMER_GROUP_0, TIMER_1, 1.2); + vTaskDelay(2000 / portTICK_PERIOD_MS); + TEST_ASSERT(alarm_flag == true); + + // disable alarm + alarm_flag = false; + timer_set_alarm(TIMER_GROUP_0, TIMER_1, TIMER_ALARM_DIS); + tg_timer_init(TIMER_GROUP_0, TIMER_1, 1.2); + vTaskDelay(2000 / portTICK_PERIOD_MS); + TEST_ASSERT(alarm_flag == false); + + // enable alarm + alarm_flag = false; + timer_set_alarm(TIMER_GROUP_1, TIMER_0, TIMER_ALARM_EN); + tg_timer_init(TIMER_GROUP_1, TIMER_0, 1.2); + vTaskDelay(2000 / portTICK_PERIOD_MS); + TEST_ASSERT(alarm_flag == true); + + // disable alarm + alarm_flag = false; + timer_set_alarm(TIMER_GROUP_1, TIMER_0, TIMER_ALARM_DIS); + tg_timer_init(TIMER_GROUP_1, TIMER_0, 1.2); + vTaskDelay(2000 / portTICK_PERIOD_MS); + TEST_ASSERT(alarm_flag == false); +} + +/** + * alarm value case: + * 1. set alarm value and get value + * 2. interrupt test time + */ +TEST_CASE("Timer set alarm value", "[hw_timer]") +{ + esp_err_t ret; + int i; + uint64_t alarm_val[4]; + timer_config_t config = { + .alarm_en = 1, + .auto_reload = TIMER_AUTORELOAD_DIS, + .counter_dir = TIMER_COUNT_UP, + .divider = TIMER_DIVIDER, + .counter_en = 0, + .intr_type = TIMER_INTR_LEVEL + }; + all_timer_init(config, true); + + // set and get alarm value + all_timer_set_alarm_value(3); + ret = timer_get_alarm_value(TIMER_GROUP_0, TIMER_0, &alarm_val[0]); + TEST_ASSERT(ret == ESP_OK); + ret = timer_get_alarm_value(TIMER_GROUP_0, TIMER_1, &alarm_val[1]); + TEST_ASSERT(ret == ESP_OK); + ret = timer_get_alarm_value(TIMER_GROUP_1, TIMER_0, &alarm_val[2]); + TEST_ASSERT(ret == ESP_OK); + ret = timer_get_alarm_value(TIMER_GROUP_1, TIMER_1, &alarm_val[3]); + TEST_ASSERT(ret == ESP_OK); + for (i = 0; i < 4; i++) { + TEST_ASSERT_EQUAL_UINT32(alarm_val[i] , TIMER_SCALE * 3); + } + + // set interrupt read alarm value + tg_timer_init(TIMER_GROUP_0, TIMER_1, 2.4); + tg_timer_init(TIMER_GROUP_1, TIMER_0, 1.4); + vTaskDelay(3000 / portTICK_PERIOD_MS); +} + +/** + * auto reload case: + * 1. no reload + * 2. auto reload + */ +TEST_CASE("Timer auto reload", "[hw_timer]") +{ + timer_config_t config = { + .alarm_en = 1, + .auto_reload = TIMER_AUTORELOAD_DIS, + .counter_dir = TIMER_COUNT_UP, + .divider = TIMER_DIVIDER, + .counter_en = 1, + .intr_type = TIMER_INTR_LEVEL + }; + all_timer_init(config, true); + + // test disable auto_reload + tg_timer_init(TIMER_GROUP_0, TIMER_0, 1.14); + tg_timer_init(TIMER_GROUP_1, TIMER_1, 1.14); + vTaskDelay(2000 / portTICK_PERIOD_MS); + + //test enable auto_reload + timer_set_auto_reload(TIMER_GROUP_0, TIMER_1, TIMER_AUTORELOAD_EN); + tg_timer_init(TIMER_GROUP_0, TIMER_1, 1.4); + timer_set_auto_reload(TIMER_GROUP_1, TIMER_0, TIMER_AUTORELOAD_EN); + tg_timer_init(TIMER_GROUP_1, TIMER_0, 1.4); + vTaskDelay(2000 / portTICK_PERIOD_MS); +} + +/** + * timer_enable_intr case: + * 1. enable timer_intr + * 2. disable timer_intr + */ +TEST_CASE("Timer enable timer interrupt", "[hw_timer]") +{ + alarm_flag = false; + timer_config_t config = { + .alarm_en = 1, + .auto_reload = TIMER_AUTORELOAD_DIS, + .counter_dir = TIMER_COUNT_UP, + .divider = TIMER_DIVIDER, + .counter_en = TIMER_PAUSE, + .intr_type = TIMER_INTR_LEVEL + }; + uint64_t set_timer_val = 0x0; + all_timer_init(config, true); + all_timer_pause(); + all_timer_set_counter_value(set_timer_val); + all_timer_set_alarm_value(1.2); + + // enable timer_intr0 + timer_set_counter_value(TIMER_GROUP_0, TIMER_0, set_timer_val); + timer_set_alarm_value(TIMER_GROUP_0, TIMER_0, 1.2 * TIMER_SCALE); + timer_isr_register(TIMER_GROUP_0, TIMER_0, test_timer_group0_isr, + (void *) TIMER_0, ESP_INTR_FLAG_LOWMED, NULL); + timer_start(TIMER_GROUP_0, TIMER_0); + vTaskDelay(2000 / portTICK_PERIOD_MS); + TEST_ASSERT(alarm_flag == true) + + // disable timer_intr0 + alarm_flag = false; + timer_set_counter_value(TIMER_GROUP_0, TIMER_0, set_timer_val); + timer_set_alarm_value(TIMER_GROUP_0, TIMER_0, 1.2 * TIMER_SCALE); + timer_disable_intr(TIMER_GROUP_0, TIMER_0); + timer_start(TIMER_GROUP_0, TIMER_0); + vTaskDelay(2000 / portTICK_PERIOD_MS); + TEST_ASSERT(alarm_flag == false) + + // enable timer_intr1 + timer_set_counter_value(TIMER_GROUP_1, TIMER_1, set_timer_val); + timer_set_alarm_value(TIMER_GROUP_1, TIMER_1, 1.2 * TIMER_SCALE); + timer_isr_register(TIMER_GROUP_1, TIMER_1, test_timer_group1_isr, + (void *) TIMER_1, ESP_INTR_FLAG_LOWMED, NULL); + timer_start(TIMER_GROUP_1, TIMER_1); + vTaskDelay(2000 / portTICK_PERIOD_MS); + TEST_ASSERT(alarm_flag == true) + + // disable timer_intr1 + alarm_flag = false; + timer_set_counter_value(TIMER_GROUP_1, TIMER_1, set_timer_val); + timer_set_alarm_value(TIMER_GROUP_1, TIMER_1, 1.2 * TIMER_SCALE); + timer_disable_intr(TIMER_GROUP_1, TIMER_1); + timer_start(TIMER_GROUP_1, TIMER_1); + vTaskDelay(2000 / portTICK_PERIOD_MS); + TEST_ASSERT(alarm_flag == false); + + //enable timer_intr1 again + timer_init(TIMER_GROUP_1, TIMER_1, &config); + timer_set_counter_value(TIMER_GROUP_1, TIMER_1, set_timer_val); + timer_set_alarm_value(TIMER_GROUP_1, TIMER_1, 1.2 * TIMER_SCALE); + timer_enable_intr(TIMER_GROUP_1, TIMER_1); + timer_start(TIMER_GROUP_1, TIMER_1); + vTaskDelay(2000 / portTICK_PERIOD_MS); + TEST_ASSERT(alarm_flag == true) +} + +/** + * enable timer group case: + * 1. enable timer group + * 2. disable timer group + */ +TEST_CASE("Timer enable timer group interrupt", "[hw_timer][ignore]") +{ + alarm_flag = false; + timer_config_t config = { + .alarm_en = 1, + .auto_reload = TIMER_AUTORELOAD_DIS, + .counter_dir = TIMER_COUNT_UP, + .divider = TIMER_DIVIDER, + .counter_en = 0, + .intr_type = TIMER_INTR_LEVEL + }; + uint64_t set_timer_val = 0x0; + all_timer_init(config, true); + all_timer_pause(); + all_timer_set_counter_value(set_timer_val); + all_timer_set_alarm_value(1.2); + + // enable timer group + timer_group_intr_enable(TIMER_GROUP_0, TIMG_T0_INT_ENA_M); + timer_isr_register(TIMER_GROUP_0, TIMER_0, test_timer_group0_isr, + (void *) TIMER_0, ESP_INTR_FLAG_LOWMED, NULL); + timer_start(TIMER_GROUP_0, TIMER_0); + vTaskDelay(2000 / portTICK_PERIOD_MS); + TEST_ASSERT(alarm_flag == true); + + //test enable auto_reload + alarm_flag = false; + timer_group_intr_disable(TIMER_GROUP_0, TIMG_T0_INT_ENA_M); + timer_start(TIMER_GROUP_0, TIMER_0); + vTaskDelay(2000 / portTICK_PERIOD_MS); + TEST_ASSERT(alarm_flag == false); + + timer_group_intr_enable(TIMER_GROUP_0, TIMG_T0_INT_ENA_M); + timer_isr_register(TIMER_GROUP_0, TIMER_0, test_timer_group0_isr, + (void *) TIMER_0, ESP_INTR_FLAG_LOWMED, NULL); + timer_start(TIMER_GROUP_0, TIMER_0); + vTaskDelay(2000 / portTICK_PERIOD_MS); + TEST_ASSERT(alarm_flag == true); +} + +/** + * isr_register case: + * Cycle register 15 times, compare the heap size to ensure no memory leaks + */ +TEST_CASE("Timer interrupt register", "[hw_timer]") +{ + int i; + int heap_size = 0; + timer_config_t config = { + .alarm_en = 1, + .auto_reload = TIMER_AUTORELOAD_DIS, + .counter_dir = TIMER_COUNT_UP, + .divider = TIMER_DIVIDER, + .counter_en = TIMER_PAUSE, + .intr_type = TIMER_INTR_LEVEL + }; + + for (i = 0; i < 15; i++) { + all_timer_init(config, true); + tg_timer_init(TIMER_GROUP_0, TIMER_0, 0.54); + tg_timer_init(TIMER_GROUP_1, TIMER_1, 0.34); + + timer_set_auto_reload(TIMER_GROUP_0, TIMER_1, TIMER_AUTORELOAD_EN); + tg_timer_init(TIMER_GROUP_0, TIMER_1, 0.4); + timer_set_auto_reload(TIMER_GROUP_1, TIMER_0, TIMER_AUTORELOAD_EN); + tg_timer_init(TIMER_GROUP_1, TIMER_0, 0.6); + vTaskDelay(1000 / portTICK_PERIOD_MS); + if (heap_size == 0) { + heap_size = esp_get_free_heap_size(); + } + } + TEST_ASSERT_INT_WITHIN(100, heap_size, esp_get_free_heap_size()); +} diff --git a/components/driver/test/test_uart.c b/components/driver/test/test_uart.c index f49c73ef7c..da6ffd1ff9 100644 --- a/components/driver/test/test_uart.c +++ b/components/driver/test/test_uart.c @@ -45,4 +45,22 @@ TEST_CASE("test uart get baud-rate","[uart]") TEST_ASSERT(UART_TOLERANCE_CHECK(baud_rate1, (1.0 + TOLERANCE)*UART_BAUD_11520, (1.0 - TOLERANCE)*UART_BAUD_11520)) TEST_ASSERT(UART_TOLERANCE_CHECK(baud_rate2, (1.0 + TOLERANCE)*UART_BAUD_115200, (1.0 - TOLERANCE)*UART_BAUD_115200)) ESP_LOGI(UART_TAG, "get baud-rate test passed ....\n"); -} \ No newline at end of file +} + +TEST_CASE("test uart tx data with break","[uart]") +{ + const int buf_len = 200; + const int send_len = 128; + const int brk_len = 10; + char *psend = (char *)malloc(buf_len); + TEST_ASSERT( psend != NULL); + memset(psend, '0', buf_len); + uart_config(UART_BAUD_115200, false); + printf("Uart%d send %d bytes with break\n", UART_NUM1, send_len); + uart_write_bytes_with_break(UART_NUM1, (const char *)psend, send_len, brk_len); + uart_wait_tx_done(UART_NUM1, (portTickType)portMAX_DELAY); + //If the code is running here, it means the test passed, otherwise it will crash due to the interrupt wdt timeout. + printf("Send data with break test passed\n"); + free(psend); +} + diff --git a/components/driver/uart.c b/components/driver/uart.c index 94f3c4c655..d9bbdac478 100644 --- a/components/driver/uart.c +++ b/components/driver/uart.c @@ -44,6 +44,8 @@ static const char* UART_TAG = "uart"; #define UART_EMPTY_THRESH_DEFAULT (10) #define UART_FULL_THRESH_DEFAULT (120) #define UART_TOUT_THRESH_DEFAULT (10) +#define UART_CLKDIV_FRAG_BIT_WIDTH (3) +#define UART_TOUT_REF_FACTOR_DEFAULT (UART_CLK_FREQ/(REF_CLK_FREQ<int_clr.val = UART_INTR_MASK; if(intr_conf->intr_enable_mask & UART_RXFIFO_TOUT_INT_ENA_M) { - UART[uart_num]->conf1.rx_tout_thrhd = ((intr_conf->rx_timeout_thresh) & UART_RX_TOUT_THRHD_V); + //Hardware issue workaround: when using ref_tick, the rx timeout threshold needs increase to 10 times. + //T_ref = T_apb * APB_CLK/(REF_TICK << CLKDIV_FRAG_BIT_WIDTH) + if(UART[uart_num]->conf0.tick_ref_always_on == 0) { + UART[uart_num]->conf1.rx_tout_thrhd = ((intr_conf->rx_timeout_thresh * UART_TOUT_REF_FACTOR_DEFAULT) & UART_RX_TOUT_THRHD_V); + } else { + UART[uart_num]->conf1.rx_tout_thrhd = ((intr_conf->rx_timeout_thresh) & UART_RX_TOUT_THRHD_V); + } UART[uart_num]->conf1.rx_tout_en = 1; } else { UART[uart_num]->conf1.rx_tout_en = 0; @@ -747,7 +755,6 @@ static void uart_rx_intr_handler_default(void *param) 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) { - p_uart->tx_len_tot = p_uart->tx_head->tx_data.size; p_uart->tx_brk_flg = 1; p_uart->tx_brk_len = p_uart->tx_head->tx_data.brk_len; } @@ -787,7 +794,7 @@ static void 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_brk_flg == 1 && p_uart->tx_len_tot == 0) { + if(p_uart->tx_len_tot == 0 && p_uart->tx_brk_flg == 1) { UART_ENTER_CRITICAL_ISR(&uart_spinlock[uart_num]); uart_reg->int_ena.tx_brk_done = 0; uart_reg->idle_conf.tx_brk_num = p_uart->tx_brk_len; @@ -796,6 +803,8 @@ static void uart_rx_intr_handler_default(void *param) uart_reg->int_ena.tx_brk_done = 1; UART_EXIT_CRITICAL_ISR(&uart_spinlock[uart_num]); p_uart->tx_waiting_brk = 1; + //do not enable TX empty interrupt + en_tx_flg = false; } else { //enable TX empty interrupt en_tx_flg = true; diff --git a/components/esp32/CMakeLists.txt b/components/esp32/CMakeLists.txt index 5fe1819b2f..b26f5efe27 100644 --- a/components/esp32/CMakeLists.txt +++ b/components/esp32/CMakeLists.txt @@ -38,7 +38,9 @@ else() target_linker_script(esp32 "ld/esp32.common.ld" "ld/esp32.rom.ld" - "ld/esp32.peripherals.ld") + "ld/esp32.peripherals.ld" + "ld/esp32.rom.libgcc.ld" + ) if(CONFIG_SPIRAM_CACHE_WORKAROUND) add_compile_options(-mfix-esp32-psram-cache-issue) diff --git a/components/esp32/Makefile.projbuild b/components/esp32/Makefile.projbuild index 63318dd66b..9a51d80b3e 100644 --- a/components/esp32/Makefile.projbuild +++ b/components/esp32/Makefile.projbuild @@ -4,8 +4,8 @@ PHY_INIT_DATA_OBJ = $(BUILD_DIR_BASE)/phy_init_data.o PHY_INIT_DATA_BIN = $(BUILD_DIR_BASE)/phy_init_data.bin # Command to flash PHY init data partition -PHY_INIT_DATA_FLASH_CMD = $(ESPTOOLPY_SERIAL) write_flash $(CONFIG_PHY_DATA_OFFSET) $(PHY_INIT_DATA_BIN) -ESPTOOL_ALL_FLASH_ARGS += $(CONFIG_PHY_DATA_OFFSET) $(PHY_INIT_DATA_BIN) +PHY_INIT_DATA_FLASH_CMD = $(ESPTOOLPY_SERIAL) write_flash $(PHY_DATA_OFFSET) $(PHY_INIT_DATA_BIN) +ESPTOOL_ALL_FLASH_ARGS += $(PHY_DATA_OFFSET) $(PHY_INIT_DATA_BIN) ESP32_COMPONENT_PATH := $(COMPONENT_PATH) @@ -38,3 +38,7 @@ CFLAGS+=-mfix-esp32-psram-cache-issue CXXFLAGS+=-mfix-esp32-psram-cache-issue endif +# Enable dynamic esp_timer overflow value if building unit tests +ifneq ("$(TEST_COMPONENTS_LIST)","") +CPPFLAGS += -DESP_TIMER_DYNAMIC_OVERFLOW_VAL +endif diff --git a/components/esp32/clk.c b/components/esp32/clk.c index 41b24c6ed9..e6874e3f4b 100644 --- a/components/esp32/clk.c +++ b/components/esp32/clk.c @@ -88,7 +88,7 @@ void esp_clk_init(void) break; default: freq_mhz = 80; - /* no break */ + /* falls through */ case 80: freq = RTC_CPU_FREQ_80M; break; diff --git a/components/esp32/component.mk b/components/esp32/component.mk index fb53bfbb43..6c03587a36 100644 --- a/components/esp32/component.mk +++ b/components/esp32/component.mk @@ -13,6 +13,9 @@ endif #specifies its own scripts. LINKER_SCRIPTS += esp32.common.ld esp32.rom.ld esp32.peripherals.ld +#Force pure functions from libgcc.a to be linked from ROM +LINKER_SCRIPTS += esp32.rom.libgcc.ld + #SPI-RAM incompatible functions can be used in when the SPI RAM #workaround is not enabled. ifndef CONFIG_SPIRAM_CACHE_WORKAROUND diff --git a/components/esp32/crosscore_int.c b/components/esp32/crosscore_int.c index 9ccda1f824..18a5237b5a 100644 --- a/components/esp32/crosscore_int.c +++ b/components/esp32/crosscore_int.c @@ -44,7 +44,7 @@ static volatile uint32_t reason[ portNUM_PROCESSORS ]; ToDo: There is a small chance the CPU already has yielded when this ISR is serviced. In that case, it's running the intended task but the ISR will cause it to switch _away_ from it. portYIELD_FROM_ISR will probably just schedule the task again, but have to check that. */ -static void esp_crosscore_isr_handle_yield() +static inline void IRAM_ATTR esp_crosscore_isr_handle_yield() { portYIELD_FROM_ISR(); } diff --git a/components/esp32/dport_panic_highint_hdl.S b/components/esp32/dport_panic_highint_hdl.S index ffd3b45f11..bddde3cdff 100644 --- a/components/esp32/dport_panic_highint_hdl.S +++ b/components/esp32/dport_panic_highint_hdl.S @@ -16,7 +16,6 @@ #include #include #include -#include #include "freertos/xtensa_context.h" #include "esp_panic.h" #include "sdkconfig.h" diff --git a/components/esp32/esp_err_to_name.c b/components/esp32/esp_err_to_name.c index b6743c31ea..f012a5fb90 100644 --- a/components/esp32/esp_err_to_name.c +++ b/components/esp32/esp_err_to_name.c @@ -55,43 +55,43 @@ typedef struct { static const esp_err_msg_t esp_err_msg_table[] = { // components/esp32/include/esp_err.h # ifdef ESP_FAIL - ERR_TBL_IT(ESP_FAIL), /* -1 */ + ERR_TBL_IT(ESP_FAIL), /* -1 Generic esp_err_t code indicating failure */ # endif # ifdef ESP_OK - ERR_TBL_IT(ESP_OK), /* 0 */ + ERR_TBL_IT(ESP_OK), /* 0 esp_err_t value indicating success (no error) */ # endif # ifdef ESP_ERR_NO_MEM - ERR_TBL_IT(ESP_ERR_NO_MEM), /* 257 0x101 */ + ERR_TBL_IT(ESP_ERR_NO_MEM), /* 257 0x101 Out of memory */ # endif # ifdef ESP_ERR_INVALID_ARG - ERR_TBL_IT(ESP_ERR_INVALID_ARG), /* 258 0x102 */ + ERR_TBL_IT(ESP_ERR_INVALID_ARG), /* 258 0x102 Invalid argument */ # endif # ifdef ESP_ERR_INVALID_STATE - ERR_TBL_IT(ESP_ERR_INVALID_STATE), /* 259 0x103 */ + ERR_TBL_IT(ESP_ERR_INVALID_STATE), /* 259 0x103 Invalid state */ # endif # ifdef ESP_ERR_INVALID_SIZE - ERR_TBL_IT(ESP_ERR_INVALID_SIZE), /* 260 0x104 */ + ERR_TBL_IT(ESP_ERR_INVALID_SIZE), /* 260 0x104 Invalid size */ # endif # ifdef ESP_ERR_NOT_FOUND - ERR_TBL_IT(ESP_ERR_NOT_FOUND), /* 261 0x105 */ + ERR_TBL_IT(ESP_ERR_NOT_FOUND), /* 261 0x105 Requested resource not found */ # endif # ifdef ESP_ERR_NOT_SUPPORTED - ERR_TBL_IT(ESP_ERR_NOT_SUPPORTED), /* 262 0x106 */ + ERR_TBL_IT(ESP_ERR_NOT_SUPPORTED), /* 262 0x106 Operation or feature not supported */ # endif # ifdef ESP_ERR_TIMEOUT - ERR_TBL_IT(ESP_ERR_TIMEOUT), /* 263 0x107 */ + ERR_TBL_IT(ESP_ERR_TIMEOUT), /* 263 0x107 Operation timed out */ # endif # ifdef ESP_ERR_INVALID_RESPONSE - ERR_TBL_IT(ESP_ERR_INVALID_RESPONSE), /* 264 0x108 */ + ERR_TBL_IT(ESP_ERR_INVALID_RESPONSE), /* 264 0x108 Received response was invalid */ # endif # ifdef ESP_ERR_INVALID_CRC - ERR_TBL_IT(ESP_ERR_INVALID_CRC), /* 265 0x109 */ + ERR_TBL_IT(ESP_ERR_INVALID_CRC), /* 265 0x109 CRC or checksum was invalid */ # endif # ifdef ESP_ERR_INVALID_VERSION - ERR_TBL_IT(ESP_ERR_INVALID_VERSION), /* 266 0x10a */ + ERR_TBL_IT(ESP_ERR_INVALID_VERSION), /* 266 0x10a Version was invalid */ # endif # ifdef ESP_ERR_INVALID_MAC - ERR_TBL_IT(ESP_ERR_INVALID_MAC), /* 267 0x10b */ + ERR_TBL_IT(ESP_ERR_INVALID_MAC), /* 267 0x10b MAC address was invalid */ # endif // components/nvs_flash/include/nvs.h # ifdef ESP_ERR_NVS_BASE @@ -132,7 +132,7 @@ static const esp_err_msg_t esp_err_msg_table[] = { ERR_TBL_IT(ESP_ERR_NVS_KEY_TOO_LONG), /* 4361 0x1109 Key name is too long */ # endif # ifdef ESP_ERR_NVS_PAGE_FULL - ERR_TBL_IT(ESP_ERR_NVS_PAGE_FULL), /* 4362 0x110a Internal error; never returned by nvs_ API + ERR_TBL_IT(ESP_ERR_NVS_PAGE_FULL), /* 4362 0x110a Internal error; never returned by nvs API functions */ # endif # ifdef ESP_ERR_NVS_INVALID_STATE @@ -157,6 +157,11 @@ static const esp_err_msg_t esp_err_msg_table[] = { # ifdef ESP_ERR_NVS_PART_NOT_FOUND ERR_TBL_IT(ESP_ERR_NVS_PART_NOT_FOUND), /* 4367 0x110f Partition with specified name is not found in the partition table */ +# endif +# ifdef ESP_ERR_NVS_NEW_VERSION_FOUND + ERR_TBL_IT(ESP_ERR_NVS_NEW_VERSION_FOUND), /* 4368 0x1110 NVS partition contains data in new format + and cannot be recognized by this version of + code */ # endif // components/ulp/include/esp32/ulp.h # ifdef ESP_ERR_ULP_BASE @@ -473,7 +478,7 @@ const char *esp_err_to_name_r(esp_err_t code, char *buf, size_t buflen) return buf; } - snprintf(buf, buflen, "Unknown error %d", code); + snprintf(buf, buflen, "%s 0x%x(%d)", esp_unknown_msg, code, code); return buf; } diff --git a/components/esp32/esp_err_to_name.c.in b/components/esp32/esp_err_to_name.c.in index b6b87312e9..5f623c62dc 100644 --- a/components/esp32/esp_err_to_name.c.in +++ b/components/esp32/esp_err_to_name.c.in @@ -58,7 +58,7 @@ const char *esp_err_to_name_r(esp_err_t code, char *buf, size_t buflen) return buf; } - snprintf(buf, buflen, "Unknown error %d", code); + snprintf(buf, buflen, "%s 0x%x(%d)", esp_unknown_msg, code, code); return buf; } diff --git a/components/esp32/esp_timer_esp32.c b/components/esp32/esp_timer_esp32.c index b2c29721b2..3d63cf2bd8 100644 --- a/components/esp32/esp_timer_esp32.c +++ b/components/esp32/esp_timer_esp32.c @@ -82,7 +82,18 @@ * ISR happens follow set_alarm, so change the ALARM_OVERFLOW_VAL to resolve this problem. * Set it to 0xefffffffUL. The remain 0x10000000UL(about 3 second) is enough to handle ISR. */ -#define ALARM_OVERFLOW_VAL 0xefffffffUL +#define DEFAULT_ALARM_OVERFLOW_VAL 0xefffffffUL + +/* Provision to set lower overflow value for unit testing. Lowering the + * overflow value helps check for race conditions which occur near overflow + * moment. + */ +#ifndef ESP_TIMER_DYNAMIC_OVERFLOW_VAL +#define ALARM_OVERFLOW_VAL DEFAULT_ALARM_OVERFLOW_VAL +#else +static uint32_t s_alarm_overflow_val = DEFAULT_ALARM_OVERFLOW_VAL; +#define ALARM_OVERFLOW_VAL (s_alarm_overflow_val) +#endif static const char* TAG = "esp_timer_impl"; @@ -216,18 +227,6 @@ void IRAM_ATTR esp_timer_impl_set_alarm(uint64_t timestamp) // Adjust current time if overflow has happened bool overflow = timer_overflow_happened(); uint64_t cur_count = REG_READ(FRC_TIMER_COUNT_REG(1)); - uint32_t offset = s_timer_ticks_per_us * 2; //remain 2us for more safe - - //If overflow is going to happen in 1us, let's wait until it happens, - //else we think it will not happen before new alarm set. - //And we should wait current timer count less than ALARM_OVERFLOW_VAL, - //maybe equals to 0. - if (cur_count + offset >= ALARM_OVERFLOW_VAL) { - do { - overflow = timer_overflow_happened(); - cur_count = REG_READ(FRC_TIMER_COUNT_REG(1)); - } while(!overflow || cur_count == ALARM_OVERFLOW_VAL); - } if (overflow) { assert(time_after_timebase_us > s_timer_us_per_overflow); @@ -237,13 +236,17 @@ void IRAM_ATTR esp_timer_impl_set_alarm(uint64_t timestamp) // Calculate desired timer compare value (may exceed 2^32-1) uint64_t compare_val = time_after_timebase_us * s_timer_ticks_per_us; uint32_t alarm_reg_val = ALARM_OVERFLOW_VAL; - // Use calculated alarm value if it is less than 2^32-1 + // Use calculated alarm value if it is less than ALARM_OVERFLOW_VAL. + // Note that if by the time we update ALARM_REG, COUNT_REG value is higher, + // interrupt will not happen for another ALARM_OVERFLOW_VAL timer ticks, + // so need to check if alarm value is too close in the future (e.g. <2 us away). + const uint32_t offset = s_timer_ticks_per_us * 2; if (compare_val < ALARM_OVERFLOW_VAL) { - // If we by the time we update ALARM_REG, COUNT_REG value is higher, - // interrupt will not happen for another 2^32 timer ticks, so need to - // check if alarm value is too close in the future (e.g. <1 us away). if (compare_val < cur_count + offset) { compare_val = cur_count + offset; + if (compare_val > ALARM_OVERFLOW_VAL) { + compare_val = ALARM_OVERFLOW_VAL; + } } alarm_reg_val = (uint32_t) compare_val; } @@ -387,3 +390,17 @@ uint64_t IRAM_ATTR esp_timer_impl_get_min_period_us() { return 50; } + +#ifdef ESP_TIMER_DYNAMIC_OVERFLOW_VAL +uint32_t esp_timer_impl_get_overflow_val() +{ + return s_alarm_overflow_val; +} + +void esp_timer_impl_set_overflow_val(uint32_t overflow_val) +{ + s_alarm_overflow_val = overflow_val; + /* update alarm value */ + esp_timer_impl_update_apb_freq(esp_clk_apb_freq() / 1000000); +} +#endif // ESP_TIMER_DYNAMIC_OVERFLOW_VAL diff --git a/components/esp32/fast_crypto_ops.c b/components/esp32/fast_crypto_ops.c index aa0054d707..7e05a7b8c9 100644 --- a/components/esp32/fast_crypto_ops.c +++ b/components/esp32/fast_crypto_ops.c @@ -36,6 +36,8 @@ * we recommend, so as the API in WPS default and WPA2 default. */ const wpa_crypto_funcs_t g_wifi_default_wpa_crypto_funcs = { + .size = sizeof(wpa_crypto_funcs_t), + .version = ESP_WIFI_CRYPTO_VERSION, .aes_wrap = (esp_aes_wrap_t)fast_aes_wrap, .aes_unwrap = (esp_aes_unwrap_t)fast_aes_unwrap, .hmac_sha256_vector = (esp_hmac_sha256_vector_t)fast_hmac_sha256_vector, @@ -58,6 +60,8 @@ const wpa_crypto_funcs_t g_wifi_default_wpa_crypto_funcs = { }; const wps_crypto_funcs_t g_wifi_default_wps_crypto_funcs = { + .size = sizeof(wps_crypto_funcs_t), + .version = ESP_WIFI_CRYPTO_VERSION, .aes_128_encrypt = (esp_aes_128_encrypt_t)fast_aes_128_cbc_encrypt, .aes_128_decrypt = (esp_aes_128_decrypt_t)fast_aes_128_cbc_decrypt, .crypto_mod_exp = (esp_crypto_mod_exp_t)fast_crypto_mod_exp, @@ -85,6 +89,8 @@ const wps_crypto_funcs_t g_wifi_default_wps_crypto_funcs = { * crypto_hash_finish, so do crypto_cipher. */ const wpa2_crypto_funcs_t g_wifi_default_wpa2_crypto_funcs = { + .size = sizeof(wpa2_crypto_funcs_t), + .version = ESP_WIFI_CRYPTO_VERSION, .crypto_hash_init = (esp_crypto_hash_init_t)fast_crypto_hash_init, .crypto_hash_update = (esp_crypto_hash_update_t)fast_crypto_hash_update, .crypto_hash_finish = (esp_crypto_hash_finish_t)fast_crypto_hash_finish, @@ -100,6 +106,8 @@ const wpa2_crypto_funcs_t g_wifi_default_wpa2_crypto_funcs = { .eap_peer_blob_deinit = (esp_eap_peer_blob_deinit_t)eap_peer_blob_deinit, .eap_peer_config_init = (esp_eap_peer_config_init_t)eap_peer_config_init, .eap_peer_config_deinit = (esp_eap_peer_config_deinit_t)eap_peer_config_deinit, + .eap_peer_register_methods = (esp_eap_peer_register_methods_t)eap_peer_register_methods, + .eap_peer_unregister_methods = (esp_eap_peer_unregister_methods_t)eap_peer_unregister_methods, .eap_deinit_prev_method = (esp_eap_deinit_prev_method_t)eap_deinit_prev_method, .eap_peer_get_eap_method = (esp_eap_peer_get_eap_method_t)eap_peer_get_eap_method, .eap_sm_abort = (esp_eap_sm_abort_t)eap_sm_abort, diff --git a/components/esp32/include/esp_attr.h b/components/esp32/include/esp_attr.h index a9c3f9a7a3..5bf9a22926 100644 --- a/components/esp32/include/esp_attr.h +++ b/components/esp32/include/esp_attr.h @@ -47,4 +47,12 @@ // Forces read-only data into RTC slow memory. See "docs/deep-sleep-stub.rst" #define RTC_RODATA_ATTR __attribute__((section(".rtc.rodata"))) +// Forces data into noinit section to avoid initialization after restart. +#define __NOINIT_ATTR __attribute__((section(".noinit"))) + +// 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 __attribute__((section(".rtc_noinit"))) + #endif /* __ESP_ATTR_H__ */ diff --git a/components/esp32/include/esp_err.h b/components/esp32/include/esp_err.h index b38a723bc3..d8820e5ae1 100644 --- a/components/esp32/include/esp_err.h +++ b/components/esp32/include/esp_err.h @@ -24,21 +24,20 @@ extern "C" { 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_OK 0 -#define ESP_FAIL -1 - -#define ESP_ERR_NO_MEM 0x101 -#define ESP_ERR_INVALID_ARG 0x102 -#define ESP_ERR_INVALID_STATE 0x103 -#define ESP_ERR_INVALID_SIZE 0x104 -#define ESP_ERR_NOT_FOUND 0x105 -#define ESP_ERR_NOT_SUPPORTED 0x106 -#define ESP_ERR_TIMEOUT 0x107 -#define ESP_ERR_INVALID_RESPONSE 0x108 -#define ESP_ERR_INVALID_CRC 0x109 -#define ESP_ERR_INVALID_VERSION 0x10A -#define ESP_ERR_INVALID_MAC 0x10B +#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 */ @@ -76,6 +75,7 @@ const char *esp_err_to_name(esp_err_t code); */ 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)); #ifndef __ASSERT_FUNC @@ -88,6 +88,7 @@ void _esp_error_check_failed(esp_err_t rc, const char *file, int line, const cha #define __ASSERT_FUNC "??" #endif #endif +/** @endcond */ /** * Macro which can be used to check the error code, diff --git a/components/esp32/include/esp_flash_data_types.h b/components/esp32/include/esp_flash_data_types.h index 3e44b2639d..bb5aa2998a 100644 --- a/components/esp32/include/esp_flash_data_types.h +++ b/components/esp32/include/esp_flash_data_types.h @@ -21,7 +21,6 @@ extern "C" { #endif -#define ESP_PARTITION_TABLE_ADDR 0x8000 #define ESP_PARTITION_MAGIC 0x50AA #define ESP_PARTITION_MAGIC_MD5 0xEBEB diff --git a/components/esp32/include/esp_mesh.h b/components/esp32/include/esp_mesh.h index 14bd21f7ea..8fea167de1 100644 --- a/components/esp32/include/esp_mesh.h +++ b/components/esp32/include/esp_mesh.h @@ -936,7 +936,7 @@ bool esp_mesh_get_self_organized(void); * be expected to find to replace the current one. * If no desired root candidate, the vote will try a specified attempts(at least 10 times), if no better * root candidate is found, keep the current one. If a better candidate is found, the new better one will - * send a root switch request to the current root, current root will respond with a root switch acknowledgement. + * send a root switch request to the current root, current root will respond with a root switch acknowledgment. * After that, the new candidate will connect to the router to be a new root, the previous root will disconnect * with the router and choose another parent instead. * So far, root switch is completed with minimal disruption to the whole mesh network. @@ -951,6 +951,8 @@ bool esp_mesh_get_self_organized(void); * * @return * - ESP_OK + * - ESP_ERR_MESH_QUEUE_FULL + * - ESP_ERR_MESH_DISCARD * - ESP_FAIL */ esp_err_t esp_mesh_waive_root(const mesh_vote_t *vote, int reason); @@ -1310,6 +1312,14 @@ esp_err_t esp_mesh_scan_get_ap_ie_len(int *len); */ esp_err_t esp_mesh_scan_get_ap_record(wifi_ap_record_t *ap_record, void *buffer); +/** + * @brief flush upstream packets pending in to_parent queue and to_parent_p2p queue + * + * @return + * - ESP_OK + */ +esp_err_t esp_mesh_flush_upstream_packets(void); + #ifdef __cplusplus } #endif diff --git a/components/esp32/include/esp_mesh_internal.h b/components/esp32/include/esp_mesh_internal.h index da349297eb..5f73984a1a 100644 --- a/components/esp32/include/esp_mesh_internal.h +++ b/components/esp32/include/esp_mesh_internal.h @@ -33,22 +33,31 @@ extern "C" { * Structures *******************************************************/ typedef struct { - int scan; /**< minimum scan times before being a root, default:10 */ - int vote; /**< max vote times in self-healing, default:10000 */ - int fail; /**< parent selection fail times, if the scan times reach this value, - will disconnect with associated children and join self-healing. default:60 */ - int monitor_ie; /**< acceptable times of parent ie change before update self ie, default:3 */ + int scan; /**< minimum scan times before being a root, default:10. */ + int vote; /**< max vote times in self-healing, default:1000. */ + int fail; /**< parent selection fail times. If the scan times reach this value, + device will disconnect with associated children and join self-healing, default:120. */ + int monitor_ie; /**< acceptable times of parent networking IE change before update self networking IE, default:10. */ } mesh_attempts_t; typedef struct { - int duration_ms; /* parent weak RSSI monitor duration, if the RSSI continues to be weak during this duration_ms, - will switch to a better parent */ - int cnx_rssi; /* RSSI threshold for keeping a good connection with parent */ - int select_rssi; /* RSSI threshold for parent selection, should be a value greater than switch_rssi */ - int switch_rssi; /* RSSI threshold for action to reselect a better parent */ + int duration_ms; /* parent weak RSSI monitor duration. If the RSSI with current parent is less than cnx_rssi continuously + within this duration_ms, device will search for a better parent. */ + int cnx_rssi; /* RSSI threshold for keeping a good connection with parent. + If set a value greater than -120 dBm, device will arm a timer to monitor current RSSI at a period time of + duration_ms. */ + int select_rssi; /* RSSI threshold for parent selection, should be a value greater than switch_rssi. */ + int switch_rssi; /* RSSI threshold for parent switch. Device will disassociate current parent and switch to a new parent when + the RSSI with the new parent is greater than this set threshold. */ int backoff_rssi; /* RSSI threshold for connecting to the root */ } mesh_switch_parent_t; +typedef struct { + int high; + int medium; + int low; +} mesh_rssi_threshold_t; + /** * @brief mesh networking IE */ @@ -58,8 +67,8 @@ typedef struct { uint8_t len; /**< element length */ uint8_t oui[3]; /**< organization identifier */ /**< mesh networking IE content */ - uint8_t type; /** mesh networking IE type */ - uint8_t encryped : 1; /**< if mesh networking IE is encrypted */ + uint8_t type; /** ESP defined IE type */ + uint8_t encryped : 1; /**< whether mesh networking IE is encrypted */ uint8_t version : 7; /**< mesh networking IE version */ /**< content */ uint8_t mesh_type; /**< mesh device type */ @@ -74,13 +83,13 @@ typedef struct { uint16_t self_cap; /**< self capacity */ uint16_t layer2_cap; /**< layer2 capacity */ uint16_t scan_ap_num; /**< the number of scanned APs */ - int8_t rssi; /**< rssi of the parent */ - int8_t router_rssi; /**< rssi of the router */ + int8_t rssi; /**< RSSI of the parent */ + int8_t router_rssi; /**< RSSI of the router */ uint8_t flag; /**< flag of networking */ uint8_t rc_addr[6]; /**< root address */ - int8_t rc_rssi; /**< root rssi */ + int8_t rc_rssi; /**< root RSSI */ uint8_t vote_addr[6]; /**< voter address */ - int8_t vote_rssi; /**< vote rssi of the router */ + int8_t vote_rssi; /**< vote RSSI of the router */ uint8_t vote_ttl; /**< vote ttl */ uint16_t votes; /**< votes */ uint16_t my_votes; /**< my votes */ @@ -115,9 +124,9 @@ esp_err_t esp_mesh_set_beacon_interval(int interval_ms); esp_err_t esp_mesh_get_beacon_interval(int *interval_ms); /** - * @brief set attempts for mesh self-organized networking + * @brief set attempts for mesh self-organized networking * - * @param attempts + * @param attempts * * @return * - ESP_OK @@ -132,7 +141,7 @@ esp_err_t esp_mesh_set_attempts(mesh_attempts_t *attempts); * * @return * - ESP_OK - * - ESP_FAIL + * - ESP_ERR_MESH_ARGUMENT */ esp_err_t esp_mesh_get_attempts(mesh_attempts_t *attempts); @@ -143,7 +152,7 @@ esp_err_t esp_mesh_get_attempts(mesh_attempts_t *attempts); * * @return * - ESP_OK - * - ESP_FAIL + * - ESP_ERR_MESH_ARGUMENT */ esp_err_t esp_mesh_set_switch_parent_paras(mesh_switch_parent_t *paras); @@ -154,10 +163,46 @@ esp_err_t esp_mesh_set_switch_parent_paras(mesh_switch_parent_t *paras); * * @return * - ESP_OK - * - ESP_FAIL + * - ESP_ERR_MESH_ARGUMENT */ esp_err_t esp_mesh_get_switch_parent_paras(mesh_switch_parent_t *paras); +/** + * @brief set RSSI threshold + * The default high RSSI threshold value is -78 dBm. + * The default medium RSSI threshold value is -82 dBm. + * The default low RSSI threshold value is -85 dBm. + * + * @param threshold RSSI threshold + * + * @return + * - ESP_OK + * - ESP_ERR_MESH_ARGUMENT + */ +esp_err_t esp_mesh_set_rssi_threshold(const mesh_rssi_threshold_t *threshold); + +/** + * @brief get RSSI threshold + * @param threshold RSSI threshold + * + * @return + * - ESP_OK + * - ESP_ERR_MESH_ARGUMENT + */ +esp_err_t esp_mesh_get_rssi_threshold(mesh_rssi_threshold_t *threshold); + +/** + * @brief enable the minimum rate to 6Mbps + * + * @attention This API shall be called before WiFi start. + * + * @param is_6m enable or not + * + * @return + * - ESP_OK + */ +esp_err_t esp_mesh_set_6m_rate(bool is_6m); + /** * @brief print the number of txQ waiting * @@ -195,6 +240,29 @@ esp_err_t esp_mesh_set_passive_scan_time(int time_ms); */ int esp_mesh_get_passive_scan_time(void); +/** + * @brief set announce interval + * The default short interval is 500 milliseconds. + * The default long interval is 3000 milliseconds. + * + * @param short_ms shall be greater than the default value + * @param long_ms shall be greater than the default value + * + * @return + * - ESP_OK + */ +esp_err_t esp_mesh_set_announce_interval(int short_ms, int long_ms); + +/** + * @brief get announce interval + * + * @param short_ms short interval + * @param long_ms long interval + * + * @return + * - ESP_OK + */ +esp_err_t esp_mesh_get_announce_interval(int *short_ms, int *long_ms); #ifdef __cplusplus } diff --git a/components/esp32/include/esp_phy_init.h b/components/esp32/include/esp_phy_init.h index 0228edf1cf..f06375d1a6 100644 --- a/components/esp32/include/esp_phy_init.h +++ b/components/esp32/include/esp_phy_init.h @@ -58,6 +58,7 @@ typedef enum{ MODEM_WIFI_STATION_MODULE, //!< Wi-Fi Station used MODEM_WIFI_SOFTAP_MODULE, //!< Wi-Fi SoftAP used MODEM_WIFI_SNIFFER_MODULE, //!< Wi-Fi Sniffer used + MODEM_WIFI_NULL_MODULE, //!< Wi-Fi Null mode used MODEM_USER_MODULE, //!< User used MODEM_MODULE_COUNT //!< Number of items }modem_sleep_module_t; @@ -73,7 +74,8 @@ typedef enum{ */ #define MODEM_WIFI_MASK ((1</xtensa/board.h - using a -I directive passed to the compiler. */ - -#error "Unspecified board. Missing -I directive to select supported Xtensa board, usually -I XTENSA_TOOLS_ROOT/xtensa-elf/include/xtensa/ (XTENSA_TOOLS_ROOT is root of Xtensa Tools install, see xt-run --show-config=xttools)" - -/* - * Copyright (c) 2013 Tensilica 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. - */ - diff --git a/components/esp32/include/xtensa/c6x-compat.h b/components/esp32/include/xtensa/c6x-compat.h deleted file mode 100644 index 4b17987ea9..0000000000 --- a/components/esp32/include/xtensa/c6x-compat.h +++ /dev/null @@ -1,1758 +0,0 @@ -/* - * Copyright (c) 2006-2010 Tensilica Inc. 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. - */ - -#ifndef __C6X_COMPAT__H -#define __C6X_COMPAT__H - -/* Unimplemented functions _gmpy, _gmpy4, _xormpy, _lssub, _cmpy, _cmpyr, - _cmpyr1, _ddotpl2r, _ddotph2r */ - - -typedef long long C6X_COMPAT_LONG40; - - -#define _memd8(a) (*((double*)(a))) -#define _memd8_const(a) (*((const double*)(a))) - -#define _amemd8(a) (*((double*)(a))) -#define _amemd8_const(a) (*((const double*)(a))) - -#define _mem8(a) (*((unsigned long long*)(a))) -#define _mem8_const(a) (*((const unsigned long long*)(a))) - -#define _mem4(a) (*((unsigned*)(a))) -#define _mem4_const(a) (*((const unsigned*)(a))) -#define _amem4_const(a) (*((const unsigned*)(a))) - -/* NOTE: To emulate a C6X properly you should define global variables - for your Xtensa with these names. Some of the emulation routines - will set these values. */ - -extern int _carry; -extern int _overflow; - -// Utility routines - - -#define TESTBIT(x,n) (((x) >> (n)) & 1) - -#define NSA_BITS 32 - -static inline unsigned int norm_shift_amt_U_and_non_U(int is_signed, int inp) { -int j=0, k=0; -int x=inp; -if (is_signed) { - /* Invert signed val if negative */ - x= TESTBIT(x,(NSA_BITS-1))? ~x: x; - x= (x&1)|(x<<1); /* Shift up to return count-1 */ - if (x ==0) - return NSA_BITS-1; - } - if (x ==0) - return NSA_BITS; - /* Now count leading zeros */ - for (j=0, k=NSA_BITS-1; k>=0; j++, k--) { - if (TESTBIT(x,k)) - return j; - } - return NSA_BITS; -} - - - -static inline long long -orig_L40_set( long long L40_var1) { - long long L40_var_out; - - L40_var_out = L40_var1 & 0x000000ffffffffffLL; - - if( L40_var1 & 0x8000000000LL) - L40_var_out = L40_var_out | 0xffffff0000000000LL; - - return( L40_var_out); -} - - - -static inline signed long long -util_saturate_n_no_state(signed long long t, int n) -{ - signed long long maxv, minv; - maxv = (1LL << (n-1)) - 1; - minv = (-1LL << (n-1)); - if (t > maxv) { - t = maxv; - } else if (t < minv) { - t = minv; - } - return t; -} - - -static inline signed long long -util_saturate_n_sgn(signed long long t, int n) -{ - signed long long result; - signed long long maxv, minv; - maxv = (1LL << (n-1)) - 1; - minv = (-1LL << (n-1)); - if (t > 0) { - result = maxv; - _overflow = 1; - } else if (t < 0) { - result = minv; - _overflow = 1; - } else { - result = 0; - } - return result; -} - - - - -/* well-behaved signed shift right (left on negative) with - saturation */ -static inline signed long long -util_shift_right_saturate_n(signed long long t, int shval, int n) -{ - /* n should be <= 62 */ - long long result; - - signed long long mask; - int actual_shift = shval; - long long shft = actual_shift > 0 ? actual_shift : -actual_shift; - - if (t == 0 || actual_shift == 0) - return t; - - if (actual_shift >= n) { - return (t < 0) ? -1 : 0; - } - if (actual_shift <= -n) { - return util_saturate_n_sgn(t, n); - } - if (actual_shift > 0) { - return t >> actual_shift; - } - /* actual_shift < 0. Check for saturation after shift. */ - mask = (-1LL << (n-shft-1)); - if (t > 0 && ((mask & t) != 0)) { - return util_saturate_n_sgn(t, n); - } - if (t < 0 && ((mask & t) != mask)) { - return util_saturate_n_sgn(t, n); - } - result = t << shft; - - return result; -} - - -/* Implemented c6x standard C compatibility functions (alphabetical - order) */ - - -static inline int _abs(int src1) { - if ((unsigned) src1 == (unsigned) 0x80000000) { - return 0x7fffffff; - } - return abs(src1); -} - - -static inline int _abs2(int src1) { - short s1[2],r[2]; - int result; - *((int*)s1) = src1; - if ((unsigned short) s1[1] == (unsigned short) 0x8000) r[1] = 0x7fff; - else r[1] = abs(s1[1]); - if ((unsigned short) s1[0] == (unsigned short) 0x8000) r[0] = 0x7fff; - else r[0] = abs(s1[0]); - result = *(int*)r; - return result; - } - - - - -static inline int _add2(int src1, int src2) { - short s1[2], s2[2], r[2]; - int result; - *((int*)s1) = src1; - *((int*)s2) = src2; - r[0] = s1[0] + s2[0]; - r[1] = s1[1] + s2[1]; - result = *(int*)r; - return result; -} - -static inline int _add4(int src1, int src2) { - char c1[4], c2[4], r[4]; - int result; - *((int*)c1) = src1; - *((int*)c2) = src2; - r[0] = c1[0] + c2[0]; - r[1] = c1[1] + c2[1]; - r[2] = c1[2] + c2[2]; - r[3] = c1[3] + c2[3]; - result = *(int*)r; - return result; -} - - - -static inline long long _addsub(unsigned int src1, unsigned int src2) -{ - - int res_lo; - int res_hi; - - res_hi = src1+src2; - res_lo = src1-src2; - return (((unsigned long long) res_hi) << 32) | ((unsigned int) res_lo) ; -} - - -static inline long long _addsub2(unsigned int src1, unsigned int src2) -{ - short s1[2], s2[2], ra[2], rs[2]; - int res_lo; - int res_hi; - - *((int*)s1) = src1; - *((int*)s2) = src2; - ra[0] = s1[0] + s2[0]; - ra[1] = s1[1] + s2[1]; - rs[0] = s1[0] - s2[0]; - rs[1] = s1[1] - s2[1]; - - res_hi = *(int*)ra; - res_lo = *(int*)rs; - return (((unsigned long long) res_hi) << 32) | ((unsigned int) res_lo) ; -} - - -static inline int _avg2(int src1, int src2) { - int low = (((int)1 + (short) src1 + (short) src2) >> 1) & 0XFFFF; - int high1 = src1 >> 16; - int high2 = src2 >> 16; - int high = ((high1 + high2 + 1) >> 1)<< 16; - return high | low; -} - - - -static inline unsigned int _avgu4(unsigned int src1, unsigned int src2) { -unsigned int res0 = ((src1 & 0xFF) + (src2 & 0xFF) + 1) >> 1; - unsigned int res1 = (((src1 & 0xFF00) >> 8) + ((src2 & 0xFF00) >> 8) + 1) >> 1; - unsigned int res2 = (((src1 & 0xFF0000) >> 16) + ((src2 & 0xFF0000) >> 16) + 1) >> 1; - unsigned int res3 = (((src1 & 0xFF000000) >> 24) + ((src2 & 0xFF000000) >> 24) + 1) >> 1; - return (res3 << 24) | (res2 << 16) | (res1 << 8) | res0; -} - - -static inline int TEN_popc (unsigned char b) -{ - int i, result = 0; - for (i = 0; i < 8; i++){ - if (b & 0x1) - result++; - b >>= 1; - } - return result; -} - -static inline unsigned int _bitc4(unsigned int src1) -{ - unsigned int res0 = TEN_popc(src1 & 0xFF); - unsigned int res1 = TEN_popc((src1 & 0xFF00) >> 8); - unsigned int res2 = TEN_popc((src1 & 0xFF0000) >> 16); - unsigned int res3 = TEN_popc((src1 & 0xFF000000) >> 24); - return (res3 << 24) | (res2 << 16) | (res1 << 8) | res0; -} - -static inline unsigned int _bitr(unsigned int src) { - int i; - unsigned r = 0; - for (i = 0; i< 32; ++i) { - r = r | (((src >> i) & 1)<<(31-i)); - } - return r; -} - - -static inline unsigned int _clr(unsigned int src2, int csta, int cstb) -{ - csta &= 0x1f; - cstb &= 0x1f; - if (csta > cstb) - return src2; - else { - unsigned int mask = (((1 << (cstb - csta)) << 1) - 1) << csta; - return src2 & (~mask); - } -} - -static inline unsigned int _clrr(unsigned int src2, int src1) -{ - unsigned int csta = (src1 >> 5) & 0x1f; - unsigned int cstb = src1 & 0x1f; - if (csta > cstb) - return src2; - else { - unsigned int mask = (((1 << (cstb - csta)) << 1) - 1) << csta; - return src2 & (~mask); - } -} - - - - -static inline int _cmpeq2(int src1, int src2) { - short s1[2], s2[2]; - int r0, r1; - int result; - *((int*)s1) = src1; - *((int*)s2) = src2; - r0 = s1[0] == s2[0] ? 1 : 0; - r1 = s1[1] == s2[1] ? 1 : 0; - result = (r1 << 1) | r0; - return result; -} - -static inline int _cmpeq4(int src1, int src2) { - char s1[4], s2[4]; - int r0, r1, r2, r3; - int result; - *((int*)s1) = src1; - *((int*)s2) = src2; - r0 = s1[0] == s2[0] ? 1 : 0; - r1 = s1[1] == s2[1] ? 1 : 0; - r2 = s1[2] == s2[2] ? 1 : 0; - r3 = s1[3] == s2[3] ? 1 : 0; - result = (r3 << 3) | (r2 << 2) | (r1 << 1) | r0; - return result; -} - - -static inline int _cmpgt2(int src1, int src2) { - short s1[2], s2[2]; - int r1, r0; - int result; - *((int*)s1) = src1; - *((int*)s2) = src2; - r0 = s1[0] > s2[0] ? 1 : 0; - r1 = s1[1] > s2[1] ? 1 : 0; - result = (r1<<1) | r0; - return result; -} - - -static inline unsigned int _cmpgtu4(unsigned int src1, unsigned int src2) { - unsigned int s1_0 = (src1 & 0xFF); - unsigned int s1_1 = (src1 & 0xFF00) >> 8; - unsigned int s1_2 = (src1 & 0xFF0000) >> 16; - unsigned int s1_3 = (src1 & 0xFF000000) >> 24; - - unsigned int s2_0 = (src2 & 0xFF); - unsigned int s2_1 = (src2 & 0xFF00) >> 8; - unsigned int s2_2 = (src2 & 0xFF0000) >> 16; - unsigned int s2_3 = (src2 & 0xFF000000) >> 24; - - unsigned int result = 0; - - if (s1_0 > s2_0) - result |= 0x1; - - if (s1_1 > s2_1) - result |= 0x2; - - if (s1_2 > s2_2) - result |= 0x4; - - if (s1_3 > s2_3) - result |= 0x8; - - return result; -} - - - - -static inline long long _ddotp4(unsigned int src1, unsigned int src2) { - unsigned int res0, res1; - short s1_0 = (src1 & 0xffff); - short s1_1 = (src1 & 0xfff0000) >> 16; - - unsigned short s2_0 = (src2 & 0xff); - unsigned short s2_1 = (src2 & 0xff00) >> 8; - unsigned short s2_2 = (src2 & 0xff0000) >> 16; - unsigned short s2_3 = (src2 & 0xff000000) >> 24; - - res0 = ((int)s1_0) * s2_0 + ((int)s1_1) * s2_1; - res1 = ((int)s1_0) * s2_2 + ((int)s1_1) * s2_3; - - return (res1 << 16) | res0; -} - - -static inline long long _ddotph2(long long src1_o_src1_e, unsigned int src2) -{ - - unsigned int src1_o = src1_o_src1_e >> 32; - unsigned int src1_e = src1_o_src1_e & 0xFFFFFFFF; - short ls1_o = src1_o & 0XFFFF; - short hs1_o = src1_o >> 16; -// short ls1_e = src1_e & 0XFFFF; - short hs1_e = src1_e >> 16; - short ls2 = src2 & 0XFFFF; - short hs2 = src2 >> 16; - - unsigned long long res_hi = ls2 * ls1_o + hs2 * hs1_o; - unsigned int res_lo = ls1_o * hs2 + hs1_e * ls2; - return (res_hi << 32) | res_lo; -} - - -static inline long long _ddotpl2(long long src1_o_src1_e, unsigned int src2) -{ - unsigned int src1_o = src1_o_src1_e >> 32; - unsigned int src1_e = src1_o_src1_e & 0xFFFFFFFF; - short ls1_o = src1_o & 0XFFFF; -// short hs1_o = src1_o >> 16; - short ls1_e = src1_e & 0XFFFF; - short hs1_e = src1_e >> 16; - short ls2 = src2 & 0XFFFF; - short hs2 = src2 >> 16; - - unsigned long long res_hi = ls2 * hs1_e + hs2 * ls1_o; - unsigned res_lo = hs1_e * hs2 + ls1_e * ls2; - return (res_hi << 32) | res_lo; -} - - -static inline unsigned int _deal(unsigned int src) -{ - int i; - unsigned short lo = 0, hi = 0; - for (i = 0; i < 32; i+= 2) { - lo >>= 1; - lo |= (src & 0x1) << 15; - src >>= 1; - hi >>= 1; - hi |= (src & 0x1) << 15; - src >>= 1; - } - return (hi << 16) | lo; -} - - -static inline long long _dmv(unsigned int src1, unsigned int src2) -{ - return (((long long) src1) << 32) | src2; -} - - -static inline int _dotpn2(int src1, int src2) { -short int s1_h = src1>>16; - short int s1_l = src1; - short int s2_h = src2>>16; - short int s2_l = src2; - return s1_h * s2_h - s1_l * s2_l; -} - - -static inline int _dotp2(int src1, int src2) { - short int s1_h = src1>>16; - short int s1_l = src1; - short int s2_h = src2>>16; - short int s2_l = src2; - return s1_h * s2_h + s1_l * s2_l; -} - - - -static inline int _dotpnrsu2(int src1, unsigned int src2) -{ - short ls1 = src1 & 0XFFFF; - unsigned short ls2 = src2 & 0XFFFF; - short hs1 = src1 >> 16; - unsigned short hs2 = src2 >> 16; - - int result = (((long long) (int)(hs1 * hs2)) - ((long long) (int)(ls1 * ls2)) + (1 << 15)) >> 16; - return result; -} - - - -static inline int _dotprsu2(int src1, unsigned int src2) { - short ls1 = src1 & 0XFFFF; - unsigned short ls2 = (src2 & 0XFFFF); - short hs1 = src1 >> 16; - unsigned short hs2 = (src2 >> 16); - - int result = (((long long) (int) (ls1 * ls2)) + ((long long) (int) (hs1 * hs2)) + (1LL << 15)) >> 16; - return result; -} - - - - - - - -static inline int _dotpsu4(int src1, unsigned int src2) { - int result; - signed char s1_0 = (src1 & 0xff); - signed char s1_1 = (src1 & 0xff00) >> 8; - signed char s1_2 = (src1 & 0xff0000) >> 16; - signed char s1_3 = (src1 & 0xff000000) >> 24; - - unsigned int s2_0 = (src2 & 0xff); - unsigned int s2_1 = (src2 & 0xff00) >> 8; - unsigned int s2_2 = (src2 & 0xff0000) >> 16; - unsigned int s2_3 = (src2 & 0xff000000) >> 24; - - result = s1_0 * s2_0 + s1_1 * s2_1 + s1_2 * s2_2 + s1_3 * s2_3; - return result; -} - - -static inline unsigned int _dotpu4(unsigned int src1, unsigned int src2) { - unsigned char v1_0 = src1 & 0xff; - unsigned char v1_1 = (src1>>8) & 0xff; - unsigned char v1_2 = (src1>>16) & 0xff; - unsigned char v1_3 = (src1>>24) & 0xff; - - unsigned char v2_0 = src2 & 0xff; - unsigned char v2_1 = (src2>>8) & 0xff; - unsigned char v2_2 = (src2>>16) & 0xff; - unsigned char v2_3 = (src2>>24) & 0xff; - - unsigned v = v1_0 * v2_0 + v1_1 * v2_1 + v1_2 * v2_2 + v1_3 * v2_3; - return v; -} - - -static inline long long _dpack2(unsigned int src1, unsigned int src2){ -unsigned short s1[2], s2[2]; -*((int*)s1) = src1; -*((int*)s2) = src2; -return ((unsigned long long) s1[1] << 48) | ((unsigned long long) s2[1] << 32) | ((unsigned long long) s1[0] << 16) | ((unsigned long long) s2[0]); -} - - -static inline long long _dpackx2(unsigned int src1, unsigned int src2){ -unsigned short s1[2], s2[2]; -*((int*)s1) = src1; -*((int*)s2) = src2; -return ((unsigned long long) s2[0] << 48) | ((unsigned long long) s1[1] << 32) | ((unsigned long long) s1[0] << 16) | ((unsigned long long) s2[1]); -} - -static inline int _ext(int src2, unsigned int csta, unsigned int cstb) -{ - return (src2 << csta) >> cstb; -} - -static inline int _extr(int src2, int src1) -{ - unsigned int csta = (src1 >> 5) & 0x1f; - unsigned int cstb = src1 & 0x1f; - return (src2 << csta) >> cstb; -} - -static inline unsigned int _extu(unsigned int src2, unsigned int csta, unsigned int cstb) -{ - return (src2 << csta) >> cstb; -} - -static inline unsigned int _extur(unsigned int src2, int src1) -{ - unsigned int csta = (src1 >> 5) & 0x1f; - unsigned int cstb = src1 & 0x1f; - return (src2 << csta) >> cstb; -} - - -static inline unsigned long long _hi(double src) { - unsigned long long v; - *(double*)&v = src; - return v>>32; -} - -static inline unsigned int _hill (long long src) -{ - return (unsigned int) (src >> 32); -} - - - -static inline double _itod(unsigned hi, unsigned lo) { - double v; - unsigned long long ll = ((((unsigned long long)(hi))<<32) | (unsigned long long)((unsigned)lo)); - *((unsigned long long *)&v) = ll; - return v; -} - - -static inline long long _itoll(unsigned int src2, unsigned int src1) -{ - return (((long long) src2) << 32) | src1; -} - - -static inline C6X_COMPAT_LONG40 _labs(C6X_COMPAT_LONG40 src2) -{ - long long maxv = (1LL << (40 -1)) - 1; - long long minv = (-1LL << (40 - 1)); - C6X_COMPAT_LONG40 lres = orig_L40_set(src2); - - lres = lres < 0 ? -lres : lres; - if (lres > maxv) lres = maxv; - else if (lres < minv) lres = minv; - - return lres; -} - - -static inline C6X_COMPAT_LONG40 _ldotp2(int src1, int src2) { -return (C6X_COMPAT_LONG40) _dotp2(src1, src2); -} - - -static inline unsigned int _lmbd(unsigned int src1, unsigned int src2) -{ - return norm_shift_amt_U_and_non_U(0,(((int) (src1 << 31)) >> 31) ^ (~src2)); -} - - -static inline unsigned int _lnorm(C6X_COMPAT_LONG40 src2) { -if (src2 == 0) - return 39; - else { - int hi = (int)(src2 >> 32); - int lo = (int)src2; - - - long long temp = (unsigned long long)(unsigned)lo | (unsigned long long)hi << 32; - temp = orig_L40_set(temp); - - if (temp == 0) return 0; - int cnt = 0; - while (((temp >> 39) & 1) == ((temp >> 38) & 1)) { - temp <<= 1; - cnt++; - } - return cnt; - } -} - - -static inline unsigned long long _lo(double src) { - unsigned long long v; - *(double*)&v = src; - return v; -} - - -static inline unsigned int _loll (long long src) -{ - return (unsigned int) src; -} - - -static inline C6X_COMPAT_LONG40 _lsadd(int src1, C6X_COMPAT_LONG40 src2) -{ - long long maxv = (1LL << (40 -1)) - 1; - long long minv = (-1LL << (40 - 1)); - int hi = (int)(src2 >> 32); - int lo = (int)src2; - long long src2_int = (unsigned long long)(unsigned)lo | (unsigned long long)hi << 32; - - - long long src2_int2 = orig_L40_set(src2_int); - - long long res = src1 + src2_int2; - - if (res > maxv) { - res = maxv; - _overflow = 1; - } - else if (res < minv) { - res = minv; - _overflow = 1; - } - - long long res2 = orig_L40_set(res); - - res2 = (signed char)(res2 >> 32); - - C6X_COMPAT_LONG40 lres = (((C6X_COMPAT_LONG40) res2) << 32) | ((unsigned int)res); - return lres; -} - - - -static inline int _max2 (int src1, int src2) { - short s1[2], s2[2], r[2]; - int result; - *((int*)s1) = src1; - *((int*)s2) = src2; - r[0] = s1[0] > s2[0] ? s1[0] : s2[0]; - r[1] = s1[1] > s2[1] ? s1[1] : s2[1]; - result = *(int*)r; - return result; -} - - - - - - -static inline unsigned int _maxu4(unsigned int src1, unsigned int src2) { - unsigned int res0, res1, res2, res3; - unsigned int s1_0 = res0 = (src1 & 0xFF); - unsigned int s1_1 = res1 = (src1 & 0xFF00) >> 8; - unsigned int s1_2 = res2 = (src1 & 0xFF0000) >> 16; - unsigned int s1_3 = res3 = (src1 & 0xFF000000) >> 24; - - unsigned int s2_0 = (src2 & 0xFF); - unsigned int s2_1 = (src2 & 0xFF00) >> 8; - unsigned int s2_2 = (src2 & 0xFF0000) >> 16; - unsigned int s2_3 = (src2 & 0xFF000000) >> 24; - -// unsigned int res = 0; - - if (s1_0 < s2_0) - res0 = s2_0; - - if (s1_1 < s2_1) - res1 = s2_1; - - if (s1_2 < s2_2) - res2 = s2_2; - - if (s1_3 < s2_3) - res3 = s2_3; - - return (res3 << 24) | (res2 << 16) | (res1 << 8) | res0; - - -} - -static inline int _min2(int src1, int src2) { - short s1[2], s2[2], r[2]; - int result; - *((int*)s1) = src1; - *((int*)s2) = src2; - r[0] = s1[0] < s2[0] ? s1[0] : s2[0]; - r[1] = s1[1] < s2[1] ? s1[1] : s2[1]; - result = *(int*)r; - return result; -} - - -static inline unsigned int _minu4(unsigned int src1, unsigned int src2) { -unsigned int res0, res1, res2, res3; - unsigned int s1_0 = res0 = (src1 & 0xFF); - unsigned int s1_1 = res1 = (src1 & 0xFF00) >> 8; - unsigned int s1_2 = res2 = (src1 & 0xFF0000) >> 16; - unsigned int s1_3 = res3 = (src1 & 0xFF000000) >> 24; - - unsigned int s2_0 = (src2 & 0xFF); - unsigned int s2_1 = (src2 & 0xFF00) >> 8; - unsigned int s2_2 = (src2 & 0xFF0000) >> 16; - unsigned int s2_3 = (src2 & 0xFF000000) >> 24; - -// unsigned int res = 0; - - if (s1_0 > s2_0) - res0 = s2_0; - - if (s1_1 > s2_1) - res1 = s2_1; - - if (s1_2 > s2_2) - res2 = s2_2; - - if (s1_3 > s2_3) - res3 = s2_3; - - return (res3 << 24) | (res2 << 16) | (res1 << 8) | res0; -} - - -static inline int _mpy(int src1, int src2) { -return (short) src1 * (short) src2; -} - - -static inline int _mpyh(int src1, int src2) { -return (short) (src1 >> 16) * (short) (src2 >> 16); -} - - -static inline long long _mpyhill (int src1, int src2) -{ - short s1 = src1 >> 16; - return ((long long) src2) * s1; -} - -static inline int _mpyhir(int src1, int src2) -{ - short s1 = src1 >> 16; - long long result = ((long long) src2) * s1 + (1 << 14); - result >>= 15; - return result; -} - - -static inline int _mpyhl(int src1, int src2) { -return (short) (src1 >> 16) * (short) (src2); -} - -static inline unsigned int _mpyhlu(unsigned int src1, unsigned int src2) { -return (unsigned short) (src1 >> 16) * (unsigned short) (src2); -} - -static inline int _mpyhslu(int src1, unsigned int src2) { -return (short) (src1 >> 16) * (unsigned short) src2; -} - - -static inline int _mpyhsu(int src1, unsigned int src2) { -return (short) (src1 >>16) * (unsigned short) (src2 >>16); -} - - -static inline unsigned int _mpyhu(unsigned int src1, unsigned int src2) { -return (unsigned short) (src1 >>16) * (unsigned short) (src2 >> 16); -} - - -static inline int _mpyhuls(unsigned int src1, int src2) { -return (unsigned short) (src1 >>16) * (signed short) (src2); -} - - -static inline int _mpyhus(unsigned int src1, int src2) { -return (unsigned short) (src1 >> 16) * (short) (src2 >>16); -} - - - -static inline long long _mpyidll (int src1, int src2) -{ - return (long long) src1 * src2; -} - - -static inline int _mpylh(int src1, int src2) { -return (signed short) (src1 & 0xffff) * (signed short) (src2 >> 16); -} - -static inline unsigned int _mpylhu(unsigned int src1, unsigned int src2) { -return (unsigned short) src1 * (unsigned short) (src2 >> 16); -} - - -static inline long long _mpylill (int src1, int src2) -{ - return ((long long) src2) * ((short)src1); -} - - - -static inline int _mpylir(int src1, int src2) -{ - short s1 = src1; - long long result = ((long long) src2) * s1 + (1 << 14); - result >>= 15; - return result; -} - - -static inline int _mpylshu(int src1, unsigned int src2) { -return (short) src1 * (unsigned short) (src2 >> 16); -} - - -static inline int _mpyluhs(unsigned int src1, int src2) { -return (unsigned short) src1 * (short) (src2 >> 16); -} - - - -static inline int _mpysu(int src1, unsigned int src2) { -return (short) src1 * (unsigned short) src2; -} - - - -static inline long long _mpysu4ll (int src1, unsigned int src2) { - unsigned short res0, res1, res2, res3; - signed char s1_0 = (src1 & 0xff); - signed char s1_1 = (src1 & 0xff00) >> 8; - signed char s1_2 = (src1 & 0xff0000) >> 16; - signed char s1_3 = (src1 & 0xff000000) >> 24; - - unsigned short s2_0 = (src2 & 0xff); - unsigned short s2_1 = (src2 & 0xff00) >> 8; - unsigned short s2_2 = (src2 & 0xff0000) >> 16; - unsigned short s2_3 = (src2 & 0xff000000) >> 24; - - res0 = s1_0 * s2_0; - res1 = s1_1 * s2_1; - res2 = s1_2 * s2_2; - res3 = s1_3 * s2_3; - - return (((unsigned long long) res3) << 48) - | (((unsigned long long) res2) << 32) - | (((unsigned long long) res1) << 16) - | res0; -} - -static inline unsigned int _mpyu(unsigned int src1, unsigned int src2) { - unsigned v = (unsigned short)src1 * (unsigned short)src2; - return v; -} - -static inline int _mpyus(unsigned int src1, int src2) { -return (unsigned short) src1 * (short) src2; -} - -static inline long long _mpyu4ll (unsigned int src1, unsigned int src2) { - unsigned short res0, res1, res2, res3; - unsigned char s1_0 = (src1 & 0xff); - unsigned char s1_1 = (src1 & 0xff00) >> 8; - unsigned char s1_2 = (src1 & 0xff0000) >> 16; - unsigned char s1_3 = (src1 & 0xff000000) >> 24; - - unsigned short s2_0 = (src2 & 0xff); - unsigned short s2_1 = (src2 & 0xff00) >> 8; - unsigned short s2_2 = (src2 & 0xff0000) >> 16; - unsigned short s2_3 = (src2 & 0xff000000) >> 24; - - res0 = s1_0 * s2_0; - res1 = s1_1 * s2_1; - res2 = s1_2 * s2_2; - res3 = s1_3 * s2_3; - - return (((unsigned long long) res3) << 48) - | (((unsigned long long) res2) << 32) - | (((unsigned long long) res1) << 16) - | res0; -} - - -static inline long long _mpy2ir(unsigned int src1, unsigned int src2) -{ - if ((src1 == 0x8000) && (src2 == 0x80000000)) { - _overflow = 1; - return 0; - } - else { - short ls1 = src1 & 0xffff; - short hs1 = src1 >> 16; - unsigned long long hi = (((long long) hs1) * (int) src2 + (1 << 14)) >> 15; - unsigned long long lo = ((((long long) ls1) * (int) src2 + (1 << 14)) >> 15) & 0xFFFFFFFF; - return (hi << 32) | lo; - } -} - - -static inline long long _mpy2ll (int src1, int src2) { - short ls1 = src1 & 0xffff; - short hs1 = src1 >> 16; - short ls2 = src2 & 0xffff; - short hs2 = src2 >> 16; - - unsigned long long hi = hs1 * hs2; - unsigned long long lo = (ls1 * ls2) & 0xFFFFFFFF; - - return (hi << 32) | lo; - -} - - -static inline int _mpy32(int src1, int src2) -{ - return src1 * src2; -} - - -static inline long long _mpy32ll(int src1, int src2) -{ - return ((long long) src1) * src2; -} - -static inline long long _mpy32su(int src1, unsigned int src2) -{ - return ((long long) src1) * ((int) src2); -} - -static inline long long _mpy32u(unsigned int src1, unsigned int src2) -{ - return ((long long) ((int) src1)) * ((long long) ((int) src2)); -} - -static inline long long _mpy32us(unsigned int src1, int src2) -{ - return ((int) src1) * ((long long) src2); -} - -static inline int _mvd (int src2) -{ - return src2; -} - - -static inline unsigned int _norm(int src2) -{ - return norm_shift_amt_U_and_non_U(1,src2); -} - - -static inline unsigned int _pack2 (unsigned int src1, unsigned int src2) { - short s1[2], s2[2], r[2]; - int result; - *((int*)s1) = src1; - *((int*)s2) = src2; - r[0] = s2[0]; - r[1] = s1[0]; - result = *(int*)r; - return result; -} - - -static inline int _packh2 (unsigned int src1, unsigned int src2) { - unsigned v0 = src1 & 0xffff0000; - unsigned v1 = src2 >> 16; - unsigned v = v0|v1; - return v; - -} - -static inline unsigned int _packh4 (unsigned int src1, unsigned int src2) { - unsigned v3 = (src1 >> 24) & 0xff; - unsigned v2 = (src1 >> 8) & 0xff; - unsigned v1 = (src2 >> 24) & 0xff; - unsigned v0 = (src2 >> 8) & 0xff; - unsigned v = (v3<<24) | (v2<<16) | (v1 << 8) | v0; - return v; -} - -static inline unsigned int _packhl2 (unsigned int src1, unsigned int src2) { - unsigned v0 = src1 & 0xffff0000; - unsigned v1 = src2 & 0x0000ffff; - unsigned v = v0|v1; - return v; -} - -static inline unsigned int _packlh2 (unsigned int src1, unsigned int src2) { - unsigned v0 = src1 << 16; - unsigned v1 = (src2 >> 16) & 0xffff; - unsigned v = v0|v1; - return v; -} - - - - -static inline unsigned int _packl4 (unsigned int src1, unsigned int src2) { - unsigned v3 = (src1 >> 16) & 0xff; - unsigned v2 = (src1) & 0xff; - unsigned v1 = (src2 >> 16) & 0xff; - unsigned v0 = (src2) & 0xff; - unsigned v = (v3<<24) | (v2<<16) | (v1 << 8) | v0; - return v; -} - - - - -static inline unsigned int _rpack2 (unsigned int src1, unsigned int src2) { -int s1 = (int) src1; -int s2 = (int) src2; -s1 = util_shift_right_saturate_n (s1, -1, 32); -s2 = util_shift_right_saturate_n (s2, -1, 32); -return (unsigned int) (s1 & 0xffff0000) | (unsigned int) ((s2 & 0xffff0000) >>16); -} - - -static inline unsigned int _rotl (unsigned int src1, unsigned int src2) -{ - src2 &= 0x1f; - return (src1 << src2) | (src1 >> (32 - src2)); -} - - -static inline int _sadd(int src1, int src2) { -signed long long res; -signed long long maxv, minv; -maxv = (1LL << (32-1)) - 1; -minv = (-1LL << (32-1)); -res = (long long) src1 + (long long) src2; -if (res > maxv) { - res = maxv; - _overflow = 1; - } -else if (res < minv ) { - res = minv; - _overflow = 1; - } -return (int) res; -} - -static inline long long _saddsub(unsigned int src1, unsigned int src2) { -int radd; -signed long long rsub; - -signed long long maxv, minv; -maxv = (1LL << (32-1)) - 1; -minv = (-1LL << (32-1)); - -radd = (int) src1 + (int) src2; - -// saturate on subtract, not add - - -rsub = (long long) ((int) src1) - (long long) ((int) src2); -if (rsub > maxv) { - rsub = maxv; - /* NOTE: TI c6x does NOT set the overflow register even if results saturate */ - /* _overflow = 1; */ - } -else if (rsub < minv ) { - rsub = minv; - /* NOTE: TI c6x does NOT set the overflow register even if results saturate */ - /* _overflow = 1; */ - } - -return (((unsigned long long) radd) << 32) | ( rsub & 0x00000000ffffffff ) ; -} - - - -static inline long long _saddsub2(unsigned int src1, unsigned int src2) { -signed int radd[2]; -signed int rsub[2]; -signed short s1[2], s2[2]; - -signed int maxv, minv; -maxv = (1L << (16-1)) - 1; -minv = (-1L << (16-1)); - -*((int*)s1) = src1; -*((int*)s2) = src2; - -radd[0] = (int) s1[0] + (int) s2[0]; -radd[1] = (int) s1[1] + (int) s2[1]; - -rsub[0] = (int) s1[0] - (int) s2[0]; -rsub[1] = (int) s1[1] - (int) s2[1]; - -if (radd[0] > maxv) { - radd[0] = maxv; - /* NOTE: TI c6x does NOT set the overflow register even if results saturate */ - /* _overflow = 1; */ - } -else if (radd[0] < minv ) { - radd[0] = minv; - /* NOTE: TI c6x does NOT set the overflow register even if results saturate */ - /* _overflow = 1; */ - } - -if (radd[1] > maxv) { - radd[1] = maxv; - /* NOTE: TI c6x does NOT set the overflow register even if results saturate */ - /* _overflow = 1; */ - } -else if (radd[1] < minv ) { - radd[1] = minv; - /* NOTE: TI c6x does NOT set the overflow register even if results saturate */ - /* _overflow = 1; */ - } - - -if (rsub[0] > maxv) { - rsub[0] = maxv; - /* NOTE: TI c6x does NOT set the overflow register even if results saturate */ - /* _overflow = 1; */ - } -else if (rsub[0] < minv ) { - rsub[0] = minv; - /* NOTE: TI c6x does NOT set the overflow register even if results saturate */ - /* _overflow = 1; */ - } - -if (rsub[1] > maxv) { - rsub[1] = maxv; - /* NOTE: TI c6x does NOT set the overflow register even if results saturate */ - /* _overflow = 1; */ - } -else if (rsub[1] < minv ) { - rsub[1] = minv; - /* NOTE: TI c6x does NOT set the overflow register even if results saturate */ - /* _overflow = 1; */ - } - - -return ((((unsigned long long) radd[1]) & 0x000000000000ffff) << 48) | - ((((unsigned long long) radd[0]) & 0x000000000000ffff) << 32) | - ((((unsigned long long) rsub[1]) & 0x000000000000ffff) << 16) | - ((((unsigned long long) rsub[0]) & 0x000000000000ffff)); -} - - - -static inline int _sadd2(int src1, int src2) { -signed short s1[2], s2[2]; -signed int r[2], maxv, minv; - -maxv = (1L << (16-1)) - 1; -minv = (-1L << (16-1)); - - -*((int*)s1) = src1; -*((int*)s2) = src2; - -r[0] = (int) s1[0] + (int) s2[0]; -r[1] = (int) s1[1] + (int) s2[1]; - -if (r[0] > maxv) { - r[0] = maxv; - /* NOTE: TI c6x does NOT set the overflow register even if results saturate */ - /* _overflow = 1; */ - } -else if (r[0] < minv ) { - r[0] = minv; - /* NOTE: TI c6x does NOT set the overflow register even if results saturate */ - /* _overflow = 1; */ - } -if (r[1] > maxv) { - r[1] = maxv; - /* NOTE: TI c6x does NOT set the overflow register even if results saturate */ - /* _overflow = 1; */ - } -else if (r[1] < minv ) { - r[1] = minv; - /* NOTE: TI c6x does NOT set the overflow register even if results saturate */ - /* _overflow = 1; */ - } - -return ((r[1] & 0xffff) << 16 ) | (r[0] & 0xffff) ; -} - - -static inline int _saddus2(unsigned int src1, int src2) { -int res0, res1; - unsigned int s1_0 = (src1 & 0xffff); - unsigned int s1_1 = (src1 & 0xffff0000) >> 16; - - short s2_0 = (src2 & 0xffff); - short s2_1 = (src2 & 0xffff0000) >> 16; - - res0 = s1_0 + s2_0; - res1 = s1_1 + s2_1; - - if (res0 >= 0x10000) - res0 = 0xffff; - else if (res0 < 0) - res0 = 0; - - if (res1 >= 0x10000) - res1 = 0xffff; - else if (res1 < 0) - res1 = 0; - - return (res1 << 16) | res0; -} - - -static inline unsigned int _saddu4(unsigned int src1, unsigned int src2) { -unsigned int res0, res1, res2, res3; - unsigned int s1_0 = (src1 & 0xff); - unsigned int s1_1 = (src1 & 0xff00) >> 8; - unsigned int s1_2 = (src1 & 0xff0000) >> 16; - unsigned int s1_3 = (src1 & 0xff000000) >> 24; - - unsigned int s2_0 = (src2 & 0xff); - unsigned int s2_1 = (src2 & 0xff00) >> 8; - unsigned int s2_2 = (src2 & 0xff0000) >> 16; - unsigned int s2_3 = (src2 & 0xff000000) >> 24; - - res0 = s1_0 + s2_0; - res1 = s1_1 + s2_1; - res2 = s1_2 + s2_2; - res3 = s1_3 + s2_3; - - if (res0 >= 0x100) - res0 = 0xff; - - if (res1 >= 0x100) - res1 = 0xff; - - if (res2 >= 0x100) - res2 = 0xff; - - if (res3 >= 0x100) - res3 = 0xff; - - return (res3 << 24) | (res2 << 16) | (res1 << 8) | res0; - -} - - - -static inline int _sat(C6X_COMPAT_LONG40 src2) -{ - long long maxv = (1LL << (32-1)) - 1; - long long minv = (-1LL << (32-1)); - - int hi = (int)(src2 >> 32); - int lo = (int)src2; - long long temp = (unsigned long long)(unsigned)lo | (unsigned long long)hi << 32; - temp = orig_L40_set(temp); - - if (temp > maxv) { - temp = maxv; - _overflow = 1; - } - else if (temp < minv) { - temp = minv; - _overflow = 1; - } - return (int) temp; -} - -static inline unsigned int _set(unsigned int src2, unsigned int csta, unsigned int cstb) -{ - csta &= 0x1f; - cstb &= 0x1f; - if (csta > cstb) - return src2; - else { - unsigned int mask = (((1 << (cstb - csta)) << 1) - 1) << csta; - return src2 | mask; - } -} - -static inline unsigned int _setr(unsigned int src2, int src1) -{ - unsigned int csta = (src1 >> 5) & 0x1f; - unsigned int cstb = src1 & 0x1f; - if (csta > cstb) - return src2; - else { - unsigned int mask = (((1 << (cstb - csta)) << 1) - 1) << csta; - return src2 | mask; - } -} - - -static inline unsigned int _shfl (unsigned int src2) -{ - unsigned short lo = src2; - unsigned short hi = src2 >> 16; - unsigned int result = 0; - int i; - for (i = 0; i < 32; i+= 2) { - result >>= 1; - result |= (lo & 0x1) << 31; - lo >>= 1; - result >>= 1; - result |= (hi & 0x1) << 31; - hi >>= 1; - } - return result; -} - -static inline long long _shfl3 (unsigned int src1, unsigned int src2) -{ - unsigned short lo = src2; - unsigned short hi = src1 >> 16; - unsigned short mid = src1; - unsigned long long result = 0; - int i; - for (i = 0; i < 32; i+= 2) { - result >>= 1; - result |= ((unsigned long long) (lo & 0x1)) << 47; - lo >>= 1; - result >>= 1; - result |= ((unsigned long long) (mid & 0x1)) << 47; - mid >>= 1; - result >>= 1; - result |= ((unsigned long long) (hi & 0x1)) << 47; - hi >>= 1; - } - return result; -} - - - -static inline unsigned int _shlmb (unsigned int src1, unsigned int src2) -{ - return (src2 << 8) | (src1 >> 24); -} - -static inline unsigned int _shrmb (unsigned int src1, unsigned int src2) -{ - return (src2 >> 8) | (src1 << 24); -} - - -static inline unsigned int _shru2 (unsigned int src1, unsigned int src2) { -unsigned short hs1 = src1 >> 16; - unsigned short ls1 = src1 & 0xFFFF; - hs1 >>= src2; - ls1 >>= src2; - return (hs1 << 16) | ls1; -} - - -static inline int _shr2 (int src1, unsigned int src2) { - short s1[2], result[2]; - *((int*)s1) = src1; - src2 = src2 & 31; - result[0] = (int)s1[0] >> src2; - result[1] = (int)s1[1] >> src2; - - return *(int*)result; -} - - -static inline int _smpy (int src1, int src2) { -unsigned long long result; -result = (((short) src1 * (short) src2) << 1); - -if ((result & 0xffffffff) == 0x80000000){ - result = 0x7fffffff; - _overflow = 1; - } -return (int) (result); -} - -static inline int _smpyh (int src1, int src2) { -unsigned long long result; -result = ((short) (src1 >> 16) * (short) (src2 >> 16)) << 1; -if ((result & 0xffffffff) == 0x80000000){ - result = 0x7fffffff; - _overflow = 1; - } -return (int) (result); -} - -static inline int _smpyhl (int src1, int src2) { -unsigned long long result; -result = ((short) (src1 >> 16) * (short) (src2)) << 1; -if ((result & 0xffffffff) == 0x80000000){ - result = 0x7fffffff; - _overflow = 1; - } -return (int) (result); -} - -static inline int _smpylh (int src1, int src2) { -unsigned long long result; -result = ((short) (src1) * (short) (src2 >> 16)) << 1; -if ((result & 0xffffffff) == 0x80000000){ - result = 0x7fffffff; - _overflow = 1; - } -return (int) (result); -} - -static inline long long _smpy2ll (int src1, int src2) { - short ls1 = src1 & 0XFFFF; - short hs1 = src1 >> 16; - short ls2 = src2 & 0XFFFF; - short hs2 = src2 >> 16; - - unsigned long long hi = (hs1 * hs2) << 1; - unsigned long long lo = ((ls1 * ls2) << 1) & 0xFFFFFFFF; - if ((hi & 0xffffffff) == 0x80000000){ - hi = 0x7fffffff; - _overflow = 1; - } - - if ((lo & 0xffffffff) == 0x80000000){ - lo = 0x7fffffff; - _overflow = 1; - } - - return (hi << 32) | lo; -} - - - - -static inline int _smpy32(int src1, int src2) -{ - long long res = (long long) src1 * src2; - res <<= 1; - res >>= 32; - return res; -} - -static inline unsigned char TEN_satu8 (short src) -{ - if (src > 0xff) - return 0xff; - else if (src < 0) - return 0; - else - return src; -} - -static inline int _spack2 (int src1, int src2) { -short s1 = (short) util_saturate_n_no_state(src1,16); -short s2 = (short) util_saturate_n_no_state(src2,16); -return ( (unsigned int) s1 << 16) | (((int) s2) & 0xFFFF); -} - - -static inline unsigned int _spacku4 (int src1, int src2) { - short lolo = src2; - short lohi = src2 >> 16; - short hilo = src1; - short hihi = src1 >> 16; - - lolo = TEN_satu8(lolo); - lohi = TEN_satu8(lohi); - hilo = TEN_satu8(hilo); - hihi = TEN_satu8(hihi); - - return (((unsigned int) hihi) << 24) | (((unsigned int) hilo) << 16) | (lohi << 8) | lolo; -} - - - -static inline int _sshl (int src1, unsigned int src2) { -short local2 = (short)(src2 & 0x7FFF); -return (int) util_shift_right_saturate_n(src1, -local2, 32); -} - - - - -static inline int _sshvl (int src2, int src1) { - short s1; - if (src1 > 31) - s1 = 31; - else if (src1 < -31) - s1 = -31; - else - s1 = src1; - - return (int) util_shift_right_saturate_n(src2, -s1, 32); -} - - - - - -static inline int _sshvr (int src2, int src1) { -short s1; - if (src1 > 31) - s1 = 31; - else if (src1 < -31) - s1 = -31; - else - s1 = src1; - return (int) util_shift_right_saturate_n(src2, s1, 32); -} - - - - -static inline int _ssub(int src1, int src2) { -signed long long res; -signed long long maxv, minv; -maxv = (1LL << (32-1)) - 1; -minv = (-1LL << (32-1)); -res = (long long) src1 - (long long) src2; -if (res > maxv) { - res = maxv; - _overflow = 1; - } -else if (res < minv ) { - res = minv; - _overflow = 1; - } -return (int) res; -} - -static inline int _ssub2(int src1, int src2) { -signed short s1[2], s2[2]; -signed int r[2], maxv, minv; - -maxv = (1L << (16-1)) - 1; -minv = (-1L << (16-1)); - - -*((int*)s1) = src1; -*((int*)s2) = src2; - -r[0] = (int) s1[0] - (int) s2[0]; -r[1] = (int) s1[1] - (int) s2[1]; - -if (r[0] > maxv) { - r[0] = maxv; - /* NOTE: TI c6x does NOT set the overflow register even if results saturate */ - /* _overflow = 1; */ - } -else if (r[0] < minv ) { - r[0] = minv; - /* NOTE: TI c6x does NOT set the overflow register even if results saturate */ - /* _overflow = 1; */ - } -if (r[1] > maxv) { - r[1] = maxv; - /* NOTE: TI c6x does NOT set the overflow register even if results saturate */ - /* _overflow = 1; */ - } -else if (r[1] < minv ) { - r[1] = minv; - /* NOTE: TI c6x does NOT set the overflow register even if results saturate */ - /* _overflow = 1; */ - } - -return ((r[1] & 0xffff) << 16 ) | (r[0] & 0xffff) ; -} - - -static inline int _subabs4 (int src1, int src2) { - int res0, res1, res2, res3; - unsigned int s1_0 = (src1 & 0xff); - unsigned int s1_1 = (src1 & 0xff00) >> 8; - unsigned int s1_2 = (src1 & 0xff0000) >> 16; - unsigned int s1_3 = (src1 & 0xff000000) >> 24; - - unsigned int s2_0 = (src2 & 0xff); - unsigned int s2_1 = (src2 & 0xff00) >> 8; - unsigned int s2_2 = (src2 & 0xff0000) >> 16; - unsigned int s2_3 = (src2 & 0xff000000) >> 24; - - res0 = s1_0 - s2_0; - res1 = s1_1 - s2_1; - res2 = s1_2 - s2_2; - res3 = s1_3 - s2_3; - - if (res0 < 0) - res0 = -res0; - - if (res1 < 0) - res1 = -res1; - - if (res2 < 0) - res2 = -res2; - - if (res3 < 0) - res3 = -res3; - - return (res3 << 24) | (res2 << 16) | (res1 << 8) | res0; -} - - -static inline unsigned int _subc (unsigned int src1, unsigned int src2) -{ - if ( src1 >= src2) - return ((src1 - src2) << 1) + 1; - else - return src1 << 1; -} - - - -static inline int _sub2(int src1, int src2) { - short s1[2], s2[2], r[2]; - int result; - *((int*)s1) = src1; - *((int*)s2) = src2; - r[0] = s1[0] - s2[0]; - r[1] = s1[1] - s2[1]; - result = *(int*)r; - return result; -} - - -static inline int _sub4(int src1, int src2) { - char c1[4], c2[4], r[4]; - int result; - *((int*)c1) = src1; - *((int*)c2) = src2; - r[0] = c1[0] - c2[0]; - r[1] = c1[1] - c2[1]; - r[2] = c1[2] - c2[2]; - r[3] = c1[3] - c2[3]; - result = *(int*)r; - return result; -} - - -static inline int _swap4 (unsigned int src1) { - unsigned char v0 = src1; - unsigned char v1 = src1 >> 8; - unsigned char v2 = src1 >> 16; - unsigned char v3 = src1 >> 24; - unsigned v = v0<<8 | v1 | v2<<24 | v3<<16; - return v; -} - -static inline unsigned int _unpkhu4 (unsigned int src1) { - unsigned v0 = src1>>24; - unsigned v1 = (src1>>16) & 0xff; - return (v0<<16) | v1; -} - -static inline unsigned int _unpklu4 (unsigned int src1) { - unsigned v1 = (src1>>8) & 0xff; - unsigned v0 = (src1) & 0xff; - return (v1<<16) | v0; -} - - - - -static inline unsigned int _xpnd2 (unsigned int src1) { - int v0 = (src1 & 0x1) ? 0x0000ffff : 0x00000000; - int v1 = (src1 & 0x2) ? 0xffff0000 : 0x00000000; - return v0|v1; -} - -static inline unsigned int _xpnd4 (unsigned int src1) { - int v0 = (src1 & 0x1) ? 0x000000ff : 0x00000000; - int v1 = (src1 & 0x2) ? 0x0000ff00 : 0x00000000; - int v2 = (src1 & 0x4) ? 0x00ff0000 : 0x00000000; - int v3 = (src1 & 0x8) ? 0xff000000 : 0x00000000; - int r = v0|v1|v2|v3; - return r; -} - - - -// end of Implemented in alphabetical order - - -#endif /* __C6X_COMPAT__H */ diff --git a/components/esp32/include/xtensa/core-macros.h b/components/esp32/include/xtensa/core-macros.h index c8f7e34762..37c48921a4 100644 --- a/components/esp32/include/xtensa/core-macros.h +++ b/components/esp32/include/xtensa/core-macros.h @@ -335,7 +335,7 @@ __asm__ __volatile__("wsr.intenable %0" :: "a"(__intenable):"memory"); \ } while(0) # define XTHAL_GET_INTERRUPT() ({ int __interrupt; \ - __asm__("rsr.interrupt %0" : "=a"(__interrupt)); \ + __asm__ __volatile__("rsr.interrupt %0" : "=a"(__interrupt)); \ __interrupt; }) # define XTHAL_SET_INTSET(v) do { int __interrupt = (int)(v); \ __asm__ __volatile__("wsr.intset %0" :: "a"(__interrupt):"memory"); \ @@ -344,7 +344,7 @@ __asm__ __volatile__("wsr.intclear %0" :: "a"(__interrupt):"memory"); \ } while(0) # define XTHAL_GET_CCOUNT() ({ int __ccount; \ - __asm__("rsr.ccount %0" : "=a"(__ccount)); \ + __asm__ __volatile__("rsr.ccount %0" : "=a"(__ccount)); \ __ccount; }) # define XTHAL_SET_CCOUNT(v) do { int __ccount = (int)(v); \ __asm__ __volatile__("wsr.ccount %0" :: "a"(__ccount):"memory"); \ diff --git a/components/esp32/include/xtensa/debugfs.h b/components/esp32/include/xtensa/debugfs.h deleted file mode 100644 index eba7b438cd..0000000000 --- a/components/esp32/include/xtensa/debugfs.h +++ /dev/null @@ -1,93 +0,0 @@ -/* Xtensa Debug-FileSystem definitions */ - -/* - * Copyright (c) 2005-2009 by Tensilica Inc. ALL RIGHTS RESERVED. - * These coded instructions, statements, and computer programs are the - * copyrighted works and confidential proprietary information of Tensilica Inc. - * They may not be modified, copied, reproduced, distributed, or disclosed to - * third parties in any manner, medium, or form, in whole or in part, without - * the prior written consent of Tensilica Inc. - */ - -#ifndef __DEBUGFS_H__ -#define __DEBUGFS_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include -#include - -int xt_dbfs_open(const char *pathname, int flags, mode_t mode); -int xt_dbfs_ftruncate(int fd, off_t length); -int xt_dbfs_truncate(const char * filename, off_t length); -int xt_dbfs_creat(const char *pathname, mode_t mode); -int xt_dbfs_errno(void); -int xt_dbfs_lseek(int fd, off_t offset, int whence); -ssize_t xt_dbfs_write(int fd, const void * buf, size_t bytes); - ssize_t xt_dbfs_open_append_close(const char * filename, int align, - const void * buf, size_t bytes); -ssize_t xt_dbfs_read(int fd, void * buf, size_t bytes); -int xt_dbfs_close(int fd); -int xt_dbfs_unlink(const char *pathname); - -/* By default, this function is a wrapper around sbrk, and follows - sbrk semantics: - - On success, it returns increment bytes of memory allocated from - system memory. - - On failure, it returns 0xFFFFFFFF - - - If you want to use a method of allocating memory other than sbrk, - implement xt_dbfs_sbrk in your own sources, and the linker will - automatically use that copy. -*/ -void * xt_dbfs_sbrk(int increment); - - - -#ifdef REPLACE_FS_WITH_DBFS -#define open xt_dbfs_open -#define close xt_dbfs_close -#define creat xt_dbfs_creat -#define lseek xt_dbfs_lseek -#define write xt_dbfs_write -#define read xt_dbfs_read -#define close xt_dbfs_close -#define unlink xt_dbfs_unlink - -#define rmdir NOT_IMPLEMENTED_IN_DBFS -#define opendir NOT_IMPLEMENTED_IN_DBFS -#define closedir NOT_IMPLEMENTED_IN_DBFS -#define dirfs NOT_IMPLEMENTED_IN_DBFS -#define readdir NOT_IMPLEMENTED_IN_DBFS -#define scandir NOT_IMPLEMENTED_IN_DBFS -#define seekdir NOT_IMPLEMENTED_IN_DBFS -#define telldir NOT_IMPLEMENTED_IN_DBFS - -#define fcntl NOT_IMPLEMENTED_IN_DBFS -#define dup2 NOT_IMPLEMENTED_IN_DBFS -#define dup NOT_IMPLEMENTED_IN_DBFS -#define flock NOT_IMPLEMENTED_IN_DBFS -#define lockf NOT_IMPLEMENTED_IN_DBFS -#define link NOT_IMPLEMENTED_IN_DBFS -#define stat NOT_IMPLEMENTED_IN_DBFS -#define fstat NOT_IMPLEMENTED_IN_DBFS -#define lstat NOT_IMPLEMENTED_IN_DBFS -#define chmod NOT_IMPLEMENTED_IN_DBFS -#define fchmod NOT_IMPLEMENTED_IN_DBFS -#define chmown NOT_IMPLEMENTED_IN_DBFS -#define lchown NOT_IMPLEMENTED_IN_DBFS -#define fchown NOT_IMPLEMENTED_IN_DBFS - -#endif - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/components/esp32/include/xtensa/feedback.h b/components/esp32/include/xtensa/feedback.h deleted file mode 100644 index aecb745333..0000000000 --- a/components/esp32/include/xtensa/feedback.h +++ /dev/null @@ -1,45 +0,0 @@ - -/* - * Copyright (c) 2013 by Tensilica Inc. ALL RIGHTS RESERVED. - * These coded instructions, statements, and computer programs are the - * copyrighted works and confidential proprietary information of Tensilica Inc. - * They may not be modified, copied, reproduced, distributed, or disclosed to - * third parties in any manner, medium, or form, in whole or in part, without - * the prior written consent of Tensilica Inc. - */ - -#ifndef __XT_FEEDBACK_INCLUDED__ -#define __XT_FEEDBACK_INCLUDED__ - -#ifdef __cplusplus -extern "C" { -#endif - -/* xt_feedback_save_and_reset - - Save and reset the accumulated feedback data. -*/ -extern void xt_feedback_save_and_reset(void); - -/* xt_feedback_enable - - Turn on feedback accumulation. Ordinarily, feedback accumulation is on - by default. If you turn it off using xt_feedback_disable, You can turn - it on again via this function. -*/ -extern void xt_feedback_enable (void); - -/* xt_feedback_disable - - Turn off feedback accumulation. If you don't want to gather feedback for a - portion of your code, use this function and then xt_feedback_enable when - you want to start again. -*/ -extern void xt_feedback_disable (void); - -#ifdef __cplusplus -} -#endif - -#endif /* __XT_FEEDBACK_INCLUDED__ */ - diff --git a/components/esp32/include/xtensa/gdbio.h b/components/esp32/include/xtensa/gdbio.h deleted file mode 100644 index 784a862978..0000000000 --- a/components/esp32/include/xtensa/gdbio.h +++ /dev/null @@ -1,80 +0,0 @@ -/* Xtensa Debug-FileSystem definitions - * - * Copyright (c) 2006-2009 by Tensilica Inc. ALL RIGHTS RESERVED. - * These coded instructions, statements, and computer programs are the - * copyrighted works and confidential proprietary information of Tensilica Inc. - * They may not be modified, copied, reproduced, distributed, or disclosed to - * third parties in any manner, medium, or form, in whole or in part, without - * the prior written consent of Tensilica Inc. - */ - -#ifndef __DEBUGFS_H__ -#define __DEBUGFS_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include -#include -#include - - int _gdbio_open_r(void * ptr, const char *pathname, int flags, mode_t mode); - int _gdbio_creat_r(void * ptr, const char *pathname, mode_t mode); - int _gdbio_lseek_r(void * ptr, int fd, off_t offset, int whence); - ssize_t _gdbio_write_r(void * ptr, int fd, const void * buf, size_t bytes); - ssize_t _gdbio_read_r(void * ptr, int fd, void * buf, size_t bytes); - int _gdbio_close_r(void * ptr, int fd); - int _gdbio_unlink_r(void * ptr, const char * pathname); - - static inline - int gdbio_open(const char *pathname, int flags, mode_t mode) { - return _gdbio_open_r(&errno, pathname, flags, mode); - } - static inline int - gdbio_creat(const char *pathname, mode_t mode) { - return _gdbio_open_r(&errno, pathname, O_CREAT|O_WRONLY|O_TRUNC, mode); - } - static inline int - gdbio_errno(void) { - return errno; - } - static inline int - gdbio_lseek(int fd, off_t offset, int whence) { - return _gdbio_lseek_r(&errno, fd, offset, whence); - } - static inline - ssize_t gdbio_write(int fd, const void * buf, size_t bytes) { - return _gdbio_write_r(&errno, fd, buf, bytes); - } - static inline - ssize_t gdbio_read(int fd, void * buf, size_t bytes) { - return _gdbio_read_r(&errno, fd, buf, bytes); - } - static inline int - gdbio_close(int fd) { - return _gdbio_close_r(&errno, fd); - } - static inline int - gdbio_unlink(const char * pathname) { - return _gdbio_unlink_r(&errno, pathname); - } - -#ifdef REPLACE_FS_WITH_GDBIO -#define open gdbio_open -#define close gdbio_close -#define creat gdbio_creat -#define lseek gdbio_lseek -#define write gdbio_write -#define read gdbio_read -#define close gdbio_close -#define unlink gdbio_unlink - -#endif - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/components/esp32/include/xtensa/jtag-xtensa.h b/components/esp32/include/xtensa/jtag-xtensa.h deleted file mode 100644 index 45ac1caa40..0000000000 --- a/components/esp32/include/xtensa/jtag-xtensa.h +++ /dev/null @@ -1,99 +0,0 @@ -/* Copyright (c) 2011-2012 Tensilica Inc. ALL RIGHTS RESERVED. -// These coded instructions, statements, and computer programs are the -// copyrighted works and confidential proprietary information of Tensilica Inc. -// They may not be modified, copied, reproduced, distributed, or disclosed to -// third parties in any manner, medium, or form, in whole or in part, without -// the prior written consent of Tensilica Inc. -*/ - -#ifndef _JTAG_XTENSA_H_ -#define _JTAG_XTENSA_H_ - - -/* ---------------- JTAG registers ------------------ */ - -/* -- ER and later JTAG registers */ -typedef enum { - regIR, - regBypass, - regNAR, - regNDR, - regIdcode, - regPWRCTL, - regPWRSTAT, - regJtagMAX, -} xtensaJtagReg; - -/* -- pre-ER JTAG registers */ -typedef enum { - regOldIR, - regOldBypass, - regOldDIRW, - regOldDIR, - regOldDDR, - regOldDOSR, - regOldESR, - regOldDCR, - regOldTraxNDR, - regOldTraxNAR, - regOldMAX -} xtensaOldJtagReg; - - -/* ---------------- JTAG Instructions ------------------ */ - -/* -- pre-ER JTAG instructions */ -typedef enum { - ji_EnableOCD = 0x11, - ji_DebugInt, - ji_RetDebugInt, // TBD: remove - ji_DisRetOCD, // TBD: remove - ji_ExecuteDI, - ji_LoadDI, - ji_ScanDDR, - ji_ReadDOSR, - ji_ScanDCR, - ji_LoadWDI, - ji_TRAX = 0x1c, - ji_BYPASS = 0x1f, -} xtensaJtagInstruction; - -typedef enum { - OCDNormalMode, - OCDRunMode, - OCDHaltMode, - OCDStepMode -} xtensaMode; - -typedef struct { - xtensaMode mode; - int DRsel; - XTMP_core core; - XTMP_tap tap; - int core_num; - jtagReg_t *jtagRegs; - void *dap; // used for ARM DAP only - bool isBig; - int dir_array_option; // used by pre-ER devices only - // for testing, below - FIXME - delete later - int ocdReg; - unsigned int wr_data; - XTMP_event start_OCD_trans; - bool data_cycle; - bool data_pending; -} coreSlaveData_t; - - -enum OCD_ACCESS_TYPE{ - NEXUS_ACCESS, - CS_ACCESS, -}; - -// pre-ER Xtensa initializiation -EXTERN XTMP_deviceStatus -XTMP_jtagCoreSlaveEX(XTMP_component component, XTMP_jtagSlave slave, void* mydata); - -extern char *OCDrd; -extern char *OCDwr; - -#endif diff --git a/components/esp32/include/xtensa/lcd-splc780d-4bitmode-board.h b/components/esp32/include/xtensa/lcd-splc780d-4bitmode-board.h deleted file mode 100644 index f4db588582..0000000000 --- a/components/esp32/include/xtensa/lcd-splc780d-4bitmode-board.h +++ /dev/null @@ -1,62 +0,0 @@ -/******************************************************************************* -Copyright (c) 2009-2013 by Tensilica Inc. ALL RIGHTS RESERVED. -These coded instructions, statements, and computer programs are the -copyrighted works and confidential proprietary information of Tensilica Inc. -They may not be modified, copied, reproduced, distributed, or disclosed to -third parties in any manner, medium, or form, in whole or in part, without -the prior written consent of Tensilica Inc. --------------------------------------------------------------------------------- - -lcd-splc780d-4bitmode-board.h Board-specific LCD info for these boards: - Avnet AV110 (XT-AV110) - Xilinx ML605 (XT-ML605) - Xilinx KC705 (XT-KC705) - -Interface between board-independent driver and board-specific header. - -This is used by a board-independent SPLC780D LCD controller (4 bit mode) -driver to obtain board-specific information about LCD displays on the board, -such as the controller register base address and spacing (a function of how -the address lines are connected on the board) and length of the visible window -of the display (a function of the LCD panel the controller drives). -The driver doesnot refer directly to the board-specific header, which therefore is not -constrained to use macro names consistent with other boards. - -!! Must not contain any board-specific macro names (only controller specific) !! - -Included at compile-time via an include path specific to the board. - -The listed boards contain a single MYTech MOC-16216B-B display driven by -a Sunplus SPLC870D controller. - -*******************************************************************************/ - -#ifndef _LCD_SPLC780D_4BIT_BOARD_H -#define _LCD_SPLC780D_4BIT_BOARD_H - -#include /* Board info */ - - -/* Base address of the controller's registers. */ -#ifdef SPLC780D_4BIT_VADDR -#define SPLC780D_4BIT_REGBASE SPLC780D_4BIT_VADDR -#endif - -/* -The controller's registers are connected at word addresses on these boards. -Each byte-wide register appears as the least-significant-byte (LSB) of the -word regardless of the endianness of the processor (so if using word accesses -then endianness doesn't matter). -*/ -#define SPLC780D_4BIT_REGSPACING 4 -typedef unsigned splc780d_4bit_reg_t; - -/* Include generic information shared by all boards that use this device. */ -#include - - -/* Display limits of the LCD panel. */ -#define DISPLAY_VISIBLE_LEN 16 /* length (chars) of visible window */ - -#endif /* _LCD_SPLC780D_4BIT_BOARD_H */ - diff --git a/components/esp32/include/xtensa/lcd-splc780d-4bitmode.h b/components/esp32/include/xtensa/lcd-splc780d-4bitmode.h deleted file mode 100644 index 0a214bb400..0000000000 --- a/components/esp32/include/xtensa/lcd-splc780d-4bitmode.h +++ /dev/null @@ -1,105 +0,0 @@ -/******************************************************************************* - -Copyright (c) 2009-2010 by Tensilica Inc. ALL RIGHTS RESERVED. -These coded instructions, statements, and computer programs are the -copyrighted works and confidential proprietary information of Tensilica Inc. -They may not be modified, copied, reproduced, distributed, or disclosed to -third parties in any manner, medium, or form, in whole or in part, without -the prior written consent of Tensilica Inc. --------------------------------------------------------------------------------- - -lcd-SPLC780D-4bitmode.h Generic definitions for Sunplus SPLC780D LCD Controller -operating in 4 bit mode. - -This is used by board-support-packages with one or more LCD displays that use -a SPLC780D controller in 4 bit mode. A BSP provides a base address for each -instance of an SPLC780D LCD controller on the board. - -Note that LCD display operation is almost totally independent of the LCD -display, depending almost entirely on the controller. However the display -may limit the number of characters of the controller's RAM buffer that are -actually visible at one time. The length of the display's visible window -is not specifified in this controller-specific header, but comes to the -driver from the board-specific "display.h" header. - -*******************************************************************************/ - -#ifndef _LCD_SPLC780D_4BIT_H_ -#define _LCD_SPLC780D_4BIT_H_ - - -/* Offsets to controller registers from base. */ -#define SPLC780D_4BIT_INST 0 -#define SPLC780D_4BIT_DATA (SPLC780D_4BIT_INST + SPLC780D_4BIT_REGSPACING) - - -#define SPLC780D_4BIT_INST_INIT1 0xFF /* First command in - init sequence */ -#define SPLC780D_4BIT_INST_INIT2 0x30 /* Second command in - init sequence, - issued 3 times */ -#define SPLC780D_4BIT_INST_INIT3 0x20 /* Third and last command - in init sequence */ -#define SPLC780D_4BIT_INST_CLEAR 0x01 /* clear (blank) display) */ -#define SPLC780D_4BIT_INST_SET_MODE 0x28 /* Set LCD mode. Supported - setting is 4 bit data - length, 2 lines, 5*8 */ -#define SPLC780D_4BIT_INST_DSPLY_ON 0x0C /* Set Display ON */ -#define SPLC780D_4BIT_INST_CRSR_INC 0x06 /* Set cursor moving direction - as increment */ - -#define SPLC780D_4BIT_LINET_ADDR 0x80 /* clear (blank) display) */ -#define SPLC780D_4BIT_LINEB_ADDR 0xC0 /* clear (blank) display) */ - -#ifndef __ASSEMBLER__ - -/* C interface to controller registers. */ -struct splc780d_4bit_s { - splc780d_4bit_reg_t inst; /* instruction register */ - splc780d_4bit_reg_t data; /* data register */ -}; - -typedef volatile struct splc780d_4bit_s splc780d_4bit_t; - -/* -Prototypes of high level driver functions. -*/ - -/* Write an instruction byte to LCD, result in two back to back writes since the - * LCD is hooked up in 4 bit mode*/ -extern void lcd_write_inst_byte(splc780d_4bit_t *lcd, unsigned char inst); - -/* Write a data byte to LCD, result in two back to back writes since the - * LCD is hooked up in 4 bit mode*/ -extern void lcd_write_data_byte(splc780d_4bit_t *lcd, unsigned char data); - -/* -Initialize the display with default settings. -*/ -extern void splc780d_4bit_init_default(splc780d_4bit_t *lcd); - -/* -Write a single character at a given position (chars from left, starting at 0). -Wait long enough afterward for the controller to be ready for more input. -Positions beyond the end of the display are ignored. -*/ -extern void splc780d_4bit_write_char(splc780d_4bit_t *lcd, unsigned pos, const char c); - -/* -Write a string to the display starting at the left (position 0). -Blank-pad to or truncate at the end of the display (overwrites any previous -string so don't need to blank the display first). -Wait long enough after each char for the controller to be ready for more input. -*/ -extern void splc780d_4bit_write_string(splc780d_4bit_t *lcd, const char *s); - -/* -Blank (clear) the entire display. -Wait long enough afterward for the controller to be ready for more input. -*/ -extern void splc780d_4bit_blank(splc780d_4bit_t *lcd); - -#endif /* __ASSEMBLER__ */ - -#endif /* _LCD_SPLC780D_4BIT_H_ */ - diff --git a/components/esp32/include/xtensa/lcd-splc780d.h b/components/esp32/include/xtensa/lcd-splc780d.h deleted file mode 100644 index 4e878e9053..0000000000 --- a/components/esp32/include/xtensa/lcd-splc780d.h +++ /dev/null @@ -1,151 +0,0 @@ -/******************************************************************************* - -Copyright (c) 2006-2007 by Tensilica Inc. ALL RIGHTS RESERVED. -These coded instructions, statements, and computer programs are the -copyrighted works and confidential proprietary information of Tensilica Inc. -They may not be modified, copied, reproduced, distributed, or disclosed to -third parties in any manner, medium, or form, in whole or in part, without -the prior written consent of Tensilica Inc. --------------------------------------------------------------------------------- - -lcd-SPLC780D.h Generic definitions for Sunplus SPLC780D LCD Controller - -This is used by board-support-packages with one or more LCD displays that use -a SPLC780D controller. A BSP provides a base address for each instance of an -SPLC780D LCD controller on the board. - -Note that LCD display operation is almost totally independent of the LCD -display, depending almost entirely on the controller. However the display -may limit the number of characters of the controller's RAM buffer that are -actually visible at one time. The length of the display's visible window -is not specifified in this controller-specific header, but comes to the -driver from the board-specific "display.h" header. - -*******************************************************************************/ - -#ifndef _LCD_SPLC780D_H_ -#define _LCD_SPLC780D_H_ - - -/* Offsets to controller registers from base. */ -#define SPLC780D_INST 0 -#define SPLC780D_DATA (SPLC780D_INST + SPLC780D_REGSPACING) - -/* -Bit fields and their values in the instruction register. -These fields are NOT orthogonal - they overlap! -Thus only one field may be written at a time, determined by the -most-significant 1 bit in the pattern (the field selector). -All less significant bits are part of the value of the selected field. -The fields and their values are grouped together to emphasize this format. -Field selector macro names end in '_' (implying something more needs -to be ORed) and the value macros are indented. The pattern written to a -bitfield is a bitwise OR of a field selector and one or more values, eg. - (SPLC780D_INST_ON_ | SPLC780D_INST_ON_DISPLAY | SPLC780D_INST_ON_CURSOR) -A single bit field (eg. SPCL780D_INST_HOME) need not have a value. - -NOTE: Controller requires a software delay after writing to the control -or data registers. For the data register it is 38us. For the control -register it is 38us for most bit fields, with the following exceptions: - SPLC780D_FUNC_ 100us. - SPLC780D_INST_CLEAR, SPLC780D_INST_HOME 1520us. -For more details and reset timing, see the SUNPLUS SPLC780D data sheet. -*/ - -#define SPLC780D_INST_CLEAR_ 0x1 /* clear (blank) display) */ - -#define SPLC780D_INST_HOME_ 0x2 /* home cursor and shift pos */ - -#define SPLC780D_INST_ENTRY_ 0x4 /* combine *ENTRY_* flags below */ -#define SPLC780D_INST_ENTRY_SHIFT 0x1 /* display shift on entry / not */ -#define SPLC780D_INST_ENTRY_INCR 0x2 /* cursor incr / decr */ -#define SPLC780D_INST_ENTRY_DECR 0 /* cursor incr / decr */ - -#define SPLC780D_INST_ON_ 0x8 /* combine *ON_* flags below */ -#define SPLC780D_INST_ON_DISPLAY 0x4 /* display on / off */ -#define SPLC780D_INST_ON_CURSOR 0x2 /* cursor on / off */ -#define SPLC780D_INST_ON_BLINK 0x1 /* blink on / off */ - -#define SPLC780D_INST_SHIFT_ 0x10 /* combine *SHIFT_* flags below */ -#define SPLC780D_INST_SHIFT_DISP 0x8 /* shift display / move cursor */ -#define SPLC780D_INST_SHIFT_CURS 0 /* shift display / move cursor */ -#define SPLC780D_INST_SHIFT_RIGHT 0x4 /* shift right / left */ -#define SPLC780D_INST_SHIFT_LEFT 0 /* shift right / left */ - -#define SPLC780D_INST_FUNC_ 0x20 /* combine *FUNC_* flags below */ -#define SPLC780D_INST_FUNC_8BIT 0x10 /* data length 8 bit / 4 bit */ -#define SPLC780D_INST_FUNC_4BIT 0 /* data length 8 bit / 4 bit */ -#define SPLC780D_INST_FUNC_2LINE 0x08 /* display lines 2 / 1 */ -#define SPLC780D_INST_FUNC_1LINE 0 /* display lines 2 / 1 */ -#define SPLC780D_INST_FUNC_F5x10 0x04 /* character font 5x10 / 5x8 */ -#define SPLC780D_INST_FUNC_F5x8 0 /* character font 5x10 / 5x8 */ - /* font must be 5x8 for 2 lines */ -#define SPLC780D_INST_CGEN_ 0x40 /* set char generator address */ -#define SPLC780D_INST_CGEN_ADDR 0x3F /* to address in this field */ -#define SPLC780D_INST_DRAM_ 0x80 /* set display data RAM address */ -#define SPLC780D_INST_DRAM_ADDR 0x7F /* to address in this field */ -#define SPLC780D_INST_DRAM_LINE2 0x40 /* address offset to line 2 */ -/* Controller limits */ -#define SPLC780D_RAMLEN_1LINE 0x50 /* length of line in RAM (1 line) */ -#define SPLC780D_RAMLEN_2LINE 0x28 /* length of line in RAM (2 line) */ - - -#ifndef __ASSEMBLER__ - -/* C interface to controller registers. */ -struct splc780d_s { - splc780d_reg_t inst; /* instruction register */ - splc780d_reg_t data; /* data register */ -}; - -typedef volatile struct splc780d_s splc780d_t; - -/* -Prototypes of high level driver functions. -*/ - -/* -Initialize the display with the FUNC_, ENTRY_ and ON_ fields as specified in -terms of the values above. The splc780d_init_default() macro is an example. -*/ -extern void splc780d_init(splc780d_t *lcd, - unsigned func, unsigned entry, unsigned on); - -/* -Initialize the display to default mode: 8-bit interface, 2 line, 5x8 font, -increment cursor on entry, display on (cursor and blinking off). -*/ -#define splc780d_init_default(lcd) \ - splc780d_init( lcd, \ - SPLC780D_INST_FUNC_8BIT \ - | SPLC780D_INST_FUNC_2LINE \ - | SPLC780D_INST_FUNC_F5x8, \ - SPLC780D_INST_ENTRY_INCR, \ - SPLC780D_INST_ON_DISPLAY \ - ) - -/* -Write a single character at a given position (chars from left, starting at 0). -Wait long enough afterward for the controller to be ready for more input. -Positions beyond the end of the display are ignored. -*/ -extern void splc780d_write_char(splc780d_t *lcd, unsigned pos, const char c); - -/* -Write a string to the display starting at the left (position 0). -Blank-pad to or truncate at the end of the display (overwrites any previous -string so don't need to blank the display first). -Wait long enough after each char for the controller to be ready for more input. -*/ -extern void splc780d_write_string(splc780d_t *lcd, const char *s); - -/* -Blank (clear) the entire display. -Wait long enough afterward for the controller to be ready for more input. -*/ -extern void splc780d_blank(splc780d_t *lcd); - -#endif /* __ASSEMBLER__ */ - -#endif /* _LCD_SPLC780D_H_ */ - diff --git a/components/esp32/include/xtensa/overlay.h b/components/esp32/include/xtensa/overlay.h deleted file mode 100644 index e959cf512f..0000000000 --- a/components/esp32/include/xtensa/overlay.h +++ /dev/null @@ -1,184 +0,0 @@ -// overlay.h -- Overlay manager header file -// $Id$ - -// Copyright (c) 2013 Tensilica 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. - - -#ifndef OVERLAY_H -#define OVERLAY_H - - -#include - - -#ifdef __cplusplus -extern "C" { -#endif - -// Define this to turn off overlay support -#ifdef XT_DISABLE_OVERLAYS - -#define OVERLAY(n) -#define DECLARE_OVERLAY(n) - -#define xt_overlay_map(ov_id) -#define xt_overlay_map_async(ov_id) 0 -#define xt_overlay_map_in_progress() 0 -#define xt_overlay_get_id() 0 -#define xt_overlay_get_state(pc) 0 -#define xt_overlay_check_map(pc,ps,ovstate,sp) 0 - -#else - -// Shorthand for convenience and portability. -#define OVERLAY(n) __attribute__((overlay(n))) - -// Structure of the overlay table required by gdb and the overlay -// manager. Should not be accessed by user code unless overriding -// the load process. -struct ovly_table { - void * vma; // The overlay's mapped address. - unsigned int size; // The size of the overlay, in bytes. - void * lma; // The overlay's load address. - unsigned int mapped; // Non-zero if overlay is currently mapped; zero otherwise. -}; - -// Constructed by the linker. Required for gdb and for the overlay -// manager. Should not be accessed by user code unless overriding -// the load process. -extern struct ovly_table _ovly_table[]; - -// Functions. -void xt_overlay_map(int ov_id); -int xt_overlay_map_async(int ov_id); -int xt_overlay_map_in_progress(void); -unsigned int xt_overlay_get_state(unsigned int pc); -unsigned int xt_overlay_check_map(unsigned int * pc, unsigned int * ps, - unsigned int ovstate, unsigned int sp); -int xt_overlay_start_map(void * dst, void * src, unsigned int len, int ov_id); -int xt_overlay_is_mapping(int ov_id); -void xt_overlay_fatal_error(int ov_id); - - -// Returns the current overlay ID. If no overlay is mapped or an overlay -// is in the middle of being mapped, returns -1. Inlined to avoid calling -// out of overlay (wastes cycles, can end up reading wrong ID on interrupt -// activity). -// -static inline int xt_overlay_get_id(void) -{ -#pragma always_inline -extern short _mapping_id; -extern short _ovly_id; - - int ret; - unsigned int flags = XTOS_SET_INTLEVEL(15); - - if (_mapping_id >= 0) { - ret = -1; - } - else { - ret = _ovly_id; - } - - XTOS_RESTORE_INTLEVEL(flags); - return ret; -} - - -// The following macros are used to declare numbered overlays and generate -// the corresponding call stubs. Use as follows: -// -// DECLARE_OVERLAY(n) -// -// See documentation for more details. - -//#include - -// At this time overlays are not supported without windowing. -#if defined(__XTENSA_WINDOWED_ABI__) - -#define xstr(x) str(x) -#define str(x) #x - -// At entry, register a8 holds the return address and a9 holds the target -// function address. This stub saves a8 on the stack at (SP - 20) which -// is the only location that is safe for us to use. Then it allocates 32 -// bytes on the stack for working storage, loads the overlay number into -// a8, and jumps to the common handler. The common handler will make sure -// that the called function is loaded into memory before calling it. -// NOTE: we are using the stack area normally reserved for nested functions. -// This means nested functions cannot be used when overlays are in use. - -#define CALL_IN(num) \ - asm(".section .gnu.linkonce.t.overlay.call." xstr(num) ".text, \"ax\"\n" \ - ".global _overlay_call_in_" xstr(num) "_\n" \ - ".align 4\n" \ - "_overlay_call_in_" xstr(num) "_:\n" \ - "s32e a8, a1, -20\n" \ - "addi a8, a1, -32\n" \ - "movsp a1, a8\n" \ - "movi a8, " xstr(num) "\n" \ - "j _overlay_call_in_common\n" \ - ".size _overlay_call_in_" xstr(num) "_, . - _overlay_call_in_" xstr(num) "_\n"); - -// The call-out stub first calls the target function, then loads the overlay -// number into register a14 and jumps to the common handler. The handler will -// make sure that the caller function is present in memory before returning. -// Note that registers a10-a13 may contain return values so must be preserved. -// -// Because we came here via a call4, the return address is in a4, and the top -// 2 bits are set to the window increment. We'll restore the top 2 bits of -// the return address from the called function's address, assuming that both -// are in the same 1 GB segment. For now this is always true. - -#define CALL_OUT(num) \ - asm(".section .gnu.linkonce.t.overlay.call." xstr(num) ".text, \"ax\"\n" \ - ".global _overlay_call_out_" xstr(num) "_\n" \ - ".align 4\n" \ - "_overlay_call_out_" xstr(num) "_:\n" \ - "slli a4, a4, 2\n" \ - "srli a4, a4, 2\n" \ - "extui a8, a9, 30, 2\n" \ - "slli a8, a8, 30\n" \ - "or a4, a4, a8\n" \ - "callx8 a9\n" \ - "movi a14, " xstr(num) "\n" \ - "j _overlay_call_out_common\n" \ - ".size _overlay_call_out_" xstr(num) "_, . - _overlay_call_out_" xstr(num) "_\n"); - -// Generate a call-in and a call-out stub for each overlay. - -#define DECLARE_OVERLAY(num) \ - CALL_IN(num) \ - CALL_OUT(num) - -#endif // defined(__XTENSA_WINDOWED_ABI__) - -#endif // XT_DISABLE_OVERLAYS - -#ifdef __cplusplus -} -#endif - -#endif // OVERLAY_H - diff --git a/components/esp32/include/xtensa/overlay_os_asm.h b/components/esp32/include/xtensa/overlay_os_asm.h deleted file mode 100644 index 4adc044e6a..0000000000 --- a/components/esp32/include/xtensa/overlay_os_asm.h +++ /dev/null @@ -1,140 +0,0 @@ -// overlay_os_asm.h -- Overlay manager assembly macros for OS use. -// $Id$ - -// Copyright (c) 2013 Tensilica 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. - - -#ifndef OVERLAY_OS_ASM_H -#define OVERLAY_OS_ASM_H - -// The macros in here are intended to be used by RTOS task switch code -// to check overlay status. Such code is usually in assembly and cannot -// call C code without penalty. For C code usage, it is best to use the -// corresponding C functions from the library. - - -// Inline assembly version of xt_overlay_get_state(). The arguments are -// three AR registers (a0-a15): -// -// "pcreg" - should contain the outgoing task's PC, i.e. the point at -// which the task got interrupted. The return value is also -// returned in this register. -// "sr1/2" - Scratch registers. These must be distinct from "pcreg". -// -// The return value is a 32-bit result that should be saved with the -// task context and passed as-is to xt_overlay_check_map. - - .macro _xt_overlay_get_state pcreg sr1 sr2 - - movi \sr1, _mapping_id - movi \sr2, _ovly_id - l16si \sr1, \sr1, 0 - l16ui \sr2, \sr2, 0 - slli \sr1, \sr1, 16 - or \pcreg, \sr1, \sr2 - - .endm - - -// Inline assembly version of xt_overlay_check_map(). It requires 5 AR -// registers (a0-a15) as arguments. -// -// "pcreg" - should contain the interrupted task's PC, i.e. the point -// at which the task got interrupted. This will be adjusted -// if required. -// "psreg" - should contain the interrupted task's PS. This will be -// adjusted if required. -// "ovreg" - should contain the overlay state on entry. Contents may -// be clobbered. -// "spreg" - should contain the tasks stack pointer on entry. -// "sr1" - Scratch register. Must be distinct from any of the above. -// -// The return values are "pcreg" and "psreg" and these must be used -// to update the task's PC and PS. -// Note that this macro may store data below the "spreg" pointer. If -// it does, then it will also disable interrupts via the PS, so that -// the task resumes with all interrupts disabled (to avoid corrupting -// this data). -// -// (SP - 24) Overlay ID to restore -// (SP - 28) Task PC -// (SP - 32) Task PS - - .macro _xt_overlay_check_map pcreg psreg ovreg spreg sr1 - -// There are four cases to deal with: -// -// _ovly_id = -1, _mapping_id = -1 -// No overlay is mapped or mapping, nothing to do. -// -// _ovly_id >= 0, _mapping_id = -1 -// An overlay was mapped, check PC to see if we need a restore. -// -// _ovly_id = -1, _mapping_id >= 0 -// An overlay is being mapped. Either it belongs to this task, which -// implies that the PC is in the mapping function, or it does not -// belong to this task. Either way there is nothing to do. -// -// _ovly_id >= 0, _mapping_id >= 0 -// Illegal, cannot happen by design. Don't need to handle this. -// -// So, the logic is to check _ovly_id first. If this is >= 0, then -// we check the task PC. If the PC is in the regions of interest then -// we'll patch the return PC to invoke xt_overlay_restore. - -.L1: - extui \sr1, \ovreg, 0, 16 // Extract _ovly_id - bbsi.l \sr1, 15, .Lno // If -1 then we're done - mov \ovreg, \sr1 // Restore this one - -// Next check the PC to see if it falls within the ranges of interest. - -.L2: - movi \sr1, _overlay_vma // Is PC < VMA range ? - bltu \pcreg, \sr1, .L3 - movi \sr1, _overlay_vma_end // Is PC > VMA range ? - bgeu \pcreg, \sr1, .L3 - j .L4 // PC is in VMA range -.L3: - movi \sr1, _overlay_call_stubs_start // Is PC < call stubs range ? - bltu \pcreg, \sr1, .Lno - movi \sr1, _overlay_call_stubs_end // Is PC > call stubs range ? - bgeu \pcreg, \sr1, .Lno - -// If we get here then a restore is needed. Save the overlay ID, PC and PS. -// Return modified PC and PS so that xt_overlay_restore() will execute in -// the context of the task when resumed. Note that the OS resumption code -// may expect PS.EXCM to be set so we leave it as is in the return value. - -.L4: - s32e \ovreg, \spreg, -24 // Save overlay ID - s32e \pcreg, \spreg, -28 // Save task PC - s32e \psreg, \spreg, -32 // Save task PS - movi \pcreg, xt_overlay_restore // Adjust resumption PC - movi \sr1, 15 - or \psreg, \psreg, \sr1 // Set intlevel to highest -.Lno: - - .endm - -#endif // OVERLAY_OS_ASM_H - diff --git a/components/esp32/include/xtensa/sim.h b/components/esp32/include/xtensa/sim.h deleted file mode 100644 index e02087c5c0..0000000000 --- a/components/esp32/include/xtensa/sim.h +++ /dev/null @@ -1,60 +0,0 @@ -/* Copyright (c) 2004-2006 by Tensilica Inc. ALL RIGHTS RESERVED. -/ These coded instructions, statements, and computer programs are the -/ copyrighted works and confidential proprietary information of Tensilica Inc. -/ They may not be modified, copied, reproduced, distributed, or disclosed to -/ third parties in any manner, medium, or form, in whole or in part, without -/ the prior written consent of Tensilica Inc. -*/ - -/* sim.h - * - * Definitions and prototypes for specific ISS SIMCALLs - * (ie. outside the standard C library). - */ - -#ifndef _INC_SIM_H_ -#define _INC_SIM_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -/* Shortcuts for enabling/disabling profiling in the Xtensa ISS */ -extern void xt_iss_profile_enable(void); -extern void xt_iss_profile_disable(void); - -/* Shortcut for setting the trace level in the Xtensa ISS */ -extern void xt_iss_trace_level(unsigned level); - -/* Generic interface for passing client commands in the Xtensa ISS: - * returns 0 on success, -1 on failure. - */ -extern int xt_iss_client_command(const char *client, const char *command); - -/* Interface for switching simulation modes in the Xtensa ISS: - * returns 0 on success, -1 on failure. - */ -#define XT_ISS_CYCLE_ACCURATE 0 -#define XT_ISS_FUNCTIONAL 1 -extern int xt_iss_switch_mode(int mode); - - -/* Interface for waiting on a system synchronization event */ -extern void xt_iss_event_wait(unsigned event_id); - -/* Interface for firing a system synchronization event */ -extern void xt_iss_event_fire(unsigned event_id); - -/* Interface for invoking a user simcall action, - * which can be registered in XTMP or XTSC. - */ -extern int xt_iss_simcall(int arg1, int arg2, int arg3, - int arg4, int arg5, int arg6); - - -#ifdef __cplusplus -} -#endif - -#endif /*_INC_SIM_H_*/ - diff --git a/components/esp32/include/xtensa/simboard.h b/components/esp32/include/xtensa/simboard.h deleted file mode 100644 index 980b0b7596..0000000000 --- a/components/esp32/include/xtensa/simboard.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (c) 2001 Tensilica 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. - */ - -/* simboard.h - Xtensa ISS "Board" specific definitions */ - -#ifndef _INC_SIMBOARD_H_ -#define _INC_SIMBOARD_H_ - -#include -#include - - -/* - * Device addresses. - */ - -/* System ROM: */ -#define XTBOARD_ROM_SIZE XSHAL_ROM_SIZE -#ifdef XSHAL_ROM_VADDR -#define XTBOARD_ROM_VADDR XSHAL_ROM_VADDR -#endif -#ifdef XSHAL_ROM_PADDR -#define XTBOARD_ROM_PADDR XSHAL_ROM_PADDR -#endif - -/* System RAM: */ -#define XTBOARD_RAM_SIZE XSHAL_RAM_SIZE -#ifdef XSHAL_RAM_VADDR -#define XTBOARD_RAM_VADDR XSHAL_RAM_VADDR -#endif -#ifdef XSHAL_RAM_PADDR -#define XTBOARD_RAM_PADDR XSHAL_RAM_PADDR -#endif - - -/* - * Things that depend on device addresses. - */ - -#define XTBOARD_CACHEATTR_WRITEBACK XSHAL_ISS_CACHEATTR_WRITEBACK -#define XTBOARD_CACHEATTR_WRITEALLOC XSHAL_ISS_CACHEATTR_WRITEALLOC -#define XTBOARD_CACHEATTR_WRITETHRU XSHAL_ISS_CACHEATTR_WRITETHRU -#define XTBOARD_CACHEATTR_BYPASS XSHAL_ISS_CACHEATTR_BYPASS -#define XTBOARD_CACHEATTR_DEFAULT XSHAL_ISS_CACHEATTR_DEFAULT - -#define XTBOARD_BUSINT_PIPE_REGIONS 0 -#define XTBOARD_BUSINT_SDRAM_REGIONS 0 - - -#endif /*_INC_SIMBOARD_H_*/ - diff --git a/components/esp32/include/xtensa/simcall-errno.h b/components/esp32/include/xtensa/simcall-errno.h deleted file mode 100644 index 445ec90135..0000000000 --- a/components/esp32/include/xtensa/simcall-errno.h +++ /dev/null @@ -1,139 +0,0 @@ -/* Error numbers for Xtensa ISS semihosting. */ - -/* Copyright (c) 2003 by Tensilica Inc. ALL RIGHTS RESERVED. - These coded instructions, statements, and computer programs are the - copyrighted works and confidential proprietary information of Tensilica Inc. - They may not be modified, copied, reproduced, distributed, or disclosed to - third parties in any manner, medium, or form, in whole or in part, without - the prior written consent of Tensilica Inc. */ - -#ifndef _SIMCALL_ERRNO_H -#define _SIMCALL_ERRNO_H - -/* Define the error numbers (using the default newlib values) with prefixes - so they can be used in ISS without conflicting with the host values. */ - -#define _SIMC_EPERM 1 -#define _SIMC_ENOENT 2 -#define _SIMC_ESRCH 3 -#define _SIMC_EINTR 4 -#define _SIMC_EIO 5 -#define _SIMC_ENXIO 6 -#define _SIMC_E2BIG 7 -#define _SIMC_ENOEXEC 8 -#define _SIMC_EBADF 9 -#define _SIMC_ECHILD 10 -#define _SIMC_EAGAIN 11 -#define _SIMC_ENOMEM 12 -#define _SIMC_EACCES 13 -#define _SIMC_EFAULT 14 -#define _SIMC_ENOTBLK 15 -#define _SIMC_EBUSY 16 -#define _SIMC_EEXIST 17 -#define _SIMC_EXDEV 18 -#define _SIMC_ENODEV 19 -#define _SIMC_ENOTDIR 20 -#define _SIMC_EISDIR 21 -#define _SIMC_EINVAL 22 -#define _SIMC_ENFILE 23 -#define _SIMC_EMFILE 24 -#define _SIMC_ENOTTY 25 -#define _SIMC_ETXTBSY 26 -#define _SIMC_EFBIG 27 -#define _SIMC_ENOSPC 28 -#define _SIMC_ESPIPE 29 -#define _SIMC_EROFS 30 -#define _SIMC_EMLINK 31 -#define _SIMC_EPIPE 32 -#define _SIMC_EDOM 33 -#define _SIMC_ERANGE 34 -#define _SIMC_ENOMSG 35 -#define _SIMC_EIDRM 36 -#define _SIMC_ECHRNG 37 -#define _SIMC_EL2NSYNC 38 -#define _SIMC_EL3HLT 39 -#define _SIMC_EL3RST 40 -#define _SIMC_ELNRNG 41 -#define _SIMC_EUNATCH 42 -#define _SIMC_ENOCSI 43 -#define _SIMC_EL2HLT 44 -#define _SIMC_EDEADLK 45 -#define _SIMC_ENOLCK 46 -#define _SIMC_EBADE 50 -#define _SIMC_EBADR 51 -#define _SIMC_EXFULL 52 -#define _SIMC_ENOANO 53 -#define _SIMC_EBADRQC 54 -#define _SIMC_EBADSLT 55 -#define _SIMC_EDEADLOCK 56 -#define _SIMC_EBFONT 57 -#define _SIMC_ENOSTR 60 -#define _SIMC_ENODATA 61 -#define _SIMC_ETIME 62 -#define _SIMC_ENOSR 63 -#define _SIMC_ENONET 64 -#define _SIMC_ENOPKG 65 -#define _SIMC_EREMOTE 66 -#define _SIMC_ENOLINK 67 -#define _SIMC_EADV 68 -#define _SIMC_ESRMNT 69 -#define _SIMC_ECOMM 70 -#define _SIMC_EPROTO 71 -#define _SIMC_EMULTIHOP 74 -#define _SIMC_ELBIN 75 -#define _SIMC_EDOTDOT 76 -#define _SIMC_EBADMSG 77 -#define _SIMC_EFTYPE 79 -#define _SIMC_ENOTUNIQ 80 -#define _SIMC_EBADFD 81 -#define _SIMC_EREMCHG 82 -#define _SIMC_ELIBACC 83 -#define _SIMC_ELIBBAD 84 -#define _SIMC_ELIBSCN 85 -#define _SIMC_ELIBMAX 86 -#define _SIMC_ELIBEXEC 87 -#define _SIMC_ENOSYS 88 -#define _SIMC_ENMFILE 89 -#define _SIMC_ENOTEMPTY 90 -#define _SIMC_ENAMETOOLONG 91 -#define _SIMC_ELOOP 92 -#define _SIMC_EOPNOTSUPP 95 -#define _SIMC_EPFNOSUPPORT 96 -#define _SIMC_ECONNRESET 104 -#define _SIMC_ENOBUFS 105 -#define _SIMC_EAFNOSUPPORT 106 -#define _SIMC_EPROTOTYPE 107 -#define _SIMC_ENOTSOCK 108 -#define _SIMC_ENOPROTOOPT 109 -#define _SIMC_ESHUTDOWN 110 -#define _SIMC_ECONNREFUSED 111 -#define _SIMC_EADDRINUSE 112 -#define _SIMC_ECONNABORTED 113 -#define _SIMC_ENETUNREACH 114 -#define _SIMC_ENETDOWN 115 -#define _SIMC_ETIMEDOUT 116 -#define _SIMC_EHOSTDOWN 117 -#define _SIMC_EHOSTUNREACH 118 -#define _SIMC_EINPROGRESS 119 -#define _SIMC_EALREADY 120 -#define _SIMC_EDESTADDRREQ 121 -#define _SIMC_EMSGSIZE 122 -#define _SIMC_EPROTONOSUPPORT 123 -#define _SIMC_ESOCKTNOSUPPORT 124 -#define _SIMC_EADDRNOTAVAIL 125 -#define _SIMC_ENETRESET 126 -#define _SIMC_EISCONN 127 -#define _SIMC_ENOTCONN 128 -#define _SIMC_ETOOMANYREFS 129 -#define _SIMC_EPROCLIM 130 -#define _SIMC_EUSERS 131 -#define _SIMC_EDQUOT 132 -#define _SIMC_ESTALE 133 -#define _SIMC_ENOTSUP 134 -#define _SIMC_ENOMEDIUM 135 -#define _SIMC_ENOSHARE 136 -#define _SIMC_ECASECLASH 137 -#define _SIMC_EILSEQ 138 -#define _SIMC_EOVERFLOW 139 - -#endif /* ! _SIMCALL_ERRNO_H */ diff --git a/components/esp32/include/xtensa/simcall-fcntl.h b/components/esp32/include/xtensa/simcall-fcntl.h deleted file mode 100644 index 1c03f5595e..0000000000 --- a/components/esp32/include/xtensa/simcall-fcntl.h +++ /dev/null @@ -1,21 +0,0 @@ -/* File control operations for Xtensa ISS semihosting. */ - -/* Copyright (c) 2003 by Tensilica Inc. ALL RIGHTS RESERVED. - These coded instructions, statements, and computer programs are the - copyrighted works and confidential proprietary information of Tensilica Inc. - They may not be modified, copied, reproduced, distributed, or disclosed to - third parties in any manner, medium, or form, in whole or in part, without - the prior written consent of Tensilica Inc. */ - -#ifndef _SIMCALL_FCNTL_H -#define _SIMCALL_FCNTL_H - -#define _SIMC_O_APPEND 0x0008 -#define _SIMC_O_NONBLOCK 0x0080 -#define _SIMC_O_CREAT 0x0100 -#define _SIMC_O_TRUNC 0x0200 -#define _SIMC_O_EXCL 0x0400 -#define _SIMC_O_TEXT 0x4000 -#define _SIMC_O_BINARY 0x8000 - -#endif /* ! _SIMCALL_FCNTL_H */ diff --git a/components/esp32/include/xtensa/simcall.h b/components/esp32/include/xtensa/simcall.h deleted file mode 100644 index d71959eea7..0000000000 --- a/components/esp32/include/xtensa/simcall.h +++ /dev/null @@ -1,189 +0,0 @@ -/* - * simcall.h - Simulator call numbers - * - * Software that runs on a simulated Xtensa processor using - * the instruction set simulator (ISS) can invoke simulator - * services using the SIMCALL instruction. The a2 register - * is set prior to executing SIMCALL to a "simcall number", - * indicating which service to invoke. This file defines the - * simcall numbers defined and/or supported by the Xtensa ISS. - * - * IMPORTANT NOTE: These numbers are highly subject to change! - * - * Copyright (c) 2002-2007 by Tensilica Inc. ALL RIGHTS RESERVED. - * These coded instructions, statements, and computer programs are the - * copyrighted works and confidential proprietary information of Tensilica Inc. - * They may not be modified, copied, reproduced, distributed, or disclosed to - * third parties in any manner, medium, or form, in whole or in part, without - * the prior written consent of Tensilica Inc. - */ - -#ifndef SIMCALL_INCLUDED -#define SIMCALL_INCLUDED - -/* - * System call like services offered by the simulator host. - * These are modeled after the Linux 2.4 kernel system calls - * for Xtensa processors. However not all system calls and - * not all functionality of a given system call are implemented, - * or necessarily have well defined or equivalent semantics in - * the context of a simulation (as opposed to a Unix kernel). - * - * These services behave largely as if they had been invoked - * as a task in the simulator host's operating system - * (eg. files accessed are those of the simulator host). - * However, these SIMCALLs model a virtual operating system - * so that various definitions, bit assignments etc - * (eg. open mode bits, errno values, etc) are independent - * of the host operating system used to run the simulation. - * Rather these definitions are specific to the Xtensa ISS. - * This way Xtensa ISA code written to use these SIMCALLs - * can (in principle) be simulated on any host. - * - * Up to 6 parameters are passed in registers a3 to a8 - * (note the 6th parameter isn't passed on the stack, - * unlike windowed function calling conventions). - * The return value is in a2. A negative value in the - * range -4096 to -1 indicates a negated error code to be - * reported in errno with a return value of -1, otherwise - * the value in a2 is returned as is. - */ - -/* These #defines need to match what's in Xtensa/OS/vxworks/xtiss/simcalls.c */ - -#define SYS_nop 0 /* n/a - setup; used to flush register windows */ -#define SYS_exit 1 /*x*/ -#define SYS_fork 2 -#define SYS_read 3 /*x*/ -#define SYS_write 4 /*x*/ -#define SYS_open 5 /*x*/ -#define SYS_close 6 /*x*/ -#define SYS_rename 7 /*x 38 - waitpid */ -#define SYS_creat 8 /*x*/ -#define SYS_link 9 /*x (not implemented on WIN32) */ -#define SYS_unlink 10 /*x*/ -#define SYS_execv 11 /* n/a - execve */ -#define SYS_execve 12 /* 11 - chdir */ -#define SYS_pipe 13 /* 42 - time */ -#define SYS_stat 14 /* 106 - mknod */ -#define SYS_chmod 15 -#define SYS_chown 16 /* 202 - lchown */ -#define SYS_utime 17 /* 30 - break */ -#define SYS_wait 18 /* n/a - oldstat */ -#define SYS_lseek 19 /*x*/ -#define SYS_getpid 20 -#define SYS_isatty 21 /* n/a - mount */ -#define SYS_fstat 22 /* 108 - oldumount */ -#define SYS_time 23 /* 13 - setuid */ -#define SYS_gettimeofday 24 /*x 78 - getuid (not implemented on WIN32) */ -#define SYS_times 25 /*X 43 - stime (Xtensa-specific implementation) */ -#define SYS_socket 26 -#define SYS_sendto 27 -#define SYS_recvfrom 28 -#define SYS_select_one 29 /* not compitible select, one file descriptor at the time */ -#define SYS_bind 30 -#define SYS_ioctl 31 - -/* - * Other... - */ -#define SYS_iss_argc 1000 /* returns value of argc */ -#define SYS_iss_argv_size 1001 /* bytes needed for argv & arg strings */ -#define SYS_iss_set_argv 1002 /* saves argv & arg strings at given addr */ - -#define SYS_memset 1004 /* fill a range of memory (fast) */ - -/* - * SIMCALLs for the ferret memory debugger. All are invoked by - * libferret.a ... ( Xtensa/Target-Libs/ferret ) - */ -#define SYS_ferret 1010 -#define SYS_malloc 1011 -#define SYS_free 1012 -#define SYS_more_heap 1013 -#define SYS_no_heap 1014 -#define SYS_enter_ferret 1015 -#define SYS_leave_ferret 1016 - -/* - * SIMCALLs for ISS client commands - */ -#define SYS_profile_enable 1020 -#define SYS_profile_disable 1021 -#define SYS_trace_level 1022 -#define SYS_client_command 1023 - -/* - * SIMCALL for simulation mode switching - */ -#define SYS_sim_mode_switch 1030 - -/* - * SIMCALLs for XTMP/XTSC event notify and core stall - */ -#define SYS_event_fire 1040 -#define SYS_event_stall 1041 - -/* - * SIMCALLs for callbacks registered in XTMP/XTSC - */ -#define SYS_callback_first 100 -#define SYS_callback_last 999 - -/* - * User defined simcall - */ -#define SYS_user_simcall 100 - -#define SYS_xmpa_errinfo 200 -#define SYS_xmpa_proc_status 201 -#define SYS_xmpa_proc_start 202 -#define SYS_xmpa_proc_stop 203 -#define SYS_xmpa_proc_mem_read 204 -#define SYS_xmpa_proc_mem_write 205 -#define SYS_xmpa_proc_mem_fill 206 -#define SYS_xmpa_proc_reg_read 207 -#define SYS_xmpa_proc_reg_write 208 - - -/* - * Extra SIMCALLs for GDB: - */ -#define SYS_gdb_break -1 /* invoked by XTOS on user exceptions if EPC points - to a break.n/break, regardless of cause! */ -#define SYS_xmon_out -2 /* invoked by XMON: ... */ -#define SYS_xmon_in -3 /* invoked by XMON: ... */ -#define SYS_xmon_flush -4 /* invoked by XMON: ... */ -#define SYS_gdb_abort -5 /* invoked by XTOS in _xtos_panic() */ -#define SYS_gdb_illegal_inst -6 /* invoked by XTOS for illegal instructions (too deeply) */ -#define SYS_xmon_init -7 /* invoked by XMON: ... */ -#define SYS_gdb_enter_sktloop -8 /* invoked by XTOS on debug exceptions */ -#define SYS_unhandled_kernel_exc -9 /* invoked by XTOS for unhandled kernel exceptions */ -#define SYS_unhandled_user_exc -10 /* invoked by XTOS for unhandled user exceptions */ -#define SYS_unhandled_double_exc -11 /* invoked by XTOS for unhandled double exceptions */ -#define SYS_unhandled_highpri_interrupt -12 /* invoked by XTOS for unhandled high-priority interrupts */ -#define SYS_xmon_close -13 /* invoked by XMON: ... */ - -/* - * SIMCALLs for vxWorks xtiss BSP: - */ -#define SYS_setup_ppp_pipes -83 -#define SYS_log_msg -84 - -/* - * SYS_select_one specifiers - */ -#define XTISS_SELECT_ONE_READ 1 -#define XTISS_SELECT_ONE_WRITE 2 -#define XTISS_SELECT_ONE_EXCEPT 3 - -/* - * SIMCALL for client calling arbitrary code in a client plug in. - * see clients/xcc_instr to see how this works. - */ - -#define SYS_client 0xC0DECAFE - - - -#endif /* !SIMCALL_INCLUDED */ diff --git a/components/esp32/include/xtensa/tie/xt_DFP_assist.h b/components/esp32/include/xtensa/tie/xt_DFP_assist.h deleted file mode 100644 index 4d529ebd3f..0000000000 --- a/components/esp32/include/xtensa/tie/xt_DFP_assist.h +++ /dev/null @@ -1,96 +0,0 @@ -/* Definitions for the xt_DFP_assist TIE package */ - -/* - * Customer ID=11657; Build=0x5fe96; Copyright (c) 2004-2010 by Tensilica Inc. ALL RIGHTS RESERVED. - * These coded instructions, statements, and computer programs are the - * copyrighted works and confidential proprietary information of Tensilica Inc. - * They may not be modified, copied, reproduced, distributed, or disclosed to - * third parties in any manner, medium, or form, in whole or in part, without - * the prior written consent of Tensilica Inc. - */ - -/* Do not modify. This is automatically generated.*/ - -#ifndef _XTENSA_xt_DFP_assist_HEADER -#define _XTENSA_xt_DFP_assist_HEADER - -#ifdef __XTENSA__ -#ifdef __XCC__ - -#include - -/* - * The following prototypes describe intrinsic functions - * corresponding to TIE instructions. Some TIE instructions - * may produce multiple results (designated as "out" operands - * in the iclass section) or may have operands used as both - * inputs and outputs (designated as "inout"). However, the C - * and C++ languages do not provide syntax that can express - * the in/out/inout constraints of TIE intrinsics. - * Nevertheless, the compiler understands these constraints - * and will check that the intrinsic functions are used - * correctly. To improve the readability of these prototypes, - * the "out" and "inout" parameters are marked accordingly - * with comments. - */ - -extern void _TIE_xt_DFP_assist_F64ITER(unsigned arr /*inout*/, unsigned ars, unsigned art, immediate oper, immediate noshift); -extern unsigned _TIE_xt_DFP_assist_F64RND(unsigned ars, unsigned art, immediate mode); -extern void _TIE_xt_DFP_assist_F64ADDC(unsigned art /*inout*/, unsigned ars, immediate immZ, immediate immC); -extern void _TIE_xt_DFP_assist_F64SUBC(unsigned art /*inout*/, unsigned ars, immediate immZ, immediate immC); -extern unsigned _TIE_xt_DFP_assist_F64SIG(unsigned ars); -extern unsigned _TIE_xt_DFP_assist_F64CMPL(unsigned ars, unsigned art); -extern unsigned _TIE_xt_DFP_assist_F64CMPH(unsigned ars, unsigned art, immediate oper); -extern unsigned _TIE_xt_DFP_assist_F64NORM(unsigned ars, unsigned art, immediate mode); -extern unsigned _TIE_xt_DFP_assist_F64SEXP(unsigned ars, unsigned art); -extern unsigned _TIE_xt_DFP_assist_RF64R(immediate hilo); -extern void _TIE_xt_DFP_assist_WF64R(unsigned ars, unsigned art, immediate hilo); -extern unsigned _TIE_xt_DFP_assist_RUR_F64R_LO(void); -extern unsigned _TIE_xt_DFP_assist_RUR_F64R_HI(void); -extern void _TIE_xt_DFP_assist_WUR_F64R_LO(unsigned art); -extern void _TIE_xt_DFP_assist_WUR_F64R_HI(unsigned art); -extern unsigned _TIE_xt_DFP_assist_RUR_F64S(void); -extern void _TIE_xt_DFP_assist_WUR_F64S(unsigned art); -#define F64ITER _TIE_xt_DFP_assist_F64ITER -#define F64RND _TIE_xt_DFP_assist_F64RND -#define F64ADDC _TIE_xt_DFP_assist_F64ADDC -#define F64SUBC _TIE_xt_DFP_assist_F64SUBC -#define F64SIG _TIE_xt_DFP_assist_F64SIG -#define F64CMPL _TIE_xt_DFP_assist_F64CMPL -#define F64CMPH _TIE_xt_DFP_assist_F64CMPH -#define F64NORM _TIE_xt_DFP_assist_F64NORM -#define F64SEXP _TIE_xt_DFP_assist_F64SEXP -#define RF64R _TIE_xt_DFP_assist_RF64R -#define WF64R _TIE_xt_DFP_assist_WF64R -#define RUR_F64R_LO _TIE_xt_DFP_assist_RUR_F64R_LO -#define RF64R_LO _TIE_xt_DFP_assist_RUR_F64R_LO -#define RUR234 _TIE_xt_DFP_assist_RUR_F64R_LO -#define RUR_F64R_HI _TIE_xt_DFP_assist_RUR_F64R_HI -#define RF64R_HI _TIE_xt_DFP_assist_RUR_F64R_HI -#define RUR235 _TIE_xt_DFP_assist_RUR_F64R_HI -#define WUR_F64R_LO _TIE_xt_DFP_assist_WUR_F64R_LO -#define WF64R_LO _TIE_xt_DFP_assist_WUR_F64R_LO -#define WUR234 _TIE_xt_DFP_assist_WUR_F64R_LO -#define WUR_F64R_HI _TIE_xt_DFP_assist_WUR_F64R_HI -#define WF64R_HI _TIE_xt_DFP_assist_WUR_F64R_HI -#define WUR235 _TIE_xt_DFP_assist_WUR_F64R_HI -#define RUR_F64S _TIE_xt_DFP_assist_RUR_F64S -#define RF64S _TIE_xt_DFP_assist_RUR_F64S -#define RUR236 _TIE_xt_DFP_assist_RUR_F64S -#define WUR_F64S _TIE_xt_DFP_assist_WUR_F64S -#define WF64S _TIE_xt_DFP_assist_WUR_F64S -#define WUR236 _TIE_xt_DFP_assist_WUR_F64S - -#ifndef RUR -#define RUR(NUM) RUR##NUM() -#endif - -#ifndef WUR -#define WUR(VAL, NUM) WUR##NUM(VAL) -#endif - -#endif /* __XCC__ */ - -#endif /* __XTENSA__ */ - -#endif /* !_XTENSA_xt_DFP_assist_HEADER */ diff --git a/components/esp32/include/xtensa/tie/xt_FP.h b/components/esp32/include/xtensa/tie/xt_FP.h deleted file mode 100644 index 229a108ab7..0000000000 --- a/components/esp32/include/xtensa/tie/xt_FP.h +++ /dev/null @@ -1,197 +0,0 @@ -/* Definitions for the xt_FP TIE package */ - -/* - * Customer ID=11657; Build=0x5fe96; Copyright (c) 2004-2010 by Tensilica Inc. ALL RIGHTS RESERVED. - * These coded instructions, statements, and computer programs are the - * copyrighted works and confidential proprietary information of Tensilica Inc. - * They may not be modified, copied, reproduced, distributed, or disclosed to - * third parties in any manner, medium, or form, in whole or in part, without - * the prior written consent of Tensilica Inc. - */ - -/* Do not modify. This is automatically generated.*/ - -#ifndef _XTENSA_xt_FP_HEADER -#define _XTENSA_xt_FP_HEADER - -#ifdef __XTENSA__ -#ifdef __XCC__ - -#include -#include -typedef float _TIE_xt_FP_xtfloat; -typedef _TIE_xt_FP_xtfloat xtfloat; - -/* - * The following prototypes describe intrinsic functions - * corresponding to TIE instructions. Some TIE instructions - * may produce multiple results (designated as "out" operands - * in the iclass section) or may have operands used as both - * inputs and outputs (designated as "inout"). However, the C - * and C++ languages do not provide syntax that can express - * the in/out/inout constraints of TIE intrinsics. - * Nevertheless, the compiler understands these constraints - * and will check that the intrinsic functions are used - * correctly. To improve the readability of these prototypes, - * the "out" and "inout" parameters are marked accordingly - * with comments. - */ - -extern unsigned _TIE_xt_FP_RUR_FCR(void); -extern void _TIE_xt_FP_WUR_FCR(unsigned v); -extern unsigned _TIE_xt_FP_RUR_FSR(void); -extern void _TIE_xt_FP_WUR_FSR(unsigned v); -extern xtfloat _TIE_xt_FP_xtfloat_loadi(const xtfloat * p, immediate imm8x4); -extern void _TIE_xt_FP_xtfloat_storei(xtfloat t, xtfloat * p, immediate imm8x4); -extern void _TIE_xt_FP_xtfloat_loadip(xtfloat t /*out*/, const xtfloat * p /*inout*/, immediate imm8x4); -extern void _TIE_xt_FP_xtfloat_storeip(xtfloat t, xtfloat * p /*inout*/, immediate imm8x4); -extern xtfloat _TIE_xt_FP_xtfloat_loadx(const xtfloat * p, int imm8x4); -extern void _TIE_xt_FP_xtfloat_storex(xtfloat t, xtfloat * p, int imm8x4); -extern void _TIE_xt_FP_xtfloat_loadxp(xtfloat t /*out*/, const xtfloat * p /*inout*/, int imm8x4); -extern void _TIE_xt_FP_xtfloat_storexp(xtfloat t, xtfloat * p /*inout*/, int imm8x4); -extern xtfloat _TIE_xt_FP_xtfloat_move(xtfloat r); -extern int _TIE_xt_FP_ROUND_S(xtfloat s, immediate t); -extern int _TIE_xt_FP_TRUNC_S(xtfloat s, immediate t); -extern unsigned _TIE_xt_FP_UTRUNC_S(xtfloat s, immediate t); -extern int _TIE_xt_FP_FLOOR_S(xtfloat s, immediate t); -extern int _TIE_xt_FP_CEIL_S(xtfloat s, immediate t); -extern xtfloat _TIE_xt_FP_LSI(const xtfloat * p, immediate imm8x4); -extern void _TIE_xt_FP_SSI(xtfloat t, xtfloat * p, immediate imm8x4); -extern void _TIE_xt_FP_LSIP(xtfloat t /*out*/, const xtfloat * p /*inout*/, immediate imm8x4); -extern void _TIE_xt_FP_SSIP(xtfloat t, xtfloat * p /*inout*/, immediate imm8x4); -extern xtfloat _TIE_xt_FP_LSX(const xtfloat * p, int imm8x4); -extern void _TIE_xt_FP_SSX(xtfloat t, xtfloat * p, int imm8x4); -extern void _TIE_xt_FP_LSXP(xtfloat t /*out*/, const xtfloat * p /*inout*/, int imm8x4); -extern void _TIE_xt_FP_SSXP(xtfloat t, xtfloat * p /*inout*/, int imm8x4); -extern xtfloat _TIE_xt_FP_ABS_S(xtfloat s); -extern xtfloat _TIE_xt_FP_NEG_S(xtfloat s); -extern xtfloat _TIE_xt_FP_MOV_S(xtfloat s); -extern void _TIE_xt_FP_MOVEQZ_S(xtfloat r /*inout*/, xtfloat s, int t); -extern void _TIE_xt_FP_MOVNEZ_S(xtfloat r /*inout*/, xtfloat s, int t); -extern void _TIE_xt_FP_MOVLTZ_S(xtfloat r /*inout*/, xtfloat s, int t); -extern void _TIE_xt_FP_MOVGEZ_S(xtfloat r /*inout*/, xtfloat s, int t); -extern void _TIE_xt_FP_MOVF_S(xtfloat r /*inout*/, xtfloat s, xtbool t); -extern void _TIE_xt_FP_MOVT_S(xtfloat r /*inout*/, xtfloat s, xtbool t); -extern unsigned _TIE_xt_FP_RFR(xtfloat s); -extern xtfloat _TIE_xt_FP_WFR(unsigned s); -extern xtfloat _TIE_xt_FP_FLOAT_S(int s, immediate t); -extern xtfloat _TIE_xt_FP_UFLOAT_S(unsigned s, immediate t); -extern xtbool _TIE_xt_FP_OEQ_S(xtfloat s, xtfloat t); -extern xtbool _TIE_xt_FP_OLE_S(xtfloat s, xtfloat t); -extern xtbool _TIE_xt_FP_OLT_S(xtfloat s, xtfloat t); -extern xtbool _TIE_xt_FP_UEQ_S(xtfloat s, xtfloat t); -extern xtbool _TIE_xt_FP_ULE_S(xtfloat s, xtfloat t); -extern xtbool _TIE_xt_FP_ULT_S(xtfloat s, xtfloat t); -extern xtbool _TIE_xt_FP_UN_S(xtfloat s, xtfloat t); -extern xtfloat _TIE_xt_FP_ADD_S(xtfloat s, xtfloat t); -extern xtfloat _TIE_xt_FP_SUB_S(xtfloat s, xtfloat t); -extern xtfloat _TIE_xt_FP_MUL_S(xtfloat s, xtfloat t); -extern void _TIE_xt_FP_MADD_S(xtfloat r /*inout*/, xtfloat s, xtfloat t); -extern void _TIE_xt_FP_MSUB_S(xtfloat r /*inout*/, xtfloat s, xtfloat t); -extern xtfloat _TIE_xt_FP_RECIP0_S(xtfloat s); -extern xtfloat _TIE_xt_FP_DIV0_S(xtfloat s); -extern xtfloat _TIE_xt_FP_NEXP01_S(xtfloat s); -extern xtfloat _TIE_xt_FP_CONST_S(immediate s); -extern void _TIE_xt_FP_MKDADJ_S(xtfloat r /*inout*/, xtfloat s); -extern xtfloat _TIE_xt_FP_MKSADJ_S(xtfloat s); -extern void _TIE_xt_FP_ADDEXPM_S(xtfloat r /*inout*/, xtfloat s); -extern void _TIE_xt_FP_ADDEXP_S(xtfloat r /*inout*/, xtfloat s); -extern void _TIE_xt_FP_DIVN_S(xtfloat r /*inout*/, xtfloat s, xtfloat t); -extern xtfloat _TIE_xt_FP_RSQRT0_S(xtfloat s); -extern xtfloat _TIE_xt_FP_SQRT0_S(xtfloat s); -extern void _TIE_xt_FP_MADDN_S(xtfloat r /*inout*/, xtfloat s, xtfloat t); -extern xtfloat _TIE_xt_FP_DIV_S(xtfloat s, xtfloat t); -extern xtfloat _TIE_xt_FP_SQRT_S(xtfloat s); -extern xtfloat _TIE_xt_FP_RECIP_S(xtfloat s); -extern xtfloat _TIE_xt_FP_RSQRT_S(xtfloat s); -extern xtfloat _TIE_xt_FP_FSQRT_S(xtfloat s); -#define XT_RUR_FCR _TIE_xt_FP_RUR_FCR -#define RFCR _TIE_xt_FP_RUR_FCR -#define RUR232 _TIE_xt_FP_RUR_FCR -#define XT_WUR_FCR _TIE_xt_FP_WUR_FCR -#define WFCR _TIE_xt_FP_WUR_FCR -#define WUR232 _TIE_xt_FP_WUR_FCR -#define XT_RUR_FSR _TIE_xt_FP_RUR_FSR -#define RFSR _TIE_xt_FP_RUR_FSR -#define RUR233 _TIE_xt_FP_RUR_FSR -#define XT_WUR_FSR _TIE_xt_FP_WUR_FSR -#define WFSR _TIE_xt_FP_WUR_FSR -#define WUR233 _TIE_xt_FP_WUR_FSR -#define XT_xtfloat_loadi _TIE_xt_FP_xtfloat_loadi -#define XT_xtfloat_storei _TIE_xt_FP_xtfloat_storei -#define XT_xtfloat_loadip _TIE_xt_FP_xtfloat_loadip -#define XT_xtfloat_storeip _TIE_xt_FP_xtfloat_storeip -#define XT_xtfloat_loadx _TIE_xt_FP_xtfloat_loadx -#define XT_xtfloat_storex _TIE_xt_FP_xtfloat_storex -#define XT_xtfloat_loadxp _TIE_xt_FP_xtfloat_loadxp -#define XT_xtfloat_storexp _TIE_xt_FP_xtfloat_storexp -#define XT_xtfloat_move _TIE_xt_FP_xtfloat_move -#define XT_ROUND_S _TIE_xt_FP_ROUND_S -#define XT_TRUNC_S _TIE_xt_FP_TRUNC_S -#define XT_UTRUNC_S _TIE_xt_FP_UTRUNC_S -#define XT_FLOOR_S _TIE_xt_FP_FLOOR_S -#define XT_CEIL_S _TIE_xt_FP_CEIL_S -#define XT_LSI _TIE_xt_FP_LSI -#define XT_SSI _TIE_xt_FP_SSI -#define XT_LSIP _TIE_xt_FP_LSIP -#define XT_SSIP _TIE_xt_FP_SSIP -#define XT_LSX _TIE_xt_FP_LSX -#define XT_SSX _TIE_xt_FP_SSX -#define XT_LSXP _TIE_xt_FP_LSXP -#define XT_SSXP _TIE_xt_FP_SSXP -#define XT_ABS_S _TIE_xt_FP_ABS_S -#define XT_NEG_S _TIE_xt_FP_NEG_S -#define XT_MOV_S _TIE_xt_FP_MOV_S -#define XT_MOVEQZ_S _TIE_xt_FP_MOVEQZ_S -#define XT_MOVNEZ_S _TIE_xt_FP_MOVNEZ_S -#define XT_MOVLTZ_S _TIE_xt_FP_MOVLTZ_S -#define XT_MOVGEZ_S _TIE_xt_FP_MOVGEZ_S -#define XT_MOVF_S _TIE_xt_FP_MOVF_S -#define XT_MOVT_S _TIE_xt_FP_MOVT_S -#define XT_RFR _TIE_xt_FP_RFR -#define XT_WFR _TIE_xt_FP_WFR -#define XT_FLOAT_S _TIE_xt_FP_FLOAT_S -#define XT_UFLOAT_S _TIE_xt_FP_UFLOAT_S -#define XT_OEQ_S _TIE_xt_FP_OEQ_S -#define XT_OLE_S _TIE_xt_FP_OLE_S -#define XT_OLT_S _TIE_xt_FP_OLT_S -#define XT_UEQ_S _TIE_xt_FP_UEQ_S -#define XT_ULE_S _TIE_xt_FP_ULE_S -#define XT_ULT_S _TIE_xt_FP_ULT_S -#define XT_UN_S _TIE_xt_FP_UN_S -#define XT_ADD_S _TIE_xt_FP_ADD_S -#define XT_SUB_S _TIE_xt_FP_SUB_S -#define XT_MUL_S _TIE_xt_FP_MUL_S -#define XT_MADD_S _TIE_xt_FP_MADD_S -#define XT_MSUB_S _TIE_xt_FP_MSUB_S -#define XT_RECIP0_S _TIE_xt_FP_RECIP0_S -#define XT_DIV0_S _TIE_xt_FP_DIV0_S -#define XT_NEXP01_S _TIE_xt_FP_NEXP01_S -#define XT_CONST_S _TIE_xt_FP_CONST_S -#define XT_MKDADJ_S _TIE_xt_FP_MKDADJ_S -#define XT_MKSADJ_S _TIE_xt_FP_MKSADJ_S -#define XT_ADDEXPM_S _TIE_xt_FP_ADDEXPM_S -#define XT_ADDEXP_S _TIE_xt_FP_ADDEXP_S -#define XT_DIVN_S _TIE_xt_FP_DIVN_S -#define XT_RSQRT0_S _TIE_xt_FP_RSQRT0_S -#define XT_SQRT0_S _TIE_xt_FP_SQRT0_S -#define XT_MADDN_S _TIE_xt_FP_MADDN_S -#define XT_DIV_S _TIE_xt_FP_DIV_S -#define XT_SQRT_S _TIE_xt_FP_SQRT_S -#define XT_RECIP_S _TIE_xt_FP_RECIP_S -#define XT_RSQRT_S _TIE_xt_FP_RSQRT_S -#define XT_FSQRT_S _TIE_xt_FP_FSQRT_S - -#ifndef RUR -#define RUR(NUM) RUR##NUM() -#endif - -#ifndef WUR -#define WUR(VAL, NUM) WUR##NUM(VAL) -#endif - -#endif /* __XCC__ */ - -#endif /* __XTENSA__ */ - -#endif /* !_XTENSA_xt_FP_HEADER */ diff --git a/components/esp32/include/xtensa/tie/xt_MAC16.h b/components/esp32/include/xtensa/tie/xt_MAC16.h deleted file mode 100644 index b46a1db7f7..0000000000 --- a/components/esp32/include/xtensa/tie/xt_MAC16.h +++ /dev/null @@ -1,239 +0,0 @@ -/* Definitions for the xt_MAC16 TIE package */ - -/* - * Customer ID=11657; Build=0x5fe96; Copyright (c) 2004-2010 by Tensilica Inc. ALL RIGHTS RESERVED. - * These coded instructions, statements, and computer programs are the - * copyrighted works and confidential proprietary information of Tensilica Inc. - * They may not be modified, copied, reproduced, distributed, or disclosed to - * third parties in any manner, medium, or form, in whole or in part, without - * the prior written consent of Tensilica Inc. - */ - -/* Do not modify. This is automatically generated.*/ - -#ifndef _XTENSA_xt_MAC16_HEADER -#define _XTENSA_xt_MAC16_HEADER - -#ifdef __XTENSA__ -#ifdef __XCC__ - -#include -#include - -/* - * The following prototypes describe intrinsic functions - * corresponding to TIE instructions. Some TIE instructions - * may produce multiple results (designated as "out" operands - * in the iclass section) or may have operands used as both - * inputs and outputs (designated as "inout"). However, the C - * and C++ languages do not provide syntax that can express - * the in/out/inout constraints of TIE intrinsics. - * Nevertheless, the compiler understands these constraints - * and will check that the intrinsic functions are used - * correctly. To improve the readability of these prototypes, - * the "out" and "inout" parameters are marked accordingly - * with comments. - */ - -extern void _TIE_xt_MAC16_UMUL_AA_HH(unsigned ars, unsigned art); -extern void _TIE_xt_MAC16_UMUL_AA_LH(unsigned ars, unsigned art); -extern void _TIE_xt_MAC16_UMUL_AA_HL(unsigned ars, unsigned art); -extern void _TIE_xt_MAC16_UMUL_AA_LL(unsigned ars, unsigned art); -extern void _TIE_xt_MAC16_MUL_AA_HH(unsigned ars, unsigned art); -extern void _TIE_xt_MAC16_MUL_AA_LH(unsigned ars, unsigned art); -extern void _TIE_xt_MAC16_MUL_AA_HL(unsigned ars, unsigned art); -extern void _TIE_xt_MAC16_MUL_AA_LL(unsigned ars, unsigned art); -extern void _TIE_xt_MAC16_MUL_AD_HH(unsigned ars, immediate my); -extern void _TIE_xt_MAC16_MUL_AD_LH(unsigned ars, immediate my); -extern void _TIE_xt_MAC16_MUL_AD_HL(unsigned ars, immediate my); -extern void _TIE_xt_MAC16_MUL_AD_LL(unsigned ars, immediate my); -extern void _TIE_xt_MAC16_MUL_DA_HH(immediate mx, unsigned art); -extern void _TIE_xt_MAC16_MUL_DA_LH(immediate mx, unsigned art); -extern void _TIE_xt_MAC16_MUL_DA_HL(immediate mx, unsigned art); -extern void _TIE_xt_MAC16_MUL_DA_LL(immediate mx, unsigned art); -extern void _TIE_xt_MAC16_MUL_DD_HH(immediate mx, immediate my); -extern void _TIE_xt_MAC16_MUL_DD_LH(immediate mx, immediate my); -extern void _TIE_xt_MAC16_MUL_DD_HL(immediate mx, immediate my); -extern void _TIE_xt_MAC16_MUL_DD_LL(immediate mx, immediate my); -extern void _TIE_xt_MAC16_MULS_AA_HH(unsigned ars, unsigned art); -extern void _TIE_xt_MAC16_MULS_AA_LH(unsigned ars, unsigned art); -extern void _TIE_xt_MAC16_MULS_AA_HL(unsigned ars, unsigned art); -extern void _TIE_xt_MAC16_MULS_AA_LL(unsigned ars, unsigned art); -extern void _TIE_xt_MAC16_MULA_AA_HH(unsigned ars, unsigned art); -extern void _TIE_xt_MAC16_MULA_AA_LH(unsigned ars, unsigned art); -extern void _TIE_xt_MAC16_MULA_AA_HL(unsigned ars, unsigned art); -extern void _TIE_xt_MAC16_MULA_AA_LL(unsigned ars, unsigned art); -extern void _TIE_xt_MAC16_MULS_AD_HH(unsigned ars, immediate my); -extern void _TIE_xt_MAC16_MULS_AD_LH(unsigned ars, immediate my); -extern void _TIE_xt_MAC16_MULS_AD_HL(unsigned ars, immediate my); -extern void _TIE_xt_MAC16_MULS_AD_LL(unsigned ars, immediate my); -extern void _TIE_xt_MAC16_MULA_AD_HH(unsigned ars, immediate my); -extern void _TIE_xt_MAC16_MULA_AD_LH(unsigned ars, immediate my); -extern void _TIE_xt_MAC16_MULA_AD_HL(unsigned ars, immediate my); -extern void _TIE_xt_MAC16_MULA_AD_LL(unsigned ars, immediate my); -extern void _TIE_xt_MAC16_MULS_DA_HH(immediate mx, unsigned art); -extern void _TIE_xt_MAC16_MULS_DA_LH(immediate mx, unsigned art); -extern void _TIE_xt_MAC16_MULS_DA_HL(immediate mx, unsigned art); -extern void _TIE_xt_MAC16_MULS_DA_LL(immediate mx, unsigned art); -extern void _TIE_xt_MAC16_MULA_DA_HH(immediate mx, unsigned art); -extern void _TIE_xt_MAC16_MULA_DA_LH(immediate mx, unsigned art); -extern void _TIE_xt_MAC16_MULA_DA_HL(immediate mx, unsigned art); -extern void _TIE_xt_MAC16_MULA_DA_LL(immediate mx, unsigned art); -extern void _TIE_xt_MAC16_MULS_DD_HH(immediate mx, immediate my); -extern void _TIE_xt_MAC16_MULS_DD_LH(immediate mx, immediate my); -extern void _TIE_xt_MAC16_MULS_DD_HL(immediate mx, immediate my); -extern void _TIE_xt_MAC16_MULS_DD_LL(immediate mx, immediate my); -extern void _TIE_xt_MAC16_MULA_DD_HH(immediate mx, immediate my); -extern void _TIE_xt_MAC16_MULA_DD_LH(immediate mx, immediate my); -extern void _TIE_xt_MAC16_MULA_DD_HL(immediate mx, immediate my); -extern void _TIE_xt_MAC16_MULA_DD_LL(immediate mx, immediate my); -extern unsigned _TIE_xt_MAC16_RSR_M0(void); -extern void _TIE_xt_MAC16_WSR_M0(unsigned art); -extern void _TIE_xt_MAC16_XSR_M0(unsigned art /*inout*/); -extern unsigned _TIE_xt_MAC16_RSR_M1(void); -extern void _TIE_xt_MAC16_WSR_M1(unsigned art); -extern void _TIE_xt_MAC16_XSR_M1(unsigned art /*inout*/); -extern unsigned _TIE_xt_MAC16_RSR_M2(void); -extern void _TIE_xt_MAC16_WSR_M2(unsigned art); -extern void _TIE_xt_MAC16_XSR_M2(unsigned art /*inout*/); -extern unsigned _TIE_xt_MAC16_RSR_M3(void); -extern void _TIE_xt_MAC16_WSR_M3(unsigned art); -extern void _TIE_xt_MAC16_XSR_M3(unsigned art /*inout*/); -extern unsigned _TIE_xt_MAC16_RSR_ACCLO(void); -extern void _TIE_xt_MAC16_WSR_ACCLO(unsigned art); -extern void _TIE_xt_MAC16_XSR_ACCLO(unsigned art /*inout*/); -extern unsigned _TIE_xt_MAC16_RSR_ACCHI(void); -extern void _TIE_xt_MAC16_WSR_ACCHI(unsigned art); -extern void _TIE_xt_MAC16_XSR_ACCHI(unsigned art /*inout*/); -extern void _TIE_xt_MAC16_MULA_DA_LL_LDDEC(immediate w, const short * s /*inout*/, immediate x, int t); -extern void _TIE_xt_MAC16_MULA_DA_LL_LDINC(immediate w, const short * s /*inout*/, immediate x, int t); -extern void _TIE_xt_MAC16_MULA_DA_HL_LDDEC(immediate w, const short * s /*inout*/, immediate x, int t); -extern void _TIE_xt_MAC16_MULA_DA_HL_LDINC(immediate w, const short * s /*inout*/, immediate x, int t); -extern void _TIE_xt_MAC16_MULA_DA_LH_LDDEC(immediate w, const short * s /*inout*/, immediate x, int t); -extern void _TIE_xt_MAC16_MULA_DA_LH_LDINC(immediate w, const short * s /*inout*/, immediate x, int t); -extern void _TIE_xt_MAC16_MULA_DA_HH_LDDEC(immediate w, const short * s /*inout*/, immediate x, int t); -extern void _TIE_xt_MAC16_MULA_DA_HH_LDINC(immediate w, const short * s /*inout*/, immediate x, int t); -extern void _TIE_xt_MAC16_MULA_DD_LL_LDDEC(immediate w, const short * s /*inout*/, immediate x, immediate y); -extern void _TIE_xt_MAC16_MULA_DD_LL_LDINC(immediate w, const short * s /*inout*/, immediate x, immediate y); -extern void _TIE_xt_MAC16_MULA_DD_HL_LDDEC(immediate w, const short * s /*inout*/, immediate x, immediate y); -extern void _TIE_xt_MAC16_MULA_DD_HL_LDINC(immediate w, const short * s /*inout*/, immediate x, immediate y); -extern void _TIE_xt_MAC16_MULA_DD_LH_LDDEC(immediate w, const short * s /*inout*/, immediate x, immediate y); -extern void _TIE_xt_MAC16_MULA_DD_LH_LDINC(immediate w, const short * s /*inout*/, immediate x, immediate y); -extern void _TIE_xt_MAC16_MULA_DD_HH_LDDEC(immediate w, const short * s /*inout*/, immediate x, immediate y); -extern void _TIE_xt_MAC16_MULA_DD_HH_LDINC(immediate w, const short * s /*inout*/, immediate x, immediate y); -extern void _TIE_xt_MAC16_LDDEC(immediate w, const short * p /*inout*/); -extern void _TIE_xt_MAC16_ULDDEC(immediate w, const unsigned short * p /*inout*/); -extern void _TIE_xt_MAC16_SLDDEC(immediate w, const short * p /*inout*/); -extern void _TIE_xt_MAC16_LDINC(immediate w, const short * p /*inout*/); -extern void _TIE_xt_MAC16_ULDINC(immediate w, const unsigned short * p /*inout*/); -extern void _TIE_xt_MAC16_SLDINC(immediate w, const short * p /*inout*/); -extern int _TIE_xt_MAC16_RSR16(void); -extern void _TIE_xt_MAC16_WSR16(int t); -extern void _TIE_xt_MAC16_XSR16(int t /*inout*/); -extern int _TIE_xt_MAC16_RSR17(void); -extern void _TIE_xt_MAC16_WSR17(int t); -extern void _TIE_xt_MAC16_XSR17(int t /*inout*/); -#define XT_UMUL_AA_HH _TIE_xt_MAC16_UMUL_AA_HH -#define XT_UMUL_AA_LH _TIE_xt_MAC16_UMUL_AA_LH -#define XT_UMUL_AA_HL _TIE_xt_MAC16_UMUL_AA_HL -#define XT_UMUL_AA_LL _TIE_xt_MAC16_UMUL_AA_LL -#define XT_MUL_AA_HH _TIE_xt_MAC16_MUL_AA_HH -#define XT_MUL_AA_LH _TIE_xt_MAC16_MUL_AA_LH -#define XT_MUL_AA_HL _TIE_xt_MAC16_MUL_AA_HL -#define XT_MUL_AA_LL _TIE_xt_MAC16_MUL_AA_LL -#define XT_MUL_AD_HH _TIE_xt_MAC16_MUL_AD_HH -#define XT_MUL_AD_LH _TIE_xt_MAC16_MUL_AD_LH -#define XT_MUL_AD_HL _TIE_xt_MAC16_MUL_AD_HL -#define XT_MUL_AD_LL _TIE_xt_MAC16_MUL_AD_LL -#define XT_MUL_DA_HH _TIE_xt_MAC16_MUL_DA_HH -#define XT_MUL_DA_LH _TIE_xt_MAC16_MUL_DA_LH -#define XT_MUL_DA_HL _TIE_xt_MAC16_MUL_DA_HL -#define XT_MUL_DA_LL _TIE_xt_MAC16_MUL_DA_LL -#define XT_MUL_DD_HH _TIE_xt_MAC16_MUL_DD_HH -#define XT_MUL_DD_LH _TIE_xt_MAC16_MUL_DD_LH -#define XT_MUL_DD_HL _TIE_xt_MAC16_MUL_DD_HL -#define XT_MUL_DD_LL _TIE_xt_MAC16_MUL_DD_LL -#define XT_MULS_AA_HH _TIE_xt_MAC16_MULS_AA_HH -#define XT_MULS_AA_LH _TIE_xt_MAC16_MULS_AA_LH -#define XT_MULS_AA_HL _TIE_xt_MAC16_MULS_AA_HL -#define XT_MULS_AA_LL _TIE_xt_MAC16_MULS_AA_LL -#define XT_MULA_AA_HH _TIE_xt_MAC16_MULA_AA_HH -#define XT_MULA_AA_LH _TIE_xt_MAC16_MULA_AA_LH -#define XT_MULA_AA_HL _TIE_xt_MAC16_MULA_AA_HL -#define XT_MULA_AA_LL _TIE_xt_MAC16_MULA_AA_LL -#define XT_MULS_AD_HH _TIE_xt_MAC16_MULS_AD_HH -#define XT_MULS_AD_LH _TIE_xt_MAC16_MULS_AD_LH -#define XT_MULS_AD_HL _TIE_xt_MAC16_MULS_AD_HL -#define XT_MULS_AD_LL _TIE_xt_MAC16_MULS_AD_LL -#define XT_MULA_AD_HH _TIE_xt_MAC16_MULA_AD_HH -#define XT_MULA_AD_LH _TIE_xt_MAC16_MULA_AD_LH -#define XT_MULA_AD_HL _TIE_xt_MAC16_MULA_AD_HL -#define XT_MULA_AD_LL _TIE_xt_MAC16_MULA_AD_LL -#define XT_MULS_DA_HH _TIE_xt_MAC16_MULS_DA_HH -#define XT_MULS_DA_LH _TIE_xt_MAC16_MULS_DA_LH -#define XT_MULS_DA_HL _TIE_xt_MAC16_MULS_DA_HL -#define XT_MULS_DA_LL _TIE_xt_MAC16_MULS_DA_LL -#define XT_MULA_DA_HH _TIE_xt_MAC16_MULA_DA_HH -#define XT_MULA_DA_LH _TIE_xt_MAC16_MULA_DA_LH -#define XT_MULA_DA_HL _TIE_xt_MAC16_MULA_DA_HL -#define XT_MULA_DA_LL _TIE_xt_MAC16_MULA_DA_LL -#define XT_MULS_DD_HH _TIE_xt_MAC16_MULS_DD_HH -#define XT_MULS_DD_LH _TIE_xt_MAC16_MULS_DD_LH -#define XT_MULS_DD_HL _TIE_xt_MAC16_MULS_DD_HL -#define XT_MULS_DD_LL _TIE_xt_MAC16_MULS_DD_LL -#define XT_MULA_DD_HH _TIE_xt_MAC16_MULA_DD_HH -#define XT_MULA_DD_LH _TIE_xt_MAC16_MULA_DD_LH -#define XT_MULA_DD_HL _TIE_xt_MAC16_MULA_DD_HL -#define XT_MULA_DD_LL _TIE_xt_MAC16_MULA_DD_LL -#define XT_RSR_M0 _TIE_xt_MAC16_RSR_M0 -#define XT_WSR_M0 _TIE_xt_MAC16_WSR_M0 -#define XT_XSR_M0 _TIE_xt_MAC16_XSR_M0 -#define XT_RSR_M1 _TIE_xt_MAC16_RSR_M1 -#define XT_WSR_M1 _TIE_xt_MAC16_WSR_M1 -#define XT_XSR_M1 _TIE_xt_MAC16_XSR_M1 -#define XT_RSR_M2 _TIE_xt_MAC16_RSR_M2 -#define XT_WSR_M2 _TIE_xt_MAC16_WSR_M2 -#define XT_XSR_M2 _TIE_xt_MAC16_XSR_M2 -#define XT_RSR_M3 _TIE_xt_MAC16_RSR_M3 -#define XT_WSR_M3 _TIE_xt_MAC16_WSR_M3 -#define XT_XSR_M3 _TIE_xt_MAC16_XSR_M3 -#define XT_RSR_ACCLO _TIE_xt_MAC16_RSR_ACCLO -#define XT_WSR_ACCLO _TIE_xt_MAC16_WSR_ACCLO -#define XT_XSR_ACCLO _TIE_xt_MAC16_XSR_ACCLO -#define XT_RSR_ACCHI _TIE_xt_MAC16_RSR_ACCHI -#define XT_WSR_ACCHI _TIE_xt_MAC16_WSR_ACCHI -#define XT_XSR_ACCHI _TIE_xt_MAC16_XSR_ACCHI -#define XT_MULA_DA_LL_LDDEC _TIE_xt_MAC16_MULA_DA_LL_LDDEC -#define XT_MULA_DA_LL_LDINC _TIE_xt_MAC16_MULA_DA_LL_LDINC -#define XT_MULA_DA_HL_LDDEC _TIE_xt_MAC16_MULA_DA_HL_LDDEC -#define XT_MULA_DA_HL_LDINC _TIE_xt_MAC16_MULA_DA_HL_LDINC -#define XT_MULA_DA_LH_LDDEC _TIE_xt_MAC16_MULA_DA_LH_LDDEC -#define XT_MULA_DA_LH_LDINC _TIE_xt_MAC16_MULA_DA_LH_LDINC -#define XT_MULA_DA_HH_LDDEC _TIE_xt_MAC16_MULA_DA_HH_LDDEC -#define XT_MULA_DA_HH_LDINC _TIE_xt_MAC16_MULA_DA_HH_LDINC -#define XT_MULA_DD_LL_LDDEC _TIE_xt_MAC16_MULA_DD_LL_LDDEC -#define XT_MULA_DD_LL_LDINC _TIE_xt_MAC16_MULA_DD_LL_LDINC -#define XT_MULA_DD_HL_LDDEC _TIE_xt_MAC16_MULA_DD_HL_LDDEC -#define XT_MULA_DD_HL_LDINC _TIE_xt_MAC16_MULA_DD_HL_LDINC -#define XT_MULA_DD_LH_LDDEC _TIE_xt_MAC16_MULA_DD_LH_LDDEC -#define XT_MULA_DD_LH_LDINC _TIE_xt_MAC16_MULA_DD_LH_LDINC -#define XT_MULA_DD_HH_LDDEC _TIE_xt_MAC16_MULA_DD_HH_LDDEC -#define XT_MULA_DD_HH_LDINC _TIE_xt_MAC16_MULA_DD_HH_LDINC -#define XT_LDDEC _TIE_xt_MAC16_LDDEC -#define XT_ULDDEC _TIE_xt_MAC16_ULDDEC -#define XT_SLDDEC _TIE_xt_MAC16_SLDDEC -#define XT_LDINC _TIE_xt_MAC16_LDINC -#define XT_ULDINC _TIE_xt_MAC16_ULDINC -#define XT_SLDINC _TIE_xt_MAC16_SLDINC -#define XT_RSR16 _TIE_xt_MAC16_RSR16 -#define XT_WSR16 _TIE_xt_MAC16_WSR16 -#define XT_XSR16 _TIE_xt_MAC16_XSR16 -#define XT_RSR17 _TIE_xt_MAC16_RSR17 -#define XT_WSR17 _TIE_xt_MAC16_WSR17 -#define XT_XSR17 _TIE_xt_MAC16_XSR17 - -#endif /* __XCC__ */ - -#endif /* __XTENSA__ */ - -#endif /* !_XTENSA_xt_MAC16_HEADER */ diff --git a/components/esp32/include/xtensa/tie/xt_MUL32.h b/components/esp32/include/xtensa/tie/xt_MUL32.h deleted file mode 100644 index 91b3c3299c..0000000000 --- a/components/esp32/include/xtensa/tie/xt_MUL32.h +++ /dev/null @@ -1,24 +0,0 @@ -/* Definitions for the 32-bit Integer Multiply Option. */ - -/* - * Customer ID=11657; Build=0x5fe96; Copyright (c) 2009 by Tensilica Inc. ALL RIGHTS RESERVED. - * These coded instructions, statements, and computer programs are the - * copyrighted works and confidential proprietary information of Tensilica Inc. - * They may not be modified, copied, reproduced, distributed, or disclosed to - * third parties in any manner, medium, or form, in whole or in part, without - * the prior written consent of Tensilica Inc. - */ - -/* NOTE: This file exists only for backward compatibility with RB-200X.x - and earlier Xtensa releases. Starting with RC-2009.0 you should use - . */ - -#ifndef _XTENSA_xt_MUL32_HEADER -#define _XTENSA_xt_MUL32_HEADER - -#ifdef __XTENSA__ - -#include - -#endif /* __XTENSA__ */ -#endif /* !_XTENSA_xt_MUL32_HEADER */ diff --git a/components/esp32/include/xtensa/tie/xt_booleans.h b/components/esp32/include/xtensa/tie/xt_booleans.h deleted file mode 100644 index 94b5b468ed..0000000000 --- a/components/esp32/include/xtensa/tie/xt_booleans.h +++ /dev/null @@ -1,69 +0,0 @@ -/* Definitions for the xt_booleans TIE package */ - -/* - * Customer ID=11657; Build=0x5fe96; Copyright (c) 2004-2010 by Tensilica Inc. ALL RIGHTS RESERVED. - * These coded instructions, statements, and computer programs are the - * copyrighted works and confidential proprietary information of Tensilica Inc. - * They may not be modified, copied, reproduced, distributed, or disclosed to - * third parties in any manner, medium, or form, in whole or in part, without - * the prior written consent of Tensilica Inc. - */ - -/* Do not modify. This is automatically generated.*/ - -#ifndef _XTENSA_xt_booleans_HEADER -#define _XTENSA_xt_booleans_HEADER - -#ifdef __XTENSA__ -#ifdef __XCC__ - -#include -typedef _TIE_xtbool xtbool; -typedef _TIE_xtbool2 xtbool2; -typedef _TIE_xtbool4 xtbool4; -typedef _TIE_xtbool8 xtbool8; -typedef _TIE_xtbool16 xtbool16; - -/* - * The following prototypes describe intrinsic functions - * corresponding to TIE instructions. Some TIE instructions - * may produce multiple results (designated as "out" operands - * in the iclass section) or may have operands used as both - * inputs and outputs (designated as "inout"). However, the C - * and C++ languages do not provide syntax that can express - * the in/out/inout constraints of TIE intrinsics. - * Nevertheless, the compiler understands these constraints - * and will check that the intrinsic functions are used - * correctly. To improve the readability of these prototypes, - * the "out" and "inout" parameters are marked accordingly - * with comments. - */ - -extern xtbool _TIE_xt_booleans_XORB(xtbool bs, xtbool bt); -extern xtbool _TIE_xt_booleans_ORBC(xtbool bs, xtbool bt); -extern xtbool _TIE_xt_booleans_ORB(xtbool bs, xtbool bt); -extern xtbool _TIE_xt_booleans_ANDBC(xtbool bs, xtbool bt); -extern xtbool _TIE_xt_booleans_ANDB(xtbool bs, xtbool bt); -extern xtbool _TIE_xt_booleans_ALL4(xtbool4 bs4); -extern xtbool _TIE_xt_booleans_ANY4(xtbool4 bs4); -extern xtbool _TIE_xt_booleans_ALL8(xtbool8 bs8); -extern xtbool _TIE_xt_booleans_ANY8(xtbool8 bs8); -extern void _TIE_xt_booleans_MOVT(unsigned arr /*inout*/, unsigned ars, xtbool bt); -extern void _TIE_xt_booleans_MOVF(unsigned arr /*inout*/, unsigned ars, xtbool bt); -#define XT_XORB _TIE_xt_booleans_XORB -#define XT_ORBC _TIE_xt_booleans_ORBC -#define XT_ORB _TIE_xt_booleans_ORB -#define XT_ANDBC _TIE_xt_booleans_ANDBC -#define XT_ANDB _TIE_xt_booleans_ANDB -#define XT_ALL4 _TIE_xt_booleans_ALL4 -#define XT_ANY4 _TIE_xt_booleans_ANY4 -#define XT_ALL8 _TIE_xt_booleans_ALL8 -#define XT_ANY8 _TIE_xt_booleans_ANY8 -#define XT_MOVT _TIE_xt_booleans_MOVT -#define XT_MOVF _TIE_xt_booleans_MOVF - -#endif /* __XCC__ */ - -#endif /* __XTENSA__ */ - -#endif /* !_XTENSA_xt_booleans_HEADER */ diff --git a/components/esp32/include/xtensa/tie/xt_coprocessors.h b/components/esp32/include/xtensa/tie/xt_coprocessors.h deleted file mode 100644 index 27215cf1cd..0000000000 --- a/components/esp32/include/xtensa/tie/xt_coprocessors.h +++ /dev/null @@ -1,48 +0,0 @@ -/* Definitions for the xt_coprocessors TIE package */ - -/* - * Customer ID=11657; Build=0x5fe96; Copyright (c) 2004-2010 by Tensilica Inc. ALL RIGHTS RESERVED. - * These coded instructions, statements, and computer programs are the - * copyrighted works and confidential proprietary information of Tensilica Inc. - * They may not be modified, copied, reproduced, distributed, or disclosed to - * third parties in any manner, medium, or form, in whole or in part, without - * the prior written consent of Tensilica Inc. - */ - -/* Do not modify. This is automatically generated.*/ - -#ifndef _XTENSA_xt_coprocessors_HEADER -#define _XTENSA_xt_coprocessors_HEADER - -#ifdef __XTENSA__ -#ifdef __XCC__ - -#include - -/* - * The following prototypes describe intrinsic functions - * corresponding to TIE instructions. Some TIE instructions - * may produce multiple results (designated as "out" operands - * in the iclass section) or may have operands used as both - * inputs and outputs (designated as "inout"). However, the C - * and C++ languages do not provide syntax that can express - * the in/out/inout constraints of TIE intrinsics. - * Nevertheless, the compiler understands these constraints - * and will check that the intrinsic functions are used - * correctly. To improve the readability of these prototypes, - * the "out" and "inout" parameters are marked accordingly - * with comments. - */ - -extern unsigned _TIE_xt_coprocessors_RSR_CPENABLE(void); -extern void _TIE_xt_coprocessors_WSR_CPENABLE(unsigned art); -extern void _TIE_xt_coprocessors_XSR_CPENABLE(unsigned art /*inout*/); -#define XT_RSR_CPENABLE _TIE_xt_coprocessors_RSR_CPENABLE -#define XT_WSR_CPENABLE _TIE_xt_coprocessors_WSR_CPENABLE -#define XT_XSR_CPENABLE _TIE_xt_coprocessors_XSR_CPENABLE - -#endif /* __XCC__ */ - -#endif /* __XTENSA__ */ - -#endif /* !_XTENSA_xt_coprocessors_HEADER */ diff --git a/components/esp32/include/xtensa/tie/xt_core.h b/components/esp32/include/xtensa/tie/xt_core.h deleted file mode 100644 index 469b199e6b..0000000000 --- a/components/esp32/include/xtensa/tie/xt_core.h +++ /dev/null @@ -1,395 +0,0 @@ -/* Definitions for the xt_core TIE package */ - -/* - * Customer ID=11657; Build=0x5fe96; Copyright (c) 2004-2010 by Tensilica Inc. ALL RIGHTS RESERVED. - * These coded instructions, statements, and computer programs are the - * copyrighted works and confidential proprietary information of Tensilica Inc. - * They may not be modified, copied, reproduced, distributed, or disclosed to - * third parties in any manner, medium, or form, in whole or in part, without - * the prior written consent of Tensilica Inc. - */ - -/* Do not modify. This is automatically generated.*/ - -#ifndef _XTENSA_xt_core_HEADER -#define _XTENSA_xt_core_HEADER - -#ifdef __XTENSA__ -#ifdef __XCC__ - - -/* - * The following prototypes describe intrinsic functions - * corresponding to TIE instructions. Some TIE instructions - * may produce multiple results (designated as "out" operands - * in the iclass section) or may have operands used as both - * inputs and outputs (designated as "inout"). However, the C - * and C++ languages do not provide syntax that can express - * the in/out/inout constraints of TIE intrinsics. - * Nevertheless, the compiler understands these constraints - * and will check that the intrinsic functions are used - * correctly. To improve the readability of these prototypes, - * the "out" and "inout" parameters are marked accordingly - * with comments. - */ - -extern void _TIE_xt_core_ILL(void); -extern void _TIE_xt_core_NOP(void); -extern void _TIE_xt_core_SIMCALL(void); -extern void _TIE_xt_core_MEMW(void); -extern void _TIE_xt_core_EXTW(void); -extern void _TIE_xt_core_ISYNC(void); -extern void _TIE_xt_core_DSYNC(void); -extern void _TIE_xt_core_ESYNC(void); -extern void _TIE_xt_core_RSYNC(void); -extern unsigned _TIE_xt_core_RSR_LBEG(void); -extern void _TIE_xt_core_WSR_LBEG(unsigned art); -extern void _TIE_xt_core_XSR_LBEG(unsigned art /*inout*/); -extern unsigned _TIE_xt_core_RSR_CONFIGID0(void); -extern void _TIE_xt_core_WSR_CONFIGID0(unsigned art); -extern unsigned _TIE_xt_core_RSR_CONFIGID1(void); -extern unsigned _TIE_xt_core_RUR_THREADPTR(void); -extern void _TIE_xt_core_WUR_THREADPTR(unsigned v); -extern unsigned _TIE_xt_core_uint32_loadi(const unsigned * p, immediate o); -extern void _TIE_xt_core_uint32_storei(unsigned c, unsigned * p, immediate o); -extern unsigned _TIE_xt_core_uint32_move(unsigned b); -extern int _TIE_xt_core_ADDI(int s, immediate i); -extern int _TIE_xt_core_OR(int s, int t); -extern int _TIE_xt_core_L32I(const int * p, immediate i); -extern void _TIE_xt_core_S32I(int r, int * p, immediate i); -extern void _TIE_xt_core_S32NB(int r, int * p, immediate i); -extern unsigned char _TIE_xt_core_L8UI(const unsigned char * p, immediate i); -extern void _TIE_xt_core_S8I(signed char r, signed char * p, immediate i); -extern unsigned short _TIE_xt_core_L16UI(const unsigned short * p, immediate i); -extern short _TIE_xt_core_L16SI(const short * p, immediate i); -extern void _TIE_xt_core_S16I(short r, short * p, immediate i); -extern int _TIE_xt_core_ADDMI(int s, immediate i); -extern int _TIE_xt_core_ADD(int s, int t); -extern int _TIE_xt_core_ADDX2(int s, int t); -extern int _TIE_xt_core_ADDX4(int s, int t); -extern int _TIE_xt_core_ADDX8(int s, int t); -extern int _TIE_xt_core_SUB(int s, int t); -extern int _TIE_xt_core_SUBX2(int s, int t); -extern int _TIE_xt_core_SUBX4(int s, int t); -extern int _TIE_xt_core_SUBX8(int s, int t); -extern int _TIE_xt_core_AND(int s, int t); -extern int _TIE_xt_core_XOR(int s, int t); -extern unsigned _TIE_xt_core_EXTUI(unsigned t, immediate i, immediate o); -extern int _TIE_xt_core_MOVI(immediate i); -extern void _TIE_xt_core_MOVEQZ(int r /*inout*/, int s, int t); -extern void _TIE_xt_core_MOVNEZ(int r /*inout*/, int s, int t); -extern void _TIE_xt_core_MOVLTZ(int r /*inout*/, int s, int t); -extern void _TIE_xt_core_MOVGEZ(int r /*inout*/, int s, int t); -extern int _TIE_xt_core_NEG(int t); -extern int _TIE_xt_core_ABS(int t); -extern void _TIE_xt_core_SSR(int s); -extern void _TIE_xt_core_SSL(int s); -extern void _TIE_xt_core_SSA8L(int s); -extern void _TIE_xt_core_SSA8B(int s); -extern void _TIE_xt_core_SSAI(immediate i); -extern int _TIE_xt_core_SLL(int s); -extern int _TIE_xt_core_SRC(int s, int t); -extern unsigned _TIE_xt_core_SRL(unsigned t); -extern int _TIE_xt_core_SRA(int t); -extern int _TIE_xt_core_SLLI(int s, immediate i); -extern int _TIE_xt_core_SRAI(int t, immediate i); -extern unsigned _TIE_xt_core_SRLI(unsigned t, immediate i); -extern int _TIE_xt_core_SSAI_SRC(int src1, int src2, immediate amount); -extern int _TIE_xt_core_SSR_SRC(int src1, int src2, int amount); -extern int _TIE_xt_core_WSR_SAR_SRC(int src1, int src2, int amount); -extern int _TIE_xt_core_SSR_SRA(int src, int amount); -extern unsigned _TIE_xt_core_SSR_SRL(unsigned src, int amount); -extern int _TIE_xt_core_SSL_SLL(int src, int amount); -extern int _TIE_xt_core_RSIL(immediate t); -extern int _TIE_xt_core_RSR_LEND(void); -extern void _TIE_xt_core_WSR_LEND(int t); -extern void _TIE_xt_core_XSR_LEND(int t /*inout*/); -extern int _TIE_xt_core_RSR_LCOUNT(void); -extern void _TIE_xt_core_WSR_LCOUNT(int t); -extern void _TIE_xt_core_XSR_LCOUNT(int t /*inout*/); -extern unsigned _TIE_xt_core_RSR_SAR(void); -extern void _TIE_xt_core_WSR_SAR(unsigned t); -extern void _TIE_xt_core_XSR_SAR(unsigned t /*inout*/); -extern unsigned _TIE_xt_core_RSR_MEMCTL(void); -extern void _TIE_xt_core_WSR_MEMCTL(unsigned t); -extern void _TIE_xt_core_XSR_MEMCTL(unsigned t /*inout*/); -extern unsigned _TIE_xt_core_RSR_LITBASE(void); -extern void _TIE_xt_core_WSR_LITBASE(unsigned t); -extern void _TIE_xt_core_XSR_LITBASE(unsigned t /*inout*/); -extern unsigned _TIE_xt_core_RSR_PS(void); -extern void _TIE_xt_core_WSR_PS(unsigned t); -extern void _TIE_xt_core_XSR_PS(unsigned t /*inout*/); -extern unsigned _TIE_xt_core_RSR_EPC1(void); -extern void _TIE_xt_core_WSR_EPC1(unsigned t); -extern void _TIE_xt_core_XSR_EPC1(unsigned t /*inout*/); -extern unsigned _TIE_xt_core_RSR_EXCSAVE1(void); -extern void _TIE_xt_core_WSR_EXCSAVE1(unsigned t); -extern void _TIE_xt_core_XSR_EXCSAVE1(unsigned t /*inout*/); -extern unsigned _TIE_xt_core_RSR_EPC2(void); -extern void _TIE_xt_core_WSR_EPC2(unsigned t); -extern void _TIE_xt_core_XSR_EPC2(unsigned t /*inout*/); -extern unsigned _TIE_xt_core_RSR_EXCSAVE2(void); -extern void _TIE_xt_core_WSR_EXCSAVE2(unsigned t); -extern void _TIE_xt_core_XSR_EXCSAVE2(unsigned t /*inout*/); -extern unsigned _TIE_xt_core_RSR_EPC3(void); -extern void _TIE_xt_core_WSR_EPC3(unsigned t); -extern void _TIE_xt_core_XSR_EPC3(unsigned t /*inout*/); -extern unsigned _TIE_xt_core_RSR_EXCSAVE3(void); -extern void _TIE_xt_core_WSR_EXCSAVE3(unsigned t); -extern void _TIE_xt_core_XSR_EXCSAVE3(unsigned t /*inout*/); -extern unsigned _TIE_xt_core_RSR_EPC4(void); -extern void _TIE_xt_core_WSR_EPC4(unsigned t); -extern void _TIE_xt_core_XSR_EPC4(unsigned t /*inout*/); -extern unsigned _TIE_xt_core_RSR_EXCSAVE4(void); -extern void _TIE_xt_core_WSR_EXCSAVE4(unsigned t); -extern void _TIE_xt_core_XSR_EXCSAVE4(unsigned t /*inout*/); -extern unsigned _TIE_xt_core_RSR_EPC5(void); -extern void _TIE_xt_core_WSR_EPC5(unsigned t); -extern void _TIE_xt_core_XSR_EPC5(unsigned t /*inout*/); -extern unsigned _TIE_xt_core_RSR_EXCSAVE5(void); -extern void _TIE_xt_core_WSR_EXCSAVE5(unsigned t); -extern void _TIE_xt_core_XSR_EXCSAVE5(unsigned t /*inout*/); -extern unsigned _TIE_xt_core_RSR_EPC6(void); -extern void _TIE_xt_core_WSR_EPC6(unsigned t); -extern void _TIE_xt_core_XSR_EPC6(unsigned t /*inout*/); -extern unsigned _TIE_xt_core_RSR_EXCSAVE6(void); -extern void _TIE_xt_core_WSR_EXCSAVE6(unsigned t); -extern void _TIE_xt_core_XSR_EXCSAVE6(unsigned t /*inout*/); -extern unsigned _TIE_xt_core_RSR_EPC7(void); -extern void _TIE_xt_core_WSR_EPC7(unsigned t); -extern void _TIE_xt_core_XSR_EPC7(unsigned t /*inout*/); -extern unsigned _TIE_xt_core_RSR_EXCSAVE7(void); -extern void _TIE_xt_core_WSR_EXCSAVE7(unsigned t); -extern void _TIE_xt_core_XSR_EXCSAVE7(unsigned t /*inout*/); -extern unsigned _TIE_xt_core_RSR_VECBASE(void); -extern void _TIE_xt_core_WSR_VECBASE(unsigned t); -extern void _TIE_xt_core_XSR_VECBASE(unsigned t /*inout*/); -extern unsigned _TIE_xt_core_RSR_EPS2(void); -extern void _TIE_xt_core_WSR_EPS2(unsigned t); -extern void _TIE_xt_core_XSR_EPS2(unsigned t /*inout*/); -extern unsigned _TIE_xt_core_RSR_EPS3(void); -extern void _TIE_xt_core_WSR_EPS3(unsigned t); -extern void _TIE_xt_core_XSR_EPS3(unsigned t /*inout*/); -extern unsigned _TIE_xt_core_RSR_EPS4(void); -extern void _TIE_xt_core_WSR_EPS4(unsigned t); -extern void _TIE_xt_core_XSR_EPS4(unsigned t /*inout*/); -extern unsigned _TIE_xt_core_RSR_EPS5(void); -extern void _TIE_xt_core_WSR_EPS5(unsigned t); -extern void _TIE_xt_core_XSR_EPS5(unsigned t /*inout*/); -extern unsigned _TIE_xt_core_RSR_EPS6(void); -extern void _TIE_xt_core_WSR_EPS6(unsigned t); -extern void _TIE_xt_core_XSR_EPS6(unsigned t /*inout*/); -extern unsigned _TIE_xt_core_RSR_EPS7(void); -extern void _TIE_xt_core_WSR_EPS7(unsigned t); -extern void _TIE_xt_core_XSR_EPS7(unsigned t /*inout*/); -extern unsigned _TIE_xt_core_RSR_EXCCAUSE(void); -extern void _TIE_xt_core_WSR_EXCCAUSE(unsigned t); -extern void _TIE_xt_core_XSR_EXCCAUSE(unsigned t /*inout*/); -extern unsigned _TIE_xt_core_RSR_EXCVADDR(void); -extern void _TIE_xt_core_WSR_EXCVADDR(unsigned t); -extern void _TIE_xt_core_XSR_EXCVADDR(unsigned t /*inout*/); -extern unsigned _TIE_xt_core_RSR_DEPC(void); -extern void _TIE_xt_core_WSR_DEPC(unsigned t); -extern void _TIE_xt_core_XSR_DEPC(unsigned t /*inout*/); -extern unsigned _TIE_xt_core_RSR_MISC0(void); -extern void _TIE_xt_core_WSR_MISC0(unsigned t); -extern void _TIE_xt_core_XSR_MISC0(unsigned t /*inout*/); -extern unsigned _TIE_xt_core_RSR_MISC1(void); -extern void _TIE_xt_core_WSR_MISC1(unsigned t); -extern void _TIE_xt_core_XSR_MISC1(unsigned t /*inout*/); -extern unsigned _TIE_xt_core_RSR_MISC2(void); -extern void _TIE_xt_core_WSR_MISC2(unsigned t); -extern void _TIE_xt_core_XSR_MISC2(unsigned t /*inout*/); -extern unsigned _TIE_xt_core_RSR_MISC3(void); -extern void _TIE_xt_core_WSR_MISC3(unsigned t); -extern void _TIE_xt_core_XSR_MISC3(unsigned t /*inout*/); -extern int _TIE_xt_core_RSR_PRID(void); -#define XT_ILL _TIE_xt_core_ILL -#define XT_NOP _TIE_xt_core_NOP -#define XT_SIMCALL _TIE_xt_core_SIMCALL -#define XT_MEMW _TIE_xt_core_MEMW -#define XT_EXTW _TIE_xt_core_EXTW -#define XT_ISYNC _TIE_xt_core_ISYNC -#define XT_DSYNC _TIE_xt_core_DSYNC -#define XT_ESYNC _TIE_xt_core_ESYNC -#define XT_RSYNC _TIE_xt_core_RSYNC -#define XT_RSR_LBEG _TIE_xt_core_RSR_LBEG -#define XT_WSR_LBEG _TIE_xt_core_WSR_LBEG -#define XT_XSR_LBEG _TIE_xt_core_XSR_LBEG -#define XT_RSR_CONFIGID0 _TIE_xt_core_RSR_CONFIGID0 -#define XT_WSR_CONFIGID0 _TIE_xt_core_WSR_CONFIGID0 -#define XT_RSR_CONFIGID1 _TIE_xt_core_RSR_CONFIGID1 -#define XT_RUR_THREADPTR _TIE_xt_core_RUR_THREADPTR -#define RTHREADPTR _TIE_xt_core_RUR_THREADPTR -#define RUR231 _TIE_xt_core_RUR_THREADPTR -#define XT_WUR_THREADPTR _TIE_xt_core_WUR_THREADPTR -#define WTHREADPTR _TIE_xt_core_WUR_THREADPTR -#define WUR231 _TIE_xt_core_WUR_THREADPTR -#define XT_uint32_loadi _TIE_xt_core_uint32_loadi -#define XT_uint32_storei _TIE_xt_core_uint32_storei -#define XT_uint32_move _TIE_xt_core_uint32_move -#define XT_ADDI _TIE_xt_core_ADDI -#define XT_OR _TIE_xt_core_OR -#define XT_L32I _TIE_xt_core_L32I -#define XT_S32I _TIE_xt_core_S32I -#define XT_S32NB _TIE_xt_core_S32NB -#define XT_L8UI _TIE_xt_core_L8UI -#define XT_S8I _TIE_xt_core_S8I -#define XT_L16UI _TIE_xt_core_L16UI -#define XT_L16SI _TIE_xt_core_L16SI -#define XT_S16I _TIE_xt_core_S16I -#define XT_ADDMI _TIE_xt_core_ADDMI -#define XT_ADD _TIE_xt_core_ADD -#define XT_ADDX2 _TIE_xt_core_ADDX2 -#define XT_ADDX4 _TIE_xt_core_ADDX4 -#define XT_ADDX8 _TIE_xt_core_ADDX8 -#define XT_SUB _TIE_xt_core_SUB -#define XT_SUBX2 _TIE_xt_core_SUBX2 -#define XT_SUBX4 _TIE_xt_core_SUBX4 -#define XT_SUBX8 _TIE_xt_core_SUBX8 -#define XT_AND _TIE_xt_core_AND -#define XT_XOR _TIE_xt_core_XOR -#define XT_EXTUI _TIE_xt_core_EXTUI -#define XT_MOVI _TIE_xt_core_MOVI -#define XT_MOVEQZ _TIE_xt_core_MOVEQZ -#define XT_MOVNEZ _TIE_xt_core_MOVNEZ -#define XT_MOVLTZ _TIE_xt_core_MOVLTZ -#define XT_MOVGEZ _TIE_xt_core_MOVGEZ -#define XT_NEG _TIE_xt_core_NEG -#define XT_ABS _TIE_xt_core_ABS -#define XT_SSR _TIE_xt_core_SSR -#define XT_SSL _TIE_xt_core_SSL -#define XT_SSA8L _TIE_xt_core_SSA8L -#define XT_SSA8B _TIE_xt_core_SSA8B -#define XT_SSAI _TIE_xt_core_SSAI -#define XT_SLL _TIE_xt_core_SLL -#define XT_SRC _TIE_xt_core_SRC -#define XT_SRL _TIE_xt_core_SRL -#define XT_SRA _TIE_xt_core_SRA -#define XT_SLLI _TIE_xt_core_SLLI -#define XT_SRAI _TIE_xt_core_SRAI -#define XT_SRLI _TIE_xt_core_SRLI -#define XT_SSAI_SRC _TIE_xt_core_SSAI_SRC -#define XT_SSR_SRC _TIE_xt_core_SSR_SRC -#define XT_WSR_SAR_SRC _TIE_xt_core_WSR_SAR_SRC -#define XT_SSR_SRA _TIE_xt_core_SSR_SRA -#define XT_SSR_SRL _TIE_xt_core_SSR_SRL -#define XT_SSL_SLL _TIE_xt_core_SSL_SLL -#define XT_RSIL _TIE_xt_core_RSIL -#define XT_RSR_LEND _TIE_xt_core_RSR_LEND -#define XT_WSR_LEND _TIE_xt_core_WSR_LEND -#define XT_XSR_LEND _TIE_xt_core_XSR_LEND -#define XT_RSR_LCOUNT _TIE_xt_core_RSR_LCOUNT -#define XT_WSR_LCOUNT _TIE_xt_core_WSR_LCOUNT -#define XT_XSR_LCOUNT _TIE_xt_core_XSR_LCOUNT -#define XT_RSR_SAR _TIE_xt_core_RSR_SAR -#define XT_WSR_SAR _TIE_xt_core_WSR_SAR -#define XT_XSR_SAR _TIE_xt_core_XSR_SAR -#define XT_RSR_MEMCTL _TIE_xt_core_RSR_MEMCTL -#define XT_WSR_MEMCTL _TIE_xt_core_WSR_MEMCTL -#define XT_XSR_MEMCTL _TIE_xt_core_XSR_MEMCTL -#define XT_RSR_LITBASE _TIE_xt_core_RSR_LITBASE -#define XT_WSR_LITBASE _TIE_xt_core_WSR_LITBASE -#define XT_XSR_LITBASE _TIE_xt_core_XSR_LITBASE -#define XT_RSR_PS _TIE_xt_core_RSR_PS -#define XT_WSR_PS _TIE_xt_core_WSR_PS -#define XT_XSR_PS _TIE_xt_core_XSR_PS -#define XT_RSR_EPC1 _TIE_xt_core_RSR_EPC1 -#define XT_WSR_EPC1 _TIE_xt_core_WSR_EPC1 -#define XT_XSR_EPC1 _TIE_xt_core_XSR_EPC1 -#define XT_RSR_EXCSAVE1 _TIE_xt_core_RSR_EXCSAVE1 -#define XT_WSR_EXCSAVE1 _TIE_xt_core_WSR_EXCSAVE1 -#define XT_XSR_EXCSAVE1 _TIE_xt_core_XSR_EXCSAVE1 -#define XT_RSR_EPC2 _TIE_xt_core_RSR_EPC2 -#define XT_WSR_EPC2 _TIE_xt_core_WSR_EPC2 -#define XT_XSR_EPC2 _TIE_xt_core_XSR_EPC2 -#define XT_RSR_EXCSAVE2 _TIE_xt_core_RSR_EXCSAVE2 -#define XT_WSR_EXCSAVE2 _TIE_xt_core_WSR_EXCSAVE2 -#define XT_XSR_EXCSAVE2 _TIE_xt_core_XSR_EXCSAVE2 -#define XT_RSR_EPC3 _TIE_xt_core_RSR_EPC3 -#define XT_WSR_EPC3 _TIE_xt_core_WSR_EPC3 -#define XT_XSR_EPC3 _TIE_xt_core_XSR_EPC3 -#define XT_RSR_EXCSAVE3 _TIE_xt_core_RSR_EXCSAVE3 -#define XT_WSR_EXCSAVE3 _TIE_xt_core_WSR_EXCSAVE3 -#define XT_XSR_EXCSAVE3 _TIE_xt_core_XSR_EXCSAVE3 -#define XT_RSR_EPC4 _TIE_xt_core_RSR_EPC4 -#define XT_WSR_EPC4 _TIE_xt_core_WSR_EPC4 -#define XT_XSR_EPC4 _TIE_xt_core_XSR_EPC4 -#define XT_RSR_EXCSAVE4 _TIE_xt_core_RSR_EXCSAVE4 -#define XT_WSR_EXCSAVE4 _TIE_xt_core_WSR_EXCSAVE4 -#define XT_XSR_EXCSAVE4 _TIE_xt_core_XSR_EXCSAVE4 -#define XT_RSR_EPC5 _TIE_xt_core_RSR_EPC5 -#define XT_WSR_EPC5 _TIE_xt_core_WSR_EPC5 -#define XT_XSR_EPC5 _TIE_xt_core_XSR_EPC5 -#define XT_RSR_EXCSAVE5 _TIE_xt_core_RSR_EXCSAVE5 -#define XT_WSR_EXCSAVE5 _TIE_xt_core_WSR_EXCSAVE5 -#define XT_XSR_EXCSAVE5 _TIE_xt_core_XSR_EXCSAVE5 -#define XT_RSR_EPC6 _TIE_xt_core_RSR_EPC6 -#define XT_WSR_EPC6 _TIE_xt_core_WSR_EPC6 -#define XT_XSR_EPC6 _TIE_xt_core_XSR_EPC6 -#define XT_RSR_EXCSAVE6 _TIE_xt_core_RSR_EXCSAVE6 -#define XT_WSR_EXCSAVE6 _TIE_xt_core_WSR_EXCSAVE6 -#define XT_XSR_EXCSAVE6 _TIE_xt_core_XSR_EXCSAVE6 -#define XT_RSR_EPC7 _TIE_xt_core_RSR_EPC7 -#define XT_WSR_EPC7 _TIE_xt_core_WSR_EPC7 -#define XT_XSR_EPC7 _TIE_xt_core_XSR_EPC7 -#define XT_RSR_EXCSAVE7 _TIE_xt_core_RSR_EXCSAVE7 -#define XT_WSR_EXCSAVE7 _TIE_xt_core_WSR_EXCSAVE7 -#define XT_XSR_EXCSAVE7 _TIE_xt_core_XSR_EXCSAVE7 -#define XT_RSR_VECBASE _TIE_xt_core_RSR_VECBASE -#define XT_WSR_VECBASE _TIE_xt_core_WSR_VECBASE -#define XT_XSR_VECBASE _TIE_xt_core_XSR_VECBASE -#define XT_RSR_EPS2 _TIE_xt_core_RSR_EPS2 -#define XT_WSR_EPS2 _TIE_xt_core_WSR_EPS2 -#define XT_XSR_EPS2 _TIE_xt_core_XSR_EPS2 -#define XT_RSR_EPS3 _TIE_xt_core_RSR_EPS3 -#define XT_WSR_EPS3 _TIE_xt_core_WSR_EPS3 -#define XT_XSR_EPS3 _TIE_xt_core_XSR_EPS3 -#define XT_RSR_EPS4 _TIE_xt_core_RSR_EPS4 -#define XT_WSR_EPS4 _TIE_xt_core_WSR_EPS4 -#define XT_XSR_EPS4 _TIE_xt_core_XSR_EPS4 -#define XT_RSR_EPS5 _TIE_xt_core_RSR_EPS5 -#define XT_WSR_EPS5 _TIE_xt_core_WSR_EPS5 -#define XT_XSR_EPS5 _TIE_xt_core_XSR_EPS5 -#define XT_RSR_EPS6 _TIE_xt_core_RSR_EPS6 -#define XT_WSR_EPS6 _TIE_xt_core_WSR_EPS6 -#define XT_XSR_EPS6 _TIE_xt_core_XSR_EPS6 -#define XT_RSR_EPS7 _TIE_xt_core_RSR_EPS7 -#define XT_WSR_EPS7 _TIE_xt_core_WSR_EPS7 -#define XT_XSR_EPS7 _TIE_xt_core_XSR_EPS7 -#define XT_RSR_EXCCAUSE _TIE_xt_core_RSR_EXCCAUSE -#define XT_WSR_EXCCAUSE _TIE_xt_core_WSR_EXCCAUSE -#define XT_XSR_EXCCAUSE _TIE_xt_core_XSR_EXCCAUSE -#define XT_RSR_EXCVADDR _TIE_xt_core_RSR_EXCVADDR -#define XT_WSR_EXCVADDR _TIE_xt_core_WSR_EXCVADDR -#define XT_XSR_EXCVADDR _TIE_xt_core_XSR_EXCVADDR -#define XT_RSR_DEPC _TIE_xt_core_RSR_DEPC -#define XT_WSR_DEPC _TIE_xt_core_WSR_DEPC -#define XT_XSR_DEPC _TIE_xt_core_XSR_DEPC -#define XT_RSR_MISC0 _TIE_xt_core_RSR_MISC0 -#define XT_WSR_MISC0 _TIE_xt_core_WSR_MISC0 -#define XT_XSR_MISC0 _TIE_xt_core_XSR_MISC0 -#define XT_RSR_MISC1 _TIE_xt_core_RSR_MISC1 -#define XT_WSR_MISC1 _TIE_xt_core_WSR_MISC1 -#define XT_XSR_MISC1 _TIE_xt_core_XSR_MISC1 -#define XT_RSR_MISC2 _TIE_xt_core_RSR_MISC2 -#define XT_WSR_MISC2 _TIE_xt_core_WSR_MISC2 -#define XT_XSR_MISC2 _TIE_xt_core_XSR_MISC2 -#define XT_RSR_MISC3 _TIE_xt_core_RSR_MISC3 -#define XT_WSR_MISC3 _TIE_xt_core_WSR_MISC3 -#define XT_XSR_MISC3 _TIE_xt_core_XSR_MISC3 -#define XT_RSR_PRID _TIE_xt_core_RSR_PRID - -#ifndef RUR -#define RUR(NUM) RUR##NUM() -#endif - -#ifndef WUR -#define WUR(VAL, NUM) WUR##NUM(VAL) -#endif - -#endif /* __XCC__ */ - -#endif /* __XTENSA__ */ - -#endif /* !_XTENSA_xt_core_HEADER */ diff --git a/components/esp32/include/xtensa/tie/xt_debug.h b/components/esp32/include/xtensa/tie/xt_debug.h deleted file mode 100644 index 676fd33c78..0000000000 --- a/components/esp32/include/xtensa/tie/xt_debug.h +++ /dev/null @@ -1,116 +0,0 @@ -/* Definitions for the xt_debug TIE package */ - -/* - * Customer ID=11657; Build=0x5fe96; Copyright (c) 2004-2010 by Tensilica Inc. ALL RIGHTS RESERVED. - * These coded instructions, statements, and computer programs are the - * copyrighted works and confidential proprietary information of Tensilica Inc. - * They may not be modified, copied, reproduced, distributed, or disclosed to - * third parties in any manner, medium, or form, in whole or in part, without - * the prior written consent of Tensilica Inc. - */ - -/* Do not modify. This is automatically generated.*/ - -#ifndef _XTENSA_xt_debug_HEADER -#define _XTENSA_xt_debug_HEADER - -#ifdef __XTENSA__ -#ifdef __XCC__ - -#include - -/* - * The following prototypes describe intrinsic functions - * corresponding to TIE instructions. Some TIE instructions - * may produce multiple results (designated as "out" operands - * in the iclass section) or may have operands used as both - * inputs and outputs (designated as "inout"). However, the C - * and C++ languages do not provide syntax that can express - * the in/out/inout constraints of TIE intrinsics. - * Nevertheless, the compiler understands these constraints - * and will check that the intrinsic functions are used - * correctly. To improve the readability of these prototypes, - * the "out" and "inout" parameters are marked accordingly - * with comments. - */ - -extern void _TIE_xt_debug_BREAK(immediate imms, immediate immt); -extern void _TIE_xt_debug_BREAK_N(immediate imms); -extern unsigned _TIE_xt_debug_RSR_DBREAKA0(void); -extern void _TIE_xt_debug_WSR_DBREAKA0(unsigned art); -extern void _TIE_xt_debug_XSR_DBREAKA0(unsigned art /*inout*/); -extern unsigned _TIE_xt_debug_RSR_DBREAKC0(void); -extern void _TIE_xt_debug_WSR_DBREAKC0(unsigned art); -extern void _TIE_xt_debug_XSR_DBREAKC0(unsigned art /*inout*/); -extern unsigned _TIE_xt_debug_RSR_DBREAKA1(void); -extern void _TIE_xt_debug_WSR_DBREAKA1(unsigned art); -extern void _TIE_xt_debug_XSR_DBREAKA1(unsigned art /*inout*/); -extern unsigned _TIE_xt_debug_RSR_DBREAKC1(void); -extern void _TIE_xt_debug_WSR_DBREAKC1(unsigned art); -extern void _TIE_xt_debug_XSR_DBREAKC1(unsigned art /*inout*/); -extern unsigned _TIE_xt_debug_RSR_IBREAKA0(void); -extern void _TIE_xt_debug_WSR_IBREAKA0(unsigned art); -extern void _TIE_xt_debug_XSR_IBREAKA0(unsigned art /*inout*/); -extern unsigned _TIE_xt_debug_RSR_IBREAKA1(void); -extern void _TIE_xt_debug_WSR_IBREAKA1(unsigned art); -extern void _TIE_xt_debug_XSR_IBREAKA1(unsigned art /*inout*/); -extern unsigned _TIE_xt_debug_RSR_IBREAKENABLE(void); -extern void _TIE_xt_debug_WSR_IBREAKENABLE(unsigned art); -extern void _TIE_xt_debug_XSR_IBREAKENABLE(unsigned art /*inout*/); -extern unsigned _TIE_xt_debug_RSR_DEBUGCAUSE(void); -extern void _TIE_xt_debug_WSR_DEBUGCAUSE(unsigned art); -extern void _TIE_xt_debug_XSR_DEBUGCAUSE(unsigned art /*inout*/); -extern unsigned _TIE_xt_debug_RSR_ICOUNT(void); -extern void _TIE_xt_debug_WSR_ICOUNT(unsigned art); -extern void _TIE_xt_debug_XSR_ICOUNT(unsigned art /*inout*/); -extern unsigned _TIE_xt_debug_RSR_ICOUNTLEVEL(void); -extern void _TIE_xt_debug_WSR_ICOUNTLEVEL(unsigned art); -extern void _TIE_xt_debug_XSR_ICOUNTLEVEL(unsigned art /*inout*/); -extern unsigned _TIE_xt_debug_RSR_DDR(void); -extern void _TIE_xt_debug_WSR_DDR(unsigned art); -extern void _TIE_xt_debug_XSR_DDR(unsigned art /*inout*/); -extern void _TIE_xt_debug_LDDR32_P(const void * ars /*inout*/); -extern void _TIE_xt_debug_SDDR32_P(void * ars /*inout*/); -#define XT_BREAK _TIE_xt_debug_BREAK -#define XT_BREAK_N _TIE_xt_debug_BREAK_N -#define XT_RSR_DBREAKA0 _TIE_xt_debug_RSR_DBREAKA0 -#define XT_WSR_DBREAKA0 _TIE_xt_debug_WSR_DBREAKA0 -#define XT_XSR_DBREAKA0 _TIE_xt_debug_XSR_DBREAKA0 -#define XT_RSR_DBREAKC0 _TIE_xt_debug_RSR_DBREAKC0 -#define XT_WSR_DBREAKC0 _TIE_xt_debug_WSR_DBREAKC0 -#define XT_XSR_DBREAKC0 _TIE_xt_debug_XSR_DBREAKC0 -#define XT_RSR_DBREAKA1 _TIE_xt_debug_RSR_DBREAKA1 -#define XT_WSR_DBREAKA1 _TIE_xt_debug_WSR_DBREAKA1 -#define XT_XSR_DBREAKA1 _TIE_xt_debug_XSR_DBREAKA1 -#define XT_RSR_DBREAKC1 _TIE_xt_debug_RSR_DBREAKC1 -#define XT_WSR_DBREAKC1 _TIE_xt_debug_WSR_DBREAKC1 -#define XT_XSR_DBREAKC1 _TIE_xt_debug_XSR_DBREAKC1 -#define XT_RSR_IBREAKA0 _TIE_xt_debug_RSR_IBREAKA0 -#define XT_WSR_IBREAKA0 _TIE_xt_debug_WSR_IBREAKA0 -#define XT_XSR_IBREAKA0 _TIE_xt_debug_XSR_IBREAKA0 -#define XT_RSR_IBREAKA1 _TIE_xt_debug_RSR_IBREAKA1 -#define XT_WSR_IBREAKA1 _TIE_xt_debug_WSR_IBREAKA1 -#define XT_XSR_IBREAKA1 _TIE_xt_debug_XSR_IBREAKA1 -#define XT_RSR_IBREAKENABLE _TIE_xt_debug_RSR_IBREAKENABLE -#define XT_WSR_IBREAKENABLE _TIE_xt_debug_WSR_IBREAKENABLE -#define XT_XSR_IBREAKENABLE _TIE_xt_debug_XSR_IBREAKENABLE -#define XT_RSR_DEBUGCAUSE _TIE_xt_debug_RSR_DEBUGCAUSE -#define XT_WSR_DEBUGCAUSE _TIE_xt_debug_WSR_DEBUGCAUSE -#define XT_XSR_DEBUGCAUSE _TIE_xt_debug_XSR_DEBUGCAUSE -#define XT_RSR_ICOUNT _TIE_xt_debug_RSR_ICOUNT -#define XT_WSR_ICOUNT _TIE_xt_debug_WSR_ICOUNT -#define XT_XSR_ICOUNT _TIE_xt_debug_XSR_ICOUNT -#define XT_RSR_ICOUNTLEVEL _TIE_xt_debug_RSR_ICOUNTLEVEL -#define XT_WSR_ICOUNTLEVEL _TIE_xt_debug_WSR_ICOUNTLEVEL -#define XT_XSR_ICOUNTLEVEL _TIE_xt_debug_XSR_ICOUNTLEVEL -#define XT_RSR_DDR _TIE_xt_debug_RSR_DDR -#define XT_WSR_DDR _TIE_xt_debug_WSR_DDR -#define XT_XSR_DDR _TIE_xt_debug_XSR_DDR -#define XT_LDDR32_P _TIE_xt_debug_LDDR32_P -#define XT_SDDR32_P _TIE_xt_debug_SDDR32_P - -#endif /* __XCC__ */ - -#endif /* __XTENSA__ */ - -#endif /* !_XTENSA_xt_debug_HEADER */ diff --git a/components/esp32/include/xtensa/tie/xt_density.h b/components/esp32/include/xtensa/tie/xt_density.h deleted file mode 100644 index da5c51ccf0..0000000000 --- a/components/esp32/include/xtensa/tie/xt_density.h +++ /dev/null @@ -1,58 +0,0 @@ -/* Definitions for the xt_density TIE package */ - -/* - * Customer ID=11657; Build=0x5fe96; Copyright (c) 2004-2010 by Tensilica Inc. ALL RIGHTS RESERVED. - * These coded instructions, statements, and computer programs are the - * copyrighted works and confidential proprietary information of Tensilica Inc. - * They may not be modified, copied, reproduced, distributed, or disclosed to - * third parties in any manner, medium, or form, in whole or in part, without - * the prior written consent of Tensilica Inc. - */ - -/* Do not modify. This is automatically generated.*/ - -#ifndef _XTENSA_xt_density_HEADER -#define _XTENSA_xt_density_HEADER - -#ifdef __XTENSA__ -#ifdef __XCC__ - -#include - -/* - * The following prototypes describe intrinsic functions - * corresponding to TIE instructions. Some TIE instructions - * may produce multiple results (designated as "out" operands - * in the iclass section) or may have operands used as both - * inputs and outputs (designated as "inout"). However, the C - * and C++ languages do not provide syntax that can express - * the in/out/inout constraints of TIE intrinsics. - * Nevertheless, the compiler understands these constraints - * and will check that the intrinsic functions are used - * correctly. To improve the readability of these prototypes, - * the "out" and "inout" parameters are marked accordingly - * with comments. - */ - -extern void _TIE_xt_density_ILL_N(void); -extern void _TIE_xt_density_NOP_N(void); -extern int _TIE_xt_density_L32I_N(const int * p, immediate i); -extern void _TIE_xt_density_S32I_N(int t, int * p, immediate i); -extern int _TIE_xt_density_ADD_N(int s, int t); -extern int _TIE_xt_density_ADDI_N(int s, immediate i); -extern int _TIE_xt_density_MOV_N(int s); -extern int _TIE_xt_density_MOVI_N(immediate i); -#define XT_ILL_N _TIE_xt_density_ILL_N -#define XT_NOP_N _TIE_xt_density_NOP_N -#define XT_L32I_N _TIE_xt_density_L32I_N -#define XT_S32I_N _TIE_xt_density_S32I_N -#define XT_ADD_N _TIE_xt_density_ADD_N -#define XT_ADDI_N _TIE_xt_density_ADDI_N -#define XT_MOV_N _TIE_xt_density_MOV_N -#define XT_MOVI_N _TIE_xt_density_MOVI_N - -#endif /* __XCC__ */ - -#endif /* __XTENSA__ */ - -#endif /* !_XTENSA_xt_density_HEADER */ diff --git a/components/esp32/include/xtensa/tie/xt_exceptions.h b/components/esp32/include/xtensa/tie/xt_exceptions.h deleted file mode 100644 index 64fb393079..0000000000 --- a/components/esp32/include/xtensa/tie/xt_exceptions.h +++ /dev/null @@ -1,45 +0,0 @@ -/* Definitions for the xt_exceptions TIE package */ - -/* - * Customer ID=11657; Build=0x5fe96; Copyright (c) 2004-2010 by Tensilica Inc. ALL RIGHTS RESERVED. - * These coded instructions, statements, and computer programs are the - * copyrighted works and confidential proprietary information of Tensilica Inc. - * They may not be modified, copied, reproduced, distributed, or disclosed to - * third parties in any manner, medium, or form, in whole or in part, without - * the prior written consent of Tensilica Inc. - */ - -/* Do not modify. This is automatically generated.*/ - -#ifndef _XTENSA_xt_exceptions_HEADER -#define _XTENSA_xt_exceptions_HEADER - -#ifdef __XTENSA__ -#ifdef __XCC__ - - -/* - * The following prototypes describe intrinsic functions - * corresponding to TIE instructions. Some TIE instructions - * may produce multiple results (designated as "out" operands - * in the iclass section) or may have operands used as both - * inputs and outputs (designated as "inout"). However, the C - * and C++ languages do not provide syntax that can express - * the in/out/inout constraints of TIE intrinsics. - * Nevertheless, the compiler understands these constraints - * and will check that the intrinsic functions are used - * correctly. To improve the readability of these prototypes, - * the "out" and "inout" parameters are marked accordingly - * with comments. - */ - -extern void _TIE_xt_exceptions_EXCW(void); -extern void _TIE_xt_exceptions_SYSCALL(void); -#define XT_EXCW _TIE_xt_exceptions_EXCW -#define XT_SYSCALL _TIE_xt_exceptions_SYSCALL - -#endif /* __XCC__ */ - -#endif /* __XTENSA__ */ - -#endif /* !_XTENSA_xt_exceptions_HEADER */ diff --git a/components/esp32/include/xtensa/tie/xt_externalregisters.h b/components/esp32/include/xtensa/tie/xt_externalregisters.h deleted file mode 100644 index 3196527c2f..0000000000 --- a/components/esp32/include/xtensa/tie/xt_externalregisters.h +++ /dev/null @@ -1,46 +0,0 @@ -/* Definitions for the xt_externalregisters TIE package */ - -/* - * Customer ID=11657; Build=0x5fe96; Copyright (c) 2004-2010 by Tensilica Inc. ALL RIGHTS RESERVED. - * These coded instructions, statements, and computer programs are the - * copyrighted works and confidential proprietary information of Tensilica Inc. - * They may not be modified, copied, reproduced, distributed, or disclosed to - * third parties in any manner, medium, or form, in whole or in part, without - * the prior written consent of Tensilica Inc. - */ - -/* Do not modify. This is automatically generated.*/ - -#ifndef _XTENSA_xt_externalregisters_HEADER -#define _XTENSA_xt_externalregisters_HEADER - -#ifdef __XTENSA__ -#ifdef __XCC__ - -#include - -/* - * The following prototypes describe intrinsic functions - * corresponding to TIE instructions. Some TIE instructions - * may produce multiple results (designated as "out" operands - * in the iclass section) or may have operands used as both - * inputs and outputs (designated as "inout"). However, the C - * and C++ languages do not provide syntax that can express - * the in/out/inout constraints of TIE intrinsics. - * Nevertheless, the compiler understands these constraints - * and will check that the intrinsic functions are used - * correctly. To improve the readability of these prototypes, - * the "out" and "inout" parameters are marked accordingly - * with comments. - */ - -extern unsigned _TIE_xt_externalregisters_RER(unsigned ars); -extern void _TIE_xt_externalregisters_WER(unsigned art, unsigned ars); -#define XT_RER _TIE_xt_externalregisters_RER -#define XT_WER _TIE_xt_externalregisters_WER - -#endif /* __XCC__ */ - -#endif /* __XTENSA__ */ - -#endif /* !_XTENSA_xt_externalregisters_HEADER */ diff --git a/components/esp32/include/xtensa/tie/xt_integerdivide.h b/components/esp32/include/xtensa/tie/xt_integerdivide.h deleted file mode 100644 index 9fbe9615b7..0000000000 --- a/components/esp32/include/xtensa/tie/xt_integerdivide.h +++ /dev/null @@ -1,50 +0,0 @@ -/* Definitions for the xt_integerdivide TIE package */ - -/* - * Customer ID=11657; Build=0x5fe96; Copyright (c) 2004-2010 by Tensilica Inc. ALL RIGHTS RESERVED. - * These coded instructions, statements, and computer programs are the - * copyrighted works and confidential proprietary information of Tensilica Inc. - * They may not be modified, copied, reproduced, distributed, or disclosed to - * third parties in any manner, medium, or form, in whole or in part, without - * the prior written consent of Tensilica Inc. - */ - -/* Do not modify. This is automatically generated.*/ - -#ifndef _XTENSA_xt_integerdivide_HEADER -#define _XTENSA_xt_integerdivide_HEADER - -#ifdef __XTENSA__ -#ifdef __XCC__ - -#include - -/* - * The following prototypes describe intrinsic functions - * corresponding to TIE instructions. Some TIE instructions - * may produce multiple results (designated as "out" operands - * in the iclass section) or may have operands used as both - * inputs and outputs (designated as "inout"). However, the C - * and C++ languages do not provide syntax that can express - * the in/out/inout constraints of TIE intrinsics. - * Nevertheless, the compiler understands these constraints - * and will check that the intrinsic functions are used - * correctly. To improve the readability of these prototypes, - * the "out" and "inout" parameters are marked accordingly - * with comments. - */ - -extern unsigned _TIE_xt_integerdivide_REMS(unsigned ars, unsigned art); -extern unsigned _TIE_xt_integerdivide_REMU(unsigned ars, unsigned art); -extern unsigned _TIE_xt_integerdivide_QUOS(unsigned ars, unsigned art); -extern unsigned _TIE_xt_integerdivide_QUOU(unsigned ars, unsigned art); -#define XT_REMS _TIE_xt_integerdivide_REMS -#define XT_REMU _TIE_xt_integerdivide_REMU -#define XT_QUOS _TIE_xt_integerdivide_QUOS -#define XT_QUOU _TIE_xt_integerdivide_QUOU - -#endif /* __XCC__ */ - -#endif /* __XTENSA__ */ - -#endif /* !_XTENSA_xt_integerdivide_HEADER */ diff --git a/components/esp32/include/xtensa/tie/xt_interrupt.h b/components/esp32/include/xtensa/tie/xt_interrupt.h deleted file mode 100644 index b20c94f47a..0000000000 --- a/components/esp32/include/xtensa/tie/xt_interrupt.h +++ /dev/null @@ -1,56 +0,0 @@ -/* Definitions for the xt_interrupt TIE package */ - -/* - * Customer ID=11657; Build=0x5fe96; Copyright (c) 2004-2010 by Tensilica Inc. ALL RIGHTS RESERVED. - * These coded instructions, statements, and computer programs are the - * copyrighted works and confidential proprietary information of Tensilica Inc. - * They may not be modified, copied, reproduced, distributed, or disclosed to - * third parties in any manner, medium, or form, in whole or in part, without - * the prior written consent of Tensilica Inc. - */ - -/* Do not modify. This is automatically generated.*/ - -#ifndef _XTENSA_xt_interrupt_HEADER -#define _XTENSA_xt_interrupt_HEADER - -#ifdef __XTENSA__ -#ifdef __XCC__ - -#include - -/* - * The following prototypes describe intrinsic functions - * corresponding to TIE instructions. Some TIE instructions - * may produce multiple results (designated as "out" operands - * in the iclass section) or may have operands used as both - * inputs and outputs (designated as "inout"). However, the C - * and C++ languages do not provide syntax that can express - * the in/out/inout constraints of TIE intrinsics. - * Nevertheless, the compiler understands these constraints - * and will check that the intrinsic functions are used - * correctly. To improve the readability of these prototypes, - * the "out" and "inout" parameters are marked accordingly - * with comments. - */ - -extern void _TIE_xt_interrupt_WAITI(immediate s); -extern unsigned _TIE_xt_interrupt_RSR_INTERRUPT(void); -extern void _TIE_xt_interrupt_WSR_INTSET(unsigned art); -extern void _TIE_xt_interrupt_WSR_INTCLEAR(unsigned art); -extern unsigned _TIE_xt_interrupt_RSR_INTENABLE(void); -extern void _TIE_xt_interrupt_WSR_INTENABLE(unsigned art); -extern void _TIE_xt_interrupt_XSR_INTENABLE(unsigned art /*inout*/); -#define XT_WAITI _TIE_xt_interrupt_WAITI -#define XT_RSR_INTERRUPT _TIE_xt_interrupt_RSR_INTERRUPT -#define XT_WSR_INTSET _TIE_xt_interrupt_WSR_INTSET -#define XT_WSR_INTCLEAR _TIE_xt_interrupt_WSR_INTCLEAR -#define XT_RSR_INTENABLE _TIE_xt_interrupt_RSR_INTENABLE -#define XT_WSR_INTENABLE _TIE_xt_interrupt_WSR_INTENABLE -#define XT_XSR_INTENABLE _TIE_xt_interrupt_XSR_INTENABLE - -#endif /* __XCC__ */ - -#endif /* __XTENSA__ */ - -#endif /* !_XTENSA_xt_interrupt_HEADER */ diff --git a/components/esp32/include/xtensa/tie/xt_ioports.h b/components/esp32/include/xtensa/tie/xt_ioports.h deleted file mode 100644 index 0253bea4cf..0000000000 --- a/components/esp32/include/xtensa/tie/xt_ioports.h +++ /dev/null @@ -1,66 +0,0 @@ -/* Definitions for the xt_ioports TIE package */ - -/* - * Customer ID=11657; Build=0x5fe96; Copyright (c) 2004-2010 by Tensilica Inc. ALL RIGHTS RESERVED. - * These coded instructions, statements, and computer programs are the - * copyrighted works and confidential proprietary information of Tensilica Inc. - * They may not be modified, copied, reproduced, distributed, or disclosed to - * third parties in any manner, medium, or form, in whole or in part, without - * the prior written consent of Tensilica Inc. - */ - -/* Do not modify. This is automatically generated.*/ - -#ifndef _XTENSA_xt_ioports_HEADER -#define _XTENSA_xt_ioports_HEADER - -#ifdef __XTENSA__ -#ifdef __XCC__ - -#include - -/* - * The following prototypes describe intrinsic functions - * corresponding to TIE instructions. Some TIE instructions - * may produce multiple results (designated as "out" operands - * in the iclass section) or may have operands used as both - * inputs and outputs (designated as "inout"). However, the C - * and C++ languages do not provide syntax that can express - * the in/out/inout constraints of TIE intrinsics. - * Nevertheless, the compiler understands these constraints - * and will check that the intrinsic functions are used - * correctly. To improve the readability of these prototypes, - * the "out" and "inout" parameters are marked accordingly - * with comments. - */ - -extern unsigned _TIE_xt_ioports_READ_IMPWIRE(void); -extern void _TIE_xt_ioports_SETB_EXPSTATE(immediate bitindex); -extern void _TIE_xt_ioports_CLRB_EXPSTATE(immediate bitindex); -extern void _TIE_xt_ioports_WRMSK_EXPSTATE(unsigned art, unsigned ars); -extern unsigned _TIE_xt_ioports_RUR_EXPSTATE(void); -extern void _TIE_xt_ioports_WUR_EXPSTATE(unsigned v); -#define READ_IMPWIRE _TIE_xt_ioports_READ_IMPWIRE -#define SETB_EXPSTATE _TIE_xt_ioports_SETB_EXPSTATE -#define CLRB_EXPSTATE _TIE_xt_ioports_CLRB_EXPSTATE -#define WRMSK_EXPSTATE _TIE_xt_ioports_WRMSK_EXPSTATE -#define RUR_EXPSTATE _TIE_xt_ioports_RUR_EXPSTATE -#define REXPSTATE _TIE_xt_ioports_RUR_EXPSTATE -#define RUR230 _TIE_xt_ioports_RUR_EXPSTATE -#define WUR_EXPSTATE _TIE_xt_ioports_WUR_EXPSTATE -#define WEXPSTATE _TIE_xt_ioports_WUR_EXPSTATE -#define WUR230 _TIE_xt_ioports_WUR_EXPSTATE - -#ifndef RUR -#define RUR(NUM) RUR##NUM() -#endif - -#ifndef WUR -#define WUR(VAL, NUM) WUR##NUM(VAL) -#endif - -#endif /* __XCC__ */ - -#endif /* __XTENSA__ */ - -#endif /* !_XTENSA_xt_ioports_HEADER */ diff --git a/components/esp32/include/xtensa/tie/xt_misc.h b/components/esp32/include/xtensa/tie/xt_misc.h deleted file mode 100644 index a0b36f4e5d..0000000000 --- a/components/esp32/include/xtensa/tie/xt_misc.h +++ /dev/null @@ -1,58 +0,0 @@ -/* Definitions for the xt_misc TIE package */ - -/* - * Customer ID=11657; Build=0x5fe96; Copyright (c) 2004-2010 by Tensilica Inc. ALL RIGHTS RESERVED. - * These coded instructions, statements, and computer programs are the - * copyrighted works and confidential proprietary information of Tensilica Inc. - * They may not be modified, copied, reproduced, distributed, or disclosed to - * third parties in any manner, medium, or form, in whole or in part, without - * the prior written consent of Tensilica Inc. - */ - -/* Do not modify. This is automatically generated.*/ - -#ifndef _XTENSA_xt_misc_HEADER -#define _XTENSA_xt_misc_HEADER - -#ifdef __XTENSA__ -#ifdef __XCC__ - -#include - -/* - * The following prototypes describe intrinsic functions - * corresponding to TIE instructions. Some TIE instructions - * may produce multiple results (designated as "out" operands - * in the iclass section) or may have operands used as both - * inputs and outputs (designated as "inout"). However, the C - * and C++ languages do not provide syntax that can express - * the in/out/inout constraints of TIE intrinsics. - * Nevertheless, the compiler understands these constraints - * and will check that the intrinsic functions are used - * correctly. To improve the readability of these prototypes, - * the "out" and "inout" parameters are marked accordingly - * with comments. - */ - -extern int _TIE_xt_misc_CLAMPS(int s, immediate i); -extern int _TIE_xt_misc_MIN(int s, int t); -extern int _TIE_xt_misc_MAX(int s, int t); -extern unsigned _TIE_xt_misc_MINU(unsigned s, unsigned t); -extern unsigned _TIE_xt_misc_MAXU(unsigned s, unsigned t); -extern int _TIE_xt_misc_NSA(int s); -extern unsigned _TIE_xt_misc_NSAU(unsigned s); -extern int _TIE_xt_misc_SEXT(int s, immediate i); -#define XT_CLAMPS _TIE_xt_misc_CLAMPS -#define XT_MIN _TIE_xt_misc_MIN -#define XT_MAX _TIE_xt_misc_MAX -#define XT_MINU _TIE_xt_misc_MINU -#define XT_MAXU _TIE_xt_misc_MAXU -#define XT_NSA _TIE_xt_misc_NSA -#define XT_NSAU _TIE_xt_misc_NSAU -#define XT_SEXT _TIE_xt_misc_SEXT - -#endif /* __XCC__ */ - -#endif /* __XTENSA__ */ - -#endif /* !_XTENSA_xt_misc_HEADER */ diff --git a/components/esp32/include/xtensa/tie/xt_mmu.h b/components/esp32/include/xtensa/tie/xt_mmu.h deleted file mode 100644 index ce786c0fea..0000000000 --- a/components/esp32/include/xtensa/tie/xt_mmu.h +++ /dev/null @@ -1,62 +0,0 @@ -/* Definitions for the xt_mmu TIE package */ - -/* - * Customer ID=11657; Build=0x5fe96; Copyright (c) 2004-2010 by Tensilica Inc. ALL RIGHTS RESERVED. - * These coded instructions, statements, and computer programs are the - * copyrighted works and confidential proprietary information of Tensilica Inc. - * They may not be modified, copied, reproduced, distributed, or disclosed to - * third parties in any manner, medium, or form, in whole or in part, without - * the prior written consent of Tensilica Inc. - */ - -/* Do not modify. This is automatically generated.*/ - -#ifndef _XTENSA_xt_mmu_HEADER -#define _XTENSA_xt_mmu_HEADER - -#ifdef __XTENSA__ -#ifdef __XCC__ - -#include - -/* - * The following prototypes describe intrinsic functions - * corresponding to TIE instructions. Some TIE instructions - * may produce multiple results (designated as "out" operands - * in the iclass section) or may have operands used as both - * inputs and outputs (designated as "inout"). However, the C - * and C++ languages do not provide syntax that can express - * the in/out/inout constraints of TIE intrinsics. - * Nevertheless, the compiler understands these constraints - * and will check that the intrinsic functions are used - * correctly. To improve the readability of these prototypes, - * the "out" and "inout" parameters are marked accordingly - * with comments. - */ - -extern void _TIE_xt_mmu_IDTLB(unsigned ars); -extern unsigned _TIE_xt_mmu_RDTLB1(unsigned ars); -extern unsigned _TIE_xt_mmu_RDTLB0(unsigned ars); -extern unsigned _TIE_xt_mmu_PDTLB(unsigned ars); -extern void _TIE_xt_mmu_WDTLB(unsigned art, unsigned ars); -extern void _TIE_xt_mmu_IITLB(unsigned ars); -extern unsigned _TIE_xt_mmu_RITLB1(unsigned ars); -extern unsigned _TIE_xt_mmu_RITLB0(unsigned ars); -extern unsigned _TIE_xt_mmu_PITLB(unsigned ars); -extern void _TIE_xt_mmu_WITLB(unsigned art, unsigned ars); -#define XT_IDTLB _TIE_xt_mmu_IDTLB -#define XT_RDTLB1 _TIE_xt_mmu_RDTLB1 -#define XT_RDTLB0 _TIE_xt_mmu_RDTLB0 -#define XT_PDTLB _TIE_xt_mmu_PDTLB -#define XT_WDTLB _TIE_xt_mmu_WDTLB -#define XT_IITLB _TIE_xt_mmu_IITLB -#define XT_RITLB1 _TIE_xt_mmu_RITLB1 -#define XT_RITLB0 _TIE_xt_mmu_RITLB0 -#define XT_PITLB _TIE_xt_mmu_PITLB -#define XT_WITLB _TIE_xt_mmu_WITLB - -#endif /* __XCC__ */ - -#endif /* __XTENSA__ */ - -#endif /* !_XTENSA_xt_mmu_HEADER */ diff --git a/components/esp32/include/xtensa/tie/xt_mul.h b/components/esp32/include/xtensa/tie/xt_mul.h deleted file mode 100644 index e20862069d..0000000000 --- a/components/esp32/include/xtensa/tie/xt_mul.h +++ /dev/null @@ -1,52 +0,0 @@ -/* Definitions for the xt_mul TIE package */ - -/* - * Customer ID=11657; Build=0x5fe96; Copyright (c) 2004-2010 by Tensilica Inc. ALL RIGHTS RESERVED. - * These coded instructions, statements, and computer programs are the - * copyrighted works and confidential proprietary information of Tensilica Inc. - * They may not be modified, copied, reproduced, distributed, or disclosed to - * third parties in any manner, medium, or form, in whole or in part, without - * the prior written consent of Tensilica Inc. - */ - -/* Do not modify. This is automatically generated.*/ - -#ifndef _XTENSA_xt_mul_HEADER -#define _XTENSA_xt_mul_HEADER - -#ifdef __XTENSA__ -#ifdef __XCC__ - -#include - -/* - * The following prototypes describe intrinsic functions - * corresponding to TIE instructions. Some TIE instructions - * may produce multiple results (designated as "out" operands - * in the iclass section) or may have operands used as both - * inputs and outputs (designated as "inout"). However, the C - * and C++ languages do not provide syntax that can express - * the in/out/inout constraints of TIE intrinsics. - * Nevertheless, the compiler understands these constraints - * and will check that the intrinsic functions are used - * correctly. To improve the readability of these prototypes, - * the "out" and "inout" parameters are marked accordingly - * with comments. - */ - -extern int _TIE_xt_mul_MUL16S(short s, short t); -extern unsigned _TIE_xt_mul_MUL16U(unsigned short s, unsigned short t); -extern int _TIE_xt_mul_MULL(int s, int t); -extern unsigned _TIE_xt_mul_MULUH(unsigned s, unsigned t); -extern int _TIE_xt_mul_MULSH(int s, int t); -#define XT_MUL16S _TIE_xt_mul_MUL16S -#define XT_MUL16U _TIE_xt_mul_MUL16U -#define XT_MULL _TIE_xt_mul_MULL -#define XT_MULUH _TIE_xt_mul_MULUH -#define XT_MULSH _TIE_xt_mul_MULSH - -#endif /* __XCC__ */ - -#endif /* __XTENSA__ */ - -#endif /* !_XTENSA_xt_mul_HEADER */ diff --git a/components/esp32/include/xtensa/tie/xt_regwin.h b/components/esp32/include/xtensa/tie/xt_regwin.h deleted file mode 100644 index 7bce471a03..0000000000 --- a/components/esp32/include/xtensa/tie/xt_regwin.h +++ /dev/null @@ -1,64 +0,0 @@ -/* Definitions for the xt_regwin TIE package */ - -/* - * Customer ID=11657; Build=0x5fe96; Copyright (c) 2004-2010 by Tensilica Inc. ALL RIGHTS RESERVED. - * These coded instructions, statements, and computer programs are the - * copyrighted works and confidential proprietary information of Tensilica Inc. - * They may not be modified, copied, reproduced, distributed, or disclosed to - * third parties in any manner, medium, or form, in whole or in part, without - * the prior written consent of Tensilica Inc. - */ - -/* Do not modify. This is automatically generated.*/ - -#ifndef _XTENSA_xt_regwin_HEADER -#define _XTENSA_xt_regwin_HEADER - -#ifdef __XTENSA__ -#ifdef __XCC__ - -#include - -/* - * The following prototypes describe intrinsic functions - * corresponding to TIE instructions. Some TIE instructions - * may produce multiple results (designated as "out" operands - * in the iclass section) or may have operands used as both - * inputs and outputs (designated as "inout"). However, the C - * and C++ languages do not provide syntax that can express - * the in/out/inout constraints of TIE intrinsics. - * Nevertheless, the compiler understands these constraints - * and will check that the intrinsic functions are used - * correctly. To improve the readability of these prototypes, - * the "out" and "inout" parameters are marked accordingly - * with comments. - */ - -extern void _TIE_xt_regwin_ENTRY(unsigned ars /*inout*/, immediate uimm12x8); -extern void _TIE_xt_regwin_ROTW(immediate simm4); -extern int _TIE_xt_regwin_MOVSP(int s); -extern int _TIE_xt_regwin_L32E(const int * s, immediate o); -extern void _TIE_xt_regwin_S32E(int t, int * s, immediate o); -extern unsigned _TIE_xt_regwin_RSR_WINDOWBASE(void); -extern void _TIE_xt_regwin_WSR_WINDOWBASE(unsigned t); -extern void _TIE_xt_regwin_XSR_WINDOWBASE(unsigned t /*inout*/); -extern unsigned _TIE_xt_regwin_RSR_WINDOWSTART(void); -extern void _TIE_xt_regwin_WSR_WINDOWSTART(unsigned t); -extern void _TIE_xt_regwin_XSR_WINDOWSTART(unsigned t /*inout*/); -#define XT_ENTRY _TIE_xt_regwin_ENTRY -#define XT_ROTW _TIE_xt_regwin_ROTW -#define XT_MOVSP _TIE_xt_regwin_MOVSP -#define XT_L32E _TIE_xt_regwin_L32E -#define XT_S32E _TIE_xt_regwin_S32E -#define XT_RSR_WINDOWBASE _TIE_xt_regwin_RSR_WINDOWBASE -#define XT_WSR_WINDOWBASE _TIE_xt_regwin_WSR_WINDOWBASE -#define XT_XSR_WINDOWBASE _TIE_xt_regwin_XSR_WINDOWBASE -#define XT_RSR_WINDOWSTART _TIE_xt_regwin_RSR_WINDOWSTART -#define XT_WSR_WINDOWSTART _TIE_xt_regwin_WSR_WINDOWSTART -#define XT_XSR_WINDOWSTART _TIE_xt_regwin_XSR_WINDOWSTART - -#endif /* __XCC__ */ - -#endif /* __XTENSA__ */ - -#endif /* !_XTENSA_xt_regwin_HEADER */ diff --git a/components/esp32/include/xtensa/tie/xt_scmpr.h b/components/esp32/include/xtensa/tie/xt_scmpr.h deleted file mode 100644 index 337c7762eb..0000000000 --- a/components/esp32/include/xtensa/tie/xt_scmpr.h +++ /dev/null @@ -1,22 +0,0 @@ - -/* - * Customer ID=11657; Build=0x5fe96; Copyright (c) 2004-2010 by Tensilica Inc. ALL RIGHTS RESERVED. - * These coded instructions, statements, and computer programs are the - * copyrighted works and confidential proprietary information of Tensilica Inc. - * They may not be modified, copied, reproduced, distributed, or disclosed to - * third parties in any manner, medium, or form, in whole or in part, without - * the prior written consent of Tensilica Inc. - */ - -/* Do not modify. This is automatically generated.*/ - -#ifndef _XTENSA_xt_scmpr_h_HEADER -#define _XTENSA_xt_scmpr_h_HEADER - - -/* Header includes start */ - - -/* Header includes end */ - -#endif /* !_XTENSA_xt_scmpr_h_HEADER */ diff --git a/components/esp32/include/xtensa/tie/xt_sync.h b/components/esp32/include/xtensa/tie/xt_sync.h deleted file mode 100644 index 9323dfe4b8..0000000000 --- a/components/esp32/include/xtensa/tie/xt_sync.h +++ /dev/null @@ -1,60 +0,0 @@ -/* Definitions for the xt_sync TIE package */ - -/* - * Customer ID=11657; Build=0x5fe96; Copyright (c) 2004-2010 by Tensilica Inc. ALL RIGHTS RESERVED. - * These coded instructions, statements, and computer programs are the - * copyrighted works and confidential proprietary information of Tensilica Inc. - * They may not be modified, copied, reproduced, distributed, or disclosed to - * third parties in any manner, medium, or form, in whole or in part, without - * the prior written consent of Tensilica Inc. - */ - -/* Do not modify. This is automatically generated.*/ - -#ifndef _XTENSA_xt_sync_HEADER -#define _XTENSA_xt_sync_HEADER - -#ifdef __XTENSA__ -#ifdef __XCC__ - -#include - -/* - * The following prototypes describe intrinsic functions - * corresponding to TIE instructions. Some TIE instructions - * may produce multiple results (designated as "out" operands - * in the iclass section) or may have operands used as both - * inputs and outputs (designated as "inout"). However, the C - * and C++ languages do not provide syntax that can express - * the in/out/inout constraints of TIE intrinsics. - * Nevertheless, the compiler understands these constraints - * and will check that the intrinsic functions are used - * correctly. To improve the readability of these prototypes, - * the "out" and "inout" parameters are marked accordingly - * with comments. - */ - -extern unsigned _TIE_xt_sync_RSR_SCOMPARE1(void); -extern void _TIE_xt_sync_WSR_SCOMPARE1(unsigned art); -extern void _TIE_xt_sync_XSR_SCOMPARE1(unsigned art /*inout*/); -extern unsigned _TIE_xt_sync_RSR_ATOMCTL(void); -extern void _TIE_xt_sync_WSR_ATOMCTL(unsigned art); -extern void _TIE_xt_sync_XSR_ATOMCTL(unsigned art /*inout*/); -extern unsigned _TIE_xt_sync_L32AI(const unsigned * p, immediate o); -extern void _TIE_xt_sync_S32RI(unsigned c, unsigned * p, immediate o); -extern void _TIE_xt_sync_S32C1I(unsigned c /*inout*/, const unsigned * p, immediate o); -#define XT_RSR_SCOMPARE1 _TIE_xt_sync_RSR_SCOMPARE1 -#define XT_WSR_SCOMPARE1 _TIE_xt_sync_WSR_SCOMPARE1 -#define XT_XSR_SCOMPARE1 _TIE_xt_sync_XSR_SCOMPARE1 -#define XT_RSR_ATOMCTL _TIE_xt_sync_RSR_ATOMCTL -#define XT_WSR_ATOMCTL _TIE_xt_sync_WSR_ATOMCTL -#define XT_XSR_ATOMCTL _TIE_xt_sync_XSR_ATOMCTL -#define XT_L32AI _TIE_xt_sync_L32AI -#define XT_S32RI _TIE_xt_sync_S32RI -#define XT_S32C1I _TIE_xt_sync_S32C1I - -#endif /* __XCC__ */ - -#endif /* __XTENSA__ */ - -#endif /* !_XTENSA_xt_sync_HEADER */ diff --git a/components/esp32/include/xtensa/tie/xt_timer.h b/components/esp32/include/xtensa/tie/xt_timer.h deleted file mode 100644 index 64db45c1a4..0000000000 --- a/components/esp32/include/xtensa/tie/xt_timer.h +++ /dev/null @@ -1,66 +0,0 @@ -/* Definitions for the xt_timer TIE package */ - -/* - * Customer ID=11657; Build=0x5fe96; Copyright (c) 2004-2010 by Tensilica Inc. ALL RIGHTS RESERVED. - * These coded instructions, statements, and computer programs are the - * copyrighted works and confidential proprietary information of Tensilica Inc. - * They may not be modified, copied, reproduced, distributed, or disclosed to - * third parties in any manner, medium, or form, in whole or in part, without - * the prior written consent of Tensilica Inc. - */ - -/* Do not modify. This is automatically generated.*/ - -#ifndef _XTENSA_xt_timer_HEADER -#define _XTENSA_xt_timer_HEADER - -#ifdef __XTENSA__ -#ifdef __XCC__ - -#include - -/* - * The following prototypes describe intrinsic functions - * corresponding to TIE instructions. Some TIE instructions - * may produce multiple results (designated as "out" operands - * in the iclass section) or may have operands used as both - * inputs and outputs (designated as "inout"). However, the C - * and C++ languages do not provide syntax that can express - * the in/out/inout constraints of TIE intrinsics. - * Nevertheless, the compiler understands these constraints - * and will check that the intrinsic functions are used - * correctly. To improve the readability of these prototypes, - * the "out" and "inout" parameters are marked accordingly - * with comments. - */ - -extern unsigned _TIE_xt_timer_RSR_CCOUNT(void); -extern void _TIE_xt_timer_WSR_CCOUNT(unsigned art); -extern void _TIE_xt_timer_XSR_CCOUNT(unsigned art /*inout*/); -extern unsigned _TIE_xt_timer_RSR_CCOMPARE0(void); -extern void _TIE_xt_timer_WSR_CCOMPARE0(unsigned art); -extern void _TIE_xt_timer_XSR_CCOMPARE0(unsigned art /*inout*/); -extern unsigned _TIE_xt_timer_RSR_CCOMPARE1(void); -extern void _TIE_xt_timer_WSR_CCOMPARE1(unsigned art); -extern void _TIE_xt_timer_XSR_CCOMPARE1(unsigned art /*inout*/); -extern unsigned _TIE_xt_timer_RSR_CCOMPARE2(void); -extern void _TIE_xt_timer_WSR_CCOMPARE2(unsigned art); -extern void _TIE_xt_timer_XSR_CCOMPARE2(unsigned art /*inout*/); -#define XT_RSR_CCOUNT _TIE_xt_timer_RSR_CCOUNT -#define XT_WSR_CCOUNT _TIE_xt_timer_WSR_CCOUNT -#define XT_XSR_CCOUNT _TIE_xt_timer_XSR_CCOUNT -#define XT_RSR_CCOMPARE0 _TIE_xt_timer_RSR_CCOMPARE0 -#define XT_WSR_CCOMPARE0 _TIE_xt_timer_WSR_CCOMPARE0 -#define XT_XSR_CCOMPARE0 _TIE_xt_timer_XSR_CCOMPARE0 -#define XT_RSR_CCOMPARE1 _TIE_xt_timer_RSR_CCOMPARE1 -#define XT_WSR_CCOMPARE1 _TIE_xt_timer_WSR_CCOMPARE1 -#define XT_XSR_CCOMPARE1 _TIE_xt_timer_XSR_CCOMPARE1 -#define XT_RSR_CCOMPARE2 _TIE_xt_timer_RSR_CCOMPARE2 -#define XT_WSR_CCOMPARE2 _TIE_xt_timer_WSR_CCOMPARE2 -#define XT_XSR_CCOMPARE2 _TIE_xt_timer_XSR_CCOMPARE2 - -#endif /* __XCC__ */ - -#endif /* __XTENSA__ */ - -#endif /* !_XTENSA_xt_timer_HEADER */ diff --git a/components/esp32/include/xtensa/tie/xt_trace.h b/components/esp32/include/xtensa/tie/xt_trace.h deleted file mode 100644 index 8d8d07fa48..0000000000 --- a/components/esp32/include/xtensa/tie/xt_trace.h +++ /dev/null @@ -1,44 +0,0 @@ -/* Definitions for the xt_trace TIE package */ - -/* - * Customer ID=11657; Build=0x5fe96; Copyright (c) 2004-2010 by Tensilica Inc. ALL RIGHTS RESERVED. - * These coded instructions, statements, and computer programs are the - * copyrighted works and confidential proprietary information of Tensilica Inc. - * They may not be modified, copied, reproduced, distributed, or disclosed to - * third parties in any manner, medium, or form, in whole or in part, without - * the prior written consent of Tensilica Inc. - */ - -/* Do not modify. This is automatically generated.*/ - -#ifndef _XTENSA_xt_trace_HEADER -#define _XTENSA_xt_trace_HEADER - -#ifdef __XTENSA__ -#ifdef __XCC__ - -#include - -/* - * The following prototypes describe intrinsic functions - * corresponding to TIE instructions. Some TIE instructions - * may produce multiple results (designated as "out" operands - * in the iclass section) or may have operands used as both - * inputs and outputs (designated as "inout"). However, the C - * and C++ languages do not provide syntax that can express - * the in/out/inout constraints of TIE intrinsics. - * Nevertheless, the compiler understands these constraints - * and will check that the intrinsic functions are used - * correctly. To improve the readability of these prototypes, - * the "out" and "inout" parameters are marked accordingly - * with comments. - */ - -extern void _TIE_xt_trace_WSR_MMID(unsigned art); -#define XT_WSR_MMID _TIE_xt_trace_WSR_MMID - -#endif /* __XCC__ */ - -#endif /* __XTENSA__ */ - -#endif /* !_XTENSA_xt_trace_HEADER */ diff --git a/components/esp32/include/xtensa/trax-api.h b/components/esp32/include/xtensa/trax-api.h deleted file mode 100644 index aa1584359b..0000000000 --- a/components/esp32/include/xtensa/trax-api.h +++ /dev/null @@ -1,93 +0,0 @@ -/* Misc TRAX API function definitions. - - Copyright (c) 2007-2012 Tensilica 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. */ - -#ifndef _TRAX_API_H_ -#define _TRAX_API_H_ - -#include -#include -#include "tpack.h" -#include "traxreg.h" - -#include "xdm-regs.h" - -/* Flags for trax_stop(): */ -#define TRAX_STOP_HALT 0x0001 /* halt immediately, don't wait for post-stop-trigger capture */ -#define TRAX_STOP_QUIET 0x0002 /* don't display informative messages */ - - -/* - * Describes a TRAX channel (based on tpack). - */ -typedef struct { - tpack_channel chan; /* channel structure header */ - /* Per TRAX unit information: */ - int trax_version; /* TRAX_ID_VER(id), one of TRAX_VER_xxx macros */ - unsigned long trax_tram_size; /* size of trace RAM in bytes */ - int trax_erratum10; /* set if TRAX 1.0 erratum workarounds needed */ - int trax_erratum20; /* set if TRAX 2.0 erratum workaround needed (PR 22161)*/ - int trax_erratum20_size; - int trax_has_busy; /* has trace-busy feature */ - int trax_has_atb; /* has ATB feature */ - /*FIXME: add various features: coresight regs (don't call it that), APB, ATB, TRAM, ... */ -} trax_channel; - - -/* Prototypes: */ - -/* TRAX Protocol API: */ -extern int trax_read_register(tpack_channel *tchan, int regno, unsigned *value); -extern int trax_write_register(tpack_channel *tchan, int regno, unsigned value); -extern int trax_read_memory(tpack_channel *tchan, int address, int size, unsigned char *pdata); -extern int trax_fill_memory(tpack_channel *tchan, int address, int size, tpack_u32 pattern); -extern int trax_enumerate_devices(tpack_channel *tchan, int * buf, int * size); - -/* TRAX Network API: */ -extern unsigned long trax_ram_size(tpack_channel *traxchan); -extern unsigned long trax_ram_size_addr(tpack_channel *traxchan); -extern int trax_create_tracefile(tpack_channel *traxchan, int size, unsigned char * data, - char *filename, int hflags, const char *toolver); -extern int trax_memaccess_safe(tpack_channel *traxchan, const char *what); -extern int trax_start(tpack_channel *traxchan, int flags); -extern int trax_stop(tpack_channel *traxchan, int flags); -extern int trax_halt(tpack_channel *traxchan, int flags); -extern int trax_save(tpack_channel *traxchan, char *filename, int flags, const char *toolver, int erratum); - -/* TRAX Misc API (no network dependencies): */ -int trax_fixed_hw(unsigned * regs); -extern int trax_display_id(unsigned id, const char *prefix); -extern int trax_display_summary(unsigned id, - unsigned status, - unsigned control, - unsigned address, - unsigned delay, - unsigned trigger, - unsigned match, - unsigned startaddr, - unsigned endaddr, - const char *prefix); - -/* Other: */ - -#endif /* _TRAX_API_H_ */ - diff --git a/components/esp32/include/xtensa/trax-core-config.h b/components/esp32/include/xtensa/trax-core-config.h deleted file mode 100644 index 42a03334aa..0000000000 --- a/components/esp32/include/xtensa/trax-core-config.h +++ /dev/null @@ -1,144 +0,0 @@ -/* Definitions for Xtensa processor config info needed for TRAX. - - Copyright (c) 2005-2011 Tensilica 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. */ - -#ifndef TRAX_CORE_CONFIG_H -#define TRAX_CORE_CONFIG_H - -#include "xtensa-params.h" - -/* - * Vector Enumerations. - */ - -/* These must match the LX2.0 and later traceport spec: */ -#define VEC_NO_VECTOR 0 -#define VEC_FIRST VEC_RESET /* first valid vector */ -#define VEC_RESET 1 -#define VEC_DEBUG 2 -#define VEC_NMI 3 -#define VEC_USER 4 -#define VEC_KERNEL 5 -#define VEC_DOUBLE 6 -#define VEC_MEMERR 7 -#define VEC_RESERVED8 8 -#define VEC_RESERVED9 9 -#define VEC_WINO4 10 -#define VEC_WINU4 11 -#define VEC_WINO8 12 -#define VEC_WINU8 13 -#define VEC_WINO12 14 -#define VEC_WINU12 15 -#define VEC_INTLEVEL2 16 -#define VEC_INTLEVEL3 17 -#define VEC_INTLEVEL4 18 -#define VEC_INTLEVEL5 19 -#define VEC_INTLEVEL6 20 -/* These are internal, i.e. don't appear like this on traceport: */ -#define VEC_DEBUG_OCD 21 -#define VEC_UNKNOWN 22 -/* Enumerations 23 through 31 are also reserved, but putting */ -/* placeholders here seems wasteful and unnecessary. */ -#define VEC_COUNT 23 - -/* Other branch (change-of-PC-flow) type encodings; - * if PC changes due to an exception or interrupt vector, - * one of the VEC_* values above is used, otherwise - * (or if it's unknown whether it's due to an exception/interrupt) - * one of the following is used: */ - -#define BRANCH_IS_VEC(n) ((n) < VEC_COUNT) /* is known to be except/interrupt? */ -#define BRANCH_OR_VEC 24 /* unknown type of branch (branch/exception/interrupt/etc) */ -#define BRANCH_UNKNOWN 25 /* unknown type of branch (anything but except/interrupt) */ -#define BRANCH_UNKNOWN_ERR 26 /* like BRANCH_UNKNOWN with known error (non-branch instr) */ -#define BRANCH_LOOPBACK 28 /* zero-overhead loopback (from LEND to LBEG) */ -#define BRANCH_CONDTAKEN 29 /* conditional branch taken (or LOOP{NEZ,GTZ} loop skip) */ -#define BRANCH_JUMP 30 /* jump (unconditional branch, i.e. J or JX) */ -#define BRANCH_IS_CALL(n) (((n) & ~3) == 32) /* is a function call? */ -#define BRANCH_CALL0 32 /* non-windowed function call (CALL0, CALLX0) */ -#define BRANCH_CALL4 33 /* windowed function call (CALL4, CALLX4) */ -#define BRANCH_CALL8 34 /* windowed function call (CALL8, CALLX8) */ -#define BRANCH_CALL12 35 /* windowed function call (CALL12, CALLX12) */ -#define BRANCH_IS_RETURN(n) ((n) >= 36) /* is any kind of return? */ -#define BRANCH_IS_CALLRETURN(n) (((n) & ~1) == 36) /* is a function return? */ -#define BRANCH_RET 36 /* non-windowed function return (RET or RET.N) */ -#define BRANCH_RETW 37 /* windowed function return (RETW or RETW.N) */ -#define BRANCH_IS_EIRETURN(n) ((n) >= 38) /* is an except/inter. return? */ -#define BRANCH_RFE 38 /* RFE or RFUE */ -#define BRANCH_RFDE 39 /* RFDE */ -#define BRANCH_RFWO 40 /* RFWO */ -#define BRANCH_RFWU 41 /* RFWU */ -#define BRANCH_RFI_2 42 /* RFI 2 */ -#define BRANCH_RFI_3 43 /* RFI 3 */ -#define BRANCH_RFI_4 44 /* RFI 4 */ -#define BRANCH_RFI_5 45 /* RFI 5 */ -#define BRANCH_RFI_6 46 /* RFI 6 */ -#define BRANCH_RFI_NMI 47 /* RFI NMILEVEL */ -#define BRANCH_RFI_DEBUG 48 /* RFI DEBUGLEVEL */ -#define BRANCH_RFME 49 /* RFME */ -#define BRANCH_COUNT 50 /* (number of defined BRANCH_xxx values) */ - - - -typedef struct { - unsigned vaddr; - unsigned vaddr2; /* for static vectors only (reloc vectors option) */ - int is_configured; -} trax_vector_t; - - -/* - * This structure describes those portion of a Tensilica processor's - * configuration that are useful for trace. - */ -typedef struct { - char ** isa_dlls; - char * core_name; /* (XPG core name, not necessarily same as XTENSA_CORE) */ - int big_endian; /* 0 = little-endian, 1 = big-endian */ - int has_loops; /* 1 = zero overhead loops configured */ - int has_autorefill; /* 1 = TLB autorefill (MMU) configured */ - unsigned max_instr_size; /* in bytes (eg. 3, 4, 8, ...) */ - unsigned int_level_max; /* number of interrupt levels configured (without NMI) */ - int debug_level; /* debug intlevel, 0 if debug not configured */ - int nmi_level; /* NMI intlevel, 0 if NMI not configured */ - unsigned targethw_min; /* min. targeted hardware version (XTENSA_HWVERSION_) */ - unsigned targethw_max; /* max. targeted hardware version (XTENSA_HWVERSION_) */ - int reloc_vectors; /* 0 = fixed vectors, 1 = relocatable vectors */ - int statvec_select; /* 0 = stat vec base 0, 1 = stat vec base 1 (SW default) */ - int vecbase_align; /* number of bits to align VECBASE (32 - bits in VECBASE) */ - unsigned statvec_base0; /* static vector base 0 */ - unsigned statvec_base1; /* static vector base 1 */ - unsigned vecbase_reset; /* reset value of VECBASE */ - trax_vector_t vectors[VEC_COUNT]; /* all vectors... */ -} trax_core_config_t; - - -/* Globals: */ -//extern const char * const trax_vector_short_names[/*VEC_COUNT*/]; // nobody uses this one -extern const char * const trax_vector_names[/*VEC_COUNT*/]; - -/* Prototypes: */ -extern int trax_read_params (trax_core_config_t *c, xtensa_params p); -extern int trax_vector_from_address(trax_core_config_t *config, unsigned long vaddr, unsigned long *vecbases); - -#endif /* TRAX_CORE_CONFIG_H */ - diff --git a/components/esp32/include/xtensa/trax-proto.h b/components/esp32/include/xtensa/trax-proto.h deleted file mode 100644 index 41d5c9fd76..0000000000 --- a/components/esp32/include/xtensa/trax-proto.h +++ /dev/null @@ -1,91 +0,0 @@ -/* This file contains functions that are hidden from the user. These are - * protocol specific functions used to read and write TRAX registers - * and the trace memory - */ - -/* - * Copyright (c) 2012-2013 Tensilica 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. - */ -#ifndef _TRAX_PROTO_H -#define _TRAX_PROTO_H - -#ifdef __cplusplus -extern "C" { -#endif - -/* Function to read register - * - * regno : The register number to be read (not ERI addressed) - * data : Location where the read value is kept - * - * returns : 0 if successful, -1 if unsuccessful - */ -int trax_read_register_eri (int regno, unsigned *data); - -/* Function to write a value into a register - * - * regno : The register number to be written (not ERI addressed) - * value : The value to be written at that register location - * - * returns : 0 if successful, -1 if unsuccessful - */ -int trax_write_register_eri (int regno, unsigned value); - -/* Function to read memory - * - * address : Address of the TraceRAM memory, each location has a word - * len : Amount of memory in bytes, to be read - * data : buffer in which the read memory is stored - * final_address: Next address to be read in the following call to this - * function (trace save mechanism) - * - * returns : 0 if successful, -1 if unsuccessful - */ -int trax_read_memory_eri (unsigned address, int len, int *data, - unsigned *final_address); - -/* Function to write a value to the memory address - * - * address : Address of the TraceRAM memory - * value : The value to be written inside that location - * - * returns : 0 if successful, -1 if unsuccessful - */ -int trax_write_memory_eri (int address, unsigned value); - -/* Function to write to a subfield of the register. - * Called by set and show parameter functions. - * - * regno : Register number - * regmask : Mask in order to toggle appropriate bits - * value : Value to be written in the masked location - * - * returns : 0 if successful, -1 if unsuccessful - */ -int trax_write_register_field_eri (int regno, unsigned regmask, - unsigned value); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/components/esp32/include/xtensa/trax-util.h b/components/esp32/include/xtensa/trax-util.h deleted file mode 100644 index 123ac366df..0000000000 --- a/components/esp32/include/xtensa/trax-util.h +++ /dev/null @@ -1,63 +0,0 @@ -/* This file contains utility functions that can be used for polling TRAX - * or executing higher level save functionality - * It assumes that print subroutines and file I/O routines are available - * on the system - */ - -/* - * Copyright (c) 2012-2013 Tensilica 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. - */ - -#ifndef _TRAX_UTIL_H -#define _TRAX_UTIL_H - - -#ifdef __cplusplus -extern "C" { -#endif - -/* User can use this function if he wants to generate a tracefile output. - * Internally it calls trax_get_trace in a loop until it realizes that - * the entire trace has been read. - * - * context : pointer to structure which contains information about the - * current TRAX session - * filename : user specified output trace file name. If the file does not - * exist, it would create the new file, else would append to it - * - * returns : 0 if successful, -1 if unsuccessful - */ -int trax_save (trax_context *context, char *filename); - -/* Displays a brief machine readable status. - * - * context : pointer to structure which contains information about the - * current TRAX session - * returns : 0 if successful, -1 if unsuccessful - */ -int trax_poll (trax_context *context); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/components/esp32/include/xtensa/trax.h b/components/esp32/include/xtensa/trax.h deleted file mode 100644 index 47049c51d2..0000000000 --- a/components/esp32/include/xtensa/trax.h +++ /dev/null @@ -1,409 +0,0 @@ -/* Header file for TRAX control Library */ - -/* - * Copyright (c) 2012-2013 Tensilica 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. - */ - -#ifndef _TRAX_H -#define _TRAX_H - -#ifdef __cplusplus -extern "C" { -#endif - -#define TRAX_STOP_HALT 0x0001 -#define TRAX_STOP_QUIET 0x0002 - -/* Flag values to indicate if the user wanted to reverse the pcstop - * parameters */ -#define TRAX_PCSTOP_REVERSE 0x0001 -#define TRAX_PCSTOP_NO_REVERSE 0x0000 - -/* Indicating whether postsize should be in terms of bytes, instructions - * or percentage of trace size captured */ -#define TRAX_POSTSIZE_BYTES 0x0000 -#define TRAX_POSTSIZE_INSTR 0x0001 -#define TRAX_POSTSIZE_PERCENT 0x0002 - -/* Size of the header inside the trace file */ -#define TRAX_HEADER_SIZE 256 - -/* Minimum size between start and end addresses */ -#define TRAX_MIN_TRACEMEM 64 - -/* For basic debugging */ -#define DEBUG 0 - -#include - -#define ffs(i) __builtin_ffs(i) - -/* Data structures */ - -/* Represents the context of the TRAX unit and the current TRAX session. - * To be used by set and show function calls to set and show appropriate - * parameters of appropriate TRAX unit. - */ - -typedef struct { - int trax_version; /* TRAX PC version information */ - unsigned long trax_tram_size; /* If trace RAM is present,size of it */ - int hflags; /* Flags that can be used to debug, - print info, etc. */ - int address_read_last; /* During saving of the trace, this - indicates the address from which - the current trace reading must - resume */ - unsigned long bytes_read; /* bytes read uptil now */ - unsigned long total_memlen; /* Total bytes to be read based on the - trace collected in the trace RAM */ - bool get_trace_started; /* indicates that the first chunk of - bytes (which include the header) has - been read */ -} trax_context; - - -/* -----------------------TRAX Initialization ------------------------------*/ - -/* Initializing the trax context. Reads registers and sets values for version, - * trace RAM size, total memory length, etc. Most of the other values are - * initialized to their default case. - * - * context : pointer to structure which contains information about the - * current TRAX session - * - * returns : 0 if successful, -1 if unsuccessful, -2 if ram_size if - * incorrect - */ -int trax_context_init_eri (trax_context *context); - -/* -----------------Starting/Stopping TRAX session -------------------------*/ - -/* Start tracing with current parameter setting. If tracing is already in - * progress, an error is reported. Otherwise, tracing starts and any unsaved - * contents of the TraceRAM is discarded - * - * context : pointer to structure which contains information about the - * current TRAX session - * returns : 0 if successful, 1 if trace is already active, - * -1 if unsuccessful - */ -int trax_start (trax_context *context); - -/* This command initiates a stop trigger or halts a trace session based of the - * value of the flag parameter passed. In case stop trigger is initiated, any - * selected post-stop-trigger capture proceeds normally. - * If trace capture was not in progress, or a stop was already triggered, the - * return value indicates appropriately. - * - * context : pointer to structure which contains information about the - * current TRAX session - * flags : To differentiate between stopping trace without any - * post-size-trigger capture (trax_halt) or with that. - * A zero value would stop the trace based on trigger and a - * value of one would halt it - * - * returns : 0 if successful, 1 if already stopped, -1 if unsuccessful - */ -int trax_stop_halt (trax_context *context, int flags); - -/* Resets the TRAX parameters to their default values which would internally - * involve resetting the TRAX registers. To invoke another trace session or - * reset the current tracing mechanism, this function needs to be called as - * it resets parameters of the context that deal with tracing information - * - * context : pointer to structure which contains information about the - * current TRAX session - * - * returns : 0 if successful, -1 if unsuccessful - */ -int trax_reset (trax_context *context); - -/* ---------------Set/Get several TRAX parameters --------------------------*/ - -/* Sets the start address and end address (word aligned) of the trace in the - * TraceRAM. Care must be taken to ensure that the difference between the - * start and the end addresses is atleast TRAX_MIN_TRACEMEM bytes. If not, - * the values are reset to default, which is 0 for startaddr and - * traceRAM_words -1 for endaddr - * - * context : pointer to structure which contains information about the - * current TRAX session - * startaddr : value to which the start address must be set. Can be - * any value between 0 - (traceRAM_words - 1) - * endaddr : value to which the end address must be set. Can be any value - * between 0 - (traceRAM_words - 1) - * - * returns : 0 if successful, -1 if unsuccessful, -2 if the difference - * between the start and end addresses is less than - * TRAX_MIN_TRACEMEM bytes or if they are passed incorrect - * values, -3 if memory shared option is not configured, in - * which case, start and end addresses are set to default - * values instead of those passed by the user - */ -int trax_set_ram_boundaries (trax_context *context, unsigned startaddr, - unsigned endaddr); - -/* Shows the start address and end address(word aligned) of the trace in the - * TraceRAM. If incorrect, the startaddress and the endaddress values are - * set to default, i.e. 0 for startaddr and traceRAM_words - 1 for endaddr - * - * context : pointer to structure which contains information about the - * current TRAX session - * startaddr : pointer to value which will contain the start address - * endaddr : pointer to value which will contain the end address - * - * returns : 0 if successful, -1 if unsuccessful - * - */ -int trax_get_ram_boundaries (trax_context *context, unsigned *startaddr, - unsigned *endaddr); - -/* Selects stop trigger via cross-trigger input - * - * context : pointer to structure which contains information about the - * current TRAX session - * value : 0 = off (reset value), 1 = on - * - * returns : 0 if successful, -1 if unsuccessful - */ -int trax_set_ctistop (trax_context *context, unsigned value); - -/* Shows if stop-trigger via cross-trigger input is off or on - * - * context : pointer to structure which contains information about the - * current TRAX session - * returns : 0 if off, 1 if on, -1 if unsuccessful - */ -int trax_get_ctistop (trax_context *context); - -/* Selects stop trigger via processor-trigger input - * - * context : pointer to structure which contains information about the - * current TRAX session - * value : 0 = off (reset value), 1 = on - * - * returns : 0 if successful, -1 if unsuccessful - */ -int trax_set_ptistop (trax_context *context, unsigned value); - -/* Shows if stop trigger visa processor-trigger input is off or on - * - * context : pointer to structure which contains information about the - * current TRAX session - * returns : 0 if off, 1 if on, -1 if unsuccessful - */ -int trax_get_ptistop (trax_context *context); - -/* Reports cross trigger output state - * - * context : pointer to structure which contains information about the - * current TRAX session - * returns : 0 if CTO bit is reset, 1 if CTO bit is set - */ -int trax_get_cto (trax_context *context); - -/* Reports processor trigger output state - * - * context : pointer to structure which contains information about the - * current TRAX session - * returns : 0 if PTO bit is reset, 1 if PTO bit is set - */ -int trax_get_pto (trax_context *context); - -/* Selects condition that asserts cross trigger output - * - * context : pointer to structure which contains information about the - * current TRAX session - * option : 0 = off(reset value)/1 = ontrig/2 = onhalt - * - * returns : 0 if successful, -1 if unsuccessful - */ -int trax_set_ctowhen (trax_context *context, int option); - -/* Shows condition that asserted cross trigger output. It can be - * any of: ontrig or onhalt or even off - * - * context : pointer to structure which contains information about the - * current TRAX session - * - * returns : 0 if off, 1 if ontrig, 2 if onhalt, -1 if unsuccessful - */ -int trax_get_ctowhen (trax_context *context); - -/* Selects condition that asserts processor trigger output - * - * context : pointer to structure which contains information about the - * current TRAX session - * option : 0 = off(reset value)/1 = ontrig/2 = onhalt - * - * returns : 0 if successful, -1 if unsuccessful - */ -int trax_set_ptowhen (trax_context *context, int option); - - -/* Shows condition that asserted processor trigger output. It can be - * any of: ontrig or onhalt or even off - * - * context : pointer to structure which contains information about the - * current TRAX session - * returns : 0 if off, 1 if ontrig, 2 if onhalt, -1 if unsuccessful - */ -int trax_get_ptowhen (trax_context *context); - -/* Selects the trace synchronization message period. - * If ATEN enabled, we cannot allow syncper to be off, set it to reset value. - * Also, if no trace RAM, and ATEN enabled, set syncper to be reset value - * i.e. 256. A value of 1 i.e. on indicates that internally the message - * frequency is set to an optimal value. This option should be preferred - * if the user is not sure what message frequency option to set for the - * trace session. - * - * context : pointer to structure which contains information about the - * current TRAX session - * option : 0 = off, 1 = on, -1 = auto, 8, 16, 32, 64, 128, - * 256 (reset value) - * - * returns : 0 if successful, -1 if unsuccessful, -2 if incorrect - * arguments - */ -int trax_set_syncper (trax_context *context, int option); - -/* Shows trace synchronization message period. Can be one of: - * off, on, auto, 8, 16, 32, 64, 128, 256 (reset value) - * - * context : pointer to structure which contains information about the - * current TRAX session - * returns : value of sync period, 0 if off, -1 if unsuccessful - */ -int trax_get_syncper (trax_context *context); - -/* Selects stop trigger via PC match. Specifies the address or - * address range to match against program counter. Trace stops when the - * processor executes an instruction matching the specified address - * or range. - * - * context : pointer to structure which contains information about the - * current TRAX session - * index : indicates the number of stop trigger (currently there is - * only one i.e. index = 0) - * startaddress : start range of the address at which the stop trigger - * should be activated - * enaddress : end range of the address at which the stop trigger should - * be activated - * flags : If non-zero, this inverts the range. i.e. trace stops - * when the processor executes an instruction that does not - * match the specified address or range - * - * returns : 0 if successful, -1 if unsuccessful, -2 if incorrect - * arguments (unaligned) - * - * Note : For the current version of TRAX library, the endaddress and - * startaddress can differ by at most 31 bytes and the total - * range i.e. (endaddress - startaddress + 1) has to be a power - * of two - */ -int trax_set_pcstop (trax_context *context, int index, unsigned long startaddress, - unsigned long endaddress, int flags); - -/* Shows the stop trigger via PC match - * - * context : pointer to structure which contains information about the - * current TRAX session - * index : container of information about the number of stop triggers - * startaddress : container of start range of stop trigger - * endaddress : container of end range of stop trigger - * flags : container of information whcih indicates whether the - * pc stop range is inverted or not. - * - * returns : 0 if successful, -1 if unsuccessful - */ -int trax_get_pcstop (trax_context *context, int *index, - unsigned long *startaddress, - unsigned long *endaddress, int *flags); - -/* This function is used to set the amount of trace to be captured past - * the stop trigger. - * - * context : pointer to structure which contains information about the - * current TRAX session - * count_unit : contains the count of units (instructions or bytes) to be - * captured post trigger. If 0, it implies that this is off - * unit : unit of measuring the count. 0 is bytes, 1 is instructions - * 2 is percentage of trace - * - * returns : 0 if successful, -1 if unsuccessful, -2 if incorrect - * arguments - * - */ -int trax_set_postsize (trax_context *context, int count_unit, int unit); - -/* This function shows the amount of TraceRAM in terms of the number of - * instructions or bytes, captured post the stop trigger - * - * context : pointer to structure which contains information about the - * current TRAX session - * count_unit : will contain the count of units(instructions or bytes) post - * trigger - * unit : will contain information about the events that are counted - * 0 implies that the traceRAM words consumed are counted and - * 1 implies that the target processor instructions executed and - * excpetions/interrupts taken are counted - * - * returns : 0 if postsize was got successfully, -1 if unsuccessful - */ -int trax_get_postsize (trax_context *context, int *count_unit, int *unit); - -/* -------------------------- TRAX save routines ---------------------------*/ - -/* This function should be called by the user to return a chunk of - * bytes in buf. It can be a lower layer function of save, or can be - * called by the user explicitly. If bytes_actually_read contains a 0 - * after a call to this function has been made, it implies that the entire - * trace has been read successfully. - * - * context : pointer to structure which contains information about - * the current TRAX session - * buf : Buffer that is allocated by the user, all the trace - * data read would be put in this buffer, which can then - * be used to generate a tracefile. - * The first TRAX_HEADER_SIZE of the buffer will always - * contain the header information. - * bytes_to_be_read : Indicates the bytes the user wants to read. The first - * invocation would need this parameter to be - * TRAX_HEADER_SIZE at least. - * - * returns : bytes actually read during the call to this function. - * 0 implies that all the bytes in the trace have been - * read, -1 if unsuccessful read/write of - * registers or memory, -2 if trace was active while - * this function was called, -3 if user enters - * bytes_to_be_read < TRAX_HEADER_SIZE in the first - * pass - */ -int trax_get_trace (trax_context *context, void *buf, - int bytes_to_be_read); -#ifdef __cplusplus -} -#endif - -#endif /* _TRAX_H */ diff --git a/components/esp32/include/xtensa/traxfile.h b/components/esp32/include/xtensa/traxfile.h deleted file mode 100644 index 4afc926a50..0000000000 --- a/components/esp32/include/xtensa/traxfile.h +++ /dev/null @@ -1,62 +0,0 @@ -/* TRAX file header definition. - - Copyright (c) 2007-2012 Tensilica 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. */ - - -#define TRAX_FHEAD_MAGIC "TRAXdmp" -#define TRAX_FHEAD_VERSION 1 - -/* Header flags: */ -#define TRAX_FHEADF_OCD_ENABLED 0x00000001 /* set if OCD was enabled while capturing trace */ -#define TRAX_FHEADF_TESTDUMP 0x00000002 /* set if is a test file - (from 'memsave' instead of 'save') */ -#define TRAX_FHEADF_OCD_ENABLED_WHILE_EXIT 0x00000004 /* set if OCD was enabled while capturing trace and - we were exiting the OCD mode */ - -/* Header at the start of a TRAX dump file. */ -typedef struct { - char magic[8]; /* 00: "TRAXdmp\0" (TRAX_FHEAD_MAGIC) */ - char endianness; /* 08: 0=little-endian, 1=big-endian */ - char version; /* 09: TRAX_FHEAD_VERSION */ - char reserved0[2]; /* 0A: ... */ - unsigned filesize; /* 0C: size of the trace file, including this header */ - unsigned trace_ofs; /* 10: start of trace output, byte offset from start of header */ - unsigned trace_size; /* 14: size of trace output in bytes */ - unsigned dumptime; /* 18: date/time of capture save (secs since 1970-01-01), 0 if unknown */ - unsigned flags; /* 1C: misc flags (TRAX_FHEAD_F_xxx) */ - char username[16]; /* 20: user doing the capture/save (up to 15 chars) */ - char toolver[24]; /* 30: tool + version used for capture/save (up to 23 chars) */ - char reserved2[40]; /* 48: (reserved - could be hostname used for dump (up to 39 chars)) */ - unsigned configid[2]; /* 70: processor ConfigID values, 0 if unknown */ - unsigned ts_freq; /* 78: timestamp frequency, 0 if not specified */ - unsigned reserved3; /* 7C: (reserved) */ - unsigned id; /* 80: TRAX registers at time of save (0 if not read) */ - unsigned control; - unsigned status; - unsigned reserved4; /* Data register (should not be read) */ - unsigned address; - unsigned trigger; - unsigned match; - unsigned delay; - unsigned trax_regs[24]; /*100: (total size) -- dummy allocation (FIXME) */ -} trax_file_header; - diff --git a/components/esp32/include/xtensa/uart-16550-board.h b/components/esp32/include/xtensa/uart-16550-board.h deleted file mode 100644 index 8ef8af1637..0000000000 --- a/components/esp32/include/xtensa/uart-16550-board.h +++ /dev/null @@ -1,69 +0,0 @@ -/******************************************************************************* -Copyright (c) 2006-2013 by Tensilica Inc. ALL RIGHTS RESERVED. -These coded instructions, statements, and computer programs are the -copyrighted works and confidential proprietary information of Tensilica Inc. -They may not be modified, copied, reproduced, distributed, or disclosed to -third parties in any manner, medium, or form, in whole or in part, without -the prior written consent of Tensilica Inc. --------------------------------------------------------------------------------- - -uart-16550-board.h Board-specific UART info on these boards: - Avnet AV60 (XT-AV60) - Avnet AV110 (XT-AV110) - Avnet AV200 (XT-AV200) - Xilinx ML605 (XT-ML605) - Xilinx KC705 (XT-KC705) - -Interface between board-independent driver and board-specific header. - -This is used by a board-independent 16550 UART driver to obtain board-specific -information about 1 instance of the 16550 UART on the board, such as the device -register base address and spacing (a function of how the address lines are -connected on the board) and the frequency of the UART clock. The driver does -not refer directly to the board-specific header, which therefore is not -constrained to use macro names consistent with other boards. - -!! Must not contain any board-specific macro names (only UART specific). !! - -Included at compile-time via an include path specific to the board. - -These boards contain a single 16550 UART implemented on the FPGA. -Their clock frequency comes from the board's core clock (not its own crystal) -which depends on the core config so is not a constant. Obtained via the BSP. - -*******************************************************************************/ - -#ifndef _UART_16550_BOARD_H -#define _UART_16550_BOARD_H - -#include /* BSP API */ -#include /* Board info */ - - -/* Base address of UART's registers. */ -#ifdef UART16550_VADDR -#define UART_16550_REGBASE UART16550_VADDR -#endif - -/* -The UART's registers are connected at word addresses on these boards. -Each byte-wide register appears as the least-significant-byte (LSB) of the -word regardless of the endianness of the processor. -*/ -#define UART_16550_REGSPACING 4 -typedef unsigned uart16550_reg_t; - -/* UART Clock Frequency in Hz */ -#define UART_16550_XTAL_FREQ xtbsp_clock_freq_hz() - -/* UART Interrupt Number */ -#ifdef UART16550_INTNUM -#define UART_16550_INTNUM UART16550_INTNUM -#endif - - -/* Include generic information shared by all boards that use this device. */ -#include - -#endif /* _UART_16550_BOARD_H */ - diff --git a/components/esp32/include/xtensa/uart-16550.h b/components/esp32/include/xtensa/uart-16550.h deleted file mode 100644 index c551c64c13..0000000000 --- a/components/esp32/include/xtensa/uart-16550.h +++ /dev/null @@ -1,152 +0,0 @@ -/******************************************************************************* - - Copyright (c) 2006-2007 Tensilica 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. - --------------------------------------------------------------------------------- - -uart-16550.h Generic definitions for National Semiconductor 16550 UART - -This is used by board-support-packages with one or more 16550 compatible UARTs. -A BSP provides a base address for each instance of a 16550 UART on the board. - -Note that a 16552 DUART (Dual UART) is simply two instances of a 16550 UART. - -*******************************************************************************/ - -#ifndef _UART_16550_H_ -#define _UART_16550_H_ - -/* C interface to UART registers. */ -struct uart_dev_s { - union { - uart16550_reg_t rxb; /* DLAB=0: receive buffer, read-only */ - uart16550_reg_t txb; /* DLAB=0: transmit buffer, write-only */ - uart16550_reg_t dll; /* DLAB=1: divisor, LS byte latch */ - } w0; - union { - uart16550_reg_t ier; /* DLAB=0: interrupt-enable register */ - uart16550_reg_t dlm; /* DLAB=1: divisor, MS byte latch */ - } w1; - - union { - uart16550_reg_t isr; /* DLAB=0: interrupt status register, read-only */ - uart16550_reg_t fcr; /* DLAB=0: FIFO control register, write-only */ - uart16550_reg_t afr; /* DLAB=1: alternate function register */ - } w2; - - uart16550_reg_t lcr; /* line control-register, write-only */ - uart16550_reg_t mcr; /* modem control-regsiter, write-only */ - uart16550_reg_t lsr; /* line status register, read-only */ - uart16550_reg_t msr; /* modem status register, read-only */ - uart16550_reg_t scr; /* scratch regsiter, read/write */ -}; - - -#define _RXB(u) ((u)->w0.rxb) -#define _TXB(u) ((u)->w0.txb) -#define _DLL(u) ((u)->w0.dll) -#define _IER(u) ((u)->w1.ier) -#define _DLM(u) ((u)->w1.dlm) -#define _ISR(u) ((u)->w2.isr) -#define _FCR(u) ((u)->w2.fcr) -#define _AFR(u) ((u)->w2.afr) -#define _LCR(u) ((u)->lcr) -#define _MCR(u) ((u)->mcr) -#define _LSR(u) ((u)->lsr) -#define _MSR(u) ((u)->msr) -#define _SCR(u) ((u)->scr) - -typedef volatile struct uart_dev_s uart_dev_t; - -/* IER bits */ -#define RCVR_DATA_REG_INTENABLE 0x01 -#define XMIT_HOLD_REG_INTENABLE 0x02 -#define RCVR_STATUS_INTENABLE 0x04 -#define MODEM_STATUS_INTENABLE 0x08 - -/* FCR bits */ -#define _FIFO_ENABLE 0x01 -#define RCVR_FIFO_RESET 0x02 -#define XMIT_FIFO_RESET 0x04 -#define DMA_MODE_SELECT 0x08 -#define RCVR_TRIGGER_LSB 0x40 -#define RCVR_TRIGGER_MSB 0x80 - -/* AFR bits */ -#define AFR_CONC_WRITE 0x01 -#define AFR_BAUDOUT_SEL 0x02 -#define AFR_RXRDY_SEL 0x04 - -/* ISR bits */ -#define INT_STATUS(r) ((r)&1) -#define INT_PRIORITY(r) (((r)>>1)&0x7) - -/* LCR bits */ -#define WORD_LENGTH(n) (((n)-5)&0x3) -#define STOP_BIT_ENABLE 0x04 -#define PARITY_ENABLE 0x08 -#define EVEN_PARITY 0x10 -#define FORCE_PARITY 0x20 -#define XMIT_BREAK 0x40 -#define DLAB_ENABLE 0x80 - -/* MCR bits */ -#define _DTR 0x01 -#define _RTS 0x02 -#define _OP1 0x04 -#define _OP2 0x08 -#define LOOP_BACK 0x10 - -/* LSR Bits */ -#define RCVR_DATA_READY 0x01 -#define OVERRUN_ERROR 0x02 -#define PARITY_ERROR 0x04 -#define FRAMING_ERROR 0x08 -#define BREAK_INTERRUPT 0x10 -#define XMIT_HOLD_EMPTY 0x20 -#define XMIT_EMPTY 0x40 -#define FIFO_ERROR 0x80 -#define RCVR_READY(u) (_LSR(u)&RCVR_DATA_READY) -#define XMIT_READY(u) (_LSR(u)&XMIT_HOLD_EMPTY) - -/* MSR bits */ -#define _RDR 0x01 -#define DELTA_DSR 0x02 -#define DELTA_RI 0x04 -#define DELTA_CD 0x08 -#define _CTS 0x10 -#define _DSR 0x20 -#define _RI 0x40 -#define _CD 0x80 - - -/* Compute 16-bit divisor for baudrate generator, with rounding: */ -#define UART_DIVISOR(clock,baud) (((clock)/16 + (baud)/2)/(baud)) - -/* Prototypes of driver functions */ -extern void uart16550_init( uart_dev_t *u, unsigned baud, unsigned ndata, - unsigned parity, unsigned nstop ); -extern void uart16550_out( uart_dev_t *u, char c ); -extern char uart16550_in( uart_dev_t *u ); -extern unsigned uart16550_measure_sys_clk( uart_dev_t *u ); - -#endif /* _UART_16550_H_ */ diff --git a/components/esp32/include/xtensa/udma.h b/components/esp32/include/xtensa/udma.h deleted file mode 100644 index a5feb77701..0000000000 --- a/components/esp32/include/xtensa/udma.h +++ /dev/null @@ -1,276 +0,0 @@ -/* Customer ID=11656; Build=0x5f626; Copyright (c) 2005-2014 by Cadence Design Systems, Inc. ALL RIGHTS RESERVED. - * These coded instructions, statements, and computer programs are the - * copyrighted works and confidential proprietary information of - * Cadence Design Systems, Inc. They may not be modified, copied, reproduced, - * distributed, or disclosed to third parties in any manner, medium, or form, - * in whole or in part, without the prior written consent of Cadence Design - * Systems Inc. - */ -#ifndef __UDMA_H__ -#define __UDMA_H__ - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/* Size of the uDMA descriptor */ -#define UDMA_DESC_STRUCT_SIZE 32 - -/* Request attribute is a bit vector passed to the udma functions - udma_copy, - * udma_2d_copy, udma_add_descs. - * Bit 0 : 1 - trigger an interrupt when done, else do nothing - * Bit 1 : 0 - retry the failed request; abort after programmer specified - * number of retries. Defaults to abort with no retries. - * 1 - abort the failed request (after retries) and all pending requests - */ -#define UDMA_DONE_INTERRUPT 0x1 -#define UDMA_ERROR_ABORT 0x0 -#define UDMA_ERROR_ABORT_ALL 0x2 - -/* Enum representing various udma error conditions, udma status, and - * return values - */ -typedef enum { - UDMA_OK = 0, - UDMA_ERROR_QUEUE_FULL = 1, - UDMA_ERROR_BAD_DESC = 2, - UDMA_ERROR_DRAM_CROSSING = 3, - UDMA_ERROR_PIF_ADDR_BUS = 4, - UDMA_ERROR_PIF_DATA_BUS = 5, - UDMA_REQ_PENDING = 6, - UDMA_REQ_DONE = 7, - UDMA_ERROR_BAD_REQUEST = 8, - UDMA_ERROR_INVALID_ARG = 11, - UDMA_ERROR_INIT = 12, - UDMA_ERROR_INTERNAL = -1 -} udma_status_t; - -#ifndef __UDMA_INTERNAL_H__ -/* Opaque structure describing a uDMA descriptor */ -struct udma_desc_struct { - char _[UDMA_DESC_STRUCT_SIZE]; -} __attribute__ ((aligned (UDMA_DESC_STRUCT_SIZE))); -#endif - -typedef struct udma_desc_struct udma_desc_t; - -/* Initialize the udma control structure, the uDMA registers with - * the descriptor queue addresses, and the uDMA sync and error interrupt - * handler. This function needs to be invoked prior to using the uDMA. - * - * xmp_udma_sync_intr : Processor interrupt number to flag udma done - * xmp_udma_error_intr : Processor interrupt number to flag udma error - * - * Returns UDMA_ERROR_INIT if there was an error during initialization else - * returns UDMA_OK. - */ -extern udma_status_t -udma_init(uint32_t xmp_udma_sync_intr, uint32_t xmp_udma_error_intr); - -/* Performs a copy of a linear block of size bytes from the src - * to the dest address. If the call returns UDMA_OK, status is set to - * UDMA_REQ_PENDING or UDMA_REQ_DONE. If there is a dma error, the error code, - * which could be one of UDMA_ERROR_BAD_DESC, UDMA_ERROR_DRAM_CROSSING, - * UDMA_ERROR_PIF_ADDR_BUS, UDMA_ERROR_PIF_DATA_BUS is returned in the status. - * Status is set to UDMA_REQ_DONE if the dma completes normally. - * On completion, the callback function is invoked with the callback_data - * and status as parameters. Note, the callback is always invoked even if - * there is a dma error. - * - * src : src address of the copy - * dest : dest address of the copy - * size : number of bytes to copy - * callback_data : optional data to be passed to callback_func - * callback_func : optional callback after copy is done - * request_attr : attribute defining how to process this request - * (see description of the request attribute in top of udma.h) - * status : track status of the copy; this gets also passed - * as the second argument to the callback_func - * - * Returns UDMA_ERROR_QUEUE_FULL if no more requests can be added, else - * returns UDMA_OK. - */ -extern udma_status_t -udma_copy(void *dest, - void *src, - size_t size, - void *callback_data, - void (*callback_func)(void *, udma_status_t *status), - uint32_t request_attr, - udma_status_t *status); - -/* Performs a copy of a 2D block of data from the src to the dest - * address. If the call returns UDMA_OK, status is set to UDMA_REQ_PENDING or - * UDMA_REQ_DONE. If there is a dma error, the error code, - * which could be one of UDMA_ERROR_BAD_DESC, UDMA_ERROR_DRAM_CROSSING, - * UDMA_ERROR_PIF_ADDR_BUS, UDMA_ERROR_PIF_DATA_BUS is returned in the status. - * Status is set to UDMA_REQ_DONE if the dma completes normally. - * On completion, the callback function is invoked with the callback_data - * and status as parameters. Note, the callback is always invoked even if - * there is a dma error. - * - * src : src address of the copy - * dest : dest address of the copy - * row_size : number of bytes per row to copy - * num_rows : number of rows to copy - * src_pitch : src pitch - * dest_pitch : dest pitch - * callback_data : optional data to be passed to callback_func - * callback_func : optional callback after copy is done - * request_attr : attribute defining how to process this request - * (see description of the request attribute in top of udma.h) - * status : track status of the copy; this gets also passed - * as the second argument to the callback_func - * - * Returns UDMA_ERROR_QUEUE_FULL if no more requests can be added, else - * returns UDMA_OK. - */ -extern udma_status_t -udma_2d_copy(void *dest, - void *src, - size_t row_size, - uint32_t num_rows, - uint32_t src_pitch, - uint32_t dest_pitch, - void *callback_data, - void (*callback_func)(void *, udma_status_t *status), - uint32_t request_attr, - udma_status_t *status); - -/* Process requests that are done. Any callbacks associated - * with the completed requests gets invoked. If there are any errors, - * the error request is (and any pending request based on the request attribute) - * cancelled and the error code is returned in the status associated with - * all such cancelled requests. Callbacks associated with the cancelled - * requests are also invoked. If all requests terminate normally, the status - * of the completed requests are set to UDMA_REQ_DONE. - * - * Returns void - */ -extern void -udma_process_requests(); - -/* Sets the udma max PIF block size - * - * max_block_size : max block size to be set - * - * Returns UDMA_ERROR_INVALID_ARG if block_size is > 3, else returns UDMA_OK - */ -udma_status_t -udma_set_max_block_size(uint32_t block_size); - -/* Sets the udma max outstanding PIF requests - * - * max_outstanding : max outstanding PIF requests - * - * Returns UDMA_ERROR_INVALID_ARG if max_outstanding is not between 1 and 16 - * else returns UDMA_OK - */ -udma_status_t -udma_set_max_outstanding(uint32_t max_outstanding); - -/* Initialize a uDMA descriptor using the copy parameters. The descriptor - * is then queued separately using udma_add_desc - * - * src : src address of the copy - * dest : dest address of the copy - * row_size : number of bytes per row to copy - * num_rows : number of rows to copy - * src_pitch : src pitch - * dest_pitch : dest pitch - * notify_with_interrupt : If 1, interrupt when dma is done with this descriptor - * if 0, do nothing, else undefined - * - * Returns void - */ -extern void -udma_set_desc(void *src, - void *dest, - size_t row_size, - uint32_t num_rows, - uint32_t src_pitch, - uint32_t dest_pitch, - uint32_t notify_with_interrupt, - udma_desc_t *desc); - -/* Add multiple uDMA descriptors to the descriptor queue. If the call returns - * UDMA_OK, the status is set to UDMA_REQ_PENDING or UDMA_REQ_DONE. - * If there is a dma error, the error code, which could be one of - * UDMA_ERROR_BAD_DESC, UDMA_ERROR_DRAM_CROSSING, UDMA_ERROR_PIF_ADDR_BUS, - * UDMA_ERROR_PIF_DATA_BUS is returned in the status. Status is set - * to UDMA_REQ_DONE, if the dma completes normally. - * On completion, the callback function is invoked with the callback_data - * and status as parameters. Note, the callback is always invoked even if - * there is a dma error. - * - * desc : descriptors to be added - * num_desc : number of descriptors to be added - * callback_data : optional data to be passed to callback_func - * callback_func : optional callback after copy is done - * request_attr : attribute defining how to process this request - * (see description of the request attribute in top of udma.h) - * Note, bit 0 (for enabling interrupt) is ignored in this call. - * To interrupt on dma completion, set the - * notify_with_interrupt parameter when creating descriptors - * using udma_set_desc. - * status : track status of the copy; this gets also passed - * as the second argument to the callback_func - * - * Returns UDMA_ERROR_QUEUE_FULL if no more descriptors can be added, - * UDMA_ERROR_INVALID_ARG if num_descs == 0, else return UDMA_OK - */ -udma_status_t -udma_add_descs(udma_desc_t *descs, - uint32_t num_descs, - void *callback_data, - void (*callback_func)(void *, udma_status_t *status), - uint32_t request_attr, - udma_status_t *status); - -/* Wait for udma copy request to complete. Could spin wait or goto waiti - * based on the sleep_wait parameter. Once the request is done, the callback - * associated with this request and any prior completed requests are handled. - * Error code, if any, is returned in the status s, else s is set to - * UDMA_REQ_DONE. - * - * s : status to wait for - * sleep_wait : sleep wait if true, else spin waits - * - * Returns void - */ -extern void -udma_wait_request(volatile udma_status_t *s, uint32_t sleep_wait); - -/* Inlined function to set the src, dest address of the descriptor - * - * src : src address of the uDMA - * dest : dest address of the uDMA - * desc : descriptor to be modified - * - * Returns void - */ -void static inline -udma_set_desc_addrs(void *src, void *dest, udma_desc_t *desc) { - uint32_t *d = (uint32_t *)desc; - *d = (uintptr_t)src; - *(d+1) = (uintptr_t)dest; -} - -/* Sets the number of retries for a failed dma request - * - * max_retries : max number of retries - * - * Sets the max number of retries for a failed dma request. The default is 0, - * i.e, no retries - */ -void -udma_set_max_retries(uint32_t max_retries); - -#ifdef __cplusplus -} -#endif - -#endif /* __UDMA_H__ */ diff --git a/components/esp32/include/xtensa/xmon.h b/components/esp32/include/xtensa/xmon.h deleted file mode 100644 index 12a757a2c1..0000000000 --- a/components/esp32/include/xtensa/xmon.h +++ /dev/null @@ -1,97 +0,0 @@ -/* xmon.h - XMON definitions - * - * $Id: //depot/rel/Eaglenest/Xtensa/OS/xmon/xmon.h#3 $ - * - * Copyright (c) 2001-2013 Tensilica 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. - */ - -#ifndef __H_XMON -#define __H_XMON - -/* Default GDB packet size */ -#define GDB_PKT_SIZE 4096 - -/*XMON signals */ -#define XMON_SIGINT 2 /*target was interrupted */ -#define XMON_SIGILL 4 /*illegal instruction */ -#define XMON_SIGTRAP 5 /*general exception */ -#define XMON_SIGSEGV 11 /*page faults */ - - -/* Type of log message from XMON to the application */ -typedef enum { - XMON_LOG, - XMON_TRACE, - XMON_ERR, - XMON_APP, - XMON_GDB -} xmon_log_t; - -/* Return value type for xmon_proc() (see below) */ -typedef enum { - XMON_GDB_PEND, - XMON_GDB_PKT, - XMON_NOT_GDB -} xmon_gdb_pkt_t; - -#ifdef _cplusplus -extern "C" { -#endif - -/* - * THE FOLLOWING ROUTINES ARE USED BY USER - */ -extern int _xmon_init(char* gdbBuf, int gdbPktSize, - void(*xlog)(xmon_log_t type, const char* str)); -//Initialize GDB communication and logging to the main app. -//For the logging to work, xlog function needs to be provided. -//gdbBuf - pointer to a buffer XMON can use to comm. with GDB -//gdbPktSize - Size of the allocated buffer for GDB communication. -//xlog - logger handle. - - -extern void _xmon_close(void); -//Main application can detach from xmon at any time - - -extern xmon_gdb_pkt_t _xmon_proc(char); -// Give character to XMON to check if GDB message -// Application is supposed to accumulate all the -// character in case the recognition fails and chars -// have to be sent to the original handler -// Return: XMON_GDB_PEND - send me more chars -// XMON_GDB_PKT - GDB message confirmed, C) not -// XMON_NOT_GDB - not GDB message - - -/* - * THE FOLLOWING ROUTINES NEED TO BE PROVIDED BY USER - */ -extern int _xmon_in(); // wait for character from GDB -extern void _xmon_out(char); // output a character to GDB -extern int _xmon_flush(void); // flush output characters - -#ifdef _cplusplus -} -#endif - -#endif diff --git a/components/esp32/include/xtensa/xmp-library.h b/components/esp32/include/xtensa/xmp-library.h deleted file mode 100644 index 624272077c..0000000000 --- a/components/esp32/include/xtensa/xmp-library.h +++ /dev/null @@ -1,789 +0,0 @@ -/* Customer ID=11656; Build=0x5f626; Copyright (c) 2008-2009 by Tensilica Inc. ALL RIGHTS RESERVED. - These coded instructions, statements, and computer programs are the - copyrighted works and confidential proprietary information of Tensilica Inc. - They may not be modified, copied, reproduced, distributed, or disclosed to - third parties in any manner, medium, or form, in whole or in part, without - the prior written consent of Tensilica Inc. */ - -#ifndef _XMP_LIBRARY_H -#define _XMP_LIBRARY_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include -#include -#if XCHAL_HAVE_RELEASE_SYNC -#include -#endif -#if XCHAL_HAVE_EXTERN_REGS -#include -#endif -#include -#include - -#include "xtensa/system/mpsystem.h" - -/* - W A R N I N G: - - xmp library clients should treat all data structures in this file - as opaque. They are only public to enable users to declare them - statically. -*/ - - -/* ------------------------------------------------------------------------- - When using XMP on cache-incoherent systems, these macros are helpful - to ensure that you are not reading stale data, and to ensure that - the data you write makes it all the way back to main memory. - */ - -#if !XCHAL_DCACHE_IS_COHERENT -#define XMP_WRITE_BACK_ELEMENT(x) xthal_dcache_region_writeback((void *)x, sizeof(*x)) -#define XMP_INVALIDATE_ELEMENT(x) xthal_dcache_region_invalidate((void *)x, sizeof(*x)) -#define XMP_WRITE_BACK_INVALIDATE_ELEMENT(x) xthal_dcache_region_writeback_inv((void *)x, sizeof(*x)) -#define XMP_WRITE_BACK_ARRAY(x) xthal_dcache_region_writeback((void *)x, sizeof(x)) -#define XMP_INVALIDATE_ARRAY(x) xthal_dcache_region_invalidate((void *)x, sizeof(x)) -#define XMP_WRITE_BACK_INVALIDATE_ARRAY(x) xthal_dcache_region_writeback_inv((void *)x, sizeof(x)) -#define XMP_WRITE_BACK_ARRAY_ELEMENTS(x, num_elements) xthal_dcache_region_writeback((void *)x, sizeof(*x) * num_elements) -#define XMP_INVALIDATE_ARRAY_ELEMENTS(x, num_elements) xthal_dcache_region_invalidate((void *)x, sizeof(*x) * num_elements) -#define XMP_WRITE_BACK_INVALIDATE_ARRAY_ELEMENTS(x, num_elements) xthal_dcache_region_writeback_inv((void *)x, sizeof(*x) * num_elements) -#else -#define XMP_WRITE_BACK_ELEMENT(x) -#define XMP_INVALIDATE_ELEMENT(x) -#define XMP_WRITE_BACK_INVALIDATE_ELEMENT(x) -#define XMP_WRITE_BACK_ARRAY(x) -#define XMP_INVALIDATE_ARRAY(x) -#define XMP_WRITE_BACK_INVALIDATE_ARRAY(x) -#define XMP_WRITE_BACK_ARRAY_ELEMENTS(x, num_elements) -#define XMP_INVALIDATE_ARRAY_ELEMENTS(x, num_elements) -#define XMP_WRITE_BACK_INVALIDATE_ARRAY_ELEMENTS(x, num_elements) -#endif - -/* ------------------------------------------------------------------------- - Initialization, error codes, constants and house-keeping - - Every core should call xmp_init with the number of cores in the - system. - - xmp_init should be called before you use any global synchronization - primitive or shared data. - - Further, before you use a dynamically allocated synchronization - primitives, you need to both initialize it by calling the - xmp_*_init function, and you need to have called xmp_init, which - sets up interrupt handlers and interrupt routing. - - The second parameter sets the interprocessor interrupt - routing. Passing zero instructs the library to use the default - routing, which will be suitable for most users. - -*/ - -extern void xmp_init (int num_cores, unsigned int interrupt_routing); - - -/* If you want finer-grained control than that provided by xmp_init, - you can the functions below individually--however, this is more - inconvenient and requires greater understanding of the library's - internals. Don't use them directly unless you have a good reason. -*/ - -extern void xmp_unpack_shared (void); -extern void xmp_route_interrupts (unsigned int routing); - -#if XCHAL_HAVE_MP_INTERRUPTS -extern void xmp_enable_ipi_interrupts (void); - -/* Turn off certain things enabled by xmp_init */ -extern void xmp_disable_ipi_interrupts (void); -#endif - -extern void xmp_end (void); - -/* Only valid after xmp_init. */ -extern int xmp_num_cores (void); - -/* How many cycles should a core wait before rechecking a - synchronization variable? Higher values will reduce memory - transactions, but will also result in higher latency in returning - from synchronization. -*/ -extern void xmp_spin_wait_set_cycles (unsigned int limit); - -/* If you would prefer to provide your own spin wait function, - to go to sleep, etc. Declare a function of this type, then call - this function. */ -typedef void (*xmp_spin_wait_function_t)(void); -extern void xmp_spin_wait_set_function (xmp_spin_wait_function_t func); -extern void xmp_spin(void); - -#define XMP_NO_OWNER 0x07 -#define XMP_MUTEX_DESTROYED 0xFE -#define XMP_ERROR_FATAL 0xFD - -#define XMP_MAX_CORES 0x4 - - -static inline unsigned int xmp_prid (void) -{ -#if XCHAL_HAVE_PRID - return XT_RSR_PRID() & 0xFF; -#else - return 0; -#endif -} - - -/* ------------------------------------------------------------------------- - Tracing - - A core must set a trace_file if it wants any synchronization - tracing to occur. Sharing file descriptors among cores is very - messy, so don't do it. This, unfortunately, means that two cores - contending for a mutex are not able to trace to the same file. - - Any object (except the atomic integer) can have tracing off or on. -*/ - -extern void xmp_set_trace_file (FILE * file); -extern void xmp_trace (const char * fmt, ...); - - -/* ------------------------------------------------------------------------- - Memory Allocation Functions. - - These do what you would expect, only from shared memory instead of - private memory. -*/ - -#if XCHAL_DCACHE_IS_COHERENT -extern void * xmp_malloc (size_t size); -extern void * xmp_calloc (size_t nmemb, size_t size); -extern void xmp_free (void * ptr); -#endif -extern void * xmp_sbrk(int size); - -/* ------------------------------------------------------------------------- - xmp_atomic_int_t - - The most basic synchronization primitive in the xmp library. - Atomic ints are sharable among processors, and even interrupt - levels on the same processor. However, their semantics are fairly - rudimentary. All other primitives are based on these, therefore, - changing this implementation affects all other primitives. - -*/ - -typedef unsigned int xmp_atomic_int_t; - -static inline xmp_atomic_int_t -xmp_coherent_l32ai(xmp_atomic_int_t * address) -{ - XMP_INVALIDATE_ELEMENT (address); - return XT_L32AI(address, 0); -} - -static inline void -xmp_coherent_s32ri(xmp_atomic_int_t value, xmp_atomic_int_t * address) -{ - XT_S32RI (value, address, 0); - XMP_WRITE_BACK_ELEMENT (address); -} - -#define XMP_ATOMIC_INT_INITIALIZER(value) (value) - -/* xmp_atomic_int_init - Initialize an int prior to use - - Nonsynchronizing, Nonblocking - - Usage: - value - initial value - integer - points to an uninitialized integer - - On exit: - initialized to given value - - Errors: none -*/ - -static inline void -xmp_atomic_int_init (xmp_atomic_int_t * integer, int value) -{ - xmp_coherent_s32ri (value, integer); -} - - -/* xmp_atomic_int_value - Read the value - - Nonsynchronizing, Nonblocking - - Usage: - integer - points to an int - - Returns: - the value -*/ - -static inline int -xmp_atomic_int_value (xmp_atomic_int_t * integer) -{ - return xmp_coherent_l32ai (integer); -} - - -/* xmp_atomic_int_conditional_increment - Conditionally increment integer - - Synchronizing, nonblocking - - Usage: - integer - points to an initialized integer - amount - how much to increment - prev - believed value of the integer - eg: prev = xmp_atomic_int_value (integer); - success = xmp_atomic_int_increment (integer, 1, prev); - - Returns: current value of integer - user should check if it matches - the previous value of the integer. If it does, then the update - was successful. - -*/ - -#define USE_ASSEMBLY_IMPLEMENTATION 0 - -static inline int -xmp_atomic_int_conditional_increment (xmp_atomic_int_t * integer, int amount, int prev) -{ - int val; - int saved; - -#if USE_ASSEMBLY_IMPLEMENTATION - /* %0 = prev - %1 = saved - %2 = atomic integer pointer - %3 = amount - */ - - asm volatile ("wsr.scompare1 %0\n" - "mov %1, %0\n" - "add %0, %0, %3\n" - "s32c1i %0, %2, 0\n" - : "+&a" (prev), "+&a"(saved) : "a" (integer), "a" (amount)); - - return prev; - -#else - - XT_WSR_SCOMPARE1 (prev); - val = prev + amount; - saved = val; - XT_S32C1I (val, integer, 0); - - return val; -#endif -} - - -/* xmp_atomic_int_increment - Increment integer - - Synchronizing, blocking - - Usage: - integer - points to an initialized integer - amount - how much to increment - - Returns: new value of integer - -*/ - -static inline int -xmp_atomic_int_increment (xmp_atomic_int_t * integer, int amount) -{ - int val; - int saved; -#if USE_ASSEMBLY_IMPLEMENTATION - /* %0 = val - %1 = saved - %2 = atomic integer pointer - %3 = amount - */ - - asm volatile ("l32ai %0, %2, 0\n" - "1:\n" - "wsr.scompare1 %0\n" - "mov %1, %0\n" - "add %0, %0, %3\n" - "s32c1i %0, %2, 0\n" - "bne %0, %1, 1b\n" - : "+&a" (val), "+&a"(saved) : "a" (integer), "a" (amount)); -#else - /* Accurately naming "val" is tricky. Sometimes it will be what we - want to be the new value, but sometimes it contains the value - that is currently at the location. */ - - /* Load location's current value */ - val = xmp_coherent_l32ai (integer); - - do { - XT_WSR_SCOMPARE1 (val); - saved = val; - /* Change it to what we would like to store there--"new_val" */ - val = val + amount; - /* Possibly store new_val, but reload location's current value no - matter what. */ - XT_S32C1I (val, integer, 0); - if (val != saved) - xmp_spin(); - } while (val != saved); - -#endif - return val + amount; -} - - -/* xmp_atomic_int_conditional_set - Set the value of an atomic integer - - Synchronizing, nonblocking - - Usage: - integer - points to an initialized integer - from - believed value of the integer - eg: prev = xmp_atomic_int_value (integer); - success = xmp_atomic_int_conditional_set (integer, 1, prev); - to - new value - - Returns: current value of integer - user should check if it matches - the previous value of the integer. If it does, then the update - was successful. - -*/ - -static inline int -xmp_atomic_int_conditional_set (xmp_atomic_int_t * integer, int from, int to) -{ - int val; - - /* Don't even try to update if the integer's value isn't what we - think it should be. This prevents acquiring this cache-line for - writing and therefore prevents bus transactions when various - cores contend. */ - val = xmp_coherent_l32ai(integer); - if (val == from) { - XT_WSR_SCOMPARE1 (from); - val = to; - /* Possibly store to, but reload location's current value no - matter what. */ - XT_S32C1I (val, integer, 0); - } - return val; -} - - -/* Macros to implement trivial spin locks. These are very primitive, but - can be useful when you don't need the higher-overhead synchronization. - - To use an xmp_atomic_int_t as a trivial spin lock, you should - initialize it to zero first. -*/ - -#define XMP_SIMPLE_SPINLOCK_ACQUIRE(atomic_int_ptr) \ - { while (xmp_atomic_int_conditional_set (atomic_int_ptr, 0, xmp_prid() + 1) != 0) \ - xmp_spin(); } -#define XMP_SIMPLE_SPINLOCK_RELEASE(atomic_int_ptr) \ - { while (xmp_atomic_int_conditional_set (atomic_int_ptr, xmp_prid() + 1, 0) != xmp_prid() + 1) \ - xmp_spin(); } - -#define XMP_SIMPLE_SPINLOCK_OWNER(atomic_int_ptr) (xmp_atomic_int_value(atomic_int_ptr) - 1) - - -/* ------------------------------------------------------------------------- - xmp_mutex_t - An even higher-level data structure to enforce - mutual exclusion between cores. A core which waits on a mutex might - sleep with a waiti and be interrupted by an interrupt. - - Mutexes can be normal or recursive. For a normal mutex, a core - attempting to acquire a mutex it already holds will result in - deadlock. For a recursive mutex, a core will succeed in acquiring a - mutex it already holds, and must release it as many times as it - acquired it. - - Mutexes are not sharable between interrupt levels--because - ownership is tracked by core, not thread. - - Like all xmp data structures, an object of type xmp_mutex_t - should be treated by the programmer as opaque. They are only - public in this header file to allow them to be declared statically. - - For configurations with 16-byte cache lines, this has the most - frequently used and changed data in the first line. - -*/ - -#if XCHAL_DCACHE_IS_COHERENT -typedef struct xmp_mutex_t { - xmp_atomic_int_t qlock; - unsigned int qhead; - unsigned int qtail; - unsigned char queue[XMP_MAX_CORES]; - unsigned short held; - - unsigned char owner; - unsigned char recursive : 1; - unsigned char trace : 1; - unsigned char system : 1; - unsigned char unused : 5; - const char * name; -} xmp_mutex_t __attribute__ ((aligned (XMP_MAX_DCACHE_LINESIZE))); - - -#define XMP_MUTEX_INITIALIZER(name) \ - { 0, 0, -1, {XMP_NO_OWNER, XMP_NO_OWNER, XMP_NO_OWNER, XMP_NO_OWNER}, \ - 0, XMP_NO_OWNER, XMP_MUTEX_FLAG_NORMAL, 0, 0, 0, name } - -#define XMP_RECURSIVE_MUTEX_INITIALIZER(name) \ - { 0, 0, -1, {XMP_NO_OWNER, XMP_NO_OWNER, XMP_NO_OWNER, XMP_NO_OWNER}, \ - 0, XMP_NO_OWNER, XMP_MUTEX_FLAG_RECURSIVE, 0, 0, 0, name } - -#define XMP_MUTEX_FLAG_NORMAL 0 -#define XMP_MUTEX_FLAG_RECURSIVE 1 - -#define XMP_MUTEX_ACQUIRE_FAILED -1 -#define XMP_MUTEX_ERROR_DESTROY_OWNED -2 -#define XMP_MUTEX_ERROR_NOT_OWNED -3 -#define XMP_MUTEX_ERROR_ALREADY_OWNED -4 - -/* - xmp_mutex_init - - Nonsynchronizing - Nonblocking - - Usage: - mutex - points to an uninitialized mutex - name - name if you want one, NULL if not. - recursive - use recursive semantices - - Returns - zero on success (always succeeds) - -*/ - -extern int xmp_mutex_init (xmp_mutex_t * mutex, - const char * name, - unsigned int recursive); - -/* - int xmp_mutex_destroy (xmp_mutex_t * mutex); - - Synchronizing - will fail if mutex is held by anyone -- including - current processor - Nonblocking - - Usage: - mutex - points to a mutex - - Returns - zero on success - non-zero if mutex is held -*/ - -extern int xmp_mutex_destroy (xmp_mutex_t * mutex); - - -/* - xmp_mutex_lock -- Synchronizing - xmp_mutex_trylock - - Usage: - mutex - points to a mutex - - Returns - zero on success -*/ - -extern int xmp_mutex_lock (xmp_mutex_t * mutex); -extern int xmp_mutex_trylock (xmp_mutex_t * mutex); - - -/* - xmp_mutex_unlock - - Synchronizing - Nonblocking - - Usage: - mutex - points to a mutex - - Returns - zero on success - mutex is released - non-zero on failure - mutex is owned by another core - - prid of processor that does own it - note that by the time this function - returns, the owner of the core may - have changed. -*/ - -extern int xmp_mutex_unlock (xmp_mutex_t * mutex); - - -/* - xmp_mutex_name - - Nonsynchronizing - Nonblocking - - Usage: - mutex - points to a mutex - - Returns the name of the given mutex, which may be NULL. - -*/ - -const char * xmp_mutex_name (const xmp_mutex_t * mutex); - - -/* - xmp_mutex_trace_on - xmp_mutex_trace_off - - Nonsynchronizing - Nonblocking - - Turn off and on tracing for the mutex. - - These functions are only present in the debug version of the library. -*/ - -extern void xmp_mutex_trace_on (xmp_mutex_t * mutex); -extern void xmp_mutex_trace_off (xmp_mutex_t * mutex); - - -/* ------------------------------------------------------------------------- - xmp_condition_t - - Condition Variables following Mesa semantics. - - Condition variables are not sharable among interrupt levels. - -*/ - - -typedef struct xmp_condition_t { - unsigned int qhead; - unsigned int qtail; - unsigned char queue[XMP_MAX_CORES]; - unsigned int waiting[XMP_MAX_CORES]; - - unsigned char trace : 1; - unsigned char unused : 7; - const char * name; -} xmp_condition_t __attribute__ ((aligned (XMP_MAX_DCACHE_LINESIZE))); - - -#define XMP_CONDITION_INITIALIZER(name) \ - { 0, -1, {XMP_NO_OWNER, XMP_NO_OWNER, XMP_NO_OWNER, XMP_NO_OWNER}, \ - {0, 0, 0, 0}, 0, 0, name} - - -/* xmp_condition_init - Initialize a condition variable - - Nonsynchronizing, Nonblocking - - Usage: - condition - pointer to an xmp_condition_t - - On exit: - condition initialized - - Errors: none -*/ - -extern int xmp_condition_init (xmp_condition_t * condition, - const char * name); -extern int xmp_condition_destroy (xmp_condition_t * condition); - - -/* xmp_condition_wait - Wait for a condition variable - - Synchronizing, blocking - - Usage: - condition - pointer to an xmp_condition_t - mutex - pointer to an xmp_mutex_t already acquired by the calling - process - - Errors: if the mutex isn't held by this core -*/ - -extern int xmp_condition_wait (xmp_condition_t * condition, - xmp_mutex_t * mutex); - -/* xmp_condition_signal - - - Signal the first (if any) core waiting on a condition variable - - You must hold the mutex you passed to xmp_condition_wait before - calling this function. - - Synchronizing, nonblocking - - Usage: - condition - pointer to an xmp_condition_t - - Errors: none -*/ - -extern int xmp_condition_signal (xmp_condition_t * condition); - - -/* xmp_condition_broadcast - - - Signal all cores waiting on a condition variable - - Synchronizing, nonblocking - - You must hold the mutex you passed to xmp_condition_wait before - calling this function. - - Usage: - condition - pointer to an xmp_condition_t - - Errors: none -*/ - -extern int xmp_condition_broadcast (xmp_condition_t * condition); - - -static inline const char * xmp_condition_name (const xmp_condition_t * condition) -{ - return condition->name; -} - -/* - xmp_condition_trace_on - xmp_condition_trace_off - - Nonsynchronizing - Nonblocking - - Turn off and on statistics and tracing for the condition. For - tracing you must also set a trace file for the core. - - These functions are only present in the debug-version of the library. -*/ - -extern void xmp_condition_trace_on (xmp_condition_t * condition); -extern void xmp_condition_trace_off (xmp_condition_t * condition); - -#endif /* XCHAL_DCACHE_IS_COHERENT */ - -/* ------------------------------------------------------------------------- - xmp_barrier_t - - Classic barriers that stop any core from continuing until a - specified number of cores reach that point. Once the barrier allows - cores through, the barrier is reset and will stop cores from - progressing again. - - Barriers are not sharable among interrupt levels. - -*/ - - -typedef struct xmp_barrier_t -{ - xmp_atomic_int_t count; - xmp_atomic_int_t state; - xmp_atomic_int_t sleeping; - unsigned short num_cores; - unsigned short trace : 1; - unsigned short system : 1; - const char * name; -} xmp_barrier_t __attribute__ ((aligned (XMP_MAX_DCACHE_LINESIZE))); - -#define XMP_BARRIER_INITIALIZER(number, name) \ - { 0, 0, 0, number, 0, 0, name } - - -/* xmp_barrier_init - Initialize a barrier - - Nonsynchronizing, Nonblocking - - Usage: - barrier - pointer to an xmp_barrier_t - num_cores - number of cores needed to arrive at the - barrier before any are allowed through - On exit: - barrier initialized - - Always returns zero. - - Errors: none -*/ - -extern int xmp_barrier_init (xmp_barrier_t * barrier, int num_cores, - const char * name); - - -/* xmp_barrier_wait - Wait on a barrier - - Nonsynchronizing, Nonblocking - - Usage: - barrier - pointer to an xmp_barrier_t - On exit: - Enough cores (as determined at the barrier's initialization) - have reached the barrier. - - Errors: none -*/ - -extern int xmp_barrier_wait (xmp_barrier_t * barrier); - - -static inline const char * xmp_barrier_name (const xmp_barrier_t * barrier) -{ - return barrier->name; -} - - -/* - xmp_barrier_trace_on - xmp_barrier_trace_off - - Nonsynchronizing - Nonblocking - - Turn on and off tracing for the barrier. For - tracing you must also set a trace file for the core. - - These functions are only present in the debug-version of the library. -*/ - -extern void xmp_barrier_trace_on (xmp_barrier_t * barrier); -extern void xmp_barrier_trace_off (xmp_barrier_t * barrier); - - -/* ------------------------------------------------------------------------- - Portions of the library that are internal, but belong here for - convenience. -*/ - -extern xmp_atomic_int_t _ResetSync; - -static inline void -xmp_initial_sync (int num_cores) -{ - xmp_atomic_int_increment (&_ResetSync, 1); - while (xmp_coherent_l32ai (&_ResetSync) != num_cores) - xmp_spin (); -} - -#ifdef __cplusplus -} -#endif - -#endif /* _XMP_LIBRARY_H */ diff --git a/components/esp32/include/xtensa/xos.h b/components/esp32/include/xtensa/xos.h deleted file mode 100644 index 883a9c975a..0000000000 --- a/components/esp32/include/xtensa/xos.h +++ /dev/null @@ -1,524 +0,0 @@ -/** @file */ - -// xos.h - XOS API interface and data structures visible to user code. - -// 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. - - -#ifndef __XOS_H__ -#define __XOS_H__ - -#ifdef __cplusplus -extern "C" { -#endif - - -#include "xos_types.h" - -#include -#if XCHAL_HAVE_INTERRUPTS -#include -#include -#endif - -#include "xos_common.h" -#include "xos_errors.h" -#include "xos_regaccess.h" - - -//----------------------------------------------------------------------------- -// Convert x into a literal string. -//----------------------------------------------------------------------------- -#define _XOS_STR(x) __XOS_STR(x) -#define __XOS_STR(x) #x - - -//----------------------------------------------------------------------------- -// XOS version. -//----------------------------------------------------------------------------- -#define XOS_VERSION_MAJOR 1 -#define XOS_VERSION_MINOR 10 -#define XOS_VERSION_STRING "1.10" ///< XOS version string. - - -//----------------------------------------------------------------------------- -// Runtime error handling. -//----------------------------------------------------------------------------- - - -//----------------------------------------------------------------------------- -/// -/// Reports a fatal error and halts XOS operation, i.e. halts the system. This -/// function will call a user-registered error handler (if one has been set) -/// and then halt the system. The user handler may do system-specific things -/// such as record the error reason in nonvolatile memory etc. -/// -/// \param errcode Error code. May be any user defined value < 0. -/// Values >=0 are reserved for use by the system. -/// -/// \param errmsg Optional text string describing the error. -/// -/// \return This function does not return. -/// -//----------------------------------------------------------------------------- -void -xos_fatal_error(int32_t errcode, const char * errmsg); - - -#if XOS_DEBUG - -// Do not call directly. -void -xos_assert(const char * file, int32_t line); - -//----------------------------------------------------------------------------- -/// -/// Check condition and fail if condition expression is false. -/// In debug builds, an assertion failure will cause a fatal error to be -/// reported. In non-debug builds, assertions are compiled out. -/// -/// NOTE: Remember that any code in XOS_ASSERT() statements gets compiled out -/// for non-debug builds. -/// -//----------------------------------------------------------------------------- - -#define XOS_ASSERT(expr) if ((expr) == 0) xos_assert(__FILE__, __LINE__) - -#else - -#define XOS_ASSERT(expr) - -#endif - - -//----------------------------------------------------------------------------- -/// -/// Interrupt handler function pointer type. -/// -//----------------------------------------------------------------------------- -typedef void (XosIntFunc)(void * arg); - -//----------------------------------------------------------------------------- -/// -/// Print handler function pointer type. -/// -//----------------------------------------------------------------------------- -typedef int32_t (XosPrintFunc)(void * arg, const char * fmt, ...); - -//----------------------------------------------------------------------------- -/// -/// Fatal error handler function pointer type. -/// -//----------------------------------------------------------------------------- -typedef void (XosFatalErrFunc)(int32_t errcode, const char * errmsg); - -//----------------------------------------------------------------------------- -/// -/// Exception handler function pointer type. -/// -//----------------------------------------------------------------------------- -typedef void (XosExcHandlerFunc)(XosExcFrame * frame); - - -//----------------------------------------------------------------------------- -/// -/// Install a user defined exception handler for the specified exception type. -/// This will override the default XOS exception handler. The handler is a C -/// function that is passed one parameter -- a pointer to the exception frame. -/// The exception frame is allocated on the stack of the thread that caused the -/// exception, and contains saved state and exception information. For details -/// of the exception frame see the structure XosExcFrame. -/// -/// \param exc Exception type (number) to override. The exception -/// numbers are enumerated in . -/// -/// \param handler Pointer to handler function to be installed. -/// To revert to the default handler, pass NULL. -/// -/// \return Returns a pointer to previous handler installed, if any. -/// -//----------------------------------------------------------------------------- -XosExcHandlerFunc * -xos_register_exception_handler(int32_t exc, XosExcHandlerFunc * handler); - - -//----------------------------------------------------------------------------- -/// -/// Install a user defined fatal error handler. This function will be called if -/// a fatal error is reported either by user code or by XOS itself. It will be -/// passed the same arguments that are passed to xos_fatal_error(). -/// -/// The handler need not return. It should make minimal assumptions about the -/// state of the system. In particular, it should not assume that further XOS -/// system calls will succeed. -/// -/// \param handler Pointer to handler function to be installed. -/// -/// \return Returns a pointer to previous handler installed, if any. -/// -//----------------------------------------------------------------------------- -XosFatalErrFunc * -xos_register_fatal_error_handler(XosFatalErrFunc * handler); - - -#ifdef _XOS_INCLUDE_INTERNAL_ -# include "xos_internal.h" -#endif - - -#include "xos_thread.h" -#include "xos_timer.h" -#include "xos_cond.h" -#include "xos_event.h" -#include "xos_mutex.h" -#include "xos_msgq.h" -#include "xos_semaphore.h" -#include "xos_stopwatch.h" - - -//----------------------------------------------------------------------------- -/// -/// Register a handler function to call when interrupt "num" occurs. -/// -/// For level-triggered and timer interrupts, the handler function will have -/// to clear the source of the interrupt before returning, to avoid infinitely -/// retaking the interrupt. Edge-triggered and software interrupts are -/// automatically cleared by the OS interrupt dispatcher (see xos_handlers.S). -/// -/// \param num Xtensa internal interrupt number (0..31). To -/// refer to a specific external interrupt number -/// (BInterrupt pin), use HAL macro XCHAL_EXTINTx_NUM -/// where 'x' is the external number. -/// -/// \param handler Pointer to handler function. -/// -/// \param arg Argument passed to handler. -/// -/// \return Returns XOS_OK if successful, else error code. -/// -//----------------------------------------------------------------------------- -int32_t -xos_register_interrupt_handler(int32_t num, XosIntFunc * handler, void * arg); - - -//----------------------------------------------------------------------------- -/// -/// Unregister a handler function for interrupt "num". If no handler was -/// installed, this function will have no effect. -/// -/// \param num Xtensa internal interrupt number (0..31). To -/// refer to a specific external interrupt number -/// (BInterrupt pin), use HAL macro XCHAL_EXTINTx_NUM -/// where 'x' is the external number. -/// -/// \return Returns XOS_OK if successful, else error code. -/// -//----------------------------------------------------------------------------- -int32_t -xos_unregister_interrupt_handler(int32_t num); - - -//----------------------------------------------------------------------------- -/// -/// Register a high priority interrupt handler for interrupt level "level". -/// -/// Unlike low and medium priority interrupt handlers, high priority handlers -/// are not installed for a specific interrupt number, but for an interrupt -/// level. The level must be above XCHAL_EXCM_LEVEL. The handler function must -/// be written in assembly since C handlers are not supported for levels above -/// XCHAL_EXCM_LEVEL. The handler function must preserve all registers except -/// a0, and must return to the dispatcher via a "ret" instruction, not "rfi". -/// -/// NOTE: This method of dispatch takes a few cycles of overhead. If you wish -/// to save even these cycles, then you can define your own dispatch function -/// to override the built-in dispatcher. See xos_handlers.S for more details. -/// -/// \param level The interrupt level to be handled. -/// -/// \param handler Pointer to handler function. -/// -/// \return Returns XOS_OK if successful, else error code. -/// -//----------------------------------------------------------------------------- -int32_t -xos_register_hp_interrupt_handler(int32_t level, void * handler); - - -//----------------------------------------------------------------------------- -/// -/// Enable a specific interrupt, by interrupt number. -/// The state (enabled vs. disabled) of individual interrupts is global, i.e. -/// not associated with any specific thread. Depending on system options and -/// implementation, this state may be stored in one of two ways: -/// - directly in the INTENABLE register, or -/// - in a global variable (this is generally the case when INTENABLE is used -/// not just to control what interrupts are enabled globally, but also for -/// software interrupt prioritization within an interrupt level, effectively -/// providing finer grained levels; in this case XOS takes care to update -/// INTENABLE whenever either the global enabled-state variable or the -/// per-thread fine-grained-level variable change). -/// Thus it is best to never access the INTENABLE register directly. -/// -/// To modify thread-specific interrupt priority level, use one of: -/// - xos_set_int_pri_level() -/// - xos_restore_int_pri_level() -/// - xos_disable_interrupts() -/// - xos_restore_interrupts() -/// -/// NOTE: To refer to a specific external interrupt number (BInterrupt pin), -/// use HAL macro XCHAL_EXTINTx_NUM where 'x' is the external interrupt -/// number. For example, to enable external interrupt 3 (BInterrupt[3]), -/// you can use: -/// -/// xos_interrupt_enable( XCHAL_EXTINT3_NUM ); -/// -/// \param intnum Interrupt number to enable. Must range between 0-31. -/// -/// \return Returns nothing. -/// -//----------------------------------------------------------------------------- -void -xos_interrupt_enable(uint32_t intnum); - - -//----------------------------------------------------------------------------- -/// -/// Disable a specific individual interrupt, by interrupt number. -/// -/// This is the counterpart to xos_interrupt_enable(). See the description -/// of xos_interrupt_enable() for further comments and notes. -/// -/// \param intnum Interrupt number to disable. Must range between 0-31. -/// -/// \return Returns nothing. -/// -//----------------------------------------------------------------------------- -void -xos_interrupt_disable(uint32_t intnum); - - -//----------------------------------------------------------------------------- -/// -/// Get the CPU's current interrupt priority level. Interrupts at or below this -/// priority level are blocked. -/// -/// \return Returns the current IPL, ranging from 0 to XCHAL_NUM_INTLEVELS. -/// -//----------------------------------------------------------------------------- -static inline uint32_t -xos_get_int_pri_level(void) -{ -#if XCHAL_HAVE_INTERRUPTS - return XT_RSR_PS() & 0xF; -#else - return 0; -#endif -} - - -//----------------------------------------------------------------------------- -/// -/// Set the CPU's interrupt priority level to the specified level, but only if -/// the current IPL is below the one requested. This function will never cause -/// the interrupt priority level to be lowered from the current level. -/// Call this function to block interrupts at or below the specified priority -/// level. -/// -/// When setting the IPL temporarily (such as in a critical section), call -/// xos_set_int_pri_level(), execute the critical code section, and then call -/// xos_restore_int_pri_level(). -/// -/// The interrupt priority level is part of the thread context, so it is saved -/// and restored across context switches. To enable and disable individual -/// interrupts globally, use the functions xos_interrupt_enable() and -/// xos_interrupt_disable() instead. -/// -/// NOTE: It is usually not required to disable interrupts at a level higher -/// than that of the highest priority interrupt that interacts with the OS -/// (i.e. calls into XOS such that threads may be woken / blocked / -/// reprioritized / switched, or otherwise access XOS data structures). -/// In XOS, that maximum level is XOS_MAX_OS_INTLEVEL, which defaults to -/// XCHAL_EXCM_LEVEL. This may be modified by editing xos_params.h and -/// rebuilding XOS. -/// -/// \param level The new interrupt priority level (IPL). -/// -/// \return Returns a value that can be used to restore the previous -/// priority level by calling xos_restore_int_pri_level(). This -/// value should be treated as opaque by application code, and -/// should be passed unchanged to the restore function. -/// -//----------------------------------------------------------------------------- -__attribute__((always_inline)) -static inline uint32_t -xos_set_int_pri_level(uint32_t level) -{ -#if XCHAL_HAVE_INTERRUPTS -#pragma no_reorder - uint32_t ps = XT_RSR_PS(); - - if (level > (ps & 0xF)) { - level = (ps & ~0xF) | level; - XT_WSR_PS(level); - XT_RSYNC(); - } - - return ps; -#else - return 0; -#endif -} - - -//----------------------------------------------------------------------------- -/// -/// Restores the CPU to a previously saved interrupt priority level. This level -/// must have been obtained by calling xos_set_int_pri_level(). -/// -/// \param oldval Return value from xos_set_int_pri_level(). -/// -/// \return Returns nothing. -/// -//----------------------------------------------------------------------------- -__attribute__((always_inline)) -static inline void -xos_restore_int_pri_level(const uint32_t oldval) -{ -#if XCHAL_HAVE_INTERRUPTS -#pragma no_reorder - XT_WSR_PS(oldval); - XT_RSYNC(); -#else - // Nothing -#endif -} - - -//----------------------------------------------------------------------------- -/// -/// Disable all interrupts that can interact directly with the OS. This is a -/// convenience function, shorthand for setting the IPL to XOS_MAX_OS_INTLEVEL. -/// -/// Returns: A value that can be used to restore the previous priority level -/// by calling xos_restore_interrupts(). This value should be treated as -/// opaque by application code, and should be passed unchanged to the restore -/// function. -/// -//----------------------------------------------------------------------------- -static inline uint32_t -xos_disable_interrupts(void) -{ - return xos_set_int_pri_level(XOS_MAX_OS_INTLEVEL); -} - - -//----------------------------------------------------------------------------- -/// -/// Restore the CPU's previously saved interrupt status. This is a convenience -/// function, the counterpart to xos_disable_interrupts(). -/// -/// \return rval Return value from xos_disable_interrupts(). -/// -/// \return Returns nothing. -/// -//----------------------------------------------------------------------------- -static inline void -xos_restore_interrupts(uint32_t rval) -{ - xos_restore_int_pri_level(rval); -} - - -#ifdef _XOS_INCLUDE_INTERNAL_ - -//----------------------------------------------------------------------------- -// Enter an OS critical section, i.e. get exclusive access to OS critical -// state and data structures. Code that manipulates the state of OS objects -// or modifies internal OS state must call this function first, to ensure -// that it has exclusive access. On a single-core system, this is equivalent -// to blocking all interrupts that can interact directly with the OS, i.e. -// all interrupts at or below XOS_MAX_OS_INTLEVEL. In a multi-core system -// this is likely to be implemented differently to achieve the same effect. -// -// Returns: A value that is to be used to restore the state of the CPU when -// exiting the critical section. This must be treated as opaque and passed -// unmodified to xos_critical_exit(). -// -// NOTE: This function is meant for use in OS code, not in applications. -//----------------------------------------------------------------------------- -__attribute__((always_inline)) -static inline uint32_t -xos_critical_enter(void) -{ -#if XCHAL_HAVE_INTERRUPTS - // This function cannot be called by high-level interrupt handlers, - // i.e. it can never be called with intlevel > XOS_MAX_OS_INTLEVEL. - // So, we do not need to check current intlevel because we will not - // ever be lowering it by setting it to XOS_MAX_OS_INTLEVEL. - // NOTE: sync after RSIL not needed. - return XT_RSIL(XOS_MAX_OS_INTLEVEL); -#else - return 0; -#endif -} - - -//----------------------------------------------------------------------------- -// Exit an OS critical section and restore CPU state. See the documentation -// for xos_critical_enter(). -// -// cflags Return value from xos_critical_enter(). -// Must be treated as an opaque value. -// -// Returns: Nothing. -// -// NOTE: This function is meant for use in OS code, not in applications. -//----------------------------------------------------------------------------- -__attribute__((always_inline)) -static inline void -xos_critical_exit(uint32_t cflags) -{ - xos_restore_int_pri_level(cflags); -} - -#endif // _XOS_INCLUDE_INTERNAL_ - - -// This file uses things defined above -#include "xos_syslog.h" - - -// Misc - -//----------------------------------------------------------------------------- -// Helper function to list all threads in system. Useful for debug. -//----------------------------------------------------------------------------- -void -xos_display_threads(void * arg, XosPrintFunc * print_fn); - - -#ifdef __cplusplus -} -#endif - -#endif // __XOS_H__ - diff --git a/components/esp32/include/xtensa/xos_common.h b/components/esp32/include/xtensa/xos_common.h deleted file mode 100644 index 647cb7f457..0000000000 --- a/components/esp32/include/xtensa/xos_common.h +++ /dev/null @@ -1,362 +0,0 @@ - -// xos_common.h - Macros and definitions common to C and assembly code. - -// 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. - - -#ifndef __XOS_COMMON_H__ -#define __XOS_COMMON_H__ - -#ifdef __cplusplus -extern "C" { -#endif - - -#include -#include -#include - -#include "xos_params.h" - - -//----------------------------------------------------------------------------- -// Macros that help define structures for both C and assembler. -// These are somewhat different from the XTOS version in xtruntime-frames.h. -//----------------------------------------------------------------------------- -#if defined(_ASMLANGUAGE) || defined(__ASSEMBLER__) - -#define STRUCT_BEGIN .pushsection .text; .struct 0 -#define STRUCT_FIELD(ctype,size,asname,name) asname: .space size -#define STRUCT_AFIELD(ctype,size,asname,name,n) asname: .space (size)*(n) -#define STRUCT_END(sname) sname##Size:; .popsection - -#else - -#define STRUCT_BEGIN typedef struct { -#define STRUCT_FIELD(ctype,size,asname,name) ctype name; -#define STRUCT_AFIELD(ctype,size,asname,name,n) ctype name[n]; -#define STRUCT_END(sname) } sname; - -#endif //_ASMLANGUAGE || __ASSEMBLER__ - - -//----------------------------------------------------------------------------- -// Offsets relative to xos_globals. -//----------------------------------------------------------------------------- -#define XOS_INTLEVEL_MASK 0 // offset to the level mask -#define XOS_INTENABLE_MASK 4 // offset to the enable mask -#define XOS_CURR_THREADPTR 8 // offset to the current thread ptr -#define XOS_NEXT_THREADPTR 12 // offset to the next thread ptr -#define XOS_INTERRUPT_TABLE 16 // offset to the interrupt table - - -//----------------------------------------------------------------------------- -// Offsets for xos_interrupt_table[] entries. -//----------------------------------------------------------------------------- -#define XOS_INTTAB_HANDLER (XOS_INTERRUPT_TABLE+0) // ofs to interrupt handler -#define XOS_INTTAB_ARG (XOS_INTERRUPT_TABLE+4) // ofs to interrupt handler arg -#define XOS_INTTAB_PS (XOS_INTERRUPT_TABLE+8) // (hwpri) PS for interrupt level -#define XOS_INTTAB_LEVEL (XOS_INTERRUPT_TABLE+8) // (swpri) interrupt level (1..7) -#define XOS_INTTAB_PRI (XOS_INTERRUPT_TABLE+9) // (swpri) interrupt priority (0..255) -#define XOS_INTTAB_PRIMASK (XOS_INTERRUPT_TABLE+12) // (swpri) mask of higher pri. interrupts - - -//----------------------------------------------------------------------------- -// Exception/interrupt stack frame layout for a pre-empted thread -// tcb->resume_fn == &xos_resume_preempted_thread). -// Pointed to by thread->esf. Located just below thread's current stack ptr. -// Thread's a1 == thread->esf + XosExcFrameSize. -// NOTE: exception frame size is a multiple of 16. -//----------------------------------------------------------------------------- -STRUCT_BEGIN -STRUCT_AFIELD(long,4,FRAME_AREG,areg, 12) // a4-a15 (offsets 0 thru 44) - // (a1 is computed, a0,a2-a3 are in s32e range of a1) -//#if XCHAL_HAVE_LOOPS -STRUCT_FIELD (long,4,FRAME_LBEG,lbeg) -STRUCT_FIELD (long,4,FRAME_LEND,lend) -STRUCT_FIELD (long,4,FRAME_LCOUNT,lcount) -//#endif -//#if XCHAL_HAVE_MAC16 -STRUCT_FIELD (long,4,FRAME_ACCLO,acclo) -STRUCT_FIELD (char,1,FRAME_ACCHI,acchi) -//#endif -STRUCT_FIELD (char,1,FRAME_SAR,sar) -STRUCT_FIELD (short,2,FRAME_PAD0,pad0) // unused -STRUCT_FIELD (long,4,FRAME_EXCCAUSE,exccause) -STRUCT_FIELD (long,4,FRAME_EXCVADDR,excvaddr) -STRUCT_FIELD (long,4,FRAME_PAD1,pad1) // unused -- pad to make multiple of 16 bytes -STRUCT_FIELD (long,4,FRAME_PAD2,pad2) -STRUCT_FIELD (long,4,FRAME_PS,ps) // (XOS_FRAME_SIZE-44) in S32E range of end -STRUCT_FIELD (long,4,FRAME_PC,pc) // (XOS_FRAME_SIZE-40) in S32E range of end -STRUCT_FIELD (long,4,FRAME_A0,a0) -STRUCT_FIELD (long,4,FRAME_A2,a2) // (XOS_FRAME_SIZE-32) in S32E range of end -STRUCT_FIELD (long,4,FRAME_A3,a3) // (XOS_FRAME_SIZE-28) in S32E range of end -STRUCT_FIELD (long,4,FRAME_LEVELMASK,levelmask) // -STRUCT_FIELD (long,4,FRAME_NESTCHAIN,nestchain) // nested C function call chain ptr -// Caller's a0-a3 save area below SP. These fields MUST be the last ones in the -// struct so that they are guaranteed to be just under the original SP (before -// we allocate the exception frame). -STRUCT_AFIELD (long,4,FRAME_CWINSAVE,cwinsave, 4) // (XOS_FRAME_SIZE-16) -STRUCT_END(XosExcFrame) // NOTE: exception frame size is 128 - -#define FRAME_AR(x) (FRAME_AREG + x*4 - 16) - -#if defined(_ASMLANGUAGE) || defined(__ASSEMBLER__) -#define XOS_FRAME_SIZE XosExcFrameSize -#else -#define XOS_FRAME_SIZE sizeof(XosExcFrame) -#endif - - -//----------------------------------------------------------------------------- -// Stack frame layout for a cooperatively switched out thread -// (tcb->resume_fn == &xos_resume_cooperative_thread). -// Pointed to by thread->esf. This is a function frame. -// Thread's a1 == thread->esf. -//----------------------------------------------------------------------------- -STRUCT_BEGIN -STRUCT_FIELD (long,4,CFRAME_A0,a0) // return PC -STRUCT_FIELD (long,4,CFRAME_LEVELMASK,levelmask) -STRUCT_FIELD (long,4,CFRAME_PS,ps) -#ifdef __XTENSA_CALL0_ABI__ -STRUCT_FIELD (long,4,CFRAME_PAD0,pad0) -STRUCT_AFIELD(long,4,CFRAME_AREG,areg,4) // callee-saved regs a12-a15 -#endif -STRUCT_END(XosCoopFrame) - - -//----------------------------------------------------------------------------- -// Offsets into thread control block (must match xos_thread.h !!) -//----------------------------------------------------------------------------- -#define TCB_RESUME_FN 12 // ptr to thread resume asm sequence -#define TCB_STACK_ESF 16 // saved stack ptr (actually, ptr to ESF) -#define TCB_TIE_SAVE 20 // ptr to TIE save area -#define TCB_RETVALUE 24 // ptr to xos_block return value -#define TCB_STACK_END 36 // ptr to end of stack (thread's initial stack ptr) -#define TCB_STARTUP_ENTRY 40 // ptr to thread entry function -#define TCB_STARTUP_ARG 44 // ptr to thread entry function's arg -#define TCB_READY 48 // thread ready state (1 byte) -#define TCB_CLIB_PTR 108 // thread C lib context pointer - -#define TCB_RESUME_CCOUNT 116 // cycle count at last resume -#define TCB_CYCLE_COUNT 120 // number of cycles consumed -#define TCB_NORMAL_RESUMES 128 // number of cooperative/restart thread resumes -#define TCB_PREEMPT_RESUMES 132 // number of pre-emptive thread resumes - - -//----------------------------------------------------------------------------- -// Coprocessor state handling: -// The coprocessor state save area is allocated on the thread stack. The stack -// must be sized appropriately. Threads that do not use coprocessors need not -// allocate the storage area. -// -// Along with the save area for each coprocessor, two bitmasks with flags per -// coprocessor (laid out as in the CPENABLE reg) help manage context switching -// coprocessors as efficiently as possible: -// -// XT_CPENABLE -// The contents of a non-running thread's CPENABLE register. -// It represents the coprocessors owned (and whose state is still needed) -// by the thread. When a thread is preempted, its CPENABLE is saved here. -// When a thread solicits a context switch, its CPENABLE is cleared - the -// compiler has saved the (caller-saved) coprocessor state if needed. -// When a non-running thread loses ownership of a CP, its bit is cleared. -// When a thread runs, it's XT_CPENABLE is loaded into the CPENABLE reg. -// Avoids coprocessor exceptions when no change of ownership is needed. -// -// XT_CPSTORED -// A bitmask with the same layout as CPENABLE, a bit per coprocessor. -// Indicates whether the state of each coprocessor is saved in the state -// save area. When a thread enters the kernel, only the state of coprocs -// still enabled in CPENABLE is saved. When the coprocessor exception -// handler assigns ownership of a coprocessor to a thread, it restores -// the saved state only if this bit is set, and clears this bit. -// -// XT_CP_CS_ST -// A bitmask with the same layout as CPENABLE, a bit per co-processor. -// Indicates whether callee-saved state is saved in the state save area. -// Callee-saved state is saved by itself on a solicited context switch, -// and restored when needed by the coprocessor exception handler. -// Unsolicited switches will cause the entire coprocessor to be saved -// when necessary. -// -// XT_NCP_ASA -// Pointer to aligned save area for non-CP state. This is always filled -// in, even if there is no non-CP state to be saved. If there is no state -// to be saved then no space is actually allocated and this pointer is -// not used. -// -// XT_CP_ASA -// Pointer to aligned save area for coprocessor state. This is filled in -// only if coprocessor state is to be saved for the thread. Allows it to be -// aligned more than the overall save area (which might be stack-aligned -// or TCB-aligned). Especially relevant for Xtensa cores configured with a -// very large data path that requires alignment greater than 16 bytes (ABI -// stack alignment). -//----------------------------------------------------------------------------- - -#define ALIGNUP(n, val) (((val) + (n)-1) & -(n)) - -// Offsets of each coprocessor save area within the 'aligned save area'. -// The non-CP TIE state save area is at offset 0, so that it does not -// move around if some or all coprocessors are not to be saved. - -#define XT_NCP_SA 0 -#define XT_CP0_SA ALIGNUP(XCHAL_CP0_SA_ALIGN, XT_NCP_SA + XCHAL_NCP_SA_SIZE) -#define XT_CP1_SA ALIGNUP(XCHAL_CP1_SA_ALIGN, XT_CP0_SA + XCHAL_CP0_SA_SIZE) -#define XT_CP2_SA ALIGNUP(XCHAL_CP2_SA_ALIGN, XT_CP1_SA + XCHAL_CP1_SA_SIZE) -#define XT_CP3_SA ALIGNUP(XCHAL_CP3_SA_ALIGN, XT_CP2_SA + XCHAL_CP2_SA_SIZE) -#define XT_CP4_SA ALIGNUP(XCHAL_CP4_SA_ALIGN, XT_CP3_SA + XCHAL_CP3_SA_SIZE) -#define XT_CP5_SA ALIGNUP(XCHAL_CP5_SA_ALIGN, XT_CP4_SA + XCHAL_CP4_SA_SIZE) -#define XT_CP6_SA ALIGNUP(XCHAL_CP6_SA_ALIGN, XT_CP5_SA + XCHAL_CP5_SA_SIZE) -#define XT_CP7_SA ALIGNUP(XCHAL_CP7_SA_ALIGN, XT_CP6_SA + XCHAL_CP6_SA_SIZE) - -#define XT_TOT_SA_SIZE ALIGNUP(16, XT_CP7_SA + XCHAL_CP7_SA_SIZE) -#define XT_NCP_SA_SIZE XCHAL_NCP_SA_SIZE - -// Offsets within the overall save area - -#define XT_CPENABLE 0 // (2 bytes) coprocessors active for this thread -#define XT_CPSTORED 2 // (2 bytes) coprocessors saved for this thread -#define XT_CP_CS_ST 4 // (2 bytes) coprocessor callee-saved regs for this thread -#define XT_NCP_ASA 8 // (4 bytes) ptr to aligned save area for nonCP state -#define XT_CP_ASA 12 // (4 bytes) ptr to aligned save area for CP state - -// Overall size allows for dynamic alignment, make sure multiple of 4 bytes. -// XT_CP_SIZE - total space needed for all coprocessors + nonCP state + hdr -// XT_NCP_SIZE - total space needed for nonCP state + hdr - -#define XT_CP_SIZE ALIGNUP(4, (16 + XT_TOT_SA_SIZE + XCHAL_TOTAL_SA_ALIGN)) -#define XT_NCP_SIZE ALIGNUP(4, (16 + XT_NCP_SA_SIZE + XCHAL_TOTAL_SA_ALIGN)) - - -//----------------------------------------------------------------------------- -// Stack size computation. -// -// XOS_STACK_MIN_SIZE -// The minimum recommended stack size for any XOS thread. If you want to -// use a stack size smaller than this, you will have to verify that the -// smaller size will work under all operating conditions. -// -// XOS_STACK_MIN_SIZE_NO_CP -// The minimum recommended atack size for threads that will not use any -// coprocessor resources. No coprocessor state will be saved/restored -// for these threads. Non-CP TIE state will still be saved/restored. -// These threads must be created with the flag XOS_THREAD_NO_CP. -// -// XOS_STACK_EXTRA -// The amount of stack space used by the system to: -// - save coprocessor state -// - save non-coprocessor TIE state -// - allocate an interrupt/exception frame -// -// XOS_STACK_EXTRA_NO_CP -// The amount of stack space used by the system to: -// - save non-coprocessor TIE state -// - allocate an interrupt/exception frame -//----------------------------------------------------------------------------- - -#define XOS_STACK_EXTRA (XOS_FRAME_SIZE + XT_CP_SIZE) -#define XOS_STACK_EXTRA_NO_CP (XOS_FRAME_SIZE + XT_NCP_SIZE) - -#ifdef __XTENSA_CALL0_ABI__ -#define XOS_STACK_MIN_SIZE (XOS_STACK_EXTRA + 0x180) -#define XOS_STACK_MIN_SIZE_NO_CP (XOS_STACK_EXTRA_NO_CP + 0x180) -#else -#define XOS_STACK_MIN_SIZE (XOS_STACK_EXTRA + 0x200) -#define XOS_STACK_MIN_SIZE_NO_CP (XOS_STACK_EXTRA_NO_CP + 0x200) -#endif - - -//----------------------------------------------------------------------------- -// Items related to C library thread safety. -//----------------------------------------------------------------------------- -#if XOS_OPT_THREAD_SAFE_CLIB - -#if XSHAL_CLIB == XTHAL_CLIB_XCLIB - #if !defined(_ASMLANGUAGE) && !defined(__ASSEMBLER__) - #include - #endif - #define CLIB_THREAD_STRUCT struct _reent xclib_reent - #define GLOBAL_CLIB_PTR _reent_ptr -#elif XSHAL_CLIB == XTHAL_CLIB_NEWLIB - #if !defined(_ASMLANGUAGE) && !defined(__ASSEMBLER__) - #include - #endif - #define CLIB_THREAD_STRUCT struct _reent newlib_reent - #define GLOBAL_CLIB_PTR _impure_ptr -#else - #error The selected C runtime library is not thread safe. -#endif - -#endif // XOS_OPT_THREAD_SAFE_CLIB - - -//----------------------------------------------------------------------------- -// Check (MAX_OS_INTLEVEL,EXCM_LEVEL) -//----------------------------------------------------------------------------- -#if XOS_MAX_OS_INTLEVEL >= XCHAL_EXCM_LEVEL -# define XOS_MAX_OSEXCM_LEVEL XOS_MAX_OS_INTLEVEL -#else -# warning "XOS_MAX_OS_INTLEVEL was set below XCHAL_EXCM_LEVEL: this was never tested" -# define XOS_MAX_OSEXCM_LEVEL XCHAL_EXCM_LEVEL -#endif - - -//----------------------------------------------------------------------------- -// Detect if in interrupt context. -//----------------------------------------------------------------------------- -#if XCHAL_HAVE_INTERRUPTS -#define INTERRUPT_CONTEXT ((XT_RSR_PS() & PS_UM) == 0) -#else -#define INTERRUPT_CONTEXT 0 -#endif - - -//----------------------------------------------------------------------------- -// Xtensa tools version. -//----------------------------------------------------------------------------- -#if defined __XCC__ -#define XTTOOLS_VERSION (__XCC__ + __XCC_MINOR__) -#else -#define XTTOOLS_VERSION (0) -#endif - - -//----------------------------------------------------------------------------- -// Erratum workarounds. -//----------------------------------------------------------------------------- - -// Erratum 487 fix is available in version RF.3 onwards and RG.2 onwards. -#if ((__XCC__ == 11000) && (__XCC_MINOR__ >= 3)) || (XTTOOLS_VERSION >= 12002) -#define HWERR_487_FIX hw_erratum_487_fix -#else -#define HWERR_487_FIX -#endif - - -#ifdef __cplusplus -} -#endif - -#endif // __XOS_COMMON_H__ - diff --git a/components/esp32/include/xtensa/xos_cond.h b/components/esp32/include/xtensa/xos_cond.h deleted file mode 100644 index 8116947d33..0000000000 --- a/components/esp32/include/xtensa/xos_cond.h +++ /dev/null @@ -1,145 +0,0 @@ -/** @file */ - -// xos_cond.h - XOS condition variables API interface and data structures. - -// 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. - -// NOTE: Do not include this file directly in your application. Including -// xos.h will automatically include this file. - -#ifndef __XOS_COND_H__ -#define __XOS_COND_H__ - -#include "xos_types.h" - -#ifdef __cplusplus -extern "C" { -#endif - - -//----------------------------------------------------------------------------- -// -// Function pointer type for condition callbacks (defined in xos_thread.h) -// -// typedef int32_t (XosCondFunc)(void * arg, int32_t sig_value, XosThread * thread); -// -//----------------------------------------------------------------------------- - - -//----------------------------------------------------------------------------- -/// -/// Condition object. -/// -//----------------------------------------------------------------------------- -typedef struct XosCond { - XosThreadQueue queue; ///< Queue of waiters. -#if XOS_COND_DEBUG - uint32_t sig; // Signature indicates valid object. -#endif -} XosCond; - - -//----------------------------------------------------------------------------- -/// -/// Initialize a condition object before first use. The object must be -/// allocated by the caller. -/// -/// \param cond Pointer to condition object. -/// -/// \return Returns nothing. -/// -//----------------------------------------------------------------------------- -void -xos_cond_create(XosCond * cond); - - -//----------------------------------------------------------------------------- -/// -/// Destroy a condition object. Must have been previously created by calling -/// xos_cond_create(). -/// -/// \param cond Pointer to condition object. -/// -/// \return Returns nothing. -/// -//----------------------------------------------------------------------------- -void -xos_cond_delete(XosCond * cond); - - -//----------------------------------------------------------------------------- -/// -/// Wait on a condition: block until the condition is satisfied. The condition -/// is satisfied when xos_cond_signal() is called on this condition *and* the -/// condition callback function returns non-zero. If there is no callback -/// function, then the condition is automatically satisfied. -/// -/// The condition structure must have been initialized before first use by -/// calling xos_cond_create(). -/// -/// \param cond Pointer to condition object. -/// -/// \param cond_fn Pointer to a function, called by xos_cond_signal(), -/// that should return non-zero if this thread is to -/// be resumed. The function is invoked as: -/// `(*cond_fn)(cond_arg, sig_value)`. -/// -/// \param cond_arg Argument passed to cond_fn. -/// -/// \return Returns the value passed to xos_cond_signal(). -/// -//----------------------------------------------------------------------------- -int32_t -xos_cond_wait(XosCond * cond, XosCondFunc * cond_fn, void * cond_arg); - - -//----------------------------------------------------------------------------- -/// -/// Trigger the condition: wake all threads waiting on the condition, if their -/// condition function evaluates to true (non-zero). If there is no condition -/// function for a thread then it is automatically awakened. -/// -/// The condition structure must have been initialized before first use by -/// calling xos_cond_create(). -/// -/// \param cond Pointer to condition object. -/// -/// \param sig_value Value passed to all waiters, returned by -/// xos_cond_wait(). -/// -/// \return Returns the number of waiting threads that were resumed. -/// -/// NOTE: Signaling a condition that has no waiters has no effect on it, and -/// the signal is not remembered. Any thread that waits on it later must be -/// woken by another call to xos_cond_signal(). -/// -//----------------------------------------------------------------------------- -int32_t -xos_cond_signal(XosCond * cond, int32_t sig_value); - - -#ifdef __cplusplus -} -#endif - -#endif // __XOS_COND_H__ - diff --git a/components/esp32/include/xtensa/xos_errors.h b/components/esp32/include/xtensa/xos_errors.h deleted file mode 100644 index 790cdde3bd..0000000000 --- a/components/esp32/include/xtensa/xos_errors.h +++ /dev/null @@ -1,107 +0,0 @@ -/** @file */ - -// xos_errors.h - XOS error codes. - -// 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. - -// NOTE: Do not include this file directly in your application. Including -// xos.h will automatically include this file. - - -#ifndef __XOS_ERRORS_H__ -#define __XOS_ERRORS_H__ - -#include "xos_types.h" - - -#define _XOS_ERR_FIRST (-65536) -#define _XOS_ERR_LAST (-1) - - -//----------------------------------------------------------------------------- -/// -/// List of XOS error codes. All error codes are negative integers, except for -/// XOS_OK which is zero. -/// XOS error codes occupy the range from -65536 up to -1. -/// The function IS_XOS_ERRCODE() can be used to check if a value lies within -/// the error code range. -/// -//----------------------------------------------------------------------------- -typedef enum xos_err_t { - XOS_OK = 0, - - XOS_ERR_NOT_FOUND = _XOS_ERR_FIRST, ///< Object not found - XOS_ERR_INVALID_PARAMETER, ///< Function parameter is invalid - XOS_ERR_LIMIT, ///< Limit exceeded - XOS_ERR_NOT_OWNED, ///< Object not owned by caller - XOS_ERR_MUTEX_LOCKED, ///< Mutex is already locked - XOS_ERR_MUTEX_NOT_OWNED, ///< Mutex not owned by caller - XOS_ERR_MUTEX_ALREADY_OWNED, ///< Mutex already owned by caller - XOS_ERR_MUTEX_DELETE, ///< Mutex being waited on has been deleted - XOS_ERR_COND_DELETE, ///< Condition being waited on has been deleted - XOS_ERR_SEM_DELETE, ///< Semaphore being waited on has been deleted - XOS_ERR_SEM_BUSY, ///< Semaphore is not available - XOS_ERR_EVENT_DELETE, ///< Event being waited on has been deleted - XOS_ERR_MSGQ_FULL, ///< Message queue is full - XOS_ERR_MSGQ_EMPTY, ///< Message queue is empty - XOS_ERR_MSGQ_DELETE, ///< Message queue being waited on has been deleted - XOS_ERR_TIMER_DELETE, ///< Timer being waited on has been deleted - XOS_ERR_CONTAINER_NOT_RTC, ///< Containing thread not of RTC type - XOS_ERR_CONTAINER_NOT_SAME_PRI, ///< Containing thread not at same priority - XOS_ERR_STACK_TOO_SMALL, ///< Thread stack is too small - XOS_ERR_CONTAINER_ILLEGAL, ///< Illegal container thread - XOS_ERR_ILLEGAL_OPERATION, ///< This operation is not allowed - XOS_ERR_THREAD_EXITED, ///< The thread has already exited - XOS_ERR_NO_TIMER, ///< No suitable timer found - XOS_ERR_FEATURE_NOT_PRESENT, ///< This feature is disabled or not implemented - XOS_ERR_TIMEOUT, ///< Wait timed out - - XOS_ERR_UNHANDLED_INTERRUPT, ///< No handler for interrupt - XOS_ERR_UNHANDLED_EXCEPTION, ///< No handler for exception - XOS_ERR_INTERRUPT_CONTEXT, ///< Operation is illegal in interrupt context - XOS_ERR_THREAD_BLOCKED, ///< Thread already blocked - XOS_ERR_ASSERT_FAILED, ///< Runtime assertion failure - XOS_ERR_CLIB_ERR, ///< Error in C library thread safety module - XOS_ERR_INTERNAL_ERROR, ///< XOS internal error - - XOS_ERR_LAST = _XOS_ERR_LAST, -} xos_err_t; - - -//----------------------------------------------------------------------------- -/// -/// Check if a value is a valid XOS error code. -/// -/// \param val Value to check -/// -/// \return Returns nonzero if 'val' is in the XOS error code range. -/// -//----------------------------------------------------------------------------- -static inline int32_t -IS_XOS_ERRCODE(xos_err_t val) -{ - return ((val >= _XOS_ERR_FIRST) && (val <= _XOS_ERR_LAST)); -} - - -#endif // __XOS_ERRORS_H__ - diff --git a/components/esp32/include/xtensa/xos_event.h b/components/esp32/include/xtensa/xos_event.h deleted file mode 100644 index 43219a2478..0000000000 --- a/components/esp32/include/xtensa/xos_event.h +++ /dev/null @@ -1,281 +0,0 @@ -/** @file */ - -// xos_event.h - XOS Event API interface and data structures. - -// 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. - -// NOTE: Do not include this file directly in your application. Including -// xos.h will automatically include this file. - -#ifndef __XOS_EVENT_H__ -#define __XOS_EVENT_H__ - -#include "xos_types.h" - -#ifdef __cplusplus -extern "C" { -#endif - - -//----------------------------------------------------------------------------- -// Defines. -//----------------------------------------------------------------------------- -#define XOS_EVENT_BITS_ALL 0xFFFFFFFF -#define XOS_EVENT_BITS_NONE 0 - - -//----------------------------------------------------------------------------- -// Event flags. -//----------------------------------------------------------------------------- - - -//----------------------------------------------------------------------------- -/// -/// Event object. -/// -//----------------------------------------------------------------------------- -typedef struct XosEvent { - XosThreadQueue waitq; ///< Queue of waiters. - uint32_t bits; ///< Event bits - uint32_t mask; ///< Specifies which bits are valid - uint16_t flags; ///< Properties. - uint16_t pad; ///< Padding -#if XOS_EVENT_DEBUG - uint32_t sig; // Valid signature indicates inited. -#endif -} XosEvent; - - -//----------------------------------------------------------------------------- -/// -/// Initialize an event object before first use. -/// -/// \param event Pointer to event object. -/// -/// \param mask Mask of active bits. Only these bits can be signaled. -/// -/// \param flags Creation flags (currently ignored, should be zero). -/// -/// \return Returns nothing. -/// -//----------------------------------------------------------------------------- -void -xos_event_create(XosEvent * event, uint32_t mask, uint32_t flags); - - -//----------------------------------------------------------------------------- -/// -/// Destroy an event object. Must have been previously created by calling -/// xos_event_create(). -/// -/// \param event Pointer to event object. -/// -/// \return Returns nothing. -/// -//----------------------------------------------------------------------------- -void -xos_event_delete(XosEvent * event); - - -//----------------------------------------------------------------------------- -/// -/// Set the specified bits in the specified event. Propagates the bit states -/// to all waiting threads and wakes them if needed. -/// -/// \param event Pointer to event object. -/// -/// \param bits Mask of bits to set. Bits not set in the mask -/// will not be modified by this call. To set all -/// the bits in the event, use the constant -/// XOS_EVENT_BITS_ALL. -/// -/// \return Returns XOS_OK on success, else error code. -/// -//----------------------------------------------------------------------------- -int32_t -xos_event_set(XosEvent * event, uint32_t bits); - - -//----------------------------------------------------------------------------- -/// -/// Clear the specified bits in the specified event. Propagates the bit states -/// to all waiting threads and wakes them if needed. -/// -/// \param event Pointer to event object. -/// -/// \param bits Mask of bits to clear. Every bit that is set in -/// the mask will be cleared from the event. Bits -/// not set in the mask will not be modified by this -/// call. To clear all the bits in an event use the -/// constant XOS_EVENT_BITS_ALL. -/// -/// \return Returns XOS_OK on success, else error code. -/// -//----------------------------------------------------------------------------- -int32_t -xos_event_clear(XosEvent * event, uint32_t bits); - - -//----------------------------------------------------------------------------- -/// -/// Clear and set the specified bits in the specified event. The two steps are -/// combined into one update, so this is faster than calling xos_event_clear() -/// and xos_event_set() separately. Only one update is sent out to waiting -/// threads. -/// -/// \param event Pointer to event object. -/// -/// \param clr_bits Mask of bits to clear. The clear operation -/// happens before the set operation. -/// -/// \param set_bits Mask of bits to set. -/// -/// \return Returns XOS_OK on success, else error code. -/// -//----------------------------------------------------------------------------- -int32_t -xos_event_clear_and_set(XosEvent * event, uint32_t clr_bits, uint32_t set_bits); - - -//----------------------------------------------------------------------------- -/// -/// Get the current state of the event object. This is a snapshot of the state -/// of the event at this time. -/// -/// \param event Pointer to event object. -/// -/// \param pstate Pointer to a uint32_t variable where the state -/// will be returned. -/// -/// \return Returns XOS_OK on success, else error code. -/// -//----------------------------------------------------------------------------- -int32_t -xos_event_get(XosEvent * event, uint32_t * pstate); - - -//----------------------------------------------------------------------------- -/// -/// Wait until all the specified bits in the wait mask become set in the given -/// event object. -/// -/// \param event Pointer to event object. -/// -/// \param bits Mask of bits to test. -/// -/// \return Returns XOS_OK on success, else error code. -/// -//----------------------------------------------------------------------------- -int32_t -xos_event_wait_all(XosEvent * event, uint32_t bits); - - -//----------------------------------------------------------------------------- -/// -/// Wait until all the specified bits in the wait mask become set in the given -/// event object, or the timeout expires. -/// -/// \param event Pointer to event object. -/// -/// \param bits Mask of bits to test. -/// -/// \param to_cycles Timeout in cycles. Convert from time to cycles -/// using the helper functions provided in xos_timer. -/// A value of zero indicates no timeout. -/// -/// \return Returns XOS_OK on success, XOS_ERR_TIMEOUT on timeout, else -/// error code. -/// -/// NOTE: If XOS_OPT_WAIT_TIMEOUT is not enabled, then the timeout value is -/// ignored, and no timeout will occur. -/// -//----------------------------------------------------------------------------- -int32_t -xos_event_wait_all_timeout(XosEvent * event, uint32_t bits, uint64_t to_cycles); - - -//----------------------------------------------------------------------------- -/// -/// Wait until any of the specified bits in the wait mask become set in the -/// given event object. -/// -/// \param event Pointer to event object. -/// -/// \param bits Mask of bits to test. -/// -/// \return Returns XOS_OK on success, else error code. -/// -//----------------------------------------------------------------------------- -int32_t -xos_event_wait_any(XosEvent * event, uint32_t bits); - - -//----------------------------------------------------------------------------- -/// -/// Wait until any of the specified bits in the wait mask become set in the -/// event object, or the timeout expires. -/// -/// \param event Pointer to event object. -/// -/// \param bits Mask of bits to test. -/// -/// \param to_cycles Timeout in cycles. Convert from time to cycles -/// using the helper functions provided in xos_timer. -/// A value of zero indicates no timeout. -/// -/// \return Returns XOS_OK on success, XOS_ERR_TIMEOUT on timeout, else -/// error code. -/// -/// NOTE: If XOS_OPT_WAIT_TIMEOUT is not enabled, then the timeout value is -/// ignored, and no timeout will occur. -/// -//----------------------------------------------------------------------------- -int32_t -xos_event_wait_any_timeout(XosEvent * event, uint32_t bits, uint64_t to_cycles); - - -//----------------------------------------------------------------------------- -/// -/// Atomically set a specified group of bits, then wait for another specified -/// group of bits to become set. -/// -/// \param event Pointer to event object. -/// -/// \param set_bits Group of bits to set. -/// -/// \param wait_bits Group of bits to wait on. All the bits in the -/// group will have to get set before the wait is -/// satisfied. -/// -/// \return Returns XOS_OK on success, else error code. -/// -//----------------------------------------------------------------------------- -int32_t -xos_event_set_and_wait(XosEvent * event, uint32_t set_bits, uint32_t wait_bits); - - -#ifdef __cplusplus -} -#endif - -#endif // __XOS_EVENT_H__ - diff --git a/components/esp32/include/xtensa/xos_internal.h b/components/esp32/include/xtensa/xos_internal.h deleted file mode 100644 index 5b8c8b4662..0000000000 --- a/components/esp32/include/xtensa/xos_internal.h +++ /dev/null @@ -1,120 +0,0 @@ - -// 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. - - -#ifndef __XOS_INTERNAL_H__ -#define __XOS_INTERNAL_H__ - -#if !defined(__XOS_H__) || !defined(_XOS_INCLUDE_INTERNAL_) - #error "xos_internal.h must be included by defining _XOS_INCLUDE_INTERNAL_ before including xos.h" -#endif - -#include -#include "xos_common.h" - -#ifdef __cplusplus -extern "C" { -#endif - - -// Use this macro to suppress compiler warnings for unused variables. - -#define UNUSED(x) (void)(x) - - -#if XOS_DEBUG - -#include -#include -# define DPRINTF printf - -#else - -# define DPRINTF(x...) do {} while(0) - -#endif - - -//----------------------------------------------------------------------------- -// Internal flags for thread creation. -//----------------------------------------------------------------------------- -#define XOS_THREAD_FAKE 0x8000 // Don't allocate stack (init and idle threads). - - -//----------------------------------------------------------------------------- -// Interrupt handler table entry. This structure defines one entry in the XOS -// interrupt handler table. -//----------------------------------------------------------------------------- -typedef struct XosIntEntry { - XosIntFunc * handler; // Pointer to handler function. - void * arg; // Argument passed to handler function. -#if XOS_OPT_INTERRUPT_SWPRI - unsigned char level; // Interrupt level. - unsigned char priority; // Interrupt priority. - short reserved; // Reserved. - unsigned int primask; // Mask of interrupts at higher priority. -#else - unsigned int ps; // Value of PS when running the handler. -#endif -} XosIntEntry; - - -//----------------------------------------------------------------------------- -// Extern variables. -//----------------------------------------------------------------------------- -extern unsigned xos_intlevel_mask; -extern unsigned xos_intenable_mask; -extern XosIntEntry xos_interrupt_table[XCHAL_NUM_INTERRUPTS]; - -extern uint32_t xos_clock_freq; -extern uint32_t xos_tick_period; -extern uint64_t xos_system_ticks; -extern uint64_t xos_system_cycles; -extern uint32_t xos_num_ctx_switches; - - -/* - -One thing I noticed is different between my initial idea of stack -assignments to RTC threads, when comparing to interrupts, is that I -expected each RTC thread priority to have its own stack, whereas -interrupts of different priorities share an interrupt stack. - -It's not really a difference in memory usage, because when assigning -multiple priorities to a stack, you have to add-up worst-case for -all priorities. One possible functional difference is that with -separate stacks per priority, it's possible to dynamically change -the priority of an RTC thread (while it's running). Not sure how -valuable that might be -- changing priority is useful with priority -inheritance, to avoid priority inversion, but I don't know how often -an RTC thread might acquire a lock (it couldn't block on acquiring a -lock in the usual sense -- it could get queued waiting and be restarted -when it becomes available, or use try_lock instead of lock). - -*/ - -#ifdef __cplusplus -} -#endif - -#endif /* __XOS_INTERNAL_H__ */ - diff --git a/components/esp32/include/xtensa/xos_msgq.h b/components/esp32/include/xtensa/xos_msgq.h deleted file mode 100644 index 30b9aa9032..0000000000 --- a/components/esp32/include/xtensa/xos_msgq.h +++ /dev/null @@ -1,278 +0,0 @@ -/** @file */ - -// xos_msgq.h - XOS Message Queue API and data structures. - -// 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. - -// NOTE: Do not include this file directly in your application. Including -// xos.h will automatically include this file. - - -#ifndef __XOS_MSGQ_H__ -#define __XOS_MSGQ_H__ - -#include "xos_types.h" - -#ifdef __cplusplus -extern "C" { -#endif - - -//----------------------------------------------------------------------------- -// XosMsgQueue is a multi-writer multi-reader message queue implementation. -// It is completely thread-safe and can be used by interrupt handlers. -// Interrupt handlers are guaranteed not to block when trying to send or -// receive a message. Messages are copied into the queue. The queue contains -// storage for a fixed number of messages defined at queue creation time. -// Messages must be a multiple of 4 bytes long (padded if necessary) and the -// message buffers must be 4-byte aligned. -//----------------------------------------------------------------------------- - - -//----------------------------------------------------------------------------- -// Message Queue flags. -//----------------------------------------------------------------------------- -#define XOS_MSGQ_WAIT_PRIORITY 0x0000 ///< Wake waiters in priority order (default) -#define XOS_MSGQ_WAIT_FIFO 0x0001 ///< Wake waiters in FIFO order -#define XOS_MSGQ_FULL 0x0002 // Queue is full -#define XOS_MSGQ_DELETED 0x8000 // Queue is deleted - - -//----------------------------------------------------------------------------- -/// -/// XosMsgQueue object. -/// -//----------------------------------------------------------------------------- -typedef struct XosMsgQueue { - uint16_t flags; ///< queue flags - uint16_t count; ///< # of messages queue can hold - uint32_t msize; ///< message size in bytes - uint16_t head; ///< write pointer - uint16_t tail; ///< read pointer - XosThreadQueue readq; ///< reader wait queue - XosThreadQueue writeq; ///< writer wait queue -#if XOS_MSGQ_DEBUG - uint32_t sig; // debug signature -#endif -#if XOS_OPT_MSGQ_STATS - uint32_t num_send; ///< # of messages put to queue - uint32_t num_recv; ///< # of messages taken from queue - uint32_t num_send_blks; ///< # of times thread blocked on send - uint32_t num_recv_blks; ///< # of times thread blocked on recv -#endif - uint32_t msg[1]; ///< first word of message buffer -} XosMsgQueue; - - -//----------------------------------------------------------------------------- -/// -/// Use these macros to statically or dynamically allocate a message queue. -/// XOS_MSGQ_ALLOC allocates a static queue, while XOS_MSGQ_SIZE can be used -/// to allocate memory via malloc() etc. -/// -/// Static: this allocates a queue named "testq", containing 10 messages, -/// each 16 bytes long. -/// -/// XOS_MSGQ_ALLOC(testq, 10, 16); -/// -/// Dynamic: this allocates a queue named "testq", containing 10 messages, -/// each 16 bytes long. -/// -/// XosMsgQueue * testq = malloc( XOS_MSGQ_SIZE(10, 16) ); -/// -/// \param name The queue name, i.e. the name of the pointer -/// to the queue. Used as the queue handle in -/// queue API calls. -/// -/// \param num Number of messages to allocate in queue. Must be > 0. -/// -/// \param size Message size in bytes. Must be > 0 and multiple of 4. -/// -//----------------------------------------------------------------------------- - -#define XOS_MSGQ_ALLOC(name, num, size) \ - static uint8_t name ## _buf[ sizeof(XosMsgQueue) + ((num) * (size)) ]; \ - XosMsgQueue * name = (XosMsgQueue *) name ## _buf; - -#define XOS_MSGQ_SIZE(num, size) \ - (sizeof(XosMsgQueue) + ((num) * (size))) - - -//----------------------------------------------------------------------------- -/// -/// Create the message queue object. Memory for the queue must be allocated by -/// the caller, either statically or via dynamic allocation. See the macros -/// XOS_MSGQ_ALLOC and XOS_MSGQ_SIZE for examples. -/// -/// \param msgq Handle (pointer) to message queue. -/// -/// \param num Number of messages allocated in queue. Must be > 0. -/// -/// \param size Message size in bytes. Must be > 0 and multiple of 4. -/// -/// \param flags Queue flags: -/// - XOS_MSGQ_WAIT_FIFO - blocked threads will be -/// woken in FIFO order. -/// - XOS_MSGQ_WAIT_PRIORITY - blocked threads will -/// be woken in priority order (default). -/// -/// \return Returns XOS_OK on success, else error code. -/// -//----------------------------------------------------------------------------- -int32_t -xos_msgq_create(XosMsgQueue * msgq, uint16_t num, uint32_t size, uint16_t flags); - - -//----------------------------------------------------------------------------- -/// -/// Destroys the specified queue. Any waiting threads are unblocked with an -/// error return. Any messages in the queue will be lost. -/// -/// \param msgq Pointer to message queue. -/// -/// \return Returns XOS_OK on success, else error code. -/// -//----------------------------------------------------------------------------- -int32_t -xos_msgq_delete(XosMsgQueue * msgq); - - -//----------------------------------------------------------------------------- -/// -/// Put a message into the queue. The message contents are copied into the next -/// available message slot. If no space is available, this function will block -/// if called from a thread, but will return immediately if called from an -/// interrupt handler. -/// -/// \param msgq Pointer to message queue. -/// -/// \param msg Pointer to message buffer. -/// -/// \return Returns XOS_OK on success, else error code. -/// -//----------------------------------------------------------------------------- -int32_t -xos_msgq_put(XosMsgQueue * msgq, const uint32_t * msg); - - -//----------------------------------------------------------------------------- -/// -/// Put a message into the queue. The message contents are copied into the next -/// available message slot. If no space is available, this function will block -/// if called from a thread, but will return immediately if called from an -/// interrupt handler. The thread will be unblocked when space frees up in the -/// queue or the timeout expires. -/// -/// \param msgq Pointer to message queue. -/// -/// \param msg Pointer to message buffer. -/// -/// \param to_cycles Timeout in cycles. Convert from time to cycles -/// using the helper functions provided in xos_timer. -/// A value of zero indicates no timeout. -/// -/// \return Returns XOS_OK on success, XOS_ERR_TIMEOUT on timeout, else error code. -/// -/// NOTE: If XOS_OPT_WAIT_TIMEOUT is not enabled, then the timeout value is -/// ignored, and no timeout will occur. -/// -//----------------------------------------------------------------------------- -int32_t -xos_msgq_put_timeout(XosMsgQueue * msgq, const uint32_t * msg, uint64_t to_cycles); - - -//----------------------------------------------------------------------------- -/// -/// Get a message from the queue. The message contents are copied into the -/// buffer that must be provided. If no message is available, this function -/// will block if called from a thread, but will return immediately if called -/// from an interrupt handler. -/// -/// \param msgq Pointer to message queue. -/// -/// \param msg Pointer to message buffer. -/// -/// \return Returns XOS_OK on success, else error code. -/// -//----------------------------------------------------------------------------- -int32_t -xos_msgq_get(XosMsgQueue * msgq, uint32_t * msg); - - -//----------------------------------------------------------------------------- -/// -/// Get a message from the queue. The message contents are copied into the -/// buffer that must be provided. If no message is available, this function -/// will block if called from a thread, but will return immediately if called -/// from an interrupt handler. The thread will be unblocked when a message -/// arrives in the queue or the timeout expires. -/// -/// \param msgq Pointer to message queue. -/// -/// \param msg Pointer to message buffer. -/// -/// \param to_cycles Timeout in cycles. Convert from time to cycles -/// using the helper functions provided in xos_timer. -/// A value of zero indicates no timeout. -/// -/// \return Returns XOS_OK on success, XOS_ERR_TIMEOUT on timeout, else error code. -/// -/// NOTE: If XOS_OPT_WAIT_TIMEOUT is not enabled, then the timeout value is -/// ignored, and no timeout will occur. -/// -//----------------------------------------------------------------------------- -int32_t -xos_msgq_get_timeout(XosMsgQueue * msgq, uint32_t * msg, uint64_t to_cycles); - - -//----------------------------------------------------------------------------- -/// -/// Check if the queue is empty. -/// -/// \param msgq Pointer to message queue. -/// -/// \return Returns nonzero if queue is empty, zero if queue is not empty. -/// -//----------------------------------------------------------------------------- -int32_t -xos_msgq_empty(XosMsgQueue * msgq); - - -//----------------------------------------------------------------------------- -/// -/// Check if the queue is full. -/// -/// \param msgq Pointer to message queue. -/// -/// \return Returns nonzero if queue is full, zero if queue is not full. -/// -//----------------------------------------------------------------------------- -int32_t -xos_msgq_full(XosMsgQueue * msgq); - - -#ifdef __cplusplus -} -#endif - -#endif // __XOS_MSGQ_H__ - diff --git a/components/esp32/include/xtensa/xos_mutex.h b/components/esp32/include/xtensa/xos_mutex.h deleted file mode 100644 index 9df5f9750b..0000000000 --- a/components/esp32/include/xtensa/xos_mutex.h +++ /dev/null @@ -1,205 +0,0 @@ -/** @file */ - -// xos_mutex.h - XOS Mutex API interface and data structures. - -// 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. - -// NOTE: Do not include this file directly in your application. Including -// xos.h will automatically include this file. - -#ifndef __XOS_MUTEX_H__ -#define __XOS_MUTEX_H__ - -#include "xos_types.h" - -#ifdef __cplusplus -extern "C" { -#endif - - -//----------------------------------------------------------------------------- -// Mutex flags. -//----------------------------------------------------------------------------- -#define XOS_MUTEX_WAIT_PRIORITY 0x0000 ///< Wake waiters in priority order (default) -#define XOS_MUTEX_WAIT_FIFO 0x0001 ///< Wake waiters in FIFO order -#define XOS_MUTEX_PRIORITY_CLG 0x0004 // Use priority ceiling -#define XOS_MUTEX_PRIORITY_INV 0x0008 // Protect against priority inversion - - -//----------------------------------------------------------------------------- -/// -/// XosMutex object. -/// -//----------------------------------------------------------------------------- -typedef struct XosMutex { - XosThread * owner; ///< Owning thread (null if unlocked). - XosThreadQueue waitq; ///< Queue of waiters. - uint32_t flags; ///< Properties. - uint32_t priority; - int32_t lock_count; ///< For recursive locking. -#if XOS_MUTEX_DEBUG - uint32_t sig; // Valid signature indicates inited. -#endif -} XosMutex; - - -//----------------------------------------------------------------------------- -/// -/// Initialize a mutex object before first use. -/// -/// \param mutex Pointer to mutex object. -/// -/// \param flags Creation flags: -/// - XOS_MUTEX_WAIT_FIFO -- Queue waiting threads -/// in fifo order. -/// - XOS_MUTEX_WAIT_PRIORITY -- Queue waiting threads -/// by priority. This is the default. -/// - XOS_MUTEX_PRIORITY_CLG -- Use specified priority -/// value as the mutex's priority ceiling. If the -/// owning thread has a priority lower than the mutex's -/// priority, then the thread will have its priority -/// raised to the higher value as long as it owns the -/// mutex. -/// - XOS_MUTEX_PRIORITY_INV -- Protect against priority -/// inversion. If there is a waiting thread with a -/// higher priority than the current owner thread, -/// then the owner thread's priority is raised to the -/// higher value for as long as it owns the mutex. -/// -/// \param priority Mutex's priority ceiling. This is used only if the -/// XOS_MUTEX_PRIORITY_CLG flag is set. -/// -/// \return Returns XOS_OK on success, else error code. -/// -/// NOTE: XOS_MUTEX_PRIORITY_CLG and XOS_MUTEX_PRIORITY_INV are NOT supported -/// in the current release. They will be supported in a future release. -/// -//----------------------------------------------------------------------------- -int32_t -xos_mutex_create(XosMutex * mutex, uint32_t flags, uint8_t priority); - - -//----------------------------------------------------------------------------- -/// -/// Destroy a mutex object. Must have been previously initialized by calling -/// xos_mutex_create(). -/// -/// \param mutex Pointer to mutex object. -/// -/// \return Returns XOS_OK on success, else error code. -/// -//----------------------------------------------------------------------------- -int32_t -xos_mutex_delete(XosMutex * mutex); - - -//----------------------------------------------------------------------------- -/// -/// Take ownership of the mutex: block until the mutex is owned. -/// The mutex must have been initialized. -/// -/// \param mutex Pointer to mutex object. -/// -/// \return Returns XOS_OK on success, else error code. -/// -//----------------------------------------------------------------------------- -int32_t -xos_mutex_lock(XosMutex * mutex); - - -//----------------------------------------------------------------------------- -/// -/// Take ownership of the mutex: block until the mutex is owned or the timeout -/// expires. The mutex must have been initialized. -/// -/// \param mutex Pointer to mutex object. -/// -/// \param to_cycles Timeout in cycles. Convert from time to cycles -/// using the helper functions provided in xos_timer. -/// A value of zero indicates no timeout. -/// -/// \return Returns XOS_OK on success, XOS_ERR_TIMEOUT on timeout, else error code. -/// -/// NOTE: If XOS_OPT_WAIT_TIMEOUT is not enabled, then the timeout value is -/// ignored, and no timeout will occur. -/// -//----------------------------------------------------------------------------- -int32_t -xos_mutex_lock_timeout(XosMutex * mutex, uint64_t to_cycles); - - -//----------------------------------------------------------------------------- -/// -/// Release ownership of the mutex. The mutex must have been initialized and -/// must be owned by the calling thread. -/// -/// \param mutex Pointer to mutex object. -/// -/// \return Returns XOS_OK on success, else error code. -/// -//----------------------------------------------------------------------------- -int32_t -xos_mutex_unlock(XosMutex * mutex); - - -//----------------------------------------------------------------------------- -/// -/// Try to take ownership of the mutex, but do not block if the mutex is taken. -/// Return immediately. The mutex must have been initialized. -/// -/// \param mutex Pointer to mutex object. -/// -/// \return Returns XOS_OK on success (mutex owned), else error code. -/// -//----------------------------------------------------------------------------- -int32_t -xos_mutex_trylock(XosMutex * mutex); - - -//----------------------------------------------------------------------------- -/// -/// Return the state of the mutex (locked or unlocked) but do not attempt to -/// take ownership. The mutex must have been initialized. -/// -/// \param mutex Pointer to mutex object. -/// -/// \return Returns 0 if the mutex is unlocked, 1 if it is locked, -1 on error. -/// -//----------------------------------------------------------------------------- -static inline int32_t -xos_mutex_test(XosMutex * mutex) -{ - XOS_ASSERT(mutex); - - if (mutex != XOS_NULL) { - return (mutex->owner != XOS_NULL) ? 1 : 0; - } - return -1; -} - - -#ifdef __cplusplus -} -#endif - -#endif // __XOS_MUTEX_H__ - diff --git a/components/esp32/include/xtensa/xos_params.h b/components/esp32/include/xtensa/xos_params.h deleted file mode 100644 index 3fca11f21a..0000000000 --- a/components/esp32/include/xtensa/xos_params.h +++ /dev/null @@ -1,276 +0,0 @@ -/** @file */ - -// xos_params.h - user-settable compile time parameters for XOS. - -// 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. - - -#ifndef __XOS_PARAMS_H__ -#define __XOS_PARAMS_H__ - -#include - -#ifdef __cplusplus -extern "C" { -#endif - - -//----------------------------------------------------------------------------- -/// -/// Number of thread priority levels. At this time XOS supports a maximum of -/// 32 priority levels (0 - 31). -/// -//----------------------------------------------------------------------------- -#ifndef XOS_NUM_PRIORITY -#define XOS_NUM_PRIORITY 16 // Default is 16 -#endif - - -//----------------------------------------------------------------------------- -/// -/// Debug flags - Set to 1 to enable debug mode (and more verbose operation). -/// Can be set individually, or define XOS_DEBUG_ALL to enable all of them. -/// -/// - XOS_DEBUG -- Generic OS debug -/// - XOS_COND_DEBUG -- Condition objects debug -/// - XOS_EVENT_DEBUG -- Event objects debug -/// - XOS_MSGQ_DEBUG -- Message queue debug -/// - XOS_MUTEX_DEBUG -- Mutex objects debug -/// - XOS_SEM_DEBUG -- Semaphore objects debug -/// - XOS_THREAD_DEBUG -- Thread module debug -/// - XOS_TIMER_DEBUG -- Timer module debug -/// -/// WARNING: Enabling one or more of these flags will affect system performance -/// and timing. -/// -/// NOTE: Not all of these have been fully implemented. -/// -//----------------------------------------------------------------------------- -#if defined XOS_DEBUG_ALL - -#define XOS_DEBUG 1 -#define XOS_THREAD_DEBUG 1 -#define XOS_TIMER_DEBUG 1 -#define XOS_COND_DEBUG 1 -#define XOS_MUTEX_DEBUG 1 -#define XOS_SEM_DEBUG 1 -#define XOS_EVENT_DEBUG 1 -#define XOS_MSGQ_DEBUG 1 - -#else - -#ifndef XOS_DEBUG -#define XOS_DEBUG 0 -#endif -#ifndef XOS_THREAD_DEBUG -#define XOS_THREAD_DEBUG 0 -#endif -#ifndef XOS_TIMER_DEBUG -#define XOS_TIMER_DEBUG 0 -#endif -#ifndef XOS_COND_DEBUG -#define XOS_COND_DEBUG 0 -#endif -#ifndef XOS_MUTEX_DEBUG -#define XOS_MUTEX_DEBUG 0 -#endif -#ifndef XOS_SEM_DEBUG -#define XOS_SEM_DEBUG 0 -#endif -#ifndef XOS_EVENT_DEBUG -#define XOS_EVENT_DEBUG 0 -#endif -#ifndef XOS_MSGQ_DEBUG -#define XOS_MSGQ_DEBUG 0 -#endif - -#endif - - -//----------------------------------------------------------------------------- -/// -/// Set this option to 1 to enable runtime statistics collection for XOS. -/// NOTE: Enabling this option does have some impact on runtime performance -/// and OS footprint. -/// -//----------------------------------------------------------------------------- -#ifndef XOS_OPT_STATS -#define XOS_OPT_STATS 1 -#endif - - -//----------------------------------------------------------------------------- -/// -/// Set this option to 1 to enable statistics tracking for message queues. -/// enabling this will cause message queue objects to increase in size, and add -/// some overhead to message queue processing. -/// -//----------------------------------------------------------------------------- -#ifndef XOS_OPT_MSGQ_STATS -#define XOS_OPT_MSGQ_STATS 0 -#endif - - -//----------------------------------------------------------------------------- -/// -/// Size of interrupt stack in bytes. Shared by all interrupt handlers. Must be -/// sized to handle worst case nested interrupts. This is also used by the idle -/// thread so must exist even if interrupts are not configured. -/// -//----------------------------------------------------------------------------- -#ifndef XOS_INT_STACK_SIZE -#if XCHAL_HAVE_INTERRUPTS -#define XOS_INT_STACK_SIZE 8192 -#else -#define XOS_INT_STACK_SIZE 32 -#endif -#endif - - -//----------------------------------------------------------------------------- -/// -/// Default maximum interrupt level at which XOS primitives may be called. -/// It is the level at which interrupts are disabled by default. -/// See also description of xos_set_int_pri_level(). -/// -//----------------------------------------------------------------------------- -#ifndef XOS_MAX_OS_INTLEVEL -#define XOS_MAX_OS_INTLEVEL XCHAL_EXCM_LEVEL -#endif - - -//----------------------------------------------------------------------------- -/// -/// Set this to 1 to enable stack checking. The stack is filled with a pattern -/// on thread creation, and the stack is checked at certain times during system -/// operation. -/// WARNING: Enabling this option can have some impact on runtime performance. -/// -//----------------------------------------------------------------------------- -#ifndef XOS_OPT_STACK_CHECK -#if XOS_DEBUG -#define XOS_OPT_STACK_CHECK 1 -#else -#define XOS_OPT_STACK_CHECK 0 -#endif -#endif - - -//----------------------------------------------------------------------------- -/// -/// Set XOS_CLOCK_FREQ to the system clock frequency if this is known ahead of -/// time. Otherwise, call xos_set_clock_freq() to set it at run time. -/// -//----------------------------------------------------------------------------- -#ifndef XOS_CLOCK_FREQ -#define XOS_CLOCK_FREQ 1000000 -#endif -#define XOS_DEFAULT_CLOCK_FREQ XOS_CLOCK_FREQ - - -//----------------------------------------------------------------------------- -/// -/// Set this option to 1 to enable software prioritization of interrupts. The -/// priority scheme applied is that a higher interrupt number at the same level -/// will have higher priority. -/// -//----------------------------------------------------------------------------- -#ifndef XOS_OPT_INTERRUPT_SWPRI -#define XOS_OPT_INTERRUPT_SWPRI 1 -#endif - - -//----------------------------------------------------------------------------- -/// -/// Set this option to 1 to use the thread-safe version of the C runtime library. -/// You may need to enable this if you call C library functions from multiple -/// threads -- see the documentation for the relevant C library to determine if -/// this is necessary. This option increases the size of the TCB. -/// NOTE: At this time only the newlib and xclib libraries are supported for -/// thread safety. -/// -//----------------------------------------------------------------------------- -#include - -#ifndef XOS_OPT_THREAD_SAFE_CLIB - -#if XSHAL_CLIB == XTHAL_CLIB_XCLIB -#define XOS_OPT_THREAD_SAFE_CLIB 1 -#elif XSHAL_CLIB == XTHAL_CLIB_NEWLIB -#define XOS_OPT_THREAD_SAFE_CLIB 1 -#else -#define XOS_OPT_THREAD_SAFE_CLIB 0 -#endif - -#endif - - -//----------------------------------------------------------------------------- -/// -/// Set this option to 1 to enable the wait timeout feature. This allows waits -/// on waitable objects to expire after a specified timeout. -/// -//----------------------------------------------------------------------------- -#ifndef XOS_OPT_WAIT_TIMEOUT -#define XOS_OPT_WAIT_TIMEOUT 1 -#endif - - -//----------------------------------------------------------------------------- -/// -/// Set this option to 1 to enable threads waiting on timer objects. If this -/// feature is not used, turning it off will make timer objects smaller, and -/// reduce the time taken by timer expiry processing (by a small amount). -/// -//----------------------------------------------------------------------------- -#ifndef XOS_OPT_TIMER_WAIT -#define XOS_OPT_TIMER_WAIT 1 -#endif - - -//----------------------------------------------------------------------------- -/// -/// Set this option to 1 to enable time-slicing between multiple threads at the -/// same priority. If this option is enabled then on every timer tick the timer -/// handler will switch out the current thread if there is another ready thread -/// at the same priority, and allow the latter thread to run. Execution will be -/// round robin switched among all the threads at the same priority. -/// -/// Currently the time slice interval is fixed to be one timer tick. -/// -/// This feature is most useful if fixed duration timer ticks are used. -/// If dynamic ticking is enabled, then time slicing will work unpredictably -/// because the interval between ticks will vary. In some cases it may be -/// better to turn time slicing off. -/// -//----------------------------------------------------------------------------- -#ifndef XOS_OPT_TIME_SLICE -#define XOS_OPT_TIME_SLICE 1 -#endif - - -#ifdef __cplusplus -} -#endif - -#endif // __XOS_PARAMS_H__ - diff --git a/components/esp32/include/xtensa/xos_regaccess.h b/components/esp32/include/xtensa/xos_regaccess.h deleted file mode 100644 index 1fea5ddc28..0000000000 --- a/components/esp32/include/xtensa/xos_regaccess.h +++ /dev/null @@ -1,201 +0,0 @@ - -// xos_regaccess.h - Access routines for various processor special registers. - -// 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. - -#ifndef __REGACCESS_H__ -#define __REGACCESS_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -#include "xos_types.h" - -#include - -#if defined (__XCC__) -#if XCHAL_HAVE_CCOUNT -#include -#endif -#endif - - -//----------------------------------------------------------------------------- -// Read CCOUNT register. -//----------------------------------------------------------------------------- -static __inline__ uint32_t xos_get_ccount(void) -{ -#if XCHAL_HAVE_CCOUNT - -#if defined (__XCC__) - return XT_RSR_CCOUNT(); -#else - uint32_t ccount; - - __asm__ __volatile__ ( "rsr %0, ccount" : "=a" (ccount) ); - return ccount; -#endif - -#else - - return 0; - -#endif -} - - -//----------------------------------------------------------------------------- -// Read CCOMPARE0 -//----------------------------------------------------------------------------- -static __inline__ uint32_t xos_get_ccompare0(void) -{ -#if XCHAL_HAVE_CCOUNT - -#if defined (__XCC__) - return XT_RSR_CCOMPARE0(); -#else - uint32_t ccompare0; - - __asm__ __volatile__ ( "rsr %0, ccompare0" : "=a" (ccompare0)); - return ccompare0; -#endif - -#else - - return 0; - -#endif -} - - -//----------------------------------------------------------------------------- -// Read CCOMPARE1 -//----------------------------------------------------------------------------- -#if (XCHAL_NUM_TIMERS > 1) -static __inline__ uint32_t xos_get_ccompare1(void) -{ -#if defined (__XCC__) - return XT_RSR_CCOMPARE1(); -#else - uint32_t ccompare1; - - __asm__ __volatile__ ( "rsr %0, ccompare1" : "=a" (ccompare1)); - return ccompare1; -#endif -} -#endif - - -//----------------------------------------------------------------------------- -// Read CCOMPARE2 -//----------------------------------------------------------------------------- -#if (XCHAL_NUM_TIMERS > 2) -static __inline__ uint32_t xos_get_ccompare2(void) -{ -#if defined (__XCC__) - return XT_RSR_CCOMPARE2(); -#else - uint32_t ccompare2; - - __asm__ __volatile__ ( "rsr %0, ccompare2" : "=a" (ccompare2)); - return ccompare2; -#endif -} -#endif - - -//----------------------------------------------------------------------------- -// Write CCOMPARE0 -//----------------------------------------------------------------------------- -static __inline__ void xos_set_ccompare0(uint32_t val) -{ -#if XCHAL_HAVE_CCOUNT - -#if defined (__XCC__) - XT_WSR_CCOMPARE0(val); - XT_ISYNC(); -#else - __asm__ __volatile__ ( - "wsr %0, ccompare0\n" - "isync" - : - : "a" (val) - ); -#endif - -#else - - // Empty - -#endif -} - - -//----------------------------------------------------------------------------- -// Write CCOMPARE1 -//----------------------------------------------------------------------------- -#if (XCHAL_NUM_TIMERS > 1) -static __inline__ void xos_set_ccompare1(uint32_t val) -{ -#if defined (__XCC__) - XT_WSR_CCOMPARE1(val); - XT_ISYNC(); -#else - __asm__ __volatile__ ( - "wsr %0, ccompare1\n" - "isync" - : - : "a" (val) - ); -#endif -} -#endif - - -//----------------------------------------------------------------------------- -// Write CCOMPARE2 -//----------------------------------------------------------------------------- -#if (XCHAL_NUM_TIMERS > 2) -static __inline__ void xos_set_ccompare2(uint32_t val) -{ -#if defined (__XCC__) - XT_WSR_CCOMPARE2(val); - XT_ISYNC(); -#else - __asm__ __volatile__ ( - "wsr %0, ccompare2\n" - "isync" - : - : "a" (val) - ); -#endif -} -#endif - - -#ifdef __cplusplus -} -#endif - -#endif // __REGACCESS_H__ - diff --git a/components/esp32/include/xtensa/xos_semaphore.h b/components/esp32/include/xtensa/xos_semaphore.h deleted file mode 100644 index 42b7914ef0..0000000000 --- a/components/esp32/include/xtensa/xos_semaphore.h +++ /dev/null @@ -1,190 +0,0 @@ -/** @file */ - -// xos_semaphore.h - XOS Semaphore API interface and data structures. - -// 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. - -// NOTE: Do not include this file directly in your application. Including -// xos.h will automatically include this file. - -#ifndef __XOS_SEMAPHORE_H__ -#define __XOS_SEMAPHORE_H__ - -#include "xos_types.h" - -#ifdef __cplusplus -extern "C" { -#endif - - -//----------------------------------------------------------------------------- -// Semaphore flags. -//----------------------------------------------------------------------------- -#define XOS_SEM_WAIT_PRIORITY 0x0000 ///< Wake waiters in priority order (default) -#define XOS_SEM_WAIT_FIFO 0x0001 ///< Wake waiters in FIFO order -#define XOS_SEM_PRIORITY_INV 0x0004 // Protect against priority inversion - - -//----------------------------------------------------------------------------- -/// -/// XosSem object. -/// -//----------------------------------------------------------------------------- -typedef struct XosSem { - uint32_t count; ///< Current count - XosThreadQueue waitq; ///< Queue of waiters. - uint32_t flags; ///< Properties. -#if XOS_SEM_DEBUG - uint32_t sig; // Valid signature indicates inited. -#endif -} XosSem; - - -//----------------------------------------------------------------------------- -/// -/// Initialize a semaphore object before first use. -/// -/// \param sem Pointer to semaphore object. -/// -/// \param flags Creation flags: -/// - XOS_SEM_WAIT_FIFO -- queue waiting threads in -/// fifo order. -/// - XOS_SEM_WAIT_PRIORITY -- queue waiting threads -/// by priority. This is the default. -/// - XOS_SEM_PRIORITY_INV -- protect against priority -/// inversion. -/// -/// \param initial_count Initial count for semaphore on creation. -/// -/// \return Returns XOS_OK on success, else error code. -/// -/// NOTE: XOS_SEM_PRIORITY_INV is NOT supported in the current release. It will -/// be supported in a future release. -/// -//----------------------------------------------------------------------------- -int32_t -xos_sem_create(XosSem * sem, uint32_t flags, uint32_t initial_count); - - -//----------------------------------------------------------------------------- -/// -/// Destroy a semaphore object. Must have been previously created by calling -/// xos_sem_create(). -/// -/// \param sem Pointer to semaphore object. -/// -/// \return Returns XOS_OK on success, else error code. -/// -//----------------------------------------------------------------------------- -int32_t -xos_sem_delete(XosSem * sem); - - -//----------------------------------------------------------------------------- -/// -/// Decrement the semaphore count: block until the decrement is possible. -/// The semaphore must have been initialized. -/// -/// \param sem Pointer to semaphore object. -/// -/// \return Returns XOS_OK on success, else error code. -/// -//----------------------------------------------------------------------------- -int32_t -xos_sem_get(XosSem * sem); - - -//----------------------------------------------------------------------------- -/// -/// Decrement the semaphore count: block until the decrement is possible or -/// the timeout expires. The semaphore must have been initialized. -/// -/// \param sem Pointer to semaphore object. -/// -/// \param to_cycles Timeout in cycles. Convert from time to cycles -/// using the helper functions provided in xos_timer. -/// A value of zero indicates no timeout. -/// -/// \return Returns XOS_OK on success, XOS_ERR_TIMEOUT on timeout, else error code. -/// -/// NOTE: If XOS_OPT_WAIT_TIMEOUT is not enabled, then the timeout value is -/// ignored, and no timeout will occur. -/// -//----------------------------------------------------------------------------- -int32_t -xos_sem_get_timeout(XosSem * sem, uint64_t to_cycles); - - -//----------------------------------------------------------------------------- -/// -/// Increment the semaphore count. The semaphore must have been initialized. -/// Remember that this action may wake up a waiting thread, and if that thread -/// is higher priority then there will be an immediate context switch. -/// -/// \param sem Pointer to semaphore object. -/// -/// \return Returns XOS_OK on success, else error code. -/// -//----------------------------------------------------------------------------- -int32_t -xos_sem_put(XosSem * sem); - - -//----------------------------------------------------------------------------- -/// -/// Try to decrement the semaphore, but do not block if the semaphore count is -/// zero. Return immediately. The semaphore must have been initialized. -/// -/// \param sem Pointer to semaphore object. -/// -/// \return Returns XOS_OK on success (semaphore decremented), else error code. -/// -//----------------------------------------------------------------------------- -int32_t -xos_sem_tryget(XosSem * sem); - - -//----------------------------------------------------------------------------- -/// -/// Return the count of the semaphore but do not attempt to decrement it. -/// The semaphore must have been initialized. -/// -/// \param sem Pointer to semaphore object. -/// -/// \return Returns semaphore count, -1 on error. -/// -//----------------------------------------------------------------------------- -static inline int32_t -xos_sem_test(XosSem * sem) -{ - XOS_ASSERT(sem); - - return sem ? sem->count : -1; -} - - -#ifdef __cplusplus -} -#endif - -#endif // __XOS_SEMAPHORE_H__ - diff --git a/components/esp32/include/xtensa/xos_stopwatch.h b/components/esp32/include/xtensa/xos_stopwatch.h deleted file mode 100644 index bf71cc388b..0000000000 --- a/components/esp32/include/xtensa/xos_stopwatch.h +++ /dev/null @@ -1,175 +0,0 @@ -/** @file */ - -// xos_stopwatch.h - XOS Stopwatch objects and related API. - -// 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. - -// NOTE: Do not include this file directly in your application. Including -// xos.h will automatically include this file. - - -#ifndef __XOS_STOPWATCH_H__ -#define __XOS_STOPWATCH_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -#include "xos_types.h" -#include "xos_params.h" - - -//----------------------------------------------------------------------------- -// A stopwatch object can be used to track elapsed time and accumulate total -// elapsed time over multiple execution periods. The stopwatch records the -// time whenever its start function is called, and stops recording the time -// when the stop function is called and updates its cumulative time counter. -// The stopwatch keeps time in cycles. This can be converted to seconds etc. -// by using the XOS conversion calls such as xos_cycles_to_secs(). -//----------------------------------------------------------------------------- - - -//----------------------------------------------------------------------------- -/// -/// XosStopwatch object. -/// -//----------------------------------------------------------------------------- -typedef struct XosStopwatch { - uint64_t total; ///< Total accumulated cycle count - uint64_t start; ///< Starting system cycle count - uint16_t active; ///< Active flag (nonzero when active) -} XosStopwatch; - - -//----------------------------------------------------------------------------- -/// -/// Initialize a stopwatch object. -/// -/// \param sw Pointer to a stopwatch object. -/// -/// \return Returns nothing. -/// -//----------------------------------------------------------------------------- -static inline void -xos_stopwatch_init(XosStopwatch * sw) -{ - sw->total = 0; - sw->start = 0; - sw->active = 0; -} - - -//----------------------------------------------------------------------------- -/// -/// Start a stopwatch. Starts cycle counting. -/// Note that this does not necessarily start counting from zero. The current -/// run (start-to-stop interval) will just get added to the accumulated count -/// in the stopwatch if any. -/// To reset the accumulated count, use xos_stopwatch_clear(). -/// -/// \param sw Pointer to a stopwatch object. -/// -/// \return Returns nothing. -/// -//----------------------------------------------------------------------------- -static inline void -xos_stopwatch_start(XosStopwatch * sw) -{ - XOS_ASSERT(!sw->active); - sw->active = 1; - sw->start = xos_get_system_cycles(); -} - - -//----------------------------------------------------------------------------- -/// -/// Stop a stopwatch. Stops cycle counting and updates total. -/// -/// \param sw Pointer to a stopwatch object. -/// -/// \return Returns nothing. -/// -//----------------------------------------------------------------------------- -static inline void -xos_stopwatch_stop(XosStopwatch * sw) -{ - XOS_ASSERT(sw->active); - sw->active = 0; - sw->total += xos_get_system_cycles() - sw->start; -} - - -//----------------------------------------------------------------------------- -/// -/// Get stopwatch accumulated count. -/// -/// \param sw Pointer to a stopwatch object. -/// -/// \return Returns the accumulated count. -/// -//----------------------------------------------------------------------------- -static inline uint64_t -xos_stopwatch_count(XosStopwatch * sw) -{ - return sw->total; -} - - -//----------------------------------------------------------------------------- -/// -/// Get elapsed time since stopwatch was started. If not started, returns zero. -/// -/// \param sw Pointer to a stopwatch object. -/// -/// \return Returns elapsed time in cycles. -/// -//----------------------------------------------------------------------------- -static inline uint64_t -xos_stopwatch_elapsed(XosStopwatch * sw) -{ - return sw->active ? xos_get_system_cycles() - sw->start : 0; -} - - -//----------------------------------------------------------------------------- -/// -/// Clears a stopwatch. Resets the accumulated count to zero, and deactivates -/// it if active. -/// -/// \param sw Pointer to a stopwatch object. -/// -/// \return Returns nothing. -/// -//----------------------------------------------------------------------------- -static inline void -xos_stopwatch_clear(XosStopwatch * sw) -{ - xos_stopwatch_init(sw); -} - - -#ifdef __cplusplus -} -#endif - -#endif // __XOS_STOPWATCH_H__ - diff --git a/components/esp32/include/xtensa/xos_syslog.h b/components/esp32/include/xtensa/xos_syslog.h deleted file mode 100644 index be56968fce..0000000000 --- a/components/esp32/include/xtensa/xos_syslog.h +++ /dev/null @@ -1,330 +0,0 @@ -/** @file */ - -// xos_syslog.h - XOS Event logging module. - -// 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. - -// NOTE: Do not include this file directly in your application. Including -// xos.h will automatically include this file. - - -#ifndef __XOS_SYSLOG_H__ -#define __XOS_SYSLOG_H__ - -#include "xos_types.h" - -#ifdef __cplusplus -extern "C" { -#endif - - -//----------------------------------------------------------------------------- -// The XOS system log is an array of fixed size entries. The size of the log -// is determined by the application, and memory for the log must be provided -// at init time. Every time the log function is called, an entry is made in -// the log and the next pointer advanced. When the log is full, it will wrap -// around and start overwriting the oldest entries. -// Logging can be done from C/C++ code as well as assembly code, and at any -// interrupt level, even from high level interrupt handlers. -//----------------------------------------------------------------------------- - - -//----------------------------------------------------------------------------- -// Defines. -//----------------------------------------------------------------------------- -#define XOS_SYSLOG_ENABLED 0x0001 - - -///---------------------------------------------------------------------------- -/// -/// Use this macro to compute how much memory to allocate for the syslog. -/// -///---------------------------------------------------------------------------- -#define XOS_SYSLOG_SIZE(num_entries) \ - ( sizeof(XosSysLog) + ((num_entries - 1) * sizeof(XosSysLogEntry)) ) - - -///---------------------------------------------------------------------------- -/// -/// System log entry structure. -/// -///---------------------------------------------------------------------------- -typedef struct XosSysLogEntry { - uint32_t timestamp; ///< Timestamp in clock cycles - uint32_t param1; ///< User defined value - uint32_t param2; ///< User defined value - struct XosSysLogEntry * next; ///< Link to next entry -} XosSysLogEntry; - - -///---------------------------------------------------------------------------- -/// -/// System log structure. -/// -///---------------------------------------------------------------------------- -typedef struct XosSysLog { - uint16_t flags; ///< Flags - uint16_t size; ///< Number of entries - XosSysLogEntry * next; ///< Next write position - XosSysLogEntry entries[1]; ///< First entry -} XosSysLog; - - -//----------------------------------------------------------------------------- -// Pointer to syslog area. -//----------------------------------------------------------------------------- -extern XosSysLog * xos_syslog; - - -//---------------------------------------------------------------------------- -/// -/// Initialize the syslog. Initializing the log also enables it. The system -/// log always wraps around when full and overwrites the oldest entries. -/// -/// \param log_mem Pointer to allocated memory for the log. -/// -/// \param num_entries The number of entries that the log can contain. -/// -/// \return Returns nothing. -/// -//---------------------------------------------------------------------------- -static inline void -xos_syslog_init(void * log_mem, uint16_t num_entries) -{ - uint16_t i; - - xos_syslog = (XosSysLog *) log_mem; - xos_syslog->size = num_entries; - xos_syslog->next = xos_syslog->entries; - - for (i = 0; i < num_entries - 1; i++) { - xos_syslog->entries[i].next = &(xos_syslog->entries[i+1]); - xos_syslog->entries[i].timestamp = 0; - } - xos_syslog->entries[i].next = xos_syslog->entries; - xos_syslog->entries[i].timestamp = 0; - - xos_syslog->flags = XOS_SYSLOG_ENABLED; -} - - -///---------------------------------------------------------------------------- -/// -/// Reset the syslog. All entries made up to now are abandoned and the write -/// pointer is set to the first entry location. -/// -/// No parameters. -/// -/// \return Returns nothing. -/// -///---------------------------------------------------------------------------- -static inline void -xos_syslog_clear() -{ -#if XCHAL_HAVE_INTERRUPTS - uint32_t ps = XT_RSIL(XCHAL_NUM_INTLEVELS); -#endif - - xos_syslog_init(xos_syslog, xos_syslog->size); -#if XCHAL_HAVE_INTERRUPTS - xos_restore_int_pri_level(ps); -#endif -} - - -///---------------------------------------------------------------------------- -/// -/// Enable logging to the syslog. This function needs to be called only if -/// logging had been previously disabled via xos_syslog_disable(), since -/// initializing the syslog automatically enables it. -/// -/// No parameters. -/// -/// \return Returns nothing. -/// -///---------------------------------------------------------------------------- -static inline void -xos_syslog_enable() -{ -#if XCHAL_HAVE_INTERRUPTS - uint32_t ps = XT_RSIL(XCHAL_NUM_INTLEVELS); -#endif - - xos_syslog->flags |= XOS_SYSLOG_ENABLED; -#if XCHAL_HAVE_INTERRUPTS - xos_restore_int_pri_level(ps); -#endif -} - - -///---------------------------------------------------------------------------- -/// -/// Disable logging to the syslog. It is sometimes useful to disable logging -/// while the log is being examined or dumped. -/// -/// No parameters. -/// -/// \return Returns nothing. -/// -///---------------------------------------------------------------------------- -static inline void -xos_syslog_disable() -{ -#if XCHAL_HAVE_INTERRUPTS - uint32_t ps = XT_RSIL(XCHAL_NUM_INTLEVELS); -#endif - xos_syslog->flags &= ~XOS_SYSLOG_ENABLED; -#if XCHAL_HAVE_INTERRUPTS - xos_restore_int_pri_level(ps); -#endif -} - - -///---------------------------------------------------------------------------- -/// -/// Write an entry into the syslog. This function does disable all interrupts -/// since logging can be done from interrupt handlers as well. It will write -/// into the log only if the log exists and is enabled. -/// -/// \param param1 User defined value. -/// -/// \param param2 User defined value. -/// -/// \return Returns nothing. -/// -///---------------------------------------------------------------------------- -static inline void -xos_syslog_write(uint32_t param1, uint32_t param2) -{ - if (xos_syslog != XOS_NULL) { -#if XCHAL_HAVE_INTERRUPTS - uint32_t ps = XT_RSIL(XCHAL_NUM_INTLEVELS); -#endif - - if ((xos_syslog->flags & XOS_SYSLOG_ENABLED) != 0) { - XosSysLogEntry * next = xos_syslog->next; - - next->timestamp = xos_get_ccount(); - next->param1 = param1; - next->param2 = param2; - - xos_syslog->next = next->next; - } - -#if XCHAL_HAVE_INTERRUPTS - xos_restore_int_pri_level(ps); -#endif - } -} - - -///---------------------------------------------------------------------------- -/// -/// Read the first (oldest) entry in the syslog. Will return an error if the -/// log has not been created or is empty. Storage to copy the entry must be -/// provided by the caller. -/// -/// \param entry Pointer to storage where the entry data will be -/// copied. This pointer must be passed to -/// xos_syslog_get_next(). -/// -/// \return Returns XOS_OK on success, else error code. -/// -///---------------------------------------------------------------------------- -static inline int32_t -xos_syslog_get_first(XosSysLogEntry * entry) -{ - if (xos_syslog == XOS_NULL) { - return XOS_ERR_NOT_FOUND; - } - - if (entry != XOS_NULL) { -#if XCHAL_HAVE_INTERRUPTS - uint32_t ps = XT_RSIL(XCHAL_NUM_INTLEVELS); -#endif - XosSysLogEntry * next = xos_syslog->next; - - // 'next' should be pointing to the next entry to be overwritten, if we - // have wrapped. This means it is the oldest entry. However if this entry - // has a zero timestamp then we have not wrapped, in which case we must - // look at the first entry in the list. - if (next->timestamp == 0) { - next = xos_syslog->entries; - } - - *entry = *next; -#if XCHAL_HAVE_INTERRUPTS - xos_restore_int_pri_level(ps); -#endif - return entry->timestamp ? XOS_OK : XOS_ERR_NOT_FOUND; - } - - return XOS_ERR_INVALID_PARAMETER; -} - - -///---------------------------------------------------------------------------- -/// -/// Get the next sequential entry from the syslog. This function must be called -/// only after xos_syslog_get_first() has been called. -/// -/// \param entry Pointer to storage where entry data will be copied. -/// Must be the same pointer that was passed in the call -/// to xos_syslog_get_first(), as it is used to keep track -/// of the current position. -/// -/// \return Returns XOS_OK on success, else error code. -/// -///---------------------------------------------------------------------------- -static inline int32_t -xos_syslog_get_next(XosSysLogEntry * entry) -{ - if (entry != XOS_NULL) { -#if XCHAL_HAVE_INTERRUPTS - uint32_t ps = XT_RSIL(XCHAL_NUM_INTLEVELS); -#endif - XosSysLogEntry * next = entry->next; - int32_t ret = XOS_OK; - - // Make sure we're not pointing past the last entry. - if ((next != XOS_NULL) && (next != xos_syslog->next) && (next->timestamp != 0)) { - *entry = *next; - } - else { - ret = XOS_ERR_NOT_FOUND; - } -#if XCHAL_HAVE_INTERRUPTS - xos_restore_int_pri_level(ps); -#endif - return ret; - } - - return XOS_ERR_INVALID_PARAMETER; -} - - -#ifdef __cplusplus -} -#endif - -#endif // __XOS_SYSLOG_H__ - diff --git a/components/esp32/include/xtensa/xos_thread.h b/components/esp32/include/xtensa/xos_thread.h deleted file mode 100644 index 8bc5077eca..0000000000 --- a/components/esp32/include/xtensa/xos_thread.h +++ /dev/null @@ -1,1086 +0,0 @@ -/** @file */ - -// xos_thread.h - XOS Thread API interface and data structures. - -// 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. - -// NOTE: Do not include this file directly in your application. Including -// xos.h will automatically include this file. - - -#ifndef __XOS_THREAD_H__ -#define __XOS_THREAD_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -#include "xos_types.h" -#include "xos_params.h" - - -//----------------------------------------------------------------------------- -// Number of thread priority levels. -//----------------------------------------------------------------------------- -#ifndef XOS_NUM_PRIORITY -#error "XOS_NUM_PRIORITY must be defined (in xos_params.h)." -#endif -#if XOS_NUM_PRIORITY > 32 -#error "The number of thread priority levels (XOS_NUM_PRIORITY) must be <= 32." -#endif -#define XOS_MAX_PRIORITY (XOS_NUM_PRIORITY) - - -//----------------------------------------------------------------------------- -// Macro for thread self pointer. -//----------------------------------------------------------------------------- -#define XOS_THREAD_SELF (xos_thread_id()) - - -//----------------------------------------------------------------------------- -/// -/// Thread entry function pointer type. -/// -//----------------------------------------------------------------------------- -typedef int32_t (XosThreadFunc)(void * arg, int32_t wake_value); - - -//----------------------------------------------------------------------------- -// Thread switcher function signature. -//----------------------------------------------------------------------------- -typedef struct XosThread XosThread; -typedef int32_t (XosSwitchFunc)(XosThread *); - - -//----------------------------------------------------------------------------- -/// -/// Condition evaluation callback function pointer type. -/// -//----------------------------------------------------------------------------- -typedef int32_t (XosCondFunc)(void * arg, int32_t sig_value, XosThread * thread); - - -//----------------------------------------------------------------------------- -/// -/// Thread exit handler function pointer type. -/// -//----------------------------------------------------------------------------- -typedef int32_t (XosThdExitFunc)(int32_t exitcode); - - -//----------------------------------------------------------------------------- -// Thread queue structure. Used to implement the ready queues as well -// as the wait queues. -//----------------------------------------------------------------------------- -typedef struct XosThreadQueue { - XosThread * head; // Pointer to first thread in queue, or 0 if none. - XosThread ** tail; // Pointer to last thread's r_next pointer, or - // to "head" if none. -} XosThreadQueue; - - -//----------------------------------------------------------------------------- -// Stack frame for a thread that is not running. That is, it has either -// been preempted or has yielded. -//----------------------------------------------------------------------------- -typedef union XosFrame { - XosExcFrame e; // resume_fn == &xos_resume_preempted_thread - XosCoopFrame c; // resume_fn == &xos_resume_cooperative_thread - // nothing for resume_fn == &xos_resume_idle_thread - // nothing for resume_fn == &xos_resume_by_restart -} XosFrame; - - -//----------------------------------------------------------------------------- -// Thread Control Block. Tracks the state and control information associated -// with a thread. -// -// IMPORTANT: keep this in sync with TCB_*** offsets in xos_common.h . -//----------------------------------------------------------------------------- -struct XosThread { - XosThread * r_next; // 00 Next thread in queue (eg. ready queue of - // its priority, or some queue of blocked threads) - // Should be NULL if not in any queue. - - XosThread ** r_pprev; // 04 Points to previous queue entry's r_next - // pointer (i.e. to itself), or to queue head - // if first in queue. NULL if not in any queue. - - XosThread * all_next; // 08 Next in list of all threads. - - void * resume_fn; // 12 Pointer to the routine to be called to - // resume this thread. On entry to such code: - // a2 == xos_curr_threadptr (thread being resumed) - // a3 == &xos_globals - - XosFrame * esf; // 16 Pointer to saved exception stack frame, - // just below thread's current stack pointer. - // For RTC threads, this is valid only while the - // thread is preempted, not when it is blocked. - - void * tie_save; // 20 TIE state save area. May be NULL if there - // is not TIE state saved for this thread. - - int32_t wake_value; // 24 Value returned from block call (by wake call) - // (for RTC: pass this to start function??) - - XosSwitchFunc * switch_fn; // 28 Pointer to a function that - // can be called from within this thread, to save - // this thread's state and switch to a specified - // other thread. Returns wake value. - - void * stack_base; // 32 Base of stack as specified by thread creator. - - void * stack_end; // 36 End of stack (adjusted for TIE state save area - // if any). - - XosThreadFunc * entry; // 40 Pointer to thread entry function. Used for - // RTC thread restart. - - void * arg; // 44 Argument value passed to entry function. - - bool ready; // 48 Set when thread is ready to run, and is in - // its priority queue (i.e. r_pprev is set when - // this flag is set). - - bool in_exit; // Exit flag, nonzero when in exit processing. - - int8_t priority; // Thread priority, 0 .. (XOS_MAX_PRI - 1). Higher - // numbers have higher priority. This must only be - // changed when thread is not ready, or by calling - // xos_thread_set_priority(). - - int8_t preempt_pri; // This thread's preemption blocking priority. - // (preempt_pri >= priority). A thread's priority - // must be higher than another's preempt_pri to be - // able to preempt it. Note that preempt_pri can - // change during runtime e.g. due to priority - // inheritance. - - uint32_t flags; // 52 Thread creation flags. - - const char * name; // 56 Thread name (mainly for debug). - - const char * block_cause; // 60 Reason for blocking. Valid only when thread - // not ready (r_pprev == 0). - - XosThread * container; // 64 Thread whose stack will be used to run - // this thread. Valid for RTC threads only, else NULL. - - XosThdExitFunc * exit_func; // 68 Thread exit handler function pointer. - - XosThreadQueue exit_waiters; // 72 Queue of threads waiting for this one to exit. - - XosThreadQueue * wq_ptr; // 80 If this thread is in a wait queue, this - // points to the queue. Must be NULL when - // thread not in a queue. - - XosCondFunc * cond_fn; // 84 Condition function. Valid only while thread - // is blocked on condition. - - void * cond_arg; // 88 Argument to be passed to condition function. - - uint16_t cp_mask; // 92 Mask of coprocessors used. - uint16_t cp_saved; // 94 Mask of coprocessors saved. - - uint32_t event_bits; // 96 event bits - uint32_t event_mask; // 100 event bit mask - uint32_t event_flags; // 104 event flags - - void * clib_ptr; // 108 Pointer to C lib context struct. - - uint32_t sig; // 112 Signature of valid TCB - - uint32_t resume_ccount; // 116 cycle count at resume - uint64_t cycle_count; // 120 number of cycles consumed (approx). - // NOTE: must be 8-byte aligned - uint32_t normal_resumes; // 128 Number of non-preemptive resumptions. - uint32_t preempt_resumes;// 132 Number of preemptive resumptions. - -#if XOS_OPT_THREAD_SAFE_CLIB - CLIB_THREAD_STRUCT; // C library context area. -#endif -}; - - -//----------------------------------------------------------------------------- -// User-visible flags for xos_thread_create(). -//----------------------------------------------------------------------------- -#define XOS_THREAD_SUSPEND 0x0001 ///< Create suspended instead of ready -#define XOS_THREAD_RTC 0x0002 ///< Run-to-completion thread -#define XOS_THREAD_NO_CP 0x0004 ///< Thread does not use coprocessors - - -//----------------------------------------------------------------------------- -// Flags used by thread creation extra parameters. -//----------------------------------------------------------------------------- -#define XOS_TP_COPROC_MASK 0x0001 -#define XOS_TP_PREEMPT_PRI 0x0002 -#define XOS_TP_EXIT_HANDLER 0x0004 - - -//----------------------------------------------------------------------------- -// Thread creation extra parameters. -//----------------------------------------------------------------------------- -typedef struct XosThreadParm { - uint32_t parms_mask; // Combination of XOS_TP_xxx flags indicating - // which parameters are valid. - - uint16_t cp_mask; // Mask of coprocessors the thread can access. - - uint32_t preempt_pri; // Initial preemption blocking priority. Can be - // changed later via xos_thread_set_priority(). - - XosThdExitFunc * handler; // Exit handler function. - -} XosThreadParm; - - -//----------------------------------------------------------------------------- -// Wrapper struct for RTC (run to completion) thread. -//----------------------------------------------------------------------------- -typedef struct XosRtcThread { - struct XosThread thread; -} XosRtcThread; - - -//----------------------------------------------------------------------------- -// External variables. -//----------------------------------------------------------------------------- -extern XosThread * xos_curr_threadptr; // Current active thread -extern XosThread * xos_next_threadptr; // Next ready thread -extern XosThread * xos_all_threads; // List of all threads - - -//----------------------------------------------------------------------------- -/// -/// Set thread creation parameter: the group of coprocessors that this thread -/// will use. This must be set during thread creation, and cannot be changed -/// after the thread has been created. Defining this allows reduction of -/// memory usage (for CP state saving) in some circumstances, and can also -/// speed up the context switch time. -/// -/// NOTE: Support for this is not currently implemented. If a thread uses -/// any coprocessor, space for all coprocessors must be reserved. -/// -/// \param parms Thread creation parameter structure. Must be -/// allocated by the caller. -/// -/// \param cp_mask Bitmask of coprocessors thread is allowed to -/// use. Bit 0 for coprocessor 0, etc. -/// -/// \return Returns nothing. -/// -//----------------------------------------------------------------------------- -static inline void -xos_threadp_set_cp_mask(XosThreadParm * parms, uint16_t cp_mask) -{ - if (parms != XOS_NULL) { - parms->parms_mask |= XOS_TP_COPROC_MASK; - parms->cp_mask = cp_mask; - } -} - - -//----------------------------------------------------------------------------- -/// -/// Set thread creation parameter: thread pre-emption priority. -/// -/// \param parms Thread creation parameter structure. Must be -/// allocated by caller. -/// -/// \param preempt_pri Thread pre-emption blocking priority. -/// From 0 .. XOS_NUM_PRIORITY - 1. -/// Must be greater or equal to the thread priority -/// (if not, is automatically set to thread priority). -/// -/// \return Returns nothing. -/// -//----------------------------------------------------------------------------- -static inline void -xos_threadp_set_preemption_priority(XosThreadParm * parms, int8_t preempt_pri) -{ - if (parms != XOS_NULL) { - parms->parms_mask |= XOS_TP_PREEMPT_PRI; - parms->preempt_pri = preempt_pri; - } -} - - -//----------------------------------------------------------------------------- -/// -/// Set thread creation parameter: thread exit handler. -/// -/// \param parms Thread creation parameter structure. Must be -/// allocated by caller. -/// -/// \param handler Exit handler function. -/// -/// \return Returns nothing. -//----------------------------------------------------------------------------- -static inline void -xos_threadp_set_exit_handler(XosThreadParm * parms, XosThdExitFunc * handler) -{ - if (parms != XOS_NULL) { - parms->parms_mask |= XOS_TP_EXIT_HANDLER; - parms->handler = handler; - } -} - - -//----------------------------------------------------------------------------- -/// -/// Create a new thread. If the thread is not created suspended, then it will -/// be made ready as soon as it is created, and will immediately run if it is -/// the highest priority non-blocked thread in the system. -/// -/// \param thread Pointer to the thread descriptor (an otherwise -/// unused XosThread structure, usually allocated -/// by the caller for the lifetime of the thread, -/// for example as a global variable). -/// -/// \param container Pointer to separate thread acting as "container" -/// for this one. At the moment, this is only meaningful -/// for run-to-completion (RTC) threads (identified with -/// the XOS_THREAD_RTC flag), in which case the container -/// must have the same priority and also be an RTC thread. -/// (The priority restriction may be lifted in a future -/// implementation, with appropriate constraints on dynamic -/// reprioritization of the created thread). -/// -/// \param entry Thread entry function, takes one argument. -/// -/// \param arg Argument "void*" that is passed to the thread function. -/// -/// \param name Unique name of the thread, for debug/display purposes. -/// This string must be valid for the lifetime of the thread -/// (only a pointer to it is stored in the thread control block). -/// Typically consists of identifier chars with no spaces. -/// -/// \param stack Base of initial stack for the thread, allocated by the -/// caller. Need not be aligned (initial stack pointer will be -/// computed and aligned from given stack base and size). -/// Required argument, except for run-to-completion threads -/// when container is non-NULL, in which case the container's -/// stack is used and this argument must be NULL. -/// -/// \param stack_size Size of the stack, in bytes. -/// NOTE: stack should be at least XOS_STACK_EXTRA bytes plus -/// whatever the thread actually needs if the thread will use -/// coprocessors/TIE state. If the thread will not touch the -/// coprocessors, then it should be XOS_STACK_EXTRA_NO_CP -/// plus whatever the thread actually needs. -/// Recommended minimum stack sizes are defined by the constants -/// XOS_STACK_MIN_SIZE and XOS_STACK_MIN_SIZE_NO_CP. -/// -/// For run-to-completion threads where container is non-NULL, -/// stack_size specifies the minimum stack size required for -/// the thread; it should be smaller or equal to the container's -/// stack. -/// -/// \param priority Initial thread priority. From 0 .. XOS_MAX_PRI - 1. -/// Higher numbers are higher priority. -/// -/// \param parms Pointer to extra parameters structure, or 0 if none given. -/// Use xos_thread_p_***() functions to set parameters in the -/// structure. -/// -/// \param flags Option flags: -/// - XOS_THREAD_SUSPEND -- Leave thread suspended instead of -/// making it ready. The thread can be made ready to run later -/// by calling xos_thread_resume(). -/// - XOS_THREAD_RTC -- Run-to-completion thread. -/// - XOS_THREAD_NO_CP -- Thread does not use coprocessors. -/// No coprocessor state will be saved for this thread. -/// Threads that have this flag set will not allocate any -/// storage for saving coprocessor state and so can have -/// smaller stacks. -/// -/// NOTE: xos_start_main() calls xos_thread_create() to convert main() into the 'main' -/// thread. -/// -/// \return Returns XOS_OK if successful, error code otherwise. -/// -//----------------------------------------------------------------------------- -int32_t -xos_thread_create(XosThread * thread, - XosThread * container, - XosThreadFunc * entry, - void * arg, - const char * name, - void * stack, - uint32_t stack_size, - int32_t priority, - XosThreadParm * parms, - uint32_t flags ); - - -//----------------------------------------------------------------------------- -/// -/// Remove thread and free up all resources. Thread must have exited already. -/// After this call returns, all resources allocated to the thread (e.g. TCB, -/// stack space, etc.) can be reused. -/// -/// \param thread Handle of thread to be deleted. -/// -/// \return Returns XOS_OK on success, else error code. -/// -/// NOTE: A thread cannot call this on itself. -/// -//----------------------------------------------------------------------------- -int32_t -xos_thread_delete(XosThread * thread); - - -//----------------------------------------------------------------------------- -/// -/// Force the thread to terminate. The thread execution is aborted, but exit -/// processing will still happen, i.e. the exit handler (if any) will be run. -/// After termination, any other threads waiting on this thread are notified. -/// This function cannot be called on the current thread. -/// -/// \param thread Handle of thread to be aborted. -/// -/// \param exitcode Exit code returned to any waiting threads. -/// -/// \return Returns XOS_OK on success, else error code. -/// -/// NOTE: If the thread is blocked waiting for something, the wait is aborted -/// and the thread is made ready. -/// NOTE: The thread is not guaranteed to have exited when this call returns. -/// It will be made ready and set up for exit processing, but when the exit -/// processing will actually happen depends on the state of the system and -/// the priority of the thread being aborted. -/// -//----------------------------------------------------------------------------- -int32_t -xos_thread_abort(XosThread * thread, int32_t exitcode); - - -//----------------------------------------------------------------------------- -/// -/// Exit the current thread. The exit handler (if any) will be run before the -/// thread terminates. -/// -/// \param exitcode Exit code to be returned to any waiting threads. -/// -/// \return This function does not return. -/// -/// NOTE: This is automatically called if the thread returns from its entry -/// function. The entry function's return value will be passed as the exit -/// code. -/// -//----------------------------------------------------------------------------- -void -xos_thread_exit(int32_t exitcode); - - -//----------------------------------------------------------------------------- -/// -/// Wait until the specified thread exits and get its exit code. If the thread -/// has exited already, an error will be returned. -/// -/// \param thread The thread to wait for. Cannot be "self", i.e. -/// one cannot wait on one's own exit. -/// -/// \param p_exitcode If not null, the exit code will be returned here. -/// -/// \return Returns XOS_OK on sucess, else error code. -/// -//----------------------------------------------------------------------------- -int32_t -xos_thread_join(XosThread * thread, int32_t * p_exitcode); - - -//----------------------------------------------------------------------------- -/// -/// Yield the CPU to the next thread in line. The calling thread remains ready -/// and is placed at the tail of the ready queue at its current priority level. -/// If there are no threads at the same priority level that are ready to run, -/// then this call will return immediately. -/// -/// \return Returns nothing. -/// -//----------------------------------------------------------------------------- -void -xos_thread_yield(); - - -//----------------------------------------------------------------------------- -/// -/// Suspend the specified thread. The thread will remain suspended until -/// xos_thread_resume() has been called on it. If the thread is already blocked -/// on some other condition, then this function will return an error. -/// -/// \param thread Handle of thread being suspended. A thread can -/// use the special handle XOS_THREAD_SELF to suspend -/// itself. -/// -/// \return Returns XOS_OK on success, else error code. -/// -//----------------------------------------------------------------------------- -int32_t -xos_thread_suspend(XosThread * thread); - - -//----------------------------------------------------------------------------- -/// -/// Resume a suspended thread. If the thread is not suspended or is blocked on -/// some other condition then this function will do nothing. Otherwise, it will -/// be made ready, and this can cause an immediate context switch if the thread -/// is at a higher priority than the calling thread. -/// -/// \param thread Handle of thread being resumed. -/// -/// \return Returns XOS_OK on success, else error code. -/// -//----------------------------------------------------------------------------- -int32_t -xos_thread_resume(XosThread * thread); - - -//----------------------------------------------------------------------------- -/// -/// Get the priority of the specified thread. This returns the priority of the -/// queried thread at this instant, however this can change at any time due to -/// other activity in the system. -/// -/// \param thread Handle of thread being queried. A thread can use -/// the special handle XOS_THREAD_SELF to query itself. -/// -/// \return Returns the thread's current priority, or -1 if the thread handle -/// is not valid. -/// -//----------------------------------------------------------------------------- -static inline int32_t -xos_thread_get_priority(XosThread * thread) -{ - XOS_ASSERT(thread); - return thread ? thread->priority : -1; -} - - -//----------------------------------------------------------------------------- -/// -/// Set the priority of the specified thread. The thread must exist. -/// -/// \param thread Handle of thread being affected. A thread can -/// use the special handle XOS_THREAD_SELF to specify -/// itself. -/// -/// \param priority The new priority level to be set. -/// -/// \return Returns XOS_OK on success, else error code. -/// -/// NOTE: Calling this function can result in a scheduler activation, and the -/// caller may be suspended as a result. -/// -//----------------------------------------------------------------------------- -int32_t -xos_thread_set_priority(XosThread * thread, int32_t priority); - - -//----------------------------------------------------------------------------- -/// -/// Return the name of the specified thread. -/// -/// \param thread Handle of thread being queried. A thread can use -/// the special handle XOS_THREAD_SELF to specify -/// itself. -/// -/// \return Returns a pointer to the name string if available, else NULL. -/// -//----------------------------------------------------------------------------- -static inline const char * -xos_thread_get_name(XosThread * thread) -{ - XOS_ASSERT(thread); - return thread ? thread->name : 0; -} - - -//----------------------------------------------------------------------------- -/// -/// Set the name of the specified thread. -/// -/// \param thread Handle of thread whose name is to be set. A thread -/// can use the special handle XOS_THREAD_SELF to specify -/// itself. -/// -/// \param name Pointer to the new name string. The string is not -/// copied, only the pointer is saved. So the string -/// must be persistent for the life of the thread. -/// -/// \return Returns XOS_OK on success, else error code. -/// -//----------------------------------------------------------------------------- -static inline int32_t -xos_thread_set_name(XosThread * thread, const char * name) -{ - XOS_ASSERT(thread); - if (thread != XOS_NULL) { - thread->name = name; - return XOS_OK; - } - - return XOS_ERR_INVALID_PARAMETER; -} - - -//----------------------------------------------------------------------------- -/// -/// Set an exit handler for the specified thread. The exit handler is run when -/// the thread terminates, either by calling xos_thread_exit() or by returning -/// from its entry function. It will also be called if the thread is being -/// terminated due to e.g. an unhandled exception. -/// -/// The handler must be a function defined as e.g.: -/// -/// int32_t exit_handler(int32_t exitcode); -/// -/// The exit handler runs in the context of the exiting thread, and can call -/// system services. It is provided with a single parameter which is the -/// thread's exit code (the exit code may be set to an error code if the -/// thread is being terminated due to an error or exception). The handler -/// must return a value which will be set as the thread's exit code. -/// -/// \param thread Handle of the thread for which the handler is -/// to be installed. A thread can use the special -/// handle XOS_THREAD_SELF to specify itself. -/// -/// \param func Pointer to exit handler function. To clear an -/// existing handler, pass NULL as the pointer. -/// -/// \return Returns XOS_OK on success, else error code. -/// -//----------------------------------------------------------------------------- -int32_t -xos_thread_set_exit_handler(XosThread * thread, XosThdExitFunc * func); - - -//----------------------------------------------------------------------------- -/// -/// Return the ID (handle) of the current thread. -/// -/// \return Returns the handle of the current thread. This handle can be -/// used in all XOS system calls. -/// -/// NOTE: If called from interrupt context, returns the handle of the thread -/// that was preempted. -/// -//----------------------------------------------------------------------------- -static inline XosThread * -xos_thread_id() -{ - return xos_curr_threadptr; -} - - -//----------------------------------------------------------------------------- -/// -/// Return the coprocessor mask for the specified thread. -/// -/// \param thread Handle of thread being queried. -/// -/// \return Returns the mask for the specified thread if available, else 0. -/// -//----------------------------------------------------------------------------- -static inline uint16_t -xos_thread_cp_mask(XosThread * thread) -{ - XOS_ASSERT(thread); - return thread ? thread->cp_mask : 0; -} - - -//----------------------------------------------------------------------------- -/// -/// Return the wake value for the specified thread. -/// -/// \return thread Handle of thread being queried. -/// -/// \return Returns The last set wake value. There is no way to detect what -/// action set the wake value and when. -/// -//----------------------------------------------------------------------------- -static inline int32_t -xos_thread_get_wake_value(XosThread * thread) -{ - XOS_ASSERT(thread); - return thread ? thread->wake_value : 0; -} - - -//----------------------------------------------------------------------------- -/// -/// Return the current value of the event bits for the current thread. -/// This function takes no parameters. -/// -/// \return Returns the current value of the event bits. The event bits -/// are set when the thread is woken from an event wait. They will -/// not change while the thread is running. There is no way to -/// determine when the event bits were last updated. -/// -//----------------------------------------------------------------------------- -static inline uint32_t -xos_thread_get_event_bits(void) -{ - XosThread * thread = xos_thread_id(); - return thread ? thread->event_bits : 0; -} - - -//----------------------------------------------------------------------------- -/// -/// Enum values for thread state. -/// -//----------------------------------------------------------------------------- -typedef enum xos_thread_state_t { - XOS_THREAD_STATE_INVALID = 0, ///< Invalid thread - XOS_THREAD_STATE_BLOCKED, ///< Thread is blocked - XOS_THREAD_STATE_READY, ///< Thread is ready to run - XOS_THREAD_STATE_RUNNING, ///< Thread is running - XOS_THREAD_STATE_EXITED, ///< Thread has exited -} xos_thread_state_t; - - -//----------------------------------------------------------------------------- -/// -/// Return the state of the specified thread. -/// -/// \param thread Handle of thread being queried. -/// -/// \return Returns one of the following values: -/// - XOS_THREAD_STATE_RUNNING -- The thread is currently running. -/// - XOS_THREAD_STATE_READY -- The thread is ready to run. -/// - XOS_THREAD_STATE_BLOCKED -- The thread is blocked on something. -/// - XOS_THREAD_STATE_INVALID -- The thread handle is invalid. -/// - XOS_THREAD_STATE_EXITED -- The thread has exited. -/// -//----------------------------------------------------------------------------- -xos_thread_state_t -xos_thread_get_state(XosThread * thread); - - -//----------------------------------------------------------------------------- -/// -/// Disable thread preemption. Prevents context switching to another thread. -/// However, interrupt handlers will still continue to be run. Multiple calls -/// will nest, and the same number of calls to xos_preemption_enable() will be -/// required to re-enable preemption. If the calling thread yields the CPU or -/// exits without enabling preemption, it will cause a system halt. -/// If the calling thread encounters a fatal error, preemption will be enabled -/// during fatal error handling. -/// -/// \return Returns the new value of preemption disable flag after this call. -/// -/// NOTE: Cannot be called from interrupt context. -/// -//----------------------------------------------------------------------------- -uint32_t -xos_preemption_disable(void); - - -//----------------------------------------------------------------------------- -/// -/// Enable thread preemption. Has no effect if preemption was already enabled. -/// Otherwise, it decrements the value of the preemption disable flag and if -/// the value goes to zero, enables preemption. -/// -/// \return Returns the new value of preemption disable flag after this call. -/// -/// NOTE: If scheduling gets enabled, it may cause an immediate context switch -/// if higher priority threads are ready. -/// -//----------------------------------------------------------------------------- -uint32_t -xos_preemption_enable(void); - - -//----------------------------------------------------------------------------- -/// -/// Initialize XOS thread support and start scheduler. -/// -/// Must be called from main() before calling any other thread function. -/// This function initializes thread support, creates the idle thread, and -/// starts the scheduler. It does not return to its caller. This means that -/// at least one user thread must be created before calling xos_start(). -/// Otherwise, the scheduler will run the idle thread since it will be the -/// only thread in the system, and no other thread can be created. -/// -/// NOTE: This function does not initialize timer/tick support. For timer -/// services to be available xos_start_system_timer() must be called. -/// -/// NOTE: xos_start() and xos_start_main() are exclusive, both cannot be -/// called within the same application. -/// -/// \param flags Currently unused (pass 0). -/// -/// \return Does not return. -/// -//----------------------------------------------------------------------------- -void -xos_start(uint32_t flags); - - -//----------------------------------------------------------------------------- -/// -/// Initialize XOS thread support and create init (main) thread. -/// -/// Must be called from main() before calling any other thread function. -/// This function converts the caller into the 'main' or 'init' thread, and -/// returns to the caller after completing initialization. -/// -/// NOTE: This function does not initialize timer/tick support. For timer -/// services to be available xos_start_system_timer() must be called. -/// -/// NOTE: xos_start_main() and xos_start() are exclusive, both cannot be -/// called within the same application. -/// -/// \param name Name of main thread (see xos_thread_create()). -/// -/// \param priority Initial priority of main thread. -/// -/// \param flags Currently unused (pass 0). -/// -/// \return Returns nothing. -/// -//----------------------------------------------------------------------------- -void -xos_start_main(const char * name, int8_t priority, uint32_t flags); - - -//----------------------------------------------------------------------------- -/// -/// Per-thread stats structure. -/// Note that the CPU use % is approximate, both because of cycle counting -/// and because of integer division. So all the threads' CPU % will not add -/// up to exactly 100%. -/// -//----------------------------------------------------------------------------- -typedef struct XosThreadStats { - XosThread * thread; ///< Thread handle (or pseudo-handle) - uint32_t cpu_pct; ///< CPU use % for this thread - uint32_t normal_switches; ///< Number of non-preemptive switches. - uint32_t preempt_switches; ///< Number of preemptive switches. - uint64_t cycle_count; ///< Number of cycles consumed. -} XosThreadStats; - - -//----------------------------------------------------------------------------- -// Thread pseudo-handles. -//----------------------------------------------------------------------------- -#define XOS_THD_STATS_IDLE ((XosThread *) 1) -#define XOS_THD_STATS_INTR ((XosThread *) 2) - - -//----------------------------------------------------------------------------- -/// -/// Get the thread statistics for the specified thread. Statistics are only -/// available if XOS_OPT_STATS has been enabled. Otherwise, the function -/// will return XOS_OK, but the structure contents will be undefined. -/// -/// \param thread Handle of thread being queried. The following -/// special pseudo-handles can be used: -/// - XOS_THD_STATS_IDLE -- stats for idle thread -/// - XOS_THD_STATS_INTR -- stats for interrupt processing -/// -/// \param stats Pointer to XosThreadStats struct to be filled in. -/// -/// \return Returns XOS_OK on success, else error code. -/// -/// NOTE: Can be called from interrupt context. -/// NOTE: This call will not fill in the "thread" and "cpu_pct" fields in the -/// "stats" structure. The thread handle is already known, and calculating the -/// CPU loading can take quite a bit of time so is not done here. -/// -//----------------------------------------------------------------------------- -int32_t -xos_thread_get_stats(XosThread * thread, XosThreadStats * stats); - - -//----------------------------------------------------------------------------- -/// -/// Get CPU loading statistics for the system. This function computes the CPU -/// percentage use for all threads in the system (including the idle thread and -/// the 'interrupt thread' (interrupt context). It also returns the cycle count -/// and number of context switches for each thread. -/// Statistics are only available if XOS_OPT_STATS has been enabled. -/// Otherwise, the function will return XOS_OK, but the structure contents will -/// be undefined. -/// -/// IMPORTANT: The entry for interrupt context does not contain a real thread -/// handle. It uses the pseudo-handle XOS_THD_STATS_INTR to indicate that this -/// entry reports interrupt statistics. This pseudo-handle cannot be used for -/// any other thread operations or queries. -/// -/// NOTE: This function disables interrupts while traversing the thread list. -/// It does not leave interrupts disabled during the computations, as that can -/// take a fair amount of time. -/// -/// \param stats Pointer to an array of XosThreadStats structures. -/// The array must be large enough to accommodate all -/// threads in the system. -/// -/// \param size The number of elements available in the array. If -/// this is smaller than the number of threads plus one -/// (for the interrupt context) then XOS_ERR_INVALID_PARAMETER -/// will be returned and '*size' will be set to the -/// minimum number of elements required. On a successful -/// return, '*size' is set to the number of elements -/// actually filled in. -/// -/// \param reset If nonzero, then thread stats counters are reset -/// after reading. This is useful if you want to track -/// the stats so as to get a better idea of current -/// system loading. E.g. calling this function once a -/// second with 'reset' nonzero will provide CPU load -/// information for the last second on each call. -/// -/// \return Returns XOS_OK on success, else error code. In particular, -/// XOS_ERR_INVALID_PARAMETER will be returned if the output buffer -/// is too small. -/// -//----------------------------------------------------------------------------- -int32_t -xos_get_cpu_load(XosThreadStats * stats, int32_t * size, int32_t reset); - - -#ifdef _XOS_INCLUDE_INTERNAL_ - -// Signature of valid thread object -#define XOS_THREAD_SIG 0x54485244 - - -// Extern functions -void -xos_init(void); - -bool -xos_init_done(void); - -bool -xos_started(void); - -int32_t -xos_schedule(XosThread * curr_thread); - -void -xos_q_remove(XosThreadQueue * queue, XosThread * thread); - -XosThread * -xos_q_pop(XosThreadQueue * queue); - -int32_t -xos_wake_queue(XosThreadQueue * queue, const char * expected_cause, int32_t wake_value); - -// Well known block causes -extern const char * const xos_blkon_idle; // (for idle thread only) -extern const char * const xos_blkon_suspend; -extern const char * const xos_blkon_delay; -extern const char * const xos_blkon_exited; -extern const char * const xos_blkon_join; -extern const char * const xos_blkon_event; -extern const char * const xos_blkon_condition; -extern const char * const xos_blkon_mutex; -extern const char * const xos_blkon_sem; -extern const char * const xos_blkon_msgq; - - -//----------------------------------------------------------------------------- -// Blocks the current active thread. -// -// Currently, this can be called from an interrupt handler to block the thread -// that was interrupted. Note that in interrupt context the current thread can -// already be in the blocked state, due to a previous call to this function. -// Can be called with interrupts enabled. -// -// block_cause Reason for blocking. -// -// block_queue Queue on to which this thread should be pushed once it -// is blocked. Can be NULL. -// -// must_schedule If nonzero, then forces a scheduling operation to pick -// the next thread to run, even if there are ready threads -// at the same priority level as the blocked thread. -// -// use_priority If nonzero, then the blocked thread will be queued in -// priority order in the specified block queue. If zero, -// the thread is queued in FIFO order. If no queue has -// been specified, this parameter is ignored. -// -// Returns: The value passed by xos_thread_wake(). -//----------------------------------------------------------------------------- -int32_t -xos_block(const char * block_cause, - XosThreadQueue * block_queue, - int32_t must_schedule, - int32_t use_priority); - - -//----------------------------------------------------------------------------- -// Unblocks the specified blocked thread and puts it at the tail end of its -// ready queue. Schedules it if it is higher priority than the current thread. -// No effect if the thread is not blocked with the specified cause. -// -// thread The thread to wake up (make ready). -// -// expected_cause The expected block cause of the thread. Thread will be -// woken only if its block cause matches this cause, or if -// expected_cause is zero. -// -// wake_value The value to be passed to the woken thread as a return -// value from xos_thread_block(). -// -// Returns: nothing. -// -// The target thread can be woken at a different priority by changing its -// priority while the thread is blocked. -// Can be called with interrupts enabled. Can be called in interrupt context. -//----------------------------------------------------------------------------- -void -xos_thread_wake(XosThread * thread, const char * expected_cause, int32_t wakevalue); - - -//----------------------------------------------------------------------------- -// Function to init C library per-thread and reentrancy support. -//----------------------------------------------------------------------------- -#if XOS_OPT_THREAD_SAFE_CLIB -void -xos_clib_init(void); - -void -xos_clib_thread_init(XosThread * thread); - -void -xos_clib_thread_cleanup(XosThread * thread); -#endif - -#endif - - -#ifdef __cplusplus -} -#endif - -#endif // __XOS_THREAD_H__ - diff --git a/components/esp32/include/xtensa/xos_timer.h b/components/esp32/include/xtensa/xos_timer.h deleted file mode 100644 index 0d89a21929..0000000000 --- a/components/esp32/include/xtensa/xos_timer.h +++ /dev/null @@ -1,592 +0,0 @@ -/** @file */ - -// xos_timer.h - XOS Timer API interface and data structures. - -// 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. - -// NOTE: Do not include this file directly in your application. Including -// xos.h will automatically include this file. - - -#ifndef __XOS_TIMER_H__ -#define __XOS_TIMER_H__ - -#include "xos_types.h" - -#ifdef __cplusplus -extern "C" { -#endif - - -//----------------------------------------------------------------------------- -/// -/// Function pointer type for timer callbacks. -/// -//----------------------------------------------------------------------------- -typedef void (XosTimerFunc)(void * arg); - - -//----------------------------------------------------------------------------- -/// -/// Timer event structure. Used to track pending timer events. -/// -//----------------------------------------------------------------------------- -typedef struct XosTimer { - struct XosTimer * next; ///< Pointer to next event in list. - uint64_t when; ///< Time (clock cycles) at which to trigger. - uint64_t delta; ///< Delta for next re-trigger, 0 if none. - XosTimerFunc * fn; ///< Function to call when timer expires. - void * arg; ///< Argument to pass to called function. - bool active; ///< Set if active (in some list of events). -#if XOS_OPT_TIMER_WAIT - XosThreadQueue waitq; ///< Queue of threads waiting on this timer. -#endif -#if XOS_TIMER_DEBUG - uint32_t signature; -#endif -} XosTimer; - - -//----------------------------------------------------------------------------- -// Extern declarations. -//----------------------------------------------------------------------------- - -// System clock frequency in cycles per second. -extern uint32_t xos_clock_freq; - - -///@{ -//----------------------------------------------------------------------------- -// Functions to convert from clock cycles to time units and vice versa. -// -// Note that these are integer conversions so for example a cycle count of less -// than one second will convert to zero seconds. -//----------------------------------------------------------------------------- - -/// Converts CPU cycles to time in seconds. -/// -/// \param cycles Number of CPU cycles. -/// -/// \return Equivalent number of seconds (truncated to integer). -static inline uint64_t -xos_cycles_to_secs(uint64_t cycles) -{ - return cycles / xos_clock_freq; -} - -/// Converts CPU cycles to time in milliseconds. -/// -/// \param cycles Number of CPU cycles. -/// -/// \return Equivalent number of milliseconds (truncated to integer). -static inline uint64_t -xos_cycles_to_msecs(uint64_t cycles) -{ - return (cycles * 1000) / xos_clock_freq; -} - -/// Converts CPU cycles to time in microseconds. -/// -/// \param cycles Number of CPU cycles. -/// -/// \return Equivalent number of microseconds (truncated to integer). -static inline uint64_t -xos_cycles_to_usecs(uint64_t cycles) -{ - return (cycles * 1000000) / xos_clock_freq; -} - -/// Converts time in seconds to CPU cycle count. -/// -/// \param secs Number of seconds. -/// -/// \return Equivalent number of CPU cycles. -static inline uint64_t -xos_secs_to_cycles(uint64_t secs) -{ - return secs * xos_clock_freq; -} - -/// Converts time in milliseconds to CPU cycle count. -/// -/// \param msecs Number of milliseconds. -/// -/// \return Equivalent number of CPU cycles. -static inline uint64_t -xos_msecs_to_cycles(uint64_t msecs) -{ - return (msecs * xos_clock_freq) / 1000; -} - -/// Converts time in microseconds to CPU cycle count. -/// -/// \param usecs Number of microseconds. -/// -/// \return Equivalent number of CPU cycles. -static inline uint64_t -xos_usecs_to_cycles(uint64_t usecs) -{ - return (usecs * xos_clock_freq) / 1000000; -} -///@} - - -//----------------------------------------------------------------------------- -/// -/// Set system clock frequency. This is expected to be set only once, and only -/// if the clock frequency is not known at compile time. -/// -/// \param freq Frequency in cycles per second. -/// -/// \return Returns nothing. -/// -//----------------------------------------------------------------------------- -static inline void -xos_set_clock_freq(uint32_t freq) -{ - xos_clock_freq = freq; -} - - -//----------------------------------------------------------------------------- -/// -/// Get current system clock frequency. -/// -/// \return Returns current system clock frequency in cycles per second. -/// -//----------------------------------------------------------------------------- -static inline uint32_t -xos_get_clock_freq() -{ - return xos_clock_freq; -} - - -//----------------------------------------------------------------------------- -/// -/// Initialize timer support and start the system timer. -/// This function must be called before calling any other timer function. -/// -/// NOTE: The smaller the tick period, the more precisely delays can be -/// specified using timers. However, we also need to make the tick period -/// large enough to allow time both to execute the tick timer interrupt handler -/// and for the application to make reasonable forward progress. If tick_period -/// is too small, the timer interrupt may re-trigger before the timer interrupt -/// handler has returned to the application, thus keeping the processor busy in -/// constantly executing the timer interrupt handler without leaving any cycles -/// for the application. Or, the application might get some cycles but only a -/// fraction of what is spent in the timer interrupt handler, thus severely -/// impacting application performance. -/// -/// The exact number of cycles needed to execute the timer interrupt handler -/// is not specified here. It depends on many factors (e.g. use of caches, -/// various processor configuration options, etc) and can vary by orders of -/// magnitude. Also note that the time to execute this handler is variable: -/// when timers expire upon a given tick timer interrupt, their respective -/// timer handler functions are called from within the interrupt handler. -/// -/// \param timer_num Which Xtensa timer to use (0..2). This timer -/// must exist and be configured at level 1 or at a -/// medium-priority interrupt level (<=EXCM_LEVEL). -/// If 'timer_num' is -1, then this function will -/// automatically choose the highest priority timer -/// that is suitable for use. This value will be -/// passed to xos_system_timer_select(). -/// -/// \param tick_period Number of clock (CCOUNT) cycles between ticks. -/// Must range between 0 and UINT32_MAX. -/// Zero is used to specify dynamic tick (tickless) -/// mode. -/// -/// \return Returns XOS_OK on success, else error code. -/// -//----------------------------------------------------------------------------- -int32_t -xos_start_system_timer(int32_t timer_num, uint32_t tick_period); - - -//----------------------------------------------------------------------------- -/// -/// Get the timer number of the system timer. Useful mainly when XOS has been -/// allowed to choose its own timer via xos_start_system_timer(). Not valid if -/// called before the system timer has been started. -/// -/// \return Returns one of XOS_SYS_TIMER_0, XOS_SYS_TIMER_1, XOS_SYS_TIMER_2 -/// or XOS_SYS_TIMER_EXTERNAL, or XOS_SYS_TIMER_NONE. -/// -//----------------------------------------------------------------------------- -int32_t -xos_get_system_timer_num(void); - - -//----------------------------------------------------------------------------- -/// -/// Initialize timer object. -/// -/// \param timer Pointer to timer event structure. -/// -/// \return Returns nothing. -/// -/// NOTE: This function should not be called on a timer object once it has -/// been activated. -/// -//----------------------------------------------------------------------------- -void xos_timer_init(XosTimer * timer); - - -//----------------------------------------------------------------------------- -// Flags for xos_timer_start(). -//----------------------------------------------------------------------------- -#define XOS_TIMER_DELTA 0x0000 -#define XOS_TIMER_PERIODIC 0x0001 -#define XOS_TIMER_ABSOLUTE 0x0002 -#define XOS_TIMER_FROM_NOW 0x0000 -#define XOS_TIMER_FROM_LAST 0x0010 - - -//----------------------------------------------------------------------------- -/// -/// Start the timer, and when the timer expires, call the specified function -/// (invoke (*fn)(arg)). If the timer is periodic, it will be automatically -/// restarted when it expires. -/// -/// The specified timer event structure must have been initialized before -/// first use by calling xos_timer_init(). -/// -/// The callback function will be called in an interrupt context. Hence it is -/// NOT safe to use any coprocessors in the function, including the FPU. If a -/// coprocessor must be used, then its state must be saved and restored across -/// its use. -/// -/// NOTE: If you are using the timer only to wait on (via xos_timer_wait()) -/// then it is not necessary to specify a callback function. You should pass -/// NULL for the callback function and zero for the callback argument. -/// -/// \param timer Pointer to timer event structure. Must have been -/// initialized. May be active or not. -/// -/// \param when When to call the function (see flags). -/// -/// \param flags Set of option flags XOS_TIMER_* \n -/// The following flags are mutually exclusive: -/// - XOS_TIMER_DELTA -- when is number of cycles from -/// [see below] (default) -/// - XOS_TIMER_PERIODIC -- when is number of cycles -/// from [see below], and timer continually -/// re-triggers at that interval -/// - XOS_TIMER_ABSOLUTE -- when is absolute value of -/// cycle count \n -/// \n -/// The following flags are mutually exclusive: -/// - XOS_TIMER_FROM_NOW -- *DELTA and *PERIODIC are -/// relative to now (default) -/// - XOS_TIMER_FROM_LAST -- *DELTA and *PERIODIC are -/// relative to the timer event's last specified expiry -/// time (usually in the future if active, in the past -/// if not, absolute 0 if was never activated). -/// -/// \param func Function to call (called in timer interrupt context). -/// This argument is optional. Specify NULL if no function -/// is to be called. -/// -/// \param arg Argument passed to callback function. Only relevant if -/// 'func' is not NULL. -/// -/// \return Returns XOS_OK on success, else error code. -/// -//----------------------------------------------------------------------------- -int32_t -xos_timer_start(XosTimer * timer, - uint64_t when, - uint32_t flags, - XosTimerFunc * func, - void * arg); - - -//----------------------------------------------------------------------------- -/// -/// Stop the timer and remove it from the list of active timers. Has no effect -/// if the timer is not active. Any waiting threads are woken up. -/// -/// The timer structure must have been initialized at least once, else its -/// contents are undefined and can lead to unpredictable results. -/// -/// \param timer Pointer to timer object. -/// -/// \return Returns XOS_OK on success, else error code. -/// -//----------------------------------------------------------------------------- -int32_t -xos_timer_stop(XosTimer * timer); - - -//----------------------------------------------------------------------------- -/// -/// Reset and restart the timer. -/// -/// The timer is reset to go off at time "when" from now. If the timer was not -/// active, it will be activated. If the timer was active, it will be restarted. -/// If the timer is periodic, the period will be set to "when". -/// The timer object must have been initialized at some point before this call. -/// -/// \param timer Pointer to timer object. -/// -/// \param when Number of cycles from now that the timer will expire. -/// -/// \return Returns XOS_OK on success, else error code. -/// -//----------------------------------------------------------------------------- -int32_t -xos_timer_restart(XosTimer * timer, uint64_t when); - - -//----------------------------------------------------------------------------- -/// -/// Check if the timer is active. The timer is active if it has been started -/// and not yet expired or canceled. -/// -/// \param timer Pointer to timer object. -/// -/// \return Returns non-zero if the timer is active, else zero. -/// -//----------------------------------------------------------------------------- -static inline int32_t -xos_timer_is_active(XosTimer * timer) -{ - return timer ? timer->active : 0; -} - - -//----------------------------------------------------------------------------- -/// -/// Get the repeat period for a periodic timer. For a one-shot timer this will -/// return zero. The period is reported in system clock cycles. -/// -/// \param timer Pointer to timer object. -/// -/// \return Returns period in cycles, or zero for non-periodic timers. -/// -//----------------------------------------------------------------------------- -static inline uint64_t -xos_timer_get_period(XosTimer * timer) -{ - return timer ? timer->delta : 0; -} - - -//----------------------------------------------------------------------------- -/// -/// Set the repeat period for a periodic timer. The period must be specified -/// in system clock cycles. -/// -/// If the timer is active, the change in period does not take effect until -/// the timer expires at least once after this call. -/// Note that setting a period of zero will effectively turn a periodic timer -/// into a one-shot timer. Similarly, a one-shot timer can be turned into a -/// periodic timer. -/// -/// \param timer Pointer to timer object. -/// -/// \param period Repeat period in system clock cycles. -/// -/// \return Returns XOS_OK on success, else error code. -/// -//----------------------------------------------------------------------------- -int32_t -xos_timer_set_period(XosTimer * timer, uint64_t period); - - -//----------------------------------------------------------------------------- -/// -/// Get the current system cycle count. This accounts for the periodic rollover -/// of the 32-bit CCOUNT cycle counter and returns a 64-bit value. -/// -/// \return Returns the current system cycle count. -/// -//----------------------------------------------------------------------------- -static inline uint64_t -xos_get_system_cycles(void) -{ - extern uint64_t xos_system_cycles; - extern uint32_t xos_last_ccount; - - // xos_last_ccount was updated when xos_system_cycles was last updated. - // We need to add in the number of cycles elapsed since then. - return xos_system_cycles + (xos_get_ccount() - xos_last_ccount); -} - - -//----------------------------------------------------------------------------- -/// -/// Put calling thread to sleep for at least the specified number of cycles. -/// The actual number of cycles spent sleeping may be larger depending upon -/// the granularity of the system timer. Once the specified time has elapsed -/// the thread will be woken and made ready. -/// -/// \param cycles Number of system clock cycles to sleep. -/// -/// \return Returns XOS_OK on success, else error code. -/// -//----------------------------------------------------------------------------- -int32_t -xos_thread_sleep(uint64_t cycles); - - -//----------------------------------------------------------------------------- -/// -/// Put calling thread to sleep for at least the specified number of msec. -/// The actual amount of time spent sleeping may be larger depending upon -/// the granularity of the system timer. Once the specified time has elapsed -/// the thread will be woken and made ready. -/// -/// \return msecs The number of milliseconds to sleep. -/// -/// \return Returns XOS_OK on success, else error code. -/// -//----------------------------------------------------------------------------- -static inline int32_t -xos_thread_sleep_msec(uint64_t msecs) -{ - return xos_thread_sleep(xos_msecs_to_cycles(msecs)); -} - - -//----------------------------------------------------------------------------- -/// -/// Put calling thread to sleep for at least the specified number of usec. -/// The actual amount of time spent sleeping may be larger depending upon -/// the granularity of the system timer. Once the specified time has elapsed -/// the thread will be woken and made ready. -/// -/// \return usecs The number of microseconds to sleep. -/// -/// \return Returns XOS_OK on success, else error code. -/// -//----------------------------------------------------------------------------- -static inline int32_t -xos_thread_sleep_usec(uint64_t usecs) -{ - return xos_thread_sleep(xos_usecs_to_cycles(usecs)); -} - - -//----------------------------------------------------------------------------- -/// -/// Wait on a timer until it expires or is cancelled. The calling thread will -/// be blocked. The timer must be active. -/// NOTE: This operation is only available if XOS_OPT_TIMER_WAIT is set -/// to 1 in the configuration options. -/// -/// \param timer Pointer to timer object. -/// -/// \return Returns XOS_OK on normal timeout, else an error code. -/// -//----------------------------------------------------------------------------- -int32_t -xos_timer_wait(XosTimer * timer); - - -//----------------------------------------------------------------------------- -// System timer control interface. -//----------------------------------------------------------------------------- - - -//----------------------------------------------------------------------------- -// Defines for system timer ID. -//----------------------------------------------------------------------------- -#define XOS_SYS_TIMER_0 0 ///< Internal timer 0 -#define XOS_SYS_TIMER_1 1 ///< Internal timer 1 -#define XOS_SYS_TIMER_2 2 ///< Internal timer 2 -#define XOS_SYS_TIMER_EXTERNAL -2 ///< External timer -#define XOS_SYS_TIMER_NONE -1 ///< No system timer selected - - -//----------------------------------------------------------------------------- -/// -/// This function handles XOS timer tick processing. It must be called by the -/// timer interrupt handler on every timer interrupt. This function computes -/// the time to the next tick and sets it up by calling xos_system_timer_set(). -/// -//----------------------------------------------------------------------------- -void -xos_tick_handler(void); - - -//----------------------------------------------------------------------------- -/// -/// Selects the timer to use. The selection may be one of the internal timers -/// or an external timer. The default implementation selects an internal timer. -/// This function can be overridden to provide custom timer processing or to -/// support an external timer. -/// -/// \param timer_num The internal timer number to select (0-2) or -/// -1 to auto-select a timer. This parameter can -/// be ignored by custom implementations that use -/// an external timer. -/// -/// \param psel Pointer to a location where the selected timer -/// ID must be returned. The timer ID must be one -/// of XOS_SYS_TIMER_0, XOS_SYS_TIMER_1, XOS_SYS_TIMER_2 -/// or XOS_SYS_TIMER_EXTERNAL. -/// -/// \return Returns XOS_OK on success, else error code. -/// -//----------------------------------------------------------------------------- -int32_t -xos_system_timer_select(int32_t timer_num, int32_t *psel); - - -//----------------------------------------------------------------------------- -/// -/// Starts the system timer and sets up the first interrupt. This function can -/// be overridden to provide custom timer processing or to support an external -/// timer. -/// -/// \param cycles The number of CPU cycles from now when the -/// first interrupt must occur. -/// -//----------------------------------------------------------------------------- -void -xos_system_timer_init(uint32_t cycles); - - -//----------------------------------------------------------------------------- -/// -/// Sets the next trigger value of the system timer. The parameter 'cycles' is -/// the number of CPU cycles from now when the interrupt must occur. -/// This function can be overridden to provide custom timer processing or to -/// support an external timer. -/// -/// \param cycles The number of CPU cycles from now when the -/// next interrupt must occur. -/// -//----------------------------------------------------------------------------- -void -xos_system_timer_set(uint32_t cycles); - - -#ifdef __cplusplus -} -#endif - -#endif // __XOS_TIMER_H__ - diff --git a/components/esp32/include/xtensa/xos_types.h b/components/esp32/include/xtensa/xos_types.h deleted file mode 100644 index a913b94a23..0000000000 --- a/components/esp32/include/xtensa/xos_types.h +++ /dev/null @@ -1,75 +0,0 @@ -/** @file */ -// xos_types.h - XOS type definitions. - -// 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. - -// NOTE: Do not include this file directly in your application. Including -// xos.h will automatically include this file. - - -#ifndef __XOS_TYPES_H__ -#define __XOS_TYPES_H__ - -#if !defined(_ASMLANGUAGE) && !defined(__ASSEMBLER__) - -#ifdef __cplusplus -extern "C" { -#endif - -#include - -//----------------------------------------------------------------------------- -// The following are defined here because of the variations in the C libraries -// that we need to work with. -// - Not all of them have stdbool.h -// - Not all of them define NULL as (void *)0 -//----------------------------------------------------------------------------- - - -//----------------------------------------------------------------------------- -/// -/// XOS define for NULL value. This makes the NULL value independent of the -/// C library (not all of them define NULL the same way). -/// -//----------------------------------------------------------------------------- -#define XOS_NULL ((void *)0) - - -//----------------------------------------------------------------------------- -/// -/// XOS definition of 'bool' type. Some C libraries do not support stdbool.h. -/// -//----------------------------------------------------------------------------- -#ifndef bool -#define bool int8_t -#define false 0 ///< XOS definition of 'false' -#define true 1 ///< XOS definition of 'true' -#endif - -#ifdef __cplusplus -} -#endif - -#endif // !defined(_ASMLANGUAGE) && !defined(__ASSEMBLER__) - -#endif // __XOS_TYPES_H__ - diff --git a/components/esp32/include/xtensa/xt_perfmon.h b/components/esp32/include/xtensa/xt_perfmon.h deleted file mode 100644 index 959052b164..0000000000 --- a/components/esp32/include/xtensa/xt_perfmon.h +++ /dev/null @@ -1,183 +0,0 @@ -/* - * Customer ID=11656; Build=0x5f626; Copyright (c) 2012 by Tensilica Inc. 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. - */ - -#ifndef __XT_PERFMON_H__ -#define __XT_PERFMON_H__ - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -typedef int counter_id_t; - -/* xt_perf_init - - Initialize the performance monitor library. Ordinarily, this - function is called automatically via the .init section. If your - environment does not support the .init section, you will need to - call this function from your code. -*/ - -extern void xt_perf_init(void); - -/* xt_perf_enable - - Turn on the performance monitor. Ordinarily, counting is off by - default. If you turn off performance monitor using xt_perf_disable or - by call to a function that disables performance monitor, you can turn - it on again via this function. -*/ - -extern void xt_perf_enable(void); - -/* xt_perf_disable - - Turn off the performance monitor. If you want to suspend counting - events for a portion of your code, use this function and then call - xt_perf_enable when you want to start again. -*/ - -extern void xt_perf_disable(void); - -/* xt_perf_clear - - Disable performance monitor and clear all initialized hardware counters. - All counter ids are invalid after call to this function and all hardware - counters available for initialization. -*/ - -extern void xt_perf_clear (void); - -/* xt_perf_counters_num - - Returns number of free hardware performance counters. After call to xt_perf_clear - all counters are free and available for initialization. With each successful - xt_perf_init_counter/xt_perf_init_event call this number is decreasing until - no free counters available. -*/ - -extern int xt_perf_counters_num (void); - -/* xt_perf_init_counter32 - - Setup 32 bit performance counter. This function disables performance monitor - if it was enabled. - - Returns zero based counter id on success or negative value if failed. - This function may fail if there is insufficient number of free hardware - counters or function arguments are invalid. - - The counter id returned on success can be used with xt_perf_reset_counter - and xt_perf_counter32 functions. - - - events group, one of XTPERF_CNT constants defined in - xt_perf_consts.h; - - events mask for selected group. Mask bit fields for each - selector defined with XTPERF_MASK prefix in xt_perf_consts.h; - - specifies interrupt levels at which to count events; - if trace_level is greater or equal to zero events are - counted only at interrupt levels below or equal to - trace_level; if trace_level is negative events are - counted only at (-trace_level) interrupt level or higher. -*/ - - -extern counter_id_t xt_perf_init_counter32 ( unsigned int selector, - unsigned int mask, - int trace_level); - -/* xt_perf_init_counter64 - - Setup 64 bit performance counter. Library emulates 64 bit counters by handling - profiling interrupt and recording overflows of 32 bit hardware counters. - This function disables performance monitor if it was enabled. - - Returns zero based counter id on success or negative value if failed. - This function may fail if there is insufficient number of free hardware - counters or function arguments are invalid. - - The counter id returned on success can be used with xt_perf_reset_counter - and xt_perf_counter64 functions. - - - events group, one of XTPERF_CNT constants defined in - xt_perf_consts.h; - - events mask for selected group. Mask bit fields for each - selector defined with XTPERF_MASK prefix in xt_perf_consts.h; - - specifies interrupt levels at which to count events; - if trace_level is greater or equal to zero events are - counted only at interrupt levels below or equal to - trace_level; if trace_level is negative events are - counted only at (-trace_level) interrupt level or higher. -*/ - -extern counter_id_t xt_perf_init_counter64 ( unsigned int selector, - unsigned int mask, - int trace_level); - -/* xt_perf_reset_counter - - Reset counter value to 0. - Returns zero on success or non zero if failed. -*/ - -extern int xt_perf_reset_counter (counter_id_t counter_id); - -/* xt_perf_counter32 - - Read 32 bit counter value. - - Returns zero if counter id is not valid. -*/ - -extern unsigned int xt_perf_counter32 (counter_id_t counter_id); - -/* xt_perf_counter64 - - Read 64 bit counter value. - - Counter must be initialized using xt_perf_init_counter64 function. - - Returns zero if counter id is not valid. -*/ - -extern unsigned long long xt_perf_counter64 (counter_id_t counter_id); - - /* xt_perf_overflow32 - - Read overflow flag of 32 bit counter. This flag is dropped when - counter initialized or reset. Once counter overflows and wraps - around the flag is set and stays set until counter reset. - - Returns negative value if counter id is invalid, zero if counter - not overflowed, positive if in overflowed state. - */ - -extern int xt_perf_overflow32 (counter_id_t counter_id); - -#ifdef __cplusplus -} -#endif - -#endif /* __XT_PERFMON_H__ */ diff --git a/components/esp32/include/xtensa/xt_profiling.h b/components/esp32/include/xtensa/xt_profiling.h deleted file mode 100644 index 650713a459..0000000000 --- a/components/esp32/include/xtensa/xt_profiling.h +++ /dev/null @@ -1,233 +0,0 @@ -/* - * Customer ID=11656; Build=0x5f626; Copyright (c) 2005-2012 by Tensilica Inc. ALL RIGHTS RESERVED. - * These coded instructions, statements, and computer programs are the - * copyrighted works and confidential proprietary information of Tensilica Inc. - * They may not be modified, copied, reproduced, distributed, or disclosed to - * third parties in any manner, medium, or form, in whole or in part, without - * the prior written consent of Tensilica Inc. - */ - -#ifndef __XT_PROFILER_H__ -#define __XT_PROFILER_H__ - -#include - -#if XCHAL_NUM_PERF_COUNTERS -/* Performance monitor counters constants */ -#include - -#endif /* XCHAL_NUM_PERF_COUNTERS */ - - -#ifdef __cplusplus -extern "C" { -#endif - -/* This file defines an interface that allows a program being profiled - to control when and how it is profiled, whether it is running under - the instruction set simulator or under the hardware profiler. - - Both ISS and HWP implement this interface, although in different - ways. Both also do the right thing if you don't call any of these - functions. -*/ - - -/* -xt_profile_init - - ISS: a no op. - - HWP: Initialize the profiler. Ordinarily, this function is called - automatically via the .init section. If your environment does not - support the .init section, you will need to call this function - by hand. -*/ -extern void xt_profile_init(void); - -/* -xt_profile_add_memory - - ISS: a no op. - - HWP: - Makes "buf_size" bytes at "buf" available to the hardware profiler. - This buffer should be initialized to zeros prior to this call. - - The hardware profiler has already estimated the amount of memory it needs, - but under certain circumstances may still run out of memory. If so, you can - provide more memory with this routine. - -*/ -extern void xt_profile_add_memory(void * buf, unsigned int buf_size); - - -/* xt_profile_enable - - Turn on the profiler. Ordinarily, profiling is on by default. - If you turn off profiling using xt_profile_disable, You can turn - it on again via this function. -*/ -extern void xt_profile_enable(void); - -/* xt_profile_disable - - Turn off the profiler. If you don't want to profile a portion of your code, - use this function and then xt_profile_enable when you want to start again. -*/ -extern void xt_profile_disable(void); - -/* xt_profile_save_and_reset - - Save and reset the profiler's data. - If there were errors, either during profiling or while attempting to - write the data, no data will be written and this function will - return non-zero. - -*/ -extern int xt_profile_save_and_reset(void); - -/* xt_profile_get_frequency - - ISS: always returns 1. - - HWP: - Returns the number of cycles between samples for timer based profiler. - In performance counters based profiler always returns 1. -*/ -extern unsigned int xt_profile_get_frequency(void); - -/* xt_profile_set_frequency - - ISS: a no op. - - HWP: - Set the number of cycles between samples for timer based profiler. - Ignored in performance counters based profiler. - - sample frequency is the number of cycles to wait between samples. It should - be a multiple of 1024. - - If you set the sample frequency to a different value than was passed in xt_profile_init, - then the labels in the output will reflect the later frequency, even though some samples may - have been taken at the earlier frequency. Typically this does not make a significant difference - in the results if this function is called early enough. -*/ -extern void xt_profile_set_frequency(unsigned int sample_frequency); - -/* xt_profile_num_errors - - ISS: always returns 0 - - HWP: - Returns the number of errors that occured while taking samples. Typically these - are out of memory errors and you need to pass a bigger buffer to - xt_profile_add_memory -*/ -extern int xt_profile_num_errors(void); - - -#if XCHAL_NUM_PERF_COUNTERS - - -/* xt_profile_randomize - - ISS: not available - - HWP: Available in performance monitor based profiler. - - Turns on or off sampling period randomization mode. Period randomization - helps to avoid aliasing problems when code being profiled is highly periodic. - Profiler maintains same average sampling period but individual sampling - steps may vary. - Period randomization is turned off by default. - - - non zero turns randomization on, - zero turns randomization off. -*/ - -extern void xt_profile_randomization(int value); - -/* xt_profile_config_clear - - ISS: not available - - HWP: Available in performance monitor based profiler. - - Stops profiling if it was enabled and clears performance counters - parameters. Accumulated profile data stays in memory and will be - saved when xt_profile_save_and_reset is called or at program exit. - Number of configured performance counters is zero after this - function call. -*/ - -extern void xt_profile_config_clear(void); - - -/* xt_profile_config_num - - ISS: not available - - HWP: Available in performance monitor based profiler. - - Returns number of free performance counters. -*/ - -extern int xt_profile_config_num(void); - - -/* xt_profile_config_counter error codes -*/ - -#define XTPROF_ERR_OUT_OF_MEM -1 -#define XTPROF_ERR_INVALID_ARGS -2 -#define XTPROF_ERR_NOT_ENOUGH_COUNTERS -3 -#define XTPROF_ERR_DEFUNCT -4 - -/* xt_profile_config_counter - - ISS: not available - - HWP: Available in performance monitor based profiler. - - Allocating and initializing one or more performance counter for sampling. - Even though event may require multiple performance counters allocated the - profile data for event is merged and dumped into single gmon file. - This function disables profiling if it was enabled. - - Returns 0 on success, non zero if failed: - XTPROF_ERR_OUT_OF_MEM - memory allocation failed; - XTPROF_ERR_INVALID_ARGS - invalid function parameters; - XTPROF_ERR_NOT_ENOUGH_COUNTERS - not enough free performance counters available; - XTPROF_ERR_DEFUNCT - profiling is disabled because of previous errors - (xt_profile_num_errors() is non zero) - - - events group, one of XTPERF_CNT constants defined in xt_perf_consts.h - - events mask for selected group. Mask bit fields for each - selector defined with XTPERF_MASK prefix in xt_perf_consts.h - - specifies interrupt levels at which to take samples; - if trace_level is greater or equal to zero samples are - taken only at interrupt levels below or equal to - trace_level; if trace_level is negative samples are taken - only at (-trace_level) interrupt level or higher. - - sampling period; 1 - record every event, 2 - record every - other event and so on; - Please note - there is overhead associated with events recording, - high frequency events may produce incorrect profile when period - is too small. -*/ - -extern int xt_profile_config_counter ( unsigned int selector, - unsigned int mask, - int trace_level, - unsigned int period); - - - -#endif /* XCHAL_NUM_PERF_COUNTERS */ - -#ifdef __cplusplus -} -#endif - -#endif /* __XT_PROFILER_H__ */ diff --git a/components/esp32/include/xtensa/xt_reftb.h b/components/esp32/include/xtensa/xt_reftb.h deleted file mode 100644 index 358c39f740..0000000000 --- a/components/esp32/include/xtensa/xt_reftb.h +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Customer ID=11656; Build=0x5f626; Copyright (c) 2009-2013 by Tensilica Inc. ALL RIGHTS RESERVED. - * These coded instructions, statements, and computer programs are the - * copyrighted works and confidential proprietary information of - * Tensilica Inc. They may be adapted and modified by bona fide - * purchasers for internal use, but neither the original nor any - * adapted or modified version may be disclosed or distributed to - * third parties in any manner, medium, or form, in whole or in part, - * without the prior written consent of Tensilica Inc. - * - * This software and its derivatives are to be executed solely on - * products incorporating a Tensilica processor. - */ - -// Utility routines for returning pass/fail status in HW simulations - -#ifndef XT_REF_TESTBENCH_H -#define XT_REF_TESTBENCH_H 1 - -#ifdef __cplusplus -extern "C" { -#endif - -// Exit routines for HW simulation -extern int diag_pass(); -extern int diag_fail(); - -// Set exit status for HW simulation -int set_diag_status(int stat); - -// Setup for user power toggling -extern int setup_power_toggle(); - -// Return exit status location -extern unsigned int* testbench_exit_location(); -// Return power toggle location -extern unsigned int* testbench_power_toggle_location(); - - -// Change exit status location -// You must also change the plusarg "+DVMagicExit" sent to the HW simulator -// or change the argument "--exit_location" sent to the ISS -extern unsigned int* set_testbench_exit_location(unsigned int*); -// Change power toggle location -// You must also change the plusarg "+DVPowerLoc" sent to the HW simulator -extern unsigned int* set_testbench_power_toggle_location(unsigned int*); - -// Exit routines with status message -// -static inline -int pass(const char *msg) -{ - return diag_pass(); -} - -static inline -int fail(const char *msg) -{ - return diag_fail(); -} - -#define POWER_TOGGLE_ON 1 -#define POWER_TOGGLE_OFF 0 - -// Routine to turn on and off power toggle -// Does a magic write that Monitors.v intercepts and appropriately turns -// SAIF dumping on and offf -// -extern volatile unsigned int *_reftb_power_toggle; - -__attribute__ ((always_inline)) -static inline -int set_power_toggle(int val) -{ -#ifdef __XTENSA__ - *_reftb_power_toggle = val; -#endif - return val; -} - -#ifdef __cplusplus -} -#endif - -#endif // XT_REF_TESTBENCH_H - diff --git a/components/esp32/include/xtensa/xtav110.h b/components/esp32/include/xtensa/xtav110.h deleted file mode 100644 index 23421f0b74..0000000000 --- a/components/esp32/include/xtensa/xtav110.h +++ /dev/null @@ -1,313 +0,0 @@ -/* Copyright (c) 2007-2013 by Tensilica Inc. ALL RIGHTS RESERVED. -/ These coded instructions, statements, and computer programs are the -/ copyrighted works and confidential proprietary information of Tensilica Inc. -/ They may not be modified, copied, reproduced, distributed, or disclosed to -/ third parties in any manner, medium, or form, in whole or in part, without -/ the prior written consent of Tensilica Inc. -*/ - -/* xtav110.h - Xtensa Avnet LX110 (XT-AV110) board specific definitions */ - -#ifndef _INC_XTAV110_H_ -#define _INC_XTAV110_H_ - -#include -#include - -#define XTBOARD_NAME "XT-AV110" - - -/* - * Default assignment of XTAV110 devices to external interrupts. - */ - -/* Ethernet interrupt: */ -#ifdef XCHAL_EXTINT1_NUM -#define ETHERNET_INTNUM XCHAL_EXTINT1_NUM -#define ETHERNET_INTLEVEL XCHAL_EXTINT1_LEVEL -#define ETHERNET_INTMASK XCHAL_EXTINT1_MASK -#else -#define ETHERNET_INTMASK 0 -#endif - -/* UART interrupt: */ -#ifdef XCHAL_EXTINT0_NUM -#define UART16550_INTNUM XCHAL_EXTINT0_NUM -#define UART16550_INTLEVEL XCHAL_EXTINT0_LEVEL -#define UART16550_INTMASK XCHAL_EXTINT0_MASK -#else -#define UART16550_INTMASK 0 -#endif - -/* Audio output interrupt (I2S transmitter FIFO): */ -#ifdef XCHAL_EXTINT2_NUM -#define AUDIO_I2S_OUT_INTNUM XCHAL_EXTINT2_NUM -#define AUDIO_I2S_OUT_INTLEVEL XCHAL_EXTINT2_LEVEL -#define AUDIO_I2S_OUT_INTMASK XCHAL_EXTINT2_MASK -#else -#define AUDIO_I2S_OUT_INTMASK 0 -#endif - -/* Audio input interrupt (I2S receiver FIFO): */ -#ifdef XCHAL_EXTINT3_NUM -#define AUDIO_I2S_IN_INTNUM XCHAL_EXTINT3_NUM -#define AUDIO_I2S_IN_INTLEVEL XCHAL_EXTINT3_LEVEL -#define AUDIO_I2S_IN_INTMASK XCHAL_EXTINT3_MASK -#else -#define AUDIO_I2S_IN_INTMASK 0 -#endif - -/* I2C interrupt */ -#ifdef XCHAL_EXTINT4_NUM -#define I2C_INTNUM XCHAL_EXTINT4_NUM -#define I2C_INTLEVEL XCHAL_EXTINT4_LEVEL -#define I2C_INTMASK XCHAL_EXTINT4_MASK -#else -#define I2C_INTMASK 0 -#endif - -/* USB interrupt */ -#ifdef XCHAL_EXTINT5_NUM -#define USB_INTNUM XCHAL_EXTINT5_NUM -#define USB_INTLEVEL XCHAL_EXTINT5_LEVEL -#define USB_INTMASK XCHAL_EXTINT5_MASK -#else -#define USB_INTMASK 0 -#endif - -/* - * Device addresses. - * - * Note: for endianness-independence, use 32-bit loads and stores for all - * register accesses to Ethernet, UART and LED devices. Undefined bits - * may need to be masked out if needed when reading if the actual register - * size is smaller than 32 bits. - * - * Note: XTAV110 bus byte lanes are defined in terms of msbyte and lsbyte - * relative to the processor. So 32-bit registers are accessed consistently - * from both big and little endian processors. However, this means byte - * sequences are not consistent between big and little endian processors. - * This is fine for RAM, and for ROM if ROM is created for a specific - * processor (and thus has correct byte sequences). However this may be - * unexpected for Flash, which might contain a file-system that one wants - * to use for multiple processor configurations (eg. the Flash might contain - * the Ethernet card's address, endianness-independent application data, etc). - * That is, byte sequences written in Flash by a core of a given endianness - * will be byte-swapped when seen by a core of the other endianness. - * Someone implementing an endianness-independent Flash file system will - * likely handle this byte-swapping issue in the Flash driver software. - */ - -#define XTBOARD_FLASH_MAXSIZE 0x1000000 /* 16 MB */ - -#ifdef XSHAL_IOBLOCK_BYPASS_PADDR - -/* Flash Memory: */ -# define XTBOARD_FLASH_PADDR (XSHAL_IOBLOCK_BYPASS_PADDR+0x08000000) - -/* FPGA registers: */ -# define XTBOARD_FPGAREGS_PADDR (XSHAL_IOBLOCK_BYPASS_PADDR+0x0D020000) - -/* Ethernet controller/transceiver SONIC SN83934: */ -# define ETHERNET_PADDR (XSHAL_IOBLOCK_BYPASS_PADDR+0x0D030000) - - -/* UART National-Semi PC16550D: */ -# define UART16550_PADDR (XSHAL_IOBLOCK_BYPASS_PADDR+0x0D050000) - -/* I2S transmitter */ -# define AUDIO_I2S_OUT_PADDR (XSHAL_IOBLOCK_BYPASS_PADDR+0x0D080000) - -/* I2S receiver */ -# define AUDIO_I2S_IN_PADDR (XSHAL_IOBLOCK_BYPASS_PADDR+0x0D088000) - -/* I2C master */ -# define I2C_PADDR (XSHAL_IOBLOCK_BYPASS_PADDR+0x0D090000) - -/* SPI controller */ -# define SPI_PADDR (XSHAL_IOBLOCK_BYPASS_PADDR+0x0D0A0000) - -/* Display controller Sunplus SPLC780D, 4bit mode, - * LCD Display MYTech MOC-16216B-B: */ -# define SPLC780D_4BIT_PADDR (XSHAL_IOBLOCK_BYPASS_PADDR+0x0D0C0000) - -/* USB Controller */ -# define USB_PADDR (XSHAL_IOBLOCK_BYPASS_PADDR+0x0D0D0000) - -/* Ethernet buffer: */ -# define ETHERNET_BUFFER_PADDR (XSHAL_IOBLOCK_BYPASS_PADDR+0x0D800000) - -#endif /* XSHAL_IOBLOCK_BYPASS_PADDR */ - -/* These devices might be accessed cached: */ -#ifdef XSHAL_IOBLOCK_CACHED_PADDR -# define XTBOARD_FLASH_CACHED_PADDR (XSHAL_IOBLOCK_CACHED_PADDR+0x08000000) -# define ETHERNET_BUFFER_CACHED_PADDR (XSHAL_IOBLOCK_CACHED_PADDR+0x0D800000) -#endif /* XSHAL_IOBLOCK_CACHED_PADDR */ - - -/*** Same thing over again, this time with virtual addresses: ***/ - -#ifdef XSHAL_IOBLOCK_BYPASS_VADDR - -/* Flash Memory: */ -# define XTBOARD_FLASH_VADDR (XSHAL_IOBLOCK_BYPASS_VADDR+0x08000000) - -/* FPGA registers: */ -# define XTBOARD_FPGAREGS_VADDR (XSHAL_IOBLOCK_BYPASS_VADDR+0x0D020000) - -/* Ethernet controller/transceiver SONIC SN83934: */ -# define ETHERNET_VADDR (XSHAL_IOBLOCK_BYPASS_VADDR+0x0D030000) - - -/* UART National-Semi PC16550D: */ -# define UART16550_VADDR (XSHAL_IOBLOCK_BYPASS_VADDR+0x0D050000) - -/* I2S transmitter */ -# define AUDIO_I2S_OUT_VADDR (XSHAL_IOBLOCK_BYPASS_VADDR+0x0D080000) - -/* I2S receiver */ -# define AUDIO_I2S_IN_VADDR (XSHAL_IOBLOCK_BYPASS_VADDR+0x0D088000) - -/* I2C master */ -# define I2C_VADDR (XSHAL_IOBLOCK_BYPASS_VADDR+0x0D090000) - -/* SPI controller */ -# define SPI_VADDR (XSHAL_IOBLOCK_BYPASS_VADDR+0x0D0A0000) - -/* Display controller Sunplus SPLC780D, 4bit mode, - * LCD Display MYTech MOC-16216B-B: */ -# define SPLC780D_4BIT_VADDR (XSHAL_IOBLOCK_BYPASS_VADDR+0x0D0C0000) - -/* USB Controller */ -# define USB_VADDR (XSHAL_IOBLOCK_BYPASS_VADDR+0x0D0D0000) - -/* Ethernet buffer: */ -# define ETHERNET_BUFFER_VADDR (XSHAL_IOBLOCK_BYPASS_VADDR+0x0D800000) - -#endif /* XSHAL_IOBLOCK_BYPASS_VADDR */ - -/* These devices might be accessed cached: */ -#ifdef XSHAL_IOBLOCK_CACHED_VADDR -# define XTBOARD_FLASH_CACHED_VADDR (XSHAL_IOBLOCK_CACHED_VADDR+0x08000000) -# define ETHERNET_BUFFER_CACHED_VADDR (XSHAL_IOBLOCK_CACHED_VADDR+0x0D800000) -#endif /* XSHAL_IOBLOCK_CACHED_VADDR */ - - -/* System ROM: */ -#define XTBOARD_ROM_SIZE XSHAL_ROM_SIZE -#ifdef XSHAL_ROM_VADDR -#define XTBOARD_ROM_VADDR XSHAL_ROM_VADDR -#endif -#ifdef XSHAL_ROM_PADDR -#define XTBOARD_ROM_PADDR XSHAL_ROM_PADDR -#endif - -/* System RAM: */ -#define XTBOARD_RAM_SIZE XSHAL_RAM_SIZE -#ifdef XSHAL_RAM_VADDR -#define XTBOARD_RAM_VADDR XSHAL_RAM_VADDR -#endif -#ifdef XSHAL_RAM_PADDR -#define XTBOARD_RAM_PADDR XSHAL_RAM_PADDR -#endif -#define XTBOARD_RAM_BYPASS_VADDR XSHAL_RAM_BYPASS_VADDR -#define XTBOARD_RAM_BYPASS_PADDR XSHAL_RAM_BYPASS_PADDR - - - -/* - * Things that depend on device addresses. - */ - - -#define XTBOARD_CACHEATTR_WRITEBACK XSHAL_XT2000_CACHEATTR_WRITEBACK -#define XTBOARD_CACHEATTR_WRITEALLOC XSHAL_XT2000_CACHEATTR_WRITEALLOC -#define XTBOARD_CACHEATTR_WRITETHRU XSHAL_XT2000_CACHEATTR_WRITETHRU -#define XTBOARD_CACHEATTR_BYPASS XSHAL_XT2000_CACHEATTR_BYPASS -#define XTBOARD_CACHEATTR_DEFAULT XSHAL_XT2000_CACHEATTR_DEFAULT - -#define XTBOARD_BUSINT_PIPE_REGIONS XSHAL_XT2000_PIPE_REGIONS -#define XTBOARD_BUSINT_SDRAM_REGIONS XSHAL_XT2000_SDRAM_REGIONS - - -/* - * FPGA registers. - * All these registers are normally accessed using 32-bit loads/stores. - */ - -/* Register offsets: */ -#define XTBOARD_DATECD_OFS 0x00 /* date code (read-only) */ -#define XTBOARD_CLKFRQ_OFS 0x04 /* clock frequency Hz (read-only) */ -#define XTBOARD_SYSLED_OFS 0x08 /* LEDs */ -#define XTBOARD_DIPSW_OFS 0x0C /* DIP switch bits (read-only) */ -#define XTBOARD_SWRST_OFS 0x10 /* software reset */ - -/* Physical register addresses: */ -#ifdef XTBOARD_FPGAREGS_PADDR -#define XTBOARD_DATECD_PADDR (XTBOARD_FPGAREGS_PADDR+XTBOARD_DATECD_OFS) -#define XTBOARD_CLKFRQ_PADDR (XTBOARD_FPGAREGS_PADDR+XTBOARD_CLKFRQ_OFS) -#define XTBOARD_SYSLED_PADDR (XTBOARD_FPGAREGS_PADDR+XTBOARD_SYSLED_OFS) -#define XTBOARD_DIPSW_PADDR (XTBOARD_FPGAREGS_PADDR+XTBOARD_DIPSW_OFS) -#define XTBOARD_SWRST_PADDR (XTBOARD_FPGAREGS_PADDR+XTBOARD_SWRST_OFS) -#endif - -/* Virtual register addresses: */ -#ifdef XTBOARD_FPGAREGS_VADDR -#define XTBOARD_DATECD_VADDR (XTBOARD_FPGAREGS_VADDR+XTBOARD_DATECD_OFS) -#define XTBOARD_CLKFRQ_VADDR (XTBOARD_FPGAREGS_VADDR+XTBOARD_CLKFRQ_OFS) -#define XTBOARD_SYSLED_VADDR (XTBOARD_FPGAREGS_VADDR+XTBOARD_SYSLED_OFS) -#define XTBOARD_DIPSW_VADDR (XTBOARD_FPGAREGS_VADDR+XTBOARD_DIPSW_OFS) -#define XTBOARD_SWRST_VADDR (XTBOARD_FPGAREGS_VADDR+XTBOARD_SWRST_OFS) -/* Register access (for C code): */ -#define XTBOARD_DATECD_REG (*(volatile unsigned*) XTBOARD_DATECD_VADDR) -#define XTBOARD_CLKFRQ_REG (*(volatile unsigned*) XTBOARD_CLKFRQ_VADDR) -#define XTBOARD_SYSLED_REG (*(volatile unsigned*) XTBOARD_SYSLED_VADDR) -#define XTBOARD_DIPSW_REG (*(volatile unsigned*) XTBOARD_DIPSW_VADDR) -#define XTBOARD_SWRST_REG (*(volatile unsigned*) XTBOARD_SWRST_VADDR) -#endif - -/* DATECD (date code; when core was built) bit fields: */ -/* BCD-coded month (01..12): */ -#define XTBOARD_DATECD_MONTH_SHIFT 24 -#define XTBOARD_DATECD_MONTH_BITS 8 -#define XTBOARD_DATECD_MONTH_MASK 0xFF000000 -/* BCD-coded day (01..31): */ -#define XTBOARD_DATECD_DAY_SHIFT 16 -#define XTBOARD_DATECD_DAY_BITS 8 -#define XTBOARD_DATECD_DAY_MASK 0x00FF0000 -/* BCD-coded year (2001..9999): */ -#define XTBOARD_DATECD_YEAR_SHIFT 0 -#define XTBOARD_DATECD_YEAR_BITS 16 -#define XTBOARD_DATECD_YEAR_MASK 0x0000FFFF - -/* SYSLED (system LED) bit fields: */ - -/* LED control bits (off=0, on=1): */ -#define XTBOARD_SYSLED_USER_SHIFT 0 -#define XTBOARD_SYSLED_USER_BITS 2 -#define XTBOARD_SYSLED_USER_MASK 0x00000003 - -/* DIP Switch SW5 (left=sw1=lsb=bit0, right=sw4=msb=bit3; off=0, on=1): */ -/* DIP switch bit fields (bit2/sw3 is reserved and presently unused): */ -#define XTBOARD_DIPSW_USER_SHIFT 0 /* labeled 1-2 (1=lsb) */ -#define XTBOARD_DIPSW_USER_BITS 2 -#define XTBOARD_DIPSW_USER_MASK 0x00000003 -#define XTBOARD_DIPSW_BOOT_SHIFT 3 /* labeled 8 (msb) */ -#define XTBOARD_DIPSW_BOOT_BITS 1 -#define XTBOARD_DIPSW_BOOT_MASK 0x00000008 -/* Boot settings: bit3/sw4, off=0, on=1 (this switch controls hardware): */ -#define XTBOARD_DIPSW_BOOT_RAM (0< - diff --git a/components/esp32/include/xtensa/xtav200.h b/components/esp32/include/xtensa/xtav200.h deleted file mode 100644 index f3d837efa6..0000000000 --- a/components/esp32/include/xtensa/xtav200.h +++ /dev/null @@ -1,280 +0,0 @@ -/* Copyright (c) 2007-2013 by Tensilica Inc. ALL RIGHTS RESERVED. -/ These coded instructions, statements, and computer programs are the -/ copyrighted works and confidential proprietary information of Tensilica Inc. -/ They may not be modified, copied, reproduced, distributed, or disclosed to -/ third parties in any manner, medium, or form, in whole or in part, without -/ the prior written consent of Tensilica Inc. -*/ - -/* xtav200.h - Xtensa Avnet LX200 (XT-AV200) board specific definitions */ - -#ifndef _INC_XTAV200_H_ -#define _INC_XTAV200_H_ - -#include -#include - -#define XTBOARD_NAME "XT-AV200" - - -/* - * Default assignment of XTAV200 devices to external interrupts. - */ - -/* Ethernet interrupt: */ -#ifdef XCHAL_EXTINT1_NUM -#define ETHERNET_INTNUM XCHAL_EXTINT1_NUM -#define ETHERNET_INTLEVEL XCHAL_EXTINT1_LEVEL -#define ETHERNET_INTMASK XCHAL_EXTINT1_MASK -#else -#define ETHERNET_INTMASK 0 -#endif - -/* UART interrupt: */ -#ifdef XCHAL_EXTINT0_NUM -#define UART16550_INTNUM XCHAL_EXTINT0_NUM -#define UART16550_INTLEVEL XCHAL_EXTINT0_LEVEL -#define UART16550_INTMASK XCHAL_EXTINT0_MASK -#else -#define UART16550_INTMASK 0 -#endif - -/* Audio output interrupt (I2S FIFO underrun): */ -#ifdef XCHAL_EXTINT2_NUM -#define AUDIO_INTNUM XCHAL_EXTINT2_NUM -#define AUDIO_INTLEVEL XCHAL_EXTINT2_LEVEL -#define AUDIO_INTMASK XCHAL_EXTINT2_MASK -#else -#define AUDIO_INTMASK 0 -#endif - -/* Audio output (I2S FIFO level) interrupt: */ -#ifdef XCHAL_EXTINT3_NUM -#define AUDIO_I2SLVL_INTNUM XCHAL_EXTINT3_NUM -#define AUDIO_I2SLVL_INTLEVEL XCHAL_EXTINT3_LEVEL -#define AUDIO_I2SLVL_INTMASK XCHAL_EXTINT3_MASK -#else -#define AUDIO_I2SLVL_INTMASK 0 -#endif - -/* Audio input (ADC FIFO level) interrupt: */ -#ifdef XCHAL_EXTINT4_NUM -#define AUDIO_ADCLVL_INTNUM XCHAL_EXTINT4_NUM -#define AUDIO_ADCLVL_INTLEVEL XCHAL_EXTINT4_LEVEL -#define AUDIO_ADCLVL_INTMASK XCHAL_EXTINT4_MASK -#else -#define AUDIO_ADCLVL_INTMASK 0 -#endif - - -/* - * Device addresses. - * - * Note: for endianness-independence, use 32-bit loads and stores for all - * register accesses to Ethernet, UART and LED devices. Undefined bits - * may need to be masked out if needed when reading if the actual register - * size is smaller than 32 bits. - * - * Note: XTAV200 bus byte lanes are defined in terms of msbyte and lsbyte - * relative to the processor. So 32-bit registers are accessed consistently - * from both big and little endian processors. However, this means byte - * sequences are not consistent between big and little endian processors. - * This is fine for RAM, and for ROM if ROM is created for a specific - * processor (and thus has correct byte sequences). However this may be - * unexpected for Flash, which might contain a file-system that one wants - * to use for multiple processor configurations (eg. the Flash might contain - * the Ethernet card's address, endianness-independent application data, etc). - * That is, byte sequences written in Flash by a core of a given endianness - * will be byte-swapped when seen by a core of the other endianness. - * Someone implementing an endianness-independent Flash file system will - * likely handle this byte-swapping issue in the Flash driver software. - */ - -#define XTBOARD_FLASH_MAXSIZE 0x1000000 /* 16 MB */ - -#ifdef XSHAL_IOBLOCK_BYPASS_PADDR - -/* Flash Memory: */ -# define XTBOARD_FLASH_PADDR (XSHAL_IOBLOCK_BYPASS_PADDR+0x08000000) - -/* FPGA registers: */ -# define XTBOARD_FPGAREGS_PADDR (XSHAL_IOBLOCK_BYPASS_PADDR+0x0D020000) - -/* Ethernet controller/transceiver SONIC SN83934: */ -# define ETHERNET_PADDR (XSHAL_IOBLOCK_BYPASS_PADDR+0x0D030000) - -/* UART National-Semi PC16550D: */ -# define UART16550_PADDR (XSHAL_IOBLOCK_BYPASS_PADDR+0x0D050000) - -/* TI 320AIC23/28-TSSOP Stereo Audio Codec: */ -# define AUDIO_PADDR (XSHAL_IOBLOCK_BYPASS_PADDR+0x0D070000) - -/* Boot 128K Sram address: */ -# define BOOT_SRAM_PADDR (XSHAL_IOBLOCK_BYPASS_PADDR+0x0D400000) - -/* Ethernet buffer: */ -# define ETHERNET_BUFFER_PADDR (XSHAL_IOBLOCK_BYPASS_PADDR+0x0D800000) - -#endif /* XSHAL_IOBLOCK_BYPASS_PADDR */ - -/* These devices might be accessed cached: */ -#ifdef XSHAL_IOBLOCK_CACHED_PADDR -# define XTBOARD_FLASH_CACHED_PADDR (XSHAL_IOBLOCK_CACHED_PADDR+0x08000000) -# define ETHERNET_BUFFER_CACHED_PADDR (XSHAL_IOBLOCK_CACHED_PADDR+0x0D800000) -# define BOOT_SRAM_CACHED_PADDR (XSHAL_IOBLOCK_CACHED_PADDR+0x0D400000) -#endif /* XSHAL_IOBLOCK_CACHED_PADDR */ - - -/*** Same thing over again, this time with virtual addresses: ***/ - -#ifdef XSHAL_IOBLOCK_BYPASS_VADDR - -/* Flash Memory: */ -# define XTBOARD_FLASH_VADDR (XSHAL_IOBLOCK_BYPASS_VADDR+0x08000000) - -/* FPGA registers: */ -# define XTBOARD_FPGAREGS_VADDR (XSHAL_IOBLOCK_BYPASS_VADDR+0x0D020000) - -/* Ethernet controller/transceiver SONIC SN83934: */ -# define ETHERNET_VADDR (XSHAL_IOBLOCK_BYPASS_VADDR+0x0D030000) - -/* UART National-Semi PC16550D: */ -# define UART16550_VADDR (XSHAL_IOBLOCK_BYPASS_VADDR+0x0D050000) - -/* TI 320AIC23/28-TSSOP Stereo Audio Codec: */ -# define AUDIO_VADDR (XSHAL_IOBLOCK_BYPASS_VADDR+0x0D070000) - -/* 128K Sram address: */ -# define BOOT_SRAM_VADDR (XSHAL_IOBLOCK_BYPASS_VADDR+0x0D400000) - -/* Ethernet buffer: */ -# define ETHERNET_BUFFER_VADDR (XSHAL_IOBLOCK_BYPASS_VADDR+0x0D800000) - -#endif /* XSHAL_IOBLOCK_BYPASS_VADDR */ - -/* These devices might be accessed cached: */ -#ifdef XSHAL_IOBLOCK_CACHED_VADDR -# define XTBOARD_FLASH_CACHED_VADDR (XSHAL_IOBLOCK_CACHED_VADDR+0x08000000) -# define AUDIO_CACHED_VADDR (XSHAL_IOBLOCK_CACHED_VADDR+0x0D070000) -# define ETHERNET_BUFFER_CACHED_VADDR (XSHAL_IOBLOCK_CACHED_VADDR+0x0D800000) -# define BOOT_SRAM_CACHED_VADDR (XSHAL_IOBLOCK_CACHED_VADDR+0x0D400000) -#endif /* XSHAL_IOBLOCK_CACHED_VADDR */ - - -/* System ROM: */ -#define XTBOARD_ROM_SIZE XSHAL_ROM_SIZE -#ifdef XSHAL_ROM_VADDR -#define XTBOARD_ROM_VADDR XSHAL_ROM_VADDR -#endif -#ifdef XSHAL_ROM_PADDR -#define XTBOARD_ROM_PADDR XSHAL_ROM_PADDR -#endif - -/* System RAM: */ -#define XTBOARD_RAM_SIZE XSHAL_RAM_SIZE -#ifdef XSHAL_RAM_VADDR -#define XTBOARD_RAM_VADDR XSHAL_RAM_VADDR -#endif -#ifdef XSHAL_RAM_PADDR -#define XTBOARD_RAM_PADDR XSHAL_RAM_PADDR -#endif -#define XTBOARD_RAM_BYPASS_VADDR XSHAL_RAM_BYPASS_VADDR -#define XTBOARD_RAM_BYPASS_PADDR XSHAL_RAM_BYPASS_PADDR - - - -/* - * Things that depend on device addresses. - */ - - -#define XTBOARD_CACHEATTR_WRITEBACK XSHAL_XT2000_CACHEATTR_WRITEBACK -#define XTBOARD_CACHEATTR_WRITEALLOC XSHAL_XT2000_CACHEATTR_WRITEALLOC -#define XTBOARD_CACHEATTR_WRITETHRU XSHAL_XT2000_CACHEATTR_WRITETHRU -#define XTBOARD_CACHEATTR_BYPASS XSHAL_XT2000_CACHEATTR_BYPASS -#define XTBOARD_CACHEATTR_DEFAULT XSHAL_XT2000_CACHEATTR_DEFAULT - -#define XTBOARD_BUSINT_PIPE_REGIONS XSHAL_XT2000_PIPE_REGIONS -#define XTBOARD_BUSINT_SDRAM_REGIONS XSHAL_XT2000_SDRAM_REGIONS - - -/* - * FPGA registers. - * All these registers are normally accessed using 32-bit loads/stores. - */ - -/* Register offsets: */ -#define XTBOARD_DATECD_OFS 0x00 /* date code (read-only) */ -#define XTBOARD_CLKFRQ_OFS 0x04 /* clock frequency Hz (read-only) */ -#define XTBOARD_SYSLED_OFS 0x08 /* LEDs */ -#define XTBOARD_DIPSW_OFS 0x0C /* DIP switch bits (read-only) */ -#define XTBOARD_SWRST_OFS 0x10 /* software reset */ - -/* Physical register addresses: */ -#ifdef XTBOARD_FPGAREGS_PADDR -#define XTBOARD_DATECD_PADDR (XTBOARD_FPGAREGS_PADDR+XTBOARD_DATECD_OFS) -#define XTBOARD_CLKFRQ_PADDR (XTBOARD_FPGAREGS_PADDR+XTBOARD_CLKFRQ_OFS) -#define XTBOARD_SYSLED_PADDR (XTBOARD_FPGAREGS_PADDR+XTBOARD_SYSLED_OFS) -#define XTBOARD_DIPSW_PADDR (XTBOARD_FPGAREGS_PADDR+XTBOARD_DIPSW_OFS) -#define XTBOARD_SWRST_PADDR (XTBOARD_FPGAREGS_PADDR+XTBOARD_SWRST_OFS) -#endif - -/* Virtual register addresses: */ -#ifdef XTBOARD_FPGAREGS_VADDR -#define XTBOARD_DATECD_VADDR (XTBOARD_FPGAREGS_VADDR+XTBOARD_DATECD_OFS) -#define XTBOARD_CLKFRQ_VADDR (XTBOARD_FPGAREGS_VADDR+XTBOARD_CLKFRQ_OFS) -#define XTBOARD_SYSLED_VADDR (XTBOARD_FPGAREGS_VADDR+XTBOARD_SYSLED_OFS) -#define XTBOARD_DIPSW_VADDR (XTBOARD_FPGAREGS_VADDR+XTBOARD_DIPSW_OFS) -#define XTBOARD_SWRST_VADDR (XTBOARD_FPGAREGS_VADDR+XTBOARD_SWRST_OFS) -/* Register access (for C code): */ -#define XTBOARD_DATECD_REG (*(volatile unsigned*) XTBOARD_DATECD_VADDR) -#define XTBOARD_CLKFRQ_REG (*(volatile unsigned*) XTBOARD_CLKFRQ_VADDR) -#define XTBOARD_SYSLED_REG (*(volatile unsigned*) XTBOARD_SYSLED_VADDR) -#define XTBOARD_DIPSW_REG (*(volatile unsigned*) XTBOARD_DIPSW_VADDR) -#define XTBOARD_SWRST_REG (*(volatile unsigned*) XTBOARD_SWRST_VADDR) -#endif - -/* DATECD (date code; when core was built) bit fields: */ -/* BCD-coded month (01..12): */ -#define XTBOARD_DATECD_MONTH_SHIFT 24 -#define XTBOARD_DATECD_MONTH_BITS 8 -#define XTBOARD_DATECD_MONTH_MASK 0xFF000000 -/* BCD-coded day (01..31): */ -#define XTBOARD_DATECD_DAY_SHIFT 16 -#define XTBOARD_DATECD_DAY_BITS 8 -#define XTBOARD_DATECD_DAY_MASK 0x00FF0000 -/* BCD-coded year (2001..9999): */ -#define XTBOARD_DATECD_YEAR_SHIFT 0 -#define XTBOARD_DATECD_YEAR_BITS 16 -#define XTBOARD_DATECD_YEAR_MASK 0x0000FFFF - -/* SYSLED (system LED) bit fields: */ - -/* LED control bits (off=0, on=1): */ -#define XTBOARD_SYSLED_USER_SHIFT 0 -#define XTBOARD_SYSLED_USER_BITS 4 -#define XTBOARD_SYSLED_USER_MASK 0x0000000F - -/* DIP Switch (left=sw1=lsb=bit0, right=sw8=msb=bit7; off=0, on=1): */ -/* DIP switch bit fields (bit6/sw7 is reserved and presently unused): */ -#define XTBOARD_DIPSW_USER_SHIFT 0 /* labeled 1-6 (1=lsb) */ -#define XTBOARD_DIPSW_USER_BITS 6 -#define XTBOARD_DIPSW_USER_MASK 0x0000003F -#define XTBOARD_DIPSW_BOOT_SHIFT 7 /* labeled 8 (msb) */ -#define XTBOARD_DIPSW_BOOT_BITS 1 -#define XTBOARD_DIPSW_BOOT_MASK 0x00000080 -/* Boot settings: bit7/sw8, off=0, on=1 (this switch controls hardware): */ -#define XTBOARD_DIPSW_BOOT_RAM (0< - diff --git a/components/esp32/include/xtensa/xtav60.h b/components/esp32/include/xtensa/xtav60.h deleted file mode 100644 index d7c8e3aed8..0000000000 --- a/components/esp32/include/xtensa/xtav60.h +++ /dev/null @@ -1,241 +0,0 @@ -/* Copyright (c) 2002-2013 by Tensilica Inc. ALL RIGHTS RESERVED. -/ These coded instructions, statements, and computer programs are the -/ copyrighted works and confidential proprietary information of Tensilica Inc. -/ They may not be modified, copied, reproduced, distributed, or disclosed to -/ third parties in any manner, medium, or form, in whole or in part, without -/ the prior written consent of Tensilica Inc. -*/ - -/* xtav60.h - Xtensa Avnet LX60 (XT-AV60) board specific definitions */ - -#ifndef _INC_XTAV60_H_ -#define _INC_XTAV60_H_ - -#include -#include - -#define XTBOARD_NAME "XT-AV60" - - -/* - * Default assignment of XTAV60 devices to external interrupts. - */ - -/* Ethernet interrupt: */ -#ifdef XCHAL_EXTINT1_NUM -#define ETHERNET_INTNUM XCHAL_EXTINT1_NUM -#define ETHERNET_INTLEVEL XCHAL_EXTINT1_LEVEL -#define ETHERNET_INTMASK XCHAL_EXTINT1_MASK -#else -#define ETHERNET_INTMASK 0 -#endif - -/* UART interrupt: */ -#ifdef XCHAL_EXTINT0_NUM -#define UART16550_INTNUM XCHAL_EXTINT0_NUM -#define UART16550_INTLEVEL XCHAL_EXTINT0_LEVEL -#define UART16550_INTMASK XCHAL_EXTINT0_MASK -#else -#define UART16550_INTMASK 0 -#endif - -/* - * Device addresses. - * - * Note: for endianness-independence, use 32-bit loads and stores for all - * register accesses to Ethernet, UART and LED devices. Undefined bits - * may need to be masked out if needed when reading if the actual register - * size is smaller than 32 bits. - * - * Note: XTAV60 bus byte lanes are defined in terms of msbyte and lsbyte - * relative to the processor. So 32-bit registers are accessed consistently - * from both big and little endian processors. However, this means byte - * sequences are not consistent between big and little endian processors. - * This is fine for RAM, and for ROM if ROM is created for a specific - * processor (and thus has correct byte sequences). However this may be - * unexpected for Flash, which might contain a file-system that one wants - * to use for multiple processor configurations (eg. the Flash might contain - * the Ethernet card's address, endianness-independent application data, etc). - * That is, byte sequences written in Flash by a core of a given endianness - * will be byte-swapped when seen by a core of the other endianness. - * Someone implementing an endianness-independent Flash file system will - * likely handle this byte-swapping issue in the Flash driver software. - */ - -#define XTBOARD_FLASH_MAXSIZE 0x400000 /* 4 MB */ - -#ifdef XSHAL_IOBLOCK_BYPASS_PADDR - -/* Flash Memory: */ -# define XTBOARD_FLASH_PADDR (XSHAL_IOBLOCK_BYPASS_PADDR+0x08000000) - -/* FPGA registers: */ -# define XTBOARD_FPGAREGS_PADDR (XSHAL_IOBLOCK_BYPASS_PADDR+0x0D020000) - -/* Ethernet controller/transceiver SONIC SN83934: */ -# define ETHERNET_PADDR (XSHAL_IOBLOCK_BYPASS_PADDR+0x0D030000) -# define ETHERNET_CONTROLLER_PADDR ETHERNET_PADDR /* legacy macro */ - -/* Display controller Sunplus SPLC780D, LCD Display MYTech MOC-16216B-B: */ -# define SPLC780D_PADDR (XSHAL_IOBLOCK_BYPASS_PADDR+0x0D040000) - -/* UART National-Semi PC16550D: */ -# define UART16550_PADDR (XSHAL_IOBLOCK_BYPASS_PADDR+0x0D050000) - -/* Boot 128K Sram address: */ -# define BOOT_SRAM_PADDR (XSHAL_IOBLOCK_BYPASS_PADDR+0x0D400000) - -/* Ethernet buffer: */ -# define ETHERNET_BUFFER_PADDR (XSHAL_IOBLOCK_BYPASS_PADDR+0x0D800000) - -#endif /* XSHAL_IOBLOCK_BYPASS_PADDR */ - -/* These devices might be accessed cached: */ -#ifdef XSHAL_IOBLOCK_CACHED_PADDR -# define XTBOARD_FLASH_CACHED_PADDR (XSHAL_IOBLOCK_CACHED_PADDR+0x08000000) -# define ETHERNET_BUFFER_CACHED_PADDR (XSHAL_IOBLOCK_CACHED_PADDR+0x0D800000) -# define BOOT_SRAM_CACHED_PADDR (XSHAL_IOBLOCK_CACHED_PADDR+0x0D400000) -#endif /* XSHAL_IOBLOCK_CACHED_PADDR */ - - -/*** Same thing over again, this time with virtual addresses: ***/ - -#ifdef XSHAL_IOBLOCK_BYPASS_VADDR - -/* Flash Memory: */ -# define XTBOARD_FLASH_VADDR (XSHAL_IOBLOCK_BYPASS_VADDR+0x08000000) - -/* FPGA registers: */ -# define XTBOARD_FPGAREGS_VADDR (XSHAL_IOBLOCK_BYPASS_VADDR+0x0D020000) - -/* Ethernet controller/transceiver SONIC SN83934: */ -# define ETHERNET_VADDR (XSHAL_IOBLOCK_BYPASS_VADDR+0x0D030000) - -/* Display controller Sunplus SPLC780D, LCD Display MYTech MOC-16216B-B: */ -# define SPLC780D_VADDR (XSHAL_IOBLOCK_BYPASS_VADDR+0x0D040000) - -/* UART National-Semi PC16550D: */ -# define UART16550_VADDR (XSHAL_IOBLOCK_BYPASS_VADDR+0x0D050000) - -/* 128K Sram address: */ -# define BOOT_SRAM_VADDR (XSHAL_IOBLOCK_BYPASS_VADDR+0x0D400000) - -/* Ethernet buffer: */ -# define ETHERNET_BUFFER_VADDR (XSHAL_IOBLOCK_BYPASS_VADDR+0x0D800000) - -#endif /* XSHAL_IOBLOCK_BYPASS_VADDR */ - -/* These devices might be accessed cached: */ -#ifdef XSHAL_IOBLOCK_CACHED_VADDR -# define XTBOARD_FLASH_CACHED_VADDR (XSHAL_IOBLOCK_CACHED_VADDR+0x08000000) -# define ETHERNET_BUFFER_CACHED_VADDR (XSHAL_IOBLOCK_CACHED_VADDR+0x0D800000) -# define BOOT_SRAM_CACHED_VADDR (XSHAL_IOBLOCK_CACHED_VADDR+0x0D400000) -#endif /* XSHAL_IOBLOCK_CACHED_VADDR */ - - -/* System ROM: */ -#define XTBOARD_ROM_SIZE XSHAL_ROM_SIZE -#ifdef XSHAL_ROM_VADDR -#define XTBOARD_ROM_VADDR XSHAL_ROM_VADDR -#endif -#ifdef XSHAL_ROM_PADDR -#define XTBOARD_ROM_PADDR XSHAL_ROM_PADDR -#endif - -/* System RAM: */ -#define XTBOARD_RAM_SIZE XSHAL_RAM_SIZE -#ifdef XSHAL_RAM_VADDR -#define XTBOARD_RAM_VADDR XSHAL_RAM_VADDR -#endif -#ifdef XSHAL_RAM_PADDR -#define XTBOARD_RAM_PADDR XSHAL_RAM_PADDR -#endif -#define XTBOARD_RAM_BYPASS_VADDR XSHAL_RAM_BYPASS_VADDR -#define XTBOARD_RAM_BYPASS_PADDR XSHAL_RAM_BYPASS_PADDR - - - -/* - * Things that depend on device addresses. - */ - - -#define XTBOARD_CACHEATTR_WRITEBACK XSHAL_XT2000_CACHEATTR_WRITEBACK -#define XTBOARD_CACHEATTR_WRITEALLOC XSHAL_XT2000_CACHEATTR_WRITEALLOC -#define XTBOARD_CACHEATTR_WRITETHRU XSHAL_XT2000_CACHEATTR_WRITETHRU -#define XTBOARD_CACHEATTR_BYPASS XSHAL_XT2000_CACHEATTR_BYPASS -#define XTBOARD_CACHEATTR_DEFAULT XSHAL_XT2000_CACHEATTR_DEFAULT - -#define XTBOARD_BUSINT_PIPE_REGIONS XSHAL_XT2000_PIPE_REGIONS -#define XTBOARD_BUSINT_SDRAM_REGIONS XSHAL_XT2000_SDRAM_REGIONS - - -/* - * FPGA registers. - * All these registers are normally accessed using 32-bit loads/stores. - */ - -/* Register offsets: */ -#define XTBOARD_DATECD_OFS 0x00 /* date code (read-only) */ -#define XTBOARD_CLKFRQ_OFS 0x04 /* clock frequency Hz (read-only) */ -#define XTBOARD_DIPSW_OFS 0x0C /* DIP switch bits (read-only) */ -#define XTBOARD_SWRST_OFS 0x10 /* software reset */ - -/* Physical register addresses: */ -#ifdef XTBOARD_FPGAREGS_PADDR -#define XTBOARD_DATECD_PADDR (XTBOARD_FPGAREGS_PADDR+XTBOARD_DATECD_OFS) -#define XTBOARD_CLKFRQ_PADDR (XTBOARD_FPGAREGS_PADDR+XTBOARD_CLKFRQ_OFS) -#define XTBOARD_DIPSW_PADDR (XTBOARD_FPGAREGS_PADDR+XTBOARD_DIPSW_OFS) -#define XTBOARD_SWRST_PADDR (XTBOARD_FPGAREGS_PADDR+XTBOARD_SWRST_OFS) -#endif - -/* Virtual register addresses: */ -#ifdef XTBOARD_FPGAREGS_VADDR -#define XTBOARD_DATECD_VADDR (XTBOARD_FPGAREGS_VADDR+XTBOARD_DATECD_OFS) -#define XTBOARD_CLKFRQ_VADDR (XTBOARD_FPGAREGS_VADDR+XTBOARD_CLKFRQ_OFS) -#define XTBOARD_DIPSW_VADDR (XTBOARD_FPGAREGS_VADDR+XTBOARD_DIPSW_OFS) -#define XTBOARD_SWRST_VADDR (XTBOARD_FPGAREGS_VADDR+XTBOARD_SWRST_OFS) -/* Register access (for C code): */ -#define XTBOARD_DATECD_REG (*(volatile unsigned*) XTBOARD_DATECD_VADDR) -#define XTBOARD_CLKFRQ_REG (*(volatile unsigned*) XTBOARD_CLKFRQ_VADDR) -#define XTBOARD_DIPSW_REG (*(volatile unsigned*) XTBOARD_DIPSW_VADDR) -#define XTBOARD_SWRST_REG (*(volatile unsigned*) XTBOARD_SWRST_VADDR) -#endif - -/* DATECD (date code; when core was built) bit fields: */ -/* BCD-coded month (01..12): */ -#define XTBOARD_DATECD_MONTH_SHIFT 24 -#define XTBOARD_DATECD_MONTH_BITS 8 -#define XTBOARD_DATECD_MONTH_MASK 0xFF000000 -/* BCD-coded day (01..31): */ -#define XTBOARD_DATECD_DAY_SHIFT 16 -#define XTBOARD_DATECD_DAY_BITS 8 -#define XTBOARD_DATECD_DAY_MASK 0x00FF0000 -/* BCD-coded year (2001..9999): */ -#define XTBOARD_DATECD_YEAR_SHIFT 0 -#define XTBOARD_DATECD_YEAR_BITS 16 -#define XTBOARD_DATECD_YEAR_MASK 0x0000FFFF - -/* DIP Switch (left=sw1=lsb=bit0, right=sw8=msb=bit7; off=0, on=1): */ -/* DIP switch bit fields (bit6/sw7 is reserved and presently unused): */ -#define XTBOARD_DIPSW_USER_SHIFT 0 /* labeled 1-6 (1=lsb) */ -#define XTBOARD_DIPSW_USER_BITS 6 -#define XTBOARD_DIPSW_USER_MASK 0x0000003F -#define XTBOARD_DIPSW_BOOT_SHIFT 7 /* labeled 8 (msb) */ -#define XTBOARD_DIPSW_BOOT_BITS 1 -#define XTBOARD_DIPSW_BOOT_MASK 0x00000080 -/* Boot settings: bit7/sw8, off=0, on=1 (this switch controls hardware): */ -#define XTBOARD_DIPSW_BOOT_RAM (0< - diff --git a/components/esp32/include/xtensa/xtav60/xtensa/lcd-splc780d-board.h b/components/esp32/include/xtensa/xtav60/xtensa/lcd-splc780d-board.h deleted file mode 100644 index 629a32581a..0000000000 --- a/components/esp32/include/xtensa/xtav60/xtensa/lcd-splc780d-board.h +++ /dev/null @@ -1,60 +0,0 @@ -/******************************************************************************* - -Copyright (c) 2006-2007 by Tensilica Inc. ALL RIGHTS RESERVED. -These coded instructions, statements, and computer programs are the -copyrighted works and confidential proprietary information of Tensilica Inc. -They may not be modified, copied, reproduced, distributed, or disclosed to -third parties in any manner, medium, or form, in whole or in part, without -the prior written consent of Tensilica Inc. --------------------------------------------------------------------------------- - -lcd-splc780d-board.h Board-specific LCD info on Avnet AV60 (XT-AV60) board. - -Interface between board-independent driver and board-specific header. - -This is used by a board-independent SPLC780D LCD controller driver to obtain -board-specific information about LCD displays on the board, such as the -controller register base address and spacing (a function of how the address -lines are connected on the board) and length of the visible window of the -display (a function of the LCD panel the controller drives). The driver does -not refer directly to the board-specific header, which therefore is not -constrained to use macro names consistent with other boards. - -!! Must not contain any board-specific macro names (only controller specific) !! - -Included at compile-time via an include path specific to the board. - -The XT-AV60 board contains a single MYTech MOC-16216B-B display driven by -a Sunplus SPLC870D controller. - -*******************************************************************************/ - -#ifndef _LCD_SPLC780D_BOARD_H -#define _LCD_SPLC780D_BOARD_H - -#include /* Board info */ - - -/* Base address of the controller's registers. */ -#ifdef SPLC780D_VADDR -#define SPLC780D_REGBASE SPLC780D_VADDR -#endif - -/* -The controller's registers are connected at word addresses on the XT-AV60. -Each byte-wide register appears as the least-significant-byte (LSB) of the -word regardless of the endianness of the processor (so if using word accesses -then endianness doesn't matter). -*/ -#define SPLC780D_REGSPACING 4 -typedef unsigned splc780d_reg_t; - -/* Include generic information shared by all boards that use this device. */ -#include - - -/* Display limits of the LCD panel. */ -#define DISPLAY_VISIBLE_LEN 16 /* length (chars) of visible window */ - -#endif /* _LCD_SPLC780D_BOARD_H */ - diff --git a/components/esp32/include/xtensa/xtbsp.h b/components/esp32/include/xtensa/xtbsp.h deleted file mode 100644 index 62356dd868..0000000000 --- a/components/esp32/include/xtensa/xtbsp.h +++ /dev/null @@ -1,269 +0,0 @@ -/******************************************************************************* - - Copyright (c) 2006-2009 Tensilica 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. - --------------------------------------------------------------------------------- - -xtbsp.h Xtensa Board Support Package API - -This API defines a minimal set of board-support functions that every supported -Xtensa board is expected to provide in the board-support-package (BSP) library -associated with the board-specific LSP. Only basic board functions are provided -in this board-independent API. API functions not applicable to a board must be -stubbed in its BSP library. More complex operations must use a board-specific -interface. Functions are grouped by type of peripheral device. - -*******************************************************************************/ - -#ifndef _XTBSP_H_ -#define _XTBSP_H_ - - -#ifdef __cplusplus -extern "C" { -#endif - - -/******************************************************************************* -BOARD INITIALIZATION. -The board with all its devices is initialized by xtbsp_board_init(). -Individual devices represented by this API can be reinitialized at any -time by calling their inidividual device init functions (grouped with -other device functions). This might be useful to (say) change the baud -rate of the UART. -*/ - - -/* -Initialize the board. Must call before any other API function. -Iniitializes BSP, board in general, and all devices on the board. -*/ -extern void xtbsp_board_init(void); - - -/******************************************************************************* -BOARD CHARACTERISTICS and CONVENIENCE FUNCTIONS. -Board support functions not associated with a particular peripheral device. -*/ - -/* -Return a short string representing the type of board. -If the board has a display, the string must fit on a single line. -*/ -extern const char * xtbsp_board_name(void); - -/* -Hardware reset the entire board (if possible). Does not return if successful. -If this function returns, it is stubbed out or not possible with this board. -*/ -extern void xtbsp_board_reset(void); - -/* -Return the clock frequency in Hertz. May be constant or computed. -*/ -extern unsigned xtbsp_clock_freq_hz(void); - -/* -Return the clock period in picoseconds. May be constant or computed. -*/ -extern unsigned xtbsp_clock_period_ps(void); - -/* -Spin (at least) a number of cycles per the processor's CCOUNT register. -Unlike a s/w delay loop, the duration is not affected by compiler -optimization or interrupts completed within the delay period. -If the processor doesn't have CCOUNT, a s/w delay loop is used to obtain -a rough approximation of the cycle count. -*/ -extern void xtbsp_delay_cycles(unsigned cycles); - -/* -Spin at least a number of nanoseconds (approximate and err in the high side). -BSP implementation should do this efficiently, avoiding integer overflow or -excessive loss of precision, run-time division or floating point. -Function implementation (vs. macro) allows BSP to optimize for the clock -frequency by pre-computing (or using constant) scale factors. -*/ -extern void xtbsp_delay_ns(unsigned ns); - - -/******************************************************************************* -C LIBRARY SUPPORT. -These functions are called by the C library libgloss interface. -Their names are predetermined apart from this BSP API. -*/ - -/* -Initialize the board. Called by C library initialization code. -Usually simply calls xtbsp_board_init(). -*/ -extern void board_init(void); - -/* -(Wait for and) Input a single byte from the default character I/O -device. Return -1 if there is no input device. -This device is usually a UART and this function calls xtbsp_uart_getchar(). -On some boards (eg.) it might be a directly connected keyboard. -*/ -extern int inbyte(void); - -/* -Output a single char to the default character I/O device (and wait -until it's been taken). -This device is usually a UART and this function calls xtbsp_uart_putchar(). -On some boards (eg.) it might be a directly connected bit-mapped screen. -*/ -extern void outbyte(int c); - - -/******************************************************************************* -UART (SERIAL I/O). -Supports a single UART in a simple polling mode and provides control of -receiver and transmitter data interrupts (client must provide handler). -Provides a mapping to processor interrupt number which can be used with -the HAL to control processor interrupt enable (INTENABLE) etc. -*/ - -/* Bitmasks to identify UART interrupts. */ -typedef enum xtbsp_uart_int { - xtbsp_uart_int_rx = 1<<0, - xtbsp_uart_int_tx = 1<<1, - /* mask of all valid interrupt bits */ - xtbsp_uart_int_all = (1<<2)-1 -} xtbsp_uart_int; - -/* -Return non-zero if the board has a UART. -*/ -extern int xtbsp_uart_exists(void); - -/* -Initialize the UART: - parity = 0 (none), 1 (odd), or 2 (even). - nstop = 1 or 2 (stop bits). - ndata = 7 or 8 (data bits). -Disables all UART interrupts. -Returns non-zero if failed (perhaps due to unsupported parameter values). -Must call before any of the following functions. -*/ -extern int xtbsp_uart_init(unsigned baud, unsigned ndata, - unsigned parity, unsigned nstop); -#define xtbsp_uart_init_default() xtbsp_uart_init(38400, 8, 0, 1) - -/* -(Wait for and) Input a single char from the UART. -Any pending xtbsp_uart_int_rx interrupt is cleared. -*/ -extern char xtbsp_uart_getchar(void); - -/* -(Wait for transmitter ready and) Output a single char to the UART. -Any pending xtbsp_uart_int_tx interrupt is cleared. -*/ -extern void xtbsp_uart_putchar(const char c); - -/* -Return true (non-zero) if a character has been received and is ready -to be input by xtbsp_uart_getchar() without waiting, else return 0. -*/ -extern int xtbsp_uart_get_isready(void); - -/* -Return non-zero if a character may be output by xtbsp_uart_putchar() -without waiting, else return 0. -Any pending xtbsp_uart_int_tx interrupt is cleared. -*/ -extern int xtbsp_uart_put_isready(void); - -/* -Return the enable status of all UART interrupts represented by this API, -that is those with bits defined in type xtbsp_uart_int (1 bit = enabled). -This is the enable status at the device, not the processor's INTENABLE. -*/ -extern xtbsp_uart_int xtbsp_uart_int_enable_status(void); - -/* -Enable selected UART interrupts at the device. -*/ -extern void xtbsp_uart_int_enable(const xtbsp_uart_int mask); - -/* -Disable selected UART interrupts at the device. -*/ -extern void xtbsp_uart_int_disable(const xtbsp_uart_int mask); - -/* -Return the interrupt number (0..31) to which the selected UART interrupt -is connected. May be used with the link-time HAL to obtain more information, -eg. Xthal_intlevel_mask[xtbsp_uart_int_number(xtbsp_uart_int_rx)] -This information can be used to control the processor's INTENABLE, etc. -Result is -1 if not connected, undefined if mask has more than 1 bit set. -*/ -extern int xtbsp_uart_int_number(const xtbsp_uart_int mask); - - -/******************************************************************************* -DISPLAY. -Supports a single display that can render a series of ASCII characters. -Functions are provided to perform generic display tasks such as display -a string, display character by character, or blank the display. -Chars are 7-bit printable ASCII. Strings are C style NUL \0 terminated. -These functions busy-wait for any required timing delays so the caller does -not have to deal with timing. Some displays require long delays which in -some client applications warrant a board and RTOS specific approach to -driving the display, however that is beyond the scope of this API. -*/ - -/* -Return non-zero if board has a display. -*/ -extern int xtbsp_display_exists(void); - -/* -Initialize the display. Must call before any of the following functions. -*/ -extern void xtbsp_display_init(void); - -/* -Display a single char at position pos (0 is leftmost). Other positions are -left untouched. Positions beyond the width of the display are ignored. -*/ -extern void xtbsp_display_char(unsigned pos, const char c); - -/* -Display a string. Blank-pad to or truncate at the end of the display -(overwrites any previous string so don't need to blank display first). -*/ -extern void xtbsp_display_string(const char *s); - -/* -Blank (clear) the entire display. -*/ -extern void xtbsp_display_blank(void); - - - -#ifdef __cplusplus -} -#endif - -#endif /* _XTBSP_H_ */ diff --git a/components/esp32/include/xtensa/xtkc705.h b/components/esp32/include/xtensa/xtkc705.h deleted file mode 100644 index 831c15d541..0000000000 --- a/components/esp32/include/xtensa/xtkc705.h +++ /dev/null @@ -1,14 +0,0 @@ -/* Copyright (c) 2006-2013 by Tensilica Inc. ALL RIGHTS RESERVED. -/ These coded instructions, statements, and computer programs are the -/ copyrighted works and confidential proprietary information of Tensilica Inc. -/ They may not be modified, copied, reproduced, distributed, or disclosed to -/ third parties in any manner, medium, or form, in whole or in part, without -/ the prior written consent of Tensilica Inc. -*/ - -/* xtkc705.h - Xtensa Xilinx KC705 (XT-KC705) board specific definitions */ - -/* 99.9% same as ML605, just indicate we're KC705 and include ML605 header: */ -#define XTBOARD_IS_KC705 1 -#include - diff --git a/components/esp32/include/xtensa/xtkc705/xtensa/board.h b/components/esp32/include/xtensa/xtkc705/xtensa/board.h deleted file mode 100644 index 5d2d834802..0000000000 --- a/components/esp32/include/xtensa/xtkc705/xtensa/board.h +++ /dev/null @@ -1,13 +0,0 @@ -/* - * board.h - Include board-specific definitions - * - * Copyright (c) 2013 by Tensilica Inc. ALL RIGHTS RESERVED. - * These coded instructions, statements, and computer programs are the - * copyrighted works and confidential proprietary information of Tensilica Inc. - * They may not be modified, copied, reproduced, distributed, or disclosed to - * third parties in any manner, medium, or form, in whole or in part, without - * the prior written consent of Tensilica Inc. - */ - -#include - diff --git a/components/esp32/include/xtensa/xtload-api.h b/components/esp32/include/xtensa/xtload-api.h deleted file mode 100644 index 4e2297f510..0000000000 --- a/components/esp32/include/xtensa/xtload-api.h +++ /dev/null @@ -1,77 +0,0 @@ -/* Customer ID=11656; Build=0x5f626; Copyright (c) 2003-2012 Tensilica Inc. ALL RIGHTS RESERVED. - These coded instructions, statements, and computer programs are the - copyrighted works and confidential proprietary information of Tensilica Inc. - They may not be modified, copied, reproduced, distributed, or disclosed to - third parties in any manner, medium, or form, in whole or in part, without - the prior written consent of Tensilica Inc. */ - -#ifndef _XTLOAD_API_H -#define _XTLOAD_API_H - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -#define XTENSA_BYTES_PER_WORD 4 -#define XLOAD_ALL_CORES -1 - -typedef int core_number_t; -typedef uint32_t xtload_address_t; -typedef uint32_t xtload_word_count_t; -typedef uint32_t * xtload_word_ptr_t; - -/* These functions correspond one-to-one with xt-load script - commands. See the documentation for xt-load for their usage. - - There are however, several higher-level script commands--such as - load-elf-file--which don't have direct analogues here. These - "missing" commands are essentially just macros that result in - several of these commands below. Note that you can execute several - of these commands, then the results of a script, or vice-versa. - */ - -void xtload_bootloader_wake (void); -void xtload_bootloader_sleep (void); -void xtload_bootloader_done (void); -void xtload_bootloader_not_done (void); -void xtload_reset_and_cont (core_number_t core); -void xtload_stall_and_reset (core_number_t core); -#define xtload_reset_and_stall xtload_stall_and_reset -void xtload_stall_and_target (core_number_t core); -void xtload_ignore_and_stall (core_number_t core); -void xtload_ignore_and_cont (core_number_t core); -#define xtload_ignore_and_continue xtload_ignore_and_cont -void xtload_read_words (xtload_address_t addr, xtload_word_count_t count); -void xtload_zero_words (xtload_address_t addr, xtload_word_count_t count); -void xtload_write_words (int swap, xtload_address_t addr, - xtload_word_ptr_t ptr, xtload_word_count_t count); -void xtload_setup_write_words (xtload_address_t addr, xtload_word_count_t count); -void xtload_read_register (core_number_t core); - -/* *I M P O R T A N T* - - The bootloader API calls this function whenever it outputs a word - to the bootloader hardware chain. - - Because the API has no information about how the bootloader - hardware is connected to the host hardware, the user must - implement this function to write a word to the bootloader's register. - - A user's implementation might write the bytes to an Xtensa queue or - to a memory-mapped register. - - For example, xt-load uses this API just like any other client. Its - implementation of this function simply writes this word to an - output file. -*/ - -void xtload_user_output_word (uint32_t word); - -#ifdef __cplusplus -} -#endif - -#endif /* _XTLOAD_API_H */ - diff --git a/components/esp32/include/xtensa/xtml605.h b/components/esp32/include/xtensa/xtml605.h deleted file mode 100644 index 5f54d700d1..0000000000 --- a/components/esp32/include/xtensa/xtml605.h +++ /dev/null @@ -1,338 +0,0 @@ -/* Copyright (c) 2007-2013 by Tensilica Inc. ALL RIGHTS RESERVED. -/ These coded instructions, statements, and computer programs are the -/ copyrighted works and confidential proprietary information of Tensilica Inc. -/ They may not be modified, copied, reproduced, distributed, or disclosed to -/ third parties in any manner, medium, or form, in whole or in part, without -/ the prior written consent of Tensilica Inc. -*/ - -/* xtml605.h - Xtensa Xilinx ML605 (XT-ML605) board specific definitions */ -/* xtkc705.h - Also includes this, for the Xilinx KC705 (XT-KC705). */ - -#ifndef _INC_ML605_H_ -#define _INC_ML605_H_ - -#include -#include - -#if XTBOARD_IS_KC705 -#define XTBOARD_NAME "XT-KC705" -#else -#define XTBOARD_NAME "XT-ML605" -#endif - - -/* - * Default assignment of ML605 devices to external interrupts. - */ - -/* Ethernet interrupt: */ -#ifdef XCHAL_EXTINT1_NUM -#define ETHERNET_INTNUM XCHAL_EXTINT1_NUM -#define ETHERNET_INTLEVEL XCHAL_EXTINT1_LEVEL -#define ETHERNET_INTMASK XCHAL_EXTINT1_MASK -#else -#define ETHERNET_INTMASK 0 -#endif - -/* UART interrupt: */ -#ifdef XCHAL_EXTINT0_NUM -#define UART16550_INTNUM XCHAL_EXTINT0_NUM -#define UART16550_INTLEVEL XCHAL_EXTINT0_LEVEL -#define UART16550_INTMASK XCHAL_EXTINT0_MASK -#else -#define UART16550_INTMASK 0 -#endif - -/* Audio output interrupt (I2S transmitter FIFO): */ -#ifdef XCHAL_EXTINT2_NUM -#define AUDIO_I2S_OUT_INTNUM XCHAL_EXTINT2_NUM -#define AUDIO_I2S_OUT_INTLEVEL XCHAL_EXTINT2_LEVEL -#define AUDIO_I2S_OUT_INTMASK XCHAL_EXTINT2_MASK -#else -#define AUDIO_I2S_OUT_INTMASK 0 -#endif - -/* Audio input interrupt (I2S receiver FIFO): */ -#ifdef XCHAL_EXTINT3_NUM -#define AUDIO_I2S_IN_INTNUM XCHAL_EXTINT3_NUM -#define AUDIO_I2S_IN_INTLEVEL XCHAL_EXTINT3_LEVEL -#define AUDIO_I2S_IN_INTMASK XCHAL_EXTINT3_MASK -#else -#define AUDIO_I2S_IN_INTMASK 0 -#endif - -/* I2C interrupt */ -#ifdef XCHAL_EXTINT4_NUM -#define I2C_INTNUM XCHAL_EXTINT4_NUM -#define I2C_INTLEVEL XCHAL_EXTINT4_LEVEL -#define I2C_INTMASK XCHAL_EXTINT4_MASK -#else -#define I2C_INTMASK 0 -#endif - -/* USB interrupt */ -#ifdef XCHAL_EXTINT5_NUM -#define USB_INTNUM XCHAL_EXTINT5_NUM -#define USB_INTLEVEL XCHAL_EXTINT5_LEVEL -#define USB_INTMASK XCHAL_EXTINT5_MASK -#else -#define USB_INTMASK 0 -#endif - -/* - * Device addresses. - * - * Note: for endianness-independence, use 32-bit loads and stores for all - * register accesses to Ethernet, UART and LED devices. Undefined bits - * may need to be masked out if needed when reading if the actual register - * size is smaller than 32 bits. - * - * Note: ML605 bus byte lanes are defined in terms of msbyte and lsbyte - * relative to the processor. So 32-bit registers are accessed consistently - * from both big and little endian processors. However, this means byte - * sequences are not consistent between big and little endian processors. - * This is fine for RAM, and for ROM if ROM is created for a specific - * processor (and thus has correct byte sequences). However this may be - * unexpected for Flash, which might contain a file-system that one wants - * to use for multiple processor configurations (eg. the Flash might contain - * the Ethernet card's address, endianness-independent application data, etc). - * That is, byte sequences written in Flash by a core of a given endianness - * will be byte-swapped when seen by a core of the other endianness. - * Someone implementing an endianness-independent Flash file system will - * likely handle this byte-swapping issue in the Flash driver software. - */ - -#define ML605_FLASH_MAXSIZE 0x01000000 /* 16 MB */ -#define ML605_FLASH_IOBLOCK_OFS 0x08000000 - -#define KC705_FLASH_MAXSIZE 0x08000000 /* 128 MB */ -#define KC705_FLASH_IOBLOCK_OFS 0x00000000 - -#if XTBOARD_IS_KC705 -#define XTBOARD_FLASH_MAXSIZE KC705_FLASH_MAXSIZE -#define XTBOARD_FLASH_IO_OFS KC705_FLASH_IOBLOCK_OFS -#else -#define XTBOARD_FLASH_MAXSIZE ML605_FLASH_MAXSIZE -#define XTBOARD_FLASH_IO_OFS ML605_FLASH_IOBLOCK_OFS -#endif - -#ifdef XSHAL_IOBLOCK_BYPASS_PADDR - -/* Flash Memory: */ -# define XTBOARD_FLASH_PADDR (XSHAL_IOBLOCK_BYPASS_PADDR+XTBOARD_FLASH_IO_OFS) - -/* FPGA registers: */ -# define XTBOARD_FPGAREGS_PADDR (XSHAL_IOBLOCK_BYPASS_PADDR+0x0D020000) - -/* Ethernet controller/transceiver SONIC SN83934: */ -# define ETHERNET_PADDR (XSHAL_IOBLOCK_BYPASS_PADDR+0x0D030000) - - -/* UART National-Semi PC16550D: */ -# define UART16550_PADDR (XSHAL_IOBLOCK_BYPASS_PADDR+0x0D050000) - -/* I2S transmitter */ -# define AUDIO_I2S_OUT_PADDR (XSHAL_IOBLOCK_BYPASS_PADDR+0x0D080000) - -/* I2S receiver */ -# define AUDIO_I2S_IN_PADDR (XSHAL_IOBLOCK_BYPASS_PADDR+0x0D088000) - -/* I2C master */ -# define I2C_PADDR (XSHAL_IOBLOCK_BYPASS_PADDR+0x0D090000) - -/* SPI controller */ -# define SPI_PADDR (XSHAL_IOBLOCK_BYPASS_PADDR+0x0D0A0000) - -/* Display controller Sunplus SPLC780D, 4bit mode, - * LCD Display MYTech MOC-16216B-B: */ -# define SPLC780D_4BIT_PADDR (XSHAL_IOBLOCK_BYPASS_PADDR+0x0D0C0000) - -/* USB Controller */ -# define USB_PADDR (XSHAL_IOBLOCK_BYPASS_PADDR+0x0D0D0000) - -/* Ethernet buffer: */ -# define ETHERNET_BUFFER_PADDR (XSHAL_IOBLOCK_BYPASS_PADDR+0x0D800000) - -#endif /* XSHAL_IOBLOCK_BYPASS_PADDR */ - -/* These devices might be accessed cached: */ -#ifdef XSHAL_IOBLOCK_CACHED_PADDR -# define XTBOARD_FLASH_CACHED_PADDR (XSHAL_IOBLOCK_CACHED_PADDR+XTBOARD_FLASH_IO_OFS) -# define ETHERNET_BUFFER_CACHED_PADDR (XSHAL_IOBLOCK_CACHED_PADDR+0x0D800000) -#endif /* XSHAL_IOBLOCK_CACHED_PADDR */ - - -/*** Same thing over again, this time with virtual addresses: ***/ - -#ifdef XSHAL_IOBLOCK_BYPASS_VADDR - -/* Flash Memory: */ -# define XTBOARD_FLASH_VADDR (XSHAL_IOBLOCK_BYPASS_VADDR+XTBOARD_FLASH_IO_OFS) - -/* FPGA registers: */ -# define XTBOARD_FPGAREGS_VADDR (XSHAL_IOBLOCK_BYPASS_VADDR+0x0D020000) - -/* Ethernet controller/transceiver SONIC SN83934: */ -# define ETHERNET_VADDR (XSHAL_IOBLOCK_BYPASS_VADDR+0x0D030000) - - -/* UART National-Semi PC16550D: */ -# define UART16550_VADDR (XSHAL_IOBLOCK_BYPASS_VADDR+0x0D050000) - -/* I2S transmitter */ -# define AUDIO_I2S_OUT_VADDR (XSHAL_IOBLOCK_BYPASS_VADDR+0x0D080000) - -/* I2S receiver */ -# define AUDIO_I2S_IN_VADDR (XSHAL_IOBLOCK_BYPASS_VADDR+0x0D088000) - -/* I2C master */ -# define I2C_VADDR (XSHAL_IOBLOCK_BYPASS_VADDR+0x0D090000) - -/* SPI controller */ -# define SPI_VADDR (XSHAL_IOBLOCK_BYPASS_VADDR+0x0D0A0000) - -/* Display controller Sunplus SPLC780D, 4bit mode, - * LCD Display MYTech MOC-16216B-B: */ -# define SPLC780D_4BIT_VADDR (XSHAL_IOBLOCK_BYPASS_VADDR+0x0D0C0000) - -/* USB Controller */ -# define USB_VADDR (XSHAL_IOBLOCK_BYPASS_VADDR+0x0D0D0000) - -/* Ethernet buffer: */ -# define ETHERNET_BUFFER_VADDR (XSHAL_IOBLOCK_BYPASS_VADDR+0x0D800000) - -#endif /* XSHAL_IOBLOCK_BYPASS_VADDR */ - -/* These devices might be accessed cached: */ -#ifdef XSHAL_IOBLOCK_CACHED_VADDR -# define XTBOARD_FLASH_CACHED_VADDR (XSHAL_IOBLOCK_CACHED_VADDR+XTBOARD_FLASH_IO_OFS) -# define ETHERNET_BUFFER_CACHED_VADDR (XSHAL_IOBLOCK_CACHED_VADDR+0x0D800000) -#endif /* XSHAL_IOBLOCK_CACHED_VADDR */ - - -/* System ROM: */ -#define XTBOARD_ROM_SIZE XSHAL_ROM_SIZE -#ifdef XSHAL_ROM_VADDR -#define XTBOARD_ROM_VADDR XSHAL_ROM_VADDR -#endif -#ifdef XSHAL_ROM_PADDR -#define XTBOARD_ROM_PADDR XSHAL_ROM_PADDR -#endif - -/* System RAM: */ -#define XTBOARD_RAM_SIZE XSHAL_RAM_SIZE -#ifdef XSHAL_RAM_VADDR -#define XTBOARD_RAM_VADDR XSHAL_RAM_VADDR -#endif -#ifdef XSHAL_RAM_PADDR -#define XTBOARD_RAM_PADDR XSHAL_RAM_PADDR -#endif -#define XTBOARD_RAM_BYPASS_VADDR XSHAL_RAM_BYPASS_VADDR -#define XTBOARD_RAM_BYPASS_PADDR XSHAL_RAM_BYPASS_PADDR - - - -/* - * Things that depend on device addresses. - */ - - -#define XTBOARD_CACHEATTR_WRITEBACK XSHAL_XT2000_CACHEATTR_WRITEBACK -#define XTBOARD_CACHEATTR_WRITEALLOC XSHAL_XT2000_CACHEATTR_WRITEALLOC -#define XTBOARD_CACHEATTR_WRITETHRU XSHAL_XT2000_CACHEATTR_WRITETHRU -#define XTBOARD_CACHEATTR_BYPASS XSHAL_XT2000_CACHEATTR_BYPASS -#define XTBOARD_CACHEATTR_DEFAULT XSHAL_XT2000_CACHEATTR_DEFAULT - -#define XTBOARD_BUSINT_PIPE_REGIONS XSHAL_XT2000_PIPE_REGIONS -#define XTBOARD_BUSINT_SDRAM_REGIONS XSHAL_XT2000_SDRAM_REGIONS - - -/* - * FPGA registers. - * All these registers are normally accessed using 32-bit loads/stores. - */ - -/* Register offsets: */ -#define XTBOARD_DATECD_OFS 0x00 /* date code (read-only) */ -#define XTBOARD_CLKFRQ_OFS 0x04 /* clock frequency Hz (read-only) */ -#define XTBOARD_SYSLED_OFS 0x08 /* LEDs */ -#define XTBOARD_DIPSW_OFS 0x0C /* DIP switch bits (read-only) */ -#define XTBOARD_SWRST_OFS 0x10 /* software reset */ - -/* Physical register addresses: */ -#ifdef XTBOARD_FPGAREGS_PADDR -#define XTBOARD_DATECD_PADDR (XTBOARD_FPGAREGS_PADDR+XTBOARD_DATECD_OFS) -#define XTBOARD_CLKFRQ_PADDR (XTBOARD_FPGAREGS_PADDR+XTBOARD_CLKFRQ_OFS) -#define XTBOARD_SYSLED_PADDR (XTBOARD_FPGAREGS_PADDR+XTBOARD_SYSLED_OFS) -#define XTBOARD_DIPSW_PADDR (XTBOARD_FPGAREGS_PADDR+XTBOARD_DIPSW_OFS) -#define XTBOARD_SWRST_PADDR (XTBOARD_FPGAREGS_PADDR+XTBOARD_SWRST_OFS) -#endif - -/* Virtual register addresses: */ -#ifdef XTBOARD_FPGAREGS_VADDR -#define XTBOARD_DATECD_VADDR (XTBOARD_FPGAREGS_VADDR+XTBOARD_DATECD_OFS) -#define XTBOARD_CLKFRQ_VADDR (XTBOARD_FPGAREGS_VADDR+XTBOARD_CLKFRQ_OFS) -#define XTBOARD_SYSLED_VADDR (XTBOARD_FPGAREGS_VADDR+XTBOARD_SYSLED_OFS) -#define XTBOARD_DIPSW_VADDR (XTBOARD_FPGAREGS_VADDR+XTBOARD_DIPSW_OFS) -#define XTBOARD_SWRST_VADDR (XTBOARD_FPGAREGS_VADDR+XTBOARD_SWRST_OFS) -/* Register access (for C code): */ -#define XTBOARD_DATECD_REG (*(volatile unsigned*) XTBOARD_DATECD_VADDR) -#define XTBOARD_CLKFRQ_REG (*(volatile unsigned*) XTBOARD_CLKFRQ_VADDR) -#define XTBOARD_SYSLED_REG (*(volatile unsigned*) XTBOARD_SYSLED_VADDR) -#define XTBOARD_DIPSW_REG (*(volatile unsigned*) XTBOARD_DIPSW_VADDR) -#define XTBOARD_SWRST_REG (*(volatile unsigned*) XTBOARD_SWRST_VADDR) -#endif - -/* DATECD (date code; when core was built) bit fields: */ -/* BCD-coded month (01..12): */ -#define XTBOARD_DATECD_MONTH_SHIFT 24 -#define XTBOARD_DATECD_MONTH_BITS 8 -#define XTBOARD_DATECD_MONTH_MASK 0xFF000000 -/* BCD-coded day (01..31): */ -#define XTBOARD_DATECD_DAY_SHIFT 16 -#define XTBOARD_DATECD_DAY_BITS 8 -#define XTBOARD_DATECD_DAY_MASK 0x00FF0000 -/* BCD-coded year (2001..9999): */ -#define XTBOARD_DATECD_YEAR_SHIFT 0 -#define XTBOARD_DATECD_YEAR_BITS 16 -#define XTBOARD_DATECD_YEAR_MASK 0x0000FFFF - -/* SYSLED (system LED) bit fields: */ - -/* LED control bits (off=0, on=1): */ -#define XTBOARD_SYSLED_USER_SHIFT 0 -#define XTBOARD_SYSLED_USER_BITS 2 -#define XTBOARD_SYSLED_USER_MASK 0x00000003 - -/* DIP Switch SW? (left=sw1=lsb=bit0, right=sw4=msb=bit3; off=0, on=1): */ -/* DIP switch bit fields (bit2/sw3 is reserved and presently unused): */ -#if XTBOARD_IS_KC705 -#define XTBOARD_DIPSW_USER_SHIFT 0 -#define XTBOARD_DIPSW_USER_BITS 2 -#define XTBOARD_DIPSW_USER_MASK 0x00000003 -#define XTBOARD_DIPSW_BOOT_SHIFT 3 -#define XTBOARD_DIPSW_BOOT_BITS 1 -#define XTBOARD_DIPSW_BOOT_MASK 0x00000008 -#else /* ML605: */ -#define XTBOARD_DIPSW_USER_SHIFT 0 -#define XTBOARD_DIPSW_USER_BITS 6 -#define XTBOARD_DIPSW_USER_MASK 0x0000003F -#define XTBOARD_DIPSW_BOOT_SHIFT 7 -#define XTBOARD_DIPSW_BOOT_BITS 1 -#define XTBOARD_DIPSW_BOOT_MASK 0x00000080 -#endif /*ML605*/ -#define XTBOARD_DIPSW_BOOT_RAM (0< - diff --git a/components/esp32/include/xtensa/xtutil.h b/components/esp32/include/xtensa/xtutil.h deleted file mode 100644 index fb05c37057..0000000000 --- a/components/esp32/include/xtensa/xtutil.h +++ /dev/null @@ -1,61 +0,0 @@ - -/* $Id$ */ -/*******************************************************************************/ -/* Copyright (c) 2001-2013 by Tensilica Inc. ALL RIGHTS RESERVED. */ -/* These coded instructions, statements, and computer programs are the */ -/* copyrighted works and confidential proprietary information of Tensilica Inc.*/ -/* They may not be modified, copied, reproduced, distributed, or disclosed to */ -/* third parties in any manner, medium, or form, in whole or in part, without */ -/* the prior written consent of Tensilica Inc. */ -/*******************************************************************************/ - -#ifndef XTUTIL_H -#define XTUTIL_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include - -extern int xt_putchar(int c); -extern int xt_puts(const char * s); -extern void xt_putn(unsigned n); -extern int xt_atoi(const char * s); -extern int xt_printf(const char *fmt, ...); -extern int xt_sprintf(char * buf, const char * fmt, ...); - -typedef int xt_output_fn(int *, int, const void *, int); -extern xt_output_fn * xt_set_output_fn(xt_output_fn * fn); - -#ifdef XTUTIL_LIB - -// Only defined if building library - -typedef void (xt_outbuf_fn)(void *, char *, int); - -extern int xt_vprintf(xt_outbuf_fn * out, void * outarg, const char * fmt, va_list ap); - -#else - -// Only defined if building application and overriding - -#ifndef XTUTIL_NO_OVERRIDE - -#define putchar xt_putchar -#define puts xt_puts -#define putn xt_putn -#define atoi xt_atoi -#define printf xt_printf -#define sprintf xt_sprintf - -#endif // XTUTIL_NO_OVERRIDE - -#endif // XTUTIL_LIB - -#ifdef __cplusplus -} -#endif - -#endif // XTUTIL_H - diff --git a/components/esp32/ld/esp32.common.ld b/components/esp32/ld/esp32.common.ld index 73f592ef13..dddccbb4b7 100644 --- a/components/esp32/ld/esp32.common.ld +++ b/components/esp32/ld/esp32.common.ld @@ -11,7 +11,7 @@ SECTIONS . = ALIGN(4); *(.rtc.literal .rtc.text) *rtc_wake_stub*.*(.literal .text .literal.* .text.*) - } >rtc_iram_seg + } > rtc_iram_seg /* RTC slow memory holds RTC wake stub data/rodata, including from any source file @@ -35,6 +35,20 @@ SECTIONS _rtc_bss_end = ABSOLUTE(.); } > rtc_slow_seg + /* This section holds data that should not be initialized at power up + and will be retained during deep sleep. The section located in + RTC SLOW Memory area. User data marked with RTC_NOINIT_ATTR will be placed + into this section. See the file "esp_attr.h" for more information. + */ + .rtc_noinit (NOLOAD): + { + . = ALIGN(4); + _rtc_noinit_start = ABSOLUTE(.); + *(.rtc_noinit .rtc_noinit.*) + . = ALIGN(4) ; + _rtc_noinit_end = ABSOLUTE(.); + } > rtc_slow_seg + /* Send .iram0 code to iram */ .iram0.vectors : { @@ -98,7 +112,7 @@ SECTIONS INCLUDE esp32.spiram.rom-functions-iram.ld _iram_text_end = ABSOLUTE(.); } > iram0_0_seg - + .dram0.data : { _data_start = ABSOLUTE(.); @@ -124,7 +138,21 @@ SECTIONS INCLUDE esp32.spiram.rom-functions-dram.ld _data_end = ABSOLUTE(.); . = ALIGN(4); - } >dram0_0_seg + } > dram0_0_seg + + /*This section holds data that should not be initialized at power up. + The section located in Internal SRAM memory region. The macro _NOINIT + can be used as attribute to place data into this section. + See the esp_attr.h file for more information. + */ + .noinit (NOLOAD): + { + . = ALIGN(4); + _noinit_start = ABSOLUTE(.); + *(.noinit .noinit.*) + . = ALIGN(4) ; + _noinit_end = ABSOLUTE(.); + } > dram0_0_seg /* Shared RAM */ .dram0.bss (NOLOAD) : @@ -147,8 +175,9 @@ SECTIONS *(COMMON) . = ALIGN (8); _bss_end = ABSOLUTE(.); + /* The heap starts right after end of this section */ _heap_start = ABSOLUTE(.); - } >dram0_0_seg + } > dram0_0_seg .flash.rodata : { diff --git a/components/esp32/ld/esp32.rom.ld b/components/esp32/ld/esp32.rom.ld index 8c458ff146..8f3aed63be 100644 --- a/components/esp32/ld/esp32.rom.ld +++ b/components/esp32/ld/esp32.rom.ld @@ -4,32 +4,22 @@ Generated for ROM with MD5sum: ab8282ae908fe9e7a63fb2a4ac2df013 ../../rom_image/prorom.elf */ PROVIDE ( abort = 0x4000bba4 ); -PROVIDE ( __absvdi2 = 0x4006387c ); -PROVIDE ( __absvsi2 = 0x40063868 ); PROVIDE ( Add2SelfBigHex256 = 0x40015b7c ); PROVIDE ( AddBigHex256 = 0x40015b28 ); PROVIDE ( AddBigHexModP256 = 0x40015c98 ); -PROVIDE ( __adddf3 = 0x40002590 ); PROVIDE ( AddP256 = 0x40015c74 ); PROVIDE ( AddPdiv2_256 = 0x40015ce0 ); -PROVIDE ( __addsf3 = 0x400020e8 ); -PROVIDE ( __addvdi3 = 0x40002cbc ); -PROVIDE ( __addvsi3 = 0x40002c98 ); PROVIDE ( aes_128_cbc_decrypt = 0x4005cc7c ); PROVIDE ( aes_128_cbc_encrypt = 0x4005cc18 ); PROVIDE ( aes_unwrap = 0x4005ccf0 ); PROVIDE ( app_gpio_arg = 0x3ffe003c ); PROVIDE ( app_gpio_handler = 0x3ffe0040 ); -PROVIDE ( __ashldi3 = 0x4000c818 ); -PROVIDE ( __ashrdi3 = 0x4000c830 ); PROVIDE ( base64_decode = 0x4005ced8 ); PROVIDE ( base64_encode = 0x4005cdbc ); PROVIDE ( BasePoint_x_256 = 0x3ff97488 ); PROVIDE ( BasePoint_y_256 = 0x3ff97468 ); PROVIDE ( bigHexInversion256 = 0x400168f0 ); PROVIDE ( bigHexP256 = 0x3ff973bc ); -PROVIDE ( __bswapdi2 = 0x400649c4 ); -PROVIDE ( __bswapsi2 = 0x4006499c ); PROVIDE ( btdm_r_ble_bt_handler_tab_p_get = 0x40019b0c ); PROVIDE ( btdm_r_btdm_option_data_p_get = 0x40010004 ); PROVIDE ( btdm_r_btdm_rom_version_get = 0x40010078 ); @@ -53,11 +43,6 @@ PROVIDE ( calloc = 0x4000bee4 ); PROVIDE ( _calloc_r = 0x4000bbf8 ); PROVIDE ( __clear_cache = 0x40063860 ); PROVIDE ( _close_r = 0x4000bd3c ); -PROVIDE ( __clrsbdi2 = 0x40064a38 ); -PROVIDE ( __clrsbsi2 = 0x40064a20 ); -PROVIDE ( __clzdi2 = 0x4000ca50 ); -PROVIDE ( __clzsi2 = 0x4000c7e8 ); -PROVIDE ( __cmpdi2 = 0x40063820 ); PROVIDE ( co_default_bdaddr = 0x3ffae704 ); PROVIDE ( co_null_bdaddr = 0x3ffb80e0 ); PROVIDE ( co_sca2ppm = 0x3ff971e8 ); @@ -69,8 +54,6 @@ PROVIDE ( crc8_be = 0x4005d114 ); PROVIDE ( crc8_le = 0x4005d0e0 ); PROVIDE ( _ctype_ = 0x3ff96354 ); PROVIDE ( __ctype_ptr__ = 0x3ff96350 ); -PROVIDE ( __ctzdi2 = 0x4000ca64 ); -PROVIDE ( __ctzsi2 = 0x4000c7f0 ); PROVIDE ( _data_end_rom = 0x4000d5c8 ); PROVIDE ( _data_end_btdm_rom = 0x4000d4f8 ); PROVIDE ( _data_start_rom = 0x4000d4f8 ); @@ -103,49 +86,21 @@ PROVIDE ( dh_group2_generator = 0x3ff9ada2 ); PROVIDE ( dh_group2_prime = 0x3ff9ad22 ); PROVIDE ( dh_group5_generator = 0x3ff9ad21 ); PROVIDE ( dh_group5_prime = 0x3ff9ac61 ); -PROVIDE ( __divdc3 = 0x40064460 ); -PROVIDE ( __divdf3 = 0x40002954 ); -PROVIDE ( __divdi3 = 0x4000ca84 ); -PROVIDE ( __divsc3 = 0x40064200 ); -PROVIDE ( __divsf3 = 0x4000234c ); -PROVIDE ( __divsi3 = 0x4000c7b8 ); PROVIDE ( g_rom_spiflash_dummy_len_plus = 0x3ffae290 ); PROVIDE ( ecc_env = 0x3ffb8d60 ); PROVIDE ( ecc_Jacobian_InfinityPoint256 = 0x3ff972e8 ); PROVIDE ( em_buf_env = 0x3ffb8d74 ); PROVIDE ( environ = 0x3ffae0b4 ); -PROVIDE ( __eqdf2 = 0x400636a8 ); -PROVIDE ( __eqsf2 = 0x40063374 ); PROVIDE ( esp_crc8 = 0x4005d144 ); PROVIDE ( _etext = 0x4000d66c ); PROVIDE ( ets_readySet_ = 0x3ffe01f0 ); PROVIDE ( ets_startup_callback = 0x3ffe0404 ); PROVIDE ( exc_cause_table = 0x3ff991d0 ); PROVIDE ( _exit_r = 0x4000bd28 ); -PROVIDE ( __extendsfdf2 = 0x40002c34 ); -PROVIDE ( __ffsdi2 = 0x4000ca2c ); -PROVIDE ( __ffssi2 = 0x4000c804 ); -PROVIDE ( __fixdfdi = 0x40002ac4 ); -PROVIDE ( __fixdfsi = 0x40002a78 ); -PROVIDE ( __fixsfdi = 0x4000244c ); -PROVIDE ( __fixsfsi = 0x4000240c ); -PROVIDE ( __fixunsdfsi = 0x40002b30 ); -PROVIDE ( __fixunssfdi = 0x40002504 ); -PROVIDE ( __fixunssfsi = 0x400024ac ); -PROVIDE ( __floatdidf = 0x4000c988 ); -PROVIDE ( __floatdisf = 0x4000c8c0 ); -PROVIDE ( __floatsidf = 0x4000c944 ); -PROVIDE ( __floatsisf = 0x4000c870 ); -PROVIDE ( __floatundidf = 0x4000c978 ); -PROVIDE ( __floatundisf = 0x4000c8b0 ); -PROVIDE ( __floatunsidf = 0x4000c938 ); -PROVIDE ( __floatunsisf = 0x4000c864 ); PROVIDE ( free = 0x4000beb8 ); PROVIDE ( _free_r = 0x4000bbcc ); PROVIDE ( _fstat_r = 0x4000bccc ); PROVIDE ( __gcc_bcmp = 0x40064a70 ); -PROVIDE ( __gedf2 = 0x40063768 ); -PROVIDE ( __gesf2 = 0x4006340c ); PROVIDE ( _getpid_r = 0x4000bcfc ); PROVIDE ( __getreent = 0x4000be8c ); PROVIDE ( _gettimeofday_r = 0x4000bc58 ); @@ -155,8 +110,6 @@ PROVIDE ( GF_Point_Jacobian_To_Affine256 = 0x40016b0c ); PROVIDE ( _global_impure_ptr = 0x3ffae0b0 ); PROVIDE ( g_phyFuns_instance = 0x3ffae0c4 ); PROVIDE ( g_rom_flashchip = 0x3ffae270 ); -PROVIDE ( __gtdf2 = 0x400636dc ); -PROVIDE ( __gtsf2 = 0x400633a0 ); PROVIDE ( gTxMsg = 0x3ffe0050 ); PROVIDE ( hci_cmd_desc_root_tab = 0x3ff976d4 ); PROVIDE ( hci_cmd_desc_tab_ctrl_bb = 0x3ff97b70 ); @@ -202,8 +155,6 @@ PROVIDE ( ld_env = 0x3ffb9510 ); PROVIDE ( ld_pcm_settings_dft = 0x3ff98a0c ); PROVIDE ( ld_sched_params = 0x3ffb96c0 ); PROVIDE ( ld_sync_train_channels = 0x3ff98a3c ); -PROVIDE ( __ledf2 = 0x40063704 ); -PROVIDE ( __lesf2 = 0x400633c0 ); PROVIDE ( _link_r = 0x4000bc9c ); PROVIDE ( llc_default_handler = 0x3ff98b3c ); PROVIDE ( llc_default_state_tab_p_get = 0x40046058 ); @@ -256,9 +207,6 @@ PROVIDE ( _lock_release_recursive = 0x4000be78 ); PROVIDE ( _lock_try_acquire = 0x4000be3c ); PROVIDE ( _lock_try_acquire_recursive = 0x4000be50 ); PROVIDE ( _lseek_r = 0x4000bd8c ); -PROVIDE ( __lshrdi3 = 0x4000c84c ); -PROVIDE ( __ltdf2 = 0x40063790 ); -PROVIDE ( __ltsf2 = 0x4006342c ); PROVIDE ( malloc = 0x4000bea0 ); PROVIDE ( _malloc_r = 0x4000bbb4 ); PROVIDE ( maxSecretKey_256 = 0x3ff97448 ); @@ -268,43 +216,19 @@ PROVIDE ( MD5Init = 0x4005da7c ); PROVIDE ( MD5Update = 0x4005da9c ); PROVIDE ( md5_vector = 0x4005db80 ); PROVIDE ( mmu_init = 0x400095a4 ); -PROVIDE ( __moddi3 = 0x4000cd4c ); -PROVIDE ( __modsi3 = 0x4000c7c0 ); PROVIDE ( __month_lengths = 0x3ff9609c ); -PROVIDE ( __muldc3 = 0x40063bf4 ); -PROVIDE ( __muldf3 = 0x4006358c ); -PROVIDE ( __muldi3 = 0x4000c9fc ); -PROVIDE ( __mulsc3 = 0x40063934 ); -PROVIDE ( __mulsf3 = 0x400632c8 ); -PROVIDE ( __mulsi3 = 0x4000c7b0 ); PROVIDE ( MultiplyBigHexByUint32_256 = 0x40016214 ); PROVIDE ( MultiplyBigHexModP256 = 0x400160b8 ); PROVIDE ( MultiplyByU32ModP256 = 0x40015fdc ); PROVIDE ( multofup = 0x4000ab8c ); -PROVIDE ( __mulvdi3 = 0x40002d78 ); -PROVIDE ( __mulvsi3 = 0x40002d60 ); PROVIDE ( mz_adler32 = 0x4005edbc ); PROVIDE ( mz_crc32 = 0x4005ee88 ); PROVIDE ( mz_free = 0x4005eed4 ); -PROVIDE ( __nedf2 = 0x400636a8 ); -PROVIDE ( __negdf2 = 0x400634a0 ); -PROVIDE ( __negdi2 = 0x4000ca14 ); -PROVIDE ( __negsf2 = 0x400020c0 ); -PROVIDE ( __negvdi2 = 0x40002e98 ); -PROVIDE ( __negvsi2 = 0x40002e78 ); -PROVIDE ( __nesf2 = 0x40063374 ); PROVIDE ( notEqual256 = 0x40015b04 ); -PROVIDE ( __nsau_data = 0x3ff96544 ); PROVIDE ( one_bits = 0x3ff971f8 ); PROVIDE ( _open_r = 0x4000bd54 ); -PROVIDE ( __paritysi2 = 0x40002f3c ); PROVIDE ( pbkdf2_sha1 = 0x40060ba4 ); PROVIDE ( phy_get_romfuncs = 0x40004100 ); -PROVIDE ( __popcountdi2 = 0x40002ef8 ); -PROVIDE ( __popcountsi2 = 0x40002ed0 ); -PROVIDE ( __popcount_tab = 0x3ff96544 ); -PROVIDE ( __powidf2 = 0x400638d4 ); -PROVIDE ( __powisf2 = 0x4006389c ); PROVIDE ( _Pri_4_HandlerAddress = 0x3ffe0648 ); PROVIDE ( _Pri_5_HandlerAddress = 0x3ffe064c ); PROVIDE ( r_btdm_option_data = 0x3ffae6e0 ); @@ -762,7 +686,14 @@ PROVIDE ( lmp_io_cap_req_handler = 0x4002c7a4 ); PROVIDE ( ld_acl_tx_packet_type_select = 0x4002fb40 ); PROVIDE ( ld_acl_sched = 0x40033268 ); PROVIDE ( ld_acl_sniff_sched = 0x4003340c ); +PROVIDE ( ld_acl_rx = 0x4003274c ); +PROVIDE ( ld_acl_tx = 0x4002ffdc ); +PROVIDE ( ld_acl_rx_sync = 0x4002fbec ); +PROVIDE ( ld_acl_rx_sync2 = 0x4002fd8c ); +PROVIDE ( ld_acl_rx_no_sync = 0x4002fe78 ); +PROVIDE ( ld_sco_modify = 0x40031778 ); PROVIDE ( lm_cmd_cmp_send = 0x40051838 ); +PROVIDE ( ld_sco_frm_cbk = 0x400349dc ); PROVIDE ( r_ld_acl_active_hop_types_get = 0x40036e10 ); PROVIDE ( r_ld_acl_afh_confirm = 0x40036d40 ); PROVIDE ( r_ld_acl_afh_prepare = 0x40036c84 ); @@ -1418,15 +1349,11 @@ PROVIDE ( _start = 0x40000704 ); PROVIDE ( start_tb_console = 0x4005a980 ); PROVIDE ( _stat_r = 0x4000bcb4 ); PROVIDE ( _stext = 0x40000560 ); -PROVIDE ( __subdf3 = 0x400026e4 ); -PROVIDE ( __subsf3 = 0x400021d0 ); PROVIDE ( SubtractBigHex256 = 0x40015bcc ); PROVIDE ( SubtractBigHexMod256 = 0x40015e8c ); PROVIDE ( SubtractBigHexUint32_256 = 0x40015f8c ); PROVIDE ( SubtractFromSelfBigHex256 = 0x40015c20 ); PROVIDE ( SubtractFromSelfBigHexSign256 = 0x40015dc8 ); -PROVIDE ( __subvdi3 = 0x40002d20 ); -PROVIDE ( __subvsi3 = 0x40002cf8 ); PROVIDE ( sw_to_hw = 0x3ffb8d40 ); PROVIDE ( syscall_table_ptr_app = 0x3ffae020 ); PROVIDE ( syscall_table_ptr_pro = 0x3ffae024 ); @@ -1444,20 +1371,9 @@ PROVIDE ( _timezone = 0x3ffae0a0 ); PROVIDE ( tinfl_decompress = 0x4005ef30 ); PROVIDE ( tinfl_decompress_mem_to_callback = 0x40060090 ); PROVIDE ( tinfl_decompress_mem_to_mem = 0x40060050 ); -PROVIDE ( __truncdfsf2 = 0x40002b90 ); PROVIDE ( _tzname = 0x3ffae030 ); PROVIDE ( UartDev = 0x3ffe019c ); -PROVIDE ( __ucmpdi2 = 0x40063840 ); -PROVIDE ( __udivdi3 = 0x4000cff8 ); -PROVIDE ( __udivmoddi4 = 0x40064ab0 ); -PROVIDE ( __udivsi3 = 0x4000c7c8 ); -PROVIDE ( __udiv_w_sdiv = 0x40064aa8 ); -PROVIDE ( __umoddi3 = 0x4000d280 ); -PROVIDE ( __umodsi3 = 0x4000c7d0 ); -PROVIDE ( __umulsidi3 = 0x4000c7d8 ); PROVIDE ( _unlink_r = 0x4000bc84 ); -PROVIDE ( __unorddf2 = 0x400637f4 ); -PROVIDE ( __unordsf2 = 0x40063478 ); PROVIDE ( user_code_start = 0x3ffe0400 ); PROVIDE ( veryBigHexP256 = 0x3ff9736c ); PROVIDE ( __wctomb = 0x3ff96540 ); diff --git a/components/esp32/ld/esp32.rom.libgcc.ld b/components/esp32/ld/esp32.rom.libgcc.ld new file mode 100644 index 0000000000..51448b3327 --- /dev/null +++ b/components/esp32/ld/esp32.rom.libgcc.ld @@ -0,0 +1,91 @@ +__absvdi2 = 0x4006387c; +__absvsi2 = 0x40063868; +__adddf3 = 0x40002590; +__addsf3 = 0x400020e8; +__addvdi3 = 0x40002cbc; +__addvsi3 = 0x40002c98; +__ashldi3 = 0x4000c818; +__ashrdi3 = 0x4000c830; +__bswapdi2 = 0x40064b08; +__bswapsi2 = 0x40064ae0; +__clrsbdi2 = 0x40064b7c; +__clrsbsi2 = 0x40064b64; +__clzdi2 = 0x4000ca50; +__clzsi2 = 0x4000c7e8; +__cmpdi2 = 0x40063820; +__ctzdi2 = 0x4000ca64; +__ctzsi2 = 0x4000c7f0; +__divdc3 = 0x400645a4; +__divdf3 = 0x40002954; +__divdi3 = 0x4000ca84; +__divsc3 = 0x4006429c; +__divsf3 = 0x4000234c; +__divsi3 = 0x4000c7b8; +__eqdf2 = 0x400636a8; +__eqsf2 = 0x40063374; +__extendsfdf2 = 0x40002c34; +__ffsdi2 = 0x4000ca2c; +__ffssi2 = 0x4000c804; +__fixdfdi = 0x40002ac4; +__fixdfsi = 0x40002a78; +__fixsfdi = 0x4000244c; +__fixsfsi = 0x4000240c; +__fixunsdfsi = 0x40002b30; +__fixunssfdi = 0x40002504; +__fixunssfsi = 0x400024ac; +__floatdidf = 0x4000c988; +__floatdisf = 0x4000c8c0; +__floatsidf = 0x4000c944; +__floatsisf = 0x4000c870; +__floatundidf = 0x4000c978; +__floatundisf = 0x4000c8b0; +__floatunsidf = 0x4000c938; +__floatunsisf = 0x4000c864; +__gedf2 = 0x40063768; +__gesf2 = 0x4006340c; +__gtdf2 = 0x400636dc; +__gtsf2 = 0x400633a0; +__ledf2 = 0x40063704; +__lesf2 = 0x400633c0; +__lshrdi3 = 0x4000c84c; +__ltdf2 = 0x40063790; +__ltsf2 = 0x4006342c; +__moddi3 = 0x4000cd4c; +__modsi3 = 0x4000c7c0; +__muldc3 = 0x40063c90; +__muldf3 = 0x4006358c; +__muldi3 = 0x4000c9fc; +__mulsc3 = 0x40063944; +__mulsf3 = 0x400632c8; +__mulsi3 = 0x4000c7b0; +__mulvdi3 = 0x40002d78; +__mulvsi3 = 0x40002d60; +__nedf2 = 0x400636a8; +__negdf2 = 0x400634a0; +__negdi2 = 0x4000ca14; +__negsf2 = 0x400020c0; +__negvdi2 = 0x40002e98; +__negvsi2 = 0x40002e78; +__nesf2 = 0x40063374; +__nsau_data = 0x3ff96544; +__paritysi2 = 0x40002f3c; +__popcount_tab = 0x3ff96544; +__popcountdi2 = 0x40002ef8; +__popcountsi2 = 0x40002ed0; +__powidf2 = 0x400638e4; +__powisf2 = 0x4006389c; +__subdf3 = 0x400026e4; +__subsf3 = 0x400021d0; +__subvdi3 = 0x40002d20; +__subvsi3 = 0x40002cf8; +__truncdfsf2 = 0x40002b90; +__ucmpdi2 = 0x40063840; +__udiv_w_sdiv = 0x40064bec; +__udivdi3 = 0x4000cff8; +__udivmoddi4 = 0x40064bf4; +__udivsi3 = 0x4000c7c8; +__umoddi3 = 0x4000d280; +__umodsi3 = 0x4000c7d0; +__umulsidi3 = 0x4000c7d8; +__unorddf2 = 0x400637f4; +__unordsf2 = 0x40063478; diff --git a/components/esp32/lib b/components/esp32/lib index f56b7bd412..acade41cab 160000 --- a/components/esp32/lib +++ b/components/esp32/lib @@ -1 +1 @@ -Subproject commit f56b7bd4127aa01dbd50eb8ac3c637690bd98f84 +Subproject commit acade41cabe41d0a5c0c1d3744a41147e8ecb4a1 diff --git a/components/esp32/panic.c b/components/esp32/panic.c index 83bc657f1a..8edb70b233 100644 --- a/components/esp32/panic.c +++ b/components/esp32/panic.c @@ -40,6 +40,7 @@ #include "esp_cache_err_int.h" #include "esp_app_trace.h" #include "esp_system.h" +#include "sdkconfig.h" #if CONFIG_SYSVIEW_ENABLE #include "SEGGER_RTT.h" #endif @@ -312,7 +313,7 @@ void xt_unhandled_exception(XtExcFrame *frame) } else { panicPutStr("Unknown"); } - panicPutStr(")\r\n"); + panicPutStr(")"); if (esp_cpu_in_ocd_debug_mode()) { panicPutStr(" at pc="); panicPutHex(frame->pc); @@ -653,7 +654,11 @@ void esp_clear_watchpoint(int no) void _esp_error_check_failed(esp_err_t rc, const char *file, int line, const char *function, const char *expression) { - ets_printf("ESP_ERROR_CHECK failed: esp_err_t 0x%x at 0x%08x\n", rc, (intptr_t)__builtin_return_address(0) - 3); + ets_printf("ESP_ERROR_CHECK failed: esp_err_t 0x%x", rc); +#ifdef CONFIG_ESP_ERR_TO_NAME_LOOKUP + ets_printf(" (%s)", esp_err_to_name(rc)); +#endif //CONFIG_ESP_ERR_TO_NAME_LOOKUP + ets_printf(" at 0x%08x\n", (intptr_t)__builtin_return_address(0) - 3); if (spi_flash_cache_enabled()) { // strings may be in flash cache ets_printf("file: \"%s\" line %d\nfunc: %s\nexpression: %s\n", file, line, function, expression); } diff --git a/components/esp32/phy_init.c b/components/esp32/phy_init.c index 314f142683..2da98c31b0 100644 --- a/components/esp32/phy_init.c +++ b/components/esp32/phy_init.c @@ -133,6 +133,8 @@ esp_err_t esp_phy_rf_init(const esp_phy_init_data_t* init_data, esp_phy_calibrat extern esp_err_t wifi_osi_funcs_register(wifi_osi_funcs_t *osi_funcs); status = wifi_osi_funcs_register(&g_wifi_osi_funcs); if(status != ESP_OK) { + ESP_LOGE(TAG, "failed to register wifi os adapter, ret(%d)", status); + _lock_release(&s_phy_rf_init_lock); return ESP_FAIL; } coex_bt_high_prio(); @@ -491,7 +493,6 @@ static esp_err_t load_cal_data_from_nvs_handle(nvs_handle handle, ESP_LOGD(TAG, "%s: invalid length of cal_data (%d)", __func__, length); return ESP_ERR_INVALID_SIZE; } - memcpy(out_cal_data->mac, sta_mac, 6); return ESP_OK; } @@ -547,6 +548,7 @@ void esp_phy_load_cal_and_init(phy_rf_module_t module) #ifdef CONFIG_ESP32_PHY_CALIBRATION_AND_DATA_STORAGE esp_phy_calibration_mode_t calibration_mode = PHY_RF_CAL_PARTIAL; + uint8_t sta_mac[6]; if (rtc_get_reset_reason(0) == DEEPSLEEP_RESET) { calibration_mode = PHY_RF_CAL_NONE; } @@ -556,6 +558,8 @@ void esp_phy_load_cal_and_init(phy_rf_module_t module) calibration_mode = PHY_RF_CAL_FULL; } + esp_efuse_mac_get_default(sta_mac); + memcpy(cal_data->mac, sta_mac, 6); esp_phy_rf_init(init_data, calibration_mode, cal_data, module); if (calibration_mode != PHY_RF_CAL_NONE && err != ESP_OK) { diff --git a/components/esp32/sleep_modes.c b/components/esp32/sleep_modes.c index 65d0f05683..f4cefb98b6 100644 --- a/components/esp32/sleep_modes.c +++ b/components/esp32/sleep_modes.c @@ -141,6 +141,13 @@ void esp_deep_sleep(uint64_t time_in_us) esp_deep_sleep_start(); } +static void IRAM_ATTR flush_uarts() +{ + for (int i = 0; i < 3; ++i) { + uart_tx_wait_idle(i); + } +} + static void IRAM_ATTR suspend_uarts() { for (int i = 0; i < 3; ++i) { @@ -160,8 +167,14 @@ static void IRAM_ATTR resume_uarts() static uint32_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags) { - // Stop UART output so that output is not lost due to APB frequency change - suspend_uarts(); + // Stop UART output so that output is not lost due to APB frequency change. + // For light sleep, suspend UART output — it will resume after wakeup. + // For deep sleep, wait for the contents of UART FIFO to be sent. + if (pd_flags & RTC_SLEEP_PD_DIG) { + flush_uarts(); + } else { + suspend_uarts(); + } // Save current frequency and switch to XTAL rtc_cpu_freq_t cpu_freq = rtc_clk_cpu_freq_get(); @@ -203,7 +216,7 @@ void IRAM_ATTR esp_deep_sleep_start() { // record current RTC time s_config.rtc_ticks_at_sleep_start = rtc_time_get(); - + esp_sync_counters_rtc_and_frc(); // Configure wake stub if (esp_get_deep_sleep_wake_stub() == NULL) { esp_set_deep_sleep_wake_stub(esp_wake_deep_sleep); @@ -428,9 +441,10 @@ touch_pad_t esp_sleep_get_touchpad_wakeup_status() if (esp_sleep_get_wakeup_cause() != ESP_SLEEP_WAKEUP_TOUCHPAD) { return TOUCH_PAD_MAX; } - uint32_t touch_mask = REG_GET_FIELD(SENS_SAR_TOUCH_CTRL2_REG, SENS_TOUCH_MEAS_EN); - assert(touch_mask != 0 && "wakeup reason is RTC_TOUCH_TRIG_EN but SENS_TOUCH_MEAS_EN is zero"); - return (touch_pad_t) (__builtin_ffs(touch_mask) - 1); + touch_pad_t pad_num; + esp_err_t ret = touch_pad_get_wakeup_status(&pad_num); + assert(ret == ESP_OK && "wakeup reason is RTC_TOUCH_TRIG_EN but SENS_TOUCH_MEAS_EN is zero"); + return pad_num; } esp_err_t esp_sleep_enable_ext0_wakeup(gpio_num_t gpio_num, int level) @@ -465,8 +479,7 @@ static void ext0_wakeup_prepare() if (desc->rtc_num == rtc_gpio_num) { REG_SET_BIT(desc->reg, desc->mux); SET_PERI_REG_BITS(desc->reg, 0x3, 0, desc->func); - REG_SET_BIT(desc->reg, desc->slpsel); - REG_SET_BIT(desc->reg, desc->slpie); + REG_SET_BIT(desc->reg, desc->ie); break; } } @@ -508,16 +521,13 @@ static void ext1_wakeup_prepare() // Route pad to RTC REG_SET_BIT(desc->reg, desc->mux); SET_PERI_REG_BITS(desc->reg, 0x3, 0, desc->func); + // set input enable in sleep mode + REG_SET_BIT(desc->reg, desc->ie); // Pad configuration depends on RTC_PERIPH state in sleep mode - if (s_config.pd_options[ESP_PD_DOMAIN_RTC_PERIPH] == ESP_PD_OPTION_ON) { - // set input enable in sleep mode - REG_SET_BIT(desc->reg, desc->slpie); - // allow sleep status signal to control IE/SLPIE mux - REG_SET_BIT(desc->reg, desc->slpsel); - } else { - // RTC_PERIPH will be disabled, so need to enable input and - // lock pad configuration. Pullups/pulldowns also need to be disabled. - REG_SET_BIT(desc->reg, desc->ie); + if (s_config.pd_options[ESP_PD_DOMAIN_RTC_PERIPH] != ESP_PD_OPTION_ON) { + // RTC_PERIPH will be powered down, so RTC_IO_ registers will + // loose their state. Lock pad configuration. + // Pullups/pulldowns also need to be disabled. REG_CLR_BIT(desc->reg, desc->pulldown); REG_CLR_BIT(desc->reg, desc->pullup); REG_SET_BIT(RTC_CNTL_HOLD_FORCE_REG, desc->hold_force); @@ -599,9 +609,9 @@ static uint32_t get_power_down_flags() // These labels are defined in the linker script: extern int _rtc_data_start, _rtc_data_end, _rtc_bss_start, _rtc_bss_end; - if (s_config.pd_options[ESP_PD_DOMAIN_RTC_SLOW_MEM] == ESP_PD_OPTION_AUTO || - &_rtc_data_end > &_rtc_data_start || - &_rtc_bss_end > &_rtc_bss_start) { + if ((s_config.pd_options[ESP_PD_DOMAIN_RTC_SLOW_MEM] == ESP_PD_OPTION_AUTO) && + (&_rtc_data_end > &_rtc_data_start || &_rtc_bss_end > &_rtc_bss_start || + (s_config.wakeup_triggers & RTC_ULP_TRIG_EN))) { s_config.pd_options[ESP_PD_DOMAIN_RTC_SLOW_MEM] = ESP_PD_OPTION_ON; } diff --git a/components/esp32/test/component.mk b/components/esp32/test/component.mk index 178dd4cf4d..592b9b9048 100644 --- a/components/esp32/test/component.mk +++ b/components/esp32/test/component.mk @@ -12,6 +12,11 @@ COMPONENT_SRCDIRS := . test_vectors WIFI_OS_ADAPTER_MD5_VAL=\"$(shell md5sum $(IDF_PATH)/components/esp32/include/esp_wifi_os_adapter.h | cut -c 1-7)\" CFLAGS+=-DWIFI_OS_ADAPTER_MD5=$(WIFI_OS_ADAPTER_MD5_VAL) +# Calculate MD5 value of header file esp_wifi_crypto_types.h +WIFI_CRYPTO_MD5_VAL=\"$(shell md5sum $(IDF_PATH)/components/esp32/include/esp_wifi_crypto_types.h | cut -c 1-7)\" +CFLAGS+=-DWIFI_CRYPTO_MD5=$(WIFI_CRYPTO_MD5_VAL) + + test_tjpgd.o: test_tjpgd_logo.h test_tjpgd_logo.h: $(COMPONENT_PATH)/logo.jpg diff --git a/components/esp32/test/test_esp32.c b/components/esp32/test/test_esp32.c index 0681660ff1..cdca805df4 100644 --- a/components/esp32/test/test_esp32.c +++ b/components/esp32/test/test_esp32.c @@ -83,8 +83,8 @@ TEST_CASE("wifi stop and deinit","[wifi]") //init nvs ESP_LOGI(TAG, EMPH_STR("nvs_flash_init")); esp_err_t r = nvs_flash_init(); - if (r == ESP_ERR_NVS_NO_FREE_PAGES) { - ESP_LOGI(TAG, EMPH_STR("no free pages, erase..")); + if (r == ESP_ERR_NVS_NO_FREE_PAGES || r == ESP_ERR_NVS_NEW_VERSION_FOUND) { + ESP_LOGI(TAG, EMPH_STR("no free pages or nvs version mismatch, erase..")); TEST_ESP_OK(nvs_flash_erase()); r = nvs_flash_init(); } diff --git a/components/esp32/test/test_esp_timer.c b/components/esp32/test/test_esp_timer.c index da8d8951cf..3b6f3b40d6 100644 --- a/components/esp32/test/test_esp_timer.c +++ b/components/esp32/test/test_esp_timer.c @@ -2,6 +2,7 @@ #include #include #include +#include #include "unity.h" #include "esp_timer.h" #include "esp_heap_caps.h" @@ -15,6 +16,20 @@ #define WITH_PROFILING 1 #endif +extern uint32_t esp_timer_impl_get_overflow_val(); +extern void esp_timer_impl_set_overflow_val(uint32_t overflow_val); + +static uint32_t s_old_overflow_val; + +static void setup_overflow() +{ + s_old_overflow_val = esp_timer_impl_get_overflow_val(); + esp_timer_impl_set_overflow_val(0x7fffff); /* overflow every ~0.1 sec */} + +static void teardown_overflow() +{ + esp_timer_impl_set_overflow_val(s_old_overflow_val); +} TEST_CASE("esp_timer orders timers correctly", "[esp_timer]") { @@ -27,6 +42,7 @@ TEST_CASE("esp_timer orders timers correctly", "[esp_timer]") const size_t num_timers = sizeof(timeouts)/sizeof(timeouts[0]); esp_timer_handle_t handles[num_timers]; char* names[num_timers]; + setup_overflow(); for (size_t i = 0; i < num_timers; ++i) { asprintf(&names[i], "timer%d", i); esp_timer_create_args_t args = { @@ -36,6 +52,7 @@ TEST_CASE("esp_timer orders timers correctly", "[esp_timer]") TEST_ESP_OK(esp_timer_create(&args, &handles[i])); TEST_ESP_OK(esp_timer_start_once(handles[i], timeouts[i] * 100)); } + teardown_overflow(); char* stream_str[1024]; FILE* stream = fmemopen(stream_str, sizeof(stream_str), "r+"); TEST_ESP_OK(esp_timer_dump(stream)); @@ -68,6 +85,42 @@ TEST_CASE("esp_timer orders timers correctly", "[esp_timer]") fclose(stream); } +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; + + uint64_t start = esp_timer_impl_get_time(); + uint64_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); +#if portNUM_PROCESSORS == 2 + xTaskCreatePinnedToCore(&set_alarm_task, "set_alarm_1", 4096, done, UNITY_FREERTOS_PRIORITY, NULL, 1); +#endif + + TEST_ASSERT(xSemaphoreTake(done, test_time_sec * 2 * 1000 / portTICK_PERIOD_MS)); +#if portNUM_PROCESSORS == 2 + TEST_ASSERT(xSemaphoreTake(done, test_time_sec * 2 * 1000 / portTICK_PERIOD_MS)); +#endif + teardown_overflow(); + vSemaphoreDelete(done); +} TEST_CASE("esp_timer produces correct delay", "[esp_timer]") { @@ -90,6 +143,7 @@ TEST_CASE("esp_timer produces correct delay", "[esp_timer]") const size_t delays_count = sizeof(delays_ms)/sizeof(delays_ms[0]); ref_clock_init(); + setup_overflow(); for (size_t i = 0; i < delays_count; ++i) { t_end = 0; int64_t t_start = ref_clock_get(); @@ -103,6 +157,7 @@ TEST_CASE("esp_timer produces correct delay", "[esp_timer]") TEST_ASSERT_INT32_WITHIN(portTICK_PERIOD_MS, delays_ms[i], ms_diff); } + teardown_overflow(); ref_clock_deinit(); TEST_ESP_OK( esp_timer_dump(stdout) ); @@ -150,6 +205,7 @@ TEST_CASE("periodic esp_timer produces correct delays", "[esp_timer]") }; TEST_ESP_OK(esp_timer_create(&create_args, &timer1)); ref_clock_init(); + setup_overflow(); args.timer = timer1; args.t_start = ref_clock_get(); args.done = xSemaphoreCreateBinary(); @@ -161,6 +217,7 @@ TEST_CASE("periodic esp_timer produces correct delays", "[esp_timer]") for (size_t i = 0; i < NUM_INTERVALS; ++i) { TEST_ASSERT_INT32_WITHIN(portTICK_PERIOD_MS, (i + 1) * delay_ms, args.intervals[i]); } + teardown_overflow(); ref_clock_deinit(); TEST_ESP_OK( esp_timer_dump(stdout) ); @@ -317,6 +374,7 @@ TEST_CASE("esp_timer for very short intervals", "[esp_timer]") esp_timer_handle_t timer1, timer2; ESP_ERROR_CHECK( esp_timer_create(&timer_args, &timer1) ); ESP_ERROR_CHECK( esp_timer_create(&timer_args, &timer2) ); + setup_overflow(); const int timeout_ms = 10; for (int timeout_delta_us = -150; timeout_delta_us < 150; timeout_delta_us++) { printf("delta=%d", timeout_delta_us); @@ -329,6 +387,7 @@ TEST_CASE("esp_timer for very short intervals", "[esp_timer]") TEST_ESP_ERR(ESP_ERR_INVALID_STATE, esp_timer_stop(timer2)); } + teardown_overflow(); vSemaphoreDelete(semaphore); } @@ -345,40 +404,75 @@ TEST_CASE("esp_timer_get_time call takes less than 1us", "[esp_timer]") TEST_PERFORMANCE_LESS_THAN(ESP_TIMER_GET_TIME_PER_CALL, "%dns", ns_per_call); } -/* This test runs for about 10 minutes and is disabled in CI. - * Such run time is needed to have FRC2 timer overflow a few times. - */ -TEST_CASE("esp_timer_get_time returns monotonic values", "[esp_timer][ignore]") +TEST_CASE("esp_timer_get_time returns monotonic values", "[esp_timer]") { - void timer_test_task(void* arg) { - int64_t delta = esp_timer_get_time() - ref_clock_get(); + typedef struct { + SemaphoreHandle_t done; + bool pass; + int test_cnt; + int error_cnt; + int64_t total_sq_error; + int64_t max_error; + } test_state_t; - const int iter_count = 1000000000; - for (int i = 0; i < iter_count; ++i) { - int64_t now = esp_timer_get_time(); - int64_t ref_now = ref_clock_get(); - int64_t diff = now - (ref_now + delta); + void timer_test_task(void* arg) { + test_state_t* state = (test_state_t*) arg; + state->pass = true; + int64_t start_time = ref_clock_get(); + int64_t delta = esp_timer_get_time() - start_time; + + int64_t now = start_time; + int error_repeat_cnt = 0; + while (now - start_time < 10000000) { /* 10 seconds */ + int64_t hs_now = esp_timer_get_time(); + now = ref_clock_get(); + int64_t diff = hs_now - (now + delta); /* Allow some difference due to rtos tick interrupting task between * getting 'now' and 'ref_now'. */ - TEST_ASSERT_INT32_WITHIN(100, 0, (int) diff); + 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->max_error = MAX(state->max_error, abs(diff)); + state->test_cnt++; + state->total_sq_error += diff * diff; } - - xSemaphoreGive((SemaphoreHandle_t) arg); + xSemaphoreGive(state->done); vTaskDelete(NULL); } + ref_clock_init(); - SemaphoreHandle_t done_1 = xSemaphoreCreateBinary(); - SemaphoreHandle_t done_2 = xSemaphoreCreateBinary(); + setup_overflow(); - xTaskCreatePinnedToCore(&timer_test_task, "t1", 4096, (void*) done_1, 6, NULL, 0); - xTaskCreatePinnedToCore(&timer_test_task, "t2", 4096, (void*) done_2, 6, NULL, 1); + test_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); + } - TEST_ASSERT_TRUE( xSemaphoreTake(done_1, portMAX_DELAY) ); - TEST_ASSERT_TRUE( xSemaphoreTake(done_2, portMAX_DELAY) ); - vSemaphoreDelete(done_1); - vSemaphoreDelete(done_2); + for (int i = 0; i < portNUM_PROCESSORS; ++i) { + TEST_ASSERT_TRUE( xSemaphoreTake(done, portMAX_DELAY) ); + printf("CPU%d: %s test_cnt=%d error_cnt=%d std_error=%d |max_error|=%d\n", + i, states[i].pass ? "PASS" : "FAIL", + states[i].test_cnt, states[i].error_cnt, + (int) sqrt(states[i].total_sq_error / states[i].test_cnt), (int) states[i].max_error); + } + + vSemaphoreDelete(done); + teardown_overflow(); ref_clock_deinit(); + + for (int i = 0; i < portNUM_PROCESSORS; ++i) { + TEST_ASSERT(states[i].pass); + } } TEST_CASE("Can dump esp_timer stats", "[esp_timer]") diff --git a/components/esp32/test/test_os_adapter_md5.c b/components/esp32/test/test_header_files_md5.c similarity index 52% rename from components/esp32/test/test_os_adapter_md5.c rename to components/esp32/test/test_header_files_md5.c index 315a386081..009de0ea59 100644 --- a/components/esp32/test/test_os_adapter_md5.c +++ b/components/esp32/test/test_header_files_md5.c @@ -5,7 +5,7 @@ #include "esp_log.h" #include "esp_wifi_internal.h" -static const char* TAG = "test_os_adapter_md5"; +static const char* TAG = "test_header_files_md5"; TEST_CASE("wifi os adapter MD5","[wifi]") { @@ -16,3 +16,13 @@ TEST_CASE("wifi os adapter MD5","[wifi]") ESP_LOGI(TAG, "test passed..."); } + +TEST_CASE("wifi crypto types MD5","[wifi]") +{ + const char *test_wifi_crypto_funcs_md5 = WIFI_CRYPTO_MD5; + + ESP_LOGI(TAG, "test wifi crypto adapter MD5..."); + TEST_ESP_OK(esp_wifi_internal_crypto_funcs_md5_check(test_wifi_crypto_funcs_md5)); + + ESP_LOGI(TAG, "test passed..."); +} diff --git a/components/esp32/test/test_intr_alloc.c b/components/esp32/test/test_intr_alloc.c index 00a325b1ea..0112814fa7 100644 --- a/components/esp32/test/test_intr_alloc.c +++ b/components/esp32/test/test_intr_alloc.c @@ -231,7 +231,7 @@ TEST_CASE("Can allocate IRAM int only with an IRAM handler", "[esp32]") } -#include "soc/spi_struct.h" +#include "soc/spi_periph.h" typedef struct { bool flag1; bool flag2; diff --git a/components/esp32/test/test_libgcc.c b/components/esp32/test/test_libgcc.c new file mode 100644 index 0000000000..7fca990d48 --- /dev/null +++ b/components/esp32/test/test_libgcc.c @@ -0,0 +1,185 @@ +#include +#include "unity.h" + +TEST_CASE("libgcc math functions", "[rom]") +{ + extern int64_t __absvdi2(int64_t x); + TEST_ASSERT(__absvdi2(-1L) == 1); + extern int __absvsi2(int x); + TEST_ASSERT(__absvsi2(-1) == 1); + extern double __adddf3(double x, double y); + TEST_ASSERT(__adddf3(1.0, 4.0) == 5.0); + extern float __addsf3(float x, float y); + TEST_ASSERT(__addsf3(1.0f, 4.0f) == 5.0f); + extern int64_t __addvdi3(int64_t x, int64_t y); + TEST_ASSERT(__addvdi3(1L, 4L) == 5L); + extern int __addvsi3(int x, int y); + TEST_ASSERT(__addvsi3(1, 4) == 5); + extern int64_t __ashldi3(int64_t x, int y); + TEST_ASSERT(__ashldi3(1, 4) == 16); + extern int64_t __ashrdi3(int64_t x, int y); + TEST_ASSERT(__ashrdi3(4, 1) == 2); + extern int64_t __bswapdi2(int64_t x); + TEST_ASSERT(__bswapdi2(0xaabbccddeeff0011ULL) == 0x1100ffeeddccbbaaULL); + extern int32_t __bswapsi2(int32_t x); + TEST_ASSERT(__bswapsi2(0xaabbccdd) == 0xddccbbaa); + extern int64_t __clrsbdi2(int64_t x); + TEST_ASSERT(__clrsbdi2(-1) == 63); + extern int __clrsbsi2(int x); + TEST_ASSERT(__clrsbsi2(-1) == 31); + extern int __clzdi2(int64_t x); + TEST_ASSERT(__clzdi2(1) == 63); + extern int __clzsi2(int x); + TEST_ASSERT(__clzsi2(1) == 31); + extern int __cmpdi2(int64_t x, int64_t y); + TEST_ASSERT(__cmpdi2(10, 10) == 1); + extern int __ctzdi2(uint64_t x); + TEST_ASSERT(__ctzdi2(0x8000000000000000ULL) == 63); + extern int __ctzsi2(unsigned x); + TEST_ASSERT(__ctzsi2(0x80000000U) == 31); + extern complex double __divdc3(double a, double b, double c, double d); + TEST_ASSERT(__divdc3(0, 1, 1, 0) == I); + extern double __divdf3(double x, double y); + TEST_ASSERT(__divdf3(16.0, 2.0) == 8.0); + extern int64_t __divdi3(int64_t x, int64_t y); + TEST_ASSERT(__divdi3(16, 2) == 8); + extern complex float __divsc3(float a, float b, float c, float d); + TEST_ASSERT(__divsc3(0, 1, 1, 0) == I); + extern float __divsf3(float x, float y); + TEST_ASSERT(__divsf3(16.0f, 2.0f) == 8.0f); + extern int __divsi3(int x, int y); + TEST_ASSERT(__divsi3(16, 2) == 8); + extern int __eqdf2(double x, double y); + TEST_ASSERT(__eqdf2(4.0, 4.0) == 0); + extern int __eqsf2(float x, float y); + TEST_ASSERT(__eqsf2(4.0f, 4.0f) == 0); + extern double __extendsfdf2(float x); + TEST_ASSERT(__extendsfdf2(4.0f) == 4.0); + extern int __ffsdi2(uint64_t x); + TEST_ASSERT(__ffsdi2(0x8000000000000000ULL) == 64); + extern int __ffssi2(unsigned x); + TEST_ASSERT(__ffssi2(0x80000000) == 32); + extern int64_t __fixdfdi(double x); + TEST_ASSERT(__fixdfdi(4.0) == 4LL); + extern int __fixdfsi(double x); + TEST_ASSERT(__fixdfsi(4.0) == 4); + extern int64_t __fixsfdi(float x); + TEST_ASSERT(__fixsfdi(4.0f) == 4LL); + extern int __fixsfsi(float x); + TEST_ASSERT(__fixsfsi(4.0f) == 4); + extern unsigned __fixunsdfsi(double x); + TEST_ASSERT(__fixunsdfsi(16.0) == 16); + extern uint64_t __fixunssfdi(float x); + TEST_ASSERT(__fixunssfdi(16.0f) == 16); + extern unsigned __fixunssfsi(float x); + TEST_ASSERT(__fixunssfsi(16.0f) == 16); + extern double __floatdidf(int64_t); + TEST_ASSERT(__floatdidf(-1LL) == -1.0f); + extern float __floatdisf(int64_t); + TEST_ASSERT(__floatdisf(-1LL) == -1.0f); + extern double __floatsidf(int x); + TEST_ASSERT(__floatsidf(-1) == -1.0); + extern float __floatsisf(int x); + TEST_ASSERT(__floatsisf(-1) == -1.0f); + extern double __floatundidf(uint64_t x); + TEST_ASSERT(__floatundidf(16) == 16.0); + extern float __floatundisf(uint64_t x); + TEST_ASSERT(__floatundisf(16) == 16.0f); + extern double __floatunsidf(unsigned x); + TEST_ASSERT(__floatunsidf(16) == 16.0); + extern float __floatunsisf(unsigned x); + TEST_ASSERT(__floatunsisf(16) == 16.0f); + extern int __gedf2(double x, double y); + TEST_ASSERT(__gedf2(2.0, 0.0) >= 0); + extern int __gesf2(float x, float y); + TEST_ASSERT(__gesf2(2.0f, 0.0f) >= 0); + extern int __gtdf2(double x, double y); + TEST_ASSERT(__gtdf2(2.0, 0.0) >= 0); + extern int __gtsf2(float x, float y); + TEST_ASSERT(__gtsf2(2.0f, 0.0f) >= 0); + extern int __ledf2(double x, double y); + TEST_ASSERT(__ledf2(0.0, 2.0) <= 0); + extern int __lesf2(float x, float y); + TEST_ASSERT(__lesf2(0.0f, 2.0f) <= 0); + extern int64_t __lshrdi3(int64_t x, int y); + TEST_ASSERT(__lshrdi3(0x8000000000000000LL, 1) == 0x4000000000000000LL); + extern int __ltdf2(double x, double y); + TEST_ASSERT(__ltdf2(0.0, 2.0) < 0); + extern int __ltsf2(float x, float y); + TEST_ASSERT(__ltsf2(0.0f, 2.0f) < 0); + extern int64_t __moddi3(int64_t x, int64_t y); + TEST_ASSERT(__moddi3(15, 2) == 1); + extern int __modsi3(int x, int y); + TEST_ASSERT(__modsi3(15, 2) == 1); + extern complex double __muldc3(double a, double b, double c, double d); + TEST_ASSERT(__muldc3(1.0, 0.0, 0.0, 1.0) == I); + extern double __muldf3(double x, double y); + TEST_ASSERT(__muldf3(2.0, 8.0) == 16.0); + extern int64_t __muldi3(int64_t x, int64_t y); + TEST_ASSERT(__muldi3(2, 8) == 16); + extern complex float __mulsc3 (float a, float b, float c, float d); + TEST_ASSERT(__mulsc3(1.0f, 0.0f, 0.0f, -1.0f) == -I); + extern float __mulsf3 (float a, float b); + TEST_ASSERT(__mulsf3(2.0f, 8.0f) == 16.0f); + extern int __mulsi3(int x, int y); + TEST_ASSERT(__mulsi3(2, 8) == 16); + extern int __mulvdi3(int64_t x, int64_t y); + TEST_ASSERT(__mulvdi3(2, 8) == 16); + extern int __mulvsi3(int x, int y); + TEST_ASSERT(__mulvsi3(2, 8) == 16); + extern int __nedf2(double x, double y); + TEST_ASSERT(__nedf2(2.0, 2.0) == 0); + extern double __negdf2(double x); + TEST_ASSERT(__negdf2(1.0) == -1.0); + extern int64_t __negdi2(int64_t x); + TEST_ASSERT(__negdi2(-1LL) == 1); + extern float __negsf2(float x); + TEST_ASSERT(__negsf2(-1.0f) == 1.0f); + extern int64_t __negvdi2(int64_t x); + TEST_ASSERT(__negvdi2(-1LL) == 1); + extern int __negvsi2(int x); + TEST_ASSERT(__negvsi2(-1) == 1); + extern int __nesf2(float x, float y); + TEST_ASSERT(__nesf2(2.0, 0.0) != 0); + extern int __paritysi2(unsigned x); + TEST_ASSERT(__paritysi2(0x10101010) == 0); + extern int __popcountdi2(uint64_t); + TEST_ASSERT(__popcountdi2(0xaaaaaaaa11111111ULL) == 24); + extern int __popcountsi2(unsigned x); + TEST_ASSERT(__popcountsi2(0x11111111) == 8); + extern double __powidf2(double x, int y); + TEST_ASSERT(__powidf2(2.0, -1) == 0.5); + extern float __powisf2(float x, int y); + TEST_ASSERT(__powisf2(2.0f, 2) == 4.0f); + extern double __subdf3(double x, double y); + TEST_ASSERT(__subdf3(2.0, 1.0) == 1.0); + extern float __subsf3(float x, float y); + TEST_ASSERT(__subsf3(5.0f, 4.0f) == 1.0f); + extern int64_t __subvdi3(int64_t x, int64_t y); + TEST_ASSERT(__subvdi3(-1LL, -1LL) == 0); + extern int __subvsi3(int x, int y); + TEST_ASSERT(__subvsi3(-1, -1) == 0); + extern float __truncdfsf2(double x); + TEST_ASSERT(__truncdfsf2(4.0) == 4.0f); + extern int __ucmpdi2(uint64_t x, uint64_t y); + TEST_ASSERT(__ucmpdi2(0x100000000ULL, 0x100000000ULL) == 1); + extern uint64_t __udivdi3(uint64_t x, uint64_t y); + TEST_ASSERT(__udivdi3(15, 2) == 7); + extern uint64_t __udivmoddi4(uint64_t x, uint64_t y, uint64_t* z); + uint64_t z; + TEST_ASSERT(__udivmoddi4(15, 2, &z) == 7); + TEST_ASSERT(z == 1); + extern unsigned __udivsi3(unsigned x, unsigned y); + TEST_ASSERT(__udivsi3(15, 2) == 7); + extern uint64_t __umoddi3(uint64_t x, uint64_t y); + TEST_ASSERT(__umoddi3(15, 2) == 1); + extern unsigned __umodsi3(unsigned x, unsigned y); + TEST_ASSERT(__umodsi3(15, 2) == 1); + extern uint64_t __umulsidi3(unsigned x, unsigned y); + TEST_ASSERT(__umulsidi3(0x10000000, 0x10000000) == 0x100000000000000ULL); + extern int __unorddf2(double x, double y); + TEST_ASSERT(__unorddf2(1.0, 2.0) == 0); + extern int __unordsf2(float x, float y); + TEST_ASSERT(__unordsf2(2.0f, 1.0f) == 0); + +} diff --git a/components/esp32/test/test_noinit.c b/components/esp32/test/test_noinit.c new file mode 100644 index 0000000000..bb1b429392 --- /dev/null +++ b/components/esp32/test/test_noinit.c @@ -0,0 +1,123 @@ +#include "unity.h" +#include "esp_system.h" +#include "rom/rtc.h" +#include "esp_log.h" + +// This is a test sequence to test behavior of .rtc_noinit and .noinit sections. +// The values placed into .rtc_noinit section go to RTC SLOW Memory segment and +// keep their value after reset and deep sleep. Use new added attribute macro +// RTC_NOINIT_ATTR for this behavior. The second macro - __NOINIT_ATTR places value +// into .noinit section which goes to SRAM and will not be initialized after reset. + +#define RTC_NOINIT_PATTERN 0xAAAAAAAA +#define _NOINIT_PATTERN 0x55555555 + +static __NOINIT_ATTR uint32_t noinit_data; +static RTC_NOINIT_ATTR uint32_t rtc_noinit_data; + +extern int _rtc_noinit_start; +extern int _rtc_noinit_end; +extern int _noinit_start; +extern int _noinit_end; + +// Pointers to the values +uint32_t *noinit_val_addr = (uint32_t*)&noinit_data; +uint32_t *rtc_noinit_val_addr = (uint32_t*)&rtc_noinit_data; + +static const char* tag = "noinit_UnitTestMain"; + +static esp_err_t check_data_seg(uint32_t *value_address, \ + uint32_t *seg_start, uint32_t *seg_end) +{ + esp_err_t result = ESP_FAIL; + if (((uint32_t)value_address <= (uint32_t)seg_end) && \ + ((uint32_t)value_address >= (uint32_t)seg_start)){ + result = ESP_OK; + } + return result; +} + +static void setup_attributes(void) +{ + rtc_noinit_data = RTC_NOINIT_PATTERN; + noinit_data = _NOINIT_PATTERN; +} + +static void init_attributes(void) +{ + setup_attributes(); + printf("noinit_data = 0x%X \n", (uint32_t)*noinit_val_addr); + printf("rtc_noinit_data = 0x%X \n", (uint32_t)*rtc_noinit_val_addr); + TEST_ASSERT(*noinit_val_addr == noinit_data); + TEST_ASSERT(*rtc_noinit_val_addr == rtc_noinit_data); +} + +static void reset_reason_power_on(void) +{ + printf("This test case checks behavior of noinit variables POWERON_RESET sequence. \n"); + RESET_REASON reason = rtc_get_reset_reason(0); + ESP_LOGI(tag, "POWERON_RESET reset values = (0x%X), (0x%X), reset reason=(%d)\n", \ + (uint32_t)*noinit_val_addr, (uint32_t)*rtc_noinit_val_addr, (uint16_t)reason); + TEST_ASSERT((reason == POWERON_RESET) || (reason == RTCWDT_RTC_RESET)); + + init_attributes(); + TEST_ASSERT(check_data_seg(noinit_val_addr, \ + (uint32_t*)&_noinit_start, \ + (uint32_t*)&_noinit_end) == ESP_OK); + TEST_ASSERT(check_data_seg(rtc_noinit_val_addr, \ + (uint32_t*)&_rtc_noinit_start, \ + (uint32_t*)&_rtc_noinit_end) == ESP_OK); + TEST_ASSERT(_NOINIT_PATTERN == *noinit_val_addr); + TEST_ASSERT(RTC_NOINIT_PATTERN == *rtc_noinit_val_addr); + + printf("Next test case will check SOFTWARE_RESET behavior. \n"); + esp_restart(); +} + +static void reset_reason_sw_reset(void) +{ + printf("This test case checks behavior of noinit variables after software reset sequence. \n"); + RESET_REASON reason = rtc_get_reset_reason(0); + ESP_LOGI(tag, "SW_CPU_RESET reset values = (0x%X), (0x%X), reset reason=(%d)\n", \ + (uint32_t)*noinit_val_addr, (uint32_t)*rtc_noinit_val_addr, (uint16_t)reason); + TEST_ASSERT(reason == SW_CPU_RESET); + TEST_ASSERT(check_data_seg(noinit_val_addr, \ + (uint32_t*)&_noinit_start, \ + (uint32_t*)&_noinit_end) == ESP_OK); + TEST_ASSERT(check_data_seg(rtc_noinit_val_addr, \ + (uint32_t*)&_rtc_noinit_start, \ + (uint32_t*)&_rtc_noinit_end) == ESP_OK); + // The ROM bootloader behavior may apply to this assert. + // TEST_ASSERT(0x55555555 == *noinit_val_addr); + TEST_ASSERT(RTC_NOINIT_PATTERN == *rtc_noinit_val_addr); + printf("Go to deep sleep to check DEEP_SLEEP_RESET behavior. \n"); + esp_sleep_enable_timer_wakeup(2000000); + esp_deep_sleep_start(); +} + +static void reset_reason_deep_sleep(void) +{ + printf("This test case checks behavior of noinit variables after deep sleep reset. \n"); + RESET_REASON reason = rtc_get_reset_reason(0); + ESP_LOGI(tag, "DEEP_SLEEP_RESET reset values = (0x%X), (0x%X), reset reason=(%d)\n", \ + (uint32_t)*noinit_val_addr, (uint32_t)*rtc_noinit_val_addr, (uint16_t)reason); + TEST_ASSERT(reason == DEEPSLEEP_RESET); + TEST_ASSERT(check_data_seg(noinit_val_addr, \ + (uint32_t*)&_noinit_start, \ + (uint32_t*)&_noinit_end) == ESP_OK); + TEST_ASSERT(check_data_seg(rtc_noinit_val_addr, \ + (uint32_t*)&_rtc_noinit_start, \ + (uint32_t*)&_rtc_noinit_end) == ESP_OK); + TEST_ASSERT(RTC_NOINIT_PATTERN == *rtc_noinit_val_addr); + printf("The noinit test cases are done.. \n"); +} + +// The lines below are required to suppress GCC warnings about casting of function pointers +// in unity macro expansion. These warnings may be treated as errors during automated test. +#pragma GCC diagnostic push // required for GCC +#pragma GCC diagnostic ignored "-Wdiscarded-qualifiers" +// The multiple stages test case to check values after certain reset reason +TEST_CASE_MULTIPLE_STAGES("NOINIT attributes behavior", + "[restart][reset=SW_CPU_RESET, DEEPSLEEP_RESET]", + reset_reason_power_on, reset_reason_sw_reset, reset_reason_deep_sleep); +#pragma GCC diagnostic pop // require GCC diff --git a/components/esp32/test/test_sleep.c b/components/esp32/test/test_sleep.c index 201c2312e3..70fe47f3ab 100644 --- a/components/esp32/test/test_sleep.c +++ b/components/esp32/test/test_sleep.c @@ -14,6 +14,8 @@ #include "soc/rtc.h" // for wakeup trigger defines #include "soc/rtc_cntl_reg.h" // for read rtc registers directly (cause) #include "soc/soc.h" // for direct register read macros +#include "rom/rtc.h" +#include "esp_newlib.h" #define ESP_EXT0_WAKEUP_LEVEL_LOW 0 #define ESP_EXT0_WAKEUP_LEVEL_HIGH 1 @@ -338,3 +340,35 @@ TEST_CASE("disable source trigger behavior", "[deepsleep]") TEST_ASSERT(err_code == ESP_ERR_INVALID_STATE); } +static RTC_DATA_ATTR struct timeval start; +static void trigger_deepsleep(void) +{ + printf("Trigger deep sleep. Waiting 30 sec ...\n"); + + // Simulate the dispersion of the calibration coefficients at start-up. + // Corrupt the calibration factor. + esp_clk_slowclk_cal_set(esp_clk_slowclk_cal_get() - 1000000); + esp_set_time_from_rtc(); + + // Delay for time error accumulation. + vTaskDelay(30000/portTICK_RATE_MS); + + // Save start time. Deep sleep. + gettimeofday(&start, NULL); + esp_sleep_enable_timer_wakeup(1000); + esp_deep_sleep_start(); +} + +static void check_time_deepsleep(void) +{ + struct timeval stop; + RESET_REASON reason = rtc_get_reset_reason(0); + TEST_ASSERT(reason == DEEPSLEEP_RESET); + gettimeofday(&stop, NULL); + // Time dt_ms must in any case be positive. + int dt_ms = (stop.tv_sec - start.tv_sec) * 1000 + (stop.tv_usec - start.tv_usec) / 1000; + printf("delta time = %d \n", dt_ms); + TEST_ASSERT_MESSAGE(dt_ms > 0, "Time in deep sleep is negative"); +} + +TEST_CASE_MULTIPLE_STAGES("check a time after wakeup from deep sleep", "[deepsleep][reset=DEEPSLEEP_RESET][timeout=60]", trigger_deepsleep, check_time_deepsleep); diff --git a/components/esp32/test/test_wifi_lib_git_commit.c b/components/esp32/test/test_wifi_lib_git_commit.c new file mode 100644 index 0000000000..8b5633f9b1 --- /dev/null +++ b/components/esp32/test/test_wifi_lib_git_commit.c @@ -0,0 +1,14 @@ +/* + Tests for the Wi-Fi +*/ +#include "unity.h" +#include "esp_log.h" +#include "esp_wifi_internal.h" + +static const char* TAG = "test_wifi_lib_git_commit_id"; + +TEST_CASE("wifi lib git commit id","[wifi]") +{ + TEST_ESP_OK( esp_wifi_internal_git_commit_id_check() ); +} + diff --git a/components/esp_http_client/esp_http_client.c b/components/esp_http_client/esp_http_client.c index 6a6f799e30..41d6c3599c 100644 --- a/components/esp_http_client/esp_http_client.c +++ b/components/esp_http_client/esp_http_client.c @@ -33,12 +33,17 @@ static const char *TAG = "HTTP_CLIENT"; +/** + * HTTP Buffer + */ typedef struct { - char *data; - int len; - char *raw_data; - int raw_len; + char *data; /*!< The HTTP data received from the server */ + int len; /*!< The HTTP data len received from the server */ + char *raw_data; /*!< The HTTP data after decoding */ + int raw_len; /*!< The HTTP data len after decoding */ + char *output_ptr; /*!< The destination address of the data to be copied to after decoding */ } esp_http_buffer_t; + /** * private HTTP Data structure */ @@ -232,9 +237,14 @@ static int http_on_body(http_parser *parser, const char *at, size_t length) { esp_http_client_t *client = parser->data; ESP_LOGD(TAG, "http_on_body %d", length); - client->response->buffer->raw_data = (char*)at; - client->response->buffer->raw_len = length; + client->response->buffer->raw_data = (char *)at; + if (client->response->buffer->output_ptr) { + memcpy(client->response->buffer->output_ptr, (char *)at, length); + client->response->buffer->output_ptr += length; + } + client->response->data_process += length; + client->response->buffer->raw_len += length; http_dispatch_event(client, HTTP_EVENT_ON_DATA, (void *)at, length); return 0; } @@ -263,7 +273,7 @@ esp_err_t esp_http_client_delete_header(esp_http_client_handle_t client, const c return http_header_delete(client->request->headers, key); } -static esp_err_t _set_config(esp_http_client_handle_t client, esp_http_client_config_t *config) +static esp_err_t _set_config(esp_http_client_handle_t client, const esp_http_client_config_t *config) { client->connection_info.method = config->method; client->connection_info.port = config->port; @@ -401,7 +411,7 @@ static esp_err_t esp_http_client_prepare(esp_http_client_handle_t client) return ESP_OK; } -esp_http_client_handle_t esp_http_client_init(esp_http_client_config_t *config) +esp_http_client_handle_t esp_http_client_init(const esp_http_client_config_t *config) { esp_http_client_handle_t client; @@ -547,10 +557,10 @@ static esp_err_t esp_http_check_response(esp_http_client_handle_t client) break; case HttpStatus_Unauthorized: auth_header = client->auth_header; - http_utils_trim_whitespace(&auth_header); - ESP_LOGI(TAG, "UNAUTHORIZED: %s", auth_header); - client->redirect_counter ++; if (auth_header) { + http_utils_trim_whitespace(&auth_header); + ESP_LOGD(TAG, "UNAUTHORIZED: %s", auth_header); + client->redirect_counter ++; if (http_utils_str_starts_with(auth_header, "Digest") == 0) { ESP_LOGD(TAG, "type = Digest"); client->connection_info.auth_type = HTTP_AUTH_TYPE_DIGEST; @@ -559,7 +569,7 @@ static esp_err_t esp_http_check_response(esp_http_client_handle_t client) client->connection_info.auth_type = HTTP_AUTH_TYPE_BASIC; } else { client->connection_info.auth_type = HTTP_AUTH_TYPE_NONE; - ESP_LOGE(TAG, "Unsupport Auth Type"); + ESP_LOGE(TAG, "This authentication method is not supported: %s", auth_header); break; } @@ -574,6 +584,9 @@ static esp_err_t esp_http_check_response(esp_http_client_handle_t client) client->auth_data->nonce = http_utils_get_string_between(auth_header, "nonce=\"", "\""); client->auth_data->opaque = http_utils_get_string_between(auth_header, "opaque=\"", "\""); client->process_again = 1; + } else { + client->connection_info.auth_type = HTTP_AUTH_TYPE_NONE; + ESP_LOGW(TAG, "This request requires authentication, but does not provide header information for that"); } } return ESP_OK; @@ -738,14 +751,13 @@ int esp_http_client_read(esp_http_client_handle_t client, char *buffer, int len) if (rlen <= 0) { return ridx; } + res_buffer->output_ptr = buffer + ridx; http_parser_execute(client->parser, client->parser_settings, res_buffer->data, rlen); + ridx += res_buffer->raw_len; + need_read -= res_buffer->raw_len; - if (res_buffer->raw_len) { - memcpy(buffer + ridx, res_buffer->raw_data, res_buffer->raw_len); - ridx += res_buffer->raw_len; - need_read -= res_buffer->raw_len; - } res_buffer->raw_len = 0; //clear + res_buffer->output_ptr = NULL; } return ridx; @@ -983,3 +995,14 @@ bool esp_http_client_is_chunked_response(esp_http_client_handle_t client) { return client->response->is_chunked; } + +esp_http_client_transport_t esp_http_client_get_transport_type(esp_http_client_handle_t client) +{ + if (!strcmp(client->connection_info.scheme, "https") ) { + return HTTP_TRANSPORT_OVER_SSL; + } else if (!strcmp(client->connection_info.scheme, "http")) { + return HTTP_TRANSPORT_OVER_TCP; + } else { + return HTTP_TRANSPORT_UNKNOWN; + } +} diff --git a/components/esp_http_client/include/esp_http_client.h b/components/esp_http_client/include/esp_http_client.h index 687cf8d3b5..f177b2a97e 100644 --- a/components/esp_http_client/include/esp_http_client.h +++ b/components/esp_http_client/include/esp_http_client.h @@ -131,7 +131,7 @@ typedef struct { * - `esp_http_client_handle_t` * - NULL if any errors */ -esp_http_client_handle_t esp_http_client_init(esp_http_client_config_t *config); +esp_http_client_handle_t esp_http_client_init(const esp_http_client_config_t *config); /** * @brief Invoke this function after `esp_http_client_init` and all the options calls are made, and will perform the @@ -334,6 +334,17 @@ esp_err_t esp_http_client_close(esp_http_client_handle_t client); */ esp_err_t esp_http_client_cleanup(esp_http_client_handle_t client); +/** + * @brief Get transport type + * + * @param[in] client The esp_http_client handle + * + * @return + * - HTTP_TRANSPORT_UNKNOWN + * - HTTP_TRANSPORT_OVER_TCP + * - HTTP_TRANSPORT_OVER_SSL + */ +esp_http_client_transport_t esp_http_client_get_transport_type(esp_http_client_handle_t client); #ifdef __cplusplus @@ -341,4 +352,4 @@ esp_err_t esp_http_client_cleanup(esp_http_client_handle_t client); #endif -#endif +#endif \ No newline at end of file diff --git a/components/esp_http_client/lib/http_utils.c b/components/esp_http_client/lib/http_utils.c index 2ccc501313..2e65888abc 100644 --- a/components/esp_http_client/lib/http_utils.c +++ b/components/esp_http_client/lib/http_utils.c @@ -63,8 +63,14 @@ char *http_utils_assign_string(char **str, const char *new_str, int len) void http_utils_trim_whitespace(char **str) { - char *end; - char *start = *str; + char *end, *start; + if (str == NULL) { + return; + } + start = *str; + if (start == NULL) { + return; + } // Trim leading space while (isspace((unsigned char)*start)) start ++; diff --git a/components/esp_http_client/lib/transport_ssl.c b/components/esp_http_client/lib/transport_ssl.c index 8a3c49c0ff..bb07c92455 100644 --- a/components/esp_http_client/lib/transport_ssl.c +++ b/components/esp_http_client/lib/transport_ssl.c @@ -206,12 +206,14 @@ static int ssl_write(transport_handle_t t, const char *buffer, int len, int time static int ssl_read(transport_handle_t t, char *buffer, int len, int timeout_ms) { - int ret; + int poll = -1, ret; transport_ssl_t *ssl = transport_get_context_data(t); - ret = mbedtls_ssl_read(&ssl->ctx, (unsigned char *)buffer, len); - if (ret == 0) { - return -1; + if (mbedtls_ssl_get_bytes_avail(&ssl->ctx) <= 0) { + if ((poll = transport_poll_read(t, timeout_ms)) <= 0) { + return poll; + } } + ret = mbedtls_ssl_read(&ssl->ctx, (unsigned char *)buffer, len); return ret; } diff --git a/components/esp_https_ota/CMakeLists.txt b/components/esp_https_ota/CMakeLists.txt new file mode 100644 index 0000000000..bfc6c12054 --- /dev/null +++ b/components/esp_https_ota/CMakeLists.txt @@ -0,0 +1,7 @@ +set(COMPONENT_ADD_INCLUDEDIRS include) +set(COMPONENT_SRCDIRS "src") + +set(COMPONENT_REQUIRES esp_http_client) +set(COMPONENT_PRIV_REQUIRES log app_update) + +register_component() diff --git a/components/esp_https_ota/component.mk b/components/esp_https_ota/component.mk new file mode 100644 index 0000000000..ebe80ffbe6 --- /dev/null +++ b/components/esp_https_ota/component.mk @@ -0,0 +1,3 @@ +COMPONENT_SRCDIRS := src + +COMPONENT_ADD_INCLUDEDIRS := include diff --git a/components/esp_https_ota/include/esp_https_ota.h b/components/esp_https_ota/include/esp_https_ota.h new file mode 100644 index 0000000000..157195601c --- /dev/null +++ b/components/esp_https_ota/include/esp_https_ota.h @@ -0,0 +1,45 @@ +// 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. + +#pragma once + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief HTTPS OTA Firmware upgrade. + * + * This function performs HTTPS OTA Firmware upgrade + * + * @param[in] config pointer to esp_http_client_config_t structure. + * + * @note For secure HTTPS updates, the `cert_pem` member of `config` + * structure must be set to the server certificate. + * + * @return + * - ESP_OK: OTA data updated, next reboot will use specified partition. + * - ESP_FAIL: For generic failure. + * - ESP_ERR_OTA_VALIDATE_FAILED: Invalid app image + * - ESP_ERR_NO_MEM: Cannot allocate memory for OTA operation. + * - ESP_ERR_FLASH_OP_TIMEOUT or ESP_ERR_FLASH_OP_FAIL: Flash write failed. + * - For other return codes, refer OTA documentation in esp-idf's app_update component. + */ +esp_err_t esp_https_ota(const esp_http_client_config_t *config); + +#ifdef __cplusplus +} +#endif diff --git a/components/esp_https_ota/src/esp_https_ota.c b/components/esp_https_ota/src/esp_https_ota.c new file mode 100644 index 0000000000..9929a18560 --- /dev/null +++ b/components/esp_https_ota/src/esp_https_ota.c @@ -0,0 +1,130 @@ +// 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. + +#include +#include +#include +#include +#include +#include + +#define OTA_BUF_SIZE 256 +static const char *TAG = "esp_https_ota"; + +static void http_cleanup(esp_http_client_handle_t client) +{ + esp_http_client_close(client); + esp_http_client_cleanup(client); +} + +esp_err_t esp_https_ota(const esp_http_client_config_t *config) +{ + if (!config) { + ESP_LOGE(TAG, "esp_http_client config not found"); + return ESP_ERR_INVALID_ARG; + } + + if (!config->cert_pem) { + ESP_LOGE(TAG, "Server certificate not found in esp_http_client config"); + return ESP_FAIL; + } + + esp_http_client_handle_t client = esp_http_client_init(config); + if (client == NULL) { + ESP_LOGE(TAG, "Failed to initialise HTTP connection"); + return ESP_FAIL; + } + + if (esp_http_client_get_transport_type(client) != HTTP_TRANSPORT_OVER_SSL) { + ESP_LOGE(TAG, "Transport is not over HTTPS"); + return ESP_FAIL; + } + + esp_err_t err = esp_http_client_open(client, 0); + if (err != ESP_OK) { + esp_http_client_cleanup(client); + ESP_LOGE(TAG, "Failed to open HTTP connection: %s", esp_err_to_name(err)); + return err; + } + esp_http_client_fetch_headers(client); + + esp_ota_handle_t update_handle = 0; + const esp_partition_t *update_partition = NULL; + ESP_LOGI(TAG, "Starting OTA..."); + update_partition = esp_ota_get_next_update_partition(NULL); + if (update_partition == NULL) { + ESP_LOGE(TAG, "Passive OTA partition not found"); + http_cleanup(client); + return ESP_FAIL; + } + ESP_LOGI(TAG, "Writing to partition subtype %d at offset 0x%x", + update_partition->subtype, update_partition->address); + + err = esp_ota_begin(update_partition, OTA_SIZE_UNKNOWN, &update_handle); + if (err != ESP_OK) { + ESP_LOGE(TAG, "esp_ota_begin failed, error=%d", err); + http_cleanup(client); + return err; + } + ESP_LOGI(TAG, "esp_ota_begin succeeded"); + ESP_LOGI(TAG, "Please Wait. This may take time"); + + esp_err_t ota_write_err = ESP_OK; + char *upgrade_data_buf = (char *)malloc(OTA_BUF_SIZE); + if (!upgrade_data_buf) { + ESP_LOGE(TAG, "Couldn't allocate memory to upgrade data buffer"); + return ESP_ERR_NO_MEM; + } + int binary_file_len = 0; + while (1) { + int data_read = esp_http_client_read(client, upgrade_data_buf, OTA_BUF_SIZE); + if (data_read == 0) { + ESP_LOGI(TAG, "Connection closed,all data received"); + break; + } + if (data_read < 0) { + ESP_LOGE(TAG, "Error: SSL data read error"); + break; + } + if (data_read > 0) { + ota_write_err = esp_ota_write( update_handle, (const void *)upgrade_data_buf, data_read); + if (ota_write_err != ESP_OK) { + break; + } + binary_file_len += data_read; + ESP_LOGD(TAG, "Written image length %d", binary_file_len); + } + } + free(upgrade_data_buf); + http_cleanup(client); + ESP_LOGD(TAG, "Total binary data length writen: %d", binary_file_len); + + esp_err_t ota_end_err = esp_ota_end(update_handle); + if (ota_write_err != ESP_OK) { + ESP_LOGE(TAG, "Error: esp_ota_write failed! err=0x%d", err); + return ota_write_err; + } else if (ota_end_err != ESP_OK) { + ESP_LOGE(TAG, "Error: esp_ota_end failed! err=0x%d. Image is invalid", ota_end_err); + return ota_end_err; + } + + err = esp_ota_set_boot_partition(update_partition); + if (err != ESP_OK) { + ESP_LOGE(TAG, "esp_ota_set_boot_partition failed! err=0x%d", err); + return err; + } + ESP_LOGI(TAG, "esp_ota_set_boot_partition succeeded"); + + return ESP_OK; +} diff --git a/components/esptool_py/Makefile.projbuild b/components/esptool_py/Makefile.projbuild index dce6b0af28..25f4b8e6f7 100644 --- a/components/esptool_py/Makefile.projbuild +++ b/components/esptool_py/Makefile.projbuild @@ -31,9 +31,17 @@ endif ESPTOOL_ELF2IMAGE_OPTIONS := +ifdef CONFIG_SECURE_BOOT_ENABLED +ifndef CONFIG_SECURE_BOOT_ALLOW_SHORT_APP_PARTITION +ifndef IS_BOOTLOADER_BUILD +ESPTOOL_ELF2IMAGE_OPTIONS += --secure-pad +endif +endif +endif + ESPTOOLPY_WRITE_FLASH=$(ESPTOOLPY_SERIAL) write_flash $(if $(CONFIG_ESPTOOLPY_COMPRESSED),-z,-u) $(ESPTOOL_WRITE_FLASH_OPTIONS) -ESPTOOL_ALL_FLASH_ARGS += $(CONFIG_APP_OFFSET) $(APP_BIN) +ESPTOOL_ALL_FLASH_ARGS += $(APP_OFFSET) $(APP_BIN) ifdef CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES ifndef IS_BOOTLOADER_BUILD @@ -50,16 +58,16 @@ APP_BIN_UNSIGNED ?= $(APP_BIN) $(APP_BIN_UNSIGNED): $(APP_ELF) $(ESPTOOLPY_SRC) $(ESPTOOLPY) elf2image $(ESPTOOL_FLASH_OPTIONS) $(ESPTOOL_ELF2IMAGE_OPTIONS) -o $@ $< -flash: all_binaries $(ESPTOOLPY_SRC) $(call prereq_if_explicit,erase_flash) - @echo "Flashing binaries to serial port $(ESPPORT) (app at offset $(CONFIG_APP_OFFSET))..." +flash: all_binaries $(ESPTOOLPY_SRC) $(call prereq_if_explicit,erase_flash) partition_table_get_info + @echo "Flashing binaries to serial port $(ESPPORT) (app at offset $(APP_OFFSET))..." ifdef CONFIG_SECURE_BOOT_ENABLED @echo "(Secure boot enabled, so bootloader not flashed automatically. See 'make bootloader' output)" endif $(ESPTOOLPY_WRITE_FLASH) $(ESPTOOL_ALL_FLASH_ARGS) -app-flash: $(APP_BIN) $(ESPTOOLPY_SRC) $(call prereq_if_explicit,erase_flash) - @echo "Flashing app to serial port $(ESPPORT), offset $(CONFIG_APP_OFFSET)..." - $(ESPTOOLPY_WRITE_FLASH) $(CONFIG_APP_OFFSET) $(APP_BIN) +app-flash: $(APP_BIN) $(ESPTOOLPY_SRC) $(call prereq_if_explicit,erase_flash) partition_table_get_info + @echo "Flashing app to serial port $(ESPPORT), offset $(APP_OFFSET)..." + $(ESPTOOLPY_WRITE_FLASH) $(APP_OFFSET) $(APP_BIN) # Submodules normally added in component.mk, but can be added # at the project level as long as qualified path @@ -85,7 +93,9 @@ endif simple_monitor: $(call prereq_if_explicit,%flash) $(MONITOR_PYTHON) -m serial.tools.miniterm --rts 0 --dtr 0 --raw $(ESPPORT) $(MONITORBAUD) -MONITOR_OPTS := --baud $(MONITORBAUD) --port $(ESPPORT) --toolchain-prefix $(CONFIG_TOOLPREFIX) --make "$(MAKE)" +PRINT_FILTER ?= + +MONITOR_OPTS := --baud $(MONITORBAUD) --port $(ESPPORT) --toolchain-prefix $(CONFIG_TOOLPREFIX) --make "$(MAKE)" --print_filter "$(PRINT_FILTER)" monitor: $(call prereq_if_explicit,%flash) $(summary) MONITOR diff --git a/components/esptool_py/esptool b/components/esptool_py/esptool index da31d9d7a1..fd8c25d216 160000 --- a/components/esptool_py/esptool +++ b/components/esptool_py/esptool @@ -1 +1 @@ -Subproject commit da31d9d7a1bb496995f8e30a6be259689948e43e +Subproject commit fd8c25d2160505fb9d5abbe56f85116a136afb05 diff --git a/components/esptool_py/flash_app_args.in b/components/esptool_py/flash_app_args.in index 1e2fa31c23..6d31ca4fef 100644 --- a/components/esptool_py/flash_app_args.in +++ b/components/esptool_py/flash_app_args.in @@ -1 +1 @@ -${CONFIG_APP_OFFSET} ${PROJECT_NAME}.bin +${APP_PARTITION_OFFSET} ${PROJECT_NAME}.bin diff --git a/components/esptool_py/flash_partition_table_args.in b/components/esptool_py/flash_partition_table_args.in index 0983e11c4b..ccfc14d71b 100644 --- a/components/esptool_py/flash_partition_table_args.in +++ b/components/esptool_py/flash_partition_table_args.in @@ -1 +1 @@ -0x8000 partition_table/partition-table.bin +${PARTITION_TABLE_OFFSET} partition_table/partition-table.bin diff --git a/components/esptool_py/flash_project_args.in b/components/esptool_py/flash_project_args.in index 70edf4fae1..d3eb6f5824 100644 --- a/components/esptool_py/flash_project_args.in +++ b/components/esptool_py/flash_project_args.in @@ -2,6 +2,6 @@ --flash_size ${ESPFLASHSIZE} --flash_freq ${ESPFLASHFREQ} 0x1000 bootloader/bootloader.bin -0x8000 partition_table/partition-table.bin -${CONFIG_APP_OFFSET} ${PROJECT_NAME}.bin +${PARTITION_TABLE_OFFSET} partition_table/partition-table.bin +${APP_PARTITION_OFFSET} ${PROJECT_NAME}.bin ${PHY_PARTITION_OFFSET} ${PHY_PARTITION_BIN_FILE} diff --git a/components/esptool_py/flasher_args.json.in b/components/esptool_py/flasher_args.json.in index 1d68a2bb99..4ec3a8c243 100644 --- a/components/esptool_py/flasher_args.json.in +++ b/components/esptool_py/flasher_args.json.in @@ -5,12 +5,12 @@ "flash_files" : { "0x1000" : "bootloader/bootloader.bin", "${PARTITION_TABLE_OFFSET}" : "partition_table/partition-table.bin", - "${CONFIG_APP_OFFSET}" : "${PROJECT_NAME}.bin", + "${APP_PARTITION_OFFSET}" : "${PROJECT_NAME}.bin", "${PHY_PARTITION_OFFSET}" : "${PHY_PARTITION_BIN_FILE}" }, "bootloader" : { "offset" : "0x1000", "file" : "bootloader/bootloader.bin" }, - "app" : { "offset" : "${CONFIG_APP_OFFSET}", + "app" : { "offset" : "${APP_PARTITION_OFFSET}", "file" : "${PROJECT_NAME}.bin" }, "partition_table" : { "offset" : "${PARTITION_TABLE_OFFSET}", "file" : "partition_table/partition-table.bin" } diff --git a/components/ethernet/emac_main.c b/components/ethernet/emac_main.c index ca9d812d31..f89c56952f 100644 --- a/components/ethernet/emac_main.c +++ b/components/ethernet/emac_main.c @@ -275,7 +275,7 @@ static void emac_set_user_config_data(eth_config_t *config ) emac_config.emac_flow_ctrl_enable = config->flow_ctrl_enable; #else if(config->flow_ctrl_enable == true) { - ESP_LOGE(TAG, "eth flow ctrl init err!!! Please run idf.py menuconfig and make sure DMA_RX_BUF_NUM > 9 ."); + ESP_LOGE(TAG, "eth flow ctrl init err!!! Please run menuconfig and make sure DMA_RX_BUF_NUM > 9 ."); } emac_config.emac_flow_ctrl_enable = false; #endif diff --git a/components/expat/CMakeLists.txt b/components/expat/CMakeLists.txt index 5791a26599..0241ae34f1 100644 --- a/components/expat/CMakeLists.txt +++ b/components/expat/CMakeLists.txt @@ -13,3 +13,6 @@ set_source_files_properties( PROPERTIES COMPILE_FLAGS -Wno-unused-function ) + +# Temporary suppress "fallthrough" warnings until they are fixed in expat repo +component_compile_options(-Wno-implicit-fallthrough) diff --git a/components/expat/component.mk b/components/expat/component.mk index 0ee1199d1b..bf34d31426 100644 --- a/components/expat/component.mk +++ b/components/expat/component.mk @@ -6,4 +6,5 @@ COMPONENT_ADD_INCLUDEDIRS := port/include include/expat COMPONENT_SRCDIRS := library port CFLAGS += -Wno-unused-function -DHAVE_EXPAT_CONFIG_H - +# Temporary suppress "fallthrough" warnings until they are fixed in expat repo +CFLAGS += -Wno-implicit-fallthrough diff --git a/components/expat/library/xmlparse.c b/components/expat/library/xmlparse.c index e69622bcfb..0f9c7ae789 100644 --- a/components/expat/library/xmlparse.c +++ b/components/expat/library/xmlparse.c @@ -1554,6 +1554,7 @@ XML_Parse(XML_Parser parser, const char *s, int len, int isFinal) errorCode = XML_ERROR_NO_MEMORY; return XML_STATUS_ERROR; } + /* falls through */ default: ps_parsing = XML_PARSING; } @@ -1680,6 +1681,7 @@ XML_ParseBuffer(XML_Parser parser, int len, int isFinal) errorCode = XML_ERROR_NO_MEMORY; return XML_STATUS_ERROR; } + /* falls through */ default: ps_parsing = XML_PARSING; } @@ -4266,8 +4268,8 @@ doProlog(XML_Parser parser, return XML_ERROR_NO_MEMORY; declEntity->publicId = NULL; } - /* fall through */ #endif /* XML_DTD */ + /* falls through */ case XML_ROLE_ENTITY_SYSTEM_ID: if (dtd->keepProcessing && declEntity) { declEntity->systemId = poolStoreString(&dtd->pool, enc, diff --git a/components/expat/library/xmltok_impl.c b/components/expat/library/xmltok_impl.c index 5f779c0571..b785129983 100644 --- a/components/expat/library/xmltok_impl.c +++ b/components/expat/library/xmltok_impl.c @@ -47,6 +47,7 @@ *nextTokPtr = ptr; \ return XML_TOK_INVALID; \ } \ + /* fall through */ \ case BT_NMSTRT: \ case BT_HEX: \ case BT_DIGIT: \ @@ -75,6 +76,7 @@ *nextTokPtr = ptr; \ return XML_TOK_INVALID; \ } \ + /* fall through */ \ case BT_NMSTRT: \ case BT_HEX: \ ptr += MINBPC(enc); \ @@ -575,7 +577,7 @@ PREFIX(scanAtts)(const ENCODING *enc, const char *ptr, const char *end, return XML_TOK_INVALID; } } - /* fall through */ + /* fall through */ case BT_EQUALS: { int open; @@ -1403,6 +1405,7 @@ PREFIX(isPublicId)(const ENCODING *enc, const char *ptr, const char *end, case BT_NMSTRT: if (!(BYTE_TO_ASCII(enc, ptr) & ~0x7f)) break; + /* fall through */ default: switch (BYTE_TO_ASCII(enc, ptr)) { case 0x24: /* $ */ diff --git a/components/fatfs/src/diskio_rawflash.c b/components/fatfs/src/diskio_rawflash.c new file mode 100644 index 0000000000..bc3b204b50 --- /dev/null +++ b/components/fatfs/src/diskio_rawflash.c @@ -0,0 +1,104 @@ +// 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. + +#include +#include "diskio.h" +#include "ffconf.h" +#include "ff.h" +#include "esp_log.h" +#include "diskio_rawflash.h" + +static const char* TAG = "diskio_rawflash"; + +const esp_partition_t* ff_raw_handles[FF_VOLUMES]; + + +DSTATUS ff_raw_initialize (BYTE pdrv) +{ + return 0; +} + +DSTATUS ff_raw_status (BYTE pdrv) +{ + return 0; +} + +DRESULT ff_raw_read (BYTE pdrv, BYTE *buff, DWORD sector, UINT count) +{ + ESP_LOGV(TAG, "ff_raw_read - pdrv=%i, sector=%i, count=%in", (unsigned int)pdrv, (unsigned int)sector, (unsigned int)count); + const esp_partition_t* part = ff_raw_handles[pdrv]; + assert(part); + esp_err_t err = esp_partition_read(part, sector * SPI_FLASH_SEC_SIZE, buff, count * SPI_FLASH_SEC_SIZE); + if (err != ESP_OK) { + ESP_LOGE(TAG, "esp_partition_read failed (0x%x)", err); + return RES_ERROR; + } + return RES_OK; +} + + +DRESULT ff_raw_write (BYTE pdrv, const BYTE *buff, DWORD sector, UINT count) +{ + return RES_ERROR; +} + +DRESULT ff_raw_ioctl (BYTE pdrv, BYTE cmd, void *buff) +{ + const esp_partition_t* part = ff_raw_handles[pdrv]; + ESP_LOGV(TAG, "ff_raw_ioctl: cmd=%in", cmd); + assert(part); + switch (cmd) { + case CTRL_SYNC: + return RES_OK; + case GET_SECTOR_COUNT: + *((DWORD *) buff) = part->size / SPI_FLASH_SEC_SIZE; + return RES_OK; + case GET_SECTOR_SIZE: + *((WORD *) buff) = SPI_FLASH_SEC_SIZE; + return RES_OK; + case GET_BLOCK_SIZE: + return RES_ERROR; + } + return RES_ERROR; +} + + +esp_err_t ff_diskio_register_raw_partition(BYTE pdrv, const esp_partition_t* part_handle) +{ + if (pdrv >= FF_VOLUMES) { + return ESP_ERR_INVALID_ARG; + } + static const ff_diskio_impl_t raw_impl = { + .init = &ff_raw_initialize, + .status = &ff_raw_status, + .read = &ff_raw_read, + .write = &ff_raw_write, + .ioctl = &ff_raw_ioctl + }; + ff_diskio_register(pdrv, &raw_impl); + ff_raw_handles[pdrv] = part_handle; + return ESP_OK; + +} + + +BYTE ff_diskio_get_pdrv_raw(const esp_partition_t* part_handle) +{ + for (int i = 0; i < FF_VOLUMES; i++) { + if (part_handle == ff_raw_handles[i]) { + return i; + } + } + return 0xff; +} diff --git a/components/fatfs/src/diskio_rawflash.h b/components/fatfs/src/diskio_rawflash.h new file mode 100644 index 0000000000..389c3bd85d --- /dev/null +++ b/components/fatfs/src/diskio_rawflash.h @@ -0,0 +1,38 @@ +// 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. + +#ifndef _DISKIO_RAWFLASH_DEFINED +#define _DISKIO_RAWFLASH_DEFINED + +#ifdef __cplusplus +extern "C" { +#endif + +#include "integer.h" +#include "esp_partition.h" + +/** + * Register spi flash partition + * + * @param pdrv drive number + * @param part_handle pointer to raw flash partition. + */ +esp_err_t ff_diskio_register_raw_partition(BYTE pdrv, const esp_partition_t* part_handle); +BYTE ff_diskio_get_pdrv_raw(const esp_partition_t* part_handle); + +#ifdef __cplusplus +} +#endif + +#endif // _DISKIO_RAWFLASH_DEFINED diff --git a/components/fatfs/src/diskio_spiflash.c b/components/fatfs/src/diskio_wl.c similarity index 96% rename from components/fatfs/src/diskio_spiflash.c rename to components/fatfs/src/diskio_wl.c index 8428ee8e3b..19d4ade252 100644 --- a/components/fatfs/src/diskio_spiflash.c +++ b/components/fatfs/src/diskio_wl.c @@ -17,7 +17,7 @@ #include "ffconf.h" #include "ff.h" #include "esp_log.h" -#include "diskio_spiflash.h" +#include "diskio_wl.h" #include "wear_levelling.h" static const char* TAG = "ff_diskio_spiflash"; diff --git a/components/fatfs/src/diskio_spiflash.h b/components/fatfs/src/diskio_wl.h similarity index 87% rename from components/fatfs/src/diskio_spiflash.h rename to components/fatfs/src/diskio_wl.h index d1de1d3dac..c2ed07dc8b 100644 --- a/components/fatfs/src/diskio_spiflash.h +++ b/components/fatfs/src/diskio_wl.h @@ -12,8 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -#ifndef _DISKIO_SPIFLASH_DEFINED -#define _DISKIO_SPIFLASH_DEFINED +#ifndef _DISKIO_WL_DEFINED +#define _DISKIO_WL_DEFINED #ifdef __cplusplus extern "C" { @@ -36,4 +36,4 @@ BYTE ff_diskio_get_pdrv_wl(wl_handle_t flash_handle); } #endif -#endif // _DISKIO_SPIFLASH_DEFINED +#endif // _DISKIO_WL_DEFINED diff --git a/components/fatfs/src/esp_vfs_fat.h b/components/fatfs/src/esp_vfs_fat.h index bd86e681a0..a2a05951e1 100644 --- a/components/fatfs/src/esp_vfs_fat.h +++ b/components/fatfs/src/esp_vfs_fat.h @@ -205,6 +205,47 @@ esp_err_t esp_vfs_fat_spiflash_mount(const char* base_path, */ esp_err_t esp_vfs_fat_spiflash_unmount(const char* base_path, wl_handle_t wl_handle); + +/** + * @brief Convenience function to initialize read-only FAT filesystem and register it in VFS + * + * This is an all-in-one function which does the following: + * + * - finds the partition with defined partition_label. Partition label should be + * configured in the partition table. + * - mounts FAT partition using FATFS library + * - registers FATFS library with VFS, with prefix given by base_prefix variable + * + * @note Wear levelling is not used when FAT is mounted in read-only mode using this function. + * + * @param base_path path where FATFS partition should be mounted (e.g. "/spiflash") + * @param partition_label label of the partition which should be used + * @param mount_config pointer to structure with extra parameters for mounting FATFS + * @return + * - ESP_OK on success + * - ESP_ERR_NOT_FOUND if the partition table does not contain FATFS partition with given label + * - ESP_ERR_INVALID_STATE if esp_vfs_fat_rawflash_mount was already called for the same partition + * - ESP_ERR_NO_MEM if memory can not be allocated + * - ESP_FAIL if partition can not be mounted + * - other error codes from SPI flash driver, or FATFS drivers + */ +esp_err_t esp_vfs_fat_rawflash_mount(const char* base_path, + const char* partition_label, + const esp_vfs_fat_mount_config_t* mount_config); + +/** + * @brief Unmount FAT filesystem and release resources acquired using esp_vfs_fat_rawflash_mount + * + * @param base_path path where partition should be registered (e.g. "/spiflash") + * @param partition_label label of partition to be unmounted + * + * @return + * - ESP_OK on success + * - ESP_ERR_INVALID_STATE if esp_vfs_fat_spiflash_mount hasn't been called + */ + esp_err_t esp_vfs_fat_rawflash_unmount(const char* base_path, const char* partition_label); + + #ifdef __cplusplus } #endif diff --git a/components/fatfs/src/ff.c b/components/fatfs/src/ff.c index 992a4ef1a6..4225a044ce 100644 --- a/components/fatfs/src/ff.c +++ b/components/fatfs/src/ff.c @@ -4694,7 +4694,6 @@ FRESULT f_truncate ( FATFS *fs; DWORD ncl; - res = validate(&fp->obj, &fs); /* Check validity of the file object */ if (res != FR_OK || (res = (FRESULT)fp->err) != FR_OK) LEAVE_FF(fs, res); if (!(fp->flag & FA_WRITE)) LEAVE_FF(fs, FR_DENIED); /* Check access mode */ diff --git a/components/fatfs/src/vfs_fat.c b/components/fatfs/src/vfs_fat.c index 9a1450c794..6d7019a1e2 100644 --- a/components/fatfs/src/vfs_fat.c +++ b/components/fatfs/src/vfs_fat.c @@ -85,6 +85,7 @@ static int vfs_fat_closedir(void* ctx, DIR* pdir); static int vfs_fat_mkdir(void* ctx, const char* name, mode_t mode); static int vfs_fat_rmdir(void* ctx, const char* name); static int vfs_fat_access(void* ctx, const char *path, int amode); +static int vfs_fat_truncate(void* ctx, const char *path, off_t length); static vfs_fat_ctx_t* s_fat_ctxs[FF_VOLUMES] = { NULL, NULL }; //backwards-compatibility with esp_vfs_fat_unregister() @@ -144,6 +145,7 @@ esp_err_t esp_vfs_fat_register(const char* base_path, const char* fat_drive, siz .mkdir_p = &vfs_fat_mkdir, .rmdir_p = &vfs_fat_rmdir, .access_p = &vfs_fat_access, + .truncate_p = &vfs_fat_truncate, }; size_t ctx_size = sizeof(vfs_fat_ctx_t) + max_files * sizeof(FIL); vfs_fat_ctx_t* fat_ctx = (vfs_fat_ctx_t*) calloc(1, ctx_size); @@ -751,3 +753,74 @@ static int vfs_fat_access(void* ctx, const char *path, int amode) return ret; } + +static int vfs_fat_truncate(void* ctx, const char *path, off_t length) +{ + FRESULT res; + FIL* file; + + int ret = 0; + + vfs_fat_ctx_t* fat_ctx = (vfs_fat_ctx_t*) ctx; + + _lock_acquire(&fat_ctx->lock); + prepend_drive_to_path(fat_ctx, &path, NULL); + + file = (FIL*) calloc(1, sizeof(FIL)); + if (file == NULL) { + ESP_LOGD(TAG, "truncate alloc failed"); + errno = ENOMEM; + ret = -1; + goto out; + } + + res = f_open(file, path, FA_WRITE); + + if (res != FR_OK) { + ESP_LOGD(TAG, "%s: fresult=%d", __func__, res); + errno = fresult_to_errno(res); + ret = -1; + goto out; + } + + res = f_size(file); + + if (res < length) { + ESP_LOGD(TAG, "truncate does not support extending size"); + errno = EPERM; + ret = -1; + goto close; + } + + res = f_lseek(file, length); + if (res != FR_OK) { + ESP_LOGD(TAG, "%s: fresult=%d", __func__, res); + errno = fresult_to_errno(res); + ret = -1; + goto close; + } + + res = f_truncate(file); + + if (res != FR_OK) { + ESP_LOGD(TAG, "%s: fresult=%d", __func__, res); + errno = fresult_to_errno(res); + ret = -1; + } + +close: + res = f_close(file); + + if (res != FR_OK) { + ESP_LOGE(TAG, "closing file opened for truncate failed"); + // Overwrite previous errors, since not being able to close + // an opened file is a more critical issue. + errno = fresult_to_errno(res); + ret = -1; + } + +out: + free(file); + _lock_release(&fat_ctx->lock); + return ret; +} diff --git a/components/fatfs/src/vfs_fat_spiflash.c b/components/fatfs/src/vfs_fat_spiflash.c index b676ed3a59..15bbd61273 100644 --- a/components/fatfs/src/vfs_fat_spiflash.c +++ b/components/fatfs/src/vfs_fat_spiflash.c @@ -20,8 +20,10 @@ #include "vfs_fat_internal.h" #include "diskio.h" +#include "diskio_rawflash.h" + #include "wear_levelling.h" -#include "diskio_spiflash.h" +#include "diskio_wl.h" static const char *TAG = "vfs_fat_spiflash"; esp_err_t esp_vfs_fat_spiflash_mount(const char* base_path, @@ -128,3 +130,78 @@ esp_err_t esp_vfs_fat_spiflash_unmount(const char *base_path, wl_handle_t wl_han if (err == ESP_OK) err = err_drv; return err; } + +esp_err_t esp_vfs_fat_rawflash_mount(const char* base_path, + const char* partition_label, + const esp_vfs_fat_mount_config_t* mount_config) +{ + esp_err_t result = ESP_OK; + + const esp_partition_t *data_partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, + ESP_PARTITION_SUBTYPE_DATA_FAT, partition_label); + if (data_partition == NULL) { + ESP_LOGE(TAG, "Failed to find FATFS partition (type='data', subtype='fat', partition_label='%s'). Check the partition table.", partition_label); + return ESP_ERR_NOT_FOUND; + } + + // connect driver to FATFS + BYTE pdrv = 0xFF; + if (ff_diskio_get_drive(&pdrv) != ESP_OK) { + ESP_LOGD(TAG, "the maximum count of volumes is already mounted"); + return ESP_ERR_NO_MEM; + } + ESP_LOGD(TAG, "using pdrv=%i", pdrv); + char drv[3] = {(char)('0' + pdrv), ':', 0}; + + result = ff_diskio_register_raw_partition(pdrv, data_partition); + if (result != ESP_OK) { + ESP_LOGE(TAG, "ff_diskio_register_raw_partition failed pdrv=%i, error - 0x(%x)", pdrv, result); + goto fail; + } + + FATFS *fs; + result = esp_vfs_fat_register(base_path, drv, mount_config->max_files, &fs); + if (result == ESP_ERR_INVALID_STATE) { + // it's okay, already registered with VFS + } else if (result != ESP_OK) { + ESP_LOGD(TAG, "esp_vfs_fat_register failed 0x(%x)", result); + goto fail; + } + + // Try to mount partition + FRESULT fresult = f_mount(fs, drv, 1); + if (fresult != FR_OK) { + ESP_LOGW(TAG, "f_mount failed (%d)", fresult); + result = ESP_FAIL; + goto fail; + } + return ESP_OK; + +fail: + esp_vfs_fat_unregister_path(base_path); + ff_diskio_unregister(pdrv); + return result; +} + + +esp_err_t esp_vfs_fat_rawflash_unmount(const char *base_path, const char* partition_label) +{ + const esp_partition_t *data_partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, + ESP_PARTITION_SUBTYPE_DATA_FAT, partition_label); + + if (data_partition == NULL) { + ESP_LOGE(TAG, "Failed to find FATFS partition (type='data', subtype='fat', partition_label='%s'). Check the partition table.", partition_label); + return ESP_ERR_NOT_FOUND; + } + + BYTE pdrv = ff_diskio_get_pdrv_raw(data_partition); + if (pdrv == 0xff) { + return ESP_ERR_INVALID_STATE; + } + char drv[3] = {(char)('0' + pdrv), ':', 0}; + + f_mount(0, drv, 0); + ff_diskio_unregister(pdrv); + esp_err_t err = esp_vfs_fat_unregister_path(base_path); + return err; +} diff --git a/components/fatfs/test/component.mk b/components/fatfs/test/component.mk index ce464a212a..c7e0582205 100644 --- a/components/fatfs/test/component.mk +++ b/components/fatfs/test/component.mk @@ -1 +1,2 @@ COMPONENT_ADD_LDFLAGS = -Wl,--whole-archive -l$(COMPONENT_NAME) -Wl,--no-whole-archive +COMPONENT_EMBED_TXTFILES := fatfs.img diff --git a/components/fatfs/test/fatfs.img b/components/fatfs/test/fatfs.img new file mode 100644 index 0000000000..d602cc782c Binary files /dev/null and b/components/fatfs/test/fatfs.img differ diff --git a/components/fatfs/test/test_fatfs_common.c b/components/fatfs/test/test_fatfs_common.c index 7390a7475f..0e84794157 100644 --- a/components/fatfs/test/test_fatfs_common.c +++ b/components/fatfs/test/test_fatfs_common.c @@ -18,6 +18,7 @@ #include #include #include +#include #include "unity.h" #include "esp_log.h" #include "esp_system.h" @@ -137,6 +138,81 @@ void test_fatfs_lseek(const char* filename) TEST_ASSERT_EQUAL(0, fclose(f)); } +void test_fatfs_truncate_file(const char* filename) +{ + int read = 0; + int truncated_len = 0; + + const char input[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + char output[sizeof(input)]; + + FILE* f = fopen(filename, "wb"); + + TEST_ASSERT_NOT_NULL(f); + TEST_ASSERT_EQUAL(strlen(input), fprintf(f, input)); + + TEST_ASSERT_EQUAL(0, fclose(f)); + + + // Extending file beyond size is not supported + TEST_ASSERT_EQUAL(-1, truncate(filename, strlen(input) + 1)); + TEST_ASSERT_EQUAL(errno, EPERM); + + TEST_ASSERT_EQUAL(-1, truncate(filename, -1)); + TEST_ASSERT_EQUAL(errno, EPERM); + + + // Truncating should succeed + const char truncated_1[] = "ABCDEFGHIJ"; + truncated_len = strlen(truncated_1); + + TEST_ASSERT_EQUAL(0, truncate(filename, truncated_len)); + + f = fopen(filename, "rb"); + TEST_ASSERT_NOT_NULL(f); + + memset(output, 0, sizeof(output)); + read = fread(output, 1, sizeof(output), f); + + TEST_ASSERT_EQUAL(truncated_len, read); + TEST_ASSERT_EQUAL_STRING_LEN(truncated_1, output, truncated_len); + + TEST_ASSERT_EQUAL(0, fclose(f)); + + + // Once truncated, the new file size should be the basis + // whether truncation should succeed or not + TEST_ASSERT_EQUAL(-1, truncate(filename, truncated_len + 1)); + TEST_ASSERT_EQUAL(EPERM, errno); + + TEST_ASSERT_EQUAL(-1, truncate(filename, strlen(input))); + TEST_ASSERT_EQUAL(EPERM, errno); + + TEST_ASSERT_EQUAL(-1, truncate(filename, strlen(input) + 1)); + TEST_ASSERT_EQUAL(EPERM, errno); + + TEST_ASSERT_EQUAL(-1, truncate(filename, -1)); + TEST_ASSERT_EQUAL(EPERM, errno); + + + // Truncating a truncated file should succeed + const char truncated_2[] = "ABCDE"; + truncated_len = strlen(truncated_2); + + TEST_ASSERT_EQUAL(0, truncate(filename, truncated_len)); + + f = fopen(filename, "rb"); + TEST_ASSERT_NOT_NULL(f); + + memset(output, 0, sizeof(output)); + read = fread(output, 1, sizeof(output), f); + + TEST_ASSERT_EQUAL(truncated_len, read); + TEST_ASSERT_EQUAL_STRING_LEN(truncated_2, output, truncated_len); + + TEST_ASSERT_EQUAL(0, fclose(f)); +} + void test_fatfs_stat(const char* filename, const char* root_dir) { struct tm tm; diff --git a/components/fatfs/test/test_fatfs_common.h b/components/fatfs/test/test_fatfs_common.h index ba7fbfcbb5..e5511ec434 100644 --- a/components/fatfs/test/test_fatfs_common.h +++ b/components/fatfs/test/test_fatfs_common.h @@ -30,7 +30,6 @@ } \ } while(0) - const char* fatfs_test_hello_str; const char* fatfs_test_hello_str_utf; @@ -46,6 +45,8 @@ void test_fatfs_open_max_files(const char* filename_prefix, size_t files_count); void test_fatfs_lseek(const char* filename); +void test_fatfs_truncate_file(const char* path); + void test_fatfs_stat(const char* filename, const char* root_dir); void test_fatfs_unlink(const char* filename); @@ -63,3 +64,4 @@ void test_fatfs_opendir_readdir_rewinddir(const char* dir_prefix); void test_fatfs_opendir_readdir_rewinddir_utf_8(const char* dir_prefix); void test_fatfs_rw_speed(const char* filename, void* buf, size_t buf_size, size_t file_size, bool write); + diff --git a/components/fatfs/test/test_fatfs_rawflash.c b/components/fatfs/test/test_fatfs_rawflash.c new file mode 100644 index 0000000000..5e60bb2965 --- /dev/null +++ b/components/fatfs/test/test_fatfs_rawflash.c @@ -0,0 +1,341 @@ +// 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. + +#include +#include +#include +#include +#include +#include +#include "unity.h" +#include "test_utils.h" +#include "esp_log.h" +#include "esp_system.h" +#include "esp_vfs.h" +#include "esp_vfs_fat.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "test_fatfs_common.h" +#include "esp_partition.h" +#include "ff.h" + + +static void test_setup(size_t max_files) +{ + extern const char fatfs_start[] asm("_binary_fatfs_img_start"); + extern const char fatfs_end[] asm("_binary_fatfs_img_end"); + esp_vfs_fat_sdmmc_mount_config_t mount_config = { + .format_if_mount_failed = false, + .max_files = max_files + }; + const esp_partition_t* part = get_test_data_partition(); + + TEST_ASSERT(part->size == (fatfs_end - fatfs_start - 1)); + + esp_partition_erase_range(part, 0, part->size); + for (int i = 0; i < part->size; i+= SPI_FLASH_SEC_SIZE) { + ESP_ERROR_CHECK( esp_partition_write(part, i, fatfs_start + i, SPI_FLASH_SEC_SIZE) ); + } + + TEST_ESP_OK(esp_vfs_fat_rawflash_mount("/spiflash", "flash_test", &mount_config)); +} + +static void test_teardown() +{ + TEST_ESP_OK(esp_vfs_fat_rawflash_unmount("/spiflash","flash_test")); +} + +TEST_CASE("(raw) can read file", "[fatfs]") +{ + test_setup(5); + FILE* f = fopen("/spiflash/hello.txt", "r"); + TEST_ASSERT_NOT_NULL(f); + char buf[32] = { 0 }; + int cb = fread(buf, 1, sizeof(buf), f); + TEST_ASSERT_EQUAL(strlen(fatfs_test_hello_str), cb); + TEST_ASSERT_EQUAL(0, strcmp(fatfs_test_hello_str, buf)); + TEST_ASSERT_EQUAL(0, fclose(f)); + test_teardown(); +} + +TEST_CASE("(raw) can open maximum number of files", "[fatfs]") +{ + size_t max_files = FOPEN_MAX - 3; /* account for stdin, stdout, stderr */ + test_setup(max_files); + + FILE** files = calloc(max_files, sizeof(FILE*)); + for (size_t i = 0; i < max_files; ++i) { + char name[32]; + snprintf(name, sizeof(name), "/spiflash/f/%d.txt", i + 1); + files[i] = fopen(name, "r"); + TEST_ASSERT_NOT_NULL(files[i]); + } + /* close everything and clean up */ + for (size_t i = 0; i < max_files; ++i) { + fclose(files[i]); + } + free(files); + test_teardown(); + +} + + +TEST_CASE("(raw) can lseek", "[fatfs]") +{ + test_setup(5); + FILE* f = fopen("/spiflash/hello.txt", "r"); + TEST_ASSERT_NOT_NULL(f); + TEST_ASSERT_EQUAL(0, fseek(f, 2, SEEK_CUR)); + TEST_ASSERT_EQUAL('l', fgetc(f)); + TEST_ASSERT_EQUAL(0, fseek(f, 4, SEEK_SET)); + TEST_ASSERT_EQUAL('o', fgetc(f)); + TEST_ASSERT_EQUAL(0, fseek(f, -5, SEEK_END)); + TEST_ASSERT_EQUAL('r', fgetc(f)); + TEST_ASSERT_EQUAL(0, fseek(f, 3, SEEK_END)); + TEST_ASSERT_EQUAL(17, ftell(f)); + + TEST_ASSERT_EQUAL(0, fseek(f, 0, SEEK_END)); + TEST_ASSERT_EQUAL(14, ftell(f)); + TEST_ASSERT_EQUAL(0, fseek(f, 0, SEEK_SET)); + test_teardown(); +} + +TEST_CASE("(raw) stat returns correct values", "[fatfs]") +{ + test_setup(5); + struct tm tm; + tm.tm_year = 2018 - 1900; + tm.tm_mon = 5; // Note: month can be 0-11 & not 1-12 + tm.tm_mday = 13; + tm.tm_hour = 11; + tm.tm_min = 2; + tm.tm_sec = 10; + time_t t = mktime(&tm); + printf("Reference time: %s", asctime(&tm)); + + struct stat st; + TEST_ASSERT_EQUAL(0, stat("/spiflash/stat.txt", &st)); + + time_t mtime = st.st_mtime; + struct tm mtm; + localtime_r(&mtime, &mtm); + printf("File time: %s", asctime(&mtm)); + TEST_ASSERT(mtime > t); // Modification time should be in future wrt ref time + + TEST_ASSERT(st.st_mode & S_IFREG); + TEST_ASSERT_FALSE(st.st_mode & S_IFDIR); + + memset(&st, 0, sizeof(st)); + TEST_ASSERT_EQUAL(0, stat("/spiflash", &st)); + TEST_ASSERT(st.st_mode & S_IFDIR); + TEST_ASSERT_FALSE(st.st_mode & S_IFREG); + + test_teardown(); +} + + + +TEST_CASE("(raw) can opendir root directory of FS", "[fatfs]") +{ + test_setup(5); + DIR* dir = opendir("/spiflash"); + TEST_ASSERT_NOT_NULL(dir); + bool found = false; + while (true) { + struct dirent* de = readdir(dir); + if (!de) { + break; + } + if (strcasecmp(de->d_name, "test_opd.txt") == 0) { + found = true; + break; + } + } + TEST_ASSERT_TRUE(found); + TEST_ASSERT_EQUAL(0, closedir(dir)); + + test_teardown(); +} +TEST_CASE("(raw) opendir, readdir, rewinddir, seekdir work as expected", "[fatfs]") +{ + test_setup(5); + + DIR* dir = opendir("/spiflash/dir"); + TEST_ASSERT_NOT_NULL(dir); + int count = 0; + const char* names[4]; + while(count < 4) { + struct dirent* de = readdir(dir); + if (!de) { + break; + } + printf("found '%s'\n", de->d_name); + if (strcasecmp(de->d_name, "1.txt") == 0) { + TEST_ASSERT_TRUE(de->d_type == DT_REG); + names[count] = "1.txt"; + ++count; + } else if (strcasecmp(de->d_name, "2.txt") == 0) { + TEST_ASSERT_TRUE(de->d_type == DT_REG); + names[count] = "2.txt"; + ++count; + } else if (strcasecmp(de->d_name, "inner") == 0) { + TEST_ASSERT_TRUE(de->d_type == DT_DIR); + names[count] = "inner"; + ++count; + } else if (strcasecmp(de->d_name, "boo.bin") == 0) { + TEST_ASSERT_TRUE(de->d_type == DT_REG); + names[count] = "boo.bin"; + ++count; + } else { + TEST_FAIL_MESSAGE("unexpected directory entry"); + } + } + TEST_ASSERT_EQUAL(count, 4); + + rewinddir(dir); + struct dirent* de = readdir(dir); + TEST_ASSERT_NOT_NULL(de); + TEST_ASSERT_EQUAL(0, strcasecmp(de->d_name, names[0])); + seekdir(dir, 3); + de = readdir(dir); + TEST_ASSERT_NOT_NULL(de); + TEST_ASSERT_EQUAL(0, strcasecmp(de->d_name, names[3])); + seekdir(dir, 1); + de = readdir(dir); + TEST_ASSERT_NOT_NULL(de); + TEST_ASSERT_EQUAL(0, strcasecmp(de->d_name, names[1])); + seekdir(dir, 2); + de = readdir(dir); + TEST_ASSERT_NOT_NULL(de); + TEST_ASSERT_EQUAL(0, strcasecmp(de->d_name, names[2])); + + TEST_ASSERT_EQUAL(0, closedir(dir)); + + test_teardown(); +} + + +typedef struct { + const char* filename; + size_t word_count; + int seed; + int val; + SemaphoreHandle_t done; + int result; +} read_test_arg_t; + +#define READ_TEST_ARG_INIT(name, seed_, val_) \ + { \ + .filename = name, \ + .seed = seed_, \ + .word_count = 8000, \ + .val = val_, \ + .done = xSemaphoreCreateBinary() \ + } + +static void read_task(void* param) +{ + read_test_arg_t* args = (read_test_arg_t*) param; + FILE* f = fopen(args->filename, "rb"); + if (f == NULL) { + args->result = ESP_ERR_NOT_FOUND; + goto done; + } + + srand(args->seed); + for (size_t i = 0; i < args->word_count; ++i) { + uint32_t rval; + int cnt = fread(&rval, sizeof(rval), 1, f); + if (cnt != 1 || rval != args->val) { + ets_printf("E(r): i=%d, cnt=%d rval=%d val=%d\n\n", i, cnt, rval, args->val); + args->result = ESP_FAIL; + goto close; + } + } + args->result = ESP_OK; + +close: + fclose(f); + +done: + xSemaphoreGive(args->done); + vTaskDelay(1); + vTaskDelete(NULL); +} + + +TEST_CASE("(raw) multiple tasks can use same volume", "[fatfs]") +{ + test_setup(5); + char names[4][64]; + for (size_t i = 0; i < 4; ++i) { + snprintf(names[i], sizeof(names[i]), "/spiflash/ccrnt/%d.txt", i + 1); + } + + read_test_arg_t args1 = READ_TEST_ARG_INIT(names[0], 1, 0x31313131); + read_test_arg_t args2 = READ_TEST_ARG_INIT(names[1], 2, 0x32323232); + read_test_arg_t args3 = READ_TEST_ARG_INIT(names[2], 3, 0x33333333); + read_test_arg_t args4 = READ_TEST_ARG_INIT(names[3], 4, 0x34343434); + + const int cpuid_0 = 0; + const int cpuid_1 = portNUM_PROCESSORS - 1; + const int stack_size = 4096; + + printf("reading files 1.txt 2.txt 3.txt 4.txt \n"); + + xTaskCreatePinnedToCore(&read_task, "r1", stack_size, &args1, 3, NULL, cpuid_1); + xTaskCreatePinnedToCore(&read_task, "r2", stack_size, &args2, 3, NULL, cpuid_0); + xTaskCreatePinnedToCore(&read_task, "r3", stack_size, &args3, 3, NULL, cpuid_0); + xTaskCreatePinnedToCore(&read_task, "r4", stack_size, &args4, 3, NULL, cpuid_1); + + xSemaphoreTake(args1.done, portMAX_DELAY); + printf("1.txt done\n"); + TEST_ASSERT_EQUAL(ESP_OK, args1.result); + xSemaphoreTake(args2.done, portMAX_DELAY); + printf("2.txt done\n"); + TEST_ASSERT_EQUAL(ESP_OK, args2.result); + xSemaphoreTake(args3.done, portMAX_DELAY); + printf("3.txt done\n"); + TEST_ASSERT_EQUAL(ESP_OK, args3.result); + xSemaphoreTake(args4.done, portMAX_DELAY); + printf("4.txt done\n"); + TEST_ASSERT_EQUAL(ESP_OK, args4.result); + + vSemaphoreDelete(args1.done); + vSemaphoreDelete(args2.done); + vSemaphoreDelete(args3.done); + vSemaphoreDelete(args4.done); + test_teardown(); +} + +TEST_CASE("(raw) write/read speed test", "[fatfs][timeout=60]") +{ + /* Erase partition before running the test to get consistent results */ + const esp_partition_t* part = get_test_data_partition(); + esp_partition_erase_range(part, 0, part->size); + + test_setup(5); + + const size_t buf_size = 16 * 1024; + uint32_t* buf = (uint32_t*) calloc(1, buf_size); + const size_t file_size = 256 * 1024; + const char* file = "/spiflash/256k.bin"; + + test_fatfs_rw_speed(file, buf, 4 * 1024, file_size, false); + test_fatfs_rw_speed(file, buf, 8 * 1024, file_size, false); + test_fatfs_rw_speed(file, buf, 16 * 1024, file_size, false); + + free(buf); + test_teardown(); +} diff --git a/components/fatfs/test/test_fatfs_sdmmc.c b/components/fatfs/test/test_fatfs_sdmmc.c index c813022071..c523c0e0ea 100644 --- a/components/fatfs/test/test_fatfs_sdmmc.c +++ b/components/fatfs/test/test_fatfs_sdmmc.c @@ -95,7 +95,6 @@ TEST_CASE("(SD) overwrite and append file", "[fatfs][sd][test_env=UT_T1_SDMODE]" test_teardown(); } - TEST_CASE("(SD) can lseek", "[fatfs][sd][test_env=UT_T1_SDMODE]") { test_setup(); @@ -103,6 +102,13 @@ TEST_CASE("(SD) can lseek", "[fatfs][sd][test_env=UT_T1_SDMODE]") test_teardown(); } +TEST_CASE("(SD) can truncate", "[fatfs][sd][test_env=UT_T1_SDMODE]") +{ + 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_setup(); diff --git a/components/fatfs/test/test_fatfs_spiflash.c b/components/fatfs/test/test_fatfs_spiflash.c index 70f73f0e53..38ea765ddc 100644 --- a/components/fatfs/test/test_fatfs_spiflash.c +++ b/components/fatfs/test/test_fatfs_spiflash.c @@ -96,6 +96,13 @@ TEST_CASE("(WL) can lseek", "[fatfs][wear_levelling]") test_teardown(); } +TEST_CASE("(WL) can truncate", "[fatfs][wear_levelling]") +{ + test_setup(); + test_fatfs_truncate_file("/spiflash/truncate.txt"); + test_teardown(); +} + TEST_CASE("(WL) stat returns correct values", "[fatfs][wear_levelling]") { test_setup(); diff --git a/components/fatfs/test_fatfs_host/Makefile b/components/fatfs/test_fatfs_host/Makefile new file mode 100644 index 0000000000..94d5c49ba1 --- /dev/null +++ b/components/fatfs/test_fatfs_host/Makefile @@ -0,0 +1,103 @@ +COMPONENT=fatfs + +TEST_PROGRAM=test_$(COMPONENT) + +#Expose as a library +COMPONENT_LIB=lib$(COMPONENT).a + +#Use wear levelling and flash simulation +WEAR_LEVELLING=wear_levelling +WEAR_LEVELLING_DIR=../../$(WEAR_LEVELLING) +WEAR_LEVELLING_HOST_DIR=$(WEAR_LEVELLING_DIR)/test_wl_host +WEAR_LEVELLING_LIB=lib$(WEAR_LEVELLING).a + +SPI_FLASH=spi_flash +SPI_FLASH_DIR=../../$(SPI_FLASH) +SPI_FLASH_SIM_DIR=$(SPI_FLASH_DIR)/sim +SPI_FLASH_LIB=lib$(SPI_FLASH).a + +all: $(TEST_PROGRAM) + +SOURCE_FILES = \ + $(addprefix ../src/, \ + diskio.c \ + ff.c \ + ffsystem.c \ + ffunicode.c \ + diskio_wl.c \ + ) \ + $(addprefix ./stubs/, log/log.c) + +TEST_SOURCE_FILES = \ + test_fatfs.cpp \ + main.cpp \ + test_utils.c + +INCLUDE_FLAGS = $(addprefix -I,\ + ../src \ + . \ + $(addprefix ./stubs/, \ + driver/include \ + freertos/include \ + sdmmc/include \ + log/include \ + ) \ + $(SPI_FLASH_DIR)/include \ + $(WEAR_LEVELLING_DIR)/include \ + ../../esp32/include \ + ../../../tools/catch \ +) + +GCOV ?= gcov + +CPPFLAGS += $(INCLUDE_FLAGS) -D CONFIG_LOG_DEFAULT_LEVEL -g -m32 +CFLAGS += -fprofile-arcs -ftest-coverage +CXXFLAGS += -std=c++11 -Wall -Werror -fprofile-arcs -ftest-coverage +LDFLAGS += -lstdc++ -fprofile-arcs -ftest-coverage + +OBJ_FILES = $(filter %.o, $(SOURCE_FILES:.cpp=.o) $(SOURCE_FILES:.c=.o)) +TEST_OBJ_FILES = $(filter %.o, $(TEST_SOURCE_FILES:.cpp=.o) $(TEST_SOURCE_FILES:.c=.o)) + +$(WEAR_LEVELLING_HOST_DIR)/$(WEAR_LEVELLING_LIB): force + $(MAKE) -C $(WEAR_LEVELLING_HOST_DIR) lib + +$(SPI_FLASH_SIM_DIR)/$(SPI_FLASH_LIB): force + $(MAKE) -C $(SPI_FLASH_SIM_DIR) lib + +force: + +$(COMPONENT_LIB): $(OBJ_FILES) + $(AR) rcs $@ $^ + +lib: $(COMPONENT_LIB) + +partition_table.bin: partition_table.csv + python ../../partition_table/gen_esp32part.py --verify $< $@ + +$(TEST_PROGRAM): lib $(TEST_OBJ_FILES) $(SPI_FLASH_SIM_DIR)/$(SPI_FLASH_LIB) $(WEAR_LEVELLING_HOST_DIR)/$(WEAR_LEVELLING_LIB) partition_table.bin + g++ $(LDFLAGS) -o $(TEST_PROGRAM) $(TEST_OBJ_FILES) -L$(abspath .) -l:$(COMPONENT_LIB) -L$(SPI_FLASH_SIM_DIR) -l:$(SPI_FLASH_LIB) -L$(WEAR_LEVELLING_HOST_DIR) -l:$(WEAR_LEVELLING_LIB) -g -m32 + +test: $(TEST_PROGRAM) + ./$(TEST_PROGRAM) + +COVERAGE_FILES = $(OBJ_FILES:.o=.gc*) $(TEST_OBJ_FILES:.o=.gc*) + +$(COVERAGE_FILES): test + +coverage.info: $(COVERAGE_FILES) + find ../ -name "*.gcno" -exec $(GCOV) -r -pb {} + + lcov --capture --directory ../ --no-external --output-file coverage.info --gcov-tool $(GCOV) + +coverage_report: coverage.info + genhtml coverage.info --output-directory coverage_report + @echo "Coverage report is in coverage_report/index.html" + +clean: + rm -f $(OBJ_FILES) $(TEST_OBJ_FILES) $(TEST_PROGRAM) $(COMPONENT_LIB) partition_table.bin + $(MAKE) -C $(WEAR_LEVELLING_HOST_DIR) clean + $(MAKE) -C $(SPI_FLASH_SIM_DIR) clean + rm -f $(COVERAGE_FILES) *.gcov + rm -rf coverage_report/ + rm -f coverage.info + +.PHONY: clean all test lib diff --git a/components/fatfs/test_fatfs_host/main.cpp b/components/fatfs/test_fatfs_host/main.cpp new file mode 100644 index 0000000000..0c7c351f43 --- /dev/null +++ b/components/fatfs/test_fatfs_host/main.cpp @@ -0,0 +1,2 @@ +#define CATCH_CONFIG_MAIN +#include "catch.hpp" diff --git a/components/fatfs/test_fatfs_host/partition_table.csv b/components/fatfs/test_fatfs_host/partition_table.csv new file mode 100644 index 0000000000..cb7fccd87b --- /dev/null +++ b/components/fatfs/test_fatfs_host/partition_table.csv @@ -0,0 +1,6 @@ +# Name, Type, SubType, Offset, Size, Flags +# Note: if you change the phy_init or app partition offset, make sure to change the offset in Kconfig.projbuild +nvs, data, nvs, 0x9000, 0x6000, +phy_init, data, phy, 0xf000, 0x1000, +factory, app, factory, 0x10000, 1M, +storage, data, fat, , 1M, \ No newline at end of file diff --git a/components/fatfs/test_fatfs_host/sdkconfig.h b/components/fatfs/test_fatfs_host/sdkconfig.h new file mode 100644 index 0000000000..b61f5811d1 --- /dev/null +++ b/components/fatfs/test_fatfs_host/sdkconfig.h @@ -0,0 +1,3 @@ +# pragma once + +#define CONFIG_WL_SECTOR_SIZE 4096 diff --git a/components/fatfs/test_fatfs_host/stubs/driver/include/driver/sdmmc_host.h b/components/fatfs/test_fatfs_host/stubs/driver/include/driver/sdmmc_host.h new file mode 100644 index 0000000000..2e68110374 --- /dev/null +++ b/components/fatfs/test_fatfs_host/stubs/driver/include/driver/sdmmc_host.h @@ -0,0 +1,6 @@ +#pragma once + +#include + +#include "sdmmc_types.h" + diff --git a/components/fatfs/test_fatfs_host/stubs/driver/include/driver/sdmmc_types.h b/components/fatfs/test_fatfs_host/stubs/driver/include/driver/sdmmc_types.h new file mode 100644 index 0000000000..22df97c5c0 --- /dev/null +++ b/components/fatfs/test_fatfs_host/stubs/driver/include/driver/sdmmc_types.h @@ -0,0 +1,11 @@ +#pragma once + +#if defined(__cplusplus) +extern "C" { +#endif + +typedef int sdmmc_card_t; + +#if defined(__cplusplus) +} +#endif \ No newline at end of file diff --git a/components/fatfs/test_fatfs_host/stubs/freertos/include/freertos/FreeRTOS.h b/components/fatfs/test_fatfs_host/stubs/freertos/include/freertos/FreeRTOS.h new file mode 100644 index 0000000000..5bafa772df --- /dev/null +++ b/components/fatfs/test_fatfs_host/stubs/freertos/include/freertos/FreeRTOS.h @@ -0,0 +1,4 @@ +#pragma once + +#include "projdefs.h" +#include "semphr.h" diff --git a/components/fatfs/test_fatfs_host/stubs/freertos/include/freertos/projdefs.h b/components/fatfs/test_fatfs_host/stubs/freertos/include/freertos/projdefs.h new file mode 100644 index 0000000000..aa8c7a3de5 --- /dev/null +++ b/components/fatfs/test_fatfs_host/stubs/freertos/include/freertos/projdefs.h @@ -0,0 +1,11 @@ +#pragma once + +#if defined(__cplusplus) +extern "C" { +#endif + +#define pdTRUE 1 + +#if defined(__cplusplus) +} +#endif diff --git a/components/fatfs/test_fatfs_host/stubs/freertos/include/freertos/semphr.h b/components/fatfs/test_fatfs_host/stubs/freertos/include/freertos/semphr.h new file mode 100644 index 0000000000..d49cafb99f --- /dev/null +++ b/components/fatfs/test_fatfs_host/stubs/freertos/include/freertos/semphr.h @@ -0,0 +1,16 @@ +#pragma once + +#if defined(__cplusplus) +extern "C" { +#endif + +#define vSemaphoreDelete( xSemaphore ) +#define xSemaphoreCreateMutex() ((void*)(1)) +#define xSemaphoreGive( xSemaphore ) +#define xSemaphoreTake( xSemaphore, xBlockTime ) pdTRUE + +typedef void* SemaphoreHandle_t; + +#if defined(__cplusplus) +} +#endif diff --git a/components/fatfs/test_fatfs_host/stubs/log/include/esp_log.h b/components/fatfs/test_fatfs_host/stubs/log/include/esp_log.h new file mode 100644 index 0000000000..f90501430e --- /dev/null +++ b/components/fatfs/test_fatfs_host/stubs/log/include/esp_log.h @@ -0,0 +1,45 @@ +#pragma once + +#include +#include + +#include "sdkconfig.h" + +#if defined(__cplusplus) +extern "C" { // Make sure we have C-declarations in C++ programs +#endif + +#define LOG_LOCAL_LEVEL ESP_LOG_DEBUG + +typedef enum { + ESP_LOG_NONE, /*!< No log output */ + ESP_LOG_ERROR, /*!< Critical errors, software module can not recover on its own */ + ESP_LOG_WARN, /*!< Error conditions from which recovery measures have been taken */ + ESP_LOG_INFO, /*!< Information messages which describe normal flow of events */ + ESP_LOG_DEBUG, /*!< Extra information which is not necessary for normal use (values, pointers, sizes, etc). */ + ESP_LOG_VERBOSE /*!< Bigger chunks of debugging information, or frequent messages which can potentially flood the output. */ +} esp_log_level_t; + +#define LOG_COLOR_E +#define LOG_COLOR_W +#define LOG_COLOR_I +#define LOG_COLOR_D +#define LOG_COLOR_V +#define LOG_RESET_COLOR + +uint32_t esp_log_timestamp(void); +void esp_log_write(esp_log_level_t level, const char* tag, const char* format, ...) __attribute__ ((format (printf, 3, 4))); + +#define LOG_FORMAT(letter, format) LOG_COLOR_ ## letter #letter " (%d) %s: " format LOG_RESET_COLOR "\n" + +#define ESP_LOGE( tag, format, ... ) if (LOG_LOCAL_LEVEL >= ESP_LOG_ERROR) { esp_log_write(ESP_LOG_ERROR, tag, LOG_FORMAT(E, format), esp_log_timestamp(), tag, ##__VA_ARGS__); } + +#define ESP_LOGV( tag, format, ... ) if (LOG_LOCAL_LEVEL >= ESP_LOG_VERBOSE) { esp_log_write(ESP_LOG_VERBOSE, tag, LOG_FORMAT(V, format), esp_log_timestamp(), tag, ##__VA_ARGS__); } + +#define ESP_LOGD( tag, format, ... ) if (LOG_LOCAL_LEVEL >= ESP_LOG_DEBUG) { esp_log_write(ESP_LOG_DEBUG, tag, LOG_FORMAT(D, format), esp_log_timestamp(), tag, ##__VA_ARGS__); } + +#define ESP_LOGW( tag, format, ... ) if (LOG_LOCAL_LEVEL >= ESP_LOG_WARN) { esp_log_write(ESP_LOG_WARN, tag, LOG_FORMAT(W, format), esp_log_timestamp(), tag, ##__VA_ARGS__); } + +#if defined(__cplusplus) +} +#endif \ No newline at end of file diff --git a/components/wear_levelling/test_wl_host/esp_log_stub.cpp b/components/fatfs/test_fatfs_host/stubs/log/log.c similarity index 87% rename from components/wear_levelling/test_wl_host/esp_log_stub.cpp rename to components/fatfs/test_fatfs_host/stubs/log/log.c index 87dd12a902..4f0c12bf82 100644 --- a/components/wear_levelling/test_wl_host/esp_log_stub.cpp +++ b/components/fatfs/test_fatfs_host/stubs/log/log.c @@ -1,4 +1,7 @@ #include +#include +#include + #include "esp_log.h" void esp_log_write(esp_log_level_t level, @@ -14,4 +17,4 @@ void esp_log_write(esp_log_level_t level, uint32_t esp_log_timestamp() { return 0; -} +} \ No newline at end of file diff --git a/components/fatfs/test_fatfs_host/stubs/sdmmc/include/sdmmc_cmd.h b/components/fatfs/test_fatfs_host/stubs/sdmmc/include/sdmmc_cmd.h new file mode 100644 index 0000000000..d68711a95f --- /dev/null +++ b/components/fatfs/test_fatfs_host/stubs/sdmmc/include/sdmmc_cmd.h @@ -0,0 +1,3 @@ +#pragma once + +#include "esp_err.h" diff --git a/components/fatfs/test_fatfs_host/test_fatfs.cpp b/components/fatfs/test_fatfs_host/test_fatfs.cpp new file mode 100644 index 0000000000..7d14df267b --- /dev/null +++ b/components/fatfs/test_fatfs_host/test_fatfs.cpp @@ -0,0 +1,93 @@ +#include +#include + +#include "ff.h" +#include "esp_partition.h" +#include "wear_levelling.h" +#include "diskio.h" +#include "diskio_wl.h" + +#include "catch.hpp" + +extern "C" void init_spi_flash(size_t chip_size, size_t block_size, size_t sector_size, size_t page_size, const char* partition_bin); + +TEST_CASE("create volume, open file, write and read back data", "[fatfs]") +{ + init_spi_flash(0x00400000, CONFIG_WL_SECTOR_SIZE * 16, CONFIG_WL_SECTOR_SIZE, CONFIG_WL_SECTOR_SIZE, "partition_table.bin"); + + FRESULT fr_result; + BYTE pdrv; + FATFS fs; + FIL file; + UINT bw; + + esp_err_t esp_result; + + const esp_partition_t *partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_FAT, "storage"); + + // Mount wear-levelled partition + wl_handle_t wl_handle; + esp_result = wl_mount(partition, &wl_handle); + REQUIRE(esp_result == ESP_OK); + + // Get a physical drive + esp_result = ff_diskio_get_drive(&pdrv); + REQUIRE(esp_result == ESP_OK); + + // Register physical drive as wear-levelled partition + esp_result = ff_diskio_register_wl_partition(pdrv, wl_handle); + + // Create FAT volume on the entire disk + DWORD part_list[] = {100, 0, 0, 0}; + BYTE work_area[FF_MAX_SS]; + + fr_result = f_fdisk(pdrv, part_list, work_area); + REQUIRE(fr_result == FR_OK); + fr_result = f_mkfs("", FM_ANY, 0, work_area, sizeof(work_area)); // Use default volume + + // Mount the volume + fr_result = f_mount(&fs, "", 0); + REQUIRE(fr_result == FR_OK); + + // Open, write and read data + fr_result = f_open(&file, "test.txt", FA_OPEN_ALWAYS | FA_READ | FA_WRITE); + REQUIRE(fr_result == FR_OK); + + // Generate data + uint32_t data_size = 100000; + + char *data = (char*) malloc(data_size); + char *read = (char*) malloc(data_size); + + for(uint32_t i = 0; i < data_size; i += sizeof(i)) + { + *((uint32_t*)(data + i)) = i; + } + + // Write generated data + fr_result = f_write(&file, data, data_size, &bw); + REQUIRE(fr_result == FR_OK); + REQUIRE(bw == data_size); + + // Move to beginning of file + fr_result = f_lseek(&file, 0); + REQUIRE(fr_result == FR_OK); + + // Read written data + fr_result = f_read(&file, read, data_size, &bw); + REQUIRE(fr_result == FR_OK); + REQUIRE(bw == data_size); + + REQUIRE(memcmp(data, read, data_size) == 0); + + // Close file + fr_result = f_close(&file); + REQUIRE(fr_result == FR_OK); + + // Unmount default volume + fr_result = f_mount(0, "", 0); + REQUIRE(fr_result == FR_OK); + + free(read); + free(data); +} diff --git a/components/fatfs/test_fatfs_host/test_utils.c b/components/fatfs/test_fatfs_host/test_utils.c new file mode 100644 index 0000000000..c3181ede75 --- /dev/null +++ b/components/fatfs/test_fatfs_host/test_utils.c @@ -0,0 +1,7 @@ +#include "esp_spi_flash.h" +#include "esp_partition.h" + +void init_spi_flash(size_t chip_size, size_t block_size, size_t sector_size, size_t page_size, const char* partition_bin) +{ + spi_flash_init(chip_size, block_size, sector_size, page_size, partition_bin); +} \ No newline at end of file diff --git a/components/freertos/CMakeLists.txt b/components/freertos/CMakeLists.txt index a0be8f0862..e0618d4a94 100644 --- a/components/freertos/CMakeLists.txt +++ b/components/freertos/CMakeLists.txt @@ -6,3 +6,13 @@ set(COMPONENT_REQUIRES) register_component() target_link_libraries(freertos "-Wl,--undefined=uxTopUsedPriority") + +set_source_files_properties( + tasks.c + event_groups.c + timers.c + queue.c + ringbuf.c + PROPERTIES COMPILE_DEFINITIONS + _ESP_FREERTOS_INTERNAL + ) diff --git a/components/freertos/component.mk b/components/freertos/component.mk index 7841d8f694..a10f84d800 100644 --- a/components/freertos/component.mk +++ b/components/freertos/component.mk @@ -5,3 +5,5 @@ COMPONENT_ADD_LDFLAGS += -Wl,--undefined=uxTopUsedPriority COMPONENT_ADD_INCLUDEDIRS := include COMPONENT_PRIV_INCLUDEDIRS := include/freertos + +tasks.o event_groups.o timers.o queue.o ringbuf.o: CFLAGS += -D_ESP_FREERTOS_INTERNAL diff --git a/components/freertos/include/freertos/portable.h b/components/freertos/include/freertos/portable.h index 9fe74b60c0..33b740e890 100644 --- a/components/freertos/include/freertos/portable.h +++ b/components/freertos/include/freertos/portable.h @@ -205,7 +205,7 @@ BaseType_t xPortInterruptedFromISRContext(); /* Multi-core: get current core ID */ static inline uint32_t IRAM_ATTR xPortGetCoreID() { int id; - asm ( + __asm__ ( "rsr.prid %0\n" " extui %0,%0,13,1" :"=r"(id)); diff --git a/components/freertos/include/freertos/portmacro.h b/components/freertos/include/freertos/portmacro.h index df5c071d17..6b98b82690 100644 --- a/components/freertos/include/freertos/portmacro.h +++ b/components/freertos/include/freertos/portmacro.h @@ -74,7 +74,6 @@ extern "C" { #include -#include #include #include #include /* required for XSHAL_CLIB */ diff --git a/components/freertos/include/freertos/task.h b/components/freertos/include/freertos/task.h index 5af62c69c6..ab605bb301 100644 --- a/components/freertos/include/freertos/task.h +++ b/components/freertos/include/freertos/task.h @@ -233,7 +233,11 @@ typedef enum * * \ingroup SchedulerControl */ +#ifdef _ESP_FREERTOS_INTERNAL #define taskENTER_CRITICAL(mux) portENTER_CRITICAL(mux) +#else +#define taskENTER_CRITICAL(mux) _Pragma("GCC warning \"'taskENTER_CRITICAL(mux)' is deprecated in ESP-IDF, consider using 'portENTER_CRITICAL(mux)'\"") portENTER_CRITICAL(mux) +#endif #define taskENTER_CRITICAL_ISR(mux) portENTER_CRITICAL_ISR(mux) /** @@ -247,7 +251,11 @@ typedef enum * * \ingroup SchedulerControl */ +#ifdef _ESP_FREERTOS_INTERNAL #define taskEXIT_CRITICAL(mux) portEXIT_CRITICAL(mux) +#else +#define taskEXIT_CRITICAL(mux) _Pragma("GCC warning \"'taskEXIT_CRITICAL(mux)' is deprecated in ESP-IDF, consider using 'portEXIT_CRITICAL(mux)'\"") portEXIT_CRITICAL(mux) +#endif #define taskEXIT_CRITICAL_ISR(mux) portEXIT_CRITICAL_ISR(mux) /** diff --git a/components/freertos/include/freertos/xtensa_rtos.h b/components/freertos/include/freertos/xtensa_rtos.h index e5982b83a5..25d42da59b 100644 --- a/components/freertos/include/freertos/xtensa_rtos.h +++ b/components/freertos/include/freertos/xtensa_rtos.h @@ -50,7 +50,6 @@ Should be included by all Xtensa generic and RTOS port-specific sources. #include #include -#include /* Include any RTOS specific definitions that are needed by this header. diff --git a/components/freertos/portmux_impl.inc.h b/components/freertos/portmux_impl.inc.h index 29bfbfc346..07a7ce9fe1 100644 --- a/components/freertos/portmux_impl.inc.h +++ b/components/freertos/portmux_impl.inc.h @@ -155,17 +155,15 @@ static inline void PORTMUX_RELEASE_MUX_FN_NAME(portMUX_TYPE *mux) { #endif assert(coreID == mux->owner); // This is a mutex we didn't lock, or it's corrupt - assert(mux->count > 0); // Indicates memory corruption - assert(mux->count < 0x100); // Indicates memory corruption mux->count--; if(mux->count == 0) { mux->owner = portMUX_FREE_VAL; - } + } else { + assert(mux->count < 0x100); // Indicates memory corruption #ifdef CONFIG_FREERTOS_PORTMUX_DEBUG_RECURSIVE - else { ets_printf("Recursive unlock: count=%d last locked %s line %d, curr %s line %d\n", mux->count, lastLockedFn, lastLockedLine, fnName, line); - } #endif + } #endif //!CONFIG_FREERTOS_UNICORE } diff --git a/components/freertos/queue.c b/components/freertos/queue.c index c5c02c1a98..a3a14931a6 100644 --- a/components/freertos/queue.c +++ b/components/freertos/queue.c @@ -2458,8 +2458,7 @@ Queue_t * const pxQueue = ( Queue_t * ) xQueue; { BaseType_t xReturn; -//ToDo: figure out locking -// taskENTER_CRITICAL(&pxQueue->mux); + taskENTER_CRITICAL(&(((Queue_t * )xQueueOrSemaphore)->mux)); { if( ( ( Queue_t * ) xQueueOrSemaphore )->pxQueueSetContainer != NULL ) { @@ -2478,7 +2477,7 @@ Queue_t * const pxQueue = ( Queue_t * ) xQueue; xReturn = pdPASS; } } -// taskEXIT_CRITICAL(&pxQueue->mux); + taskEXIT_CRITICAL(&(((Queue_t * )xQueueOrSemaphore)->mux)); return xReturn; } @@ -2507,12 +2506,12 @@ Queue_t * const pxQueue = ( Queue_t * ) xQueue; } else { -// taskENTER_CRITICAL(&pxQueue->mux); + taskENTER_CRITICAL(&(pxQueueOrSemaphore->mux)); { /* The queue is no longer contained in the set. */ pxQueueOrSemaphore->pxQueueSetContainer = NULL; } -// taskEXIT_CRITICAL(&pxQueue->mux); + taskEXIT_CRITICAL(&(pxQueueOrSemaphore->mux)); xReturn = pdPASS; } @@ -2555,9 +2554,15 @@ Queue_t * const pxQueue = ( Queue_t * ) xQueue; Queue_t *pxQueueSetContainer = pxQueue->pxQueueSetContainer; BaseType_t xReturn = pdFALSE; - /* This function must be called form a critical section. */ + /* + * This function is called with a Queue's / Semaphore's spinlock already + * acquired. Acquiring the Queue set's spinlock is still necessary. + */ configASSERT( pxQueueSetContainer ); + + //Acquire the Queue set's spinlock + portENTER_CRITICAL(&(pxQueueSetContainer->mux)); configASSERT( pxQueueSetContainer->uxMessagesWaiting < pxQueueSetContainer->uxLength ); if( pxQueueSetContainer->uxMessagesWaiting < pxQueueSetContainer->uxLength ) @@ -2588,6 +2593,9 @@ Queue_t * const pxQueue = ( Queue_t * ) xQueue; mtCOVERAGE_TEST_MARKER(); } + //Release the Queue set's spinlock + portEXIT_CRITICAL(&(pxQueueSetContainer->mux)); + return xReturn; } diff --git a/components/freertos/test/test_freertos_debug_functions.c b/components/freertos/test/test_freertos_debug_functions.c index 70c1b5b0cd..0a6e147359 100644 --- a/components/freertos/test/test_freertos_debug_functions.c +++ b/components/freertos/test/test_freertos_debug_functions.c @@ -16,7 +16,7 @@ #if (CONFIG_FREERTOS_QUEUE_REGISTRY_SIZE > 0) #define NO_OF_QUEUES_PER_CORE ((int)((CONFIG_FREERTOS_QUEUE_REGISTRY_SIZE - 3)/portNUM_PROCESSORS)) //Save space for some preallocated tasks #define NO_OF_QUEUES_TOTAL (NO_OF_QUEUES_PER_CORE * portNUM_PROCESSORS) -#define QUEUE_NAME_MAX_LENGTH 10 +#define QUEUE_NAME_MAX_LENGTH 30 static SemaphoreHandle_t start_sem[portNUM_PROCESSORS]; static SemaphoreHandle_t done_sem = NULL; diff --git a/components/freertos/test/test_queuesets.c b/components/freertos/test/test_queuesets.c new file mode 100644 index 0000000000..00e440d2e2 --- /dev/null +++ b/components/freertos/test/test_queuesets.c @@ -0,0 +1,137 @@ +#include +#include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/queue.h" +#include "freertos/semphr.h" +#include "unity.h" + +/* + * Basic queue set tests. Multiple queues are added to a queue set then each + * queue is filled in a sequential order. The members returned from the queue + * set must adhered to the order in which the queues were filled. + */ +#define NO_OF_QUEUES 5 +#define QUEUE_LEN 4 +#define ITEM_SIZE sizeof(uint32_t) + +static QueueHandle_t handles[NO_OF_QUEUES]; +static QueueSetHandle_t set_handle; + +TEST_CASE("Test Queue sets", "[freertos]") +{ + //Create queue set, queues, and add queues to queue set + set_handle = xQueueCreateSet(NO_OF_QUEUES * QUEUE_LEN); + for (int i = 0; i < NO_OF_QUEUES; i++) { + handles[i] = xQueueCreate(QUEUE_LEN, ITEM_SIZE); + TEST_ASSERT_MESSAGE(handles[i] != NULL, "Failed to create queue"); + TEST_ASSERT_MESSAGE(xQueueAddToSet(handles[i], set_handle) == pdPASS, "Failed to add to queue set"); + } + + //Fill queue set via filling each queue + for (int i = 0; i < NO_OF_QUEUES; i++) { + for (int j = 0; j < QUEUE_LEN; j++) { + uint32_t item_num = (i * QUEUE_LEN) + j; + TEST_ASSERT_MESSAGE(xQueueSendToBack(handles[i], &item_num, portMAX_DELAY) == pdTRUE, "Failed to send to queue"); + } + } + + //Check queue set is notified in correct order + for (int i = 0; i < NO_OF_QUEUES; i++) { + for (int j = 0; j < QUEUE_LEN; j++) { + QueueSetMemberHandle_t member = xQueueSelectFromSet(set_handle, portMAX_DELAY); + TEST_ASSERT_EQUAL_MESSAGE(handles[i], member, "Incorrect queue set member returned"); + uint32_t item; + xQueueReceive((QueueHandle_t)member, &item, 0); + TEST_ASSERT_EQUAL_MESSAGE(((i * QUEUE_LEN) + j), item, "Incorrect item value"); + } + } + + //Remove queues from queue set and delete queues + for (int i = 0; i < NO_OF_QUEUES; i++) { + TEST_ASSERT_MESSAGE(xQueueRemoveFromSet(handles[i], set_handle), "Failed to remove from queue set"); + vQueueDelete(handles[i]); + } + vQueueDelete(set_handle); +} + +/* + * Queue set thread safety test. Test the SMP thread safety by adding two queues + * to a queue set and have a task on each core send to the queues simultaneously. + * Check returned queue set members are valid. + */ +#ifndef CONFIG_FREERTOS_UNICORE +static volatile bool sync_flags[portNUM_PROCESSORS]; +static SemaphoreHandle_t sync_sem; + +static void send_task(void *arg) +{ + QueueHandle_t queue = (QueueHandle_t)arg; + + //Wait until task on the other core starts running + xSemaphoreTake(sync_sem, portMAX_DELAY); + sync_flags[xPortGetCoreID()] = true; + while (!sync_flags[!xPortGetCoreID()]) { + ; + } + + //Fill queue + for (int i = 0; i < QUEUE_LEN; i++) { + uint32_t item = i; + xQueueSendToBack(queue, &item, portMAX_DELAY); + } + + xSemaphoreGive(sync_sem); + vTaskDelete(NULL); +} + +TEST_CASE("Test Queue sets thread safety", "[freertos]") +{ + //Create queue set, queues, and a send task on each core + sync_sem = xSemaphoreCreateCounting(portNUM_PROCESSORS, 0); + QueueHandle_t queue_handles[portNUM_PROCESSORS]; + QueueSetHandle_t queueset_handle = xQueueCreateSet(portNUM_PROCESSORS * QUEUE_LEN); + for (int i = 0; i < portNUM_PROCESSORS; i++) { + sync_flags[i] = false; + queue_handles[i] = xQueueCreate(QUEUE_LEN, ITEM_SIZE); + TEST_ASSERT_MESSAGE(xQueueAddToSet(queue_handles[i], queueset_handle) == pdPASS, "Failed to add to queue set"); + xTaskCreatePinnedToCore(send_task, "send", 2048, (void *)queue_handles[i], 10, NULL, i); + } + + //Start both send tasks + portDISABLE_INTERRUPTS(); + for (int i = 0; i < portNUM_PROCESSORS; i++) { + xSemaphoreGive(sync_sem); + } + portENABLE_INTERRUPTS(); + vTaskDelay(2); + + //Check returned queue set members are valid + uint32_t expect_0 = 0; + uint32_t expect_1 = 0; + for (int i = 0; i < (portNUM_PROCESSORS * QUEUE_LEN); i++) { + QueueSetMemberHandle_t member = xQueueSelectFromSet(queueset_handle, portMAX_DELAY); + uint32_t item; + if (member == queue_handles[0]) { + xQueueReceive((QueueHandle_t)member, &item, 0); + TEST_ASSERT_EQUAL_MESSAGE(expect_0, item, "Incorrect item value"); + expect_0++; + } else if (member == queue_handles[1]) { + xQueueReceive((QueueHandle_t)member, &item, 0); + TEST_ASSERT_EQUAL_MESSAGE(expect_1, item, "Incorrect item value"); + expect_1++; + } else { + TEST_ASSERT_MESSAGE(0, "Incorrect queue set member returned"); + } + } + + for (int i = 0; i < portNUM_PROCESSORS; i++) { + xSemaphoreTake(sync_sem, portMAX_DELAY); + } + for (int i = 0; i < portNUM_PROCESSORS; i++) { + xQueueRemoveFromSet(queueset_handle, handles[i]); + vQueueDelete(queue_handles[i]); + } + vQueueDelete(queueset_handle); +} +#endif diff --git a/components/freertos/test/test_thread_local.c b/components/freertos/test/test_thread_local.c index d5f782b43c..b80c960fc3 100644 --- a/components/freertos/test/test_thread_local.c +++ b/components/freertos/test/test_thread_local.c @@ -87,7 +87,8 @@ static void task_test_tls(void *arg) TEST_CASE("TLS test", "[freertos]") { - static StackType_t s_stack[2048]; + const size_t stack_size = 3072; + StackType_t s_stack[stack_size]; /* with 8KB test task stack (default) this test still has ~3KB headroom */ StaticTask_t s_task; bool running[2] = {true, true}; #if CONFIG_FREERTOS_UNICORE == 0 @@ -96,10 +97,13 @@ TEST_CASE("TLS test", "[freertos]") int other_core = 0; #endif - xTaskCreatePinnedToCore((TaskFunction_t)&task_test_tls, "task_test_tls", 3072, &running[0], 5, NULL, 0); - xTaskCreateStaticPinnedToCore((TaskFunction_t)&task_test_tls, "task_test_tls", sizeof(s_stack), &running[1], - 5, s_stack, &s_task, other_core); + xTaskCreatePinnedToCore((TaskFunction_t)&task_test_tls, "task_test_tls", stack_size, &running[0], + UNITY_FREERTOS_PRIORITY, NULL, 0); + xTaskCreateStaticPinnedToCore((TaskFunction_t)&task_test_tls, "task_test_tls", stack_size, &running[1], + UNITY_FREERTOS_PRIORITY, s_stack, &s_task, other_core); while (running[0] || running[1]) { vTaskDelay(10); } + vTaskDelay(10); /* Make sure idle task can clean up s_task, before it goes out of scope */ } + diff --git a/components/heap/heap_private.h b/components/heap/heap_private.h index 5103cfd178..a8a0ac9fda 100644 --- a/components/heap/heap_private.h +++ b/components/heap/heap_private.h @@ -49,7 +49,7 @@ extern SLIST_HEAD(registered_heap_ll, heap_t_) registered_heaps; bool heap_caps_match(const heap_t *heap, uint32_t caps); /* return all possible capabilities (across all priorities) for a given heap */ -inline static uint32_t get_all_caps(const heap_t *heap) +inline static IRAM_ATTR uint32_t get_all_caps(const heap_t *heap) { if (heap->heap == NULL) { return 0; diff --git a/components/heap/multi_heap_poisoning.c b/components/heap/multi_heap_poisoning.c index 1fdf586aa3..aa50bc59e7 100644 --- a/components/heap/multi_heap_poisoning.c +++ b/components/heap/multi_heap_poisoning.c @@ -182,7 +182,8 @@ void *multi_heap_malloc(multi_heap_handle_t heap, size_t size) data = poison_allocated_region(head, size); #ifdef SLOW /* check everything we got back is FREE_FILL_PATTERN & swap for MALLOC_FILL_PATTERN */ - assert( verify_fill_pattern(data, size, true, true, true) ); + bool ret = verify_fill_pattern(data, size, true, true, true); + assert( ret ); #endif } diff --git a/components/heap/test/test_malloc_caps.c b/components/heap/test/test_malloc_caps.c index 0be5f6a6ca..950f18455c 100644 --- a/components/heap/test/test_malloc_caps.c +++ b/components/heap/test/test_malloc_caps.c @@ -9,6 +9,7 @@ #include "esp_heap_caps.h" #include "esp_spi_flash.h" #include +#include TEST_CASE("Capabilities allocator test", "[heap]") { @@ -38,18 +39,24 @@ TEST_CASE("Capabilities allocator test", "[heap]") TEST_ASSERT((((int)m1)&0xFF000000)==0x3F000000); free(m1); - printf("Freeing; allocating 10K of 32K-capable RAM\n"); - m1 = heap_caps_malloc(10*1024, MALLOC_CAP_32BIT); + //The goal here is to allocate from IRAM. Since there is no external IRAM (yet) + //the following gives size of IRAM-only (not D/IRAM) memory. + size_t free_iram = heap_caps_get_free_size(MALLOC_CAP_INTERNAL) - + heap_caps_get_free_size(MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL); + size_t alloc32 = MIN(free_iram / 2, 10*1024) & (~3); + printf("Freeing; allocating %u bytes of 32K-capable RAM\n", alloc32); + m1 = heap_caps_malloc(alloc32, MALLOC_CAP_32BIT); printf("--> %p\n", m1); + //Check that we got IRAM back + TEST_ASSERT((((int)m1)&0xFF000000)==0x40000000); free8 = heap_caps_get_free_size(MALLOC_CAP_8BIT); free32 = heap_caps_get_free_size(MALLOC_CAP_32BIT); printf("Free 8bit-capable memory (after 32-bit): %dK, 32-bit capable memory %dK\n", free8, free32); - //Only 32-bit should have gone down by 10K: 32-bit isn't necessarily 8bit capable - TEST_ASSERT(free32<(free32start-10*1024)); + //Only 32-bit should have gone down by alloc32: 32-bit isn't necessarily 8bit capable + TEST_ASSERT(free32<(free32start-alloc32)); TEST_ASSERT(free8==free8start); - //Assume we got IRAM back - TEST_ASSERT((((int)m1)&0xFF000000)==0x40000000); free(m1); + printf("Allocating impossible caps\n"); m1= heap_caps_malloc(10*1024, MALLOC_CAP_8BIT|MALLOC_CAP_EXEC); printf("--> %p\n", m1); @@ -57,14 +64,15 @@ TEST_CASE("Capabilities allocator test", "[heap]") printf("Testing changeover iram -> dram"); // priorities will exhaust IRAM first, then start allocating from DRAM for (x=0; x<10; x++) { - m2[x]= heap_caps_malloc(10*1024, MALLOC_CAP_32BIT); + m2[x]= heap_caps_malloc(alloc32, MALLOC_CAP_32BIT); printf("--> %p\n", m2[x]); } TEST_ASSERT((((int)m2[0])&0xFF000000)==0x40000000); TEST_ASSERT((((int)m2[9])&0xFF000000)==0x3F000000); printf("Test if allocating executable code still gives IRAM, even with dedicated IRAM region depleted\n"); // (the allocation should come from D/IRAM) - m1= heap_caps_malloc(10*1024, MALLOC_CAP_EXEC); + free_iram = heap_caps_get_free_size(MALLOC_CAP_EXEC); + m1= heap_caps_malloc(MIN(free_iram / 2, 10*1024), MALLOC_CAP_EXEC); printf("--> %p\n", m1); TEST_ASSERT((((int)m1)&0xFF000000)==0x40000000); free(m1); diff --git a/components/idf_test/include/idf_performance.h b/components/idf_test/include/idf_performance.h index f98f75c317..fc128eecbb 100644 --- a/components/idf_test/include/idf_performance.h +++ b/components/idf_test/include/idf_performance.h @@ -11,7 +11,7 @@ /* declare the performance here */ #define IDF_PERFORMANCE_MAX_HTTPS_REQUEST_BIN_SIZE 800 #define IDF_PERFORMANCE_MAX_FREERTOS_SPINLOCK_CYCLES_PER_OP 200 -#define IDF_PERFORMANCE_MAX_FREERTOS_SPINLOCK_CYCLES_PER_OP_PSRAM 270 +#define IDF_PERFORMANCE_MAX_FREERTOS_SPINLOCK_CYCLES_PER_OP_PSRAM 300 #define IDF_PERFORMANCE_MAX_FREERTOS_SPINLOCK_CYCLES_PER_OP_UNICORE 130 #define IDF_PERFORMANCE_MAX_ESP_TIMER_GET_TIME_PER_CALL 1000 #define IDF_PERFORMANCE_MAX_SPI_PER_TRANS_NO_POLLING 30 diff --git a/components/idf_test/integration_test/INIT_COND_SSC.yml b/components/idf_test/integration_test/INIT_COND_SSC.yml index d143bf02a0..0676015330 100644 --- a/components/idf_test/integration_test/INIT_COND_SSC.yml +++ b/components/idf_test/integration_test/INIT_COND_SSC.yml @@ -7,6 +7,17 @@ - - SSC SSC1 ram - - 'R SSC1 C +FREEHEAP:' +.MESH_INIT_COND: &MESH_INIT_COND + test script: InitCondBase + restore post cmd set: + - '' + - - SSC SSC[1-] mesh -Q -o 1 + - - R SSC[1-] C MESH_NETWORK + - - SSC SSC[1-] mesh -Q -o 3 + - - R SSC[1-] C +MESH_CONFIG:ALL + - - SSC SSC[1-] ram + - - R SSC[1-] A :(\d+) + initial condition: - tag: APM1 <<: *SSC_INIT_COND @@ -355,11 +366,11 @@ initial condition: - - R SSC2 C +BLEADV:OK - - SSC SSC2 gatts -S -z load -p 0xA0 - - R SSC2 C +GATTS:StartService,OK,A000 + - - SSC SSC1 gattc -F -r + - - R SSC1 C +GATTC:OK - - SSC SSC1 bleconn -C -p 0x10 -a - - R SSC1 C +BLE:GattcConnect,OK - P SSC2 C +BLE:GattsConnect - - - SSC SSC1 gattc -F -r - - - R SSC1 C +GATTC:OK force restore cmd set: - '' - - SSC SSC[1-2] reboot @@ -383,11 +394,11 @@ initial condition: - - R SSC2 C +BLEADV:OK - - SSC SSC2 gatts -S -z load -p 0xA0 - - R SSC2 C +GATTS:StartService,OK,A000 + - - SSC SSC1 gattc -F -r + - - R SSC1 C +GATTC:OK - - SSC SSC1 bleconn -C -p 0x10 -a - - R SSC1 C +BLE:GattcConnect,OK - P SSC2 C +BLE:GattsConnect - - - SSC SSC1 gattc -F -r - - - R SSC1 C +GATTC:OK restore post cmd set: - '' - - SSC SSC1 ram @@ -425,11 +436,11 @@ initial condition: - - R SSC2 C +BLEADV:OK - - SSC SSC2 gatts -S -z load -p 0xA2 - - R SSC2 C +GATTS:StartService,OK,A002 + - - SSC SSC1 gattc -F -r + - - R SSC1 C +GATTC:OK - - SSC SSC1 bleconn -C -p 0x10 -a - - R SSC1 C +BLE:GattcConnect,OK - P SSC2 C +BLE:GattsConnect - - - SSC SSC1 gattc -F -r - - - R SSC1 C +GATTC:OK force restore cmd set: - '' - - SSC SSC[1-2] reboot @@ -453,11 +464,11 @@ initial condition: - - R SSC2 C +BLEADV:OK - - SSC SSC2 gatts -S -z load -p 0xA2 - - R SSC2 C +GATTS:StartService,OK,A002 + - - SSC SSC1 gattc -F -r + - - R SSC1 C +GATTC:OK - - SSC SSC1 bleconn -C -p 0x10 -a - - R SSC1 C +BLE:GattcConnect,OK - P SSC2 C +BLE:GattsConnect - - - SSC SSC1 gattc -F -r - - - R SSC1 C +GATTC:OK restore post cmd set: - '' - - SSC SSC1 ram @@ -495,13 +506,13 @@ initial condition: - - R SSC2 C +BLEADV:OK - - SSC SSC[1-2] gatts -S -z load -p 0xA2 - - R SSC[1-2] C +GATTS:StartService,OK,A002 + - - SSC SSC[1-2] gattc -F -r + - - R SSC[1-2] C +GATTC:OK - - SSC SSC1 bleconn -C -p 0x10 -a - - R SSC1 C +BLE:GattcConnect,OK - P SSC2 C +BLE:GattsConnect - - SSC SSC2 bleconn -C -p 0x10 -a - - R SSC2 C +BLE:GattcOpen,OK - - - SSC SSC[1-2] gattc -F -r - - - R SSC[1-2] C +GATTC:OK force restore cmd set: - '' - - SSC SSC[1-2] reboot @@ -525,13 +536,13 @@ initial condition: - - R SSC2 C +BLEADV:OK - - SSC SSC[1-2] gatts -S -z load -p 0xA2 - - R SSC[1-2] C +GATTS:StartService,OK,A002 + - - SSC SSC[1-2] gattc -F -r + - - R SSC[1-2] C +GATTC:OK - - SSC SSC1 bleconn -C -p 0x10 -a - - R SSC1 C +BLE:GattcConnect,OK - P SSC2 C +BLE:GattsConnect - - SSC SSC2 bleconn -C -p 0x10 -a - - R SSC2 C +BLE:GattcOpen,OK - - - SSC SSC[1-2] gattc -F -r - - - R SSC[1-2] C +GATTC:OK restore post cmd set: - '' - - SSC SSC1 ram @@ -565,6 +576,8 @@ initial condition: - - P SSC[2-5] C +BLEADV:Start,OK - - SSC SSC[2-5] gatts -S -z load -p 0xA2 - - P SSC[2-5] C +GATTS:StartService,OK,A002 + - - SSC SSC1 gattc -F -r + - - R SSC1 C +GATTC:OK - - LOOP 4 1 "[2,3,4,5]" "[2,3,4,5]" "[2,3,4,5]" - '' - - SSC SSC1 bleconn -C -p 0x10 -a @@ -593,13 +606,13 @@ initial condition: - - P SSC[2-5] C +BLEADV:Start,OK - - SSC SSC[2-5] gatts -S -z load -p 0xA2 - - P SSC[2-5] C +GATTS:StartService,OK,A002 + - - SSC SSC1 gattc -F -r + - - R SSC1 C +GATTC:OK - - LOOP 4 1 "[2,3,4,5]" "[2,3,4,5]" "[2,3,4,5]" - '' - - SSC SSC1 bleconn -C -p 0x10 -a - - R SSC1 RE "\+BLE:GattcConnect,OK,0010,%%s"%%() - P SSC{%d} C +BLE:GattsConnect - - - SSC SSC1 gattc -F -r - - - R SSC1 C +GATTC:OK restore post cmd set: - '' - - SSC SSC1 ram @@ -637,11 +650,11 @@ initial condition: - '' - - SSC SSC1 bleadv -D -z start - - P SSC1 C +BLEADV:Start,OK + - - SSC SSC[2-5] gattc -F -r + - - R SSC[2-5] C +GATTC:OK - - SSC SSC{%d} bleconn -C -p 0x10 -a - - R SSC{%d} RE "\+BLE:GattcConnect,OK,0010,%%s"%%() - P SSC1 C +BLE:GattsConnect - - - SSC SSC[2-5] gattc -F -r - - - R SSC[2-5] C +GATTC:OK force restore cmd set: - '' - - SSC SSC[1-5] reboot @@ -661,6 +674,8 @@ initial condition: - - R SSC[1-5] C +BLEADV:OK - - SSC SSC1 gatts -S -z load -p 0xA2 - - R SSC1 C +GATTS:StartService,OK,A002 + - - SSC SSC[2-5] gattc -F -r + - - R SSC[2-5] C +GATTC:OK - - LOOP 4 2 "[2,3,4,5]" "[2,3,4,5]" - '' - - SSC SSC1 bleadv -D -z start @@ -668,8 +683,6 @@ initial condition: - - SSC SSC{%d} bleconn -C -p 0x10 -a - - R SSC{%d} RE "\+BLE:GattcConnect,OK,0010,%%s"%%() - P SSC1 C +BLE:GattsConnect - - - SSC SSC[2-5] gattc -F -r - - - R SSC[2-5] C +GATTC:OK restore post cmd set: - '' - - SSC SSC1 ram @@ -1045,6 +1058,8 @@ initial condition: - ["P SSC[2-5] C +GATTS:StartService,OK,A000"] - - SSC SSC[1-5] bleadv -D -z stop - - R SSC[1-5] C +BLEADV:OK + - - SSC SSC1 gattc -F -r + - - R SSC1 C +GATTC:OK - - SSC SSC1 ram - - R SSC1 A :(\d+) - tag: BLE_INIT_SMP @@ -1084,6 +1099,8 @@ initial condition: - - R SSC2 C +BLEADV:OK - - SSC SSC[1-2] blesmp -L -c [1,0] - - R SSC[1-2] C +BLESMP:OK + - - SSC SSC1 gattc -F -r + - - R SSC1 C +GATTC:OK - - SSC SSC1 ram - - R SSC1 A :(\d+) restore post cmd set: @@ -1111,6 +1128,8 @@ initial condition: - - R SSC2 C +BLEADV:OK - - SSC SSC[1-2] blesmp -L -c [1,0] - - R SSC[1-2] C +BLESMP:OK + - - SSC SSC1 gattc -F -r + - - R SSC1 C +GATTC:OK - - SSC SSC1 ram - - R SSC1 A :(\d+) - tag: BLE_INIT_SMP5 @@ -1150,6 +1169,8 @@ initial condition: - - R SSC[2-5] C +BLEADV:OK - - SSC SSC[1-5] blesmp -L -c [1,0] - - R SSC[1-5] C +BLESMP:OK + - - SSC SSC1 gattc -F -r + - - R SSC1 C +GATTC:OK restore post cmd set: - '' - - SSC SSC[1-5] ble -R @@ -1175,6 +1196,8 @@ initial condition: # do wifi disconnect, to prevent wifi reconnect cause bad BLE performance - - SSC SSC[1-5] sta -D - [] + - - SSC SSC1 gattc -F -r + - - R SSC1 C +GATTC:OK - - SSC SSC1 ram - - R SSC1 A :(\d+) - tag: NOW1 @@ -2026,3 +2049,209 @@ initial condition: - - R SSC[1-2] C +BLEADV:OK - - SSC SSC1 ram - - R SSC1 A :(\d+) +- tag: ENABLED_1 + <<: *MESH_INIT_COND + initial condition detail: if mesh tree not exist, start one node first, then start others, after mesh network + established, root connect server + check cmd set: + - '' + - - SSC SSC[1-] mesh -Q -o 2 + - - R SSC[1-] T + - - MESHTREE + - - R PC_COM RE "MESHTREE:%%s%20nodes"%%() + - - SOC SOC1 LISTEN + - - R SOC_COM L OK + - - SSC MNODE(0) mesh -S -o 0 -i -t + - - '' + - - SOC SOC1 MACCEPT GSOC1 + - - P MNODE(0) C +CONNECT,OK + - R SOC_COM L OK + - - SSC SSC[1-] mesh -F -o 4 -a 1 + - - P SSC[1-] C +MESHFLAG:OK + - - SSC SSC[1-] mesh -F -o 5 -a 1 + - - P SSC[1-] C +MESHFLAG:OK + restore cmd set: + - '' + - - SSC SSC[1-] reboot + - - P SSC[1-] C !!!ready!!! + - - SSC SSC[1-] mesh -I + - - P SSC[1-] C +MESH:INITED + - - SSC SSC[1-] mesh -A -o 12 -t -c -l -f -b + - - P SSC[1-] C +MESH_SET_PARENT_SWITCH:OK + - - SSC SSC[1-] mesh -A -o 9 -t -s + - - P SSC[1-] C +MESH_SET_AP_AUTH_MODE:OK C +MESH_SET_AP_AUTH_PWD:OK + - - SSC SSC[1-] mesh -P -g -s -p -n + -m -y + - - P SSC[1-] C +MESH:CONFIG,OK + - - SSC SSC1 mesh -T + - - P SSC1 C +MESH:START,OK + - - DELAY 10 + - - '' + - - SSC SSC[2-] mesh -T + - - P SSC[2-] C +MESH:START,OK + - - DELAY + - - '' + - - SSC SSC[1-] mesh -Q -o 2 + - - R SSC[1-] T + - - MESHTREE + - - R PC_COM RE "MESHTREE:%%s%20nodes"%%() + - - SSC MNODE(0) mesh -Q -o 1 -t + - - R MNODE(0) C NETWORK_TIME:PASS + - - SOC SOC1 LISTEN + - - R SOC_COM L OK + - - SSC MNODE(0) mesh -S -o 0 -i -t + - - '' + - - SOC SOC1 MACCEPT GSOC1 + - - P MNODE(0) C +CONNECT,OK + - R SOC_COM L OK + - - SSC SSC[1-] mesh -F -o 4 -a 1 + - - P SSC[1-] C +MESHFLAG:OK + - - SSC SSC[1-] mesh -F -o 5 -a 1 + - - P SSC[1-] C +MESHFLAG:OK + force restore cmd set: + - '' + - - SSC SSC[1-] restore + - - P SSC[1-] C !!!ready!!! + - - SSC SSC[1-] mesh -I + - - P SSC[1-] C +MESH:INITED + - - SSC SSC[1-] mesh -A -o 12 -t -c -l -f -b + - - P SSC[1-] C +MESH_SET_PARENT_SWITCH:OK + - - SSC SSC[1-] mesh -A -o 9 -t -s + - - P SSC[1-] C +MESH_SET_AP_AUTH_MODE:OK C +MESH_SET_AP_AUTH_PWD:OK + - - SSC SSC[1-] mesh -P -g -s -p -n + -m -y + - - P SSC[1-] C +MESH:CONFIG,OK + - - SSC SSC1 mesh -T + - - P SSC1 C +MESH:START,OK + - - DELAY 10 + - - '' + - - SSC SSC[2-] mesh -T + - - P SSC[2-] C +MESH:START,OK + - - DELAY + - - '' + - - SSC SSC[1-] mesh -Q -o 2 + - - R SSC[1-] T + - - MESHTREE + - - R PC_COM RE "MESHTREE:%%s%20nodes"%%() + - - SSC MNODE(0) mesh -Q -o 1 -t + - - R MNODE(0) C NETWORK_TIME:PASS + - - SOC SOC1 LISTEN + - - R SOC_COM L OK + - - SSC MNODE(0) mesh -S -o 0 -i -t + - - '' + - - SOC SOC1 MACCEPT GSOC1 + - - P MNODE(0) C +CONNECT,OK + - R SOC_COM L OK + - - SSC SSC[1-] mesh -F -o 4 -a 1 + - - P SSC[1-] C +MESHFLAG:OK + - - SSC SSC[1-] mesh -F -o 5 -a 1 + - - P SSC[1-] C +MESHFLAG:OK +- tag: ENABLED_2 + <<: *MESH_INIT_COND + initial condition detail: if mesh tree not exist, start all nodes together + check cmd set: + - '' + - - SSC SSC[1-] mesh -Q -o 2 + - - R SSC[1-] T + - - MESHTREE + - - R PC_COM RE "MESHTREE:%%s%20nodes"%%() + restore cmd set: + - '' + - - SSC SSC[1-] reboot + - - P SSC[1-] C !!!ready!!! + - - SSC SSC[1-] mesh -I + - - P SSC[1-] C +MESH:INITED + - - SSC SSC[1-] mesh -A -o 12 -t -c -l -f -b + - - P SSC[1-] C +MESH_SET_PARENT_SWITCH:OK + - - SSC SSC[1-] mesh -A -o 9 -t -s + - - P SSC[1-] C +MESH_SET_AP_AUTH_MODE:OK C +MESH_SET_AP_AUTH_PWD:OK + - - SSC SSC[1-] mesh -P -g -s -p -n + -m -y + - - P SSC[1-] C +MESH:CONFIG,OK + - - SSC SSC[1-] mesh -T + - - P SSC[1-] C +MESH:START,OK + - - DELAY + - - '' + - - SSC SSC[1-] mesh -Q -o 2 + - - R SSC[1-] T + - - MESHTREE + - - R PC_COM RE "MESHTREE:%%s%20nodes"%%() + - - SSC MNODE(0) mesh -Q -o 1 -t + - - R MNODE(0) C NETWORK_TIME:PASS + force restore cmd set: + - '' + - - SSC SSC[1-] restore + - - P SSC[1-] C !!!ready!!! + - - SSC SSC[1-] mesh -I + - - P SSC[1-] C +MESH:INITED + - - SSC SSC[1-] mesh -A -o 12 -t -c -l -f -b + - - P SSC[1-] C +MESH_SET_PARENT_SWITCH:OK + - - SSC SSC[1-] mesh -A -o 9 -t -s + - - P SSC[1-] C +MESH_SET_AP_AUTH_MODE:OK C +MESH_SET_AP_AUTH_PWD:OK + - - SSC SSC[1-] mesh -P -g -s -p -n + -m -y + - - P SSC[1-] C +MESH:CONFIG,OK + - - SSC SSC[1-] mesh -T + - - P SSC[1-] C +MESH:START,OK + - - DELAY + - - '' + - - SSC SSC[1-] mesh -Q -o 2 + - - R SSC[1-] T + - - MESHTREE + - - R PC_COM RE "MESHTREE:%%s%20nodes"%%() + - - SSC MNODE(0) mesh -Q -o 1 -t + - - R MNODE(0) C NETWORK_TIME:PASS +- tag: ENABLED_3 + <<: *MESH_INIT_COND + initial condition detail: all mesh nodes in softap+sta mode, mesh configed but not started + check cmd set: + - '' + restore cmd set: + - '' + - - SSC SSC[1-] reboot + - - P SSC[1-] C !!!ready!!! + - - SSC SSC[1-] mesh -I + - - P SSC[1-] C +MESH:INITED + - - SSC SSC[1-] mesh -A -o 12 -t -c -l -f -b + - - P SSC[1-] C +MESH_SET_PARENT_SWITCH:OK + - - SSC SSC[1-] mesh -A -o 9 -t -s + - - P SSC[1-] C +MESH_SET_AP_AUTH_MODE:OK C +MESH_SET_AP_AUTH_PWD:OK + - - SSC SSC[1-] mesh -P -g -s -p -n + -m -y + - - P SSC[1-] C +MESH:CONFIG,OK + force restore cmd set: + - '' + - - SSC SSC[1-] restore + - - P SSC[1-] C !!!ready!!! + - - SSC SSC[1-] mesh -I + - - P SSC[1-] C +MESH:INITED + - - SSC SSC[1-] mesh -A -o 12 -t -c -l -f -b + - - P SSC[1-] C +MESH_SET_PARENT_SWITCH:OK + - - SSC SSC[1-] mesh -A -o 9 -t -s + - - P SSC[1-] C +MESH_SET_AP_AUTH_MODE:OK C +MESH_SET_AP_AUTH_PWD:OK + - - SSC SSC[1-] mesh -P -g -s -p -n + -m -y + - - P SSC[1-] C +MESH:CONFIG,OK +- tag: DISABLED_1 + <<: *MESH_INIT_COND + initial condition detail: all mesh node in softap+sta mode, disable all mesh node + check cmd set: + - '' + - - ASSERT + - - '' + restore cmd set: + - '' + - - SSC SSC[1-] reboot + - - P SSC[1-] C !!!ready!!! + - - SSC SSC[1-] op -Q + - - P SSC[1-] C +CURMODE:3 + - - SSC SSC[1-] sta -D + - - P SSC[1-] C +QAP:OK + force restore cmd set: + - '' + - - SSC SSC[1-] restore + - - P SSC[1-] C !!!ready!!! + - - SSC SSC[1-] op -S -o 3 + - - P SSC[1-] C +MODE:OK + - - SSC SSC[1-] sta -D + - - P SSC[1-] C +QAP:OK \ No newline at end of file diff --git a/components/idf_test/integration_test/TC_IT_BTSTK_GAP.yml b/components/idf_test/integration_test/TC_IT_BTSTK_GAP.yml index 02a4ae7c57..95bde1cf2d 100644 --- a/components/idf_test/integration_test/TC_IT_BTSTK_GAP.yml +++ b/components/idf_test/integration_test/TC_IT_BTSTK_GAP.yml @@ -132,14 +132,14 @@ test cases: - - "SSC SSC2 blescan -L -c 0 -s 1" - ["R SSC2 C +BLESCAN:SetScanParam,OK"] - - "SSC SSC2 blescan -D -z start -t 3" - - ["R SSC2 P "] + - ["R SSC2 P C Complete"] - - "SSC SSC1 ble -S -z name -n 123456789012345678901234567890123" - ["R SSC1 C +BLE:ERROR"] - *set_default_adv_data - - "SSC SSC2 blescan -L -c 0 -s 1" - ["R SSC2 C +BLESCAN:SetScanParam,OK"] - - "SSC SSC2 blescan -D -z start -t 3" - - ["R SSC2 P "] + - ["R SSC2 P C Complete"] - ID: BTSTK_GAP_02001 <<: *GAP_CASE test point 2: BLE GAP config advertising data @@ -1761,6 +1761,8 @@ test cases: 3. scan with the correct adv data cmd set: - "" + - - "SSC SSC2 blescan -L -c 0 -d 1" + - ["R SSC2 C +BLESCAN:SetScanParam,OK"] - *dut1_stop_adv - - "SSC SSC1 bleadv -R -t 1 -r 0x020AEB06FF1112131415051220004000021901020106" - ["R SSC1 C +BLEADV:OK"] @@ -1791,6 +1793,8 @@ test cases: - "" - *dut1_stop_adv - *dut2_stop_adv + - - "SSC SSC2 blescan -L -c 0 -d 1" + - ["R SSC2 C +BLESCAN:SetScanParam,OK"] - - LOOP 4 3 "['0302ABCD','0303ABCD','0504ABCDABCD','0505ABCDABCD',]" "['insrv16,0xABCD','srv16,0xABCD','insrv32,0xABCDABCD','srv32,0xABCDABCD']" - - "SSC SSC1 bleadv -R -t 1 -r 0x{%s}" - ["R SSC1 C +BLEADV:OK"] @@ -1823,6 +1827,8 @@ test cases: - "" - *dut1_stop_adv - *dut2_stop_adv + - - "SSC SSC2 blescan -L -c 0 -d 1" + - ["R SSC2 C +BLESCAN:SetScanParam,OK"] - - LOOP 3 3 "['0416ABCDEF','0620ABCDABCDEF','1221ABCDABCDABCDABCDABCDABCDABCDABCDEF',]" "['srvdata,0xABCDEF','srvdata32,0xABCDABCDEF','srvdata128,0xABCDABCDABCDABCDABCDABCDABCDABCDEF']" - - "SSC SSC1 bleadv -R -t 1 -r 0x{%s}" - ["R SSC1 C +BLEADV:OK"] @@ -1846,6 +1852,8 @@ test cases: cmd set: - "" - *dut1_stop_adv + - - "SSC SSC2 blescan -L -c 0 -d 1" + - ["R SSC2 C +BLESCAN:SetScanParam,OK"] - - "SSC SSC1 bleadv -R -t 1 -r 0x15FF1011121314151617181910111213141516171819" - ["R SSC1 C +BLEADV:OK"] - - "SSC SSC1 bleadv -R -t 2 -r 0x020AEB051220004000021901020106" @@ -1884,6 +1892,8 @@ test cases: cmd set: - "" - *dut1_stop_adv + - - "SSC SSC2 blescan -L -c 0 -d 1" + - ["R SSC2 C +BLESCAN:SetScanParam,OK"] - - "SSC SSC1 ble -S -z name -n abcde" - ["R SSC1 C +BLE"] - - "SSC SSC1 bleadv -L -c 0 -n 1 -t 3" @@ -1924,6 +1934,8 @@ test cases: cmd set: - "" - *dut1_stop_adv + - - "SSC SSC2 blescan -L -c 0 -d 1" + - ["R SSC2 C +BLESCAN:SetScanParam,OK"] - *set_default_ble_name - - "SSC SSC1 bleadv -L -c 0 -x 1 -t 3" - ["R SSC1 C +BLEADV:SetAdv,OK"] @@ -1963,6 +1975,8 @@ test cases: cmd set: - "" - *dut1_stop_adv + - - "SSC SSC2 blescan -L -c 0 -d 1" + - ["R SSC2 C +BLESCAN:SetScanParam,OK"] - *set_default_ble_name - - "SSC SSC1 bleadv -L -c 0 -i 0x20-0x40 -t 3" - ["R SSC1 C +BLEADV:SetAdv,OK"] @@ -2002,6 +2016,8 @@ test cases: cmd set: - "" - *dut1_stop_adv + - - "SSC SSC2 blescan -L -c 0 -d 1" + - ["R SSC2 C +BLESCAN:SetScanParam,OK"] - *set_default_ble_name - - "SSC SSC1 bleadv -L -c 0 -a 0 -t 3" - ["R SSC1 C +BLEADV:SetAdv,OK"] @@ -2033,6 +2049,8 @@ test cases: cmd set: - "" - *dut1_stop_adv + - - "SSC SSC2 blescan -L -c 0 -d 1" + - ["R SSC2 C +BLESCAN:SetScanParam,OK"] - *set_default_ble_name - - "SSC SSC1 bleadv -L -c 0 -m 0x12345678 -t 3" - ["R SSC1 C +BLEADV:SetAdv,OK"] @@ -2057,6 +2075,8 @@ test cases: cmd set: - "" - *dut1_stop_adv + - - "SSC SSC2 blescan -L -c 0 -d 1" + - ["R SSC2 C +BLESCAN:SetScanParam,OK"] - *set_default_ble_name - - "SSC SSC1 bleadv -L -c 0 -n 0 -d 0x1234123456 -t 3" - ["R SSC1 C +BLEADV:SetAdv,OK"] @@ -2081,6 +2101,8 @@ test cases: cmd set: - "" - *dut1_stop_adv + - - "SSC SSC2 blescan -L -c 0 -d 1" + - ["R SSC2 C +BLESCAN:SetScanParam,OK"] - - "SSC SSC1 bleadv -L -c 0 -n 0 -x 0 -i 0x00-0x00 -s ABCD,ABCDDCBA,12349B5F8000008000100000ABCD0000 -t 3" - ["R SSC1 C +BLEADV:SetAdv,OK"] - *dut1_start_adv diff --git a/components/idf_test/integration_test/TC_IT_BTSTK_GATT.yml b/components/idf_test/integration_test/TC_IT_BTSTK_GATT.yml index 6e153fb58a..f1a88881d1 100644 --- a/components/idf_test/integration_test/TC_IT_BTSTK_GATT.yml +++ b/components/idf_test/integration_test/TC_IT_BTSTK_GATT.yml @@ -304,6 +304,7 @@ test cases: initial condition: BLE_CONN3 cmd set: - "" + - *primary_service_discovery - - "SSC SSC2 gatts -V -c 0xC300 -p 0xA2 -z set -v 0x02" - ["R SSC2 C +GATTS:SetAttrVal,OK"] - - "SSC SSC1 gattc -R -z char -s 0xA002 -c 0xC300 -p 0x10" @@ -499,6 +500,7 @@ test cases: initial condition: BLE_CONN3 cmd set: - "" + - *primary_service_discovery - - "SSC SSC2 gatts -V -c 0xC300 -d 0x2901 -p 0xA2 -z set -v 0x02" - ["R SSC2 C +GATTS:SetAttrVal,OK"] - - "SSC SSC1 gattc -R -z descriptor -s 0xA002 -c 0xC300 -d 0x2901 -p 0x10" diff --git a/components/idf_test/integration_test/TC_IT_MESH_COMM.yml b/components/idf_test/integration_test/TC_IT_MESH_COMM.yml new file mode 100644 index 0000000000..30e07fc46b --- /dev/null +++ b/components/idf_test/integration_test/TC_IT_MESH_COMM.yml @@ -0,0 +1,178 @@ +test cases: +- CI ready: 'Yes' + ID: MESH_COMM_0101 + SDK: ESP32_IDF + Test App: SSC_MESH + auto test: 'Yes' + category: Function + cmd set: + - '' + - - SSC MNODE(0) meshsend -S -d -l 1000 -c 20 -b 20 -f 2 + - - P MNODE(0) C +MESHSEND,OK + - P MNODE(0,-1) C +MESHRXPKT:OK + execution time: 0.0 + expected result: |- + 1. succeed + 2. succeed + 3. succeed + 4. succeed + initial condition: ENABLED_2 + level: Integration + module: Mesh + steps: |- + 1. mesh init + 2. mesh config + 3. mesh start + 4. root send unicast to leaf + sub module: Communication + summary: root send unicast to leaf + test environment: SSC_T50_1 + test point 1: basic function + test point 2: unicast test + version: v1 (2017-7-20) +- CI ready: 'Yes' + ID: MESH_COMM_0106 + SDK: ESP32_IDF + Test App: SSC_MESH + auto test: 'Yes' + category: Function + cmd set: + - '' + - - SSC MNODE(0,-1) meshsend -S -d -l 1000 -c 20 -b 20 -f 2 + - - P MNODE(0,-1) C +MESHSEND,OK + - P MNODE(0) C +MESHRXPKT:OK + execution time: 0.0 + expected result: |- + 1. succeed + 2. succeed + 3. succeed + 4. succeed + initial condition: ENABLED_1 + level: Integration + module: Mesh + steps: |- + 1. mesh init + 2. mesh config + 3. mesh start + 4. leaf send unicast to root + sub module: Communication + summary: leaf send unicast to root + test environment: SSC_T50_1 + test point 1: basic function + test point 2: unicast test + version: v1 (2017-7-20) +- CI ready: 'Yes' + ID: MESH_COMM_0116 + SDK: ESP32_IDF + Test App: SSC + auto test: 'Yes' + category: Function + cmd set: + - '' + - - SSC MNODE(0,-1) meshsend -S -d -l 1000 -c 100 -f 2 + - - P MNODE(0,-1) C +MESHTXPKT:OK C +MESHSEND,OK + - P MNODE(0,1) C +MESHRXPKT:OK + - - DELAY 5 + - - '' + - - SSC MNODE(0,-1) meshsend -S -d -l 1000 -c 10 -f 2 + - - P MNODE(0,-1) C +MESHTXPKT:OK C +MESHSEND,OK + - P MNODE(0,1) C +MESHRXPKT:OK + expected result: |- + 1. succeed + 2. succeed + 3. succeed + 4. succeed + initial condition: ENABLED_2 + level: Integration + module: Mesh + steps: |- + 1. mesh init + 2. mesh config + 3. mesh start + 4. root send unicast to others + sub module: Communication + summary: fluid control test when node send packets upward + test environment: SSC_T50_1 + test point 1: basic function + test point 2: unicast test + version: v1 (2017-7-20) +- CI ready: 'Yes' + ID: MESH_COMM_0210 + SDK: ESP32_IDF + Test App: SSC_MESH + auto test: 'Yes' + category: Function + cmd set: + - '' + - - SSC MNODE(0) meshsend -S -d -l 1460 -c 20 -b 20 -f 4 + - - P MNODE(0) C +MESHTXPKT:OK C +MESHSEND,OK + - P MNODE(0,0) C +MESHRXPKT:OK + execution time: 0.0 + expected result: |- + 1. succeed + 2. succeed + 3. succeed + 4. succeed + initial condition: ENABLED_1 + level: Integration + module: Mesh + steps: |- + 1. mesh init + 2. mesh config + 3. mesh start + 4. root send unicast + sub module: Communication + summary: root send unicast downward with flag=FROMDS + test environment: SSC_T50_1 + test point 1: basic function + test point 2: meshsend parameter check + version: v1 (2017-7-20) +- CI ready: 'Yes' + ID: MESH_COMM_0902 + SDK: ESP32_IDF + Test App: SSC_MESH + auto test: 'Yes' + category: Function + cmd set: + - '' + - - SSC MNODE(0,0,0) mesh -D -o 0 -g + - - P MNODE(0,0,0) C +MESH_ADDR_LIST_ADD + - - SSC MNODE(0,0,0) mesh -D -o 0 -g + - - P MNODE(0,0,0) C +MESH_ADDR_LIST_ADD + - - SSC MNODE(0,0,0) meshsend -P -p 0 -t 7 -l 12 + - - P MNODE(0,0,0) C +MESHSEND:OPTION,1 + - - SSC MNODE(0,0,0) meshsend -S -w 1 -d 01:00:5E:00:00:00 -c 10 -b 20 -f + 2 + - - P MNODE(0,0,0) C +MESHTXPKT:ERROR C +MESHSEND,OK + - P MNODE(0,0) NC +MESHRXPKT:OK + - - SSC MNODE(0,0,0) meshsend -S -w 1 -d 01:00:5E:00:00:00 -l 0 -c 10 -b 20 -f + 2 + - - P MNODE(0,0,0) C +MESHTXPKT:ERROR C +MESHSEND,OK + - P MNODE(0,0) NC +MESHRXPKT:OK + - - SSC MNODE(0,0,0) meshsend -S -w 1 -d 01:00:5E:00:00:00 -l 1000 -c 10 -b 20 -f + 2 + - - P MNODE(0,0,0) C +MESHTXPKT:OK C +MESHSEND,OK + - P MNODE(0) C +MESHRXPKT:OK + - - SSC MNODE(0,0,0) meshsend -S -w 1 -d 01:00:5E:00:00:00 -l 1460 -c 10 -b 20 -f + 2 + - - P MNODE(0,0,0) C +MESHTXPKT:ERROR C +MESHSEND,OK + execution time: 0.0 + expected result: |- + 1. succeed + 2. succeed + 3. succeed + 4. succeed + initial condition: ENABLED_1 + level: Integration + module: Mesh + steps: |- + 1. mesh init + 2. mesh config + 3. mesh start + 4. node send multicast with different length + sub module: Communication + summary: node send multicast with different length + test environment: SSC_T50_1 + test point 1: basic function + test point 2: meshsend parameter check + version: v1 (2017-7-20) diff --git a/components/idf_test/integration_test/TC_IT_MESH_EST.yml b/components/idf_test/integration_test/TC_IT_MESH_EST.yml new file mode 100644 index 0000000000..9d5ac0b766 --- /dev/null +++ b/components/idf_test/integration_test/TC_IT_MESH_EST.yml @@ -0,0 +1,217 @@ +test cases: +- CI ready: 'Yes' + ID: MESH_EST_0106 + SDK: ESP32_IDF + Test App: SSC_MESH + auto test: 'Yes' + category: Function + cmd set: + - '' + - - SSC SSC[1-] mesh -I + - - P SSC[1-] C +MESH:INITED + - - SSC SSC[1-] mesh -A -o 7 -t 25 + - - P SSC[1-] C +MESH_SET_TX_POWER:OK + - - SSC SSC[1-] mesh -P -g -s -p -n -m -y + - - P SSC[1-] C +MESH:CONFIG,OK + - - SSC SSC[1-] mesh -T + - - P SSC[1-] C +MESH:START + - - DELAY + - - '' + - - SSC SSC[1-] mesh -Q -o 2 + - - R SSC[1-] T + - - MESHTREE + - - R PC_COM RE "MESHTREE:%%s%20nodes"%%() + execution time: 0.0 + expected result: |- + 1. succeed + 2. succeed + 3. succeed + initial condition: DISABLED_1 + level: Integration + module: Mesh + steps: |- + 1. mesh init + 2. mesh config + 3. mesh start + sub module: Network Establish + summary: set node with different tx power, then establish network + test environment: SSC_T50_1 + test point 1: basic function + test point 2: mesh config + version: v1 (2017-7-20) +- CI ready: 'Yes' + ID: MESH_EST_0313 + SDK: ESP32_IDF + Test App: SSC_MESH + auto test: 'Yes' + category: Function + cmd set: + - '' + - - SSC SSC[1-] mesh -I + - - P SSC[1-] C +MESH:INITED + - - SSC SSC[1-] mesh -P -g -s -p -n + -m -y + - - P SSC[1-] C +MESH:CONFIG,OK + - - SSC SSC[1-2] mesh -T + - - P SSC[1-2] C +MESH:START + - - DELAY 30 + - - '' + - - SSC SSC[1-2] mesh -Q -o 2 + - - R SSC[1-2] T 2 + - - MESHTREE + - - R PC_COM C MESHTREE:2%20nodes + - - SSC MNODE(0) reboot + - - P MNODE(0) C !!!ready!!! + - P MNODE(0,0) C MESH_EVENT_DISCONNECTED + - - DELAY 10 + - - P MNODE(0,0) C MESH_EVENT_CONNECTED,1 + execution time: 0.0 + expected result: |- + 1. succeed + 2. succeed + 3. succeed + 4. succeed + initial condition: DISABLED_1 + level: Integration + module: Mesh + steps: |- + 1. switch to sta+softap mode + 2. mesh init + 3. mesh config + 4. mesh start + sub module: Network Establish + summary: 2 nodes do mesh network establish,then reboot root + test environment: SSC_T50_1 + test point 1: basic function + test point 2: mesh network establish + version: v1 (2017-7-20) +- CI ready: 'Yes' + ID: MESH_EST_0317 + SDK: ESP32_IDF + Test App: SSC_MESH + auto test: 'Yes' + category: Function + cmd set: + - '' + - - SSC SSC[1-] mesh -I + - - P SSC[1-] C +MESH:INITED + - - SSC SSC[1-] mesh -P -g -s -p -n + -m 1 -y 15 + - - P SSC[1-] C +MESH:CONFIG,OK + - - SSC SSC[1-15] mesh -T + - - P SSC[1-15] C +MESH:START + - - DELAY + - - '' + - - SSC SSC[1-15] mesh -Q -o 2 + - - R SSC[1-15] T 15 + - - MESHTREE + - - R PC_COM C MESHTREE:15%20nodes + execution time: 0.0 + expected result: |- + 1. succeed + 2. succeed + 3. succeed + 4. succeed + 5. succeed + initial condition: DISABLED_1 + level: Integration + module: Mesh + steps: |- + 1. switch to sta+softap mode + 2. mesh init + 3. mesh config: set mesh layer=15 + 4. start 15 nodes + 5. check mesh tree + sub module: Network Establish + summary: set special mesh tree which layer=15 + test environment: SSC_T50_1 + test point 1: basic function + test point 2: mesh network establish + version: v1 (2017-7-20) +- CI ready: 'Yes' + ID: MESH_EST_0404 + SDK: ESP32_IDF + Test App: SSC_MESH + auto test: 'Yes' + category: Function + cmd set: + - '' + - - SSC MNODE(0) reboot + - - P MNODE(0) C !!!ready!!! + - - DELAY 2 + - - '' + - - SSC MNODE(0) mesh -I + - - P MNODE(0) C +MESH:INITED + - - SSC MNODE(0) mesh -A -o 9 -t -s + - - P MNODE(0) C +MESH_SET_AP_AUTH_MODE:OK C +MESH_SET_AP_AUTH_PWD:OK + - - SSC MNODE(0) mesh -P -g -s -p -n + -m -y + - - P MNODE(0) C +MESH:CONFIG,OK + - - SSC MNODE(0) mesh -T + - - P MNODE(0) C +MESH:START + - - DELAY + - - '' + - - SSC SSC[1-] mesh -Q -o 2 + - - R SSC[1-] T + - - MESHTREE + - - R PC_COM RE "MESHTREE:%%s%20nodes"%%() + execution time: 0.0 + expected result: |- + 1. succeed + 2. succeed + 3. succeed + 4. succeed + 5. succeed + initial condition: ENABLED_2 + level: Integration + module: Mesh + steps: |- + 1. mesh init + 2. mesh config + 3. mesh start + 4. save value + 5. all nodes reboot + sub module: Network Establish + summary: after network is establish, disable root,wait some time, start the root node again + test environment: SSC_T50_1 + test point 1: basic function + test point 2: mesh network re-establish + version: v1 (2017-7-20) +- CI ready: 'Yes' + ID: MESH_EST_0405 + SDK: ESP32_IDF + Test App: SSC_MESH + auto test: 'Yes' + category: Function + cmd set: + - '' + - - SSC MNODE(0) reboot + - - P MNODE(0) C !!!ready!!! + - - DELAY + - - '' + - - SSC SSC[1-] mesh -Q -o 2 + - - R SSC[1-] T + - - MESHTREE + - - R PC_COM RE "MESHTREE:%%s%20nodes"%%() + execution time: 0.0 + expected result: |- + 1. succeed + 2. succeed + 3. succeed + 4. succeed + 5. succeed + initial condition: ENABLED_2 + level: Integration + module: Mesh + steps: |- + 1. mesh init + 2. mesh config + 3. mesh start + 4. save value + 5. all nodes reboot + sub module: Network Establish + summary: after network is establish, disable root, check mesh network + test environment: SSC_T50_1 + test point 1: basic function + test point 2: mesh network re-establish + version: v1 (2017-7-20) diff --git a/components/idf_test/integration_test/TC_IT_TCPIP_DHCP.yml b/components/idf_test/integration_test/TC_IT_TCPIP_DHCP.yml index 435c31a5d8..cbc431a2a3 100644 --- a/components/idf_test/integration_test/TC_IT_TCPIP_DHCP.yml +++ b/components/idf_test/integration_test/TC_IT_TCPIP_DHCP.yml @@ -593,7 +593,7 @@ test cases: - - P SSC1 C +DHCP:AP,OK - P SSC2 C +JAP:DISCONNECTED - - SSC SSC2 sta -D - - - R SSC2 C +JAP:DISCONNECTED + - - R SSC2 C OK - - SSC SSC1 dhcp -E -o 2 - - R SSC1 C +DHCP:AP,OK - - SSC SSC1 dhcp -S -o 2 diff --git a/components/idf_test/integration_test/TC_IT_WIFI_CONN.yml b/components/idf_test/integration_test/TC_IT_WIFI_CONN.yml index 34d24635b5..0f9bcd1f3f 100644 --- a/components/idf_test/integration_test/TC_IT_WIFI_CONN.yml +++ b/components/idf_test/integration_test/TC_IT_WIFI_CONN.yml @@ -810,12 +810,6 @@ test cases: - - R PC_COM NC ERROR C +WIFICONN:OK - - SSC SSC2 sta -C -s -p - - R SSC2 RE JAP:DISCONNECTED,\d+,5 - - - WIFI DISCONN - - - P PC_COM C OK - - R SSC2 C +JAP:CONNECTED - - - SSC SSC1 ap -S -s -p -t 3 -m 1 - - - P SSC1 C +SAP:OK - - P SSC2 RE JAP:DISCONNECTED,\d+,4 execution time: 0.0 expected result: |- 1. succeed @@ -823,8 +817,6 @@ test cases: 3. succeed 4. succeed 5. disconnect event REASON_ASSOC_TOOMANY - 6. succeed, target2 connect succeed - 7. disconnect event REASON_ASSOC_EXPIRE initial condition: T2_1 level: Integration module: WIFI MAC @@ -834,11 +826,8 @@ test cases: 3. target2 disconnect 4. PC WIFI NIC connect to target1 5. target2 connect to target1 with correct password - 6. PC WIFI NIC disconnect - 7. reconfig softap sub module: WIFI Connect - summary: test wifi disconnect reason REASON_ASSOC_TOOMANY, REASON_HANDSHAKE_TIMEOUT, - REASON_ASSOC_EXPIRE + summary: test wifi disconnect reason REASON_ASSOC_TOOMANY, REASON_HANDSHAKE_TIMEOUT test environment: SSC_T2_1 test point 1: basic function test point 2: wifi disconnect reason test diff --git a/components/idf_test/integration_test/TEST_ENV_SSC.yml b/components/idf_test/integration_test/TEST_ENV_SSC.yml index e9675ec477..08c652f971 100644 --- a/components/idf_test/integration_test/TEST_ENV_SSC.yml +++ b/components/idf_test/integration_test/TEST_ENV_SSC.yml @@ -238,3 +238,11 @@ test environment: PC has 1 wired NIC connected to AP. PC has 1 WiFi NIC. 6 SSC target connect with PC by UART. +- tag: SSC_T50_1 + <<: *TEST_ENV + Special: Y + Target Count: 50 + test environment detail: |- + PC has 1 wired NIC connected to AP. + PC has 1 WiFi NIC. + 50 SSC target connect with PC by UART. diff --git a/components/libsodium/CMakeLists.txt b/components/libsodium/CMakeLists.txt index 674534c916..0ad301662e 100644 --- a/components/libsodium/CMakeLists.txt +++ b/components/libsodium/CMakeLists.txt @@ -98,3 +98,10 @@ set_source_files_properties( PROPERTIES COMPILE_FLAGS -Wno-unused-variable ) + +# Temporary suppress "fallthrough" warnings until they are fixed in libsodium repo +set_source_files_properties( + ${SRC}/crypto_shorthash/siphash24/ref/shorthash_siphashx24_ref.c + ${SRC}/crypto_shorthash/siphash24/ref/shorthash_siphash24_ref.c + PROPERTIES COMPILE_FLAGS + -Wno-implicit-fallthrough) diff --git a/components/libsodium/component.mk b/components/libsodium/component.mk index 9862a274b8..12dcb571a5 100644 --- a/components/libsodium/component.mk +++ b/components/libsodium/component.mk @@ -86,3 +86,7 @@ CFLAGS += -DNATIVE_LITTLE_ENDIAN -DHAVE_WEAK_SYMBOLS -D__STDC_LIMIT_MACROS -D__ # randombytes.c needs to pull in platform-specific implementation $(LSRC)/randombytes/randombytes.o: CFLAGS+=-DRANDOMBYTES_DEFAULT_IMPLEMENTATION + +# Temporary suppress "fallthrough" warnings until they are fixed in libsodium repo +$(LSRC)/crypto_shorthash/siphash24/ref/shorthash_siphashx24_ref.o: CFLAGS += -Wno-implicit-fallthrough +$(LSRC)/crypto_shorthash/siphash24/ref/shorthash_siphash24_ref.o: CFLAGS += -Wno-implicit-fallthrough diff --git a/components/libsodium/test/component.mk b/components/libsodium/test/component.mk index 572099caed..f59730b830 100644 --- a/components/libsodium/test/component.mk +++ b/components/libsodium/test/component.mk @@ -5,7 +5,9 @@ LS_TESTDIR := ../libsodium/test/default LS_TEST_OBJDIR := libsodium/test/default -ifdef TESTS_ALL +TESTS_ALL ?= 0 + +ifeq ($(TESTS_ALL),1) $(info not linking libsodium tests, use 'TEST_COMPONENTS=libsodium' to test it) else COMPONENT_ADD_LDFLAGS = -Wl,--whole-archive -l$(COMPONENT_NAME) -Wl,--no-whole-archive diff --git a/components/log/README.rst b/components/log/README.rst index 034c32d792..03ca5f0da8 100644 --- a/components/log/README.rst +++ b/components/log/README.rst @@ -8,11 +8,11 @@ Log library has two ways of managing log verbosity: compile time, set via menuco The log levels are Error, Warning, Info, Debug, and Verbose (from lowest to highest level of verbosity). -At compile time, filtering is done using :ref:`CONFIG_LOG_DEFAULT_LEVEL` option, set via menuconfig. All logging statements for levels higher than :ref:`CONFIG_LOG_DEFAULT_LEVEL` will be removed by the preprocessor. +At compile time, filtering is done using :envvar:`CONFIG_LOG_DEFAULT_LEVEL` option, set via menuconfig. All logging statements for levels higher than :envvar:`CONFIG_LOG_DEFAULT_LEVEL` will be removed by the preprocessor. -At run time, all logs below :ref:`CONFIG_LOG_DEFAULT_LEVEL` are enabled by default. :cpp:func:`esp_log_level_set` function may be used to reduce logging level per module. Modules are identified by their tags, which are human-readable ASCII zero-terminated strings. +At run time, all logs below :envvar:`CONFIG_LOG_DEFAULT_LEVEL` are enabled by default. :cpp:func:`esp_log_level_set` function may be used to reduce logging level per module. Modules are identified by their tags, which are human-readable ASCII zero-terminated strings. -Note that :cpp:func:`esp_log_level_set` can not increase logging level beyound that set by :ref:`CONFIG_LOG_DEFAULT_LEVEL`. To increase log level for a specific file at compile time, `LOG_LOCAL_LEVEL` macro can be used (see below for details). +Note that :cpp:func:`esp_log_level_set` can not increase logging level beyound that set by :envvar:`CONFIG_LOG_DEFAULT_LEVEL`. To increase log level for a specific file at compile time, `LOG_LOCAL_LEVEL` macro can be used (see below for details). How to use this library ----------------------- diff --git a/components/lwip/Kconfig b/components/lwip/Kconfig index efd053b5f2..55141ffbb3 100644 --- a/components/lwip/Kconfig +++ b/components/lwip/Kconfig @@ -104,7 +104,7 @@ config LWIP_STATS config LWIP_ETHARP_TRUST_IP_MAC bool "Enable LWIP ARP trust" - default y + default n help Enabling this option allows ARP table to be updated. @@ -117,6 +117,17 @@ config LWIP_ETHARP_TRUST_IP_MAC The peer *is* in the ARP table if it requested our address before. Also notice that this slows down input processing of every IP packet! + There are two known issues in real application if this feature is enabled: + - The LAN peer may have bug to update the ARP table after the ARP entry is aged out. + If the ARP entry on the LAN peer is aged out but failed to be updated, all IP packets + sent from LWIP to the LAN peer will be dropped by LAN peer. + - The LAN peer may not be trustful, the LAN peer may send IP packets to LWIP with + two different MACs, but the same IP address. If this happens, the LWIP has problem + to receive IP packets from LAN peer. + + So the recommendation is to disable this option. + Here the LAN peer means the other side to which the ESP station or soft-AP is connected. + config TCPIP_RECVMBOX_SIZE int "TCPIP task receive mail box size" default 32 @@ -329,6 +340,16 @@ config TCP_QUEUE_OOSEQ Disable this option to save some RAM during TCP sessions, at the expense of increased retransmissions if segments arrive out of order. +config ESP_TCP_KEEP_CONNECTION_WHEN_IP_CHANGES + bool "Keep TCP connections when IP changed" + default n + help + This option is enabled when the following scenario happen: + network dropped and reconnected, IP changes is like: 192.168.0.2->0.0.0.0->192.168.0.2 + + Disable this option to keep consistent with the original LWIP code behavior. + + choice TCP_OVERSIZE prompt "Pre-allocate transmit PBUF size" default TCP_OVERSIZE_MSS diff --git a/components/lwip/api/api_lib.c b/components/lwip/api/api_lib.c index 42d80a1ee3..92ea4dced1 100644 --- a/components/lwip/api/api_lib.c +++ b/components/lwip/api/api_lib.c @@ -407,9 +407,9 @@ netconn_accept(struct netconn *conn, struct netconn **new_conn) #if TCP_LISTEN_BACKLOG /* Let the stack know that we have accepted the connection. */ API_MSG_VAR_ALLOC_DONTFAIL(msg); - API_MSG_VAR_REF(msg).msg.conn = conn; - /* don't care for the return value of lwip_netconn_do_recv */ - TCPIP_APIMSG_NOERR(&API_MSG_VAR_REF(msg), lwip_netconn_do_recv); + API_MSG_VAR_REF(msg).msg.conn = newconn; + /* don't care for the return value of lwip_netconn_do_accepted */ + TCPIP_APIMSG_NOERR(&API_MSG_VAR_REF(msg), lwip_netconn_do_accepted); API_MSG_VAR_FREE(msg); #endif /* TCP_LISTEN_BACKLOG */ diff --git a/components/lwip/api/api_msg.c b/components/lwip/api/api_msg.c index 32a3754190..531bca2352 100644 --- a/components/lwip/api/api_msg.c +++ b/components/lwip/api/api_msg.c @@ -536,6 +536,9 @@ accept_function(void *arg, struct tcp_pcb *newpcb, err_t err) to the application thread */ newconn->last_err = err; + /* handle backlog counter */ + tcp_backlog_delayed(newpcb); + if (sys_mbox_trypost(&conn->acceptmbox, newconn) != ERR_OK) { ESP_STATS_DROP_INC(esp.acceptmbox_post_fail); /* When returning != ERR_OK, the pcb is aborted in tcp_process(), @@ -1503,24 +1506,38 @@ lwip_netconn_do_recv(void *m) msg->err = ERR_OK; if (msg->conn->pcb.tcp != NULL) { if (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_TCP) { -#if TCP_LISTEN_BACKLOG - if (msg->conn->pcb.tcp->state == LISTEN) { - tcp_accepted(msg->conn->pcb.tcp); - } else -#endif /* TCP_LISTEN_BACKLOG */ - { - u32_t remaining = msg->msg.r.len; - do { - u16_t recved = (remaining > 0xffff) ? 0xffff : (u16_t)remaining; - tcp_recved(msg->conn->pcb.tcp, recved); - remaining -= recved; - } while (remaining != 0); - } + u32_t remaining = msg->msg.r.len; + do { + u16_t recved = (remaining > 0xffff) ? 0xffff : (u16_t)remaining; + tcp_recved(msg->conn->pcb.tcp, recved); + remaining -= recved; + } while (remaining != 0); } } TCPIP_APIMSG_ACK(msg); } +#if TCP_LISTEN_BACKLOG +/** Indicate that a TCP pcb has been accepted + * Called from netconn_accept + * + * @param m the api_msg pointing to the connection + */ +void +lwip_netconn_do_accepted(void *m) +{ + struct api_msg_msg *msg = (struct api_msg_msg *)m; + + msg->err = ERR_OK; + if (msg->conn->pcb.tcp != NULL) { + if (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_TCP) { + tcp_backlog_accepted(msg->conn->pcb.tcp); + } + } + TCPIP_APIMSG_ACK(msg); +} +#endif /* TCP_LISTEN_BACKLOG */ + /** * See if more data needs to be written from a previous call to netconn_write. * Called initially from lwip_netconn_do_write. If the first call can't send all data diff --git a/components/lwip/api/sockets.c b/components/lwip/api/sockets.c index badde6613a..184b1080be 100644 --- a/components/lwip/api/sockets.c +++ b/components/lwip/api/sockets.c @@ -266,11 +266,11 @@ do{\ }\ }while(0) -#define LWIP_SET_CLOSE_FLAG() \ +#define LWIP_SET_CLOSE_FLAG(_flag) \ do{\ LWIP_SOCK_LOCK(__sock);\ LWIP_DEBUGF(ESP_THREAD_SAFE_DEBUG, ("mark sock closing\n"));\ - __sock->state = LWIP_SOCK_CLOSING;\ + __sock->state = (_flag);\ LWIP_SOCK_UNLOCK(__sock);\ }while(0) @@ -3312,8 +3312,11 @@ int lwip_close_r(int s) { LWIP_API_LOCK(); - LWIP_SET_CLOSE_FLAG(); + LWIP_SET_CLOSE_FLAG(LWIP_SOCK_CLOSING); __ret = lwip_close(s); + if (EWOULDBLOCK == __sock->err) { + LWIP_SET_CLOSE_FLAG(LWIP_SOCK_OPEN); + } LWIP_API_UNLOCK(); } diff --git a/components/lwip/apps/dhcpserver.c b/components/lwip/apps/dhcpserver.c index a79d0fd638..718d22a546 100644 --- a/components/lwip/apps/dhcpserver.c +++ b/components/lwip/apps/dhcpserver.c @@ -373,13 +373,8 @@ static u8_t *add_offer_options(u8_t *optptr) *optptr++ = DHCP_OPTION_INTERFACE_MTU; *optptr++ = 2; -#ifdef CLASS_B_NET *optptr++ = 0x05; *optptr++ = 0xdc; -#else - *optptr++ = 0x02; - *optptr++ = 0x40; -#endif *optptr++ = DHCP_OPTION_PERFORM_ROUTER_DISCOVERY; *optptr++ = 1; diff --git a/components/lwip/core/ipv4/ip4.c b/components/lwip/core/ipv4/ip4.c index d2b9195a45..af8bf55aef 100644 --- a/components/lwip/core/ipv4/ip4.c +++ b/components/lwip/core/ipv4/ip4.c @@ -133,16 +133,14 @@ bool ip4_netif_exist(const ip4_addr_t *src, const ip4_addr_t *dest) return false; } /** - * Source based IPv4 routing hook function. This function works only - * when destination IP is broadcast IP. + * Source based IPv4 routing hook function. */ struct netif * ESP_IRAM_ATTR ip4_route_src_hook(const ip4_addr_t *dest, const ip4_addr_t *src) { struct netif *netif = NULL; - /* destination IP is broadcast IP? */ - if ((src != NULL) && (dest->addr == IPADDR_BROADCAST)) { + if ((src != NULL) && !ip4_addr_isany(src)) { /* iterate through netifs */ for (netif = netif_list; netif != NULL; netif = netif->next) { /* is the netif up, does it have a link and a valid address? */ diff --git a/components/lwip/core/netif.c b/components/lwip/core/netif.c index 2b25143c6f..b5995f26f7 100644 --- a/components/lwip/core/netif.c +++ b/components/lwip/core/netif.c @@ -453,10 +453,10 @@ void netif_set_ipaddr(struct netif *netif, const ip4_addr_t *ipaddr) { ip4_addr_t new_addr = (ipaddr ? *ipaddr : *IP4_ADDR_ANY); -#if ESP_LWIP +#if ESP_TCP_KEEP_CONNECTION_WHEN_IP_CHANGES ip4_addr_t *last_addr = ip_2_ip4(&netif->last_ip_addr); #else - ip4_addr_t *last_addr = netif_ip4_addr(netif); + ip4_addr_t *last_addr = ip_2_ip4(&(netif->ip_addr)); #endif /* address is actually being changed? */ diff --git a/components/lwip/core/tcp.c b/components/lwip/core/tcp.c index 920523e45d..596f3d4343 100644 --- a/components/lwip/core/tcp.c +++ b/components/lwip/core/tcp.c @@ -149,6 +149,22 @@ tcp_tmr(void) } } +#if LWIP_CALLBACK_API || TCP_LISTEN_BACKLOG +/** Called when a listen pcb is closed. Iterates one pcb list and removes the + * closed listener pcb from pcb->listener if matching. + */ +static void +tcp_remove_listener(struct tcp_pcb *list, struct tcp_pcb_listen *lpcb) +{ + struct tcp_pcb *pcb; + for (pcb = list; pcb != NULL; pcb = pcb->next) { + if (pcb->listener == lpcb) { + pcb->listener = NULL; + } + } +} +#endif + void tcp_set_fin_wait_1(struct tcp_pcb *pcb) { @@ -158,6 +174,70 @@ tcp_set_fin_wait_1(struct tcp_pcb *pcb) #endif } +/** Called when a listen pcb is closed. Iterates all pcb lists and removes the + * closed listener pcb from pcb->listener if matching. + */ +static void +tcp_listen_closed(struct tcp_pcb *pcb) +{ +#if LWIP_CALLBACK_API || TCP_LISTEN_BACKLOG + size_t i; + LWIP_ASSERT("pcb != NULL", pcb != NULL); + LWIP_ASSERT("pcb->state == LISTEN", pcb->state == LISTEN); + for (i = 1; i < LWIP_ARRAYSIZE(tcp_pcb_lists); i++) { + tcp_remove_listener(*tcp_pcb_lists[i], (struct tcp_pcb_listen *)pcb); + } +#endif + LWIP_UNUSED_ARG(pcb); +} + +#if TCP_LISTEN_BACKLOG +/** @ingroup tcp_raw + * Delay accepting a connection in respect to the listen backlog: + * the number of outstanding connections is increased until + * tcp_backlog_accepted() is called. + * + * ATTENTION: the caller is responsible for calling tcp_backlog_accepted() + * or else the backlog feature will get out of sync! + * + * @param pcb the connection pcb which is not fully accepted yet + */ +void +tcp_backlog_delayed(struct tcp_pcb *pcb) +{ + LWIP_ASSERT("pcb != NULL", pcb != NULL); + if ((pcb->flags & TF_BACKLOGPEND) == 0) { + if (pcb->listener != NULL) { + pcb->listener->accepts_pending++; + LWIP_ASSERT("accepts_pending != 0", pcb->listener->accepts_pending != 0); + pcb->flags |= TF_BACKLOGPEND; + } + } +} + +/** @ingroup tcp_raw + * A delayed-accept a connection is accepted (or closed/aborted): decreases + * the number of outstanding connections after calling tcp_backlog_delayed(). + * + * ATTENTION: the caller is responsible for calling tcp_backlog_accepted() + * or else the backlog feature will get out of sync! + * + * @param pcb the connection pcb which is now fully accepted (or closed/aborted) + */ +void +tcp_backlog_accepted(struct tcp_pcb *pcb) +{ + LWIP_ASSERT("pcb != NULL", pcb != NULL); + if ((pcb->flags & TF_BACKLOGPEND) != 0) { + if (pcb->listener != NULL) { + LWIP_ASSERT("accepts_pending != 0", pcb->listener->accepts_pending != 0); + pcb->listener->accepts_pending--; + pcb->flags &= ~TF_BACKLOGPEND; + } + } +} +#endif /* TCP_LISTEN_BACKLOG */ + /** * Closes the TX side of a connection held by the PCB. * For tcp_close(), a RST is sent if the application didn't receive all data @@ -227,6 +307,7 @@ tcp_close_shutdown(struct tcp_pcb *pcb, u8_t rst_on_unacked_data) break; case LISTEN: err = ERR_OK; + tcp_listen_closed(pcb); tcp_pcb_remove(&tcp_listen_pcbs.pcbs, pcb); memp_free(MEMP_TCP_PCB_LISTEN, pcb); pcb = NULL; @@ -241,6 +322,7 @@ tcp_close_shutdown(struct tcp_pcb *pcb, u8_t rst_on_unacked_data) case SYN_RCVD: err = tcp_send_fin(pcb); if (err == ERR_OK) { + tcp_backlog_accepted(pcb); MIB2_STATS_INC(mib2.tcpattemptfails); tcp_set_fin_wait_1(pcb); } @@ -408,6 +490,7 @@ tcp_abandon(struct tcp_pcb *pcb, int reset) pcb->ooseq = NULL; } #endif /* TCP_QUEUE_OOSEQ */ + tcp_backlog_accepted(pcb); if (send_rst) { LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_abandon: sending RST\n")); tcp_rst(seqno, ackno, &pcb->local_ip, &pcb->remote_ip, local_port, pcb->remote_port); @@ -1747,27 +1830,7 @@ tcp_pcb_purge(struct tcp_pcb *pcb) LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge\n")); -#if TCP_LISTEN_BACKLOG - if (pcb->state == SYN_RCVD) { - /* Need to find the corresponding listen_pcb and decrease its accepts_pending */ - struct tcp_pcb_listen *lpcb; - LWIP_ASSERT("tcp_pcb_purge: pcb->state == SYN_RCVD but tcp_listen_pcbs is NULL", - tcp_listen_pcbs.listen_pcbs != NULL); - for (lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = lpcb->next) { - if ((lpcb->local_port == pcb->local_port) && - (IP_IS_V6_VAL(pcb->local_ip) == IP_IS_V6_VAL(lpcb->local_ip)) && - (ip_addr_isany(&lpcb->local_ip) || - ip_addr_cmp(&pcb->local_ip, &lpcb->local_ip))) { - /* port and address of the listen pcb match the timed-out pcb */ - LWIP_ASSERT("tcp_pcb_purge: listen pcb does not have accepts pending", - lpcb->accepts_pending > 0); - lpcb->accepts_pending--; - break; - } - } - } -#endif /* TCP_LISTEN_BACKLOG */ - + tcp_backlog_accepted(pcb); if (pcb->refused_data != NULL) { LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge: data left on ->refused_data\n")); @@ -1917,6 +1980,31 @@ tcp_eff_send_mss_impl(u16_t sendmss, const ip_addr_t *dest } #endif /* TCP_CALCULATE_EFF_SEND_MSS */ +/** Helper function for tcp_netif_ip4_addr_changed() that iterates a pcb list */ +static void +tcp_netif_ip_addr_changed_pcblist(const ip4_addr_t* old_addr, struct tcp_pcb* pcb_list) +{ + struct tcp_pcb *pcb; + pcb = pcb_list; + while (pcb != NULL) { + /* PCB bound to current local interface address? */ + if (ip4_addr_cmp(ip_2_ip4(&pcb->local_ip), old_addr) +#if LWIP_AUTOIP + /* connections to link-local addresses must persist (RFC3927 ch. 1.9) */ + && (!IP_IS_V4_VAL(pcb->local_ip) || !ip4_addr_islinklocal(ip_2_ip4(&pcb->local_ip))) +#endif /* LWIP_AUTOIP */ + ) { + /* this connection must be aborted */ + struct tcp_pcb *next = pcb->next; + LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_STATE, ("netif_set_ipaddr: aborting TCP pcb %p\n", (void *)pcb)); + tcp_abort(pcb); + pcb = next; + } else { + pcb = pcb->next; + } + } +} + #if LWIP_IPV4 /** This function is called from netif.c when address is changed or netif is removed * @@ -1927,18 +2015,29 @@ void tcp_netif_ipv4_addr_changed(const ip4_addr_t* old_addr, const ip4_addr_t* n { struct tcp_pcb_listen *lpcb, *next; - if (!ip4_addr_isany(new_addr)) { - /* PCB bound to current local interface address? */ - for (lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = next) { - next = lpcb->next; - /* Is this an IPv4 pcb? */ - if (!IP_IS_V6_VAL(lpcb->local_ip)) { - /* PCB bound to current local interface address? */ - if ((!(ip4_addr_isany(ip_2_ip4(&lpcb->local_ip)))) && - (ip4_addr_cmp(ip_2_ip4(&lpcb->local_ip), old_addr))) { - /* The PCB is listening to the old ipaddr and - * is set to listen to the new one instead */ - ip_addr_copy_from_ip4(lpcb->local_ip, *new_addr); + if (!ip4_addr_isany(old_addr)) { +#if ESP_TCP_KEEP_CONNECTION_WHEN_IP_CHANGES + if ((new_addr == NULL) || ((!ip4_addr_isany_val(*new_addr)) && (!ip4_addr_cmp(old_addr, new_addr)))) { +#endif + tcp_netif_ip_addr_changed_pcblist(old_addr, tcp_active_pcbs); + tcp_netif_ip_addr_changed_pcblist(old_addr, tcp_bound_pcbs); +#if ESP_TCP_KEEP_CONNECTION_WHEN_IP_CHANGES + } +#endif + + if (!ip4_addr_isany(new_addr)) { + /* PCB bound to current local interface address? */ + for (lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = next) { + next = lpcb->next; + /* Is this an IPv4 pcb? */ + if (!IP_IS_V6_VAL(lpcb->local_ip)) { + /* PCB bound to current local interface address? */ + if ((!(ip4_addr_isany(ip_2_ip4(&lpcb->local_ip)))) && + (ip4_addr_cmp(ip_2_ip4(&lpcb->local_ip), old_addr))) { + /* The PCB is listening to the old ipaddr and + * is set to listen to the new one instead */ + ip_addr_copy_from_ip4(lpcb->local_ip, *new_addr); + } } } } diff --git a/components/lwip/core/tcp_in.c b/components/lwip/core/tcp_in.c index 23dc5ae1c1..a6f2946299 100644 --- a/components/lwip/core/tcp_in.c +++ b/components/lwip/core/tcp_in.c @@ -568,6 +568,7 @@ tcp_listen_input(struct tcp_pcb_listen *pcb) } #if TCP_LISTEN_BACKLOG pcb->accepts_pending++; + npcb->flags |= TF_BACKLOGPEND; #endif /* TCP_LISTEN_BACKLOG */ /* Set up the new PCB. */ ip_addr_copy(npcb->local_ip, *ip_current_dest_addr()); @@ -582,6 +583,10 @@ tcp_listen_input(struct tcp_pcb_listen *pcb) #if LWIP_CALLBACK_API npcb->accept = pcb->accept; #endif /* LWIP_CALLBACK_API */ + +#if LWIP_CALLBACK_API || TCP_LISTEN_BACKLOG + npcb->listener = pcb; +#endif /* inherit socket options */ npcb->so_options = pcb->so_options & SOF_INHERITED; /* Register the new PCB so that we can begin receiving segments @@ -785,11 +790,19 @@ tcp_process(struct tcp_pcb *pcb) if (TCP_SEQ_BETWEEN(ackno, pcb->lastack+1, pcb->snd_nxt)) { pcb->state = ESTABLISHED; LWIP_DEBUGF(TCP_DEBUG, ("TCP connection established %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest)); +#if LWIP_CALLBACK_API || TCP_LISTEN_BACKLOG #if LWIP_CALLBACK_API LWIP_ASSERT("pcb->accept != NULL", pcb->accept != NULL); #endif - /* Call the accept function. */ - TCP_EVENT_ACCEPT(pcb, ERR_OK, err); + + if (pcb->listener == NULL) { + err = ERR_VAL; + } else { +#endif + tcp_backlog_accepted(pcb); + /* Call the accept function. */ + TCP_EVENT_ACCEPT(pcb, ERR_OK, err); + } if (err != ERR_OK) { /* If the accept function returns with an error, we abort * the connection. */ diff --git a/components/lwip/include/lwip/lwip/ip_addr.h b/components/lwip/include/lwip/lwip/ip_addr.h index 74897a9ee9..5928f7eb24 100644 --- a/components/lwip/include/lwip/lwip/ip_addr.h +++ b/components/lwip/include/lwip/lwip/ip_addr.h @@ -47,6 +47,8 @@ extern "C" { #define IPADDR_TYPE_V6 6U #define IPADDR_TYPE_ANY 46U +#define IP_IS_V4_VAL(ipaddr) (IP_GET_TYPE(&ipaddr) == IPADDR_TYPE_V4) + #if LWIP_IPV4 && LWIP_IPV6 /** A union struct for both IP version's addresses. * ATTENTION: watch out for its size when adding IPv6 address scope! diff --git a/components/lwip/include/lwip/lwip/priv/api_msg.h b/components/lwip/include/lwip/lwip/priv/api_msg.h index 02d191a53c..a786b2ee44 100644 --- a/components/lwip/include/lwip/lwip/priv/api_msg.h +++ b/components/lwip/include/lwip/lwip/priv/api_msg.h @@ -232,6 +232,9 @@ void lwip_netconn_do_disconnect (void *m); void lwip_netconn_do_listen (void *m); void lwip_netconn_do_send (void *m); void lwip_netconn_do_recv (void *m); +#if TCP_LISTEN_BACKLOG +void lwip_netconn_do_accepted (void *m); +#endif void lwip_netconn_do_write (void *m); void lwip_netconn_do_getaddr (void *m); void lwip_netconn_do_close (void *m); diff --git a/components/lwip/include/lwip/lwip/tcp.h b/components/lwip/include/lwip/lwip/tcp.h index f7a46b2e83..269b4e3d39 100644 --- a/components/lwip/include/lwip/lwip/tcp.h +++ b/components/lwip/include/lwip/lwip/tcp.h @@ -138,7 +138,7 @@ typedef u16_t tcpflags_t; #define TCPWND16(x) (x) #define TCP_WND_MAX(pcb) TCP_WND(pcb) typedef u16_t tcpwnd_size_t; -typedef u8_t tcpflags_t; +typedef u16_t tcpflags_t; #endif enum tcp_state { @@ -203,6 +203,9 @@ struct tcp_pcb { #define TF_NAGLEMEMERR 0x80U /* nagle enabled, memerr, try to output to prevent delayed ACK to happen */ #if LWIP_WND_SCALE #define TF_WND_SCALE 0x0100U /* Window Scale option enabled */ +#endif +#if TCP_LISTEN_BACKLOG +#define TF_BACKLOGPEND 0x0200U /* If this is set, a connection pcb has increased the backlog on its listener */ #endif /* the rest of the fields are in host byte order @@ -311,6 +314,10 @@ struct tcp_pcb { u8_t rcv_scale; #endif +#if TCP_LISTEN_BACKLOG + struct tcp_pcb_listen *listener; +#endif + #if ESP_STATS_TCP #define ESP_STATS_TCP_ARRAY_SIZE 20 u16_t retry_cnt[TCP_MAXRTX]; @@ -383,16 +390,17 @@ void tcp_err (struct tcp_pcb *pcb, tcp_err_fn err); #define tcp_nagle_disabled(pcb) (((pcb)->flags & TF_NODELAY) != 0) #if TCP_LISTEN_BACKLOG -#define tcp_accepted(pcb) do { \ - LWIP_ASSERT("pcb->state == LISTEN (called for wrong pcb?)", pcb->state == LISTEN); \ - (((struct tcp_pcb_listen *)(pcb))->accepts_pending--); } while(0) #define tcp_backlog_set(pcb, new_backlog) do { \ LWIP_ASSERT("pcb->state == LISTEN (called for wrong pcb?)", (pcb)->state == LISTEN); \ ((struct tcp_pcb_listen *)(pcb))->backlog = ((new_backlog) ? (new_backlog) : 1); } while(0) +void tcp_backlog_delayed(struct tcp_pcb* pcb); +void tcp_backlog_accepted(struct tcp_pcb* pcb); #else /* TCP_LISTEN_BACKLOG */ -#define tcp_accepted(pcb) LWIP_ASSERT("pcb->state == LISTEN (called for wrong pcb?)", \ - (pcb)->state == LISTEN) +#define tcp_backlog_set(pcb, new_backlog) +#define tcp_backlog_delayed(pcb) +#define tcp_backlog_accepted(pcb) #endif /* TCP_LISTEN_BACKLOG */ +#define tcp_accepted(pcb) do { LWIP_UNUSED_ARG(pcb); } while(0) /* compatibility define, not needed any more */ void tcp_recved (struct tcp_pcb *pcb, u16_t len); err_t tcp_bind (struct tcp_pcb *pcb, const ip_addr_t *ipaddr, diff --git a/components/lwip/include/lwip/port/lwipopts.h b/components/lwip/include/lwip/port/lwipopts.h index 4d4ceb564f..8f1dd44ff5 100644 --- a/components/lwip/include/lwip/port/lwipopts.h +++ b/components/lwip/include/lwip/port/lwipopts.h @@ -296,6 +296,12 @@ */ #define TCP_QUEUE_OOSEQ CONFIG_TCP_QUEUE_OOSEQ +/** + * ESP_TCP_KEEP_CONNECTION_WHEN_IP_CHANGES==1: Keep TCP connection when IP changed + * scenario happens: 192.168.0.2 -> 0.0.0.0 -> 192.168.0.2 or 192.168.0.2 -> 0.0.0.0 + */ + +#define ESP_TCP_KEEP_CONNECTION_WHEN_IP_CHANGES CONFIG_ESP_TCP_KEEP_CONNECTION_WHEN_IP_CHANGES /* * LWIP_EVENT_API==1: The user defines lwip_tcp_event() to receive all * events (accept, sent, etc) that happen in the system. diff --git a/components/mbedtls/mbedtls b/components/mbedtls/mbedtls index b3a48ac894..b9ada30675 160000 --- a/components/mbedtls/mbedtls +++ b/components/mbedtls/mbedtls @@ -1 +1 @@ -Subproject commit b3a48ac894b660f6b99dd10f01818fb6fc389b42 +Subproject commit b9ada3067587aaccb37c33d41733bb82496c6342 diff --git a/components/mbedtls/port/mbedtls_debug.c b/components/mbedtls/port/mbedtls_debug.c index e9f038b6ab..316a76a990 100644 --- a/components/mbedtls/port/mbedtls_debug.c +++ b/components/mbedtls/port/mbedtls_debug.c @@ -34,12 +34,16 @@ void mbedtls_esp_enable_debug_log(mbedtls_ssl_config *conf, int threshold) switch(threshold) { case 1: level = ESP_LOG_WARN; + break; case 2: level = ESP_LOG_INFO; + break; case 3: level = ESP_LOG_DEBUG; + break; case 4: level = ESP_LOG_VERBOSE; + break; } esp_log_level_set(TAG, level); } @@ -76,6 +80,7 @@ static void mbedtls_esp_debug(void *ctx, int level, break; case 3: ESP_LOGD(TAG, "%s:%d %s", file, line, str); + break; case 4: ESP_LOGV(TAG, "%s:%d %s", file, line, str); break; diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index 8ead7c44d5..ce2f5fa87e 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -1180,7 +1180,7 @@ static void _mdns_create_answer_from_parsed_packet(mdns_parsed_packet_t * parsed } if (service) { if (q->type == MDNS_TYPE_PTR || q->type == MDNS_TYPE_ANY) { - if (q->type == MDNS_TYPE_PTR) { + if (q->type == MDNS_TYPE_PTR || !parsed_packet->probe) { shared = true; } if (!_mdns_alloc_answer(&packet->answers, MDNS_TYPE_PTR, service->service, false, false) @@ -1404,6 +1404,7 @@ static void _mdns_pcb_send_bye(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t i if (!packet) { return; } + packet->flags = MDNS_FLAGS_AUTHORITATIVE; size_t i; for (i=0; ianswers, MDNS_TYPE_PTR, services[i]->service, true, true)) { @@ -2554,7 +2555,7 @@ void mdns_parse_packet(mdns_rx_packet_t * packet) continue; } - if (type == MDNS_TYPE_ANY) { + if (type == MDNS_TYPE_ANY && !_str_null_or_empty(name->host)) { parsed_packet->probe = true; } @@ -3703,7 +3704,7 @@ static void _mdns_execute_action(mdns_action_t * action) a = a->next; } if (a->next == action->data.srv_del.service) { - mdns_srv_item_t * b = a; + mdns_srv_item_t * b = a->next; a->next = a->next->next; _mdns_send_bye(&b, 1, false); _mdns_free_service(b->service); diff --git a/components/micro-ecc/micro-ecc b/components/micro-ecc/micro-ecc index 14222e062d..d037ec8954 160000 --- a/components/micro-ecc/micro-ecc +++ b/components/micro-ecc/micro-ecc @@ -1 +1 @@ -Subproject commit 14222e062d77f45321676e813d9525f32a88e8fa +Subproject commit d037ec89546fad14b5c4d5456c2e23a71e554966 diff --git a/components/newlib/platform_include/esp_newlib.h b/components/newlib/platform_include/esp_newlib.h index 192844393b..31adf7d847 100644 --- a/components/newlib/platform_include/esp_newlib.h +++ b/components/newlib/platform_include/esp_newlib.h @@ -38,4 +38,9 @@ void esp_setup_syscall_table(); */ void esp_set_time_from_rtc(); +/* + * Sync counters RTC and FRC. Update boot_time. + */ +void esp_sync_counters_rtc_and_frc(); + #endif //__ESP_NEWLIB_H__ diff --git a/components/newlib/platform_include/sys/unistd.h b/components/newlib/platform_include/sys/unistd.h new file mode 100644 index 0000000000..e76c84b90b --- /dev/null +++ b/components/newlib/platform_include/sys/unistd.h @@ -0,0 +1,30 @@ +// 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. + + +#ifndef _ESP_SYS_UNISTD_H +#define _ESP_SYS_UNISTD_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include_next + +int _EXFUN(truncate, (const char *, off_t __length)); + +#ifdef __cplusplus +} +#endif +#endif /* _SYS_UNISTD_H */ diff --git a/components/newlib/test/test_newlib.c b/components/newlib/test/test_newlib.c index 2836fc3d27..10d81e1630 100644 --- a/components/newlib/test/test_newlib.c +++ b/components/newlib/test/test_newlib.c @@ -124,15 +124,20 @@ static bool fn_in_rom(void *fn, const char *name) TEST_CASE("check if ROM or Flash is used for functions", "[newlib]") { -#ifdef CONFIG_NEWLIB_NANO_FORMAT +#if defined(CONFIG_NEWLIB_NANO_FORMAT) && !defined(CONFIG_SPIRAM_SUPPORT) TEST_ASSERT(fn_in_rom(printf, "printf")); TEST_ASSERT(fn_in_rom(sscanf, "sscanf")); #else TEST_ASSERT_FALSE(fn_in_rom(printf, "printf")); TEST_ASSERT_FALSE(fn_in_rom(sscanf, "sscanf")); #endif +#if !defined(CONFIG_SPIRAM_SUPPORT) TEST_ASSERT(fn_in_rom(atoi, "atoi")); TEST_ASSERT(fn_in_rom(strtol, "strtol")); +#else + TEST_ASSERT_FALSE(fn_in_rom(atoi, "atoi")); + TEST_ASSERT_FALSE(fn_in_rom(strtol, "strtol")); +#endif } #ifndef CONFIG_NEWLIB_NANO_FORMAT diff --git a/components/newlib/time.c b/components/newlib/time.c index 37b78f3de5..6137f21435 100644 --- a/components/newlib/time.c +++ b/components/newlib/time.c @@ -36,6 +36,7 @@ #include "freertos/xtensa_api.h" #include "freertos/task.h" #include "sdkconfig.h" +#include "limits.h" #if defined( CONFIG_ESP32_TIME_SYSCALL_USE_RTC ) || defined( CONFIG_ESP32_TIME_SYSCALL_USE_RTC_FRC1 ) #define WITH_RTC 1 @@ -80,9 +81,9 @@ static uint64_t s_boot_time; static _lock_t s_boot_time_lock; static _lock_t s_adjust_time_lock; // stores the start time of the slew -RTC_DATA_ATTR static uint64_t adjtime_start = 0; +static uint64_t adjtime_start = 0; // is how many microseconds total to slew -RTC_DATA_ATTR static int64_t adjtime_total_correction = 0; +static int64_t adjtime_total_correction = 0; #define ADJTIME_CORRECTION_FACTOR 6 static uint64_t get_time_since_boot(); #endif @@ -371,3 +372,11 @@ uint64_t system_get_rtc_time(void) #endif } +void esp_sync_counters_rtc_and_frc() +{ +#if defined( WITH_FRC ) && defined( WITH_RTC ) + adjtime_corr_stop(); + int64_t s_microseconds_offset_cur = get_rtc_time_us() - esp_timer_get_time(); + set_boot_time(get_adjusted_boot_time() + ((int64_t)s_microseconds_offset - s_microseconds_offset_cur)); +#endif +} diff --git a/components/nghttp/port/http_parser.c b/components/nghttp/port/http_parser.c index 3c896ffadc..8c1f4dd077 100644 --- a/components/nghttp/port/http_parser.c +++ b/components/nghttp/port/http_parser.c @@ -1814,7 +1814,7 @@ reexecute: case 2: parser->upgrade = 1; - + /* falls through */ case 1: parser->flags |= F_SKIPBODY; break; @@ -2374,7 +2374,7 @@ http_parser_parse_url(const char *buf, size_t buflen, int is_connect, case s_req_server_with_at: found_at = 1; - /* FALLTROUGH */ + /* falls through */ case s_req_server: uf = UF_HOST; break; diff --git a/components/nvs_flash/include/nvs.h b/components/nvs_flash/include/nvs.h index c58f62f9c6..44c6c7a2ca 100644 --- a/components/nvs_flash/include/nvs.h +++ b/components/nvs_flash/include/nvs.h @@ -38,12 +38,13 @@ typedef uint32_t nvs_handle; #define ESP_ERR_NVS_INVALID_HANDLE (ESP_ERR_NVS_BASE + 0x07) /*!< Handle has been closed or is NULL */ #define ESP_ERR_NVS_REMOVE_FAILED (ESP_ERR_NVS_BASE + 0x08) /*!< The value wasn’t updated because flash write operation has failed. The value was written however, and update will be finished after re-initialization of nvs, provided that flash operation doesn’t fail again. */ #define ESP_ERR_NVS_KEY_TOO_LONG (ESP_ERR_NVS_BASE + 0x09) /*!< Key name is too long */ -#define ESP_ERR_NVS_PAGE_FULL (ESP_ERR_NVS_BASE + 0x0a) /*!< Internal error; never returned by nvs_ API functions */ +#define ESP_ERR_NVS_PAGE_FULL (ESP_ERR_NVS_BASE + 0x0a) /*!< Internal error; never returned by nvs API functions */ #define ESP_ERR_NVS_INVALID_STATE (ESP_ERR_NVS_BASE + 0x0b) /*!< NVS is in an inconsistent state due to a previous error. Call nvs_flash_init and nvs_open again, then retry. */ #define ESP_ERR_NVS_INVALID_LENGTH (ESP_ERR_NVS_BASE + 0x0c) /*!< String or blob length is not sufficient to store data */ #define ESP_ERR_NVS_NO_FREE_PAGES (ESP_ERR_NVS_BASE + 0x0d) /*!< NVS partition doesn't contain any empty pages. This may happen if NVS partition was truncated. Erase the whole partition and call nvs_flash_init again. */ #define ESP_ERR_NVS_VALUE_TOO_LONG (ESP_ERR_NVS_BASE + 0x0e) /*!< String or blob length is longer than supported by the implementation */ #define ESP_ERR_NVS_PART_NOT_FOUND (ESP_ERR_NVS_BASE + 0x0f) /*!< Partition with specified name is not found in the partition table */ +#define ESP_ERR_NVS_NEW_VERSION_FOUND (ESP_ERR_NVS_BASE + 0x10) /*!< NVS partition contains data in new format and cannot be recognized by this version of code */ #define NVS_DEFAULT_PART_NAME "nvs" /*!< Default partition name of the NVS partition in the partition table */ /** diff --git a/components/nvs_flash/nvs_partition_generator/README.rst b/components/nvs_flash/nvs_partition_generator/README.rst index 5b62ebc394..f324f016f1 100644 --- a/components/nvs_flash/nvs_partition_generator/README.rst +++ b/components/nvs_flash/nvs_partition_generator/README.rst @@ -19,9 +19,9 @@ Type Supported values are ``file``, ``data`` and ``namespace``. Encoding - Supported values are: ``u8``, ``i8``, ``u16``, ``u32``, ``i32``, ``string``, ``hex2bin`` and ``binary``. This specifies how actual data values are encoded in the resultant binary file. Difference between ``string`` and ``binary`` encoding is that ``string`` data is terminated with a NULL character, whereas ``binary`` data is not. + Supported values are: ``u8``, ``i8``, ``u16``, ``u32``, ``i32``, ``string``, ``hex2bin``, ``base64`` and ``binary``. This specifies how actual data values are encoded in the resultant binary file. Difference between ``string`` and ``binary`` encoding is that ``string`` data is terminated with a NULL character, whereas ``binary`` data is not. - .. note:: For ``file`` type, only ``hex2bin``, ``string`` and ``binary`` is supported as of now. + .. note:: For ``file`` type, only ``hex2bin``, ``base64``, ``string`` and ``binary`` is supported as of now. Value Data value. diff --git a/components/nvs_flash/nvs_partition_generator/nvs_partition_gen.py b/components/nvs_flash/nvs_partition_generator/nvs_partition_gen.py old mode 100644 new mode 100755 index ecbe9b5db0..6224d3b94b --- a/components/nvs_flash/nvs_partition_generator/nvs_partition_gen.py +++ b/components/nvs_flash/nvs_partition_generator/nvs_partition_gen.py @@ -132,7 +132,7 @@ class Page(object): # set Type if encoding == "string": entry_struct[1] = Page.SZ - elif encoding == "hex2bin" or encoding == "binary": + elif encoding in ["hex2bin", "binary", "base64"]: entry_struct[1] = Page.BLOB # compute CRC of data @@ -248,11 +248,14 @@ class NVS(object): raise InputError("%s: Invalid data length. Should be multiple of 2." % key) value = binascii.a2b_hex(value) + if encoding == "base64": + value = binascii.a2b_base64(value) + if encoding == "string": value += '\0' encoding = encoding.lower() - varlen_encodings = ["string", "binary", "hex2bin"] + varlen_encodings = ["string", "binary", "hex2bin", "base64"] primitive_encodings = ["u8", "i8", "u16", "u32", "i32"] if encoding in varlen_encodings: try: @@ -308,7 +311,7 @@ def write_entry(nvs_instance, key, datatype, encoding, value): :param nvs_instance: Instance of an NVS class returned by nvs_open() :param key: Key of the data :param datatype: Data type. Valid values are "file", "data" and "namespace" - :param encoding: Data encoding. Valid values are "u8", "i8", "u16", "u32", "i32", "string", "binary" and "hex2bin" + :param encoding: Data encoding. Valid values are "u8", "i8", "u16", "u32", "i32", "string", "binary", "hex2bin" and "base64" :param value: Data value in ascii encoded string format for "data" datatype and filepath for "file" datatype :return: None """ @@ -333,29 +336,42 @@ def nvs_close(nvs_instance): """ nvs_instance.__exit__(None, None, None) -def main(): - parser = argparse.ArgumentParser(description="ESP32 NVS partition generation utility") - parser.add_argument( - "input", - help="Path to CSV file to parse. Will use stdin if omitted", - type=argparse.FileType('rb'), - default=sys.stdin) +def nvs_part_gen(input_filename=None, output_filename=None): + input_file = open(input_filename, 'rb') + output_file = open(output_filename, 'wb') - parser.add_argument( - "output", - help='Path to output converted binary file. Will use stdout if omitted', - type=argparse.FileType('wb'), - default=sys.stdout) - - args = parser.parse_args() - with nvs_open(args.output) as nvs_obj: - reader = csv.DictReader(args.input, delimiter=',') + with nvs_open(output_file) as nvs_obj: + reader = csv.DictReader(input_file, delimiter=',') for row in reader: try: write_entry(nvs_obj, row["key"], row["type"], row["encoding"], row["value"]) except InputError as e: print(e) + input_file.close() + output_file.close() exit(-2) + input_file.close() + output_file.close() + +def main(): + parser = argparse.ArgumentParser(description="ESP32 NVS partition generation utility") + parser.add_argument( + "input", + help="Path to CSV file to parse. Will use stdin if omitted", + default=sys.stdin) + + parser.add_argument( + "output", + help='Path to output converted binary file. Will use stdout if omitted', + default=sys.stdout) + + args = parser.parse_args() + input_filename = args.input + output_filename = args.output + nvs_part_gen(input_filename, output_filename) + + + if __name__ == "__main__": main() diff --git a/components/nvs_flash/nvs_partition_generator/sample.csv b/components/nvs_flash/nvs_partition_generator/sample.csv index ccade4dbb1..bc70aa14c7 100644 --- a/components/nvs_flash/nvs_partition_generator/sample.csv +++ b/components/nvs_flash/nvs_partition_generator/sample.csv @@ -7,6 +7,8 @@ dummyU32Key,data,u32,4294967295 dummyI32Key,data,i32,-2147483648 dummyStringKey,data,string,0A:0B:0C:0D:0E:0F dummyHex2BinKey,data,hex2bin,010203abcdef +dummyBase64Key,data,base64,MTIzYWJj hexFileKey,file,hex2bin,testdata/sample.hex +base64FileKey,file,base64,testdata/sample.base64 stringFileKey,file,string,testdata/sample.txt binFileKey,file,binary,testdata/sample.bin diff --git a/components/nvs_flash/nvs_partition_generator/testdata/sample.base64 b/components/nvs_flash/nvs_partition_generator/testdata/sample.base64 new file mode 100644 index 0000000000..0c16c99a22 --- /dev/null +++ b/components/nvs_flash/nvs_partition_generator/testdata/sample.base64 @@ -0,0 +1 @@ +AQIDBAUGBwgJq83v diff --git a/components/nvs_flash/src/nvs_api.cpp b/components/nvs_flash/src/nvs_api.cpp index 40d67b942b..8d0e6c0389 100644 --- a/components/nvs_flash/src/nvs_api.cpp +++ b/components/nvs_flash/src/nvs_api.cpp @@ -28,6 +28,9 @@ static const char* TAG = "nvs"; #define ESP_LOGD(...) #endif +extern "C" void nvs_dump(const char *partName); +extern "C" esp_err_t nvs_flash_init_custom(const char *partName, uint32_t baseSector, uint32_t sectorCount); + class HandleEntry : public intrusive_list_node { static uint32_t s_nvs_next_handle; diff --git a/components/nvs_flash/src/nvs_page.cpp b/components/nvs_flash/src/nvs_page.cpp index 9fc1a6edad..7590a7fd58 100644 --- a/components/nvs_flash/src/nvs_page.cpp +++ b/components/nvs_flash/src/nvs_page.cpp @@ -64,6 +64,11 @@ esp_err_t Page::load(uint32_t sectorNumber) } else { mState = header.mState; mSeqNumber = header.mSeqNumber; + if(header.mVersion < NVS_VERSION) { + return ESP_ERR_NVS_NEW_VERSION_FOUND; + } else { + mVersion = header.mVersion; + } } switch (mState) { @@ -628,6 +633,7 @@ esp_err_t Page::initialize() Header header; header.mState = mState; header.mSeqNumber = mSeqNumber; + header.mVersion = mVersion; header.mCrc32 = header.calculateCrc32(); auto rc = spi_flash_write(mBaseAddress, &header, sizeof(header)); @@ -799,6 +805,15 @@ esp_err_t Page::setSeqNumber(uint32_t seqNumber) return ESP_OK; } +esp_err_t Page::setVersion(uint8_t ver) +{ + if (mState != PageState::UNINITIALIZED) { + return ESP_ERR_NVS_INVALID_STATE; + } + mVersion = ver; + return ESP_OK; +} + esp_err_t Page::erase() { auto sector = mBaseAddress / SPI_FLASH_SEC_SIZE; diff --git a/components/nvs_flash/src/nvs_page.hpp b/components/nvs_flash/src/nvs_page.hpp index 9baa76dbf1..67f3840b2f 100644 --- a/components/nvs_flash/src/nvs_page.hpp +++ b/components/nvs_flash/src/nvs_page.hpp @@ -51,6 +51,8 @@ public: static const uint8_t NS_INDEX = 0; static const uint8_t NS_ANY = 255; + static const uint8_t NVS_VERSION = 0xff; // Decrement to upgrade + enum class PageState : uint32_t { // All bits set, default state after flash erase. Page has not been initialized yet. UNINITIALIZED = 0xffffffff, @@ -83,6 +85,8 @@ public: esp_err_t getSeqNumber(uint32_t& seqNumber) const; esp_err_t setSeqNumber(uint32_t seqNumber); + + esp_err_t setVersion(uint8_t version); esp_err_t writeItem(uint8_t nsIndex, ItemType datatype, const char* key, const void* data, size_t dataSize); @@ -142,12 +146,13 @@ protected: public: Header() { - std::fill_n(mReserved, sizeof(mReserved)/sizeof(mReserved[0]), UINT32_MAX); + std::fill_n(mReserved, sizeof(mReserved)/sizeof(mReserved[0]), UINT8_MAX); } PageState mState; // page state uint32_t mSeqNumber; // sequence number of this page - uint32_t mReserved[5]; // unused, must be 0xffffffff + uint8_t mVersion; // nvs format version + uint8_t mReserved[19]; // unused, must be 0xff uint32_t mCrc32; // crc of everything except mState uint32_t calculateCrc32(); @@ -198,6 +203,7 @@ protected: uint32_t mBaseAddress = 0; PageState mState = PageState::INVALID; uint32_t mSeqNumber = UINT32_MAX; + uint8_t mVersion = NVS_VERSION; typedef CompressedEnumTable TEntryTable; TEntryTable mEntryTable; size_t mNextFreeEntry = INVALID_ENTRY; diff --git a/components/nvs_flash/test/test_nvs.c b/components/nvs_flash/test/test_nvs.c index 87ca519944..87f2c677b0 100644 --- a/components/nvs_flash/test/test_nvs.c +++ b/components/nvs_flash/test/test_nvs.c @@ -16,7 +16,7 @@ TEST_CASE("various nvs tests", "[nvs]") { nvs_handle handle_1; esp_err_t err = nvs_flash_init(); - if (err == ESP_ERR_NVS_NO_FREE_PAGES) { + if (err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND) { ESP_LOGW(TAG, "nvs_flash_init failed (0x%x), erasing partition and retrying", err); const esp_partition_t* nvs_partition = esp_partition_find_first( ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_NVS, NULL); @@ -83,7 +83,7 @@ TEST_CASE("calculate used and free space", "[nvs]") TEST_ASSERT_TRUE(h_count_entries == 0); esp_err_t err = nvs_flash_init(); - if (err == ESP_ERR_NVS_NO_FREE_PAGES) { + if (err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND) { ESP_LOGW(TAG, "nvs_flash_init failed (0x%x), erasing partition and retrying", err); const esp_partition_t* nvs_partition = esp_partition_find_first( ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_NVS, NULL); diff --git a/components/nvs_flash/test_nvs_host/esp_error_check_stub.cpp b/components/nvs_flash/test_nvs_host/esp_error_check_stub.cpp index 9cff4af310..34d8704e7b 100644 --- a/components/nvs_flash/test_nvs_host/esp_error_check_stub.cpp +++ b/components/nvs_flash/test_nvs_host/esp_error_check_stub.cpp @@ -1,9 +1,14 @@ #include "catch.hpp" #include "esp_err.h" +#include "sdkconfig.h" void _esp_error_check_failed(esp_err_t rc, const char *file, int line, const char *function, const char *expression) { - printf("ESP_ERROR_CHECK failed: esp_err_t 0x%x at %p\n", rc, __builtin_return_address(0)); + printf("ESP_ERROR_CHECK failed: esp_err_t 0x%x", rc); +#ifdef CONFIG_ESP_ERR_TO_NAME_LOOKUP + printf(" (%s)", esp_err_to_name(rc)); +#endif //CONFIG_ESP_ERR_TO_NAME_LOOKUP + printf(" at %p\n", __builtin_return_address(0)); printf("file: \"%s\" line %d\nfunc: %s\nexpression: %s\n", file, line, function, expression); abort(); } diff --git a/components/nvs_flash/test_nvs_host/test_nvs.cpp b/components/nvs_flash/test_nvs_host/test_nvs.cpp index 658fdb53fb..22d30d0557 100644 --- a/components/nvs_flash/test_nvs_host/test_nvs.cpp +++ b/components/nvs_flash/test_nvs_host/test_nvs.cpp @@ -1548,6 +1548,9 @@ TEST_CASE("read data from partition generated via partition generation utility", uint8_t hexdata[] = {0x01, 0x02, 0x03, 0xab, 0xcd, 0xef}; TEST_ESP_OK( nvs_get_blob(handle, "dummyHex2BinKey", buf, &buflen)); CHECK(memcmp(buf, hexdata, buflen) == 0); + uint8_t base64data[] = {'1', '2', '3', 'a', 'b', 'c'}; + TEST_ESP_OK( nvs_get_blob(handle, "dummyBase64Key", buf, &buflen)); + CHECK(memcmp(buf, base64data, buflen) == 0); } TEST_CASE("dump all performance data", "[nvs]") diff --git a/components/partition_table/CMakeLists.txt b/components/partition_table/CMakeLists.txt index eae14ceb2f..aa835c704b 100644 --- a/components/partition_table/CMakeLists.txt +++ b/components/partition_table/CMakeLists.txt @@ -1,14 +1,8 @@ register_config_only_component() -# Set partition_csv to the configured partition source file -# -if(CONFIG_PARTITION_TABLE_CUSTOM) - # Custom filename expands any path relative to the project - get_filename_component(partition_csv "${CONFIG_PARTITION_TABLE_FILENAME}" ABSOLUTE BASE_DIR "${PROJECT_PATH}") -else() - # Other .csv files are always in the component directory - set(partition_csv "${CMAKE_CURRENT_SOURCE_DIR}/${CONFIG_PARTITION_TABLE_FILENAME}") -endif() +if(NOT BOOTLOADER_BUILD) + +set(partition_csv "${PARTITION_CSV_PATH}") if(CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES) set(unsigned_partition_bin "partition-table-unsigned.bin") @@ -56,3 +50,4 @@ set_property(GLOBAL APPEND_STRING PROPERTY ESPTOOL_WRITE_FLASH_ARGS "${PARTITION_TABLE_OFFSET} ${final_partition_bin} ") +endif() diff --git a/components/partition_table/Kconfig.projbuild b/components/partition_table/Kconfig.projbuild index 09635d67a3..db311145e0 100644 --- a/components/partition_table/Kconfig.projbuild +++ b/components/partition_table/Kconfig.projbuild @@ -27,22 +27,6 @@ config PARTITION_TABLE_CUSTOM_FILENAME Name of the custom partition CSV filename. This path is evaluated relative to the project root directory. -config PARTITION_TABLE_CUSTOM_APP_BIN_OFFSET - hex "Factory app partition offset" if PARTITION_TABLE_CUSTOM - default 0x10000 - help - If using a custom partition table, specify the offset in the flash - where 'make flash' should write the built app. - -config PARTITION_TABLE_CUSTOM_PHY_DATA_OFFSET - hex "PHY data partition offset" if PARTITION_TABLE_CUSTOM - depends on ESP32_PHY_INIT_DATA_IN_PARTITION - default 0xf000 - help - If using a custom partition table, specify the offset in the flash - where 'make flash' should write the initial PHY data file. - - config PARTITION_TABLE_FILENAME string default partitions_singleapp.csv if PARTITION_TABLE_SINGLE_APP && !ESP32_ENABLE_COREDUMP_TO_FLASH @@ -51,16 +35,13 @@ config PARTITION_TABLE_FILENAME default partitions_two_ota_coredump.csv if PARTITION_TABLE_TWO_OTA && ESP32_ENABLE_COREDUMP_TO_FLASH default PARTITION_TABLE_CUSTOM_FILENAME if PARTITION_TABLE_CUSTOM -config APP_OFFSET - hex - default PARTITION_TABLE_CUSTOM_APP_BIN_OFFSET if PARTITION_TABLE_CUSTOM - default 0x10000 # this is the factory app offset used by the default tables - -config PHY_DATA_OFFSET - depends on ESP32_PHY_INIT_DATA_IN_PARTITION - hex - default PARTITION_TABLE_CUSTOM_PHY_DATA_OFFSET if PARTITION_TABLE_CUSTOM - default 0xf000 # this is the factory app offset used by the default tables +config PARTITION_TABLE_OFFSET + hex "Offset of partition table" + default 0x8000 + help + The address of partition table (by default 0x8000). + Allows you to move the partition table, it gives more space for the bootloader. + Note that the bootloader and app will both need to be compiled with the same PARTITION_TABLE_OFFSET value. config PARTITION_TABLE_MD5 bool "Generate an MD5 checksum for the partition table" diff --git a/components/partition_table/Makefile.projbuild b/components/partition_table/Makefile.projbuild index 930737fffa..4973201f38 100644 --- a/components/partition_table/Makefile.projbuild +++ b/components/partition_table/Makefile.projbuild @@ -6,10 +6,10 @@ # the partition table binary as part of the build process. This # binary is then added to the list of files for esptool.py to flash. # -.PHONY: partition_table partition_table-flash partition_table-clean +.PHONY: partition_table partition_table-flash partition_table-clean partition_table_get_info PARTITION_MD5_OPT := -ifneq ("$(CONFIG_PARTITION_TABLE_MD5)", "y") +ifndef CONFIG_PARTITION_TABLE_MD5 PARTITION_MD5_OPT := "--disable-md5sum" endif @@ -18,10 +18,19 @@ ifneq ("$(CONFIG_ESPTOOLPY_FLASHSIZE)", "") PARTITION_FLASHSIZE_OPT := --flash-size $(CONFIG_ESPTOOLPY_FLASHSIZE) endif -GEN_ESP32PART := $(PYTHON) $(COMPONENT_PATH)/gen_esp32part.py -q $(PARTITION_MD5_OPT) $(PARTITION_FLASHSIZE_OPT) +PARTITION_SECURE_OPT := +ifdef CONFIG_SECURE_BOOT_ENABLED +ifndef CONFIG_SECURE_BOOT_ALLOW_SHORT_APP_PARTITION +PARTITION_SECURE_OPT += --secure +endif +endif -# Has a matching value in bootloader_support esp_flash_partitions.h -PARTITION_TABLE_OFFSET := 0x8000 +# Address of partition table +PARTITION_TABLE_OFFSET := $(CONFIG_PARTITION_TABLE_OFFSET) +PARTITION_TABLE_OFFSET_ARG := --offset $(PARTITION_TABLE_OFFSET) + +GEN_ESP32PART := $(PYTHON) $(COMPONENT_PATH)/gen_esp32part.py -q $(PARTITION_MD5_OPT) $(PARTITION_FLASHSIZE_OPT) $(PARTITION_TABLE_OFFSET_ARG) $(PARTITION_SECURE_OPT) +GET_PART_INFO := $(COMPONENT_PATH)/parttool.py -q # if CONFIG_PARTITION_TABLE_FILENAME is unset, means we haven't re-generated config yet... ifneq ("$(CONFIG_PARTITION_TABLE_FILENAME)","") @@ -51,12 +60,19 @@ $(PARTITION_TABLE_BIN_UNSIGNED): $(PARTITION_TABLE_CSV_PATH) $(SDKCONFIG_MAKEFIL @echo "Building partitions from $(PARTITION_TABLE_CSV_PATH)..." $(GEN_ESP32PART) $< $@ -all_binaries: $(PARTITION_TABLE_BIN) +all_binaries: $(PARTITION_TABLE_BIN) partition_table_get_info + +partition_table_get_info: $(PARTITION_TABLE_BIN) + $(eval PHY_DATA_OFFSET:=$(shell $(GET_PART_INFO) --type data --subtype phy --offset $(PARTITION_TABLE_BIN))) + $(eval APP_OFFSET:=$(shell $(GET_PART_INFO) --default-boot-partition --offset $(PARTITION_TABLE_BIN))) + +export APP_OFFSET +export PHY_DATA_OFFSET PARTITION_TABLE_FLASH_CMD = $(ESPTOOLPY_SERIAL) write_flash $(PARTITION_TABLE_OFFSET) $(PARTITION_TABLE_BIN) ESPTOOL_ALL_FLASH_ARGS += $(PARTITION_TABLE_OFFSET) $(PARTITION_TABLE_BIN) -partition_table: $(PARTITION_TABLE_BIN) +partition_table: $(PARTITION_TABLE_BIN) partition_table_get_info @echo "Partition table binary generated. Contents:" @echo $(SEPARATOR) $(GEN_ESP32PART) $< diff --git a/components/partition_table/gen_esp32part.py b/components/partition_table/gen_esp32part.py index 275976b741..92bf35a233 100755 --- a/components/partition_table/gen_esp32part.py +++ b/components/partition_table/gen_esp32part.py @@ -4,7 +4,7 @@ # # Converts partition tables to/from CSV and binary formats. # -# See http://esp-idf.readthedocs.io/en/latest/api-guides/partition-tables.html +# See https://docs.espressif.com/projects/esp-idf/en/latest/api-guides/partition-tables.html # for explanation of partition table structure and uses. # # Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD @@ -31,11 +31,14 @@ import binascii MAX_PARTITION_LENGTH = 0xC00 # 3K for partition data (96 entries) leaves 1K in a 4K sector for signature MD5_PARTITION_BEGIN = b"\xEB\xEB" + b"\xFF" * 14 # The first 2 bytes are like magic numbers for MD5 sum +PARTITION_TABLE_SIZE = 0x1000 # Size of partition table -__version__ = '1.0' +__version__ = '1.1' quiet = False md5sum = True +secure = False +offset_part_table = 0 def status(msg): """ Print status message to stderr """ @@ -77,8 +80,11 @@ class PartitionTable(list): raise # fix up missing offsets & negative sizes - last_end = 0x5000 # first offset after partition table + last_end = offset_part_table + PARTITION_TABLE_SIZE # first offset after partition table for e in res: + if offset_part_table != 0 and e.offset is not None and e.offset < last_end: + critical("WARNING: 0x%x address in the partition table is below 0x%x" % (e.offset, last_end)) + e.offset = None if e.offset is None: pad_to = 0x10000 if e.type == PartitionDefinition.APP_TYPE else 4 if last_end % pad_to != 0: @@ -101,6 +107,38 @@ class PartitionTable(list): else: return super(PartitionTable, self).__getitem__(item) + def find_by_type(self, ptype, subtype): + """ Return a partition by type & subtype, returns + None if not found """ + TYPES = PartitionDefinition.TYPES + SUBTYPES = PartitionDefinition.SUBTYPES + # convert ptype & subtypes names (if supplied this way) to integer values + try: + ptype = TYPES[ptype] + except KeyError: + try: + ptypes = int(ptype, 0) + except TypeError: + pass + try: + subtype = SUBTYPES[int(ptype)][subtype] + except KeyError: + try: + ptypes = int(ptype, 0) + except TypeError: + pass + + for p in self: + if p.type == ptype and p.subtype == subtype: + return p + return None + + def find_by_name(self, name): + for p in self: + if p.name == name: + return p + return None + def verify(self): # verify each partition individually for p in self: @@ -108,8 +146,8 @@ class PartitionTable(list): # check for overlaps last = None for p in sorted(self, key=lambda x:x.offset): - if p.offset < 0x5000: - raise InputError("Partition offset 0x%x is below 0x5000" % p.offset) + if p.offset < offset_part_table + PARTITION_TABLE_SIZE: + raise InputError("Partition offset 0x%x is below 0x%x" % (p.offset, offset_part_table + PARTITION_TABLE_SIZE)) if last is not None and p.offset < last.offset + last.size: raise InputError("Partition at 0x%x overlaps 0x%x-0x%x" % (p.offset, last.offset, last.offset+last.size-1)) last = p @@ -197,7 +235,7 @@ class PartitionDefinition(object): "encrypted" : 0 } - # add subtypes for the 16 OTA slot values ("ota_XXX, etc.") + # add subtypes for the 16 OTA slot values ("ota_XX, etc.") for ota_slot in range(16): SUBTYPES[TYPES["app"]]["ota_%d" % ota_slot] = 0x10 + ota_slot @@ -250,6 +288,18 @@ class PartitionDefinition(object): def __cmp__(self, other): return self.offset - other.offset + def __lt__(self, other): + return self.offset < other.offset + + def __gt__(self, other): + return self.offset > other.offset + + def __le__(self, other): + return self.offset <= other.offset + + def __ge__(self, other): + return self.offset >= other.offset + def parse_type(self, strval): if strval == "": raise InputError("Field 'type' can't be left empty.") @@ -275,6 +325,8 @@ class PartitionDefinition(object): align = self.ALIGNMENT.get(self.type, 4) 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: + 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") @@ -358,6 +410,8 @@ def parse_int(v, keywords={}): def main(): global quiet global md5sum + global offset_part_table + global secure parser = argparse.ArgumentParser(description='ESP32 partition table utility') parser.add_argument('--flash-size', help='Optional flash size limit, checks partition table fits in flash', @@ -365,7 +419,8 @@ def main(): parser.add_argument('--disable-md5sum', help='Disable md5 checksum for the partition table', default=False, action='store_true') parser.add_argument('--verify', '-v', help='Verify partition table fields', default=True, action='store_false') parser.add_argument('--quiet', '-q', help="Don't print status messages to stderr", action='store_true') - + parser.add_argument('--offset', '-o', help='Set offset partition table', default='0x8000') + parser.add_argument('--secure', help="Require app partitions to be suitable for secure boot", action='store_true') parser.add_argument('input', help='Path to CSV or binary file to parse. Will use stdin if omitted.', type=argparse.FileType('rb'), default=sys.stdin) parser.add_argument('output', help='Path to output converted binary or CSV file. Will use stdout if omitted, unless the --display argument is also passed (in which case only the summary is printed.)', nargs='?', @@ -375,6 +430,8 @@ def main(): quiet = args.quiet md5sum = not args.disable_md5sum + secure = args.secure + offset_part_table = int(args.offset, 0) input = args.input.read() input_is_binary = input[0:2] == PartitionDefinition.MAGIC_BYTES if input_is_binary: diff --git a/components/partition_table/parttool.py b/components/partition_table/parttool.py new file mode 100755 index 0000000000..8188dfe3dd --- /dev/null +++ b/components/partition_table/parttool.py @@ -0,0 +1,129 @@ +#!/usr/bin/env python +# +# parttool returns info about the required partition. +# +# This utility is used by the make system to get information +# about the start addresses: partition table, factory area, phy area. +# +# 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. +from __future__ import print_function, division +import argparse +import os +import re +import struct +import sys +import hashlib +import binascii +import gen_esp32part as gen + +__version__ = '1.0' + +quiet = False + +def status(msg): + """ Print status message to stderr """ + if not quiet: + critical(msg) + +def critical(msg): + """ Print critical message to stderr """ + if not quiet: + sys.stderr.write(msg) + sys.stderr.write('\n') + +def main(): + global quiet + parser = argparse.ArgumentParser(description='Returns info about the required partition.') + + parser.add_argument('--quiet', '-q', help="Don't print status messages to stderr", action='store_true') + + search_type = parser.add_mutually_exclusive_group() + search_type.add_argument('--partition-name', '-p', help='The name of the required partition', type=str, default=None) + search_type.add_argument('--type', '-t', help='The type of the required partition', type=str, default=None) + search_type.add_argument('--default-boot-partition', help='Select the default boot partition, '+ + 'using the same fallback logic as the IDF bootloader', action="store_true") + + parser.add_argument('--subtype', '-s', help='The subtype of the required partition', type=str, default=None) + + parser.add_argument('--offset', '-o', help='Return offset of required partition', action="store_true") + parser.add_argument('--size', help='Return size of required partition', action="store_true") + + parser.add_argument('input', help='Path to CSV or binary file to parse. Will use stdin if omitted.', + type=argparse.FileType('rb'), default=sys.stdin) + + args = parser.parse_args() + + if args.type is not None and args.subtype is None: + status("If --type is specified, --subtype is required") + return 2 + if args.type is None and args.subtype is not None: + status("--subtype is only used with --type") + return 2 + + quiet = args.quiet + + input = args.input.read() + input_is_binary = input[0:2] == gen.PartitionDefinition.MAGIC_BYTES + if input_is_binary: + status("Parsing binary partition input...") + table = gen.PartitionTable.from_binary(input) + else: + input = input.decode() + status("Parsing CSV input...") + table = gen.PartitionTable.from_csv(input) + + found_partition = None + + if args.default_boot_partition: + search = [ "factory" ] + [ "ota_%d" % d for d in range(16) ] + for subtype in search: + found_partition = table.find_by_type("app", subtype) + if found_partition is not None: + break + elif args.partition_name is not None: + found_partition = table.find_by_name(args.partition_name) + elif args.type is not None: + found_partition = table.find_by_type(args.type, args.subtype) + else: + raise RuntimeError("invalid partition selection choice") + + if found_partition is None: + return 1 # nothing found + + if args.offset: + print('0x%x ' % (found_partition.offset)) + if args.size: + print('0x%x' % (found_partition.size)) + + return 0 + +class InputError(RuntimeError): + def __init__(self, e): + super(InputError, self).__init__(e) + + +class ValidationError(InputError): + def __init__(self, partition, message): + super(ValidationError, self).__init__( + "Partition %s invalid: %s" % (partition.name, message)) + + +if __name__ == '__main__': + try: + r = main() + sys.exit(r) + except InputError as e: + print(e, file=sys.stderr) + sys.exit(2) diff --git a/components/partition_table/project_include.cmake b/components/partition_table/project_include.cmake index 1658df30e8..3ddf904303 100644 --- a/components/partition_table/project_include.cmake +++ b/components/partition_table/project_include.cmake @@ -1 +1,42 @@ -set(PARTITION_TABLE_OFFSET 0x8000) +if(NOT BOOTLOADER_BUILD) + +set(PARTITION_TABLE_OFFSET ${CONFIG_PARTITION_TABLE_OFFSET}) + +# Set PARTITION_CSV_PATH to the configured partition CSV file +# absolute path +if(CONFIG_PARTITION_TABLE_CUSTOM) + # Custom filename expands any path relative to the project + get_filename_component(PARTITION_CSV_PATH "${CONFIG_PARTITION_TABLE_FILENAME}" ABSOLUTE BASE_DIR "${PROJECT_PATH}") + + if(NOT EXISTS "${PARTITION_CSV_PATH}") + message(FATAL_ERROR "Partition table CSV file ${PARTITION_CSV_PATH} not found. " + "Change custom partition CSV path in menuconfig.") + endif() +else() + # Other .csv files are always in the component directory + get_filename_component(PARTITION_CSV_PATH "${COMPONENT_PATH}/${CONFIG_PARTITION_TABLE_FILENAME}" ABSOLUTE) + + if(NOT EXISTS "${PARTITION_CSV_PATH}") + message(FATAL_ERROR "Internal error, built-in ${PARTITION_CSV_PATH} not found.") + endif() +endif() + +# need to re-run CMake if the partition CSV changes, as the offsets/sizes of partitions may change +set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS ${PARTITION_CSV_PATH}) + +# Parse the partition table to get variable partition offsets & sizes which must be known at CMake runtime +macro(get_partition_info variable get_part_info_args) + execute_process(COMMAND + get_part_info ${COMPONENT_PATH}/parttool.py -q ${get_part_info_args} ${PARTITION_CSV_PATH} + OUTPUT_VARIABLE ${variable} + OUTPUT_STRIP_TRAILING_WHITESPACE) +endmacro() + +if(CONFIG_ESP32_PHY_INIT_DATA_IN_PARTITION) + get_partition_info(PHY_PARTITION_OFFSET "--type data --subtype phy --offset") + set(PHY_PARTITION_BIN_FILE "${CMAKE_BINARY_DIR}/esp32/phy_init_data.bin") +endif() + +get_partition_info(APP_PARTITION_OFFSET "--default-boot-partition --offset") + +endif() 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 4919a53d87..a1d2503406 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 @@ -356,5 +356,53 @@ app,app, factory, 32K, 1M t.verify() +class PartToolTests(unittest.TestCase): + + def _run_parttool(self, csvcontents, args): + csvpath = tempfile.mktemp() + with open(csvpath, "w") as f: + f.write(csvcontents) + try: + return subprocess.check_output([sys.executable, "../parttool.py"] + args.split(" ") + [ csvpath ]).strip() + finally: + os.remove(csvpath) + + def test_find_basic(self): + csv = """ +nvs, data, nvs, 0x9000, 0x4000 +otadata, data, ota, 0xd000, 0x2000 +phy_init, data, phy, 0xf000, 0x1000 +factory, app, factory, 0x10000, 1M + """ + rpt = lambda args: self._run_parttool(csv, args) + + self.assertEqual( + rpt("--type data --subtype nvs --offset"), "0x9000") + self.assertEqual( + rpt("--type data --subtype nvs --size"), "0x4000") + self.assertEqual( + rpt("--partition-name otadata --offset"), "0xd000") + self.assertEqual( + rpt("--default-boot-partition --offset"), "0x10000") + + def test_fallback(self): + csv = """ +nvs, data, nvs, 0x9000, 0x4000 +otadata, data, ota, 0xd000, 0x2000 +phy_init, data, phy, 0xf000, 0x1000 +ota_0, app, ota_0, 0x30000, 1M +ota_1, app, ota_1, , 1M + """ + rpt = lambda args: self._run_parttool(csv, args) + + self.assertEqual( + rpt("--type app --subtype ota_1 --offset"), "0x130000") + self.assertEqual( + rpt("--default-boot-partition --offset"), "0x30000") # ota_0 + csv_mod = csv.replace("ota_0", "ota_2") + self.assertEqual( + self._run_parttool(csv_mod, "--default-boot-partition --offset"), + "0x130000") # now default is ota_1 + if __name__ =="__main__": unittest.main() diff --git a/components/soc/esp32/gpio_periph.c b/components/soc/esp32/gpio_periph.c new file mode 100644 index 0000000000..3534b7b3e5 --- /dev/null +++ b/components/soc/esp32/gpio_periph.c @@ -0,0 +1,58 @@ +// 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. + +#include "soc/gpio_periph.h" + +const uint32_t GPIO_PIN_MUX_REG[GPIO_PIN_COUNT] = { + IO_MUX_GPIO0_REG, + IO_MUX_GPIO1_REG, + IO_MUX_GPIO2_REG, + IO_MUX_GPIO3_REG, + IO_MUX_GPIO4_REG, + IO_MUX_GPIO5_REG, + IO_MUX_GPIO6_REG, + IO_MUX_GPIO7_REG, + IO_MUX_GPIO8_REG, + IO_MUX_GPIO9_REG, + IO_MUX_GPIO10_REG, + IO_MUX_GPIO11_REG, + IO_MUX_GPIO12_REG, + IO_MUX_GPIO13_REG, + IO_MUX_GPIO14_REG, + IO_MUX_GPIO15_REG, + IO_MUX_GPIO16_REG, + IO_MUX_GPIO17_REG, + IO_MUX_GPIO18_REG, + IO_MUX_GPIO19_REG, + 0, + IO_MUX_GPIO21_REG, + IO_MUX_GPIO22_REG, + IO_MUX_GPIO23_REG, + 0, + IO_MUX_GPIO25_REG, + IO_MUX_GPIO26_REG, + IO_MUX_GPIO27_REG, + 0, + 0, + 0, + 0, + IO_MUX_GPIO32_REG, + IO_MUX_GPIO33_REG, + IO_MUX_GPIO34_REG, + IO_MUX_GPIO35_REG, + IO_MUX_GPIO36_REG, + IO_MUX_GPIO37_REG, + IO_MUX_GPIO38_REG, + IO_MUX_GPIO39_REG, +}; diff --git a/components/soc/esp32/include/soc/gpio_pins.h b/components/soc/esp32/include/soc/gpio_pins.h new file mode 100644 index 0000000000..6c2bfb7418 --- /dev/null +++ b/components/soc/esp32/include/soc/gpio_pins.h @@ -0,0 +1,28 @@ +// 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. + +#ifndef _GPIO_PINS_H +#define _GPIO_PINS_H +#ifdef __cplusplus +extern "C" +{ +#endif + +#define GPIO_PIN_COUNT 40 + +#ifdef __cplusplus +} +#endif + +#endif // _GPIO_PINS_H diff --git a/components/soc/esp32/include/soc/periph_defs.h b/components/soc/esp32/include/soc/periph_defs.h new file mode 100644 index 0000000000..7aa21fc963 --- /dev/null +++ b/components/soc/esp32/include/soc/periph_defs.h @@ -0,0 +1,61 @@ +// 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. + +#ifndef _SOC_PERIPH_DEFS_H_ +#define _SOC_PERIPH_DEFS_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + PERIPH_LEDC_MODULE = 0, + PERIPH_UART0_MODULE, + PERIPH_UART1_MODULE, + PERIPH_UART2_MODULE, + PERIPH_I2C0_MODULE, + PERIPH_I2C1_MODULE, + PERIPH_I2S0_MODULE, + PERIPH_I2S1_MODULE, + PERIPH_TIMG0_MODULE, + PERIPH_TIMG1_MODULE, + PERIPH_PWM0_MODULE, + PERIPH_PWM1_MODULE, + PERIPH_PWM2_MODULE, + PERIPH_PWM3_MODULE, + PERIPH_UHCI0_MODULE, + PERIPH_UHCI1_MODULE, + PERIPH_RMT_MODULE, + PERIPH_PCNT_MODULE, + PERIPH_SPI_MODULE, + PERIPH_HSPI_MODULE, + PERIPH_VSPI_MODULE, + PERIPH_SPI_DMA_MODULE, + PERIPH_SDMMC_MODULE, + PERIPH_SDIO_SLAVE_MODULE, + PERIPH_CAN_MODULE, + PERIPH_EMAC_MODULE, + PERIPH_RNG_MODULE, + PERIPH_WIFI_MODULE, + PERIPH_BT_MODULE, + PERIPH_WIFI_BT_COMMON_MODULE, + PERIPH_BT_BASEBAND_MODULE, + PERIPH_BT_LC_MODULE, +} periph_module_t; + +#ifdef __cplusplus +} +#endif + +#endif /* _SOC_PERIPH_DEFS_H_ */ diff --git a/components/soc/esp32/include/soc/soc.h b/components/soc/esp32/include/soc/soc.h index 660abbdb3f..bc822e2364 100644 --- a/components/soc/esp32/include/soc/soc.h +++ b/components/soc/esp32/include/soc/soc.h @@ -133,6 +133,7 @@ #ifndef __ASSEMBLER__ #define BIT(nr) (1UL << (nr)) +#define BIT64(nr) (1ULL << (nr)) #else #define BIT(nr) (1 << (nr)) #endif diff --git a/components/soc/esp32/include/soc/spi_pins.h b/components/soc/esp32/include/soc/spi_pins.h new file mode 100644 index 0000000000..49be9b7c13 --- /dev/null +++ b/components/soc/esp32/include/soc/spi_pins.h @@ -0,0 +1,39 @@ +// 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. + +#ifndef _SOC_SPI_PINS_H_ +#define _SOC_SPI_PINS_H_ + +#define SPI_IOMUX_PIN_NUM_MISO 7 +#define SPI_IOMUX_PIN_NUM_MOSI 8 +#define SPI_IOMUX_PIN_NUM_CLK 6 +#define SPI_IOMUX_PIN_NUM_CS 11 +#define SPI_IOMUX_PIN_NUM_WP 10 +#define SPI_IOMUX_PIN_NUM_HD 9 + +#define HSPI_IOMUX_PIN_NUM_MISO 12 +#define HSPI_IOMUX_PIN_NUM_MOSI 13 +#define HSPI_IOMUX_PIN_NUM_CLK 14 +#define HSPI_IOMUX_PIN_NUM_CS 15 +#define HSPI_IOMUX_PIN_NUM_WP 2 +#define HSPI_IOMUX_PIN_NUM_HD 4 + +#define VSPI_IOMUX_PIN_NUM_MISO 19 +#define VSPI_IOMUX_PIN_NUM_MOSI 23 +#define VSPI_IOMUX_PIN_NUM_CLK 18 +#define VSPI_IOMUX_PIN_NUM_CS 5 +#define VSPI_IOMUX_PIN_NUM_WP 22 +#define VSPI_IOMUX_PIN_NUM_HD 21 + +#endif /* _SOC_SPI_PINS_H_ */ \ No newline at end of file diff --git a/components/soc/esp32/rtc_periph.c b/components/soc/esp32/rtc_periph.c new file mode 100644 index 0000000000..36439362c8 --- /dev/null +++ b/components/soc/esp32/rtc_periph.c @@ -0,0 +1,59 @@ +// 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. + +#include "soc/rtc_periph.h" + +//Reg,Mux,Fun,IE,Up,Down,Rtc_number +const rtc_gpio_desc_t rtc_gpio_desc[GPIO_PIN_COUNT] = { + {RTC_IO_TOUCH_PAD1_REG, RTC_IO_TOUCH_PAD1_MUX_SEL_M, RTC_IO_TOUCH_PAD1_FUN_SEL_S, RTC_IO_TOUCH_PAD1_FUN_IE_M, RTC_IO_TOUCH_PAD1_RUE_M, RTC_IO_TOUCH_PAD1_RDE_M, RTC_IO_TOUCH_PAD1_SLP_SEL_M, RTC_IO_TOUCH_PAD1_SLP_IE_M, RTC_IO_TOUCH_PAD1_HOLD_M, RTC_CNTL_TOUCH_PAD1_HOLD_FORCE_M, RTC_IO_TOUCH_PAD1_DRV_V, RTC_IO_TOUCH_PAD1_DRV_S, RTCIO_GPIO0_CHANNEL}, //0 + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1}, //1 + {RTC_IO_TOUCH_PAD2_REG, RTC_IO_TOUCH_PAD2_MUX_SEL_M, RTC_IO_TOUCH_PAD2_FUN_SEL_S, RTC_IO_TOUCH_PAD2_FUN_IE_M, RTC_IO_TOUCH_PAD2_RUE_M, RTC_IO_TOUCH_PAD2_RDE_M, RTC_IO_TOUCH_PAD2_SLP_SEL_M, RTC_IO_TOUCH_PAD2_SLP_IE_M, RTC_IO_TOUCH_PAD2_HOLD_M, RTC_CNTL_TOUCH_PAD2_HOLD_FORCE_M, RTC_IO_TOUCH_PAD2_DRV_V, RTC_IO_TOUCH_PAD2_DRV_S, RTCIO_GPIO2_CHANNEL}, //2 + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1}, //3 + {RTC_IO_TOUCH_PAD0_REG, RTC_IO_TOUCH_PAD0_MUX_SEL_M, RTC_IO_TOUCH_PAD0_FUN_SEL_S, RTC_IO_TOUCH_PAD0_FUN_IE_M, RTC_IO_TOUCH_PAD0_RUE_M, RTC_IO_TOUCH_PAD0_RDE_M, RTC_IO_TOUCH_PAD0_SLP_SEL_M, RTC_IO_TOUCH_PAD0_SLP_IE_M, RTC_IO_TOUCH_PAD0_HOLD_M, RTC_CNTL_TOUCH_PAD0_HOLD_FORCE_M, RTC_IO_TOUCH_PAD0_DRV_V, RTC_IO_TOUCH_PAD0_DRV_S, RTCIO_GPIO4_CHANNEL}, //4 + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1}, //5 + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1}, //6 + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1}, //7 + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1}, //8 + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1}, //9 + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1}, //10 + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1}, //11 + {RTC_IO_TOUCH_PAD5_REG, RTC_IO_TOUCH_PAD5_MUX_SEL_M, RTC_IO_TOUCH_PAD5_FUN_SEL_S, RTC_IO_TOUCH_PAD5_FUN_IE_M, RTC_IO_TOUCH_PAD5_RUE_M, RTC_IO_TOUCH_PAD5_RDE_M, RTC_IO_TOUCH_PAD5_SLP_SEL_M, RTC_IO_TOUCH_PAD5_SLP_IE_M, RTC_IO_TOUCH_PAD5_HOLD_M, RTC_CNTL_TOUCH_PAD5_HOLD_FORCE_M, RTC_IO_TOUCH_PAD5_DRV_V, RTC_IO_TOUCH_PAD5_DRV_S, RTCIO_GPIO12_CHANNEL}, //12 + {RTC_IO_TOUCH_PAD4_REG, RTC_IO_TOUCH_PAD4_MUX_SEL_M, RTC_IO_TOUCH_PAD4_FUN_SEL_S, RTC_IO_TOUCH_PAD4_FUN_IE_M, RTC_IO_TOUCH_PAD4_RUE_M, RTC_IO_TOUCH_PAD4_RDE_M, RTC_IO_TOUCH_PAD4_SLP_SEL_M, RTC_IO_TOUCH_PAD4_SLP_IE_M, RTC_IO_TOUCH_PAD4_HOLD_M, RTC_CNTL_TOUCH_PAD4_HOLD_FORCE_M, RTC_IO_TOUCH_PAD4_DRV_V, RTC_IO_TOUCH_PAD4_DRV_S, RTCIO_GPIO13_CHANNEL}, //13 + {RTC_IO_TOUCH_PAD6_REG, RTC_IO_TOUCH_PAD6_MUX_SEL_M, RTC_IO_TOUCH_PAD6_FUN_SEL_S, RTC_IO_TOUCH_PAD6_FUN_IE_M, RTC_IO_TOUCH_PAD6_RUE_M, RTC_IO_TOUCH_PAD6_RDE_M, RTC_IO_TOUCH_PAD6_SLP_SEL_M, RTC_IO_TOUCH_PAD6_SLP_IE_M, RTC_IO_TOUCH_PAD6_HOLD_M, RTC_CNTL_TOUCH_PAD6_HOLD_FORCE_M, RTC_IO_TOUCH_PAD6_DRV_V, RTC_IO_TOUCH_PAD6_DRV_S, RTCIO_GPIO14_CHANNEL}, //14 + {RTC_IO_TOUCH_PAD3_REG, RTC_IO_TOUCH_PAD3_MUX_SEL_M, RTC_IO_TOUCH_PAD3_FUN_SEL_S, RTC_IO_TOUCH_PAD3_FUN_IE_M, RTC_IO_TOUCH_PAD3_RUE_M, RTC_IO_TOUCH_PAD3_RDE_M, RTC_IO_TOUCH_PAD3_SLP_SEL_M, RTC_IO_TOUCH_PAD3_SLP_IE_M, RTC_IO_TOUCH_PAD3_HOLD_M, RTC_CNTL_TOUCH_PAD3_HOLD_FORCE_M, RTC_IO_TOUCH_PAD3_DRV_V, RTC_IO_TOUCH_PAD3_DRV_S, RTCIO_GPIO15_CHANNEL}, //15 + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1}, //16 + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1}, //17 + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1}, //18 + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1}, //19 + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1}, //20 + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1}, //21 + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1}, //22 + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1}, //23 + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1}, //24 + {RTC_IO_PAD_DAC1_REG, RTC_IO_PDAC1_MUX_SEL_M, RTC_IO_PDAC1_FUN_SEL_S, RTC_IO_PDAC1_FUN_IE_M, RTC_IO_PDAC1_RUE_M, RTC_IO_PDAC1_RDE_M, RTC_IO_PDAC1_SLP_SEL_M, RTC_IO_PDAC1_SLP_IE_M, RTC_IO_PDAC1_HOLD_M, RTC_CNTL_PDAC1_HOLD_FORCE_M, RTC_IO_PDAC1_DRV_V, RTC_IO_PDAC1_DRV_S, RTCIO_GPIO25_CHANNEL}, //25 + {RTC_IO_PAD_DAC2_REG, RTC_IO_PDAC2_MUX_SEL_M, RTC_IO_PDAC2_FUN_SEL_S, RTC_IO_PDAC2_FUN_IE_M, RTC_IO_PDAC2_RUE_M, RTC_IO_PDAC2_RDE_M, RTC_IO_PDAC2_SLP_SEL_M, RTC_IO_PDAC2_SLP_IE_M, RTC_IO_PDAC2_HOLD_M, RTC_CNTL_PDAC2_HOLD_FORCE_M, RTC_IO_PDAC2_DRV_V, RTC_IO_PDAC2_DRV_S, RTCIO_GPIO26_CHANNEL}, //26 + {RTC_IO_TOUCH_PAD7_REG, RTC_IO_TOUCH_PAD7_MUX_SEL_M, RTC_IO_TOUCH_PAD7_FUN_SEL_S, RTC_IO_TOUCH_PAD7_FUN_IE_M, RTC_IO_TOUCH_PAD7_RUE_M, RTC_IO_TOUCH_PAD7_RDE_M, RTC_IO_TOUCH_PAD7_SLP_SEL_M, RTC_IO_TOUCH_PAD7_SLP_IE_M, RTC_IO_TOUCH_PAD7_HOLD_M, RTC_CNTL_TOUCH_PAD7_HOLD_FORCE_M, RTC_IO_TOUCH_PAD7_DRV_V, RTC_IO_TOUCH_PAD7_DRV_S, RTCIO_GPIO27_CHANNEL}, //27 + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1}, //28 + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1}, //29 + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1}, //30 + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1}, //31 + {RTC_IO_XTAL_32K_PAD_REG, RTC_IO_X32P_MUX_SEL_M, RTC_IO_X32P_FUN_SEL_S, RTC_IO_X32P_FUN_IE_M, RTC_IO_X32P_RUE_M, RTC_IO_X32P_RDE_M, RTC_IO_X32P_SLP_SEL_M, RTC_IO_X32P_SLP_IE_M, RTC_IO_X32P_HOLD_M, RTC_CNTL_X32P_HOLD_FORCE_M, RTC_IO_X32P_DRV_V, RTC_IO_X32P_DRV_S, RTCIO_GPIO32_CHANNEL}, //32 + {RTC_IO_XTAL_32K_PAD_REG, RTC_IO_X32N_MUX_SEL_M, RTC_IO_X32N_FUN_SEL_S, RTC_IO_X32N_FUN_IE_M, RTC_IO_X32N_RUE_M, RTC_IO_X32N_RDE_M, RTC_IO_X32N_SLP_SEL_M, RTC_IO_X32N_SLP_IE_M, RTC_IO_X32N_HOLD_M, RTC_CNTL_X32N_HOLD_FORCE_M, RTC_IO_X32N_DRV_V, RTC_IO_X32N_DRV_S, RTCIO_GPIO33_CHANNEL}, //33 + {RTC_IO_ADC_PAD_REG, RTC_IO_ADC1_MUX_SEL_M, RTC_IO_ADC1_FUN_SEL_S, RTC_IO_ADC1_FUN_IE_M, 0, 0, RTC_IO_ADC1_SLP_SEL_M, RTC_IO_ADC1_SLP_IE_M, RTC_IO_ADC1_HOLD_M, RTC_CNTL_ADC1_HOLD_FORCE_M, 0, 0, RTCIO_GPIO34_CHANNEL}, //34 + {RTC_IO_ADC_PAD_REG, RTC_IO_ADC2_MUX_SEL_M, RTC_IO_ADC2_FUN_SEL_S, RTC_IO_ADC2_FUN_IE_M, 0, 0, RTC_IO_ADC2_SLP_SEL_M, RTC_IO_ADC2_SLP_IE_M, RTC_IO_ADC2_HOLD_M, RTC_CNTL_ADC2_HOLD_FORCE_M, 0, 0, RTCIO_GPIO35_CHANNEL}, //35 + {RTC_IO_SENSOR_PADS_REG, RTC_IO_SENSE1_MUX_SEL_M, RTC_IO_SENSE1_FUN_SEL_S, RTC_IO_SENSE1_FUN_IE_M, 0, 0, RTC_IO_SENSE1_SLP_SEL_M, RTC_IO_SENSE1_SLP_IE_M, RTC_IO_SENSE1_HOLD_M, RTC_CNTL_SENSE1_HOLD_FORCE_M, 0, 0, RTCIO_GPIO36_CHANNEL}, //36 + {RTC_IO_SENSOR_PADS_REG, RTC_IO_SENSE2_MUX_SEL_M, RTC_IO_SENSE2_FUN_SEL_S, RTC_IO_SENSE2_FUN_IE_M, 0, 0, RTC_IO_SENSE2_SLP_SEL_M, RTC_IO_SENSE2_SLP_IE_M, RTC_IO_SENSE2_HOLD_M, RTC_CNTL_SENSE2_HOLD_FORCE_M, 0, 0, RTCIO_GPIO37_CHANNEL}, //37 + {RTC_IO_SENSOR_PADS_REG, RTC_IO_SENSE3_MUX_SEL_M, RTC_IO_SENSE3_FUN_SEL_S, RTC_IO_SENSE3_FUN_IE_M, 0, 0, RTC_IO_SENSE3_SLP_SEL_M, RTC_IO_SENSE3_SLP_IE_M, RTC_IO_SENSE3_HOLD_M, RTC_CNTL_SENSE3_HOLD_FORCE_M, 0, 0, RTCIO_GPIO38_CHANNEL}, //38 + {RTC_IO_SENSOR_PADS_REG, RTC_IO_SENSE4_MUX_SEL_M, RTC_IO_SENSE4_FUN_SEL_S, RTC_IO_SENSE4_FUN_IE_M, 0, 0, RTC_IO_SENSE4_SLP_SEL_M, RTC_IO_SENSE4_SLP_IE_M, RTC_IO_SENSE4_HOLD_M, RTC_CNTL_SENSE4_HOLD_FORCE_M, 0, 0, RTCIO_GPIO39_CHANNEL}, //39 +}; diff --git a/components/soc/esp32/spi_periph.c b/components/soc/esp32/spi_periph.c new file mode 100644 index 0000000000..92e748e939 --- /dev/null +++ b/components/soc/esp32/spi_periph.c @@ -0,0 +1,91 @@ +// 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. + +#include "soc/spi_periph.h" + +/* + Bunch of constants for every SPI peripheral: GPIO signals, irqs, hw addr of registers etc +*/ +const spi_signal_conn_t spi_periph_signal[3] = { + { + .spiclk_out = SPICLK_OUT_IDX, + .spiclk_in = SPICLK_IN_IDX, + .spid_out = SPID_OUT_IDX, + .spiq_out = SPIQ_OUT_IDX, + .spiwp_out = SPIWP_OUT_IDX, + .spihd_out = SPIHD_OUT_IDX, + .spid_in = SPID_IN_IDX, + .spiq_in = SPIQ_IN_IDX, + .spiwp_in = SPIWP_IN_IDX, + .spihd_in = SPIHD_IN_IDX, + .spics_out = {SPICS0_OUT_IDX, SPICS1_OUT_IDX, SPICS2_OUT_IDX}, + .spics_in = SPICS0_IN_IDX, + .spiclk_iomux_pin = SPI_IOMUX_PIN_NUM_CLK, + .spid_iomux_pin = SPI_IOMUX_PIN_NUM_MOSI, + .spiq_iomux_pin = SPI_IOMUX_PIN_NUM_MISO, + .spiwp_iomux_pin = SPI_IOMUX_PIN_NUM_WP, + .spihd_iomux_pin = SPI_IOMUX_PIN_NUM_HD, + .spics0_iomux_pin = SPI_IOMUX_PIN_NUM_CS, + .irq = ETS_SPI1_INTR_SOURCE, + .irq_dma = ETS_SPI1_DMA_INTR_SOURCE, + .module = PERIPH_SPI_MODULE, + .hw = &SPI1 + }, { + .spiclk_out = HSPICLK_OUT_IDX, + .spiclk_in = HSPICLK_IN_IDX, + .spid_out = HSPID_OUT_IDX, + .spiq_out = HSPIQ_OUT_IDX, + .spiwp_out = HSPIWP_OUT_IDX, + .spihd_out = HSPIHD_OUT_IDX, + .spid_in = HSPID_IN_IDX, + .spiq_in = HSPIQ_IN_IDX, + .spiwp_in = HSPIWP_IN_IDX, + .spihd_in = HSPIHD_IN_IDX, + .spics_out = {HSPICS0_OUT_IDX, HSPICS1_OUT_IDX, HSPICS2_OUT_IDX}, + .spics_in = HSPICS0_IN_IDX, + .spiclk_iomux_pin = HSPI_IOMUX_PIN_NUM_CLK, + .spid_iomux_pin = HSPI_IOMUX_PIN_NUM_MOSI, + .spiq_iomux_pin = HSPI_IOMUX_PIN_NUM_MISO, + .spiwp_iomux_pin = HSPI_IOMUX_PIN_NUM_WP, + .spihd_iomux_pin = HSPI_IOMUX_PIN_NUM_HD, + .spics0_iomux_pin = HSPI_IOMUX_PIN_NUM_CS, + .irq = ETS_SPI2_INTR_SOURCE, + .irq_dma = ETS_SPI2_DMA_INTR_SOURCE, + .module = PERIPH_HSPI_MODULE, + .hw = &SPI2 + }, { + .spiclk_out = VSPICLK_OUT_IDX, + .spiclk_in = VSPICLK_IN_IDX, + .spid_out = VSPID_OUT_IDX, + .spiq_out = VSPIQ_OUT_IDX, + .spiwp_out = VSPIWP_OUT_IDX, + .spihd_out = VSPIHD_OUT_IDX, + .spid_in = VSPID_IN_IDX, + .spiq_in = VSPIQ_IN_IDX, + .spiwp_in = VSPIWP_IN_IDX, + .spihd_in = VSPIHD_IN_IDX, + .spics_out = {VSPICS0_OUT_IDX, VSPICS1_OUT_IDX, VSPICS2_OUT_IDX}, + .spics_in = VSPICS0_IN_IDX, + .spiclk_iomux_pin = VSPI_IOMUX_PIN_NUM_CLK, + .spid_iomux_pin = VSPI_IOMUX_PIN_NUM_MOSI, + .spiq_iomux_pin = VSPI_IOMUX_PIN_NUM_MISO, + .spiwp_iomux_pin = VSPI_IOMUX_PIN_NUM_WP, + .spihd_iomux_pin = VSPI_IOMUX_PIN_NUM_HD, + .spics0_iomux_pin = VSPI_IOMUX_PIN_NUM_CS, + .irq = ETS_SPI3_INTR_SOURCE, + .irq_dma = ETS_SPI3_DMA_INTR_SOURCE, + .module = PERIPH_VSPI_MODULE, + .hw = &SPI3 + } +}; \ No newline at end of file diff --git a/components/soc/include/soc/gpio_periph.h b/components/soc/include/soc/gpio_periph.h new file mode 100644 index 0000000000..59ccee5651 --- /dev/null +++ b/components/soc/include/soc/gpio_periph.h @@ -0,0 +1,31 @@ +// 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. + +#ifndef _SOC_GPIO_PERIPH_H +#define _SOC_GPIO_PERIPH_H +#include "stdint.h" +#include "soc/gpio_pins.h" +#include "soc/io_mux_reg.h" +#ifdef __cplusplus +extern "C" +{ +#endif + +extern const uint32_t GPIO_PIN_MUX_REG[GPIO_PIN_COUNT]; + +#ifdef __cplusplus +} +#endif + +#endif // _SOC_GPIO_PERIPH_H diff --git a/components/soc/include/soc/rtc_periph.h b/components/soc/include/soc/rtc_periph.h new file mode 100644 index 0000000000..832186c3d8 --- /dev/null +++ b/components/soc/include/soc/rtc_periph.h @@ -0,0 +1,62 @@ +// 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. + +#ifndef _SOC_RTC_PERIPH_H +#define _SOC_RTC_PERIPH_H +#include +#include "soc/rtc_io_reg.h" +#include "soc/rtc_cntl_reg.h" +#include "soc/rtc_gpio_channel.h" +#include "soc/gpio_pins.h" +#ifdef __cplusplus +extern "C" +{ +#endif + +/** + * @brief Pin function information for a single GPIO pad's RTC functions. + * + * This is an internal function of the driver, and is not usually useful + * for external use. + */ +typedef struct { + uint32_t reg; /*!< Register of RTC pad, or 0 if not an RTC GPIO */ + uint32_t mux; /*!< Bit mask for selecting digital pad or RTC pad */ + uint32_t func; /*!< Shift of pad function (FUN_SEL) field */ + uint32_t ie; /*!< Mask of input enable */ + uint32_t pullup; /*!< Mask of pullup enable */ + uint32_t pulldown; /*!< Mask of pulldown enable */ + uint32_t slpsel; /*!< If slpsel bit is set, slpie will be used as pad input enabled signal in sleep mode */ + uint32_t slpie; /*!< Mask of input enable in sleep mode */ + uint32_t hold; /*!< Mask of hold enable */ + uint32_t hold_force;/*!< Mask of hold_force bit for RTC IO in RTC_CNTL_HOLD_FORCE_REG */ + uint32_t drv_v; /*!< Mask of drive capability */ + uint32_t drv_s; /*!< Offset of drive capability */ + int rtc_num; /*!< RTC IO number, or -1 if not an RTC GPIO */ +} rtc_gpio_desc_t; + +/** + * @brief Provides access to a constant table of RTC I/O pin + * function information. + * + * This is an internal function of the driver, and is not usually useful + * for external use. + */ +extern const rtc_gpio_desc_t rtc_gpio_desc[GPIO_PIN_COUNT]; + +#ifdef __cplusplus +} +#endif + +#endif // _SOC_RTC_PERIPH_H diff --git a/components/soc/include/soc/spi_periph.h b/components/soc/include/soc/spi_periph.h new file mode 100644 index 0000000000..00c5f3e138 --- /dev/null +++ b/components/soc/include/soc/spi_periph.h @@ -0,0 +1,66 @@ +// 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. + +#ifndef _SOC_SPI_PERIPH_H_ +#define _SOC_SPI_PERIPH_H_ + +#include +#include "soc/soc.h" +#include "soc/periph_defs.h" +//include soc related (generated) definitions +#include "soc/spi_pins.h" +#include "soc/spi_reg.h" +#include "soc/spi_struct.h" +#include "soc/gpio_sig_map.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +/* + Stores a bunch of per-spi-peripheral data. +*/ +typedef struct { + const uint8_t spiclk_out; //GPIO mux output signals + const uint8_t spiclk_in; + const uint8_t spid_out; + const uint8_t spiq_out; + const uint8_t spiwp_out; + const uint8_t spihd_out; + const uint8_t spid_in; //GPIO mux input signals + const uint8_t spiq_in; + const uint8_t spiwp_in; + const uint8_t spihd_in; + const uint8_t spics_out[3]; // /CS GPIO output mux signals + const uint8_t spics_in; + const uint8_t spiclk_iomux_pin; //IO pins of IO_MUX muxed signals + const uint8_t spid_iomux_pin; + const uint8_t spiq_iomux_pin; + const uint8_t spiwp_iomux_pin; + const uint8_t spihd_iomux_pin; + const uint8_t spics0_iomux_pin; + const uint8_t irq; //irq source for interrupt mux + const uint8_t irq_dma; //dma irq source for interrupt mux + const periph_module_t module; //peripheral module, for enabling clock etc + spi_dev_t *hw; //Pointer to the hardware registers +} spi_signal_conn_t; + +extern const spi_signal_conn_t spi_periph_signal[3]; + +#ifdef __cplusplus +} +#endif + +#endif /* _SOC_SPI_PERIPH_H_ */ \ No newline at end of file diff --git a/components/spi_flash/README.rst b/components/spi_flash/README.rst index 601603954b..807b592d28 100644 --- a/components/spi_flash/README.rst +++ b/components/spi_flash/README.rst @@ -36,7 +36,7 @@ image header, flashed at offset 0x1000. By default, the SPI flash size is detected by esptool.py when this bootloader is written to flash, and the header is updated with the correct size. Alternatively, it is possible to generate a fixed flash size by setting -:ref:`CONFIG_ESPTOOLPY_FLASHSIZE` in ``idf.py menuconfig``. +:envvar:`CONFIG_ESPTOOLPY_FLASHSIZE` in ``make menuconfig``. If it is necessary to override the configured flash size at runtime, is is possible to set the ``chip_size`` member of ``g_rom_flashchip`` structure. This diff --git a/components/spi_flash/flash_mmap.c b/components/spi_flash/flash_mmap.c index 43fdf6ccd4..f4249799dc 100644 --- a/components/spi_flash/flash_mmap.c +++ b/components/spi_flash/flash_mmap.c @@ -127,20 +127,20 @@ esp_err_t IRAM_ATTR spi_flash_mmap(size_t src_addr, size_t size, spi_flash_mmap_ // region which should be mapped int phys_page = src_addr / SPI_FLASH_MMU_PAGE_SIZE; int page_count = (size + SPI_FLASH_MMU_PAGE_SIZE - 1) / SPI_FLASH_MMU_PAGE_SIZE; - //prepare a linear pages array to feed into spi_flash_mmap_pages - int *pages=malloc(sizeof(int)*page_count); - if (pages==NULL) { + // prepare a linear pages array to feed into spi_flash_mmap_pages + int *pages = heap_caps_malloc(sizeof(int)*page_count, MALLOC_CAP_INTERNAL); + if (pages == NULL) { return ESP_ERR_NO_MEM; } for (int i = 0; i < page_count; i++) { pages[i] = phys_page+i; } - ret=spi_flash_mmap_pages(pages, page_count, memory, out_ptr, out_handle); + ret = spi_flash_mmap_pages(pages, page_count, memory, out_ptr, out_handle); free(pages); return ret; } -esp_err_t IRAM_ATTR spi_flash_mmap_pages(int *pages, size_t page_count, spi_flash_mmap_memory_t memory, +esp_err_t IRAM_ATTR spi_flash_mmap_pages(const int *pages, size_t page_count, spi_flash_mmap_memory_t memory, const void** out_ptr, spi_flash_mmap_handle_t* out_handle) { esp_err_t ret; @@ -148,6 +148,9 @@ esp_err_t IRAM_ATTR spi_flash_mmap_pages(int *pages, size_t page_count, spi_flas if (!page_count) { return ESP_ERR_INVALID_ARG; } + if (!esp_ptr_internal(pages)) { + return ESP_ERR_INVALID_ARG; + } for (int i = 0; i < page_count; i++) { if (pages[i] < 0 || pages[i]*SPI_FLASH_MMU_PAGE_SIZE >= g_rom_flashchip.chip_size) { return ESP_ERR_INVALID_ARG; diff --git a/components/spi_flash/include/esp_spi_flash.h b/components/spi_flash/include/esp_spi_flash.h index 9caa47e408..7977e116fe 100644 --- a/components/spi_flash/include/esp_spi_flash.h +++ b/components/spi_flash/include/esp_spi_flash.h @@ -185,8 +185,8 @@ typedef uint32_t spi_flash_mmap_handle_t; * @param size Size of region to be mapped. This size will be rounded * up to a 64kB boundary * @param memory Address space where the region should be mapped (data or instruction) - * @param out_ptr Output, pointer to the mapped memory region - * @param out_handle Output, handle which should be used for spi_flash_munmap call + * @param[out] out_ptr Output, pointer to the mapped memory region + * @param[out] out_handle Output, handle which should be used for spi_flash_munmap call * * @return ESP_OK on success, ESP_ERR_NO_MEM if pages can not be allocated */ @@ -204,14 +204,19 @@ esp_err_t spi_flash_mmap(size_t src_addr, size_t size, spi_flash_mmap_memory_t m * @param pages An array of numbers indicating the 64kB pages in flash to be mapped * contiguously into memory. These indicate the indexes of the 64kB pages, * not the byte-size addresses as used in other functions. - * @param pagecount Number of entries in the pages array + * Array must be located in internal memory. + * @param page_count Number of entries in the pages array * @param memory Address space where the region should be mapped (instruction or data) - * @param out_ptr Output, pointer to the mapped memory region - * @param out_handle Output, handle which should be used for spi_flash_munmap call + * @param[out] out_ptr Output, pointer to the mapped memory region + * @param[out] out_handle Output, handle which should be used for spi_flash_munmap call * - * @return ESP_OK on success, ESP_ERR_NO_MEM if pages can not be allocated + * @return + * - ESP_OK on success + * - ESP_ERR_NO_MEM if pages can not be allocated + * - ESP_ERR_INVALID_ARG if pagecount is zero or pages array is not in + * internal memory */ -esp_err_t spi_flash_mmap_pages(int *pages, size_t pagecount, spi_flash_mmap_memory_t memory, +esp_err_t spi_flash_mmap_pages(const int *pages, size_t page_count, spi_flash_mmap_memory_t memory, const void** out_ptr, spi_flash_mmap_handle_t* out_handle); diff --git a/components/spi_flash/partition.c b/components/spi_flash/partition.c index 1c3ac610fa..4003291999 100644 --- a/components/spi_flash/partition.c +++ b/components/spi_flash/partition.c @@ -17,7 +17,7 @@ #include #include #include - +#include "esp_flash_partitions.h" #include "esp_attr.h" #include "esp_flash_data_types.h" #include "esp_spi_flash.h" @@ -145,14 +145,14 @@ static esp_err_t load_partitions() const uint32_t* ptr; spi_flash_mmap_handle_t handle; // map 64kB block where partition table is located - esp_err_t err = spi_flash_mmap(ESP_PARTITION_TABLE_ADDR & 0xffff0000, + esp_err_t err = spi_flash_mmap(ESP_PARTITION_TABLE_OFFSET & 0xffff0000, SPI_FLASH_SEC_SIZE, SPI_FLASH_MMAP_DATA, (const void**) &ptr, &handle); if (err != ESP_OK) { return err; } // calculate partition address within mmap-ed region const esp_partition_info_t* it = (const esp_partition_info_t*) - (ptr + (ESP_PARTITION_TABLE_ADDR & 0xffff) / sizeof(*ptr)); + (ptr + (ESP_PARTITION_TABLE_OFFSET & 0xffff) / sizeof(*ptr)); const esp_partition_info_t* end = it + SPI_FLASH_SEC_SIZE / sizeof(*it); // tail of the linked list of partitions partition_list_item_t* last = NULL; diff --git a/components/spi_flash/sim/Makefile b/components/spi_flash/sim/Makefile new file mode 100644 index 0000000000..d5da7f9a63 --- /dev/null +++ b/components/spi_flash/sim/Makefile @@ -0,0 +1,67 @@ +COMPONENT=spi_flash +COMPONENT_LIB=lib$(COMPONENT).a + +all: lib + +SOURCE_FILES = \ + ../partition.c \ + ../flash_ops.c \ + SpiFlash.cpp \ + flash_mock_util.c \ + flash_mock.cpp \ + $(addprefix stubs/, \ + newlib/lock.c \ + app_update/esp_ota_eps.c \ + ) + +INCLUDE_FLAGS = $(addprefix -I,\ + . \ + ../include \ + ../../esp32/include/ \ + $(addprefix stubs/, \ + newlib/include \ + log/include \ + freertos/include \ + ) \ + $(addprefix ../../../components/, \ + soc/esp32/include \ + esp32/include \ + bootloader_support/include \ + app_update/include \ + ) \ + ../../../tools/catch \ +) + +GCOV ?= gcov + +CPPFLAGS += $(INCLUDE_FLAGS) -D CONFIG_LOG_DEFAULT_LEVEL -g -m32 +CFLAGS += -fprofile-arcs -ftest-coverage +CXXFLAGS += -std=c++11 -Wall -Werror -fprofile-arcs -ftest-coverage +LDFLAGS += -lstdc++ -fprofile-arcs -ftest-coverage + +OBJ_FILES = $(filter %.o, $(SOURCE_FILES:.cpp=.o) $(SOURCE_FILES:.c=.o)) + +$(COMPONENT_LIB): $(OBJ_FILES) + $(AR) rcs $@ $^ + +lib: $(COMPONENT_LIB) + +COVERAGE_FILES = $(OBJ_FILES:.o=.gc*) + +$(COVERAGE_FILES): lib + +coverage.info: $(COVERAGE_FILES) + find ../ -name "*.gcno" -exec $(GCOV) -r -pb {} + + lcov --capture --directory ../ --no-external --output-file coverage.info --gcov-tool $(GCOV) + +coverage_report: coverage.info + genhtml coverage.info --output-directory coverage_report + @echo "Coverage report is in coverage_report/index.html" + +clean: + rm -f $(OBJ_FILES) $(COMPONENT_LIB) + rm -f $(COVERAGE_FILES) *.gcov + rm -rf coverage_report/ + rm -f coverage.info + +.PHONY: clean lib all diff --git a/components/spi_flash/sim/SpiFlash.cpp b/components/spi_flash/sim/SpiFlash.cpp new file mode 100644 index 0000000000..2c48ebbdd2 --- /dev/null +++ b/components/spi_flash/sim/SpiFlash.cpp @@ -0,0 +1,127 @@ +// 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. + +#include "SpiFlash.h" + +#include +#include +#include +#include +#include +#include +#include + +#include "sdkconfig.h" +#include "esp_flash_data_types.h" + +using namespace std; + +SpiFlash::SpiFlash() +{ + return; +} + +SpiFlash::~SpiFlash() +{ + deinit(); +} + +void SpiFlash::init(size_t chip_size, size_t block_size, size_t sector_size, size_t page_size, const char* partitions_bin) +{ + // De-initialize first + deinit(); + + this->chip_size = chip_size; + this->block_size = block_size; + this->sector_size = sector_size; + this->page_size = page_size; + + this->memory = (uint8_t *) malloc(this->chip_size); + memset(this->memory, 0xFF, this->chip_size); + + ifstream ifd(partitions_bin, ios::binary | ios::ate); + int size = ifd.tellg(); + + ifd.seekg(0, ios::beg); + vector buffer; + + buffer.resize(size); + + ifd.read(buffer.data(), size); + + memcpy(&this->memory[CONFIG_PARTITION_TABLE_OFFSET], buffer.data(), buffer.size()); +} + +void SpiFlash::deinit() +{ + if(inited) + { + free(this->memory); + } +} + +size_t SpiFlash::get_chip_size() +{ + return this->chip_size; +} + +size_t SpiFlash::get_sector_size() +{ + return this->sector_size; +} + +esp_rom_spiflash_result_t SpiFlash::erase_block(uint32_t block) +{ + memset(&this->memory[block * this->block_size], 0xFF, this->block_size); + return ESP_ROM_SPIFLASH_RESULT_OK; +} + +esp_rom_spiflash_result_t SpiFlash::erase_sector(size_t sector) +{ + memset(&this->memory[sector * this->sector_size], 0xFF, this->sector_size); + return ESP_ROM_SPIFLASH_RESULT_OK; +} + +esp_rom_spiflash_result_t SpiFlash::erase_page(uint32_t page) +{ + memset(&this->memory[page * this->page_size], 0xFF, this->page_size); + return ESP_ROM_SPIFLASH_RESULT_OK; +} + +esp_rom_spiflash_result_t SpiFlash::write(size_t dest_addr, const void *src, size_t size) +{ + // Emulate inability to set programmed bits without erasing + for(uint32_t ctr = 0; ctr < size; ctr++) + { + uint8_t data = ((uint8_t*)src)[ctr]; + uint8_t written = this->memory[dest_addr + ctr]; + + data &= written; + + this->memory[dest_addr + ctr] = data; + } + + return ESP_ROM_SPIFLASH_RESULT_OK; +} + +esp_rom_spiflash_result_t SpiFlash::read(size_t src_addr, void *dest, size_t size) +{ + memcpy(dest, &this->memory[src_addr], size); + return ESP_ROM_SPIFLASH_RESULT_OK; +} + +uint8_t* SpiFlash::get_memory_ptr(uint32_t src_address) +{ + return &this->memory[src_address]; +} \ No newline at end of file diff --git a/components/spi_flash/sim/SpiFlash.h b/components/spi_flash/sim/SpiFlash.h new file mode 100644 index 0000000000..ef879a966c --- /dev/null +++ b/components/spi_flash/sim/SpiFlash.h @@ -0,0 +1,62 @@ +// 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. + +#ifndef _SpiFlash_H_ +#define _SpiFlash_H_ + +#include "esp_err.h" +#include "rom/spi_flash.h" + +/** +* @brief This class is used to emulate flash devices. +* +*/ +class SpiFlash +{ + +public: + SpiFlash(); + ~SpiFlash(); + + void init(size_t chip_size, size_t block_size, size_t sector_size, size_t page_size, const char* partitions_bin); + + esp_rom_spiflash_result_t erase_block(uint32_t block); + esp_rom_spiflash_result_t erase_sector(uint32_t sector); + esp_rom_spiflash_result_t erase_page(uint32_t page); + + esp_rom_spiflash_result_t write(size_t dest_addr, const void *src, size_t size); + esp_rom_spiflash_result_t read(size_t src_addr, void *dest, size_t size); + + size_t get_chip_size(); + size_t get_sector_size(); + + uint8_t* get_memory_ptr(uint32_t src_address); + +private: + bool inited = false; + + size_t chip_size; + size_t block_size; + size_t sector_size; + size_t page_size; + + uint8_t* memory; + + void* partitions; + uint8_t partitions_num; + + void deinit(); +}; + +#endif // _SpiFlash_H_ diff --git a/components/spi_flash/sim/flash_mock.cpp b/components/spi_flash/sim/flash_mock.cpp new file mode 100644 index 0000000000..e6a992ebc0 --- /dev/null +++ b/components/spi_flash/sim/flash_mock.cpp @@ -0,0 +1,65 @@ +#include "SpiFlash.h" + +#include "esp_spi_flash.h" +#include "esp_partition.h" + +#include "esp_err.h" +#include "rom/spi_flash.h" + +static SpiFlash spiflash = SpiFlash(); + +esp_rom_spiflash_chip_t g_rom_flashchip; + +extern "C" void _spi_flash_init(size_t chip_size, size_t block_size, size_t sector_size, size_t page_size, const char* partitions_bin) +{ + spiflash.init(chip_size, block_size, sector_size, page_size, partitions_bin); + + g_rom_flashchip.chip_size = chip_size; + g_rom_flashchip.block_size = block_size; + g_rom_flashchip.sector_size = sector_size; + g_rom_flashchip.page_size = page_size; +} + +esp_err_t spi_flash_mmap(size_t src_addr, size_t size, spi_flash_mmap_memory_t memory, + const void** out_ptr, spi_flash_mmap_handle_t* out_handle) +{ + *out_handle = 0; + *out_ptr = (void*)spiflash.get_memory_ptr(src_addr); + + return ESP_OK; +} + +void spi_flash_munmap(spi_flash_mmap_handle_t handle) +{ + return; +} + +esp_rom_spiflash_result_t esp_rom_spiflash_read(uint32_t target, uint32_t *dest, int32_t len) +{ + return spiflash.read(target, dest, len); +} + +esp_rom_spiflash_result_t esp_rom_spiflash_erase_block(uint32_t block) +{ + return spiflash.erase_block(block); +} + +esp_rom_spiflash_result_t esp_rom_spiflash_erase_sector(uint32_t sector) +{ + return spiflash.erase_sector(sector); +} + +esp_rom_spiflash_result_t esp_rom_spiflash_erase_page(uint32_t page) +{ + return spiflash.erase_page(page); +} + +esp_rom_spiflash_result_t esp_rom_spiflash_write(uint32_t target, const uint32_t *src, int32_t len) +{ + return spiflash.write(target, src, len); +} + +esp_rom_spiflash_result_t esp_rom_spiflash_write_encrypted(uint32_t flash_addr, uint32_t *data, uint32_t len) +{ + return spiflash.write(flash_addr, data, len); +} \ No newline at end of file diff --git a/components/spi_flash/sim/flash_mock_util.c b/components/spi_flash/sim/flash_mock_util.c new file mode 100644 index 0000000000..f12d59ac08 --- /dev/null +++ b/components/spi_flash/sim/flash_mock_util.c @@ -0,0 +1,57 @@ +#include "esp_spi_flash.h" +#include "esp_partition.h" + +#include "esp_err.h" +#include "rom/spi_flash.h" + +extern void _spi_flash_init(size_t chip_size, size_t block_size, size_t sector_size, size_t page_size, const char* partition_bin); + +void spi_flash_init(size_t chip_size, size_t block_size, size_t sector_size, size_t page_size, const char* partition_bin) +{ + _spi_flash_init(chip_size, block_size, sector_size, page_size, partition_bin); +} + +void spi_flash_mark_modified_region(size_t start_addr, size_t length) +{ + return; +} + +esp_rom_spiflash_result_t esp_rom_spiflash_unlock() +{ + return ESP_ROM_SPIFLASH_RESULT_OK; +} + +void spi_flash_init_lock() +{ + return; +} + +void spi_flash_op_lock() +{ + return; +} + +void spi_flash_op_unlock() +{ + return; +} + +void spi_flash_disable_interrupts_caches_and_other_cpu() +{ + return; +} + +void spi_flash_enable_interrupts_caches_and_other_cpu() +{ + return; +} + +void spi_flash_disable_interrupts_caches_and_other_cpu_no_os() +{ + return; +} + +void spi_flash_enable_interrupts_caches_no_os() +{ + return; +} \ No newline at end of file diff --git a/components/spi_flash/sim/sdkconfig.h b/components/spi_flash/sim/sdkconfig.h new file mode 100644 index 0000000000..7d44e7f1ba --- /dev/null +++ b/components/spi_flash/sim/sdkconfig.h @@ -0,0 +1,3 @@ +#pragma once + +#define CONFIG_PARTITION_TABLE_OFFSET 0x8000 diff --git a/components/spi_flash/sim/stubs/app_update/esp_ota_eps.c b/components/spi_flash/sim/stubs/app_update/esp_ota_eps.c new file mode 100644 index 0000000000..59ed6245f6 --- /dev/null +++ b/components/spi_flash/sim/stubs/app_update/esp_ota_eps.c @@ -0,0 +1,13 @@ +#include "esp_ota_ops.h" +#include "esp_partition.h" + +const esp_partition_t* esp_ota_get_running_partition(void) +{ + // Return first instance of an app partition + const esp_partition_t* partition = esp_partition_find_first(ESP_PARTITION_TYPE_APP, + ESP_PARTITION_SUBTYPE_ANY, + NULL); + assert(partition != NULL); + + return partition; +} diff --git a/components/spi_flash/sim/stubs/freertos/include/freertos/FreeRTOS.h b/components/spi_flash/sim/stubs/freertos/include/freertos/FreeRTOS.h new file mode 100644 index 0000000000..e0dd0a7e84 --- /dev/null +++ b/components/spi_flash/sim/stubs/freertos/include/freertos/FreeRTOS.h @@ -0,0 +1,8 @@ +#pragma once + +#include "projdefs.h" +#include "semphr.h" + +// Avoid redefinition compile error. Put here since this is included +// in flash_ops.c. +#define spi_flash_init() overriden_spi_flash_init() diff --git a/components/spi_flash/sim/stubs/freertos/include/freertos/projdefs.h b/components/spi_flash/sim/stubs/freertos/include/freertos/projdefs.h new file mode 100644 index 0000000000..2ec0b5f107 --- /dev/null +++ b/components/spi_flash/sim/stubs/freertos/include/freertos/projdefs.h @@ -0,0 +1,11 @@ +#pragma once + +#if defined(__cplusplus) +extern "C" { +#endif + +#define pdTRUE 1 + +#if defined(__cplusplus) +} +#endif diff --git a/components/spi_flash/sim/stubs/freertos/include/freertos/semphr.h b/components/spi_flash/sim/stubs/freertos/include/freertos/semphr.h new file mode 100644 index 0000000000..d49cafb99f --- /dev/null +++ b/components/spi_flash/sim/stubs/freertos/include/freertos/semphr.h @@ -0,0 +1,16 @@ +#pragma once + +#if defined(__cplusplus) +extern "C" { +#endif + +#define vSemaphoreDelete( xSemaphore ) +#define xSemaphoreCreateMutex() ((void*)(1)) +#define xSemaphoreGive( xSemaphore ) +#define xSemaphoreTake( xSemaphore, xBlockTime ) pdTRUE + +typedef void* SemaphoreHandle_t; + +#if defined(__cplusplus) +} +#endif diff --git a/components/spi_flash/sim/stubs/freertos/include/freertos/task.h b/components/spi_flash/sim/stubs/freertos/include/freertos/task.h new file mode 100644 index 0000000000..7b9637ef9c --- /dev/null +++ b/components/spi_flash/sim/stubs/freertos/include/freertos/task.h @@ -0,0 +1 @@ +#pragma once \ No newline at end of file diff --git a/components/spi_flash/sim/stubs/log/include/esp_log.h b/components/spi_flash/sim/stubs/log/include/esp_log.h new file mode 100644 index 0000000000..a9c2380006 --- /dev/null +++ b/components/spi_flash/sim/stubs/log/include/esp_log.h @@ -0,0 +1,48 @@ +#pragma once + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define LOG_LOCAL_LEVEL ESP_LOG_DEBUG + +typedef enum { + ESP_LOG_NONE, /*!< No log output */ + ESP_LOG_ERROR, /*!< Critical errors, software module can not recover on its own */ + ESP_LOG_WARN, /*!< Error conditions from which recovery measures have been taken */ + ESP_LOG_INFO, /*!< Information messages which describe normal flow of events */ + ESP_LOG_DEBUG, /*!< Extra information which is not necessary for normal use (values, pointers, sizes, etc). */ + ESP_LOG_VERBOSE /*!< Bigger chunks of debugging information, or frequent messages which can potentially flood the output. */ +} esp_log_level_t; + +#define LOG_COLOR_E +#define LOG_COLOR_W +#define LOG_COLOR_I +#define LOG_COLOR_D +#define LOG_COLOR_V +#define LOG_RESET_COLOR + +uint32_t esp_log_timestamp(void); +void esp_log_write(esp_log_level_t level, const char* tag, const char* format, ...) __attribute__ ((format (printf, 3, 4))); + +#define LOG_FORMAT(letter, format) LOG_COLOR_ ## letter #letter " (%d) %s: " format LOG_RESET_COLOR "\n" + +#define ESP_LOGE( tag, format, ... ) if (LOG_LOCAL_LEVEL >= ESP_LOG_ERROR) { esp_log_write(ESP_LOG_ERROR, tag, LOG_FORMAT(E, format), esp_log_timestamp(), tag, ##__VA_ARGS__); } + +#define ESP_LOGV( tag, format, ... ) if (LOG_LOCAL_LEVEL >= ESP_LOG_VERBOSE) { esp_log_write(ESP_LOG_VERBOSE, tag, LOG_FORMAT(V, format), esp_log_timestamp(), tag, ##__VA_ARGS__); } + +#define ESP_LOGD( tag, format, ... ) if (LOG_LOCAL_LEVEL >= ESP_LOG_DEBUG) { esp_log_write(ESP_LOG_DEBUG, tag, LOG_FORMAT(D, format), esp_log_timestamp(), tag, ##__VA_ARGS__); } + +#define ESP_LOGW( tag, format, ... ) if (LOG_LOCAL_LEVEL >= ESP_LOG_WARN) { esp_log_write(ESP_LOG_WARN, tag, LOG_FORMAT(W, format), esp_log_timestamp(), tag, ##__VA_ARGS__); } + +// Assume that flash encryption is not enabled. Put here since in partition.c +// esp_log.h is included later than esp_flash_encrypt.h. +#define esp_flash_encryption_enabled() false + +#ifdef __cplusplus +} +#endif + diff --git a/components/spi_flash/sim/stubs/log/log.c b/components/spi_flash/sim/stubs/log/log.c new file mode 100644 index 0000000000..5d606d357f --- /dev/null +++ b/components/spi_flash/sim/stubs/log/log.c @@ -0,0 +1,22 @@ +#include +#include +#include +#include + +#include "esp_log.h" + +void esp_log_write(esp_log_level_t level, + const char *tag, + const char *format, ...) +{ + va_list arg; + va_start(arg, format); + vprintf(format, arg); + va_end(arg); +} + +uint32_t esp_log_timestamp() +{ + return 0; +} + diff --git a/components/spi_flash/sim/stubs/newlib/include/sys/lock.h b/components/spi_flash/sim/stubs/newlib/include/sys/lock.h new file mode 100644 index 0000000000..2b5b9f59ec --- /dev/null +++ b/components/spi_flash/sim/stubs/newlib/include/sys/lock.h @@ -0,0 +1,17 @@ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +typedef int _lock_t; + +void _lock_acquire(_lock_t *lock); +void _lock_close(_lock_t *lock); +void _lock_init(_lock_t *lock); +void _lock_release(_lock_t *lock); + +#ifdef __cplusplus +} +#endif + diff --git a/components/spi_flash/sim/stubs/newlib/lock.c b/components/spi_flash/sim/stubs/newlib/lock.c new file mode 100644 index 0000000000..f221fdbda1 --- /dev/null +++ b/components/spi_flash/sim/stubs/newlib/lock.c @@ -0,0 +1,21 @@ +#include "sys/lock.h" + +void _lock_acquire(_lock_t *lock) +{ + return; +} + +void _lock_close(_lock_t *lock) +{ + return; +} + +void _lock_init(_lock_t *lock) +{ + return; +} + +void _lock_release(_lock_t *lock) +{ + return; +} diff --git a/components/spiffs/CMakeLists.txt b/components/spiffs/CMakeLists.txt index a85f98d2b3..54356cb0d6 100644 --- a/components/spiffs/CMakeLists.txt +++ b/components/spiffs/CMakeLists.txt @@ -1,6 +1,6 @@ set(COMPONENT_ADD_INCLUDEDIRS "include") -set(COMPONENT_PRIV_INCLUDEDIRS "spiffs/src") -set(COMPONENT_SRCDIRS ". spiffs/src") +set(COMPONENT_PRIV_INCLUDEDIRS "." "spiffs/src") +set(COMPONENT_SRCDIRS "." "spiffs/src") set(COMPONENT_REQUIRES spi_flash) set(COMPONENT_PRIV_REQUIRES bootloader_support) diff --git a/components/spiffs/component.mk b/components/spiffs/component.mk index 70f96dfd49..f245a57e10 100644 --- a/components/spiffs/component.mk +++ b/components/spiffs/component.mk @@ -1,5 +1,5 @@ COMPONENT_ADD_INCLUDEDIRS := include -COMPONENT_PRIV_INCLUDEDIRS := spiffs/src +COMPONENT_PRIV_INCLUDEDIRS := . spiffs/src COMPONENT_SRCDIRS := . spiffs/src COMPONENT_SUBMODULES := spiffs diff --git a/components/spiffs/esp_spiffs.c b/components/spiffs/esp_spiffs.c index d5fb180038..e24cb12c07 100644 --- a/components/spiffs/esp_spiffs.c +++ b/components/spiffs/esp_spiffs.c @@ -30,29 +30,12 @@ #include "esp_vfs.h" #include "esp_err.h" #include "rom/spi_flash.h" - -static const char * TAG = "SPIFFS"; +#include "spiffs_api.h" #ifdef CONFIG_SPIFFS_USE_MTIME _Static_assert(CONFIG_SPIFFS_META_LENGTH >= sizeof(time_t), "SPIFFS_META_LENGTH size should be >= sizeof(time_t)"); #endif //CONFIG_SPIFFS_USE_MTIME -/** - * @brief SPIFFS definition structure - */ -typedef struct { - spiffs *fs; /*!< Handle to the underlying SPIFFS */ - SemaphoreHandle_t lock; /*!< FS lock */ - const esp_partition_t* partition; /*!< The partition on which SPIFFS is located */ - char base_path[ESP_VFS_PATH_MAX+1]; /*!< Mount point */ - bool by_label; /*!< Partition was mounted by label */ - spiffs_config cfg; /*!< SPIFFS Mount configuration */ - uint8_t *work; /*!< Work Buffer */ - uint8_t *fds; /*!< File Descriptor Buffer */ - uint32_t fds_sz; /*!< File Descriptor Buffer Length */ - uint8_t *cache; /*!< Cache Buffer */ - uint32_t cache_sz; /*!< Cache Buffer Length */ -} esp_spiffs_t; /** * @brief SPIFFS DIR structure @@ -89,77 +72,6 @@ static time_t vfs_spiffs_get_mtime(const spiffs_stat* s); static esp_spiffs_t * _efs[CONFIG_SPIFFS_MAX_PARTITIONS]; -void spiffs_api_lock(spiffs *fs) -{ - xSemaphoreTake(((esp_spiffs_t *)(fs->user_data))->lock, portMAX_DELAY); -} - -void spiffs_api_unlock(spiffs *fs) -{ - xSemaphoreGive(((esp_spiffs_t *)(fs->user_data))->lock); -} - -static s32_t spiffs_api_read(spiffs *fs, uint32_t addr, uint32_t size, uint8_t *dst) -{ - esp_err_t err = esp_partition_read(((esp_spiffs_t *)(fs->user_data))->partition, - addr, dst, size); - if (err) { - ESP_LOGE(TAG, "failed to read addr %08x, size %08x, err %d", addr, size, err); - return -1; - } - return 0; -} - -static s32_t spiffs_api_write(spiffs *fs, uint32_t addr, uint32_t size, uint8_t *src) -{ - esp_err_t err = esp_partition_write(((esp_spiffs_t *)(fs->user_data))->partition, - addr, src, size); - if (err) { - ESP_LOGE(TAG, "failed to write addr %08x, size %08x, err %d", addr, size, err); - return -1; - } - return 0; -} - -static s32_t spiffs_api_erase(spiffs *fs, uint32_t addr, uint32_t size) -{ - esp_err_t err = esp_partition_erase_range(((esp_spiffs_t *)(fs->user_data))->partition, - addr, size); - if (err) { - ESP_LOGE(TAG, "failed to erase addr %08x, size %08x, err %d", addr, size, err); - return -1; - } - return 0; -} - -static void spiffs_api_check(spiffs *fs, spiffs_check_type type, - spiffs_check_report report, uint32_t arg1, uint32_t arg2) -{ - static const char * spiffs_check_type_str[3] = { - "LOOKUP", - "INDEX", - "PAGE" - }; - - static const char * spiffs_check_report_str[7] = { - "PROGRESS", - "ERROR", - "FIX INDEX", - "FIX LOOKUP", - "DELETE ORPHANED INDEX", - "DELETE PAGE", - "DELETE BAD FILE" - }; - - if (report != SPIFFS_CHECK_PROGRESS) { - ESP_LOGE(TAG, "CHECK: type:%s, report:%s, %x:%x", spiffs_check_type_str[type], - spiffs_check_report_str[report], arg1, arg2); - } else { - ESP_LOGV(TAG, "CHECK PROGRESS: report:%s, %x:%x", - spiffs_check_report_str[report], arg1, arg2); - } -} - static void esp_spiffs_free(esp_spiffs_t ** efs) { esp_spiffs_t * e = *efs; @@ -232,7 +144,7 @@ static esp_err_t esp_spiffs_init(const esp_vfs_spiffs_conf_t* conf) esp_partition_subtype_t subtype = conf->partition_label ? ESP_PARTITION_SUBTYPE_ANY : ESP_PARTITION_SUBTYPE_DATA_SPIFFS; - const esp_partition_t* partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, + const esp_partition_t* partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, subtype, conf->partition_label); if (!partition) { ESP_LOGE(TAG, "spiffs partition could not be found"); @@ -310,7 +222,7 @@ static esp_err_t esp_spiffs_init(const esp_vfs_spiffs_conf_t* conf) efs->fs->user_data = (void *)efs; efs->partition = partition; - s32_t res = SPIFFS_mount(efs->fs, &efs->cfg, efs->work, efs->fds, efs->fds_sz, + s32_t res = SPIFFS_mount(efs->fs, &efs->cfg, efs->work, efs->fds, efs->fds_sz, efs->cache, efs->cache_sz, spiffs_api_check); if (conf->format_if_mount_failed && res != SPIFFS_OK) { @@ -323,7 +235,7 @@ static esp_err_t esp_spiffs_init(const esp_vfs_spiffs_conf_t* conf) esp_spiffs_free(&efs); return ESP_FAIL; } - res = SPIFFS_mount(efs->fs, &efs->cfg, efs->work, efs->fds, efs->fds_sz, + res = SPIFFS_mount(efs->fs, &efs->cfg, efs->work, efs->fds, efs->fds_sz, efs->cache, efs->cache_sz, spiffs_api_check); } if (res != SPIFFS_OK) { @@ -710,27 +622,30 @@ static struct dirent* vfs_spiffs_readdir(void* ctx, DIR* pdir) return out_dirent; } -static int vfs_spiffs_readdir_r(void* ctx, DIR* pdir, struct dirent* entry, +static int vfs_spiffs_readdir_r(void* ctx, DIR* pdir, struct dirent* entry, struct dirent** out_dirent) { assert(pdir); esp_spiffs_t * efs = (esp_spiffs_t *)ctx; vfs_spiffs_dir_t * dir = (vfs_spiffs_dir_t *)pdir; struct spiffs_dirent out; - if (SPIFFS_readdir(&dir->d, &out) == 0) { - errno = spiffs_res_to_errno(SPIFFS_errno(efs->fs)); - SPIFFS_clearerr(efs->fs); - if (!errno) { - *out_dirent = NULL; + size_t plen; + char * item_name; + do { + if (SPIFFS_readdir(&dir->d, &out) == 0) { + errno = spiffs_res_to_errno(SPIFFS_errno(efs->fs)); + SPIFFS_clearerr(efs->fs); + if (!errno) { + *out_dirent = NULL; + } + return errno; } - return errno; - } - const char * item_name = (const char *)out.name; - size_t plen = strlen(dir->path); + item_name = (char *)out.name; + plen = strlen(dir->path); + + } while ((plen > 1) && (strncasecmp(dir->path, (const char*)out.name, plen) || out.name[plen] != '/' || !out.name[plen + 1])); + if (plen > 1) { - if (strncasecmp(dir->path, (const char *)out.name, plen) || out.name[plen] != '/' || !out.name[plen+1]) { - return vfs_spiffs_readdir_r(ctx, pdir, entry, out_dirent); - } item_name += plen + 1; } else if (item_name[0] == '/') { item_name++; diff --git a/components/spiffs/spiffs_api.c b/components/spiffs/spiffs_api.c new file mode 100644 index 0000000000..6dd3db9637 --- /dev/null +++ b/components/spiffs/spiffs_api.c @@ -0,0 +1,93 @@ +// 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. + +#include "freertos/FreeRTOS.h" +#include "esp_log.h" +#include "esp_partition.h" +#include "esp_spiffs.h" +#include "esp_vfs.h" +#include "spiffs_api.h" + +const char* TAG = "SPIFFS"; + +void spiffs_api_lock(spiffs *fs) +{ + xSemaphoreTake(((esp_spiffs_t *)(fs->user_data))->lock, portMAX_DELAY); +} + +void spiffs_api_unlock(spiffs *fs) +{ + xSemaphoreGive(((esp_spiffs_t *)(fs->user_data))->lock); +} + +s32_t spiffs_api_read(spiffs *fs, uint32_t addr, uint32_t size, uint8_t *dst) +{ + esp_err_t err = esp_partition_read(((esp_spiffs_t *)(fs->user_data))->partition, + addr, dst, size); + if (err) { + ESP_LOGE(TAG, "failed to read addr %08x, size %08x, err %d", addr, size, err); + return -1; + } + return 0; +} + +s32_t spiffs_api_write(spiffs *fs, uint32_t addr, uint32_t size, uint8_t *src) +{ + esp_err_t err = esp_partition_write(((esp_spiffs_t *)(fs->user_data))->partition, + addr, src, size); + if (err) { + ESP_LOGE(TAG, "failed to write addr %08x, size %08x, err %d", addr, size, err); + return -1; + } + return 0; +} + +s32_t spiffs_api_erase(spiffs *fs, uint32_t addr, uint32_t size) +{ + esp_err_t err = esp_partition_erase_range(((esp_spiffs_t *)(fs->user_data))->partition, + addr, size); + if (err) { + ESP_LOGE(TAG, "failed to erase addr %08x, size %08x, err %d", addr, size, err); + return -1; + } + return 0; +} + +void spiffs_api_check(spiffs *fs, spiffs_check_type type, + spiffs_check_report report, uint32_t arg1, uint32_t arg2) +{ + static const char * spiffs_check_type_str[3] = { + "LOOKUP", + "INDEX", + "PAGE" + }; + + static const char * spiffs_check_report_str[7] = { + "PROGRESS", + "ERROR", + "FIX INDEX", + "FIX LOOKUP", + "DELETE ORPHANED INDEX", + "DELETE PAGE", + "DELETE BAD FILE" + }; + + if (report != SPIFFS_CHECK_PROGRESS) { + ESP_LOGE(TAG, "CHECK: type:%s, report:%s, %x:%x", spiffs_check_type_str[type], + spiffs_check_report_str[report], arg1, arg2); + } else { + ESP_LOGV(TAG, "CHECK PROGRESS: report:%s, %x:%x", + spiffs_check_report_str[report], arg1, arg2); + } +} diff --git a/components/spiffs/spiffs_api.h b/components/spiffs/spiffs_api.h new file mode 100644 index 0000000000..492da7cde7 --- /dev/null +++ b/components/spiffs/spiffs_api.h @@ -0,0 +1,59 @@ +// 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. + +#pragma once + +#include +#include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/semphr.h" +#include "spiffs.h" +#include "esp_vfs.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern const char* TAG; + +/** + * @brief SPIFFS definition structure + */ +typedef struct { + spiffs *fs; /*!< Handle to the underlying SPIFFS */ + SemaphoreHandle_t lock; /*!< FS lock */ + const esp_partition_t* partition; /*!< The partition on which SPIFFS is located */ + char base_path[ESP_VFS_PATH_MAX+1]; /*!< Mount point */ + bool by_label; /*!< Partition was mounted by label */ + spiffs_config cfg; /*!< SPIFFS Mount configuration */ + uint8_t *work; /*!< Work Buffer */ + uint8_t *fds; /*!< File Descriptor Buffer */ + uint32_t fds_sz; /*!< File Descriptor Buffer Length */ + uint8_t *cache; /*!< Cache Buffer */ + uint32_t cache_sz; /*!< Cache Buffer Length */ +} esp_spiffs_t; + +s32_t spiffs_api_read(spiffs *fs, uint32_t addr, uint32_t size, uint8_t *dst); + +s32_t spiffs_api_write(spiffs *fs, uint32_t addr, uint32_t size, uint8_t *src); + +s32_t spiffs_api_erase(spiffs *fs, uint32_t addr, uint32_t size); + +void spiffs_api_check(spiffs *fs, spiffs_check_type type, + spiffs_check_report report, uint32_t arg1, uint32_t arg2); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/components/spiffs/test/test_spiffs.c b/components/spiffs/test/test_spiffs.c index 3805848b43..60bca410bd 100644 --- a/components/spiffs/test/test_spiffs.c +++ b/components/spiffs/test/test_spiffs.c @@ -275,6 +275,63 @@ void test_spiffs_opendir_readdir_rewinddir(const char* dir_prefix) TEST_ASSERT_EQUAL(0, closedir(dir)); } +void test_spiffs_readdir_many_files(const char* dir_prefix) +{ + const int n_files = 40; + const int n_folders = 4; + unsigned char file_count[n_files * n_folders]; + memset(file_count, 0, sizeof(file_count)/sizeof(file_count[0])); + char file_name[ESP_VFS_PATH_MAX + CONFIG_SPIFFS_OBJ_NAME_LEN]; + + /* clean stale files before the test */ + DIR* dir = opendir(dir_prefix); + if (dir) { + while (true) { + struct dirent* de = readdir(dir); + if (!de) { + break; + } + snprintf(file_name, sizeof(file_name), "%s/%s", dir_prefix, de->d_name); + unlink(file_name); + } + } + + /* create files */ + for (int d = 0; d < n_folders; ++d) { + printf("filling directory %d\n", d); + for (int f = 0; f < n_files; ++f) { + snprintf(file_name, sizeof(file_name), "%s/%d/%d.txt", dir_prefix, d, f); + test_spiffs_create_file_with_text(file_name, file_name); + } + } + + /* list files */ + for (int d = 0; d < n_folders; ++d) { + printf("listing files in directory %d\n", d); + snprintf(file_name, sizeof(file_name), "%s/%d", dir_prefix, d); + dir = opendir(file_name); + TEST_ASSERT_NOT_NULL(dir); + while (true) { + struct dirent* de = readdir(dir); + if (!de) { + break; + } + int file_id; + TEST_ASSERT_EQUAL(1, sscanf(de->d_name, "%d.txt", &file_id)); + file_count[file_id + d * n_files]++; + } + closedir(dir); + } + + /* check that all created files have been seen */ + for (int d = 0; d < n_folders; ++d) { + printf("checking that all files have been found in directory %d\n", d); + for (int f = 0; f < n_files; ++f) { + TEST_ASSERT_EQUAL(1, file_count[f + d * n_files]); + } + } +} + typedef struct { const char* filename; @@ -537,6 +594,13 @@ TEST_CASE("opendir, readdir, rewinddir, seekdir work as expected", "[spiffs]") test_teardown(); } +TEST_CASE("readdir with large number of files", "[spiffs][timeout=15]") +{ + test_setup(); + test_spiffs_readdir_many_files("/spiffs/dir2"); + test_teardown(); +} + TEST_CASE("multiple tasks can use same volume", "[spiffs]") { test_setup(); diff --git a/components/spiffs/test_spiffs_host/Makefile b/components/spiffs/test_spiffs_host/Makefile new file mode 100644 index 0000000000..db94ab96f5 --- /dev/null +++ b/components/spiffs/test_spiffs_host/Makefile @@ -0,0 +1,97 @@ +COMPONENT=spiffs + +TEST_PROGRAM=test_$(COMPONENT) + +#Expose as a library +COMPONENT_LIB=lib$(COMPONENT).a + +SPI_FLASH=spi_flash +SPI_FLASH_DIR=../../$(SPI_FLASH) +SPI_FLASH_SIM_DIR=$(SPI_FLASH_DIR)/sim +SPI_FLASH_LIB=lib$(SPI_FLASH).a + +all: $(TEST_PROGRAM) + +SOURCE_FILES = \ + ../spiffs_api.c \ + $(addprefix ../spiffs/src/, \ + spiffs_cache.c \ + spiffs_check.c \ + spiffs_gc.c \ + spiffs_hydrogen.c \ + spiffs_nucleus.c \ + ) \ + $(addprefix ./stubs/, \ + log/log.c \ + ) + +TEST_SOURCE_FILES = \ + test_spiffs.cpp \ + main.cpp \ + test_utils.c + +INCLUDE_FLAGS = $(addprefix -I,\ + . \ + .. \ + ../spiffs/src \ + ../include \ + $(addprefix ./stubs/, \ + log/include \ + freertos/include \ + newlib/include \ + vfs/include \ + ) \ + ../../esp32/include \ + $(SPI_FLASH_DIR)/include \ + ../../../tools/catch \ +) + +GCOV ?= gcov + +CPPFLAGS += $(INCLUDE_FLAGS) -D CONFIG_LOG_DEFAULT_LEVEL -g -m32 +CFLAGS += -fprofile-arcs -ftest-coverage +CXXFLAGS += -std=c++11 -Wall -Werror -fprofile-arcs -ftest-coverage +LDFLAGS += -lstdc++ -fprofile-arcs -ftest-coverage + +OBJ_FILES = $(filter %.o, $(SOURCE_FILES:.cpp=.o) $(SOURCE_FILES:.c=.o)) +TEST_OBJ_FILES = $(filter %.o, $(TEST_SOURCE_FILES:.cpp=.o) $(TEST_SOURCE_FILES:.c=.o)) + +$(SPI_FLASH_SIM_DIR)/$(SPI_FLASH_LIB): force + $(MAKE) -C $(SPI_FLASH_SIM_DIR) lib + +force: + +$(COMPONENT_LIB): $(OBJ_FILES) + $(AR) rcs $@ $^ + +lib: $(COMPONENT_LIB) + +partitions_table.bin: partitions_table.csv + python ../../partition_table/gen_esp32part.py --verify $< $@ + +$(TEST_PROGRAM): lib $(TEST_OBJ_FILES) $(SPI_FLASH_SIM_DIR)/$(SPI_FLASH_LIB) partitions_table.bin + g++ $(LDFLAGS) -o $(TEST_PROGRAM) $(TEST_OBJ_FILES) -L$(abspath .) -l:$(COMPONENT_LIB) -L$(SPI_FLASH_SIM_DIR) -l:$(SPI_FLASH_LIB) -g -m32 + +test: $(TEST_PROGRAM) + ./$(TEST_PROGRAM) + +COVERAGE_FILES = $(OBJ_FILES:.o=.gc*) $(TEST_OBJ_FILES:.o=.gc*) + +$(COVERAGE_FILES): test + +coverage.info: $(COVERAGE_FILES) + find ../ -name "*.gcno" -exec $(GCOV) -r -pb {} + + lcov --capture --directory ../ --no-external --output-file coverage.info --gcov-tool $(GCOV) + +coverage_report: coverage.info + genhtml coverage.info --output-directory coverage_report + @echo "Coverage report is in coverage_report/index.html" + +clean: + rm -f $(OBJ_FILES) $(TEST_OBJ_FILES) $(TEST_PROGRAM) $(COMPONENT_LIB) partitions_table.bin + $(MAKE) -C $(SPI_FLASH_SIM_DIR) clean + rm -f $(COVERAGE_FILES) *.gcov + rm -rf coverage_report/ + rm -f coverage.info + +.PHONY: clean all test lib diff --git a/components/spiffs/test_spiffs_host/main.cpp b/components/spiffs/test_spiffs_host/main.cpp new file mode 100644 index 0000000000..178916eab8 --- /dev/null +++ b/components/spiffs/test_spiffs_host/main.cpp @@ -0,0 +1,3 @@ +#define CATCH_CONFIG_MAIN +#include "catch.hpp" + diff --git a/components/spiffs/test_spiffs_host/partitions_table.csv b/components/spiffs/test_spiffs_host/partitions_table.csv new file mode 100644 index 0000000000..d02771b51b --- /dev/null +++ b/components/spiffs/test_spiffs_host/partitions_table.csv @@ -0,0 +1,6 @@ +# Name, Type, SubType, Offset, Size, Flags +# Note: if you change the phy_init or app partition offset, make sure to change the offset in Kconfig.projbuild +nvs, data, nvs, 0x9000, 0x6000, +phy_init, data, phy, 0xf000, 0x1000, +factory, app, factory, 0x10000, 1M, +storage, data, spiffs, , 2M, diff --git a/components/spiffs/test_spiffs_host/sdkconfig.h b/components/spiffs/test_spiffs_host/sdkconfig.h new file mode 100644 index 0000000000..f798d5ebc8 --- /dev/null +++ b/components/spiffs/test_spiffs_host/sdkconfig.h @@ -0,0 +1,14 @@ +#pragma once + +#define CONFIG_SPIFFS_USE_MAGIC_LENGTH 1 +#define CONFIG_SPIFFS_MAX_PARTITIONS 3 +#define CONFIG_SPIFFS_OBJ_NAME_LEN 32 +#define CONFIG_SPIFFS_PAGE_SIZE 256 +#define CONFIG_SPIFFS_GC_MAX_RUNS 10 +#define CONFIG_SPIFFS_CACHE_WR 1 +#define CONFIG_SPIFFS_CACHE 1 +#define CONFIG_SPIFFS_META_LENGTH 4 +#define CONFIG_SPIFFS_USE_MAGIC 1 +#define CONFIG_SPIFFS_PAGE_CHECK 1 +#define CONFIG_SPIFFS_USE_MTIME 1 +#define CONFIG_WL_SECTOR_SIZE 4096 diff --git a/components/spiffs/test_spiffs_host/stubs/freertos/include/freertos/FreeRTOS.h b/components/spiffs/test_spiffs_host/stubs/freertos/include/freertos/FreeRTOS.h new file mode 100644 index 0000000000..5bafa772df --- /dev/null +++ b/components/spiffs/test_spiffs_host/stubs/freertos/include/freertos/FreeRTOS.h @@ -0,0 +1,4 @@ +#pragma once + +#include "projdefs.h" +#include "semphr.h" diff --git a/components/spiffs/test_spiffs_host/stubs/freertos/include/freertos/projdefs.h b/components/spiffs/test_spiffs_host/stubs/freertos/include/freertos/projdefs.h new file mode 100644 index 0000000000..aa8c7a3de5 --- /dev/null +++ b/components/spiffs/test_spiffs_host/stubs/freertos/include/freertos/projdefs.h @@ -0,0 +1,11 @@ +#pragma once + +#if defined(__cplusplus) +extern "C" { +#endif + +#define pdTRUE 1 + +#if defined(__cplusplus) +} +#endif diff --git a/components/spiffs/test_spiffs_host/stubs/freertos/include/freertos/semphr.h b/components/spiffs/test_spiffs_host/stubs/freertos/include/freertos/semphr.h new file mode 100644 index 0000000000..c589795fbe --- /dev/null +++ b/components/spiffs/test_spiffs_host/stubs/freertos/include/freertos/semphr.h @@ -0,0 +1,16 @@ +#pragma once + +#if defined(__cplusplus) +extern "C" { +#endif + +#define vSemaphoreDelete( xSemaphore ) +#define xSemaphoreCreateMutex() ((void*)(1)) +#define xSemaphoreGive( xSemaphore ) +#define xSemaphoreTake( xSemaphore, xBlockTime ) pdTRUE + +typedef void* SemaphoreHandle_t; + +#if defined(__cplusplus) +} +#endif diff --git a/components/spiffs/test_spiffs_host/stubs/freertos/include/freertos/task.h b/components/spiffs/test_spiffs_host/stubs/freertos/include/freertos/task.h new file mode 100644 index 0000000000..7b9637ef9c --- /dev/null +++ b/components/spiffs/test_spiffs_host/stubs/freertos/include/freertos/task.h @@ -0,0 +1 @@ +#pragma once \ No newline at end of file diff --git a/components/spiffs/test_spiffs_host/stubs/log/include/esp_log.h b/components/spiffs/test_spiffs_host/stubs/log/include/esp_log.h new file mode 100644 index 0000000000..84756cdb93 --- /dev/null +++ b/components/spiffs/test_spiffs_host/stubs/log/include/esp_log.h @@ -0,0 +1,51 @@ +#pragma once + +#include +#include + +#include "sdkconfig.h" + +#define strlcpy(a, b, c) +#define strlcat(a, b, c) + +#if defined(__cplusplus) +extern "C" { +#endif + +#define LOG_LOCAL_LEVEL ESP_LOG_DEBUG + +typedef enum { + ESP_LOG_NONE, /*!< No log output */ + ESP_LOG_ERROR, /*!< Critical errors, software module can not recover on its own */ + ESP_LOG_WARN, /*!< Error conditions from which recovery measures have been taken */ + ESP_LOG_INFO, /*!< Information messages which describe normal flow of events */ + ESP_LOG_DEBUG, /*!< Extra information which is not necessary for normal use (values, pointers, sizes, etc). */ + ESP_LOG_VERBOSE /*!< Bigger chunks of debugging information, or frequent messages which can potentially flood the output. */ +} esp_log_level_t; + +#define LOG_COLOR_E +#define LOG_COLOR_W +#define LOG_COLOR_I +#define LOG_COLOR_D +#define LOG_COLOR_V +#define LOG_RESET_COLOR + +#undef _Static_assert +#define _Static_assert(cond, message) + +uint32_t esp_log_timestamp(void); +void esp_log_write(esp_log_level_t level, const char* tag, const char* format, ...) __attribute__ ((format (printf, 3, 4))); + +#define LOG_FORMAT(letter, format) LOG_COLOR_ ## letter #letter " (%d) %s: " format LOG_RESET_COLOR "\n" + +#define ESP_LOGE( tag, format, ... ) if (LOG_LOCAL_LEVEL >= ESP_LOG_ERROR) { esp_log_write(ESP_LOG_ERROR, tag, LOG_FORMAT(E, format), esp_log_timestamp(), tag, ##__VA_ARGS__); } + +#define ESP_LOGV( tag, format, ... ) if (LOG_LOCAL_LEVEL >= ESP_LOG_VERBOSE) { esp_log_write(ESP_LOG_VERBOSE, tag, LOG_FORMAT(V, format), esp_log_timestamp(), tag, ##__VA_ARGS__); } + +#define ESP_LOGD( tag, format, ... ) if (LOG_LOCAL_LEVEL >= ESP_LOG_DEBUG) { esp_log_write(ESP_LOG_DEBUG, tag, LOG_FORMAT(D, format), esp_log_timestamp(), tag, ##__VA_ARGS__); } + +#define ESP_LOGW( tag, format, ... ) if (LOG_LOCAL_LEVEL >= ESP_LOG_WARN) { esp_log_write(ESP_LOG_WARN, tag, LOG_FORMAT(W, format), esp_log_timestamp(), tag, ##__VA_ARGS__); } + +#if defined(__cplusplus) +} +#endif \ No newline at end of file diff --git a/components/spiffs/test_spiffs_host/stubs/log/log.c b/components/spiffs/test_spiffs_host/stubs/log/log.c new file mode 100644 index 0000000000..d01a96ff45 --- /dev/null +++ b/components/spiffs/test_spiffs_host/stubs/log/log.c @@ -0,0 +1,22 @@ + +#include +#include +#include + +#include "esp_log.h" + +void esp_log_write(esp_log_level_t level, + const char *tag, + const char *format, ...) +{ + va_list arg; + va_start(arg, format); + vprintf(format, arg); + va_end(arg); +} + +uint32_t esp_log_timestamp() +{ + return 0; +} + diff --git a/components/spiffs/test_spiffs_host/stubs/newlib/include/sys/lock.h b/components/spiffs/test_spiffs_host/stubs/newlib/include/sys/lock.h new file mode 100644 index 0000000000..7892465ada --- /dev/null +++ b/components/spiffs/test_spiffs_host/stubs/newlib/include/sys/lock.h @@ -0,0 +1,10 @@ +#pragma once + +#include + +typedef int _lock_t; + +void _lock_acquire(_lock_t *lock); +void _lock_close(_lock_t *lock); +void _lock_init(_lock_t *lock); +void _lock_release(_lock_t *lock); diff --git a/components/spiffs/test_spiffs_host/stubs/newlib/lock.c b/components/spiffs/test_spiffs_host/stubs/newlib/lock.c new file mode 100644 index 0000000000..697615ffd9 --- /dev/null +++ b/components/spiffs/test_spiffs_host/stubs/newlib/lock.c @@ -0,0 +1,21 @@ +#include "sys/lock.h" + +void _lock_acquire(_lock_t *lock) +{ + return; +} + +void _lock_close(_lock_t *lock) +{ + return; +} + +void _lock_init(_lock_t *lock) +{ + return; +} + +void _lock_release(_lock_t *lock) +{ + return; +} diff --git a/components/spiffs/test_spiffs_host/stubs/vfs/include/esp_vfs.h b/components/spiffs/test_spiffs_host/stubs/vfs/include/esp_vfs.h new file mode 100644 index 0000000000..36c6384a3e --- /dev/null +++ b/components/spiffs/test_spiffs_host/stubs/vfs/include/esp_vfs.h @@ -0,0 +1,6 @@ +#pragma once + +#include "esp_err.h" + +#define ESP_VFS_FLAG_CONTEXT_PTR 1 +#define ESP_VFS_PATH_MAX 15 diff --git a/components/spiffs/test_spiffs_host/test_spiffs.cpp b/components/spiffs/test_spiffs_host/test_spiffs.cpp new file mode 100644 index 0000000000..d4a76210e6 --- /dev/null +++ b/components/spiffs/test_spiffs_host/test_spiffs.cpp @@ -0,0 +1,107 @@ +#include +#include +#include + +#include "esp_partition.h" +#include "spiffs.h" +#include "spiffs_nucleus.h" +#include "spiffs_api.h" + +#include "catch.hpp" + +extern "C" void init_spi_flash(size_t chip_size, size_t block_size, size_t sector_size, size_t page_size, const char* partition_bin); + +TEST_CASE("format disk, open file, write and read file", "[spiffs]") +{ + init_spi_flash(0x00400000, CONFIG_WL_SECTOR_SIZE * 16, CONFIG_WL_SECTOR_SIZE, CONFIG_WL_SECTOR_SIZE, "partitions_table.bin"); + + spiffs fs; + spiffs_config cfg; + + const esp_partition_t *partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_SPIFFS, "storage"); + + // Configure objects needed by SPIFFS + esp_spiffs_t esp_user_data; + esp_user_data.partition = partition; + fs.user_data = (void*)&esp_user_data; + + cfg.hal_erase_f = spiffs_api_erase; + cfg.hal_read_f = spiffs_api_read; + cfg.hal_write_f = spiffs_api_write; + cfg.log_block_size = CONFIG_WL_SECTOR_SIZE; + cfg.log_page_size = CONFIG_SPIFFS_PAGE_SIZE; + cfg.phys_addr = 0; + cfg.phys_erase_block = CONFIG_WL_SECTOR_SIZE; + cfg.phys_size = partition->size; + + uint32_t max_files = 5; + + uint32_t fds_sz = max_files * sizeof(spiffs_fd); + uint32_t work_sz = cfg.log_page_size * 2; + uint32_t cache_sz = sizeof(spiffs_cache) + max_files * (sizeof(spiffs_cache_page) + + cfg.log_page_size); + + uint8_t *work = (uint8_t*) malloc(work_sz); + uint8_t *fds = (uint8_t*) malloc(fds_sz); + uint8_t *cache = (uint8_t*) malloc(cache_sz); + + s32_t spiffs_res; + + // Special mounting procedure: mount, format, mount as per + // https://github.com/pellepl/spiffs/wiki/Using-spiffs + spiffs_res = SPIFFS_mount(&fs, &cfg, work, fds, fds_sz, + cache, cache_sz, spiffs_api_check); + REQUIRE(spiffs_res == SPIFFS_ERR_NOT_A_FS); + + spiffs_res = SPIFFS_format(&fs); + REQUIRE(spiffs_res >= SPIFFS_OK); + + spiffs_res = SPIFFS_mount(&fs, &cfg, work, fds, fds_sz, + cache, cache_sz, spiffs_api_check); + REQUIRE(spiffs_res >= SPIFFS_OK); + + // Open test file + spiffs_res = SPIFFS_open(&fs, "test.txt", SPIFFS_O_CREAT | SPIFFS_O_RDWR, 0); + REQUIRE(spiffs_res >= SPIFFS_OK); + + // Generate data + spiffs_file file = spiffs_res; + + uint32_t data_size = 100000; + + char *data = (char*) malloc(data_size); + char *read = (char*) malloc(data_size); + + for(uint32_t i = 0; i < data_size; i += sizeof(i)) + { + *((uint32_t*)(data + i)) = i; + } + + s32_t bw; + + // Write data to file + spiffs_res = SPIFFS_write(&fs, file, (void*)data, data_size); + REQUIRE(spiffs_res >= SPIFFS_OK); + REQUIRE(spiffs_res == data_size); + + // Set the file object pointer to the beginning + spiffs_res = SPIFFS_lseek(&fs, file, 0, SPIFFS_SEEK_SET); + REQUIRE(spiffs_res >= SPIFFS_OK); + + // Read the file + spiffs_res = SPIFFS_read(&fs, file, (void*)read, data_size); + REQUIRE(spiffs_res >= SPIFFS_OK); + REQUIRE(spiffs_res == data_size); + + // Close the test file + spiffs_res = SPIFFS_close(&fs, file); + REQUIRE(spiffs_res >= SPIFFS_OK); + + REQUIRE(memcmp(data, read, data_size) == 0); + + // Unmount + SPIFFS_unmount(&fs); + + free(read); + free(data); +} diff --git a/components/spiffs/test_spiffs_host/test_utils.c b/components/spiffs/test_spiffs_host/test_utils.c new file mode 100644 index 0000000000..c3181ede75 --- /dev/null +++ b/components/spiffs/test_spiffs_host/test_utils.c @@ -0,0 +1,7 @@ +#include "esp_spi_flash.h" +#include "esp_partition.h" + +void init_spi_flash(size_t chip_size, size_t block_size, size_t sector_size, size_t page_size, const char* partition_bin) +{ + spi_flash_init(chip_size, block_size, sector_size, page_size, partition_bin); +} \ No newline at end of file diff --git a/components/ulp/component_ulp_common.mk b/components/ulp/component_ulp_common.mk index 70e5b0205b..e051af0789 100644 --- a/components/ulp/component_ulp_common.mk +++ b/components/ulp/component_ulp_common.mk @@ -81,7 +81,7 @@ build: $(COMPONENT_BUILD_DIR)/$(ULP_EXPORTS_HEADER) \ $(ULP_EXP_DEP_OBJECTS) : $(ULP_EXPORTS_HEADER) $(ULP_SYM) # Finally, set all the variables processed by the build system. -COMPONENT_EXTRA_CLEAN := $(ULP_OBJECTS) \ +COMPONENT_EXTRA_CLEAN += $(ULP_OBJECTS) \ $(ULP_LD_SCRIPT) \ $(ULP_PREPROCESSED) \ $(ULP_ELF) $(ULP_BIN) \ @@ -91,6 +91,6 @@ COMPONENT_EXTRA_CLEAN := $(ULP_OBJECTS) \ $(ULP_DEP) \ $(ULP_LISTINGS) -COMPONENT_EMBED_FILES := $(COMPONENT_BUILD_DIR)/$(ULP_BIN) -COMPONENT_ADD_LDFLAGS := -l$(COMPONENT_NAME) -T $(COMPONENT_BUILD_DIR)/$(ULP_EXPORTS_LD) -COMPONENT_EXTRA_INCLUDES := $(COMPONENT_BUILD_DIR) +COMPONENT_EMBED_FILES += $(COMPONENT_BUILD_DIR)/$(ULP_BIN) +COMPONENT_ADD_LDFLAGS += -l$(COMPONENT_NAME) -T $(COMPONENT_BUILD_DIR)/$(ULP_EXPORTS_LD) +COMPONENT_EXTRA_INCLUDES += $(COMPONENT_BUILD_DIR) diff --git a/components/ulp/include/esp32/ulp.h b/components/ulp/include/esp32/ulp.h index 64bfff8c45..8acbd7120b 100644 --- a/components/ulp/include/esp32/ulp.h +++ b/components/ulp/include/esp32/ulp.h @@ -17,6 +17,7 @@ #include #include #include "esp_err.h" +#include "soc/soc.h" #ifdef __cplusplus extern "C" { @@ -860,7 +861,7 @@ esp_err_t ulp_process_macros_and_load(uint32_t load_addr, const ulp_insn_t* prog * 3. TEXT_SIZE, size of .text section (2 bytes) * 4. DATA_SIZE, size of .data section (2 bytes) * 5. BSS_SIZE, size of .bss section (2 bytes) - * 6. (TEXT_OFFSET - 16) bytes of arbitrary data (will not be loaded into RTC memory) + * 6. (TEXT_OFFSET - 12) bytes of arbitrary data (will not be loaded into RTC memory) * 7. .text section * 8. .data section * diff --git a/components/ulp/test/component.mk b/components/ulp/test/component.mk index ce464a212a..41228b2576 100644 --- a/components/ulp/test/component.mk +++ b/components/ulp/test/component.mk @@ -1 +1,11 @@ -COMPONENT_ADD_LDFLAGS = -Wl,--whole-archive -l$(COMPONENT_NAME) -Wl,--no-whole-archive +ULP_APP_NAME = ulp_test + +ULP_S_SOURCES = $(addprefix $(COMPONENT_PATH)/ulp/, \ + test_jumps.S \ + ) + +ULP_EXP_DEP_OBJECTS := test_ulp_as.o + +include $(IDF_PATH)/components/ulp/component_ulp_common.mk + +COMPONENT_ADD_LDFLAGS += -Wl,--whole-archive -l$(COMPONENT_NAME) -Wl,--no-whole-archive diff --git a/components/ulp/test/test_ulp.c b/components/ulp/test/test_ulp.c index 197a12b61b..766a71742e 100644 --- a/components/ulp/test/test_ulp.c +++ b/components/ulp/test/test_ulp.c @@ -271,7 +271,7 @@ TEST_CASE("ulp power consumption in deep sleep", "[ulp][ignore]") { assert(CONFIG_ULP_COPROC_RESERVE_MEM >= 4 && "this test needs ULP_COPROC_RESERVE_MEM option set in menuconfig"); ulp_insn_t insn = I_HALT(); - RTC_SLOW_MEM[0] = *(uint32_t*) &insn; + memcpy(&RTC_SLOW_MEM[0], &insn, sizeof(insn)); REG_WRITE(SENS_ULP_CP_SLEEP_CYC0_REG, 0x8000); diff --git a/components/ulp/test/test_ulp_as.c b/components/ulp/test/test_ulp_as.c new file mode 100644 index 0000000000..b0a080717a --- /dev/null +++ b/components/ulp/test/test_ulp_as.c @@ -0,0 +1,25 @@ +#include +#include "unity.h" +#include "soc/rtc_cntl_reg.h" +#include "esp32/ulp.h" +#include "ulp_test.h" + + +extern const uint8_t ulp_test_bin_start[] asm("_binary_ulp_test_bin_start"); +extern const uint8_t ulp_test_bin_end[] asm("_binary_ulp_test_bin_end"); + + +TEST_CASE("jumps condition", "[ulp]") +{ + esp_err_t err = ulp_load_binary(0, ulp_test_bin_start, + (ulp_test_bin_end - ulp_test_bin_start) / sizeof(uint32_t)); + TEST_ESP_OK(err); + + REG_CLR_BIT(RTC_CNTL_INT_RAW_REG, RTC_CNTL_ULP_CP_INT_RAW); + TEST_ESP_OK(ulp_run(&ulp_test_jumps - RTC_SLOW_MEM)); + usleep(10000); + + TEST_ASSERT_NOT_EQUAL(0, REG_GET_BIT(RTC_CNTL_INT_RAW_REG, RTC_CNTL_ULP_CP_INT_RAW)); + TEST_ASSERT_EQUAL(0, ulp_jumps_fail & UINT16_MAX); + TEST_ASSERT_EQUAL(1, ulp_jumps_pass & UINT16_MAX); +} diff --git a/components/ulp/test/ulp/test_jumps.S b/components/ulp/test/ulp/test_jumps.S new file mode 100644 index 0000000000..65df226037 --- /dev/null +++ b/components/ulp/test/ulp/test_jumps.S @@ -0,0 +1,101 @@ +#include "soc/rtc_cntl_reg.h" +#include "soc/rtc_io_reg.h" +#include "soc/soc_ulp.h" + + .bss + + .global jumps_pass +jumps_pass: + .long 0 + + .global jumps_fail +jumps_fail: + .long 0 + + .text + .global test_jumps +test_jumps: + + /* tests for LT (less than) condition */ + stage_rst /* cnt = 0 */ + jumps test_fail, 0, LT /* 0 < 0: false, should not jump */ + jumps 1f, 1, LT /* 0 < 1: true, should jump */ + jump test_fail +1: + stage_inc 2 /* cnt = 2 */ + jumps 1f, 3, LT /* 2 < 1: true */ + jump test_fail +1: + jumps test_fail, 1, LT /* 2 < 1: false */ + jumps test_fail, 2, LT /* 2 < 2: false */ + + /* tests for LE (less or equal) condition */ + stage_rst /* cnt = 0 */ + jumps 1f, 0, LE /* 0 <= 0: true */ + jump test_fail +1: + jumps 1f, 1, LE /* 0 <= 1: true */ + jump test_fail +1: + stage_inc 2 /* cnt = 2 */ + jumps test_fail, 1, LE /* 2 <= 1: false */ + + /* tests for EQ (equal) condition */ + stage_rst /* cnt = 0 */ + jumps 1f, 0, EQ /* 0 = 0: true */ + jump test_fail +1: + jumps test_fail, 1, EQ /* 0 = 1: false */ + + stage_inc 1 /* cnt = 1 */ + jumps test_fail, 0, EQ /* 1 = 0: false */ + jumps test_fail, 2, EQ /* 1 = 2: false */ + jumps 1f, 1, EQ /* 1 = 1: true */ +1: + + /* tests for GE (greater or equal) condition */ + stage_rst /* cnt = 0 */ + jumps 1f, 0, GE /* 0 >= 0: true */ + jump test_fail +1: + jumps test_fail, 1, GE /* 0 >= 1: false */ + + stage_inc 1 /* cnt = 1 */ + jumps 1f, 0, GE /* 1 >= 0: true */ + jump test_fail +1: + jumps 1f, 1, GE /* 1 >= 1: true */ + jump test_fail +1: + jumps test_fail, 2, GE /* 1 >= 2: false */ + + /* tests for GT (greater than) condition */ + stage_rst /* cnt = 0 */ + jumps test_fail, 0, GT /* 0 > 0: false */ + jumps test_fail, 1, GE /* 0 > 1: false */ + + stage_inc 1 /* cnt = 1 */ + jumps 1f, 0, GT /* 1 > 0: true */ + jump test_fail +1: + jumps test_fail, 1, GT /* 1 > 1: false */ + jumps test_fail, 2, GT /* 1 > 2: false */ + + jump test_pass + +test_fail: + move r0, jumps_fail + move r1, 1 + st r1, r0, 0 + jump done + +test_pass: + move r0, jumps_pass + move r1, 1 + st r1, r0, 0 + jump done + + .global done +done: + wake + halt diff --git a/components/vfs/README.rst b/components/vfs/README.rst index 36af5c388c..e7e50fd671 100644 --- a/components/vfs/README.rst +++ b/components/vfs/README.rst @@ -94,7 +94,7 @@ are the :example:`peripherals/uart_select` and the :example:`system/select` examples. If :cpp:func:`select` is used for socket file descriptors only then one can -enable the :ref:`CONFIG_USE_ONLY_LWIP_SELECT` option which can reduce the code +enable the :envvar:`CONFIG_USE_ONLY_LWIP_SELECT` option which can reduce the code size and improve performance. Paths diff --git a/components/vfs/include/esp_vfs.h b/components/vfs/include/esp_vfs.h index 61b01b76f1..4d847274b4 100644 --- a/components/vfs/include/esp_vfs.h +++ b/components/vfs/include/esp_vfs.h @@ -174,6 +174,10 @@ typedef struct int (*access_p)(void* ctx, const char *path, int amode); int (*access)(const char *path, int amode); }; + union { + int (*truncate_p)(void* ctx, const char *path, off_t length); + int (*truncate)(const char *path, off_t length); + }; /** start_select is called for setting up synchronous I/O multiplexing of the desired file descriptors in the given VFS */ esp_err_t (*start_select)(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, SemaphoreHandle_t *signal_sem); /** socket select function for socket FDs with the functionality of POSIX select(); this should be set only for the socket VFS */ diff --git a/components/vfs/test/test_vfs_fd.c b/components/vfs/test/test_vfs_fd.c index c4292d3fca..48396e6067 100644 --- a/components/vfs/test/test_vfs_fd.c +++ b/components/vfs/test/test_vfs_fd.c @@ -243,7 +243,7 @@ TEST_CASE("Open & write & close through VFS passes performance test", "[vfs]") TEST_ESP_OK( esp_vfs_register(VFS_PREF1, &desc, NULL) ); const int64_t begin = esp_timer_get_time(); - const int iter_count = 1000; + const int iter_count = 5000; for (int i = 0; i < iter_count; ++i) { const int fd = open(VFS_PREF1 FILE1, 0, 0); diff --git a/components/vfs/vfs.c b/components/vfs/vfs.c index 778db912a0..f0a195992d 100644 --- a/components/vfs/vfs.c +++ b/components/vfs/vfs.c @@ -717,6 +717,20 @@ int access(const char *path, int amode) return ret; } +int truncate(const char *path, off_t length) +{ + int ret; + const vfs_entry_t* vfs = get_vfs_for_path(path); + struct _reent* r = __getreent(); + if (vfs == NULL) { + __errno_r(r) = ENOENT; + return -1; + } + const char* path_within_vfs = translate_path(vfs, path); + CHECK_AND_CALL(ret, r, vfs, truncate, path_within_vfs, length); + return ret; +} + static void call_end_selects(int end_index, const fds_triple_t *vfs_fds_triple) { for (int i = 0; i < end_index; ++i) { diff --git a/components/vfs/vfs_uart.c b/components/vfs/vfs_uart.c index e52b5dd74f..d53de75976 100644 --- a/components/vfs/vfs_uart.c +++ b/components/vfs/vfs_uart.c @@ -335,28 +335,28 @@ static esp_err_t uart_start_select(int nfds, fd_set *readfds, fd_set *writefds, const int max_fds = MIN(nfds, UART_NUM); - taskENTER_CRITICAL(uart_get_selectlock()); + portENTER_CRITICAL(uart_get_selectlock()); if (_readfds || _writefds || _errorfds || _readfds_orig || _writefds_orig || _errorfds_orig || _signal_sem) { - taskEXIT_CRITICAL(uart_get_selectlock()); + portEXIT_CRITICAL(uart_get_selectlock()); uart_end_select(); return ESP_ERR_INVALID_STATE; } if ((_readfds_orig = malloc(sizeof(fd_set))) == NULL) { - taskEXIT_CRITICAL(uart_get_selectlock()); + portEXIT_CRITICAL(uart_get_selectlock()); uart_end_select(); return ESP_ERR_NO_MEM; } if ((_writefds_orig = malloc(sizeof(fd_set))) == NULL) { - taskEXIT_CRITICAL(uart_get_selectlock()); + portEXIT_CRITICAL(uart_get_selectlock()); uart_end_select(); return ESP_ERR_NO_MEM; } if ((_errorfds_orig = malloc(sizeof(fd_set))) == NULL) { - taskEXIT_CRITICAL(uart_get_selectlock()); + portEXIT_CRITICAL(uart_get_selectlock()); uart_end_select(); return ESP_ERR_NO_MEM; } @@ -382,7 +382,7 @@ static esp_err_t uart_start_select(int nfds, fd_set *readfds, fd_set *writefds, FD_ZERO(writefds); FD_ZERO(exceptfds); - taskEXIT_CRITICAL(uart_get_selectlock()); + portEXIT_CRITICAL(uart_get_selectlock()); // s_one_select_lock is not released on successfull exit - will be // released in uart_end_select() @@ -391,7 +391,7 @@ static esp_err_t uart_start_select(int nfds, fd_set *readfds, fd_set *writefds, static void uart_end_select() { - taskENTER_CRITICAL(uart_get_selectlock()); + portENTER_CRITICAL(uart_get_selectlock()); for (int i = 0; i < UART_NUM; ++i) { uart_set_select_notif_callback(i, NULL); } @@ -416,7 +416,7 @@ static void uart_end_select() free(_errorfds_orig); _errorfds_orig = NULL; } - taskEXIT_CRITICAL(uart_get_selectlock()); + portEXIT_CRITICAL(uart_get_selectlock()); _lock_release(&s_one_select_lock); } diff --git a/components/wear_levelling/Partition.cpp b/components/wear_levelling/Partition.cpp index 63fef6ed6b..e23f7fefd9 100644 --- a/components/wear_levelling/Partition.cpp +++ b/components/wear_levelling/Partition.cpp @@ -31,6 +31,7 @@ esp_err_t Partition::erase_sector(size_t sector) result = erase_range(sector * SPI_FLASH_SEC_SIZE, SPI_FLASH_SEC_SIZE); return result; } + esp_err_t Partition::erase_range(size_t start_address, size_t size) { esp_err_t result = esp_partition_erase_range(this->partition, start_address, size); @@ -48,6 +49,7 @@ esp_err_t Partition::write(size_t dest_addr, const void *src, size_t size) result = esp_partition_write(this->partition, dest_addr, src, size); return result; } + esp_err_t Partition::read(size_t src_addr, void *dest, size_t size) { esp_err_t result = ESP_OK; diff --git a/components/wear_levelling/doc/wl_sw_structure.rst b/components/wear_levelling/doc/wl_sw_structure.rst index ee897489ba..e1579dbf9d 100644 --- a/components/wear_levelling/doc/wl_sw_structure.rst +++ b/components/wear_levelling/doc/wl_sw_structure.rst @@ -10,10 +10,9 @@ The WLC Files ^^^^^^^^^^^^^^^ The WLC consist of few components that are implemented in different files. The list and brief description of these components written below. - - Flash_Access - memory access interface. Used to access the memory. A classes WL_Flash, Partition, SPI_Flash, Flash_Emulator are implements this interface. + - Flash_Access - memory access interface. Used to access the memory. A classes WL_Flash, Partition, SPI_Flash are implements this interface. - SPI_Flash - class implements the Flash_Access interface to provide access to the flash memory. - Partition - class implements the Flash_Access interface to provide access to the partition. - - Flash_Emulator - class implements the Flash_Access interface to provide test functionality for WLC testing. - WL_Flash - the main class that implements wear levelling functionality. - WL_State - contains state structure of the WLC. - WL_Config - contains structure to configure the WLC component at startup. diff --git a/components/wear_levelling/test_wl_host/Flash_Emulator.cpp b/components/wear_levelling/test_wl_host/Flash_Emulator.cpp deleted file mode 100644 index 5dc69a8bb4..0000000000 --- a/components/wear_levelling/test_wl_host/Flash_Emulator.cpp +++ /dev/null @@ -1,129 +0,0 @@ -// 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. - -#include "Flash_Emulator.h" - -#include -#include -#include - -Flash_Emulator::Flash_Emulator(size_t size, size_t sector_sise, size_t min_size) -{ - this->reset_count = 0x7fffffff; - this->size = size; - this->sector_sise = sector_sise; - this->min_size = min_size; - this->buff = (uint8_t *)malloc(this->size); - this->access_count = new uint32_t[this->size / this->sector_sise]; - memset(this->access_count, 0, this->size / this->sector_sise * sizeof(uint32_t)); -} - -size_t Flash_Emulator::chip_size() -{ - return this->size; -} -size_t Flash_Emulator::sector_size() -{ - return this->sector_sise; -} - -esp_err_t Flash_Emulator::erase_sector(size_t sector) -{ - esp_err_t result = ESP_OK; - if ((this->reset_count != 0x7fffffff) && (this->reset_count != 0)) { - this->reset_count--; - } - if (this->reset_count <= 0) { - result = ESP_FAIL; - return result; - } - memset(&this->buff[sector * this->sector_sise], -1, this->sector_sise); - this->access_count[sector]++; - return result; -} - -uint32_t Flash_Emulator::get_access_minmax() -{ - uint32_t min = INT32_MAX; - uint32_t max = 0; - for (size_t i = 0; i < (this->size / this->sector_sise) - 2; i++) { - if (this->access_count[i] < min) { - min = this->access_count[i]; - } - if (this->access_count[i] > max) { - max = this->access_count[i]; - } - } - return max - min; -} - -esp_err_t Flash_Emulator::erase_range(size_t start_address, size_t size) -{ - esp_err_t result = ESP_OK; - uint32_t start_sector = start_address / this->sector_sise; - uint32_t count = (size + this->sector_sise - 1) / this->sector_sise; - for (size_t i = 0; i < count; i++) { - result |= this->erase_sector(start_sector + i); - } - return result; -} - -esp_err_t Flash_Emulator::write(size_t dest_addr, const void *src, size_t size) -{ - esp_err_t result = ESP_OK; - if ((size % this->min_size) != 0) { - result = ESP_ERR_INVALID_SIZE; - return result; - } - if ((dest_addr % this->min_size) != 0) { - result = ESP_ERR_INVALID_SIZE; - return result; - } - if ((this->reset_count != 0x7fffffff) && (this->reset_count != 0)) { - this->reset_count--; - } - if (this->reset_count <= 0) { - result = ESP_FAIL; - return result; - } - memcpy(&this->buff[dest_addr], src, size); - return result; -} - -esp_err_t Flash_Emulator::read(size_t src_addr, void *dest, size_t size) -{ - esp_err_t result = ESP_OK; - if (this->reset_count <= 0) { - result = ESP_FAIL; - return result; - } - memcpy(dest, &this->buff[src_addr], size); - return result; -} - -Flash_Emulator::~Flash_Emulator() -{ - free(this->buff); - delete this->access_count; -} - -void Flash_Emulator::SetResetCount(uint32_t count) -{ - this->reset_count = count; -} - -void Flash_Emulator::SetResetSector(size_t sector) -{ - this->reset_sector = sector; -} diff --git a/components/wear_levelling/test_wl_host/Flash_Emulator.h b/components/wear_levelling/test_wl_host/Flash_Emulator.h deleted file mode 100644 index 02a1be9825..0000000000 --- a/components/wear_levelling/test_wl_host/Flash_Emulator.h +++ /dev/null @@ -1,59 +0,0 @@ -// 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. - -#ifndef _Flash_Emulator_H_ -#define _Flash_Emulator_H_ - -#include "esp_err.h" -#include "Flash_Access.h" -/** -* @brief This class is used to emulate flash devices. Class implements Flash_Access interface -* -*/ -class Flash_Emulator : public Flash_Access -{ - -public: - Flash_Emulator(size_t size, size_t sector_sise, size_t min_size); - - virtual size_t chip_size(); - - virtual esp_err_t erase_sector(size_t sector); - virtual esp_err_t erase_range(size_t start_address, size_t size); - - virtual esp_err_t write(size_t dest_addr, const void *src, size_t size); - virtual esp_err_t read(size_t src_addr, void *dest, size_t size); - - virtual size_t sector_size(); - - virtual ~Flash_Emulator(); - - uint32_t get_access_minmax(); -public: - size_t size; - size_t sector_sise; - size_t min_size; - uint8_t *buff; - - uint32_t *access_count; - -public: - uint32_t reset_count; - size_t reset_sector; - void SetResetCount(uint32_t count); - void SetResetSector(size_t sector); - -}; - -#endif // _Flash_Emulator_H_ diff --git a/components/wear_levelling/test_wl_host/Makefile b/components/wear_levelling/test_wl_host/Makefile index e71187180c..99de299423 100644 --- a/components/wear_levelling/test_wl_host/Makefile +++ b/components/wear_levelling/test_wl_host/Makefile @@ -1,55 +1,85 @@ -TEST_PROGRAM=test_wl +COMPONENT=wear_levelling + +TEST_PROGRAM=test_$(COMPONENT) + +# Expose as a library for FS components that require wear_levelling +COMPONENT_LIB=lib$(COMPONENT).a + +# Use simulated block device +SPI_FLASH=spi_flash +SPI_FLASH_DIR=../../$(SPI_FLASH) +SPI_FLASH_SIM_DIR=$(SPI_FLASH_DIR)/sim +SPI_FLASH_LIB=lib$(SPI_FLASH).a + all: $(TEST_PROGRAM) SOURCE_FILES = \ - esp_error_check_stub.cpp \ $(addprefix ../, \ - crc32.cpp \ - WL_Flash.cpp \ - ../nvs_flash/test_nvs_host/crc.cpp\ + wear_levelling.cpp \ + crc32.cpp \ + WL_Flash.cpp \ + Partition.cpp \ ) \ - Flash_Emulator.cpp \ - wl_tests_host.cpp \ - TestPowerDown.cpp \ - esp_log_stub.cpp \ - main.cpp + $(addprefix stubs/, \ + newlib/lock.c \ + log/log.c \ + esp32/crc.cpp \ + ) +TEST_SOURCE_FILES = \ + test_wl.cpp \ + main.cpp \ + test_utils.c INCLUDE_FLAGS = $(addprefix -I,\ + . \ ../ \ ../include \ ../private_include \ + $(addprefix stubs/, \ + newlib/include \ + log/include \ + ) \ + $(SPI_FLASH_DIR)/include \ ../../esp32/include \ - ../../soc/esp32/include \ - ../../log/include \ - ../../spi_flash/include \ - ../../nvs_flash/test_nvs_host \ ../../../tools/catch \ -) +) GCOV ?= gcov -CPPFLAGS += $(INCLUDE_FLAGS) -D CONFIG_LOG_DEFAULT_LEVEL +CPPFLAGS += $(INCLUDE_FLAGS) -D CONFIG_LOG_DEFAULT_LEVEL -g -m32 CFLAGS += -fprofile-arcs -ftest-coverage CXXFLAGS += -std=c++11 -Wall -Werror -fprofile-arcs -ftest-coverage LDFLAGS += -lstdc++ -fprofile-arcs -ftest-coverage -OBJ_FILES = $(SOURCE_FILES:.cpp=.o) +OBJ_FILES = $(filter %.o, $(SOURCE_FILES:.cpp=.o) $(SOURCE_FILES:.c=.o)) +TEST_OBJ_FILES = $(filter %.o, $(TEST_SOURCE_FILES:.cpp=.o) $(TEST_SOURCE_FILES:.c=.o)) -COVERAGE_FILES = $(OBJ_FILES:.o=.gc*) +$(SPI_FLASH_SIM_DIR)/$(SPI_FLASH_LIB): force + $(MAKE) -C $(SPI_FLASH_SIM_DIR) lib -$(OBJ_FILES): %.o: %.cpp +$(COMPONENT_LIB): $(OBJ_FILES) + $(AR) rcs $@ $^ -$(TEST_PROGRAM): $(OBJ_FILES) - g++ $(LDFLAGS) -o $(TEST_PROGRAM) $(OBJ_FILES) +force: -$(OUTPUT_DIR): - mkdir -p $(OUTPUT_DIR) +lib: $(COMPONENT_LIB) + +partition_table.bin: partition_table.csv + python ../../../components/partition_table/gen_esp32part.py --verify $< $@ + +$(TEST_PROGRAM): lib $(TEST_OBJ_FILES) $(SPI_FLASH_SIM_DIR)/$(SPI_FLASH_LIB) partition_table.bin + g++ $(LDFLAGS) -o $@ $(TEST_OBJ_FILES) -L$(abspath .) -l:$(COMPONENT_LIB) -L$(SPI_FLASH_SIM_DIR) -l:$(SPI_FLASH_LIB) -g -m32 test: $(TEST_PROGRAM) ./$(TEST_PROGRAM) -$(COVERAGE_FILES): $(TEST_PROGRAM) test +$(OUTPUT_DIR): + mkdir -p $(OUTPUT_DIR) + +COVERAGE_FILES = $(OBJ_FILES:.o=.gc*) $(TEST_OBJ_FILES:.o=.gc*) + +$(COVERAGE_FILES): test coverage.info: $(COVERAGE_FILES) find ../ -name "*.gcno" -exec $(GCOV) -r -pb {} + @@ -60,9 +90,10 @@ coverage_report: coverage.info @echo "Coverage report is in coverage_report/index.html" clean: - rm -f $(OBJ_FILES) $(TEST_PROGRAM) + $(MAKE) -C $(SPI_FLASH_SIM_DIR) clean + rm -f $(OBJ_FILES) $(TEST_OBJ_FILES) $(TEST_PROGRAM) $(COMPONENT_LIB) partition_table.bin rm -f $(COVERAGE_FILES) *.gcov rm -rf coverage_report/ rm -f coverage.info -.PHONY: clean all test +.PHONY: clean all test lib diff --git a/components/wear_levelling/test_wl_host/TestPowerDown.cpp b/components/wear_levelling/test_wl_host/TestPowerDown.cpp deleted file mode 100644 index 056d815a12..0000000000 --- a/components/wear_levelling/test_wl_host/TestPowerDown.cpp +++ /dev/null @@ -1,110 +0,0 @@ -// 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. - - -#include "WL_Config.h" -#include "WL_Flash.h" -#include "Flash_Emulator.h" -#ifdef _MSC_VER -#define CHECK(m) -#else -#include "catch.hpp" -#endif - -extern Flash_Access *s_flash; - -bool test_power_down(WL_Flash *wl_flash, Flash_Emulator *emul, uint32_t used_sectors_count) -{ - REQUIRE(wl_flash->init() == ESP_OK); - s_flash = wl_flash; - - uint32_t add_const = 0; - int32_t sectors_count = s_flash->chip_size() / s_flash->sector_size(); - esp_err_t err = ESP_OK; - uint32_t *sector_data = new uint32_t[s_flash->sector_size() / sizeof(uint32_t)]; - - for (int32_t i = 0; i < sectors_count; i++) { - REQUIRE(s_flash->erase_sector(i) == ESP_OK); - for (uint32_t m = 0; m < s_flash->sector_size() / sizeof(uint32_t); m++) { - uint32_t temp_data = i * s_flash->sector_size() + add_const + m; - sector_data[m] = temp_data; - } - REQUIRE(s_flash->write(i * s_flash->sector_size(), sector_data, s_flash->sector_size()) == ESP_OK); - } - for (int32_t i = 0; i < sectors_count; i++) { - err |= s_flash->read(i * s_flash->sector_size(), sector_data, s_flash->sector_size()); - for (uint32_t m = 0; m < s_flash->sector_size() / sizeof(uint32_t); m++) { - uint32_t temp_data = i * s_flash->sector_size() + add_const + m; - REQUIRE(temp_data == sector_data[m]); - if (temp_data != sector_data[m]) { - printf("Error - read: %08x, expected %08x\n", sector_data[m], temp_data); - } - } - } - - int32_t max_count = 100; - int32_t max_check_count = used_sectors_count; - printf("used_sectors_count=%d\n", used_sectors_count); - for (int32_t k = 0; k < max_check_count; k++) { - - emul->SetResetCount(max_count); - int32_t err_sector = -1; - for (int32_t i = 0; i < sectors_count; i++) { - err = ESP_OK; - err = s_flash->erase_sector(i); - if (err != ESP_OK) { - err_sector = i; - break; - } - for (uint32_t m = 0; m < s_flash->sector_size() / sizeof(uint32_t); m++) { - uint32_t temp_data = i * s_flash->sector_size() + add_const + m; - sector_data[m] = temp_data; - } - err = s_flash->write(i * s_flash->sector_size(), sector_data, s_flash->sector_size()); - if (err != ESP_OK) { - err_sector = i; - break; - } - } - if (err_sector >= 0) { - max_count++; - } else { - max_count = 0; - } - emul->SetResetCount(INT32_MAX); - REQUIRE(wl_flash->init() == ESP_OK); - for (int32_t i = 0; i < sectors_count; i++) { - if (i != err_sector) { - err |= s_flash->read(i * s_flash->sector_size(), sector_data, s_flash->sector_size()); - for (uint32_t m = 0; m < s_flash->sector_size() / sizeof(uint32_t); m++) { - uint32_t temp_data = i * s_flash->sector_size() + add_const + m; - REQUIRE(temp_data == sector_data[m]); - if (temp_data != sector_data[m]) { - printf("Error - read: %08x, expected %08x, m=%i, sector=%i\n", sector_data[m], temp_data, m, i); - } - } - } - } - if (err_sector != -1) { - err |= s_flash->erase_sector(err_sector); - for (uint32_t m = 0; m < s_flash->sector_size() / sizeof(uint32_t); m++) { - uint32_t temp_data = err_sector * s_flash->sector_size() + add_const + m; - sector_data[m] = temp_data; - } - err |= s_flash->write(err_sector * s_flash->sector_size(), sector_data, s_flash->sector_size()); - } - printf("[%3.f%%] err_sector=%i\n", (float)k / ((float)max_check_count) * 100.0f, err_sector); - } - delete[] sector_data; - return true; -} diff --git a/components/wear_levelling/test_wl_host/esp_error_check_stub.cpp b/components/wear_levelling/test_wl_host/esp_error_check_stub.cpp index 9cff4af310..1eb70e3e9f 100644 --- a/components/wear_levelling/test_wl_host/esp_error_check_stub.cpp +++ b/components/wear_levelling/test_wl_host/esp_error_check_stub.cpp @@ -1,9 +1,14 @@ #include "catch.hpp" #include "esp_err.h" +#include "sdkconfig.h" void _esp_error_check_failed(esp_err_t rc, const char *file, int line, const char *function, const char *expression) { - printf("ESP_ERROR_CHECK failed: esp_err_t 0x%x at %p\n", rc, __builtin_return_address(0)); + printf("ESP_ERROR_CHECK failed: esp_err_t 0x%x", rc); +#ifdef CONFIG_ESP_ERR_TO_NAME_LOOKUP + printf(" (%s)", esp_err_to_name(rc)); +#endif //CONFIG_ESP_ERR_TO_NAME_LOOKUP + printf(" at %p\n", __builtin_return_address(0)); printf("file: \"%s\" line %d\nfunc: %s\nexpression: %s\n", file, line, function, expression); abort(); } diff --git a/components/wear_levelling/test_wl_host/main.cpp b/components/wear_levelling/test_wl_host/main.cpp index 0c7c351f43..063e87874e 100644 --- a/components/wear_levelling/test_wl_host/main.cpp +++ b/components/wear_levelling/test_wl_host/main.cpp @@ -1,2 +1,2 @@ #define CATCH_CONFIG_MAIN -#include "catch.hpp" +#include "catch.hpp" \ No newline at end of file diff --git a/components/wear_levelling/test_wl_host/partition_table.csv b/components/wear_levelling/test_wl_host/partition_table.csv new file mode 100644 index 0000000000..cb7fccd87b --- /dev/null +++ b/components/wear_levelling/test_wl_host/partition_table.csv @@ -0,0 +1,6 @@ +# Name, Type, SubType, Offset, Size, Flags +# Note: if you change the phy_init or app partition offset, make sure to change the offset in Kconfig.projbuild +nvs, data, nvs, 0x9000, 0x6000, +phy_init, data, phy, 0xf000, 0x1000, +factory, app, factory, 0x10000, 1M, +storage, data, fat, , 1M, \ No newline at end of file diff --git a/components/wear_levelling/test_wl_host/sdkconfig.h b/components/wear_levelling/test_wl_host/sdkconfig.h index e69de29bb2..3085b06d82 100644 --- a/components/wear_levelling/test_wl_host/sdkconfig.h +++ b/components/wear_levelling/test_wl_host/sdkconfig.h @@ -0,0 +1,3 @@ +#pragma once + +#define CONFIG_WL_SECTOR_SIZE 4096 \ No newline at end of file diff --git a/components/wear_levelling/test_wl_host/stubs/esp32/crc.cpp b/components/wear_levelling/test_wl_host/stubs/esp32/crc.cpp new file mode 100644 index 0000000000..4cbb9be9ec --- /dev/null +++ b/components/wear_levelling/test_wl_host/stubs/esp32/crc.cpp @@ -0,0 +1,64 @@ +// 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" unsigned int 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/wear_levelling/test_wl_host/stubs/log/include/esp_log.h b/components/wear_levelling/test_wl_host/stubs/log/include/esp_log.h new file mode 100644 index 0000000000..a1d838d116 --- /dev/null +++ b/components/wear_levelling/test_wl_host/stubs/log/include/esp_log.h @@ -0,0 +1,44 @@ +#pragma once + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define LOG_LOCAL_LEVEL ESP_LOG_DEBUG + +typedef enum { + ESP_LOG_NONE, /*!< No log output */ + ESP_LOG_ERROR, /*!< Critical errors, software module can not recover on its own */ + ESP_LOG_WARN, /*!< Error conditions from which recovery measures have been taken */ + ESP_LOG_INFO, /*!< Information messages which describe normal flow of events */ + ESP_LOG_DEBUG, /*!< Extra information which is not necessary for normal use (values, pointers, sizes, etc). */ + ESP_LOG_VERBOSE /*!< Bigger chunks of debugging information, or frequent messages which can potentially flood the output. */ +} esp_log_level_t; + +#define LOG_COLOR_E +#define LOG_COLOR_W +#define LOG_COLOR_I +#define LOG_COLOR_D +#define LOG_COLOR_V +#define LOG_RESET_COLOR + +uint32_t esp_log_timestamp(void); +void esp_log_write(esp_log_level_t level, const char* tag, const char* format, ...) __attribute__ ((format (printf, 3, 4))); + +#define LOG_FORMAT(letter, format) LOG_COLOR_ ## letter #letter " (%d) %s: " format LOG_RESET_COLOR "\n" + +#define ESP_LOGE( tag, format, ... ) if (LOG_LOCAL_LEVEL >= ESP_LOG_ERROR) { esp_log_write(ESP_LOG_ERROR, tag, LOG_FORMAT(E, format), esp_log_timestamp(), tag, ##__VA_ARGS__); } + +#define ESP_LOGV( tag, format, ... ) if (LOG_LOCAL_LEVEL >= ESP_LOG_VERBOSE) { esp_log_write(ESP_LOG_VERBOSE, tag, LOG_FORMAT(V, format), esp_log_timestamp(), tag, ##__VA_ARGS__); } + +#define ESP_LOGD( tag, format, ... ) if (LOG_LOCAL_LEVEL >= ESP_LOG_DEBUG) { esp_log_write(ESP_LOG_DEBUG, tag, LOG_FORMAT(D, format), esp_log_timestamp(), tag, ##__VA_ARGS__); } + +#define ESP_LOGW( tag, format, ... ) if (LOG_LOCAL_LEVEL >= ESP_LOG_WARN) { esp_log_write(ESP_LOG_WARN, tag, LOG_FORMAT(W, format), esp_log_timestamp(), tag, ##__VA_ARGS__); } + +#ifdef __cplusplus +} +#endif + diff --git a/components/wear_levelling/test_wl_host/stubs/log/log.c b/components/wear_levelling/test_wl_host/stubs/log/log.c new file mode 100644 index 0000000000..0cacb3ac79 --- /dev/null +++ b/components/wear_levelling/test_wl_host/stubs/log/log.c @@ -0,0 +1,21 @@ +#include +#include +#include +#include + +#include "esp_log.h" + +void esp_log_write(esp_log_level_t level, + const char *tag, + const char *format, ...) +{ + va_list arg; + va_start(arg, format); + vprintf(format, arg); + va_end(arg); +} + +uint32_t esp_log_timestamp() +{ + return 0; +} \ No newline at end of file diff --git a/components/wear_levelling/test_wl_host/stubs/newlib/include/sys/lock.h b/components/wear_levelling/test_wl_host/stubs/newlib/include/sys/lock.h new file mode 100644 index 0000000000..b244c9127a --- /dev/null +++ b/components/wear_levelling/test_wl_host/stubs/newlib/include/sys/lock.h @@ -0,0 +1,16 @@ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +typedef int _lock_t; + +void _lock_acquire(_lock_t *lock); +void _lock_close(_lock_t *lock); +void _lock_init(_lock_t *lock); +void _lock_release(_lock_t *lock); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/components/wear_levelling/test_wl_host/stubs/newlib/lock.c b/components/wear_levelling/test_wl_host/stubs/newlib/lock.c new file mode 100644 index 0000000000..d13b6eaac3 --- /dev/null +++ b/components/wear_levelling/test_wl_host/stubs/newlib/lock.c @@ -0,0 +1,21 @@ +#include "sys/lock.h" + +void _lock_acquire(_lock_t *lock) +{ + return; +} + +void _lock_close(_lock_t *lock) +{ + return; +} + +void _lock_init(_lock_t *lock) +{ + return; +} + +void _lock_release(_lock_t *lock) +{ + return; +} \ No newline at end of file diff --git a/components/wear_levelling/test_wl_host/test_utils.c b/components/wear_levelling/test_wl_host/test_utils.c new file mode 100644 index 0000000000..c3181ede75 --- /dev/null +++ b/components/wear_levelling/test_wl_host/test_utils.c @@ -0,0 +1,7 @@ +#include "esp_spi_flash.h" +#include "esp_partition.h" + +void init_spi_flash(size_t chip_size, size_t block_size, size_t sector_size, size_t page_size, const char* partition_bin) +{ + spi_flash_init(chip_size, block_size, sector_size, page_size, partition_bin); +} \ No newline at end of file diff --git a/components/wear_levelling/test_wl_host/test_wl.cpp b/components/wear_levelling/test_wl_host/test_wl.cpp new file mode 100644 index 0000000000..4b467e9d57 --- /dev/null +++ b/components/wear_levelling/test_wl_host/test_wl.cpp @@ -0,0 +1,87 @@ +#include +#include +#include + +#include "esp_spi_flash.h" +#include "esp_partition.h" +#include "wear_levelling.h" +#include "WL_Flash.h" + +#include "catch.hpp" + +#include "sdkconfig.h" + +extern "C" void init_spi_flash(size_t chip_size, size_t block_size, size_t sector_size, size_t page_size, const char* partition_bin); + +TEST_CASE("write and read back data", "[wear_levelling]") +{ + init_spi_flash(0x00400000, CONFIG_WL_SECTOR_SIZE * 16, CONFIG_WL_SECTOR_SIZE, CONFIG_WL_SECTOR_SIZE, "partition_table.bin"); + + esp_err_t result; + wl_handle_t wl_handle; + + int flash_handle; + const esp_partition_t *partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_FAT, "storage"); + + // Mount wear-levelled partition + result = wl_mount(partition, &wl_handle); + REQUIRE(result == ESP_OK); + + // Get the sector size + uint32_t sector_size = wl_sector_size(wl_handle); + REQUIRE(sector_size == CONFIG_WL_SECTOR_SIZE); + + uint8_t* data = (uint8_t*) malloc(partition->size); + uint8_t* read = (uint8_t*) malloc(partition->size); + + uint32_t sectors = partition->size / sector_size; + + // Generate data + for(uint32_t sector = 0; sector < sectors; sector++) + { + uint32_t sector_address = sector * sector_size; + + for(uint32_t i = 0; i < sector_size / sizeof(i); i++) + { + ((uint32_t*) data)[i] = sector_address + i; + } + } + + // Write data + result = wl_write(wl_handle, 0, data, partition->size); + REQUIRE(result == ESP_OK); + + // Read data + result = wl_read(wl_handle, 0, read, partition->size); + REQUIRE(result == ESP_OK); + + // Verify that written and read data match + REQUIRE(memcmp(data, read, partition->size)); + + // Erase some ranges + result = wl_erase_range(wl_handle, 0, sector_size); + REQUIRE(result == ESP_OK); + result = wl_erase_range(wl_handle, 12288, sector_size * 2); + REQUIRE(result == ESP_OK); + result = wl_erase_range(wl_handle, 28672, sector_size * 3); + REQUIRE(result == ESP_OK); + + // Expected data after erasure + memset(data + 0, 0xFF, sector_size); + memset(data + 12288, 0xFF, sector_size * 2); + memset(data + 28672, 0xFF, sector_size * 3); + + // Read again, with erased ranges + result = wl_read(wl_handle, 0, read, partition->size); + REQUIRE(result == ESP_OK); + + // Verify that written and read data match + REQUIRE(memcmp(data, read, partition->size)); + + // Unmount + result = wl_unmount(wl_handle); + REQUIRE(result == ESP_OK); + + free(data); + free(read); +} diff --git a/components/wear_levelling/test_wl_host/wl_tests_host.cpp b/components/wear_levelling/test_wl_host/wl_tests_host.cpp deleted file mode 100644 index 84bb59fea2..0000000000 --- a/components/wear_levelling/test_wl_host/wl_tests_host.cpp +++ /dev/null @@ -1,56 +0,0 @@ -// 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. - -#include -#include "WL_Config.h" -#include "WL_Flash.h" -#include "Flash_Emulator.h" -#include "catch.hpp" - -#define FLASH_SECTOR_SIZE 512 -#define FLASH_USED_SECTOR (1024 - 3) -#define FLASH_ACCESS_SIZE (FLASH_SECTOR_SIZE*(FLASH_USED_SECTOR + 1 + 2)) -#define FLASH_START_ADDR 0x1000 -#define FLASH_PAGE_SIZE FLASH_SECTOR_SIZE*1 -#define FLASH_UPDATERATE 3 -#define FLASH_TEMP_SIZE FLASH_SECTOR_SIZE -#define FLASH_WR_BLOCK_SIZE 16 - -static const char *TAG = "wl_test_host"; -Flash_Access *s_flash; - -extern bool test_power_down(WL_Flash *wl_flash, Flash_Emulator *emul, uint32_t used_sectors_count); - -#define TEST_COUNT_MAX 100 - -TEST_CASE("flash starts with all bytes == 0xff", "[spi_flash_emu]") -{ - wl_config_t *wl = new wl_config_t(); - - wl->full_mem_size = FLASH_ACCESS_SIZE; - wl->start_addr = FLASH_START_ADDR; - wl->sector_size = FLASH_SECTOR_SIZE; - wl->page_size = FLASH_PAGE_SIZE; - wl->updaterate = FLASH_UPDATERATE; - wl->temp_buff_size = FLASH_TEMP_SIZE; - wl->wr_size = FLASH_WR_BLOCK_SIZE; - - WL_Flash *wl_flash = new WL_Flash(); - Flash_Emulator *emul = new Flash_Emulator(FLASH_ACCESS_SIZE + FLASH_START_ADDR, FLASH_SECTOR_SIZE, FLASH_WR_BLOCK_SIZE); - CHECK(wl_flash->config(wl, emul) == ESP_OK); - - test_power_down(wl_flash, emul, TEST_COUNT_MAX); -} - - diff --git a/components/wpa_supplicant/component.mk b/components/wpa_supplicant/component.mk index d2120dbc39..ae73ccf126 100644 --- a/components/wpa_supplicant/component.mk +++ b/components/wpa_supplicant/component.mk @@ -1,4 +1,4 @@ -COMPONENT_ADD_INCLUDEDIRS := include port/include ../esp32/include +COMPONENT_ADD_INCLUDEDIRS := include port/include COMPONENT_SRCDIRS := src/crypto port src/fast_crypto src/wpa2/eap_peer src/wpa2/tls src/wpa2/utils src/wps CFLAGS += -DEMBEDDED_SUPP -DIEEE8021X_EAPOL -DEAP_PEER_METHOD -DEAP_MSCHAPv2 -DEAP_TTLS -DEAP_TLS -DEAP_PEAP -DUSE_WPA2_TASK -DCONFIG_WPS2 -DCONFIG_WPS_PIN -DUSE_WPS_TASK -DESPRESSIF_USE -DESP32_WORKAROUND -D__ets__ -Wno-strict-aliasing diff --git a/components/wpa_supplicant/include/wpa2/eap_peer/eap_methods.h b/components/wpa_supplicant/include/wpa2/eap_peer/eap_methods.h index 253b2d8a17..7d518dec2c 100644 --- a/components/wpa_supplicant/include/wpa2/eap_peer/eap_methods.h +++ b/components/wpa_supplicant/include/wpa2/eap_peer/eap_methods.h @@ -33,4 +33,7 @@ int eap_peer_peap_register(void); int eap_peer_ttls_register(void); int eap_peer_mschapv2_register(void); +void eap_peer_unregister_methods(void); +int eap_peer_register_methods(void); + #endif /* EAP_METHODS_H */ diff --git a/components/wpa_supplicant/src/wpa2/eap_peer/eap.c b/components/wpa_supplicant/src/wpa2/eap_peer/eap.c index d492831fd6..865da65470 100644 --- a/components/wpa_supplicant/src/wpa2/eap_peer/eap.c +++ b/components/wpa_supplicant/src/wpa2/eap_peer/eap.c @@ -305,7 +305,7 @@ struct wpabuf * eap_sm_build_nak(struct eap_sm *sm, EapType type, u8 id) wpabuf_put_be24(resp, m->vendor); wpabuf_put_be32(resp, m->method); } else - wpabuf_put_u8(resp, EAP_TYPE_NONE); + wpabuf_put_u8(resp, m->method); found++; } if (!found) { diff --git a/components/wpa_supplicant/src/wpa2/tls/x509v3.c b/components/wpa_supplicant/src/wpa2/tls/x509v3.c index f7962db81c..66a0e448e6 100644 --- a/components/wpa_supplicant/src/wpa2/tls/x509v3.c +++ b/components/wpa_supplicant/src/wpa2/tls/x509v3.c @@ -494,20 +494,28 @@ static char * x509_name_attr_str(enum x509_name_attr_type type) switch (type) { case X509_NAME_ATTR_NOT_USED: strcpy(name_attr, "[N/A]"); + break; case X509_NAME_ATTR_DC: strcpy(name_attr, "DC"); + break; case X509_NAME_ATTR_CN: strcpy(name_attr, "CN"); + break; case X509_NAME_ATTR_C: strcpy(name_attr, "C"); + break; case X509_NAME_ATTR_L: strcpy(name_attr, "L"); + break; case X509_NAME_ATTR_ST: strcpy(name_attr, "ST"); + break; case X509_NAME_ATTR_O: strcpy(name_attr, "O"); + break; case X509_NAME_ATTR_OU: strcpy(name_attr, "OU"); + break; default : strcpy(name_attr, "?"); } diff --git a/docs/Doxyfile b/docs/Doxyfile index 98c698275a..fe1ba03f41 100644 --- a/docs/Doxyfile +++ b/docs/Doxyfile @@ -142,6 +142,8 @@ INPUT = \ ../../components/esp32/include/esp_ipc.h \ ## Over The Air Updates (OTA) ../../components/app_update/include/esp_ota_ops.h \ + ## ESP HTTPS OTA + ../../components/esp_https_ota/include/esp_https_ota.h \ ## Sleep ## NOTE: for line below header_file.inc is not used ../../components/esp32/include/esp_sleep.h \ @@ -174,7 +176,9 @@ INPUT = \ ../../components/freertos/include/freertos/semphr.h \ ../../components/freertos/include/freertos/timers.h \ ../../components/freertos/include/freertos/event_groups.h \ - ../../components/freertos/include/freertos/ringbuf.h + ../../components/freertos/include/freertos/ringbuf.h \ + ### Helper functions for error codes + ../../components/esp32/include/esp_err.h diff --git a/docs/README.md b/docs/README.md index f240d9ebb4..9119ff1628 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,18 +1,16 @@ # Documentation Source Folder -This folder contains source files of **ESP-IDF documentation** available in [English](https://esp-idf.readthedocs.io/en/latest/) and [中文](https://esp-idf.readthedocs.io/zh_CN/latest/). +This folder contains source files of **ESP-IDF documentation** available in [English](https://docs.espressif.com/projects/esp-idf/en/latest/) and [中文](https://docs.espressif.com/projects/esp-idf/zh_CN/latest/). The sources do not render well in GitHub and some information is not visible at all. Use actual documentation generated within about 20 minutes on each commit: -## English +# Hosted Documentation -* Main server: https://esp-idf.readthedocs.io/en/latest/ or http://esp-idf.readthedocs.io/en/latest/ -* Mirror: https://espressif-docs.readthedocs-hosted.com/projects/esp-idf/en/latest/ -* Latest docs mirror: https://dl.espressif.com/doc/esp-idf/latest/ +* English: https://docs.espressif.com/projects/esp-idf/en/latest/ +* 中文: https://docs.espressif.com/projects/esp-idf/zh_CN/latest/ + +The above URLs are all for the master branch latest version. Click the drop-down in the bottom left to choose a stable version or to download a PDF. -## 中文 -* Main server: https://esp-idf.readthedocs.io/zh_CN/latest/ or http://esp-idf.readthedocs.io/zh_CN/latest/ -* Mirror: https://espressif-docs.readthedocs-hosted.com/projects/esp-idf/zh_CN/latest/ diff --git a/docs/_static/diagrams/spi_master/miso_timing_waveform.rst b/docs/_static/diagrams/spi_master/miso_timing_waveform.rst new file mode 100644 index 0000000000..ec11ea1ff8 --- /dev/null +++ b/docs/_static/diagrams/spi_master/miso_timing_waveform.rst @@ -0,0 +1,17 @@ +.. this picture is generated by https://wavedrom.com/, using the sphinx plugin sphinxcontrib-wavedrom +.. due to plugin issue, we cannot place only the picture information in a standalone file, but have to take .. wavedrom:: inside + +.. wavedrom:: + + { signal: [ + { name: 'SCLK', wave: 'p...', node: '.ad...' }, + { name: 'MISO', wave: 'x3x.', node: '.b...', phase:-1.8 }, + { name: 'MISO delayed', wave: 'x3x.', node: '.c.', phase:-2.4 }, + ], + edge: [ + 'a|->b input delay', + 'b|->c gpio delay', + 'c-|>d setup slack' + ], + config: { hscale: 3 } + } diff --git a/docs/_static/diagrams/spi_master/miso_timing_waveform_async.rst b/docs/_static/diagrams/spi_master/miso_timing_waveform_async.rst new file mode 100644 index 0000000000..dd3ae8b1ef --- /dev/null +++ b/docs/_static/diagrams/spi_master/miso_timing_waveform_async.rst @@ -0,0 +1,19 @@ +.. this picture is generated by https://wavedrom.com/, using the sphinx plugin sphinxcontrib-wavedrom +.. due to plugin issue, we cannot place only the picture information in a standalone file, but have to take .. wavedrom:: inside + +.. wavedrom:: + + { signal: [ + { name: 'SCLK', wave: '0.1....0....1...', node: '..a.........e'}, + { name: 'SLV_CLK',wave: 'p..............', node: '..b..', phase: -0.5 }, + { name: 'MISO', wave: 'x...3.....x....', node: '....c', phase:-0.5}, + { name: 'MISO delayed', wave: 'x.......3.....x.', node: '........d'}, + ], + edge: [ + 'a|->b sample delay', + 'b|->c slave output delay', + 'c|->d gpio delay', + 'd-|>e setup slack', + 'a-|>c input delay' + ], + } diff --git a/docs/_static/diagrams/spi_master/spi_master_freq_tv.plt b/docs/_static/diagrams/spi_master/spi_master_freq_tv.plt new file mode 100644 index 0000000000..b96d3d4e8d --- /dev/null +++ b/docs/_static/diagrams/spi_master/spi_master_freq_tv.plt @@ -0,0 +1,33 @@ +# this is a GNUPLOT script generating the figure of spi_master_freq_tv.png + +set xlabel "Input delay (ns)" +set xrange [0: 125] +set ylabel "Fmax (MHz)" +set yrange [0: 81] +set xtics 12.5 textcolor rgb "black" +set ytics 10 textcolor rgb "black" +set border 3 lc rgb "gray" lw 2 +set grid lt -1 lc rgb "gray" lw 2 +set samples 10000 +set terminal png size 700,500 +set output "plot.png" + +apb = 12.5 + +#each line is broken into 10 pieces by the range determined by i +f1(i,x) = (x>= i*apb) && (x < (i+1)*apb) ? 80./(i+1) : 1/0 + +set style circle radius graph 0.008 + +#solid and empty circles are draw by the coordinates given in the csv +plot [0:125]\ + f1(-1, x) lw 3lc rgb "blue" title "IOMUX",\ + for [i=0:9] f1(i, x) with lines lw 3 lc rgb "blue" notitle,\ + f1(0, x+25) lw 3 lc rgb "red" title "GPIO",\ + for [i=2:11] f1(i, x+25) with lines lw 3 lc rgb "red" notitle, \ + "tv.csv" using 1:2 with circles notitle fill solid fc rgb "blue", \ + "tv.csv" using 1:4 with circles notitle fc rgb "blue",\ + "tv.csv" using 1:3 with circles notitle fill solid fc rgb "red" ,\ + "tv.csv" using 1:5 with circles notitle fc rgb "red" + + diff --git a/docs/_static/diagrams/spi_master/spi_timing.pptx b/docs/_static/diagrams/spi_master/spi_timing.pptx new file mode 100644 index 0000000000..2f6666cfa5 Binary files /dev/null and b/docs/_static/diagrams/spi_master/spi_timing.pptx differ diff --git a/docs/_static/diagrams/spi_master/tv.csv b/docs/_static/diagrams/spi_master/tv.csv new file mode 100644 index 0000000000..c17ad61203 --- /dev/null +++ b/docs/_static/diagrams/spi_master/tv.csv @@ -0,0 +1,29 @@ +0 80 26.66666667 #DIV/0! #DIV/0! +12.5 40 20 80 26.66666667 +25 26.66666667 16 40 20 +37.5 20 13.33333333 26.66666667 16 +50 16 11.42857143 20 13.33333333 +62.5 13.33333333 10 16 11.42857143 +75 11.42857143 8.888888889 13.33333333 10 +87.5 10 8 11.42857143 8.888888889 +100 8.888888889 7.272727273 10 8 +112.5 8 6.666666667 8.888888889 7.272727273 +125 7.272727273 6.153846154 8 6.666666667 +137.5 6.666666667 5.714285714 7.272727273 6.153846154 +150 6.153846154 5.333333333 6.666666667 5.714285714 +162.5 5.714285714 5 6.153846154 5.333333333 +175 5.333333333 4.705882353 5.714285714 5 +187.5 5 4.444444444 5.333333333 4.705882353 +200 4.705882353 4.210526316 5 4.444444444 +212.5 4.444444444 4 4.705882353 4.210526316 +225 4.210526316 3.80952381 4.444444444 4 +237.5 4 3.636363636 4.210526316 3.80952381 +250 3.80952381 3.47826087 4 3.636363636 +262.5 3.636363636 3.333333333 3.80952381 3.47826087 +275 3.47826087 3.2 3.636363636 3.333333333 +287.5 3.333333333 3.076923077 3.47826087 3.2 +300 3.2 2.962962963 3.333333333 3.076923077 +312.5 3.076923077 2.857142857 3.2 2.962962963 +325 2.962962963 2.75862069 3.076923077 2.857142857 +337.5 2.857142857 2.666666667 2.962962963 2.75862069 +350 2.75862069 2.580645161 2.857142857 2.666666667 diff --git a/docs/_static/hw-debugging-startup-tab.jpg b/docs/_static/hw-debugging-startup-tab.jpg index 667d672f39..bad2d59383 100644 Binary files a/docs/_static/hw-debugging-startup-tab.jpg and b/docs/_static/hw-debugging-startup-tab.jpg differ diff --git a/docs/_static/miso_timing_waveform.png b/docs/_static/miso_timing_waveform.png new file mode 100644 index 0000000000..19cc223bc0 Binary files /dev/null and b/docs/_static/miso_timing_waveform.png differ diff --git a/docs/_static/miso_timing_waveform_async.png b/docs/_static/miso_timing_waveform_async.png new file mode 100644 index 0000000000..4cf84e2daf Binary files /dev/null and b/docs/_static/miso_timing_waveform_async.png differ diff --git a/docs/_static/spi_master_freq_tv.png b/docs/_static/spi_master_freq_tv.png new file mode 100644 index 0000000000..d8d888d7f1 Binary files /dev/null and b/docs/_static/spi_master_freq_tv.png differ diff --git a/docs/_static/spi_miso.png b/docs/_static/spi_miso.png new file mode 100644 index 0000000000..4580938ff1 Binary files /dev/null and b/docs/_static/spi_miso.png differ diff --git a/docs/_static/what-you-need-cmake.png b/docs/_static/what-you-need-cmake.png index b98d2bbfd2..d088be0850 100644 Binary files a/docs/_static/what-you-need-cmake.png and b/docs/_static/what-you-need-cmake.png differ diff --git a/docs/conf_common.py b/docs/conf_common.py index be7b86ffd1..843943e2d0 100644 --- a/docs/conf_common.py +++ b/docs/conf_common.py @@ -32,13 +32,16 @@ if 'BUILDDIR' in os.environ: # Call Doxygen to get XML files from the header files print("Calling Doxygen to generate latest XML files") -os.system("doxygen ../Doxyfile") +if os.system("doxygen ../Doxyfile") != 0: + raise RuntimeError('Doxygen call failed') + # Doxygen has generated XML files in 'xml' directory. # Copy them to 'xml_in', only touching the files which have changed. copy_if_modified('xml/', 'xml_in/') # Generate 'api_name.inc' files using the XML files by Doxygen -os.system('python ../gen-dxd.py') +if os.system('python ../gen-dxd.py') != 0: + raise RuntimeError('gen-dxd.py failed') # Generate 'kconfig.inc' file from components' Kconfig files print("Generating kconfig.inc from kconfig contents") @@ -53,9 +56,27 @@ confgen_args = ["python", "--create-config-if-missing", "--env", "COMPONENT_KCONFIGS={}".format(kconfigs), "--env", "COMPONENT_KCONFIGS_PROJBUILD={}".format(kconfig_projbuilds), - "--output", "docs", kconfig_inc_path + "--output", "docs", kconfig_inc_path + '.in' ] subprocess.check_call(confgen_args) +copy_if_modified(kconfig_inc_path + '.in', kconfig_inc_path) + +# Generate 'esp_err_defs.inc' file with ESP_ERR_ error code definitions +esp_err_inc_path = '{}/inc/esp_err_defs.inc'.format(builddir) +if os.system('python ../../tools/gen_esp_err_to_name.py --rst_output ' + esp_err_inc_path + '.in') != 0: + raise RuntimeError('gen_esp_err_to_name.py failed') +copy_if_modified(esp_err_inc_path + '.in', esp_err_inc_path) + +# Generate version-related includes +# +# (Note: this is in a function as it needs to access configuration to get the language) +def generate_version_specific_includes(app): + print("Generating version-specific includes...") + version_tmpdir = '{}/version_inc'.format(builddir) + if os.system('python ../gen-version-specific-includes.py {} {}'.format(app.config.language, version_tmpdir)): + raise RuntimeError('gen-version-specific-includes.py failed') + copy_if_modified(version_tmpdir, '{}/inc'.format(builddir)) + # http://stackoverflow.com/questions/12772927/specifying-an-online-image-in-sphinx-restructuredtext-format # @@ -344,3 +365,4 @@ if not on_rtd: # only import and set the theme if we're building docs locally # https://github.com/rtfd/sphinx_rtd_theme/pull/432 def setup(app): app.add_stylesheet('theme_overrides.css') + generate_version_specific_includes(app) diff --git a/docs/docs_common.mk b/docs/docs_common.mk new file mode 100644 index 0000000000..85056dc394 --- /dev/null +++ b/docs/docs_common.mk @@ -0,0 +1,213 @@ +# "Common" Makefile for Sphinx documentation +# +# (included from en/Makefile & zh_CN/Makefile +# +# NOTE: This makefile runs with cwd=either en or zh_CN subfolder, so this +# (docs/) directory is '..' relative to it. + +# ************ IMPORTANT ***************** +# +# ReadTheDocs DOES NOT USE THIS MAKEFILE, +# so any behaviour additions must be +# done via Sphinx Config not here +# +# **************************************** + +# You can set these variables from the command line. +SPHINXOPTS = +SPHINXBUILD = sphinx-build +PAPER = +BUILDDIR = _build + +# User-friendly check for sphinx-build +ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1) +$(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don\'t have Sphinx installed, grab it from http://sphinx-doc.org/) +endif + +# Internal variables. +PAPEROPT_a4 = -D latex_paper_size=a4 +PAPEROPT_letter = -D latex_paper_size=letter +ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) -w sphinx-warning-log.txt . +# the i18n builder cannot share the environment and doctrees with the others +I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . + +.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext dependencies version-specific-includes + +help: + @echo "Please use \`make \' where is one of" + @echo " html to make standalone HTML files" + @echo " dirhtml to make HTML files named index.html in directories" + @echo " singlehtml to make a single large HTML file" + @echo " pickle to make pickle files" + @echo " json to make JSON files" + @echo " htmlhelp to make HTML files and a HTML help project" + @echo " qthelp to make HTML files and a qthelp project" + @echo " devhelp to make HTML files and a Devhelp project" + @echo " epub to make an epub" + @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" + @echo " latexpdf to make LaTeX files and run them through pdflatex" + @echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx" + @echo " text to make text files" + @echo " man to make manual pages" + @echo " texinfo to make Texinfo files" + @echo " info to make Texinfo files and run them through makeinfo" + @echo " gettext to make PO message catalogs" + @echo " changes to make an overview of all changed/added/deprecated items" + @echo " xml to make Docutils-native XML files" + @echo " pseudoxml to make pseudoxml-XML files for display purposes" + @echo " linkcheck to check all external links for integrity" + @echo " doctest to run all doctests embedded in the documentation (if enabled) " + +clean: + rm -rf $(BUILDDIR)/* + +html: + $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." + +dirhtml: + $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." + +singlehtml: + $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml + @echo + @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." + +pickle: + $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle + @echo + @echo "Build finished; now you can process the pickle files." + +json: + $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json + @echo + @echo "Build finished; now you can process the JSON files." + +htmlhelp: + $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp + @echo + @echo "Build finished; now you can run HTML Help Workshop with the" \ + ".hhp project file in $(BUILDDIR)/htmlhelp." + +qthelp: + $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp + @echo + @echo "Build finished; now you can run "qcollectiongenerator" with the" \ + ".qhcp project file in $(BUILDDIR)/qthelp, like this:" + @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/ReadtheDocsTemplate.qhcp" + @echo "To view the help file:" + @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/ReadtheDocsTemplate.qhc" + +devhelp: + $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp + @echo + @echo "Build finished." + @echo "To view the help file:" + @echo "# mkdir -p $$HOME/.local/share/devhelp/ReadtheDocsTemplate" + @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/ReadtheDocsTemplate" + @echo "# devhelp" + +epub: + $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub + @echo + @echo "Build finished. The epub file is in $(BUILDDIR)/epub." + +latex: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo + @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." + @echo "Run \`make' in that directory to run these through (pdf)latex" \ + "(use \`make latexpdf' here to do that automatically)." + +latexpdf: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo "Running LaTeX files through pdflatex..." + $(MAKE) -C $(BUILDDIR)/latex all-pdf + @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." + +latexpdfja: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo "Running LaTeX files through platex and dvipdfmx..." + $(MAKE) -C $(BUILDDIR)/latex all-pdf-ja + @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." + +text: + $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text + @echo + @echo "Build finished. The text files are in $(BUILDDIR)/text." + +man: + $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man + @echo + @echo "Build finished. The manual pages are in $(BUILDDIR)/man." + +texinfo: + $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo + @echo + @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." + @echo "Run \`make' in that directory to run these through makeinfo" \ + "(use \`make info' here to do that automatically)." + +info: + $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo + @echo "Running Texinfo files through makeinfo..." + make -C $(BUILDDIR)/texinfo info + @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." + +gettext: + $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale + @echo + @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." + +changes: + $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes + @echo + @echo "The overview file is in $(BUILDDIR)/changes." + +linkcheck: + $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck + @echo + @echo "Link check complete; look for any errors in the above output " \ + "or in $(BUILDDIR)/linkcheck/output.txt." + +gh-linkcheck: + @echo "Checking for hardcoded GitHub links" + @if (find ../ -name '*.rst' | xargs grep \ + 'https://github.com/espressif/esp-idf/tree\|https://github.com/espressif/esp-idf/blob\|https://github.com/espressif/esp-idf/raw'\ + ); \ + then \ + echo "WARNINIG: Some .rst files contain hardcoded Github links."; \ + echo "Please check above output and replace links with one of the following:"; \ + echo "- :idf:\`dir\` - points to directory inside ESP-IDF"; \ + echo "- :idf_file:\`file\` - points to file inside ESP-IDF"; \ + echo "- :idf_raw:\`file\` - points to raw view of the file inside ESP-IDF"; \ + echo "- :component:\`dir\` - points to directory inside ESP-IDF components dir"; \ + echo "- :component_file:\`file\` - points to file inside ESP-IDF components dir"; \ + echo "- :component_raw:\`file\` - points to raw view of the file inside ESP-IDF"; \ + echo " components dir"; \ + echo "- :example:\`dir\` - points to directory inside ESP-IDF examples dir"; \ + echo "- :example_file:\`file\` - points to file inside ESP-IDF examples dir"; \ + echo "- :example_raw:\`file\` - points to raw view of the file inside ESP-IDF"; \ + echo " examples dir"; \ + echo "These link types will point to the correct GitHub version automatically"; \ + exit 1; \ + fi + @echo "No hardcoded links found" + +doctest: + $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest + @echo "Testing of doctests in the sources finished, look at the " \ + "results in $(BUILDDIR)/doctest/output.txt." + +xml: + $(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml + @echo + @echo "Build finished. The XML files are in $(BUILDDIR)/xml." + +pseudoxml: + $(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml + @echo + @echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml." diff --git a/docs/en/Makefile b/docs/en/Makefile index cc32abbd51..281b720196 100644 --- a/docs/en/Makefile +++ b/docs/en/Makefile @@ -1,201 +1,2 @@ -# Makefile for Sphinx documentation -# - -# You can set these variables from the command line. -SPHINXOPTS = -SPHINXBUILD = sphinx-build -PAPER = -BUILDDIR = _build - -# User-friendly check for sphinx-build -ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1) -$(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/) -endif - -# Internal variables. -PAPEROPT_a4 = -D latex_paper_size=a4 -PAPEROPT_letter = -D latex_paper_size=letter -ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) -w sphinx-warning-log.txt . -# the i18n builder cannot share the environment and doctrees with the others -I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . - -.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext - -help: - @echo "Please use \`make ' where is one of" - @echo " html to make standalone HTML files" - @echo " dirhtml to make HTML files named index.html in directories" - @echo " singlehtml to make a single large HTML file" - @echo " pickle to make pickle files" - @echo " json to make JSON files" - @echo " htmlhelp to make HTML files and a HTML help project" - @echo " qthelp to make HTML files and a qthelp project" - @echo " devhelp to make HTML files and a Devhelp project" - @echo " epub to make an epub" - @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" - @echo " latexpdf to make LaTeX files and run them through pdflatex" - @echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx" - @echo " text to make text files" - @echo " man to make manual pages" - @echo " texinfo to make Texinfo files" - @echo " info to make Texinfo files and run them through makeinfo" - @echo " gettext to make PO message catalogs" - @echo " changes to make an overview of all changed/added/deprecated items" - @echo " xml to make Docutils-native XML files" - @echo " pseudoxml to make pseudoxml-XML files for display purposes" - @echo " linkcheck to check all external links for integrity" - @echo " doctest to run all doctests embedded in the documentation (if enabled)" - -clean: - rm -rf $(BUILDDIR)/* - -html: - $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html - @echo - @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." - -dirhtml: - $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml - @echo - @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." - -singlehtml: - $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml - @echo - @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." - -pickle: - $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle - @echo - @echo "Build finished; now you can process the pickle files." - -json: - $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json - @echo - @echo "Build finished; now you can process the JSON files." - -htmlhelp: - $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp - @echo - @echo "Build finished; now you can run HTML Help Workshop with the" \ - ".hhp project file in $(BUILDDIR)/htmlhelp." - -qthelp: - $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp - @echo - @echo "Build finished; now you can run "qcollectiongenerator" with the" \ - ".qhcp project file in $(BUILDDIR)/qthelp, like this:" - @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/ReadtheDocsTemplate.qhcp" - @echo "To view the help file:" - @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/ReadtheDocsTemplate.qhc" - -devhelp: - $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp - @echo - @echo "Build finished." - @echo "To view the help file:" - @echo "# mkdir -p $$HOME/.local/share/devhelp/ReadtheDocsTemplate" - @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/ReadtheDocsTemplate" - @echo "# devhelp" - -epub: - $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub - @echo - @echo "Build finished. The epub file is in $(BUILDDIR)/epub." - -latex: - $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex - @echo - @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." - @echo "Run \`make' in that directory to run these through (pdf)latex" \ - "(use \`make latexpdf' here to do that automatically)." - -latexpdf: - $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex - @echo "Running LaTeX files through pdflatex..." - $(MAKE) -C $(BUILDDIR)/latex all-pdf - @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." - -latexpdfja: - $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex - @echo "Running LaTeX files through platex and dvipdfmx..." - $(MAKE) -C $(BUILDDIR)/latex all-pdf-ja - @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." - -text: - $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text - @echo - @echo "Build finished. The text files are in $(BUILDDIR)/text." - -man: - $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man - @echo - @echo "Build finished. The manual pages are in $(BUILDDIR)/man." - -texinfo: - $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo - @echo - @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." - @echo "Run \`make' in that directory to run these through makeinfo" \ - "(use \`make info' here to do that automatically)." - -info: - $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo - @echo "Running Texinfo files through makeinfo..." - make -C $(BUILDDIR)/texinfo info - @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." - -gettext: - $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale - @echo - @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." - -changes: - $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes - @echo - @echo "The overview file is in $(BUILDDIR)/changes." - -linkcheck: - $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck - @echo - @echo "Link check complete; look for any errors in the above output " \ - "or in $(BUILDDIR)/linkcheck/output.txt." - -gh-linkcheck: - @echo "Checking for hardcoded GitHub links" - @if (find ../ -name '*.rst' | xargs grep \ - 'https://github.com/espressif/esp-idf/tree\|https://github.com/espressif/esp-idf/blob\|https://github.com/espressif/esp-idf/raw'\ - ); \ - then \ - echo "WARNINIG: Some .rst files contain hardcoded Github links."; \ - echo "Please check above output and replace links with one of the following:"; \ - echo "- :idf:\`dir\` - points to directory inside ESP-IDF"; \ - echo "- :idf_file:\`file\` - points to file inside ESP-IDF"; \ - echo "- :idf_raw:\`file\` - points to raw view of the file inside ESP-IDF"; \ - echo "- :component:\`dir\` - points to directory inside ESP-IDF components dir"; \ - echo "- :component_file:\`file\` - points to file inside ESP-IDF components dir"; \ - echo "- :component_raw:\`file\` - points to raw view of the file inside ESP-IDF"; \ - echo " components dir"; \ - echo "- :example:\`dir\` - points to directory inside ESP-IDF examples dir"; \ - echo "- :example_file:\`file\` - points to file inside ESP-IDF examples dir"; \ - echo "- :example_raw:\`file\` - points to raw view of the file inside ESP-IDF"; \ - echo " examples dir"; \ - echo "These link types will point to the correct GitHub version automatically"; \ - exit 1; \ - fi - @echo "No hardcoded links found" - -doctest: - $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest - @echo "Testing of doctests in the sources finished, look at the " \ - "results in $(BUILDDIR)/doctest/output.txt." - -xml: - $(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml - @echo - @echo "Build finished. The XML files are in $(BUILDDIR)/xml." - -pseudoxml: - $(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml - @echo - @echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml." +LANGUAGE=en +include ../docs_common.mk diff --git a/docs/en/api-guides/app_trace.rst b/docs/en/api-guides/app_trace.rst index 53ff5b2958..68f8c74c42 100644 --- a/docs/en/api-guides/app_trace.rst +++ b/docs/en/api-guides/app_trace.rst @@ -30,7 +30,7 @@ The library supports two modes of operation: **Post-mortem mode**. This is the default mode. The mode does not need interaction from the host side. In this mode tracing module does not check whether host has read all the data from *HW UP BUFFER* buffer and overwrites old data with the new ones. This mode is useful when only the latest trace data are interesting to the user, e.g. for analyzing program's behaviour just before the crash. Host can read the data later on upon user request, e.g. via special OpenOCD command in case of working via JTAG interface. -**Streaming mode.** Tracing module enters this mode when host connects to ESP32. In this mode before writing new data to *HW UP BUFFER* tracing module checks that there is enough space in it and if necessary waits for the host to read data and free enough memory. Maximum waiting time is controled via timeout values passed by users to corresponding API routines. So when application tries to write data to trace buffer using finite value of the maximum waiting time it is possible situation that this data will be dropped. Especially this is true for tracing from time critical code (ISRs, OS scheduler code etc.) when infinite timeouts can lead to system malfunction. In order to avoid loss of such critical data developers can enable additional data buffering via menuconfig option :ref:`CONFIG_ESP32_APPTRACE_PENDING_DATA_SIZE_MAX`. This macro specifies the size of data which can be buffered in above conditions. The option can also help to overcome situation when data transfer to the host is temporarily slowed down, e.g due to USB bus congestions etc. But it will not help when average bitrate of trace data stream exceeds HW interface capabilities. +**Streaming mode.** Tracing module enters this mode when host connects to ESP32. In this mode before writing new data to *HW UP BUFFER* tracing module checks that there is enough space in it and if necessary waits for the host to read data and free enough memory. Maximum waiting time is controled via timeout values passed by users to corresponding API routines. So when application tries to write data to trace buffer using finite value of the maximum waiting time it is possible situation that this data will be dropped. Especially this is true for tracing from time critical code (ISRs, OS scheduler code etc.) when infinite timeouts can lead to system malfunction. In order to avoid loss of such critical data developers can enable additional data buffering via menuconfig option :envvar:`CONFIG_ESP32_APPTRACE_PENDING_DATA_SIZE_MAX`. This macro specifies the size of data which can be buffered in above conditions. The option can also help to overcome situation when data transfer to the host is temporarily slowed down, e.g due to USB bus congestions etc. But it will not help when average bitrate of trace data stream exceeds HW interface capabilities. Configuration Options and Dependencies @@ -47,8 +47,8 @@ Using of this feature depends on two components: There are two additional menuconfig options not mentioned above: -1. *Threshold for flushing last trace data to host on panic* (:ref:`CONFIG_ESP32_APPTRACE_POSTMORTEM_FLUSH_TRAX_THRESH`). This option is necessary due to the nature of working over JTAG. In that mode trace data are exposed to the host in 16KB blocks. In post-mortem mode when one block is filled it is exposed to the host and the previous one becomes unavailable. In other words trace data are overwritten in 16KB granularity. On panic the latest data from the current input block are exposed to host and host can read them for post-analysis. It can happen that system panic occurs when there are very small amount of data which are not exposed to the host yet. In this case the previous 16KB of collected data will be lost and host will see the latest, but very small piece of the trace. It can be insufficient to diagnose the problem. This menuconfig option allows avoiding such situations. It controls the threshold for flushing data in case of panic. For example user can decide that it needs not less then 512 bytes of the recent trace data, so if there is less then 512 bytes of pending data at the moment of panic they will not be flushed and will not overwrite previous 16KB. The option is only meaningful in post-mortem mode and when working over JTAG. -2. *Timeout for flushing last trace data to host on panic* (:ref:`CONFIG_ESP32_APPTRACE_ONPANIC_HOST_FLUSH_TMO`). The option is only meaningful in streaming mode and controls the maximum time tracing module will wait for the host to read the last data in case of panic. +1. *Threshold for flushing last trace data to host on panic* (:envvar:`CONFIG_ESP32_APPTRACE_POSTMORTEM_FLUSH_TRAX_THRESH`). This option is necessary due to the nature of working over JTAG. In that mode trace data are exposed to the host in 16KB blocks. In post-mortem mode when one block is filled it is exposed to the host and the previous one becomes unavailable. In other words trace data are overwritten in 16KB granularity. On panic the latest data from the current input block are exposed to host and host can read them for post-analysis. It can happen that system panic occurs when there are very small amount of data which are not exposed to the host yet. In this case the previous 16KB of collected data will be lost and host will see the latest, but very small piece of the trace. It can be insufficient to diagnose the problem. This menuconfig option allows avoiding such situations. It controls the threshold for flushing data in case of panic. For example user can decide that it needs not less then 512 bytes of the recent trace data, so if there is less then 512 bytes of pending data at the moment of panic they will not be flushed and will not overwrite previous 16KB. The option is only meaningful in post-mortem mode and when working over JTAG. +2. *Timeout for flushing last trace data to host on panic* (:envvar:`CONFIG_ESP32_APPTRACE_ONPANIC_HOST_FLUSH_TMO`). The option is only meaningful in streaming mode and controls the maximum time tracing module will wait for the host to read the last data in case of panic. How to use this library @@ -323,9 +323,9 @@ Another useful IDF feature built on top of application tracing library is the sy How To Use It """"""""""""" -Support for this feature is enabled by *Component config > Application Level Tracing > FreeRTOS SystemView Tracing* (:ref:`CONFIG_SYSVIEW_ENABLE`) menuconfig option. There are several other options enabled under the same menu: +Support for this feature is enabled by *Component config > Application Level Tracing > FreeRTOS SystemView Tracing* (:envvar:`CONFIG_SYSVIEW_ENABLE`) menuconfig option. There are several other options enabled under the same menu: -1. *ESP32 timer to use as SystemView timestamp source* (:ref:`CONFIG_SYSVIEW_TS_SOURCE`) selects the source of timestamps for SystemView events. In single core mode timestamps are generated using ESP32 internal cycle counter running at maximum 240 Mhz (~4 ns granularity). In dual-core mode external timer working at 40Mhz is used, so timestamp granularity is 25 ns. +1. *ESP32 timer to use as SystemView timestamp source* (:envvar:`CONFIG_SYSVIEW_TS_SOURCE`) selects the source of timestamps for SystemView events. In single core mode timestamps are generated using ESP32 internal cycle counter running at maximum 240 Mhz (~4 ns granularity). In dual-core mode external timer working at 40Mhz is used, so timestamp granularity is 25 ns. 2. Individually enabled or disabled collection of SystemView events (``CONFIG_SYSVIEW_EVT_XXX``): - Trace Buffer Overflow Event diff --git a/docs/en/api-guides/blufi.rst b/docs/en/api-guides/blufi.rst new file mode 100644 index 0000000000..429c5d9e64 --- /dev/null +++ b/docs/en/api-guides/blufi.rst @@ -0,0 +1,431 @@ +BluFi +^^^^^ + +Overview +-------- +The BluFi for ESP32 is a Wi-Fi network configuration function via Bluetooth channel. It provides a secure protocol to pass Wi-Fi configuration and credentials to the ESP32. Using this information ESP32 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. + +You can customize symmetric encryption, asymmetric encryption and checksum support customization. Here we use the DH algorithm for key negotiation, 128-AES algorithm for data encryption, and CRC16 algorithm for checksum verification. + +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. + +1. Set the ESP32 into GATT Server mode and then it will send broadcasts with specific *advertising data*. You can customize this broadcast as needed, which is not a part of the BluFi Profile. + +2. Use the App installed on the mobile phone to search for this particular broadcast. The mobile phone will connect to ESP32 as the GATT Client once the broadcast is confirmed. The App used during this part is up to you. + +3. After the GATT connection is successfully established, the mobile phone will send a data frame for key negotiation to ESP32 (see the section :ref:`frame_formats` for details). + +4. After ESP32 receives the data frame of key negotiation, it will parse the content according to the user-defined negotiation method. + +5. The mobile phone works with ESP32 for key negotiation using the encryption algorithms such as DH, RSA or ECC. + +6. After the negotiation process is completed, the mobile phone will send a control frame for security-mode setup to ESP32. + +7. When receiving this control frame, ESP32 will be able to encrypt and decrypt the communication data using the shared key and the security configuration. + +8. The mobile phone sends the data frame defined in the section of :ref:`frame_formats`,with the Wi-Fi configuration information to ESP32, including SSID, password, etc. + +9. The mobile phone sends a control frame of Wi-Fi connection request to ESP32. When receiving this control frame, ESP32 will regard the communication of essential information as done and get ready to connect to the Wi-Fi. + +10. After connecting to the Wi-Fi, ESP32 will send a control frame of Wi-Fi connection status report to the mobile phone,to report the connection status. At this point the networking procedure is completed. + +.. note:: + + 1. After ESP32 receives the control frame of security-mode configuration, it will execute the operations in accordance with the defined security mode. + + 2. The data lengths before and after symmetric encryption/decryption must stay the same. It also supports in-place encryption and decryption. + +The flow chat of BluFi +----------------------- + +.. seqdiag:: + :caption: BluFi Flow Chart + :align: center + + seqdiag blufi { + activation = none; + node_width = 80; + node_height = 60; + edge_length = 380; + span_height = 10; + default_fontsize = 12; + + Phone <- ESP32 [label="Advertising"]; + Phone -> ESP32 [label="Create GATT connection"]; + Phone <- ESP32 [label="Negotiate key procedure"]; + Phone -> ESP32 [label="Negotiate key procedure"]; + Phone -> ESP32 [label="CTRL: Set ESP32 to Phone Security mode"]; + Phone -> ESP32 [label="DATA: SSID"]; + Phone -> ESP32 [label="DATA: Password"]; + Phone -> ESP32 [label="DATA: Other information, such as CA certification"]; + Phone -> ESP32 [label="CTRL: Connect to AP"]; + Phone <- ESP32 [label="DATA: Connection State Report"]; + } + +.. _frame_formats: + +The Frame Formats Defined in BluFi +----------------------------------- + +The frame formats for the communication between the mobile phone App and ESP32 are defined as follows: + +The frame format with no fragment (8 bit): + ++------------+---------------+-----------------+-------------+----------------+----------------+ +| LSB - Type | Frame Control | Sequence Number | Data Length | Data | MSB - CheckSum | ++============+===============+=================+=============+================+================+ +| 1 | 1 | 1 | 1 | ${Data Length} | 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): + ++------------+--------------------+----------------+------------+-------------------------------------------+----------------+ +| LSB - Type | FrameControl(Frag) | SequenceNumber | DataLength | Data | MSB - CheckSum | ++ + + + +----------------------+--------------------+ + +| | | | | Total Content Length | Content | | ++============+====================+================+============+======================+====================+================+ +| 1 | 1 | 1 | 1 | 2 | ${Data Length} - 2 | 2 | ++------------+--------------------+----------------+------------+----------------------+--------------------+----------------+ + +Normally, the control frame does not contain data bits, except for Ack Frame. + +The format of Ack Frame(8 bit): + ++------------------+----------------+------------------+--------------+-----------------------+----------------+ +| LSB - Type (Ack) | Frame Control | SequenceNumber | Data Length | Data | MSB - CheckSum | ++ + + + +-----------------------+ + +| | | | | Acked Sequence Number | | ++==================+================+==================+==============+=======================+================+ +| 1 | 1 | 1 | 1 | 1 | 2 | ++------------------+----------------+------------------+--------------+-----------------------+----------------+ + +1. Type + + The **Type** field, taking 1 byte, is divided into **Type** and **Subtype**, that Type uses the lower 2 bits and **Subtype** uses the upper 6 bits. + + * The control frame is not encrypted for the time being and supports to be verified; + + * The data frame supports to be encrypted and verified. + + **1.1 Control Frame (0x0b’00)** + + +-------------------------+--------------------------------------------------------------+---------------------------------------------------------------+---------------------------------------------------------------+ + | Control Frame / 0x0b’00 | Implication | Explanation | Note | + +=========================+==============================================================+===============================================================+===============================================================+ + | 0x0b’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. | + +-------------------------+--------------------------------------------------------------+---------------------------------------------------------------+---------------------------------------------------------------+ + | 0x1b’000001 | Set ESP32 to the security mode. | To inform ESP32 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, ESP32 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 ESP32 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. | + +-------------------------+--------------------------------------------------------------+---------------------------------------------------------------+---------------------------------------------------------------+ + | 0x2b’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 ESP32. +---------------------------------------------------------------+ + | | | | 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. | + +-------------------------+--------------------------------------------------------------+---------------------------------------------------------------+---------------------------------------------------------------+ + | 0x3b’000011 | Connect ESP32 to the AP. | To notify ESP32 that the essential information has been sent | No data field is contained. | + | | | and it is allowed to connect to the AP. | | + +-------------------------+--------------------------------------------------------------+---------------------------------------------------------------+---------------------------------------------------------------+ + | 0x4b’000100 | Disconnect ESP32 from the AP. | | No data field is contained. | + +-------------------------+--------------------------------------------------------------+---------------------------------------------------------------+---------------------------------------------------------------+ + | 0x5b’000101 | To get the information of ESP32’s Wi-Fi mode and its status. | | No data field is contained. | + | | | | When receiving this control frame, ESP32 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. | + +-------------------------+--------------------------------------------------------------+---------------------------------------------------------------+---------------------------------------------------------------+ + | 0x6b’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. | + +-------------------------+--------------------------------------------------------------+---------------------------------------------------------------+---------------------------------------------------------------+ + | 0x7b'000111 | Get the version information. | | | + +-------------------------+--------------------------------------------------------------+---------------------------------------------------------------+---------------------------------------------------------------+ + | 0x8b’001000 | Disconnect the BLE GATT link. | | ESP32 will disconnect the BLE GATT link | + | | | | after receives this command. | + +-------------------------+--------------------------------------------------------------+---------------------------------------------------------------+---------------------------------------------------------------+ + | 0x9b’001001 | Get the Wi-Fi list. | To get ESP32 to scan the Wi-Fi access points around. | No data field is contained. | + | | | | When receiving this control frame, | + | | | | ESP32 will send back a follow-up frame of Wi-Fi list | + | | | | report to the mobile phone. | + +-------------------------+--------------------------------------------------------------+---------------------------------------------------------------+---------------------------------------------------------------+ + + **1.2 Data Frame (0x1b’01)** + + +--------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ + | Data Frame | Implication | Explanation | Note | + +==============+====================================================+===============================================================+=======================================================================+ + | 0x0b’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. | | + +--------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ + | 0x1b’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 ESP32 to the mobile phone, | + | | | | it means to provide the mobile phone with the needed information. | + +--------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ + | 0x2b’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 ESP32 to the mobile phone, | + | | | | it means to provide the mobile phone with the needed information. | + +--------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ + | 0x3b’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 ESP32 to the mobile phone, | + | | | | it means to provide the mobile phone with the needed information. | + +--------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ + | 0x4b’000100 | Send the SSID for SoftAP mode. | | The length of the data depends on the length field. | + | | | | When the transmission direction is ESP32 to the mobile phone, | + | | | | it means to provide the mobile phone with the needed information. | + +--------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ + | 0x5b’000101 | Send the password for SoftAPmode. | | The length of the data depends on the length field. | + | | | | When the transmission direction is ESP32 to the mobile phone, | + | | | | it means to provide the mobile phone with the needed information. | + +--------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ + | 0x6b’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 ESP32 | + | | | | to the mobile phone, it means to provide the mobile phone with | + | | | | the needed information. | + +--------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ + | 0x7b’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 ESP32 to the mobile phone, | + | | | | it means to provide the mobile phone with the needed information. | + +--------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ + | 0x8b’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 ESP32 to the mobile phone, | + | | | | it means to provide the mobile phone with the needed information. | + +--------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ + | 0x9b’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. | | + +--------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ + | 0xab’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. | + +--------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ + | 0xbb’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. | | + +--------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ + | 0xcb’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. | | + +--------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ + | 0xdb’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. | + +--------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ + | 0xeb’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. | + +--------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ + | 0xfb’001111 | Wi-Fi Connection State Report | To notify the phone of the ESP32'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. | + +--------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ + | 0x10b’010000 | Version | | data[0]= great versiondata[1]= sub version | + +--------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ + | 0x11B’010001 | Wi-Fi List | To send the Wi-Fi list to ESP32. | 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. | + +--------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ + | 0x12B’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 | + +--------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ + | 0x13B’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. | + +--------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ + +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 ESP32; | + +--------------------+------------------------------------------------------------------------------------------------+ + | | 1 means ESP32 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 | | + +--------------------+------------------------------------------------------------------------------------------------+ + +3. Sequence Control + + Sequence control field. When a frame is sent,the value of sequence fied is automatically incremented by 1 regardless of the type of frame, which prevents Replay Attack. The sequence is cleared after each reconnection. + +4. Length + + The length of the data field that does not include CheckSum. + +5. Data + + The instruction of the data field is different according to various values of Type or Subtype. Please refer to the table above. + +6. CheckSum + + This field takes 2 bytes that is used to check "sequence + data length + clear text data". + +The Security Implementation of ESP32 +------------------------------------- + +1. Securing data + + To ensure that the transmission of the Wi-Fi SSID and password is secure, the message needs to be encrypted using symmetric encryption algorithms, such as AES, DES and so on. Before using symmetric encryption algorithms, the devices are required to negotiate (or generate) a shared key using an asymmetric encryption algorithm (DH, RSA, ECC, etc). + +2. Ensuring data integrity + + To ensure data integrity, you need to add a checksum algorithm, such as SHA1, MD5, CRC, etc. + +3. Securing identity (signature) + + Algorithm like RSA can be used to secure identity. But for DH, it needs other algorithms as an companion for signature. + +4. Replay attack prevention + + It is added to the Sequence field and used during the checksum verification. + + For the coding of ESP32, you can determine and develop the security processing, such as key negotiation. The mobile application sends the negotiation data to ESP32 and then the data will be sent to the application layer for processing. If the application layer does not process it, you can use the DH encryption algorithm provided by BluFi to negotiate the key. + + The application layer needs to register several security-related functions to 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) + +This function is for ESP32 to receive normal data during negotiation, and after processing is completed, the data will be transmitted using Output_data and Output_len. + +BluFi will send output_data from Negotiate_data_handler after Negotiate_data_handler is called. + +Here are two "*", because the length of the data to be emitted is unknown that requires the function to allocate itself (malloc) or point to the global variable, and to inform whether the memory needs to be freed by NEED_FREE. + +.. code-block:: c + + typedef int (* esp_blufi_encrypt_func_t)(uint8_t iv8, uint8_t *crypt_data, int cyprt_len) + +The data to be encrypted and decrypted must use the same length. The IV8 is a 8 bit sequence value of frames, which can be used as a 8 bit of IV. + +.. code-block:: c + + typedef int (* esp_blufi_decrypt_func_t)(uint8_t iv8, uint8_t *crypt_data, int crypt_len) + +The data to be encrypted and decrypted must use the same length. The IV8 is a 8 bit sequence value of frames, which can be used as a 8 bit of IV. + +.. code-block:: c + + typedef uint16_t (*esp_blufi_checksum_func_t)(uint8_t iv8, uint8_t *data, int len) + +This function is used to compute CheckSum and return a value of CheckSum. BluFi uses the returned value to compare the CheckSum of the frame. + +GATT Related Instructions +------------------------- + +UUID +>>>>> + +BluFi Service UUID: 0xFFFF,16 bit + +BluFi (the mobile -> ESP32): 0xFF01, writable + +Blufi (ESP32 -> the mobile phone): 0xFF02, readable and callable + +.. note:: + + 1. The Ack mechanism is already defined in the profile, but there is no implementation based on the code for the time being. + + 2. Other parts have been implemented. \ No newline at end of file diff --git a/docs/en/api-guides/bootloader.rst b/docs/en/api-guides/bootloader.rst index 6e5efbcc04..0c04a646dd 100644 --- a/docs/en/api-guides/bootloader.rst +++ b/docs/en/api-guides/bootloader.rst @@ -13,22 +13,22 @@ FACTORY reset --------------------------- The user can write a basic working firmware and load it into the factory partition. Next, update the firmware via OTA (over the air). The updated firmware will be loaded into an OTA app partition slot and the OTA data partition is updated to boot from this partition. -If you want to be able to roll back to the factory firmware and clear the settings, then you need to set :ref:`CONFIG_BOOTLOADER_FACTORY_RESET`. +If you want to be able to roll back to the factory firmware and clear the settings, then you need to set :envvar:`CONFIG_BOOTLOADER_FACTORY_RESET`. The factory reset mechanism allows to reset the device to factory settings: - Clear one or more data partitions. - Boot from "factory" partition. -:ref:`CONFIG_BOOTLOADER_DATA_FACTORY_RESET` allows customers to select which data partitions will be erased when the factory reset is executed. +:envvar:`CONFIG_BOOTLOADER_DATA_FACTORY_RESET` allows customers to select which data partitions will be erased when the factory reset is executed. Can specify the names of partitions through comma-delimited with optional spaces for readability. (Like this: "nvs, phy_init, nvs_custom, ..."). Make sure that the name specified in the partition table and here are the same. Partitions of type "app" cannot be specified here. -:ref:`CONFIG_BOOTLOADER_OTA_DATA_ERASE` - the device will boot from "factory" partition after a factory reset. The OTA data partition will be cleared. +:envvar:`CONFIG_BOOTLOADER_OTA_DATA_ERASE` - the device will boot from "factory" partition after a factory reset. The OTA data partition will be cleared. -: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 on reset to trigger this. +:envvar:`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 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 low continuously for this period of time after reset before a factory reset or test partition boot (as applicable) is performed. +:envvar:`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. Partition table.:: @@ -45,12 +45,12 @@ Partition table.:: Boot from TEST firmware ------------------------ The user can write a special firmware for testing in production, and run it as needed. The partition table also needs a dedicated partition for this testing firmware (See `partition table`). -To trigger a test app you need to set :ref:`CONFIG_BOOTLOADER_APP_TEST`. +To trigger a test app you need to set :envvar:`CONFIG_BOOTLOADER_APP_TEST`. -:ref:`CONFIG_BOOTLOADER_NUM_PIN_APP_TEST` - number of the GPIO input 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. +:envvar:`CONFIG_BOOTLOADER_NUM_PIN_APP_TEST` - number of the GPIO input 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 old application will boot (factory or any OTA 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. +:envvar:`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. Customer bootloader --------------------- diff --git a/docs/en/api-guides/console.rst b/docs/en/api-guides/console.rst index c012c49d1d..490c9948d4 100644 --- a/docs/en/api-guides/console.rst +++ b/docs/en/api-guides/console.rst @@ -15,7 +15,7 @@ Line editing Line editing feature lets users compose commands by typing them, erasing symbols using 'backspace' key, navigating within the command using left/right keys, navigating to previously typed commands using up/down keys, and performing autocompletion using 'tab' key. -.. note:: This feature relies on ANSI escape sequence support in the terminal application. As such, serial monitors which display raw UART data can not be used together with the line editing library. If you see ``[6n`` or similar escape sequence when running get_started/console example instead of a command prompt (``[esp32]>``), it means that the serial monitor does not support escape sequences. Programs which are known to work are GNU screen, minicom, and idf_monitor.py (which can be invoked using ``idf.py monitor`` from project directory). +.. note:: This feature relies on ANSI escape sequence support in the terminal application. As such, serial monitors which display raw UART data can not be used together with the line editing library. If you see ``[6n`` or similar escape sequence when running get_started/console example instead of a command prompt (``[esp32]>``), it means that the serial monitor does not support escape sequences. Programs which are known to work are GNU screen, minicom, and idf_monitor.py (which can be invoked using ``make monitor`` from project directory). Here is an overview of functions provided by `linenoise`_ library. diff --git a/docs/en/api-guides/core_dump.rst b/docs/en/api-guides/core_dump.rst index 36ea823d98..99821b8c91 100644 --- a/docs/en/api-guides/core_dump.rst +++ b/docs/en/api-guides/core_dump.rst @@ -16,7 +16,7 @@ ESP-IDF provides special script `espcoredump.py` to help users to retrieve and a Configuration ------------- -There are a number of core dump related configuration options which user can choose in configuration menu of the application (`idf.py menuconfig`). +There are a number of core dump related configuration options which user can choose in configuration menu of the application (`make menuconfig`). 1. Core dump data destination (`Components -> ESP32-specific config -> Core dump destination`): @@ -83,6 +83,6 @@ Generic command syntax: * --gdb,-g GDB. Path to gdb to use for data retrieval. * --core,-c CORE. Path to core dump file to use (if skipped core dump will be read from flash). * --core-format,-t CORE_FORMAT. Specifies that file passed with "-c" is an ELF ("elf"), dumped raw binary ("raw") or base64-encoded ("b64") format. - * --off,-o OFF. Ofsset of coredump partition in flash (type "idf.py partition_table" to see it). - * --save-core,-s SAVE_CORE. Save core to file. Othwerwise temporary core file will be deleted. Ignored with "-c". + * --off,-o OFF. Offset of coredump partition in flash (type `make partition_table` to see it). + * --save-core,-s SAVE_CORE. Save core to file. Otherwise temporary core file will be deleted. Ignored with "-c". * --print-mem,-m Print memory dump. Used only with "info_corefile". diff --git a/docs/en/api-guides/error-handling.rst b/docs/en/api-guides/error-handling.rst new file mode 100644 index 0000000000..284bcc753f --- /dev/null +++ b/docs/en/api-guides/error-handling.rst @@ -0,0 +1,122 @@ +.. highlight:: c + +Error Handling +============== + +Overview +-------- + +Identifying and handling run-time errors is important for developing robust applications. There can be multiple kinds of run-time errors: + +- Recoverable errors: + + - Errors indicated by functions through return values (error codes) + - C++ exceptions, thrown using ``throw`` keyword + +- Unrecoverable (fatal) errors: + + - Failed assertions (using ``assert`` macro and equivalent methods) and ``abort()`` calls. + - CPU exceptions: access to protected regions of memory, illegal instruction, etc. + - System level checks: watchdog timeout, cache access error, stack overflow, stack smashing, heap corruption, etc. + +This guide explains ESP-IDF error handling mechanisms related to recoverable errors, and provides some common error handling patterns. + +For instructions on diagnosing unrecoverable errors, see :doc:`Fatal Errors `. + +Error codes +----------- + +The majority of ESP-IDF-specific functions use :cpp:type:`esp_err_t` type to return error codes. :cpp:type:`esp_err_t` is a signed integer type. Success (no error) is indicated with ``ESP_OK`` code, which is defined as zero. + +Various ESP-IDF header files define possible error codes using preprocessor defines. Usually these defines start with ``ESP_ERR_`` prefix. Common error codes for generic failures (out of memory, timeout, invalid argument, etc.) are defined in ``esp_err.h`` file. Various components in ESP-IDF may define additional error codes for specific situations. + +For the complete list of error codes, see :doc:`Error Code Reference <../api-reference/error-codes>`. + + +Converting error codes to error messages +---------------------------------------- + +For each error code defined in ESP-IDF components, :cpp:type:`esp_err_t` value can be converted to an error code name using :cpp:func:`esp_err_to_name` or :cpp:func:`esp_err_to_name_r` functions. For example, passing ``0x101`` to :cpp:func:`esp_err_to_name` will return "ESP_ERR_NO_MEM" string. Such strings can be used in log output to make it easier to understand which error has happened. + +Additionally, :cpp:func:`esp_err_to_name_r` function will attempt to interpret the error code as a `standard POSIX error code `_, if no matching ``ESP_ERR_`` value is found. This is done using ``strerror_r`` function. POSIX error codes (such as ``ENOENT``, ``ENOMEM``) are defined in ``errno.h`` and are typically obtained from ``errno`` variable. In ESP-IDF this variable is thread-local: multiple FreeRTOS tasks have their own copies of ``errno``. Functions which set ``errno`` only modify its value for the task they run in. + +This feature is enabled by default, but can be disabled to reduce application binary size. See :envvar:`CONFIG_ESP_ERR_TO_NAME_LOOKUP`. When this feature is disabled, :cpp:func:`esp_err_to_name` and :cpp:func:`esp_err_to_name_r` are still defined and can be called. In this case, :cpp:func:`esp_err_to_name` will return ``UNKNOWN ERROR``, and :cpp:func:`esp_err_to_name_r` will return ``Unknown error 0xXXXX(YYYYY)``, where ``0xXXXX`` and ``YYYYY`` are the hexadecimal and decimal representations of the error code, respectively. + +``ESP_ERROR_CHECK`` macro +------------------------- + +:cpp:func:`ESP_ERROR_CHECK` macro serves similar purpose as ``assert``, except that it checks :cpp:type:`esp_err_t` value rather than a ``bool`` condition. If the argument of :cpp:func:`ESP_ERROR_CHECK` is not equal :c:macro:`ESP_OK`, then an error message is printed on the console, and ``abort()`` is called. + +Error message will typically look like this:: + + ESP_ERROR_CHECK failed: esp_err_t 0x107 (ESP_ERR_TIMEOUT) at 0x400d1fdf + + file: "/Users/user/esp/example/main/main.c" line 20 + func: app_main + expression: sdmmc_card_init(host, &card) + + Backtrace: 0x40086e7c:0x3ffb4ff0 0x40087328:0x3ffb5010 0x400d1fdf:0x3ffb5030 0x400d0816:0x3ffb5050 + +.. note:: If :doc:`IDF monitor <../get-started/idf-monitor>` is used, addresses in the backtrace will be converted to file names and line numbers. + +- The first line mentions the error code as a hexadecimal value, and the identifier used for this error in source code. The latter depends on :envvar:`CONFIG_ESP_ERR_TO_NAME_LOOKUP` option being set. Address in the program where error has occured is printed as well. + +- Subsequent lines show the location in the program where :cpp:func:`ESP_ERROR_CHECK` macro was called, and the expression which was passed to the macro as an argument. + +- Finally, backtrace is printed. This is part of panic handler output common to all fatal errors. See :doc:`Fatal Errors ` for more information about the backtrace. + + +Error handling patterns +----------------------- + +1. Attempt to recover. Depending on the situation, this might mean to retry the call after some time, or attempt to de-initialize the driver and re-initialize it again, or fix the error condition using an out-of-band mechanism (e.g reset an external peripheral which is not responding). + + Example:: + + esp_err_t err; + do { + err = sdio_slave_send_queue(addr, len, arg, timeout); + // keep retrying while the sending queue is full + } while (err == ESP_ERR_TIMEOUT); + if (err != ESP_OK) { + // handle other errors + } + +2. Propagate the error to the caller. In some middleware components this means that a function must exit with the same error code, making sure any resource allocations are rolled back. + + Example:: + + sdmmc_card_t* card = calloc(1, sizeof(sdmmc_card_t)); + if (card == NULL) { + return ESP_ERR_NO_MEM; + } + esp_err_t err = sdmmc_card_init(host, &card); + if (err != ESP_OK) { + // Clean up + free(card); + // Propagate the error to the upper layer (e.g. to notify the user). + // Alternatively, application can define and return custom error code. + return err; + } + +3. Convert into unrecoverable error, for example using ``ESP_ERROR_CHECK``. See `ESP_ERROR_CHECK macro`_ section for details. + + Terminating the application in case of an error is usually undesirable behaviour for middleware components, but is sometimes acceptable at application level. + + Many ESP-IDF examples use ``ESP_ERROR_CHECK`` to handle errors from various APIs. This is not the best practice for applications, and is done to make example code more concise. + + Example:: + + ESP_ERROR_CHECK(spi_bus_initialize(host, bus_config, dma_chan)); + + +C++ Exceptions +-------------- + +Support for C++ Exceptions in ESP-IDF is disabled by default, but can be enabled using :envvar:`CONFIG_CXX_EXCEPTIONS` option. + +Enabling exception handling normally increases application binary size by a few kB. Additionally it may be necessary to reserve some amount of RAM for exception emergency pool. Memory from this pool will be used if it is not possible to allocate exception object from the heap. Amount of memory in the emergency pool can be set using :envvar:`CONFIG_CXX_EXCEPTIONS_EMG_POOL_SIZE` variable. + +If an exception is thrown, but there is no ``catch`` block, the program will be terminated by ``abort`` function, and backtrace will be printed. See :doc:`Fatal Errors ` for more information about backtraces. + + diff --git a/docs/en/api-guides/external-ram.rst b/docs/en/api-guides/external-ram.rst index 52704365db..15438072b6 100644 --- a/docs/en/api-guides/external-ram.rst +++ b/docs/en/api-guides/external-ram.rst @@ -65,7 +65,7 @@ The use of external RAM has a few restrictions: execution of code afterwards slower. * External RAM cannot be used as task stack memory; because of this, xTaskCreate and similar functions will always allocate internal memory for stack and task TCBs and xTaskCreateStatic-type functions will check if the buffers passed are internal. However, for tasks not calling - on code in ROM in any way, directly or indirectly, the menuconfig option :ref:`CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY` will eliminate + on code in ROM in any way, directly or indirectly, the menuconfig option :envvar:`CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY` will eliminate the check in xTaskCreateStatic, allowing task stack in external RAM. Using this is not advised, however. @@ -91,7 +91,7 @@ The bugs in this silicon revision introduce a hazard when certain sequences of m To work around this, the gcc compiler to compile ESP-IDF has been expanded with a flag: ``-mfix-esp32-psram-cache-issue``. With this flag passed to gcc on the command line, the compiler works around these sequences and only outputs code that can safely be executed. -In ESP-IDF, this flag is enabled when you select :ref:`CONFIG_SPIRAM_CACHE_WORKAROUND`. ESP-IDF also takes other measures to make +In ESP-IDF, this flag is enabled when you select :envvar:`CONFIG_SPIRAM_CACHE_WORKAROUND`. ESP-IDF also takes other measures to make sure no combination of PSRAM access plus the offending instruction sets are used: it links to a version of Newlib recompiled with the gcc flag, doesn't use some ROM functions and allocates static memory for the WiFi stack. diff --git a/docs/en/api-guides/fatal-errors.rst b/docs/en/api-guides/fatal-errors.rst new file mode 100644 index 0000000000..ba98b61c13 --- /dev/null +++ b/docs/en/api-guides/fatal-errors.rst @@ -0,0 +1,293 @@ +Fatal Errors +============ + +Overview +-------- + +In certain situations, execution of the program can not be continued in a well defined way. In ESP-IDF, these situations include: + +- CPU Exceptions: Illegal Instruction, Load/Store Alignment Error, Load/Store Prohibited error, Double Exception. + +- System level checks and safeguards: + + - :doc:`Interrupt watchdog <../api-reference/system/wdts>` timeout + - :doc:`Task watchdog <../api-reference/system/wdts>` timeout (only fatal if :envvar:`CONFIG_TASK_WDT_PANIC` is set) + - Cache access error + - Brownout detection event + - Stack overflow + - Stack smashing protection check + - Heap integrity check + +- Failed assertions, via ``assert``, ``configASSERT`` and similar macros. + +This guide explains the procedure used in ESP-IDF for handling these errors, and provides suggestions on troubleshooting the errors. + +Panic Handler +------------- + +Every error cause listed in the `Overview`_ will be handled by *panic handler*. + +Panic handler will start by printing the cause of the error to the console. For CPU exceptions, the message will be similar to:: + + Guru Meditation Error: Core 0 panic'ed (IllegalInstruction). Exception was unhandled. + +For some of the system level checks (interrupt watchdog, cache access error), the message will be similar to:: + + Guru Meditation Error: Core 0 panic'ed (Cache disabled but cached memory region accessed) + +In all cases, error cause will be printed in parens. See `Guru Meditation Errors`_ for a list of possible error causes. + +Subsequent behavior of the panic handler can be set using :envvar:`CONFIG_ESP32_PANIC` configuration choice. The available options are: + +- Print registers and reboot (``CONFIG_ESP32_PANIC_PRINT_REBOOT``) — default option. + + This will print register values at the point of the exception, print the backtrace, and restart the chip. + +- Print registers and halt (``CONFIG_ESP32_PANIC_PRINT_HALT``) + + Similar to the above option, but halt instead of rebooting. External reset is required to restart the program. + +- Silent reboot (``CONFIG_ESP32_PANIC_SILENT_REBOOT``) + + Don't print registers or backtrace, restart the chip immediately. + +- Invoke GDB Stub (``CONFIG_ESP32_PANIC_GDBSTUB``) + + Start GDB server which can communicate with GDB over console UART port. See `GDB Stub`_ for more details. + +Behavior of panic handler is affected by two other configuration options. + +- If :envvar:`CONFIG_ESP32_DEBUG_OCDAWARE` is enabled (which is the default), panic handler will detect whether a JTAG debugger is connected. If it is, execution will be halted and control will be passed to the debugger. In this case registers and backtrace are not dumped to the console, and GDBStub / Core Dump functions are not used. + +- If :doc:`Core Dump ` feature is enabled (``CONFIG_ESP32_ENABLE_COREDUMP_TO_FLASH`` or ``CONFIG_ESP32_ENABLE_COREDUMP_TO_UART`` options), then system state (task stacks and registers) will be dumped either to Flash or UART, for later analysis. + +The following diagram illustrates panic handler behavior: + +.. blockdiag:: + :caption: Panic Handler Flowchart + :align: center + + blockdiag panic-handler { + orientation = portrait; + edge_layout = flowchart; + default_group_color = white; + + cpu_exception [label = "CPU Exception", shape=roundedbox]; + sys_check [label = "Cache error,\nInterrupt WDT,\nabort()", shape=roundedbox]; + check_ocd [label = "JTAG debugger\nconnected?", shape=diamond, width=160, height=80]; + print_error_cause [label = "Print error/\nexception cause"]; + use_jtag [label = "Send signal to\nJTAG debugger", shape=roundedbox]; + dump_registers [label = "Print registers\nand backtrace"]; + check_coredump [label = "Core dump\nenabled?", shape=flowchart.condition]; + do_coredump [label = "Core dump\nto UART or Flash"]; + check_gdbstub [label = "GDB Stub\nenabled?", shape=flowchart.condition]; + do_gdbstub [label = "Start GDB Stub", shape=roundedbox]; + halt [label = "Halt", shape=roundedbox]; + reboot [label = "Reboot", shape=roundedbox]; + check_halt [label = "Halt?", shape=flowchart.condition]; + + group {cpu_exception, sys_check}; + + cpu_exception -> print_error_cause; + sys_check -> print_error_cause; + print_error_cause -> check_ocd; + check_ocd -> use_jtag [label = "Yes"]; + check_ocd -> dump_registers [label = "No"]; + dump_registers -> check_coredump + check_coredump -> do_coredump [label = "Yes"]; + do_coredump -> check_gdbstub; + check_coredump -> check_gdbstub [label = "No"]; + check_gdbstub -> check_halt [label = "No"]; + check_gdbstub -> do_gdbstub [label = "Yes"]; + check_halt -> halt [label = "Yes"]; + check_halt -> reboot [label = "No"]; + } + +Register Dump and Backtrace +--------------------------- + +Unless ``CONFIG_ESP32_PANIC_SILENT_REBOOT`` option is enabled, panic handler prints some of the CPU registers, and the backtrace, to the console:: + + Core 0 register dump: + PC : 0x400e14ed PS : 0x00060030 A0 : 0x800d0805 A1 : 0x3ffb5030 + A2 : 0x00000000 A3 : 0x00000001 A4 : 0x00000001 A5 : 0x3ffb50dc + A6 : 0x00000000 A7 : 0x00000001 A8 : 0x00000000 A9 : 0x3ffb5000 + A10 : 0x00000000 A11 : 0x3ffb2bac A12 : 0x40082d1c A13 : 0x06ff1ff8 + A14 : 0x3ffb7078 A15 : 0x00000000 SAR : 0x00000014 EXCCAUSE: 0x0000001d + EXCVADDR: 0x00000000 LBEG : 0x4000c46c LEND : 0x4000c477 LCOUNT : 0xffffffff + + Backtrace: 0x400e14ed:0x3ffb5030 0x400d0802:0x3ffb5050 + +Register values printed are the register values in the exception frame, i.e. values at the moment when CPU exception or other fatal error has occured. + +Register dump is not printed if the panic handler was executed as a result of an ``abort()`` call. + +In some cases, such as interrupt watchdog timeout, panic handler may print additional CPU registers (EPC1-EPC4) and the registers/backtrace of the code running on the other CPU. + +Backtrace line contains PC:SP pairs, where PC is the Program Counter and SP is Stack Pointer, for each stack frame of the current task. If a fatal error happens inside an ISR, the backtrace may include PC:SP pairs both from the task which was interrupted, and from the ISR. + +If :doc:`IDF Monitor <../get-started/idf-monitor>` is used, Program Counter values will be converted to code locations (function name, file name, and line number), and the output will be annotated with additional lines:: + + Core 0 register dump: + PC : 0x400e14ed PS : 0x00060030 A0 : 0x800d0805 A1 : 0x3ffb5030 + 0x400e14ed: app_main at /Users/user/esp/example/main/main.cpp:36 + + A2 : 0x00000000 A3 : 0x00000001 A4 : 0x00000001 A5 : 0x3ffb50dc + A6 : 0x00000000 A7 : 0x00000001 A8 : 0x00000000 A9 : 0x3ffb5000 + A10 : 0x00000000 A11 : 0x3ffb2bac A12 : 0x40082d1c A13 : 0x06ff1ff8 + 0x40082d1c: _calloc_r at /Users/user/esp/esp-idf/components/newlib/syscalls.c:51 + + A14 : 0x3ffb7078 A15 : 0x00000000 SAR : 0x00000014 EXCCAUSE: 0x0000001d + EXCVADDR: 0x00000000 LBEG : 0x4000c46c LEND : 0x4000c477 LCOUNT : 0xffffffff + + Backtrace: 0x400e14ed:0x3ffb5030 0x400d0802:0x3ffb5050 + 0x400e14ed: app_main at /Users/user/esp/example/main/main.cpp:36 + + 0x400d0802: main_task at /Users/user/esp/esp-idf/components/esp32/cpu_start.c:470 + +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 +-------- + +If ``CONFIG_ESP32_PANIC_GDBSTUB`` option is enabled, panic handler will not reset the chip when fatal error happens. Instead, it will start GDB remote protocol server, commonly referred to as GDB Stub. When this happens, GDB instance running on the host computer can be instructed to connect to the ESP32 UART port. + +If :doc:`IDF Monitor <../get-started/idf-monitor>` is used, GDB is started automatically when GDB Stub prompt is detected on the UART. The output would look like this:: + + Entering gdb stub now. + $T0b#e6GNU gdb (crosstool-NG crosstool-ng-1.22.0-80-gff1f415) 7.10 + Copyright (C) 2015 Free Software Foundation, Inc. + License GPLv3+: GNU GPL version 3 or later + This is free software: you are free to change and redistribute it. + There is NO WARRANTY, to the extent permitted by law. Type "show copying" + and "show warranty" for details. + This GDB was configured as "--host=x86_64-build_apple-darwin16.3.0 --target=xtensa-esp32-elf". + Type "show configuration" for configuration details. + For bug reporting instructions, please see: + . + Find the GDB manual and other documentation resources online at: + . + For help, type "help". + Type "apropos word" to search for commands related to "word"... + Reading symbols from /Users/user/esp/example/build/example.elf...done. + Remote debugging using /dev/cu.usbserial-31301 + 0x400e1b41 in app_main () + at /Users/user/esp/example/main/main.cpp:36 + 36 *((int*) 0) = 0; + (gdb) + +GDB prompt can be used to inspect CPU registers, local and static variables, and arbitrary locations in memory. It is not possible to set breakpoints, change PC, or continue execution. To reset the program, exit GDB and perform external reset: Ctrl-T Ctrl-R in IDF Monitor, or using external reset button on the development board. + +Guru Meditation Errors +---------------------- + +.. Note to editor: titles of the following section need to match exception causes printed by the panic handler. Do not change the titles (insert spaces, reword, etc.) unless panic handler messages are also changed. + +.. Note to translator: When translating this section, avoid translating the following section titles. "Guru Meditation" in the title of this section should also not be translated. Keep these two notes when translating. + +This section explains the meaning of different error causes, printed in parens after ``Guru Meditation Error: Core panic'ed`` message. + +.. note:: See `Wikipedia article `_ for historical origins of "Guru Meditation". + + +IllegalInstruction +^^^^^^^^^^^^^^^^^^ + +This CPU exception indicates that the instruction which was executed was not a valid instruction. +Most common reasons for this error include: + +- FreeRTOS task function has returned. In FreeRTOS, if task function needs to terminate, it should call :cpp:func:`vTaskDelete` function and delete itself, instead of returning. + +- Failure to load next instruction from SPI flash. This usually happens if: + + - Application has reconfigured SPI flash pins as some other function (GPIO, UART, etc.). Consult Hardware Design Guidelines and the Datasheet for the chip or module for details about SPI flash pins. + + - Some external device was accidentally connected to SPI flash pins, and has interfered with communication between ESP32 and SPI flash. + + +InstrFetchProhibited +^^^^^^^^^^^^^^^^^^^^ + +This CPU exception indicates that CPU could not load an instruction because the the address of the instruction did not belong to a valid region in instruction RAM or ROM. + +Usually this means an attempt to call a function pointer, which does not point to valid code. ``PC`` (Program Counter) register can be used as an indicator: it will be zero or will contain garbage value (not ``0x4xxxxxxx``). + +LoadProhibited, StoreProhibited +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +This CPU exception happens when application attempts to read from or write to an invalid memory location. The address which was written/read is found in ``EXCVADDR`` register in the register dump. If this address is zero, it usually means that application attempted to dereference a NULL pointer. If this address is close to zero, it usually means that application attempted to access member of a structure, but the pointer to the structure was NULL. If this address is something else (garbage value, not in ``0x3fxxxxxx`` - ``0x6xxxxxxx`` range), it likely means that the pointer used to access the data was either not initialized or was corrupted. + +IntegerDivideByZero +^^^^^^^^^^^^^^^^^^^ + +Application has attempted to do integer division by zero. + +LoadStoreAlignment +^^^^^^^^^^^^^^^^^^ + +Application has attempted to read or write memory location, and address alignment did not match load/store size. For example, 32-bit load can only be done from 4-byte aligned address, and 16-bit load can only be done from a 2-byte aligned address. + +LoadStoreError +^^^^^^^^^^^^^^ + +Application has attempted to do a 8- or 16- bit load/store from a memory region which only supports 32-bit loads/stores. For example, dereferencing a ``char*`` pointer which points into intruction memory will result in such an error. + +Unhandled debug exception +^^^^^^^^^^^^^^^^^^^^^^^^^ + +This will usually be followed by a message like:: + + Debug exception reason: Stack canary watchpoint triggered (task_name) + +This error indicates that application has written past the end of the stack of ``task_name`` task. Note that not every stack overflow is guaranteed to trigger this error. It is possible that the task writes to stack beyond the stack canary location, in which case the watchpoint will not be triggered. + +Interrupt wdt timeout on CPU0 / CPU1 +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Indicates that interrupt watchdog timeout has occured. See :doc:`Watchdogs <../api-reference/system/wdts>` for more information. + +Cache disabled but cached memory region accessed +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +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. + +Other Fatal Errors +------------------ + +Brownout +^^^^^^^^ + +ESP32 has a built-in brownout detector, which is enabled by default. Brownout detector can trigger system reset if supply voltage goes below safe level. Brownout detector can be configured using :envvar:`CONFIG_BROWNOUT_DET` and :envvar:`CONFIG_BROWNOUT_DET_LVL_SEL` options. +When brownout detector triggers, the following message is printed:: + + Brownout detector was triggered + +Chip is reset after the message is printed. + +Note that if supply voltage is dropping at a fast rate, only part of the message may be seen on the console. + +Corrupt Heap +^^^^^^^^^^^^ + +ESP-IDF heap implementation contains a number of run-time checks of heap structure. Additional checks ("Heap Poisoning") can be enabled in menuconfig. If one of the checks fails, message similar to the following will be printed:: + + CORRUPT HEAP: Bad tail at 0x3ffe270a. Expected 0xbaad5678 got 0xbaac5678 + assertion "head != NULL" failed: file "/Users/user/esp/esp-idf/components/heap/multi_heap_poisoning.c", line 201, function: multi_heap_free + abort() was called at PC 0x400dca43 on core 0 + +Consult :doc:`Heap Memory Debugging <../api-reference/system/heap_debug>` documentation for further information. + +Stack Smashing +^^^^^^^^^^^^^^ + +Stack smashing protection (based on GCC ``-fstack-protector*`` flags) can be enabled in ESP-IDF using :envvar:`CONFIG_STACK_CHECK_MODE` option. If stack smashing is detected, message similar to the following will be printed:: + + Stack smashing protect failure! + + abort() was called at PC 0x400d2138 on core 0 + + Backtrace: 0x4008e6c0:0x3ffc1780 0x4008e8b7:0x3ffc17a0 0x400d2138:0x3ffc17c0 0x400e79d5:0x3ffc17e0 0x400e79a7:0x3ffc1840 0x400e79df:0x3ffc18a0 0x400e2235:0x3ffc18c0 0x400e1916:0x3ffc18f0 0x400e19cd:0x3ffc1910 0x400e1a11:0x3ffc1930 0x400e1bb2:0x3ffc1950 0x400d2c44:0x3ffc1a80 + 0 + +The backtrace should point to the function where stack smashing has occured. Check the function code for unbounded access to local arrays. + diff --git a/docs/en/api-guides/freertos-smp.rst b/docs/en/api-guides/freertos-smp.rst index 40665d9c5b..c2f72f5f6e 100644 --- a/docs/en/api-guides/freertos-smp.rst +++ b/docs/en/api-guides/freertos-smp.rst @@ -89,7 +89,7 @@ Static Alocation ^^^^^^^^^^^^^^^^^ This feature has been backported from FreeRTOS v9.0.0 to ESP-IDF. The -:ref:`CONFIG_SUPPORT_STATIC_ALLOCATION` option must be enabled in `menuconfig` +:envvar:`CONFIG_SUPPORT_STATIC_ALLOCATION` option must be enabled in `menuconfig` in order for static allocation functions to be available. Once enabled, the following functions can be called... @@ -462,7 +462,7 @@ called for that TLSP during task deletion. If a deletion callback is `NULL`, users should manually free the memory pointed to by the associated TLSP before task deletion in order to avoid memory leak. -:ref:`CONFIG_FREERTOS_THREAD_LOCAL_STORAGE_POINTERS` in menuconfig can be used +:envvar:`CONFIG_FREERTOS_THREAD_LOCAL_STORAGE_POINTERS` in menuconfig can be used to configure the number TLSP and Deletion Callbacks a TCB will have. For more details see :doc:`FreeRTOS API reference<../api-reference/system/freertos>`. @@ -478,21 +478,21 @@ The ESP-IDF FreeRTOS can be configured using ``make menuconfig`` under ESP-IDF FreeRTOS configuration options. For a full list of ESP-IDF FreeRTOS configurations, see :doc:`FreeRTOS <../api-reference/kconfig>` -:ref:`CONFIG_FREERTOS_UNICORE` will run ESP-IDF FreeRTOS only +:envvar:`CONFIG_FREERTOS_UNICORE` will run ESP-IDF FreeRTOS only on **PRO_CPU**. Note that this is **not equivalent to running vanilla FreeRTOS**. Behaviors of multiple components in ESP-IDF will be modified such as :component_file:`esp32/cpu_start.c`. For more details regarding the effects of running ESP-IDF FreeRTOS on a single core, search for occurences of ``CONFIG_FREERTOS_UNICORE`` in the ESP-IDF components. -:ref:`CONFIG_FREERTOS_THREAD_LOCAL_STORAGE_POINTERS` will define the +:envvar:`CONFIG_FREERTOS_THREAD_LOCAL_STORAGE_POINTERS` will define the number of Thread Local Storage Pointers each task will have in ESP-IDF FreeRTOS. -:ref:`CONFIG_SUPPORT_STATIC_ALLOCATION` will enable the backported +:envvar:`CONFIG_SUPPORT_STATIC_ALLOCATION` will enable the backported functionality of :cpp:func:`xTaskCreateStaticPinnedToCore` in ESP-IDF FreeRTOS -:ref:`CONFIG_FREERTOS_ASSERT_ON_UNTESTED_FUNCTION` will trigger a halt in +:envvar:`CONFIG_FREERTOS_ASSERT_ON_UNTESTED_FUNCTION` will trigger a halt in particular functions in ESP-IDF FreeRTOS which have not been fully tested in an SMP context. diff --git a/docs/en/api-guides/general-notes.rst b/docs/en/api-guides/general-notes.rst index f3f934968b..71ae1eff4a 100644 --- a/docs/en/api-guides/general-notes.rst +++ b/docs/en/api-guides/general-notes.rst @@ -111,6 +111,12 @@ Constant data may also be placed into DRAM, for example if it is used in an ISR Needless to say, it is not advised to use ``printf`` and other output functions in ISRs. For debugging purposes, use ``ESP_EARLY_LOGx`` macros when logging from ISRs. Make sure that both ``TAG`` and format string are placed into ``DRAM`` in that case. +The macro ``__NOINIT_ATTR`` can be used as attribute to place data into ``.noinit`` section. The values placed into this section will not be initialized at startup and keep its value after software restart. + +Example:: + + __NOINIT_ATTR uint32_t noinit_data; + DROM (data stored in Flash) ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -121,6 +127,12 @@ RTC slow memory Global and static variables used by code which runs from RTC memory (i.e. deep sleep stub code) must be placed into RTC slow memory. Please check detailed description in :doc:`deep sleep ` documentation. +The attribute macro named ``RTC_NOINIT_ATTR`` can be used to place data into this type of memory. The values placed into this section keep their value after waking from deep sleep. + +Example:: + + RTC_NOINIT_ATTR uint32_t rtc_noinit_data; + DMA Capable Requirement ----------------------- diff --git a/docs/en/api-guides/index.rst b/docs/en/api-guides/index.rst index 21ec7d69a7..0a0f9c8e9b 100644 --- a/docs/en/api-guides/index.rst +++ b/docs/en/api-guides/index.rst @@ -7,6 +7,8 @@ API Guides General Notes Build System Build System (CMake) + Error Handling + Fatal Errors Deep Sleep Wake Stubs ESP32 Core Dump Flash Encryption <../security/flash-encryption> @@ -24,4 +26,5 @@ API Guides ROM debug console WiFi Driver Mesh Stack + BluFi External SPI-connected RAM diff --git a/docs/en/api-guides/jtag-debugging/tips-and-quirks.rst b/docs/en/api-guides/jtag-debugging/tips-and-quirks.rst index bc81dbd6f5..fb48f6d8b5 100644 --- a/docs/en/api-guides/jtag-debugging/tips-and-quirks.rst +++ b/docs/en/api-guides/jtag-debugging/tips-and-quirks.rst @@ -9,7 +9,7 @@ This section provides collection of all tips and quirks referred to from various Breakpoints and watchpoints available ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -The ESP32 supports 2 hardware breakpoints. It also supports two watchpoints, so two variables can be watched for change or read by the GDB command ``watch myVariable``. Note that menuconfig option :ref:`CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK` uses the 2nd watchpoint and will not provide expected results, if you also try to use it within OpenOCD / GDB. See menuconfig's help for detailed description. +The ESP32 supports 2 hardware breakpoints. It also supports two watchpoints, so two variables can be watched for change or read by the GDB command ``watch myVariable``. Note that menuconfig option :envvar:`CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK` uses the 2nd watchpoint and will not provide expected results, if you also try to use it within OpenOCD / GDB. See menuconfig's help for detailed description. .. _jtag-debugging-tip-where-breakpoints: @@ -35,8 +35,8 @@ Support options for OpenOCD at compile time ESP-IDF has some support options for OpenOCD debugging which can be set at compile time: -* :ref:`CONFIG_ESP32_DEBUG_OCDAWARE` is enabled by default. If a panic or unhandled exception is thrown and a JTAG debugger is connected (ie openocd is running), ESP-IDF will break into the debugger. -* :ref:`CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK` (disabled by default) sets watchpoint index 1 (the second of two) at the end of any task stack. This is the most accurate way to debug task stack overflows. Click the link for more details. +* :envvar:`CONFIG_ESP32_DEBUG_OCDAWARE` is enabled by default. If a panic or unhandled exception is thrown and a JTAG debugger is connected (ie openocd is running), ESP-IDF will break into the debugger. +* :envvar:`CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK` (disabled by default) sets watchpoint index 1 (the second of two) at the end of any task stack. This is the most accurate way to debug task stack overflows. Click the link for more details. Please see the :ref:`make menuconfig ` menu for more details on setting compile-time options. @@ -81,8 +81,8 @@ What is the meaning of debugger's startup commands? On startup, debugger is issuing sequence of commands to reset the chip and halt it at specific line of code. This sequence (shown below) is user defined to pick up at most convenient / appropriate line and start debugging. * ``mon reset halt`` — reset the chip and keep the CPUs halted +* ``flushregs`` — monitor (``mon``) command can not inform GDB that the target state has changed. GDB will assume that whatever stack the target had before ``mon reset halt`` will still be valid. In fact, after reset the target state will change, and executing ``flushregs`` is a way to force GDB to get new state from the target. * ``thb app_main`` — insert a temporary hardware breakpoint at ``app_main``, put here another function name if required -* ``x $a1=0`` — this is the tricky part. As far as we can tell, there is no way for a ``mon`` command to tell GDB that the target state has changed. GDB will assume that whatever stack the target had before ``mon reset halt`` will still be valid. In fact, after reset the target state will change and executing ``x $a1=0`` is a way to force GDB to get new state from the target. * ``c`` — resume the program. It will then stop at breakpoint inserted at ``app_main``. diff --git a/docs/en/api-guides/jtag-debugging/using-debugger.rst b/docs/en/api-guides/jtag-debugging/using-debugger.rst index e42210aed6..2c8e5d7a06 100644 --- a/docs/en/api-guides/jtag-debugging/using-debugger.rst +++ b/docs/en/api-guides/jtag-debugging/using-debugger.rst @@ -48,7 +48,7 @@ Once installation is complete, configure debugging session following steps below Configuration of GDB Hardware Debugging - Debugger tab -8. The last tab to that requires changing of default configuration is "Startup". Under "Initialization Commands" uncheck "Reset and Delay (seconds)" and "Halt"". Then, in entry field below, type ``mon reset halt`` and ``x $a1=0`` (in two separate lines). +8. The last tab to that requires changing of default configuration is "Startup". Under "Initialization Commands" uncheck "Reset and Delay (seconds)" and "Halt"". Then, in entry field below, type ``mon reset halt`` and ``flushregs`` (in two separate lines). .. note:: If you want to update image in the flash automatically before starting new debug session add the following lines of commands at the beginning of "Initialization Commands" textbox:: @@ -113,8 +113,8 @@ Command Line target remote :3333 mon reset halt + flushregs thb app_main - x $a1=0 c Save this file in current directory. diff --git a/docs/en/api-guides/partition-tables.rst b/docs/en/api-guides/partition-tables.rst index 2893dbcaaa..6363f58f89 100644 --- a/docs/en/api-guides/partition-tables.rst +++ b/docs/en/api-guides/partition-tables.rst @@ -107,7 +107,7 @@ When type is "data", the subtype field can be specified as ota (0), phy (1), nvs - phy (1) is for storing PHY initialisation data. This allows PHY to be configured per-device, instead of in firmware. - In the default configuration, the phy partition is not used and PHY initialisation data is compiled into the app itself. As such, this partition can be removed from the partition table to save space. - - To load PHY data from this partition, run ``make menuconfig`` and enable :ref:`CONFIG_ESP32_PHY_INIT_DATA_IN_PARTITION` option. You will also need to flash your devices with phy init data as the esp-idf build system does not do this automatically. + - To load PHY data from this partition, run ``make menuconfig`` and enable :envvar:`CONFIG_ESP32_PHY_INIT_DATA_IN_PARTITION` option. You will also need to flash your devices with phy init data as the esp-idf build system does not do this automatically. - nvs (2) is for the :doc:`Non-Volatile Storage (NVS) API <../api-reference/storage/nvs_flash>`. - NVS is used to store per-device PHY calibration data (different to initialisation data). @@ -153,7 +153,7 @@ MD5 checksum The binary format of the partition table contains an MD5 checksum computed based on the partition table. This checksum is used for checking the integrity of the partition table during the boot. -The MD5 checksum generation can be disabled by the ``--disable-md5sum`` option of ``gen_esp32part.py`` or by the :ref:`CONFIG_PARTITION_TABLE_MD5` option. This is useful for example when one uses a legacy bootloader which cannot process MD5 checksums and the boot fails with the error message ``invalid magic number 0xebeb``. +The MD5 checksum generation can be disabled by the ``--disable-md5sum`` option of ``gen_esp32part.py`` or by the :envvar:`CONFIG_PARTITION_TABLE_MD5` option. This is useful for example when one uses a legacy bootloader which cannot process MD5 checksums and the boot fails with the error message ``invalid magic number 0xebeb``. Flashing the partition table ---------------------------- diff --git a/docs/en/api-guides/ulp.rst b/docs/en/api-guides/ulp.rst index 9f913ff814..a712b8ec02 100644 --- a/docs/en/api-guides/ulp.rst +++ b/docs/en/api-guides/ulp.rst @@ -15,8 +15,8 @@ Installing the toolchain ULP coprocessor code is written in assembly and compiled using the `binutils-esp32ulp toolchain`_. -1. Download the toolchain using the links listed on this page: -https://github.com/espressif/binutils-esp32ulp/wiki#downloads +1. Download pre-built binaries of the latest toolchain release from: +https://github.com/espressif/binutils-esp32ulp/releases. 2. Extract the toolchain into a directory, and add the path to the ``bin/`` directory of the toolchain to the ``PATH`` environment variable. @@ -134,7 +134,7 @@ Each ULP program is embedded into the ESP-IDF application as a binary blob. Appl Once the program is loaded into RTC memory, application can start it, passing the address of the entry point to ``ulp_run`` function:: - ESP_ERROR_CHECK( ulp_run((&ulp_entry - RTC_SLOW_MEM) / sizeof(uint32_t)) ); + ESP_ERROR_CHECK( ulp_run(&ulp_entry - RTC_SLOW_MEM) ); .. doxygenfunction:: ulp_run diff --git a/docs/en/api-guides/ulp_instruction_set.rst b/docs/en/api-guides/ulp_instruction_set.rst index bc042ed654..71d35d83a0 100644 --- a/docs/en/api-guides/ulp_instruction_set.rst +++ b/docs/en/api-guides/ulp_instruction_set.rst @@ -1,903 +1,927 @@ -ULP coprocessor instruction set -=============================== - -This document provides details about the instructions used by ESP32 ULP coprocessor assembler. - -ULP coprocessor has 4 16-bit general purpose registers, labeled R0, R1, R2, R3. It also has an 8-bit counter register (stage_cnt) which can be used to implement loops. Stage count regiter is accessed using special instructions. - -ULP coprocessor can access 8k bytes of RTC_SLOW_MEM memory region. Memory is addressed in 32-bit word units. It can also access peripheral registers in RTC_CNTL, RTC_IO, and SENS peripherals. - -All instructions are 32-bit. Jump instructions, ALU instructions, peripheral register and memory access instructions are executed in 1 cycle. Instructions which work with peripherals (TSENS, ADC, I2C) take variable number of cycles, depending on peripheral operation. - -The instruction syntax is case insensitive. Upper and lower case letters can be used and intermixed arbitrarily. This is true both for register names and instruction names. - -Note about addressing ---------------------- -ESP32 ULP coprocessor's JUMP, ST, LD instructions which take register as an argument (jump address, store/load base address) expect the argument to be expressed in 32-bit words. - -Consider the following example program:: - - entry: - NOP - NOP - NOP - NOP - loop: - MOVE R1, loop - JUMP R1 - -When this program is assembled and linked, address of label ``loop`` will be equal to 16 (expressed in bytes). However `JUMP` instruction expects the address stored in register to be expressed in 32-bit words. To account for this common use case, assembler will convert the address of label `loop` from bytes to words, when generating ``MOVE`` instruction, so the code generated code will be equivalent to:: - - 0000 NOP - 0004 NOP - 0008 NOP - 000c NOP - 0010 MOVE R1, 4 - 0014 JUMP R1 - -The other case is when the argument of ``MOVE`` instruction is not a label but a constant. In this case assembler will use the value as is, without any conversion:: - - .set val, 0x10 - MOVE R1, val - -In this case, value loaded into R1 will be ``0x10``. - -Similar considerations apply to ``LD`` and ``ST`` instructions. Consider the following code:: - - .global array - array: .long 0 - .long 0 - .long 0 - .long 0 - - MOVE R1, array - MOVE R2, 0x1234 - ST R2, R1, 0 // write value of R2 into the first array element, - // i.e. array[0] - - ST R2, R1, 4 // write value of R2 into the second array element - // (4 byte offset), i.e. array[1] - - ADD R1, R1, 2 // this increments address by 2 words (8 bytes) - ST R2, R1, 0 // write value of R2 into the third array element, - // i.e. array[2] - -Note about instruction execution time -------------------------------------- - -ULP coprocessor is clocked from RTC_FAST_CLK, which is normally derived from the internal 8MHz oscillator. Applications which need to know exact ULP clock frequency can calibrate it against the main XTAL clock:: - - #include "soc/rtc.h" - - // calibrate 8M/256 clock against XTAL, get 8M/256 clock period - uint32_t rtc_8md256_period = rtc_clk_cal(RTC_CAL_8MD256, 100); - uint32_t rtc_fast_freq_hz = 1000000ULL * (1 << RTC_CLK_CAL_FRACT) * 256 / rtc_8md256_period; - -ULP coprocessor needs 2 clock cycle to fetch each instuction (fetching is not pipelined), plus certain number of cycles to execute, depending on the instruction. See description of each instruction for details on the execution time. - -Note that when accessing RTC memories and RTC registers, ULP coprocessor has lower priority than the main CPUs. This means that ULP coprocessor execution may be suspended while the main CPUs access same memory region as the ULP. - - -**NOP** - no operation ----------------------- - -**Syntax** - **NOP** -**Operands** - None -**Cycles** - 2 (fetch) + 1 (execute) -**Description** - No operation is performed. Only the PC is incremented. - -**Example**:: - - 1: NOP - - -**ADD** - Add to register -------------------------- - -**Syntax** - **ADD** *Rdst, Rsrc1, Rsrc2* - - **ADD** *Rdst, Rsrc1, imm* - - -**Operands** - - *Rdst* - Register R[0..3] - - *Rsrc1* - Register R[0..3] - - *Rsrc2* - Register R[0..3] - - *Imm* - 16-bit signed value - -**Cycles** - 2 (fetch) + 2 (execute) - -**Description** - The instruction adds source register to another source register or to a 16-bit signed value and stores result to the destination register. - -**Examples**:: - - 1: ADD R1, R2, R3 //R1 = R2 + R3 - - 2: Add R1, R2, 0x1234 //R1 = R2 + 0x1234 - - 3: .set value1, 0x03 //constant value1=0x03 - Add R1, R2, value1 //R1 = R2 + value1 - - - 4: .global label //declaration of variable label - Add R1, R2, label //R1 = R2 + label - ... - label: nop //definition of variable label - - -**SUB** - Subtract from register --------------------------------- - -**Syntax** - **SUB** *Rdst, Rsrc1, Rsrc2* - - **SUB** *Rdst, Rsrc1, imm* - -**Operands** - - *Rdst* - Register R[0..3] - - *Rsrc1* - Register R[0..3] - - *Rsrc2* - Register R[0..3] - - *Imm* - 16-bit signed value - -**Cycles** - 2 (fetch) + 2 (execute) - -**Description** - The instruction subtracts the source register from another source register or subtracts 16-bit signed value from a source register, and stores result to the destination register. - -**Examples**:: - - 1: SUB R1, R2, R3 //R1 = R2 - R3 - - 2: sub R1, R2, 0x1234 //R1 = R2 - 0x1234 - - 3: .set value1, 0x03 //constant value1=0x03 - SUB R1, R2, value1 //R1 = R2 - value1 - 4: .global label //declaration of variable label - SUB R1, R2, label //R1 = R2 - label - .... - label: nop //definition of variable label - - -**AND** - Logical AND of two operands -------------------------------------- - -**Syntax** - **AND** *Rdst, Rsrc1, Rsrc2* - - **AND** *Rdst, Rsrc1, imm* - -**Operands** - - *Rdst* - Register R[0..3] - - *Rsrc1* - Register R[0..3] - - *Rsrc2* - Register R[0..3] - - *Imm* - 16-bit signed value - -**Cycles** - 2 (fetch) + 2 (execute) - -**Description** - The instruction does logical AND of a source register and another source register or 16-bit signed value and stores result to the destination register. - -**Examples**:: - - 1: AND R1, R2, R3 //R1 = R2 & R3 - - 2: AND R1, R2, 0x1234 //R1 = R2 & 0x1234 - - 3: .set value1, 0x03 //constant value1=0x03 - AND R1, R2, value1 //R1 = R2 & value1 - - 4: .global label //declaration of variable label - AND R1, R2, label //R1 = R2 & label - ... - label: nop //definition of variable label - - -**OR** - Logical OR of two operands ------------------------------------ - -**Syntax** - **OR** *Rdst, Rsrc1, Rsrc2* - - **OR** *Rdst, Rsrc1, imm* - -**Operands** - - *Rdst* - Register R[0..3] - - *Rsrc1* - Register R[0..3] - - *Rsrc2* - Register R[0..3] - - *Imm* - 16-bit signed value - -**Cycles** - 2 (fetch) + 2 (execute) - -**Description** - The instruction does logical OR of a source register and another source register or 16-bit signed value and stores result to the destination register. - -**Examples**:: - - 1: OR R1, R2, R3 //R1 = R2 \| R3 - - 2: OR R1, R2, 0x1234 //R1 = R2 \| 0x1234 - - 3: .set value1, 0x03 //constant value1=0x03 - OR R1, R2, value1 //R1 = R2 \| value1 - - 4: .global label //declaration of variable label - OR R1, R2, label //R1 = R2 \|label - ... - label: nop //definition of variable label - - - -**LSH** - Logical Shift Left ----------------------------- - -**Syntax** - **LSH** *Rdst, Rsrc1, Rsrc2* - - **LSH** *Rdst, Rsrc1, imm* - -**Operands** - - *Rdst* - Register R[0..3] - - *Rsrc1* - Register R[0..3] - - *Rsrc2* - Register R[0..3] - - *Imm* - 16-bit signed value - -**Cycles** - 2 (fetch) + 2 (execute) - -**Description** - The instruction does logical shift to left of source register to number of bits from another source register or 16-bit signed value and store result to the destination register. - -**Examples**:: - - 1: LSH R1, R2, R3 //R1 = R2 << R3 - - 2: LSH R1, R2, 0x03 //R1 = R2 << 0x03 - - 3: .set value1, 0x03 //constant value1=0x03 - LSH R1, R2, value1 //R1 = R2 << value1 - - 4: .global label //declaration of variable label - LSH R1, R2, label //R1 = R2 << label - ... - label: nop //definition of variable label - - -**RSH** - Logical Shift Right ------------------------------ - -**Syntax** - **RSH** *Rdst, Rsrc1, Rsrc2* - - **RSH** *Rdst, Rsrc1, imm* - -**Operands** - *Rdst* - Register R[0..3] - *Rsrc1* - Register R[0..3] - *Rsrc2* - Register R[0..3] - *Imm* - 16-bit signed value - -**Cycles** - 2 (fetch) + 2 (execute) - -**Description** - The instruction does logical shift to right of source register to number of bits from another source register or 16-bit signed value and store result to the destination register. - -**Examples**:: - - 1: RSH R1, R2, R3 //R1 = R2 >> R3 - - 2: RSH R1, R2, 0x03 //R1 = R2 >> 0x03 - - 3: .set value1, 0x03 //constant value1=0x03 - RSH R1, R2, value1 //R1 = R2 >> value1 - - 4: .global label //declaration of variable label - RSH R1, R2, label //R1 = R2 >> label - label: nop //definition of variable label - - - -**MOVE** – Move to register ---------------------------- - -**Syntax** - **MOVE** *Rdst, Rsrc* - - **MOVE** *Rdst, imm* - -**Operands** - - *Rdst* – Register R[0..3] - - *Rsrc* – Register R[0..3] - - *Imm* – 16-bit signed value - -**Cycles** - 2 (fetch) + 2 (execute) - -**Description** - The instruction move to destination register value from source register or 16-bit signed value. - - Note that when a label is used as an immediate, the address of the label will be converted from bytes to words. This is because LD, ST, and JUMP instructions expect the address register value to be expressed in words rather than bytes. To avoid using an extra instruction - - -**Examples**:: - - 1: MOVE R1, R2 //R1 = R2 >> R3 - - 2: MOVE R1, 0x03 //R1 = R2 >> 0x03 - - 3: .set value1, 0x03 //constant value1=0x03 - MOVE R1, value1 //R1 = value1 - - 4: .global label //declaration of label - MOVE R1, label //R1 = address_of(label) / 4 - ... - label: nop //definition of label - - -**ST** – Store data to the memory ---------------------------------- - -**Syntax** - **ST** *Rsrc, Rdst, offset* - -**Operands** - - *Rsrc* – Register R[0..3], holds the 16-bit value to store - - *Rdst* – Register R[0..3], address of the destination, in 32-bit words - - *Offset* – 10-bit signed value, offset in bytes - -**Cycles** - 2 (fetch) + 4 (execute) - -**Description** - The instruction stores the 16-bit value of Rsrc to the lower half-word of memory with address Rdst+offset. The upper half-word is written with the current program counter (PC), expressed in words, shifted left by 5 bits:: - - Mem[Rdst + offset / 4]{31:0} = {PC[10:0], 5'b0, Rsrc[15:0]} - - The application can use higher 16 bits to determine which instruction in the ULP program has written any particular word into memory. - -**Examples**:: - - 1: ST R1, R2, 0x12 //MEM[R2+0x12] = R1 - - 2: .data //Data section definition - Addr1: .word 123 // Define label Addr1 16 bit - .set offs, 0x00 // Define constant offs - .text //Text section definition - MOVE R1, 1 // R1 = 1 - MOVE R2, Addr1 // R2 = Addr1 - ST R1, R2, offs // MEM[R2 + 0] = R1 - // MEM[Addr1 + 0] will be 32'h600001 - - -**LD** – Load data from the memory ----------------------------------- - -**Syntax** - **LD** *Rdst, Rsrc, offset* - -**Operands** - *Rdst* – Register R[0..3], destination - - *Rsrc* – Register R[0..3], holds address of destination, in 32-bit words - - *Offset* – 10-bit signed value, offset in bytes - -**Cycles** - 2 (fetch) + 4 (execute) - -**Description** - The instruction loads lower 16-bit half-word from memory with address Rsrc+offset into the destination register Rdst:: - - Rdst[15:0] = Mem[Rsrc + offset / 4][15:0] - -**Examples**:: - - 1: LD R1, R2, 0x12 //R1 = MEM[R2+0x12] - - 2: .data //Data section definition - Addr1: .word 123 // Define label Addr1 16 bit - .set offs, 0x00 // Define constant offs - .text //Text section definition - MOVE R1, 1 // R1 = 1 - MOVE R2, Addr1 // R2 = Addr1 / 4 (address of label is converted into words) - LD R1, R2, offs // R1 = MEM[R2 + 0] - // R1 will be 123 - - - - -**JUMP** – Jump to an absolute address --------------------------------------- - -**Syntax** - **JUMP** *Rdst* - - **JUMP** *ImmAddr* - - **JUMP** *Rdst, Condition* - - **JUMP** *ImmAddr, Condition* - - -**Operands** - - *Rdst* – Register R[0..3] containing address to jump to (expressed in 32-bit words) - - - *ImmAddr* – 13 bits address (expressed in bytes), aligned to 4 bytes - - - *Condition*: - - EQ – jump if last ALU operation result was zero - - OV – jump if last ALU has set overflow flag - -**Cycles** - 2 (fetch) + 2 (execute) - -**Description** - The instruction makes jump to the specified address. Jump can be either unconditional or based on an ALU flag. - -**Examples**:: - - 1: JUMP R1 // Jump to address in R1 (address in R1 is in 32-bit words) - - 2: JUMP 0x120, EQ // Jump to address 0x120 (in bytes) if ALU result is zero - - 3: JUMP label // Jump to label - ... - label: nop // Definition of label - - 4: .global label // Declaration of global label - - MOVE R1, label // R1 = label (value loaded into R1 is in words) - JUMP R1 // Jump to label - ... - label: nop // Definition of label - - - -**JUMPR** – Jump to a relative offset (condition based on R0) -------------------------------------------------------------- - -**Syntax** - **JUMPR** *Step, Threshold, Condition* - -**Operands** - - *Step* – relative shift from current position, in bytes - - *Threshold* – threshold value for branch condition - - *Condition*: - - *GE* (greater or equal) – jump if value in R0 >= threshold - - - *LT* (less than) – jump if value in R0 < threshold - -**Cycles** - 2 (fetch) + 2 (execute) - -**Description** - The instruction makes a jump to a relative address if condition is true. Condition is the result of comparison of R0 register value and the threshold value. - -**Examples**:: - - 1:pos: JUMPR 16, 20, GE // Jump to address (position + 16 bytes) if value in R0 >= 20 - - 2: // Down counting loop using R0 register - MOVE R0, 16 // load 16 into R0 - label: SUB R0, R0, 1 // R0-- - NOP // do something - JUMPR label, 1, GE // jump to label if R0 >= 1 - - - -**JUMPS** – Jump to a relative address (condition based on stage count) ------------------------------------------------------------------------ - -**Syntax** - **JUMPS** *Step, Threshold, Condition* - -**Operands** - - *Step* – relative shift from current position, in bytes - - *Threshold* – threshold value for branch condition - - *Condition*: - - *EQ* (equal) – jump if value in stage_cnt == threshold - - *LT* (less than) – jump if value in stage_cnt < threshold - - *GT* (greater than) – jump if value in stage_cnt > threshold - -**Cycles** - 2 (fetch) + 2 (execute) - -**Description** - The instruction makes a jump to a relative address if condition is true. Condition is the result of comparison of count register value and threshold value. - -**Examples**:: - - 1:pos: JUMPS 16, 20, EQ // Jump to (position + 16 bytes) if stage_cnt == 20 - - 2: // Up counting loop using stage count register - STAGE_RST // set stage_cnt to 0 - label: STAGE_INC 1 // stage_cnt++ - NOP // do something - JUMPS label, 16, LT // jump to label if stage_cnt < 16 - - - -**STAGE_RST** – Reset stage count register ------------------------------------------- -**Syntax** - **STAGE_RST** - -**Operands** - No operands - -**Description** - The instruction sets the stage count register to 0 - -**Cycles** - 2 (fetch) + 2 (execute) - -**Examples**:: - - 1: STAGE_RST // Reset stage count register - - - -**STAGE_INC** – Increment stage count register ----------------------------------------------- - -**Syntax** - **STAGE_INC** *Value* - -**Operands** - - *Value* – 8 bits value - -**Cycles** - 2 (fetch) + 2 (execute) - -**Description** - The instruction increments stage count register by given value. - -**Examples**:: - - 1: STAGE_INC 10 // stage_cnt += 10 - - 2: // Up counting loop example: - STAGE_RST // set stage_cnt to 0 - label: STAGE_INC 1 // stage_cnt++ - NOP // do something - JUMPS label, 16, LT // jump to label if stage_cnt < 16 - - -**STAGE_DEC** – Decrement stage count register ----------------------------------------------- - -**Syntax** - **STAGE_DEC** *Value* - -**Operands** - - *Value* – 8 bits value - -**Cycles** - 2 (fetch) + 2 (execute) - -**Description** - The instruction decrements stage count register by given value. - -**Examples**:: - - 1: STAGE_DEC 10 // stage_cnt -= 10; - - 2: // Down counting loop exaple - STAGE_RST // set stage_cnt to 0 - STAGE_INC 16 // increment stage_cnt to 16 - label: STAGE_DEC 1 // stage_cnt--; - NOP // do something - JUMPS label, 0, GT // jump to label if stage_cnt > 0 - - -**HALT** – End the program --------------------------- - -**Syntax** - **HALT** - -**Operands** - No operands - -**Cycles** - 2 (fetch) + 2 (execute) - -**Description** - The instruction halts the ULP coprocessor and restarts ULP wakeup timer, if it is enabled. - -**Examples**:: - - 1: HALT // Halt the coprocessor - - - -**WAKE** – Wake up the chip ---------------------------- - -**Syntax** - **WAKE** - -**Operands** - No operands - -**Cycles** - 2 (fetch) + 2 (execute) - -**Description** - The instruction sends an interrupt from ULP to RTC controller. - - - If the SoC is in deep sleep mode, and ULP wakeup is enabled, this causes the SoC to wake up. - - - If the SoC is not in deep sleep mode, and ULP interrupt bit (RTC_CNTL_ULP_CP_INT_ENA) is set in RTC_CNTL_INT_ENA_REG register, RTC interrupt will be triggered. - - Note that before using WAKE instruction, ULP program may needs to wait until RTC controller is ready to wake up the main CPU. This is indicated using RTC_CNTL_RDY_FOR_WAKEUP bit of RTC_CNTL_LOW_POWER_ST_REG register. If WAKE instruction is executed while RTC_CNTL_RDY_FOR_WAKEUP is zero, it has no effect (wake up does not occur). - -**Examples**:: - - 1: is_rdy_for_wakeup: // Read RTC_CNTL_RDY_FOR_WAKEUP bit - READ_RTC_FIELD(RTC_CNTL_LOW_POWER_ST_REG, RTC_CNTL_RDY_FOR_WAKEUP) - AND r0, r0, 1 - JUMP is_rdy_for_wakeup, eq // Retry until the bit is set - WAKE // Trigger wake up - REG_WR 0x006, 24, 24, 0 // Stop ULP timer (clear RTC_CNTL_ULP_CP_SLP_TIMER_EN) - HALT // Stop the ULP program - // After these instructions, SoC will wake up, - // and ULP will not run again until started by the main program. - - - -**SLEEP** – set ULP wakeup timer period ---------------------------------------- - -**Syntax** - **SLEEP** *sleep_reg* - -**Operands** - - *sleep_reg* – 0..4, selects one of ``SENS_ULP_CP_SLEEP_CYCx_REG`` registers. - -**Cycles** - 2 (fetch) + 2 (execute) - -**Description** - The instruction selects which of the ``SENS_ULP_CP_SLEEP_CYCx_REG`` (x = 0..4) register values is to be used by the ULP wakeup timer as wakeup period. By default, the value from ``SENS_ULP_CP_SLEEP_CYC0_REG`` is used. - -**Examples**:: - - 1: SLEEP 1 // Use period set in SENS_ULP_CP_SLEEP_CYC1_REG - - 2: .set sleep_reg, 4 // Set constant - SLEEP sleep_reg // Use period set in SENS_ULP_CP_SLEEP_CYC4_REG - - -**WAIT** – wait some number of cycles -------------------------------------- - -**Syntax** - **WAIT** *Cycles* - -**Operands** - - *Cycles* – number of cycles for wait - -**Cycles** - 2 (fetch) + *Cycles* (execute) - -**Description** - The instruction delays for given number of cycles. - -**Examples**:: - - 1: WAIT 10 // Do nothing for 10 cycles - - 2: .set wait_cnt, 10 // Set a constant - WAIT wait_cnt // wait for 10 cycles - - - - -**TSENS** – do measurement with temperature sensor --------------------------------------------------- - -**Syntax** - - **TSENS** *Rdst, Wait_Delay* - -**Operands** - - *Rdst* – Destination Register R[0..3], result will be stored to this register - - *Wait_Delay* – number of cycles used to perform the measurement - -**Cycles** - 2 (fetch) + *Wait_Delay* + 3 * TSENS_CLK - -**Description** - The instruction performs measurement using TSENS and stores the result into a general purpose register. - -**Examples**:: - - 1: TSENS R1, 1000 // Measure temperature sensor for 1000 cycles, - // and store result to R1 - - - - -**ADC** – do measurement with ADC ---------------------------------- - -**Syntax** - - **ADC** *Rdst, Sar_sel, Mux* - - - **ADC** *Rdst, Sar_sel, Mux, 0* — deprecated form - -**Operands** - - *Rdst* – Destination Register R[0..3], result will be stored to this register - - *Sar_sel* – Select ADC: 0 = SARADC1, 1 = SARADC2 - - *Mux* - selected PAD, SARADC Pad[Mux+1] is enabled - -**Cycles** - 2 (fetch) + 21 + max(1, SAR_AMP_WAIT1) + max(1, SAR_AMP_WAIT2) + max(1, SAR_AMP_WAIT3) + SARx_SAMPLE_CYCLE + SARx_SAMPLE_BIT - -**Description** - The instruction makes measurements from ADC. - -**Examples**:: - - 1: ADC R1, 0, 1 // Measure value using ADC1 pad 2 and store result into R1 - -**I2C_RD** - read single byte from I2C slave ----------------------------------------------- - -**Syntax** - - **I2C_RD** *Sub_addr, High, Low, Slave_sel* - -**Operands** - - *Sub_addr* – Address within the I2C slave to read. - - *High*, *Low* — Define range of bits to read. Bits outside of [High, Low] range are masked. - - *Slave_sel* - Index of I2C slave address to use. - -**Cycles** - 2 (fetch) + I2C communication time - -**Description** - ``I2C_RD`` instruction reads one byte from I2C slave with index ``Slave_sel``. Slave address (in 7-bit format) has to be set in advance into `SENS_I2C_SLAVE_ADDRx` register field, where ``x == Slave_sel``. - 8 bits of read result is stored into `R0` register. - -**Examples**:: - - 1: I2C_RD 0x10, 7, 0, 0 // Read byte from sub-address 0x10 of slave with address set in SENS_I2C_SLAVE_ADDR0 - - -**I2C_WR** - write single byte to I2C slave ----------------------------------------------- - -**Syntax** - - **I2C_WR** *Sub_addr, Value, High, Low, Slave_sel* - -**Operands** - - *Sub_addr* – Address within the I2C slave to write. - - *Value* – 8-bit value to be written. - - *High*, *Low* — Define range of bits to write. Bits outside of [High, Low] range are masked. - - *Slave_sel* - Index of I2C slave address to use. - -**Cycles** - 2 (fetch) + I2C communication time - -**Description** - ``I2C_WR`` instruction writes one byte to I2C slave with index ``Slave_sel``. Slave address (in 7-bit format) has to be set in advance into `SENS_I2C_SLAVE_ADDRx` register field, where ``x == Slave_sel``. - -**Examples**:: - - 1: I2C_WR 0x20, 0x33, 7, 0, 1 // Write byte 0x33 to sub-address 0x20 of slave with address set in SENS_I2C_SLAVE_ADDR1. - - -**REG_RD** – read from peripheral register ------------------------------------------- - -**Syntax** - **REG_RD** *Addr, High, Low* - -**Operands** - - *Addr* – register address, in 32-bit words - - *High* – High part of R0 - - *Low* – Low part of R0 - -**Cycles** - 2 (fetch) + 6 (execute) - -**Description** - The instruction reads up to 16 bits from a peripheral register into a general purpose register: ``R0 = REG[Addr][High:Low]``. - - This instruction can access registers in RTC_CNTL, RTC_IO, SENS, and RTC_I2C peripherals. Address of the the register, as seen from the ULP, - can be calculated from the address of the same register on the DPORT bus as follows:: - - addr_ulp = (addr_dport - DR_REG_RTCCNTL_BASE) / 4 - -**Examples**:: - - 1: REG_RD 0x120, 2, 0 // load 4 bits: R0 = {12'b0, REG[0x120][7:4]} - - -**REG_WR** – write to peripheral register ------------------------------------------ - -**Syntax** - **REG_WR** *Addr, High, Low, Data* - -**Operands** - - *Addr* – register address, in 32-bit words. - - *High* – High part of R0 - - *Low* – Low part of R0 - - *Data* – value to write, 8 bits - -**Cycles** - 2 (fetch) + 10 (execute) - -**Description** - The instruction writes up to 8 bits from a general purpose register into a peripheral register. ``REG[Addr][High:Low] = data`` - - This instruction can access registers in RTC_CNTL, RTC_IO, SENS, and RTC_I2C peripherals. Address of the the register, as seen from the ULP, - can be calculated from the address of the same register on the DPORT bus as follows:: - - addr_ulp = (addr_dport - DR_REG_RTCCNTL_BASE) / 4 - -**Examples**:: - - 1: REG_WR 0x120, 7, 0, 0x10 // set 8 bits: REG[0x120][7:0] = 0x10 - -Convenience macros for peripheral registers access --------------------------------------------------- - -ULP source files are passed through C preprocessor before the assembler. This allows certain macros to be used to facilitate access to peripheral registers. - -Some existing macros are defined in ``soc/soc_ulp.h`` header file. These macros allow access to the fields of peripheral registers by their names. -Peripheral registers names which can be used with these macros are the ones defined in ``soc/rtc_cntl_reg.h``, ``soc/rtc_io_reg.h``, ``soc/sens_reg.h``, and ``soc/rtc_i2c_reg.h``. - -READ_RTC_REG(rtc_reg, low_bit, bit_width) - Read up to 16 bits from rtc_reg[low_bit + bit_width - 1 : low_bit] into R0. For example:: - - #include "soc/soc_ulp.h" - #include "soc/rtc_cntl_reg.h" - - /* Read 16 lower bits of RTC_CNTL_TIME0_REG into R0 */ - READ_RTC_REG(RTC_CNTL_TIME0_REG, 0, 16) - -READ_RTC_FIELD(rtc_reg, field) - Read from a field in rtc_reg into R0, up to 16 bits. For example:: - - #include "soc/soc_ulp.h" - #include "soc/sens_reg.h" - - /* Read 8-bit SENS_TSENS_OUT field of SENS_SAR_SLAVE_ADDR3_REG into R0 */ - READ_RTC_FIELD(SENS_SAR_SLAVE_ADDR3_REG, SENS_TSENS_OUT) - -WRITE_RTC_REG(rtc_reg, low_bit, bit_width, value) - Write immediate value into rtc_reg[low_bit + bit_width - 1 : low_bit], bit_width <= 8. For example:: - - #include "soc/soc_ulp.h" - #include "soc/rtc_io_reg.h" - - /* Set BIT(2) of RTC_GPIO_OUT_DATA_W1TS field in RTC_GPIO_OUT_W1TS_REG */ - WRITE_RTC_REG(RTC_GPIO_OUT_W1TS_REG, RTC_GPIO_OUT_DATA_W1TS_S + 2, 1, 1) - - -WRITE_RTC_FIELD(rtc_reg, field, value) - Write immediate value into a field in rtc_reg, up to 8 bits. For example:: - - #include "soc/soc_ulp.h" - #include "soc/rtc_cntl_reg.h" - - /* Set RTC_CNTL_ULP_CP_SLP_TIMER_EN field of RTC_CNTL_STATE0_REG to 0 */ - WRITE_RTC_FIELD(RTC_CNTL_STATE0_REG, RTC_CNTL_ULP_CP_SLP_TIMER_EN, 0) - - - - - - +ULP coprocessor instruction set +=============================== + +This document provides details about the instructions used by ESP32 ULP coprocessor assembler. + +ULP coprocessor has 4 16-bit general purpose registers, labeled R0, R1, R2, R3. It also has an 8-bit counter register (stage_cnt) which can be used to implement loops. Stage count regiter is accessed using special instructions. + +ULP coprocessor can access 8k bytes of RTC_SLOW_MEM memory region. Memory is addressed in 32-bit word units. It can also access peripheral registers in RTC_CNTL, RTC_IO, and SENS peripherals. + +All instructions are 32-bit. Jump instructions, ALU instructions, peripheral register and memory access instructions are executed in 1 cycle. Instructions which work with peripherals (TSENS, ADC, I2C) take variable number of cycles, depending on peripheral operation. + +The instruction syntax is case insensitive. Upper and lower case letters can be used and intermixed arbitrarily. This is true both for register names and instruction names. + +Note about addressing +--------------------- +ESP32 ULP coprocessor's JUMP, ST, LD instructions which take register as an argument (jump address, store/load base address) expect the argument to be expressed in 32-bit words. + +Consider the following example program:: + + entry: + NOP + NOP + NOP + NOP + loop: + MOVE R1, loop + JUMP R1 + +When this program is assembled and linked, address of label ``loop`` will be equal to 16 (expressed in bytes). However `JUMP` instruction expects the address stored in register to be expressed in 32-bit words. To account for this common use case, assembler will convert the address of label `loop` from bytes to words, when generating ``MOVE`` instruction, so the code generated code will be equivalent to:: + + 0000 NOP + 0004 NOP + 0008 NOP + 000c NOP + 0010 MOVE R1, 4 + 0014 JUMP R1 + +The other case is when the argument of ``MOVE`` instruction is not a label but a constant. In this case assembler will use the value as is, without any conversion:: + + .set val, 0x10 + MOVE R1, val + +In this case, value loaded into R1 will be ``0x10``. + +Similar considerations apply to ``LD`` and ``ST`` instructions. Consider the following code:: + + .global array + array: .long 0 + .long 0 + .long 0 + .long 0 + + MOVE R1, array + MOVE R2, 0x1234 + ST R2, R1, 0 // write value of R2 into the first array element, + // i.e. array[0] + + ST R2, R1, 4 // write value of R2 into the second array element + // (4 byte offset), i.e. array[1] + + ADD R1, R1, 2 // this increments address by 2 words (8 bytes) + ST R2, R1, 0 // write value of R2 into the third array element, + // i.e. array[2] + +Note about instruction execution time +------------------------------------- + +ULP coprocessor is clocked from RTC_FAST_CLK, which is normally derived from the internal 8MHz oscillator. Applications which need to know exact ULP clock frequency can calibrate it against the main XTAL clock:: + + #include "soc/rtc.h" + + // calibrate 8M/256 clock against XTAL, get 8M/256 clock period + uint32_t rtc_8md256_period = rtc_clk_cal(RTC_CAL_8MD256, 100); + uint32_t rtc_fast_freq_hz = 1000000ULL * (1 << RTC_CLK_CAL_FRACT) * 256 / rtc_8md256_period; + +ULP coprocessor needs certain number of clock cycles to fetch each instuction, plus certain number of cycles to execute it, depending on the instruction. See description of each instruction below for details on the execution time. + +Instruction fetch time is: + +- 2 clock cycles — for instructions following ALU and branch instructions. +- 4 clock cycles — in other cases. + +Note that when accessing RTC memories and RTC registers, ULP coprocessor has lower priority than the main CPUs. This means that ULP coprocessor execution may be suspended while the main CPUs access same memory region as the ULP. + + +**NOP** - no operation +---------------------- + +**Syntax** + **NOP** +**Operands** + None +**Cycles** + 2 cycle to execute, 4 cycles to fetch next instruction +**Description** + No operation is performed. Only the PC is incremented. + +**Example**:: + + 1: NOP + + +**ADD** - Add to register +------------------------- + +**Syntax** + **ADD** *Rdst, Rsrc1, Rsrc2* + + **ADD** *Rdst, Rsrc1, imm* + + +**Operands** + - *Rdst* - Register R[0..3] + - *Rsrc1* - Register R[0..3] + - *Rsrc2* - Register R[0..3] + - *Imm* - 16-bit signed value + +**Cycles** + 2 cycles to execute, 4 cycles to fetch next instruction + +**Description** + The instruction adds source register to another source register or to a 16-bit signed value and stores result to the destination register. + +**Examples**:: + + 1: ADD R1, R2, R3 //R1 = R2 + R3 + + 2: Add R1, R2, 0x1234 //R1 = R2 + 0x1234 + + 3: .set value1, 0x03 //constant value1=0x03 + Add R1, R2, value1 //R1 = R2 + value1 + + + 4: .global label //declaration of variable label + Add R1, R2, label //R1 = R2 + label + ... + label: nop //definition of variable label + + +**SUB** - Subtract from register +-------------------------------- + +**Syntax** + **SUB** *Rdst, Rsrc1, Rsrc2* + + **SUB** *Rdst, Rsrc1, imm* + +**Operands** + - *Rdst* - Register R[0..3] + - *Rsrc1* - Register R[0..3] + - *Rsrc2* - Register R[0..3] + - *Imm* - 16-bit signed value + +**Cycles** + 2 cycles to execute, 4 cycles to fetch next instruction + +**Description** + The instruction subtracts the source register from another source register or subtracts 16-bit signed value from a source register, and stores result to the destination register. + +**Examples**:: + + 1: SUB R1, R2, R3 //R1 = R2 - R3 + + 2: sub R1, R2, 0x1234 //R1 = R2 - 0x1234 + + 3: .set value1, 0x03 //constant value1=0x03 + SUB R1, R2, value1 //R1 = R2 - value1 + 4: .global label //declaration of variable label + SUB R1, R2, label //R1 = R2 - label + .... + label: nop //definition of variable label + + +**AND** - Logical AND of two operands +------------------------------------- + +**Syntax** + **AND** *Rdst, Rsrc1, Rsrc2* + + **AND** *Rdst, Rsrc1, imm* + +**Operands** + - *Rdst* - Register R[0..3] + - *Rsrc1* - Register R[0..3] + - *Rsrc2* - Register R[0..3] + - *Imm* - 16-bit signed value + +**Cycles** + 2 cycles to execute, 4 cycles to fetch next instruction + +**Description** + The instruction does logical AND of a source register and another source register or 16-bit signed value and stores result to the destination register. + +**Examples**:: + + 1: AND R1, R2, R3 //R1 = R2 & R3 + + 2: AND R1, R2, 0x1234 //R1 = R2 & 0x1234 + + 3: .set value1, 0x03 //constant value1=0x03 + AND R1, R2, value1 //R1 = R2 & value1 + + 4: .global label //declaration of variable label + AND R1, R2, label //R1 = R2 & label + ... + label: nop //definition of variable label + + +**OR** - Logical OR of two operands +----------------------------------- + +**Syntax** + **OR** *Rdst, Rsrc1, Rsrc2* + + **OR** *Rdst, Rsrc1, imm* + +**Operands** + - *Rdst* - Register R[0..3] + - *Rsrc1* - Register R[0..3] + - *Rsrc2* - Register R[0..3] + - *Imm* - 16-bit signed value + +**Cycles** + 2 cycles to execute, 4 cycles to fetch next instruction + +**Description** + The instruction does logical OR of a source register and another source register or 16-bit signed value and stores result to the destination register. + +**Examples**:: + + 1: OR R1, R2, R3 //R1 = R2 \| R3 + + 2: OR R1, R2, 0x1234 //R1 = R2 \| 0x1234 + + 3: .set value1, 0x03 //constant value1=0x03 + OR R1, R2, value1 //R1 = R2 \| value1 + + 4: .global label //declaration of variable label + OR R1, R2, label //R1 = R2 \|label + ... + label: nop //definition of variable label + + + +**LSH** - Logical Shift Left +---------------------------- + +**Syntax** + **LSH** *Rdst, Rsrc1, Rsrc2* + + **LSH** *Rdst, Rsrc1, imm* + +**Operands** + - *Rdst* - Register R[0..3] + - *Rsrc1* - Register R[0..3] + - *Rsrc2* - Register R[0..3] + - *Imm* - 16-bit signed value + +**Cycles** + 2 cycles to execute, 4 cycles to fetch next instruction + +**Description** + The instruction does logical shift to left of source register to number of bits from another source register or 16-bit signed value and store result to the destination register. + +**Examples**:: + + 1: LSH R1, R2, R3 //R1 = R2 << R3 + + 2: LSH R1, R2, 0x03 //R1 = R2 << 0x03 + + 3: .set value1, 0x03 //constant value1=0x03 + LSH R1, R2, value1 //R1 = R2 << value1 + + 4: .global label //declaration of variable label + LSH R1, R2, label //R1 = R2 << label + ... + label: nop //definition of variable label + + +**RSH** - Logical Shift Right +----------------------------- + +**Syntax** + **RSH** *Rdst, Rsrc1, Rsrc2* + + **RSH** *Rdst, Rsrc1, imm* + +**Operands** + *Rdst* - Register R[0..3] + *Rsrc1* - Register R[0..3] + *Rsrc2* - Register R[0..3] + *Imm* - 16-bit signed value + +**Cycles** + 2 cycles to execute, 4 cycles to fetch next instruction + +**Description** + The instruction does logical shift to right of source register to number of bits from another source register or 16-bit signed value and store result to the destination register. + +**Examples**:: + + 1: RSH R1, R2, R3 //R1 = R2 >> R3 + + 2: RSH R1, R2, 0x03 //R1 = R2 >> 0x03 + + 3: .set value1, 0x03 //constant value1=0x03 + RSH R1, R2, value1 //R1 = R2 >> value1 + + 4: .global label //declaration of variable label + RSH R1, R2, label //R1 = R2 >> label + label: nop //definition of variable label + + + +**MOVE** – Move to register +--------------------------- + +**Syntax** + **MOVE** *Rdst, Rsrc* + + **MOVE** *Rdst, imm* + +**Operands** + - *Rdst* – Register R[0..3] + - *Rsrc* – Register R[0..3] + - *Imm* – 16-bit signed value + +**Cycles** + 2 cycles to execute, 4 cycles to fetch next instruction + +**Description** + The instruction move to destination register value from source register or 16-bit signed value. + + Note that when a label is used as an immediate, the address of the label will be converted from bytes to words. This is because LD, ST, and JUMP instructions expect the address register value to be expressed in words rather than bytes. To avoid using an extra instruction + + +**Examples**:: + + 1: MOVE R1, R2 //R1 = R2 >> R3 + + 2: MOVE R1, 0x03 //R1 = R2 >> 0x03 + + 3: .set value1, 0x03 //constant value1=0x03 + MOVE R1, value1 //R1 = value1 + + 4: .global label //declaration of label + MOVE R1, label //R1 = address_of(label) / 4 + ... + label: nop //definition of label + + +**ST** – Store data to the memory +--------------------------------- + +**Syntax** + **ST** *Rsrc, Rdst, offset* + +**Operands** + - *Rsrc* – Register R[0..3], holds the 16-bit value to store + - *Rdst* – Register R[0..3], address of the destination, in 32-bit words + - *Offset* – 10-bit signed value, offset in bytes + +**Cycles** + 4 cycles to execute, 4 cycles to fetch next instruction + +**Description** + The instruction stores the 16-bit value of Rsrc to the lower half-word of memory with address Rdst+offset. The upper half-word is written with the current program counter (PC), expressed in words, shifted left by 5 bits:: + + Mem[Rdst + offset / 4]{31:0} = {PC[10:0], 5'b0, Rsrc[15:0]} + + The application can use higher 16 bits to determine which instruction in the ULP program has written any particular word into memory. + +**Examples**:: + + 1: ST R1, R2, 0x12 //MEM[R2+0x12] = R1 + + 2: .data //Data section definition + Addr1: .word 123 // Define label Addr1 16 bit + .set offs, 0x00 // Define constant offs + .text //Text section definition + MOVE R1, 1 // R1 = 1 + MOVE R2, Addr1 // R2 = Addr1 + ST R1, R2, offs // MEM[R2 + 0] = R1 + // MEM[Addr1 + 0] will be 32'h600001 + + +**LD** – Load data from the memory +---------------------------------- + +**Syntax** + **LD** *Rdst, Rsrc, offset* + +**Operands** + *Rdst* – Register R[0..3], destination + + *Rsrc* – Register R[0..3], holds address of destination, in 32-bit words + + *Offset* – 10-bit signed value, offset in bytes + +**Cycles** + 4 cycles to execute, 4 cycles to fetch next instruction + +**Description** + The instruction loads lower 16-bit half-word from memory with address Rsrc+offset into the destination register Rdst:: + + Rdst[15:0] = Mem[Rsrc + offset / 4][15:0] + +**Examples**:: + + 1: LD R1, R2, 0x12 //R1 = MEM[R2+0x12] + + 2: .data //Data section definition + Addr1: .word 123 // Define label Addr1 16 bit + .set offs, 0x00 // Define constant offs + .text //Text section definition + MOVE R1, 1 // R1 = 1 + MOVE R2, Addr1 // R2 = Addr1 / 4 (address of label is converted into words) + LD R1, R2, offs // R1 = MEM[R2 + 0] + // R1 will be 123 + + + + +**JUMP** – Jump to an absolute address +-------------------------------------- + +**Syntax** + **JUMP** *Rdst* + + **JUMP** *ImmAddr* + + **JUMP** *Rdst, Condition* + + **JUMP** *ImmAddr, Condition* + + +**Operands** + - *Rdst* – Register R[0..3] containing address to jump to (expressed in 32-bit words) + + - *ImmAddr* – 13 bits address (expressed in bytes), aligned to 4 bytes + + - *Condition*: + - EQ – jump if last ALU operation result was zero + - OV – jump if last ALU has set overflow flag + +**Cycles** + 2 cycles to execute, 2 cycles to fetch next instruction + +**Description** + The instruction makes jump to the specified address. Jump can be either unconditional or based on an ALU flag. + +**Examples**:: + + 1: JUMP R1 // Jump to address in R1 (address in R1 is in 32-bit words) + + 2: JUMP 0x120, EQ // Jump to address 0x120 (in bytes) if ALU result is zero + + 3: JUMP label // Jump to label + ... + label: nop // Definition of label + + 4: .global label // Declaration of global label + + MOVE R1, label // R1 = label (value loaded into R1 is in words) + JUMP R1 // Jump to label + ... + label: nop // Definition of label + + + +**JUMPR** – Jump to a relative offset (condition based on R0) +------------------------------------------------------------- + +**Syntax** + **JUMPR** *Step, Threshold, Condition* + +**Operands** + - *Step* – relative shift from current position, in bytes + - *Threshold* – threshold value for branch condition + - *Condition*: + - *GE* (greater or equal) – jump if value in R0 >= threshold + + - *LT* (less than) – jump if value in R0 < threshold + +**Cycles** + 2 cycles to execute, 2 cycles to fetch next instruction + +**Description** + The instruction makes a jump to a relative address if condition is true. Condition is the result of comparison of R0 register value and the threshold value. + +**Examples**:: + + 1:pos: JUMPR 16, 20, GE // Jump to address (position + 16 bytes) if value in R0 >= 20 + + 2: // Down counting loop using R0 register + MOVE R0, 16 // load 16 into R0 + label: SUB R0, R0, 1 // R0-- + NOP // do something + JUMPR label, 1, GE // jump to label if R0 >= 1 + + + +**JUMPS** – Jump to a relative address (condition based on stage count) +----------------------------------------------------------------------- + +**Syntax** + **JUMPS** *Step, Threshold, Condition* + +**Operands** + - *Step* – relative shift from current position, in bytes + - *Threshold* – threshold value for branch condition + - *Condition*: + - *EQ* (equal) – jump if value in stage_cnt == threshold + - *LT* (less than) – jump if value in stage_cnt < threshold + - *LE* (less or equal) - jump if value in stage_cnt <= threshold + - *GT* (greater than) – jump if value in stage_cnt > threshold + - *GE* (greater or equal) — jump if value in stage_cnt >= threshold + +**Cycles** + Conditions *LE*, *LT*, *GE*: 2 cycles to execute, 2 cycles to fetch next instruction + + Conditions *EQ*, *GT* are implemented in the assembler using two **JUMPS** instructions:: + + // JUMPS target, threshold, EQ is implemented as: + + JUMPS next, threshold, LT + JUMPS target, threshold, LE + next: + + // JUMPS target, threshold, GT is implemented as: + + JUMPS next, threshold, LE + JUMPS target, threshold, GE + next: + + Therefore the execution time will depend on the branches taken: either 2 cycles to execute + 2 cycles to fetch, or 4 cycles to execute + 4 cycles to fetch. + + +**Description** + The instruction makes a jump to a relative address if condition is true. Condition is the result of comparison of count register value and threshold value. + +**Examples**:: + + 1:pos: JUMPS 16, 20, EQ // Jump to (position + 16 bytes) if stage_cnt == 20 + + 2: // Up counting loop using stage count register + STAGE_RST // set stage_cnt to 0 + label: STAGE_INC 1 // stage_cnt++ + NOP // do something + JUMPS label, 16, LT // jump to label if stage_cnt < 16 + + + +**STAGE_RST** – Reset stage count register +------------------------------------------ +**Syntax** + **STAGE_RST** + +**Operands** + No operands + +**Description** + The instruction sets the stage count register to 0 + +**Cycles** + 2 cycles to execute, 4 cycles to fetch next instruction + +**Examples**:: + + 1: STAGE_RST // Reset stage count register + + + +**STAGE_INC** – Increment stage count register +---------------------------------------------- + +**Syntax** + **STAGE_INC** *Value* + +**Operands** + - *Value* – 8 bits value + +**Cycles** + 2 cycles to execute, 4 cycles to fetch next instruction + +**Description** + The instruction increments stage count register by given value. + +**Examples**:: + + 1: STAGE_INC 10 // stage_cnt += 10 + + 2: // Up counting loop example: + STAGE_RST // set stage_cnt to 0 + label: STAGE_INC 1 // stage_cnt++ + NOP // do something + JUMPS label, 16, LT // jump to label if stage_cnt < 16 + + +**STAGE_DEC** – Decrement stage count register +---------------------------------------------- + +**Syntax** + **STAGE_DEC** *Value* + +**Operands** + - *Value* – 8 bits value + +**Cycles** + 2 cycles to execute, 4 cycles to fetch next instruction + +**Description** + The instruction decrements stage count register by given value. + +**Examples**:: + + 1: STAGE_DEC 10 // stage_cnt -= 10; + + 2: // Down counting loop exaple + STAGE_RST // set stage_cnt to 0 + STAGE_INC 16 // increment stage_cnt to 16 + label: STAGE_DEC 1 // stage_cnt--; + NOP // do something + JUMPS label, 0, GT // jump to label if stage_cnt > 0 + + +**HALT** – End the program +-------------------------- + +**Syntax** + **HALT** + +**Operands** + No operands + +**Cycles** + 2 cycles to execute + +**Description** + The instruction halts the ULP coprocessor and restarts ULP wakeup timer, if it is enabled. + +**Examples**:: + + 1: HALT // Halt the coprocessor + + + +**WAKE** – Wake up the chip +--------------------------- + +**Syntax** + **WAKE** + +**Operands** + No operands + +**Cycles** + 2 cycles to execute, 4 cycles to fetch next instruction + +**Description** + The instruction sends an interrupt from ULP to RTC controller. + + - If the SoC is in deep sleep mode, and ULP wakeup is enabled, this causes the SoC to wake up. + + - If the SoC is not in deep sleep mode, and ULP interrupt bit (RTC_CNTL_ULP_CP_INT_ENA) is set in RTC_CNTL_INT_ENA_REG register, RTC interrupt will be triggered. + + Note that before using WAKE instruction, ULP program may needs to wait until RTC controller is ready to wake up the main CPU. This is indicated using RTC_CNTL_RDY_FOR_WAKEUP bit of RTC_CNTL_LOW_POWER_ST_REG register. If WAKE instruction is executed while RTC_CNTL_RDY_FOR_WAKEUP is zero, it has no effect (wake up does not occur). + +**Examples**:: + + 1: is_rdy_for_wakeup: // Read RTC_CNTL_RDY_FOR_WAKEUP bit + READ_RTC_FIELD(RTC_CNTL_LOW_POWER_ST_REG, RTC_CNTL_RDY_FOR_WAKEUP) + AND r0, r0, 1 + JUMP is_rdy_for_wakeup, eq // Retry until the bit is set + WAKE // Trigger wake up + REG_WR 0x006, 24, 24, 0 // Stop ULP timer (clear RTC_CNTL_ULP_CP_SLP_TIMER_EN) + HALT // Stop the ULP program + // After these instructions, SoC will wake up, + // and ULP will not run again until started by the main program. + + + +**SLEEP** – set ULP wakeup timer period +--------------------------------------- + +**Syntax** + **SLEEP** *sleep_reg* + +**Operands** + - *sleep_reg* – 0..4, selects one of ``SENS_ULP_CP_SLEEP_CYCx_REG`` registers. + +**Cycles** + 2 cycles to execute, 4 cycles to fetch next instruction + +**Description** + The instruction selects which of the ``SENS_ULP_CP_SLEEP_CYCx_REG`` (x = 0..4) register values is to be used by the ULP wakeup timer as wakeup period. By default, the value from ``SENS_ULP_CP_SLEEP_CYC0_REG`` is used. + +**Examples**:: + + 1: SLEEP 1 // Use period set in SENS_ULP_CP_SLEEP_CYC1_REG + + 2: .set sleep_reg, 4 // Set constant + SLEEP sleep_reg // Use period set in SENS_ULP_CP_SLEEP_CYC4_REG + + +**WAIT** – wait some number of cycles +------------------------------------- + +**Syntax** + **WAIT** *Cycles* + +**Operands** + - *Cycles* – number of cycles for wait + +**Cycles** + 2 + *Cycles* cycles to execute, 4 cycles to fetch next instruction + +**Description** + The instruction delays for given number of cycles. + +**Examples**:: + + 1: WAIT 10 // Do nothing for 10 cycles + + 2: .set wait_cnt, 10 // Set a constant + WAIT wait_cnt // wait for 10 cycles + + + + +**TSENS** – do measurement with temperature sensor +-------------------------------------------------- + +**Syntax** + - **TSENS** *Rdst, Wait_Delay* + +**Operands** + - *Rdst* – Destination Register R[0..3], result will be stored to this register + - *Wait_Delay* – number of cycles used to perform the measurement + +**Cycles** + 2 + *Wait_Delay* + 3 * TSENS_CLK to execute, 4 cycles to fetch next instruction + +**Description** + The instruction performs measurement using TSENS and stores the result into a general purpose register. + +**Examples**:: + + 1: TSENS R1, 1000 // Measure temperature sensor for 1000 cycles, + // and store result to R1 + + + + +**ADC** – do measurement with ADC +--------------------------------- + +**Syntax** + - **ADC** *Rdst, Sar_sel, Mux* + + - **ADC** *Rdst, Sar_sel, Mux, 0* — deprecated form + +**Operands** + - *Rdst* – Destination Register R[0..3], result will be stored to this register + - *Sar_sel* – Select ADC: 0 = SARADC1, 1 = SARADC2 + - *Mux* - selected PAD, SARADC Pad[Mux+1] is enabled + +**Cycles** + ``23 + max(1, SAR_AMP_WAIT1) + max(1, SAR_AMP_WAIT2) + max(1, SAR_AMP_WAIT3) + SARx_SAMPLE_CYCLE + SARx_SAMPLE_BIT`` cycles to execute, 4 cycles to fetch next instruction + +**Description** + The instruction makes measurements from ADC. + +**Examples**:: + + 1: ADC R1, 0, 1 // Measure value using ADC1 pad 2 and store result into R1 + +**I2C_RD** - read single byte from I2C slave +---------------------------------------------- + +**Syntax** + - **I2C_RD** *Sub_addr, High, Low, Slave_sel* + +**Operands** + - *Sub_addr* – Address within the I2C slave to read. + - *High*, *Low* — Define range of bits to read. Bits outside of [High, Low] range are masked. + - *Slave_sel* - Index of I2C slave address to use. + +**Cycles** + Execution time mostly depends on I2C communication time. 4 cycles to fetch next instruction. + +**Description** + ``I2C_RD`` instruction reads one byte from I2C slave with index ``Slave_sel``. Slave address (in 7-bit format) has to be set in advance into `SENS_I2C_SLAVE_ADDRx` register field, where ``x == Slave_sel``. + 8 bits of read result is stored into `R0` register. + +**Examples**:: + + 1: I2C_RD 0x10, 7, 0, 0 // Read byte from sub-address 0x10 of slave with address set in SENS_I2C_SLAVE_ADDR0 + + +**I2C_WR** - write single byte to I2C slave +---------------------------------------------- + +**Syntax** + - **I2C_WR** *Sub_addr, Value, High, Low, Slave_sel* + +**Operands** + - *Sub_addr* – Address within the I2C slave to write. + - *Value* – 8-bit value to be written. + - *High*, *Low* — Define range of bits to write. Bits outside of [High, Low] range are masked. + - *Slave_sel* - Index of I2C slave address to use. + +**Cycles** + Execution time mostly depends on I2C communication time. 4 cycles to fetch next instruction. + +**Description** + ``I2C_WR`` instruction writes one byte to I2C slave with index ``Slave_sel``. Slave address (in 7-bit format) has to be set in advance into `SENS_I2C_SLAVE_ADDRx` register field, where ``x == Slave_sel``. + +**Examples**:: + + 1: I2C_WR 0x20, 0x33, 7, 0, 1 // Write byte 0x33 to sub-address 0x20 of slave with address set in SENS_I2C_SLAVE_ADDR1. + + +**REG_RD** – read from peripheral register +------------------------------------------ + +**Syntax** + **REG_RD** *Addr, High, Low* + +**Operands** + - *Addr* – register address, in 32-bit words + - *High* – High part of R0 + - *Low* – Low part of R0 + +**Cycles** + 4 cycles to execute, 4 cycles to fetch next instruction + +**Description** + The instruction reads up to 16 bits from a peripheral register into a general purpose register: ``R0 = REG[Addr][High:Low]``. + + This instruction can access registers in RTC_CNTL, RTC_IO, SENS, and RTC_I2C peripherals. Address of the the register, as seen from the ULP, + can be calculated from the address of the same register on the DPORT bus as follows:: + + addr_ulp = (addr_dport - DR_REG_RTCCNTL_BASE) / 4 + +**Examples**:: + + 1: REG_RD 0x120, 2, 0 // load 4 bits: R0 = {12'b0, REG[0x120][7:4]} + + +**REG_WR** – write to peripheral register +----------------------------------------- + +**Syntax** + **REG_WR** *Addr, High, Low, Data* + +**Operands** + - *Addr* – register address, in 32-bit words. + - *High* – High part of R0 + - *Low* – Low part of R0 + - *Data* – value to write, 8 bits + +**Cycles** + 8 cycles to execute, 4 cycles to fetch next instruction + +**Description** + The instruction writes up to 8 bits from a general purpose register into a peripheral register. ``REG[Addr][High:Low] = data`` + + This instruction can access registers in RTC_CNTL, RTC_IO, SENS, and RTC_I2C peripherals. Address of the the register, as seen from the ULP, + can be calculated from the address of the same register on the DPORT bus as follows:: + + addr_ulp = (addr_dport - DR_REG_RTCCNTL_BASE) / 4 + +**Examples**:: + + 1: REG_WR 0x120, 7, 0, 0x10 // set 8 bits: REG[0x120][7:0] = 0x10 + +Convenience macros for peripheral registers access +-------------------------------------------------- + +ULP source files are passed through C preprocessor before the assembler. This allows certain macros to be used to facilitate access to peripheral registers. + +Some existing macros are defined in ``soc/soc_ulp.h`` header file. These macros allow access to the fields of peripheral registers by their names. +Peripheral registers names which can be used with these macros are the ones defined in ``soc/rtc_cntl_reg.h``, ``soc/rtc_io_reg.h``, ``soc/sens_reg.h``, and ``soc/rtc_i2c_reg.h``. + +READ_RTC_REG(rtc_reg, low_bit, bit_width) + Read up to 16 bits from rtc_reg[low_bit + bit_width - 1 : low_bit] into R0. For example:: + + #include "soc/soc_ulp.h" + #include "soc/rtc_cntl_reg.h" + + /* Read 16 lower bits of RTC_CNTL_TIME0_REG into R0 */ + READ_RTC_REG(RTC_CNTL_TIME0_REG, 0, 16) + +READ_RTC_FIELD(rtc_reg, field) + Read from a field in rtc_reg into R0, up to 16 bits. For example:: + + #include "soc/soc_ulp.h" + #include "soc/sens_reg.h" + + /* Read 8-bit SENS_TSENS_OUT field of SENS_SAR_SLAVE_ADDR3_REG into R0 */ + READ_RTC_FIELD(SENS_SAR_SLAVE_ADDR3_REG, SENS_TSENS_OUT) + +WRITE_RTC_REG(rtc_reg, low_bit, bit_width, value) + Write immediate value into rtc_reg[low_bit + bit_width - 1 : low_bit], bit_width <= 8. For example:: + + #include "soc/soc_ulp.h" + #include "soc/rtc_io_reg.h" + + /* Set BIT(2) of RTC_GPIO_OUT_DATA_W1TS field in RTC_GPIO_OUT_W1TS_REG */ + WRITE_RTC_REG(RTC_GPIO_OUT_W1TS_REG, RTC_GPIO_OUT_DATA_W1TS_S + 2, 1, 1) + + +WRITE_RTC_FIELD(rtc_reg, field, value) + Write immediate value into a field in rtc_reg, up to 8 bits. For example:: + + #include "soc/soc_ulp.h" + #include "soc/rtc_cntl_reg.h" + + /* Set RTC_CNTL_ULP_CP_SLP_TIMER_EN field of RTC_CNTL_STATE0_REG to 0 */ + WRITE_RTC_FIELD(RTC_CNTL_STATE0_REG, RTC_CNTL_ULP_CP_SLP_TIMER_EN, 0) + + + + + + diff --git a/docs/en/api-guides/wifi.rst b/docs/en/api-guides/wifi.rst index aefbb39302..67160dfee0 100644 --- a/docs/en/api-guides/wifi.rst +++ b/docs/en/api-guides/wifi.rst @@ -11,16 +11,18 @@ Important Notes ESP32 Wi-Fi Feature List ------------------------- -- Supports Station-only mode, SoftAP-only mode, Station/SoftAP-coexistence mode -- Supports IEEE-802.11B, IEEE-802.11G, IEEE802.11N and APIs to configure the protocol mode -- Supports WPA/WPA2/WPA2-Enterprise and WPS -- Supports AMPDU, HT40, QoS and other key features -- Supports Modem-sleep -- Supports an Espressif-specific protocol which, in turn, supports up to **1 km** of data traffic +- Support Station-only mode, SoftAP-only mode, Station/SoftAP-coexistence mode +- Support IEEE-802.11B, IEEE-802.11G, IEEE802.11N and APIs to configure the protocol mode +- Support WPA/WPA2/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 - Up to 20 MBit/sec TCP throughput and 30 MBit/sec UDP throughput over the air -- Supports Sniffer +- Support Sniffer - Support set fast_crypto algorithm and normal algorithm switch which used in wifi connect - Support both fast scan and all channel scan feature +- Support multiple antennas +- Support channel state information How To Write a Wi-Fi Application ---------------------------------- @@ -71,25 +73,49 @@ as the default error-handling code in the application development phase. However ESP32 Wi-Fi Programming Model ------------------------------ -The ESP32 Wi-Fi programming model is depicted as follows:: +The ESP32 Wi-Fi programming model is depicted as follows: + +.. blockdiag:: + :caption: Wi-Fi Programming Model + :align: center + + blockdiag wifi-programming-model { + + # global attributes + node_height = 60; + node_width = 100; + span_width = 100; + span_height = 60; + default_shape = roundedbox; + default_group_color = none; + + # node labels + TCP_STACK [label="TCP\n stack", fontsize=12]; + EVNT_TASK [label="Event\n task", fontsize=12]; + APPL_TASK [label="Application\n task", width = 120, fontsize=12]; + WIFI_DRV [label="Wi-Fi\n Driver", width = 120, fontsize=12]; + KNOT [shape=none]; + + # node connections + labels + TCP_STACK -> EVNT_TASK [label=event]; + EVNT_TASK -> APPL_TASK [label="callback\n or event"]; + + # arrange nodes vertically + group { + label = "default handler"; + orientation = portrait; + EVNT_TASK <- WIFI_DRV [label=event]; + } + + # intermediate node + group { + label = "user handler"; + orientation = portrait; + APPL_TASK -- KNOT; + } + WIFI_DRV <- KNOT [label="API\n call"]; + } - default handler user handler - ----------- ------------- ------------- - | | event | | callback or | | - | TCPIP | ---------> | event | ----------> | application | - | stack | | task | event | task | - ----------- ------------- ------------- - /|\ | - | | - event | | - | | - | | - ------------- | - | | | - | Wi-Fi Driver|/__________________| - | |\ API call - | | - ------------- The Wi-Fi driver can be considered a black box that knows nothing about high-layer code, such as the TCPIP stack, application task, event task, etc. All the Wi-Fi driver can do is receive API calls from the high layer, @@ -209,78 +235,61 @@ Currently, the ESP32 implementation will never generate this event. It may be re ESP32 Wi-Fi Station General Scenario --------------------------------------- -Below is a "big scenario" which describes some small scenarios in Station mode:: +Below is a "big scenario" which describes some small scenarios in Station mode: + +.. seqdiag:: + :caption: Sample Wi-Fi Event Scenarios in Station Mode + :align: center + + seqdiag sample-scenarios-station-mode { + activation = none; + node_width = 80; + node_height = 60; + edge_length = 140; + span_height = 5; + default_shape = roundedbox; + default_fontsize = 12; + + MAIN_TASK [label = "Main\ntask"]; + APP_TASK [label = "App\ntask"]; + EVENT_TASK [label = "Event\ntask"]; + LWIP_TASK [label = "LwIP\ntask"]; + WIFI_TASK [label = "Wi-Fi\ntask"]; + + === 1. Init Phase === + MAIN_TASK -> LWIP_TASK [label="1.1> Create / init LwIP"]; + MAIN_TASK -> EVENT_TASK [label="1.2> Create / init event"]; + MAIN_TASK -> WIFI_TASK [label="1.3> Create / init Wi-Fi"]; + MAIN_TASK -> APP_TASK [label="1.4> Create app task"]; + === 2. Configure Phase === + MAIN_TASK -> WIFI_TASK [label="2> Configure Wi-Fi"]; + === 3. Start Phase === + MAIN_TASK -> WIFI_TASK [label="3.1> Start Wi-Fi"]; + EVENT_TASK <- WIFI_TASK [label="3.2> SYSTEM_EVENT_STA_START"]; + APP_TASK <- EVENT_TASK [label="3.3> SYSTEM_EVENT_STA_START"]; + === 4. Connect Phase === + APP_TASK -> WIFI_TASK [label="4.1> Connect Wi-Fi"]; + EVENT_TASK <- WIFI_TASK [label="4.2> SYSTEM_EVENT_STA_CONNECTED"]; + APP_TASK <- EVENT_TASK [label="4.3> SYSTEM_EVENT_STA_CONNECTED"]; + === 5. Got IP Phase === + EVENT_TASK -> LWIP_TASK [label="5.1> Start DHCP client"]; + EVENT_TASK <- LWIP_TASK [label="5.2> SYSTEM_EVENT_STA_GOT_IP"]; + APP_TASK <- EVENT_TASK [label="5.3> SYSTEM_EVENT_STA_GOT_IP"]; + APP_TASK -> APP_TASK [label="5.4> socket related init"]; + === 6. Disconnect Phase === + EVENT_TASK <- WIFI_TASK [label="6.1> SYSTEM_EVENT_STA_DISCONNECTED"]; + APP_TASK <- EVENT_TASK [label="6.2> SYSTEM_EVENT_STA_DISCONNECTED"]; + APP_TASK -> APP_TASK [label="6.3> disconnect handling"]; + === 7. IP Change Phase === + EVENT_TASK <- LWIP_TASK [label="7.1> SYSTEM_EVENT_STA_GOT_IP"]; + APP_TASK <- EVENT_TASK [label="7.2> SYSTEM_EVENT_STA_GOT_IP"]; + APP_TASK -> APP_TASK [label="7.3> Socket error handling"]; + === 8. Deinit Phase === + APP_TASK -> WIFI_TASK [label="8.1> Disconnect Wi-Fi"]; + APP_TASK -> WIFI_TASK [label="8.2> Stop Wi-Fi"]; + APP_TASK -> WIFI_TASK [label="8.3> Deinit Wi-Fi"]; + } - --------- --------- --------- --------- --------- - | Main | | app | | Event | | LwIP | | Wi-Fi | - | task | | task | | task | | task | | task | - --------- --------- --------- --------- --------- - | | | | | --- - | 1.1> create/init LwIP | | | | - |---------------------------------------------------------->| | | - | 1.2> create/init event | | | - |-------------------------------------->| | | 1. Init Phase - | | 1.3> create/init Wi-Fi | | - |----------------------------------------------------------------------------->| | - | 1.4> create app task | | | | - |------------------>| | | | | - | | | | | --- - | | | | | | - | | | | | - | | 2> configure Wi-Fi | | 2. Configure Phase - |----------------------------------------------------------------------------->| - | | | | | | - | | | | | --- - | | 3.1> start Wi-Fi | | | - |----------------------------------------------------------------------------->| - | | | 3.2 > SYSTEM_EVENT_STA_START | 3. Start Phase - | | |<-------------------------------------| - | 3.3> SYSTEM_EVENT_STA_START | | | - | |<------------------| | | --- - | | | | | | - | | | | | | - | | 4.1> connect wifi | | | - | |--------------------------------------------------------->| 4. Connect Phase - | | | 4.2> SYSTEM_EVENT_STA_CONNECTED | | - | | |<-------------------------------------| | - | 4.3> SYSTEM_EVENT_STA_CONNECTED | | | - | |<------------------| | | --- - | | | | | | - | | | | | | - | | 5.1> start DHCP client | | | - | | |------------------>| | | - | | 5.2> SYSTEM_EVENT_STA_GOT_IP | | - | | |<------------------| | - | 5.3> SYSTEM_EVENT_STA_GOT_IP | | 5. Got IP Phase - | |<------------------| | | - | |----- | | | | - | | | 5.4> socket related init | | | - | |<---- | | | | - | | | | | --- - | | | 6.1> SYSTEM_EVENT_STA_DISCONNECTED | | - | | |<-------------------------------------| - | 6.2> SYSTEM_EVENT_STA_DISCONNECTED | | 6. Disconnect Phase - | |<------------------| | | - | |----- | | | | - | | | 6.3> disconnect handling | | | - | |<---- | | | --- - | | | | | | - | | 7.1> SYSTEM_EVENT_STA_GOT_IP | | - | | |<------------------| | | - | 7.2> SYSTEM_EVENT_STA_GOT_IP | | - | |<------------------| | | 7. IP change phase - | |----- | | | - | | | 7.3> socket error handling | | | - | |<---- | | | | - | | | | | --- - | | 8.1> disconnect Wi-Fi | | | - | |--------------------------------------------------------->| - | | 8.2> stop Wi-Fi | | 8. Deinit phase - | |--------------------------------------------------------->| - | | 8.3> deinit Wi-Fi | | | - | |--------------------------------------------------------->| | - | | | | | --- - 1. Wi-Fi/LwIP Init Phase ++++++++++++++++++++++++++++++ @@ -347,63 +356,51 @@ In step 4.2, the Wi-Fi connection may fail because, for example, the password is ESP32 Wi-Fi soft-AP General Scenario --------------------------------------------- -Below is a "big scenario" which describes some small scenarios in Soft-AP mode:: +Below is a "big scenario" which describes some small scenarios in Soft-AP mode: + + .. seqdiag:: + :caption: Sample Wi-Fi Event Scenarios in Soft-AP Mode + :align: center + + seqdiag sample-scenarios-soft-ap-mode { + activation = none; + node_width = 80; + node_height = 60; + edge_length = 140; + span_height = 5; + default_shape = roundedbox; + default_fontsize = 12; + + MAIN_TASK [label = "Main\ntask"]; + APP_TASK [label = "App\ntask"]; + EVENT_TASK [label = "Event\ntask"]; + LWIP_TASK [label = "LwIP\ntask"]; + WIFI_TASK [label = "Wi-Fi\ntask"]; + + === 1. Init Phase === + MAIN_TASK -> LWIP_TASK [label="1.1> Create / init LwIP"]; + MAIN_TASK -> EVENT_TASK [label="1.2> Create / init event"]; + MAIN_TASK -> WIFI_TASK [label="1.3> Create / init Wi-Fi"]; + MAIN_TASK -> APP_TASK [label="1.4> Create app task"]; + === 2. Configure Phase === + MAIN_TASK -> WIFI_TASK [label="2> Configure Wi-Fi"]; + === 3. Start Phase === + MAIN_TASK -> WIFI_TASK [label="3.1> Start Wi-Fi"]; + EVENT_TASK <- WIFI_TASK [label="3.2> SYSTEM_EVENT_AP_START"]; + APP_TASK <- EVENT_TASK [label="3.3> SYSTEM_EVENT_AP_START"]; + === 4. Connect Phase === + EVENT_TASK <- WIFI_TASK [label="4.1> SYSTEM_EVENT_AP_STA_CONNECTED"]; + APP_TASK <- EVENT_TASK [label="4.2> SYSTEM_EVENT_AP_STA_CONNECTED"]; + === 5. Disconnect Phase === + EVENT_TASK <- WIFI_TASK [label="5.1> SYSTEM_EVENT_STA_DISCONNECTED"]; + APP_TASK <- EVENT_TASK [label="5.2> SYSTEM_EVENT_STA_DISCONNECTED"]; + APP_TASK -> APP_TASK [label="5.3> disconnect handling"]; + === 6. Deinit Phase === + APP_TASK -> WIFI_TASK [label="6.1> Disconnect Wi-Fi"]; + APP_TASK -> WIFI_TASK [label="6.2> Stop Wi-Fi"]; + APP_TASK -> WIFI_TASK [label="6.3> Deinit Wi-Fi"]; + } - --------- --------- --------- --------- --------- - | Main | | app | | Event | | LwIP | | Wi-Fi | - | task | | task | | task | | task | | task | - --------- --------- --------- --------- --------- - | | | | | - | | | | | --- - | 1.1> create/init LwIP | | | | - |---------------------------------------------------------->| | | - | 1.2> create/init event | | | - |-------------------------------------->| | | 1. Init Phase - | | 1.3> create/init Wi-Fi | | - |----------------------------------------------------------------------------->| | - | 1.4> create app task | | | | - |------------------>| | | | | - | | | | | --- - | | | | | | - | | | | | - | | 2> configure Wi-Fi | | 2. Configure Phase - |----------------------------------------------------------------------------->| - | | | | | | - | | | | | --- - | | | | | | - | | 3.1> start Wi-Fi | | - |----------------------------------------------------------------------------->| 3. Start Phase - | | | 3.2 > SYSTEM_EVENT_AP_START | - | | |<-------------------------------------| | - | 3.3> SYSTEM_EVENT_AP_START | | | - | |<------------------| | | --- - | | | | | | - | | | | | - | | | 4.1> SYSTEM_EVENT_AP_STACONNECTED | 4. Connect Phase - | | |<-------------------------------------| - | 4.2> SYSTEM_EVENT_AP_STACONNECTED | | | - | |<------------------| | | --- - | | | | | | - | | | | | | - | | | 5.1> SYSTEM_EVENT_STA_DISCONNECTED | - | | |<-------------------------------------| 5. Disconnect Phase - | 5.2> SYSTEM_EVENT_STA_DISCONNECTED | | - | |<------------------| | | | - | |----- | | | | - | | | 5.3> disconnect handling | | | - | |<---- | | | --- - | | | | | | - | | | | | | - | | | | | | - | | 6.1> disconnect Wi-Fi | | | - | |--------------------------------------------------------->| - | | 6.2> stop Wi-Fi | | 6. Deinit phase - | |--------------------------------------------------------->| - | | 6.3> deinit Wi-Fi | | | - | |--------------------------------------------------------->| | - | | | | | --- - | | | | | - ESP32 Wi-Fi Scan ------------------------ @@ -512,38 +509,34 @@ The scan type and other scan attributes are configured by esp_wifi_scan_start. T Scan All APs In All Channels(foreground) +++++++++++++++++++++++++++++++++++++++++++ -Scenario:: +Scenario: - --------- --------- --------- - | app | | event | | Wi-Fi | - | task | | task | | task | - --------- --------- --------- - | | | - | | | - | 1.1> Configure country code | - |-------------------------------------->| - | 1.2> Scan configuration | - |-------------------------------------->| - | | | - | | | - | | |---- - | | | | 2.1> Scan channel 1 - | | |<--- - | | |---- - | | | | 2.2> Scan channel 2 - | | |<--- - | | | - | | | .... ... - | | | - | | |---- - | | | | 2.x> Scan channel N - | | |<--- - | | | - | 3.1 SYSTEM_EVENT_SCAN_DONE | - | |<------------------| - | 3.2 SYSTEM_EVENT_SCAN_DONE | - |<------------------| | - | | | +.. seqdiag:: + :caption: Foreground Scan of all Wi-Fi Channels + :align: center + + seqdiag foreground-scan-all-channels { + activation = none; + node_width = 80; + node_height = 60; + edge_length = 160; + span_height = 5; + default_shape = roundedbox; + default_fontsize = 12; + + APP_TASK [label = "App\ntask"]; + EVENT_TASK [label = "Event\ntask"]; + WIFI_TASK [label = "Wi-Fi\ntask"]; + + APP_TASK -> WIFI_TASK [label="1.1 > Configure country code"]; + APP_TASK -> WIFI_TASK [label="1.2 > Scan configuration"]; + WIFI_TASK -> WIFI_TASK [label="2.1 > Scan channel 1"]; + WIFI_TASK -> WIFI_TASK [label="2.2 > Scan channel 2"]; + WIFI_TASK -> WIFI_TASK [label="..."]; + WIFI_TASK -> WIFI_TASK [label="2.x > Scan channel N"]; + EVENT_TASK <- WIFI_TASK [label="3.1 > SYSTEM_EVENT_SCAN_DONE"]; + APP_TASK <- EVENT_TASK [label="3.2 > SYSTEM_EVENT_SCAN_DONE"]; + } The scenario above describes an all-channel, foreground scan. The foreground scan can only occur in Station mode where the station does not connect to any AP. Whether it is a foreground or background scan is totally determined by the Wi-Fi driver, and cannot be configured by the application. @@ -572,84 +565,70 @@ Scan-Done Event Handling Phase Scan All APs on All Channels(background) ++++++++++++++++++++++++++++++++++++++++ -Scenario:: +Scenario: - --------- --------- --------- - | app | | event | | Wi-Fi | - | task | | task | | task | - --------- --------- --------- - | | | - | | | - | 1.1> Configure country code | - |-------------------------------------->| - | 1.2> Scan configuration | - |-------------------------------------->| - | | | - | | | - | | |---- - | | | | 2.1> Scan channel 1 - | | |<--- - | | |---- - | | | | 2.2> Back to home channel H - | | |<--- - | | |---- - | | | | 2.3> Scan channel 2 - | | |<--- - | | |---- - | | | | 2.4> Back to home channel H - | | |<--- - | | | - | | | .... ... - | | | - | | |---- - | | | | 2.x-1> Scan channel N - | | |<--- - | | |---- - | | | | 2.x> Back to home channel H - | | |<--- - | | | - | 3.1 SYSTEM_EVENT_SCAN_DONE | - | |<------------------| - | 3.2 SYSTEM_EVENT_SCAN_DONE | - |<------------------| | - | | | +.. seqdiag:: + :caption: Background Scan of all Wi-Fi Channels + :align: center + + seqdiag background-scan-all-channels { + activation = none; + node_width = 80; + node_height = 60; + edge_length = 160; + span_height = 5; + default_shape = roundedbox; + default_fontsize = 12; + + APP_TASK [label = "App\ntask"]; + EVENT_TASK [label = "Event\ntask"]; + WIFI_TASK [label = "Wi-Fi\ntask"]; + + APP_TASK -> WIFI_TASK [label="1.1 > Configure country code"]; + APP_TASK -> WIFI_TASK [label="1.2 > Scan configuration"]; + WIFI_TASK -> WIFI_TASK [label="2.1 > Scan channel 1"]; + WIFI_TASK -> WIFI_TASK [label="2.2 > Back to home channel H"]; + WIFI_TASK -> WIFI_TASK [label="2.3 > Scan channel 2"]; + WIFI_TASK -> WIFI_TASK [label="2.4 > Back to home channel H"]; + WIFI_TASK -> WIFI_TASK [label="..."]; + WIFI_TASK -> WIFI_TASK [label="2.x-1 > Scan channel N"]; + WIFI_TASK -> WIFI_TASK [label="2.x > Back to home channel H"]; + EVENT_TASK <- WIFI_TASK [label="3.1 > SYSTEM_EVENT_SCAN_DONE"]; + APP_TASK <- EVENT_TASK [label="3.2 > SYSTEM_EVENT_SCAN_DONE"]; + } The scenario above is an all-channel background scan. Compared to `Scan All APs In All Channels(foreground)`_ , the difference in the all-channel background scan is that the Wi-Fi driver will scan the back-to-home channel for 30 ms before it switches to the next channel to give the Wi-Fi connection a chance to transmit/receive data. Scan for a Specific AP in All Channels +++++++++++++++++++++++++++++++++++++++ -Scenario:: +Scenario: - --------- --------- --------- - | app | | event | | Wi-Fi | - | task | | task | | task | - --------- --------- --------- - | | | - | | | - | 1.1> Configure country code | - |-------------------------------------->| - | 1.2> Scan configuration | - |-------------------------------------->| - | | | - | | | - | | |---- - | | | | 2.1> Scan channel C1 - | | |<--- - | | |---- - | | | | 2.2> Scan channel C2 - | | |<--- - | | | - | | | ... - | | | - | | |---- - | | | | 2.x> Scan channel CN, or the AP is found - | | |<--- - | | | - | 3.1 SYSTEM_EVENT_SCAN_DONE | - | |<------------------| - | 3.2 SYSTEM_EVENT_SCAN_DONE | - |<------------------| | - | | | +.. seqdiag:: + :caption: Scan of specific Wi-Fi Channels + :align: center + + seqdiag scan-specific-channels { + activation = none; + node_width = 80; + node_height = 60; + edge_length = 160; + span_height = 5; + default_shape = roundedbox; + default_fontsize = 12; + + APP_TASK [label = "App\ntask"]; + EVENT_TASK [label = "Event\ntask"]; + WIFI_TASK [label = "Wi-Fi\ntask"]; + + APP_TASK -> WIFI_TASK [label="1.1 > Configure country code"]; + APP_TASK -> WIFI_TASK [label="1.2 > Scan configuration"]; + WIFI_TASK -> WIFI_TASK [label="2.1 > Scan channel C1"]; + WIFI_TASK -> WIFI_TASK [label="2.2 > Scan channel C2"]; + WIFI_TASK -> WIFI_TASK [label="..."]; + WIFI_TASK -> WIFI_TASK [label="2.x > Scan channel CN, or the AP is found"]; + EVENT_TASK <- WIFI_TASK [label="3.1 > SYSTEM_EVENT_SCAN_DONE"]; + APP_TASK <- EVENT_TASK [label="3.2 > SYSTEM_EVENT_SCAN_DONE"]; + } This scan is similar to `Scan All APs In All Channels(foreground)`_. The differences are: @@ -679,60 +658,50 @@ ESP32 Wi-Fi Station Connecting Scenario ---------------------------------------- Generally, the application does not need to care about the connecting process. Below is a brief introduction to the process for those who are really interested. -Scenario:: +Scenario: + +.. seqdiag:: + :caption: Wi-Fi Station Connecting Process + :align: center + + seqdiag station-connecting-process { + activation = none; + node_width = 80; + node_height = 60; + edge_length = 160; + span_height = 5; + default_shape = roundedbox; + default_fontsize = 12; + + EVENT_TASK [label = "Event\ntask"]; + WIFI_TASK [label = "Wi-Fi\ntask"]; + AP [label = "AP"]; + + === 1. Scan Phase === + WIFI_TASK -> WIFI_TASK [label="1.1 > Scan"]; + EVENT_TASK <- WIFI_TASK [label="1.2 > SYSTEM_EVENT_STA_DISCONNECTED"]; + === 2. Auth Phase === + WIFI_TASK -> AP [label="2.1 > Auth request"]; + EVENT_TASK <- WIFI_TASK [label="2.2 > SYSTEM_EVENT_STA_DISCONNECTED"]; + WIFI_TASK <- AP [label="2.3 > Auth response"]; + EVENT_TASK <- WIFI_TASK [label="2.4 > SYSTEM_EVENT_STA_DISCONNECTED"]; + === 3. Assoc Phase === + WIFI_TASK -> AP [label="3.1 > Assoc request"]; + EVENT_TASK <- WIFI_TASK [label="3.2 > SYSTEM_EVENT_STA_DISCONNECTED"]; + WIFI_TASK <- AP [label="3.3 > Assoc response"]; + EVENT_TASK <- WIFI_TASK [label="3.4 > SYSTEM_EVENT_STA_DISCONNECTED"]; + === 4. 4-way Handshake Phase === + WIFI_TASK -> AP [label="4.1 > 1/4 EAPOL"]; + EVENT_TASK <- WIFI_TASK [label="4.2 > SYSTEM_EVENT_STA_DISCONNECTED"]; + WIFI_TASK -> AP [label="4.3 > 2/4 EAPOL"]; + EVENT_TASK <- WIFI_TASK [label="4.4 > SYSTEM_EVENT_STA_DISCONNECTED"]; + WIFI_TASK -> AP [label="4.5 > 3/4 EAPOL"]; + EVENT_TASK <- WIFI_TASK [label="4.6 > SYSTEM_EVENT_STA_DISCONNECTED"]; + WIFI_TASK -> AP [label="4.7 > 4/4 EAPOL"]; + EVENT_TASK <- WIFI_TASK [label="4.8 > SYSTEM_EVENT_STA_DISCONNECTED"]; + EVENT_TASK <- WIFI_TASK [label="4.9 > SYSTEM_EVENT_STA_DISCONNECTED"]; + } - --------- --------- --------- - | Event | | Wi-Fi | | AP | - | task | | task | | | - --------- --------- --------- - | | | - | | | --- - | |---- | | - | | | 1.1> Scan | - | |<--- | Scan phase - | 1.2> SYSTEM_EVENT_STA_DISCONNECTED | - |<------------------| | | - | | | --- - | | | | - | 2.1> Auth Request | | - | |------------------>| | - | 2.2> SYSTEM_EVENT_STA_DISCONNECTED | - |<------------------| | Auth phase - | 2.3> Auth Response | - | |<------------------| | - | 2.4> SYSTEM_EVENT_STA_DISCONNECTED | | - |<------------------| | --- - | | | | - | | 3.1 Assoc Request | | - | |------------------>| | - | 3.2> SYSTEM_EVENT_STA_DISCONNECTED | - |<------------------| | Assoc phase - | 3.3 Assoc Response | - | |<------------------| | - | 3.4> SYSTEM_EVENT_STA_DISCONNECTED | | - |<------------------| | | - | | | --- - | | | | - | | 4.1> 1/4 EAPOL | | - | |<------------------| | - | 4.2> SYSTEM_EVENT_STA_DISCONNECTED | | - |<------------------| | | - | | 4.3> 2/4 EAPOL | | - | |------------------>| | - | 4.4> SYSTEM_EVENT_STA_DISCONNECTED | - |<------------------| | 4-way handshake phase - | | 4.5> 3/4 EAPOL | - | |<------------------| | - | 4.6> SYSTEM_EVENT_STA_DISCONNECTED | | - |<------------------| | | - | | 4.7> 4/4 EAPOL | | - | |------------------>| | - | 4.8> SYSTEM_EVENT_STA_DISCONNECTED | | - |<------------------| | | - | | | | - | 4.9> SYSTEM_EVENT_STA_DISCONNECTED | | - |<------------------| | --- - | | | Scan Phase +++++++++++++++++++++ @@ -1475,6 +1444,57 @@ Generally, following steps can be taken to configure the multiple antennas: .enabled_ant1 = 3 }; +Wi-Fi Channel State Information +------------------------------------ + +Channel state information (CSI) refers to the channel information of a Wi-Fi connection. In ESP32, this information consists of channel frequency responses of sub-carriers and is estimated when packets are received from the transmitter. Each channel frequency response of sub-carrier is recorded by two bytes of signed characters. The first one is imaginary part and the second one is real part. There are up to three fields of channel frequency responses according to the type of received packet. They are legacy long training field (LLTF), high throughput LTF (HT-LTF) and space time block code HT-LTF (STBC-HT-LTF). For different types of packets which are received on channels with different state, the sub-carrier index and total bytes of signed characters of CSI is shown in the following table. + ++-------------+--------------------+-----------------------------------------+--------------------------------------------------------+----------------------------------------------------------+ +| channel | secondary channel | none | above | below | ++-------------+--------------------+-------------+---------------------------+----------+---------------------------------------------+----------+-----------------------------------------------+ +| packet | signal mode | non HT | HT | non HT | HT | non HT | HT | ++ +--------------------+-------------+---------------------------+----------+-----------------+---------------------------+----------+-------------------+---------------------------+ +| information | channel bandwidth | 20MHz | 20MHz | 20MHz | 20MHz | 40MHz | 20MHz | 20MHz | 40MHz | ++ +--------------------+-------------+-------------+-------------+----------+----------+------+-------------+-------------+----------+----------+--------+-------------+-------------+ +| | STBC | non STBC | non STBC | STBC | non STBC | non STBC | STBC | non STBC | STBC | non STBC | non STBC | STBC | non STBC | STBC | ++-------------+--------------------+-------------+-------------+-------------+----------+----------+------+-------------+-------------+----------+----------+--------+-------------+-------------+ +| sub-carrier | LLTF | 0~31,-31~-1 | 0~31,-31~-1 | 0~31,-31~-1 | 0~63 | 0~63 | 0~63 | 0~63 | 0~63 | -64~-1 | -64~-1 | -64~-1 | -64~-1 | -64~-1 | ++ +--------------------+-------------+-------------+-------------+----------+----------+------+-------------+-------------+----------+----------+--------+-------------+-------------+ +| index | HT-LTF | - | 0~31,-31~-1 | 0~31,-31~-1 | - | 0~63 | 0~62 | 0~63,-64~-1 | 0~60,-60~-1 | - | -64~-1 | -62~-1 | 0~63,-64~-1 | 0~60,-60~-1 | ++ +--------------------+-------------+-------------+-------------+----------+----------+------+-------------+-------------+----------+----------+--------+-------------+-------------+ +| | STBC-HT-LTF | - | - | 0~31,-31~-1 | - | - | 0~62 | - | 0~60,-60~-1 | - | - | -62~-1 | - | 0~60,-60~-1 | ++-------------+--------------------+-------------+-------------+-------------+----------+----------+------+-------------+-------------+----------+----------+--------+-------------+-------------+ +| total bytes | 128 | 256 | 384 | 128 | 256 | 380 | 384 | 612 | 128 | 256 | 376 | 384 | 612 | ++----------------------------------+-------------+-------------+-------------+----------+----------+------+-------------+-------------+----------+----------+--------+-------------+-------------+ + +All of the information in the table can be found in the structure wifi_csi_info_t. + + - Secondary channel refers to secondary_channel field of rx_ctrl field. + - Signal mode of packet refers to sig_mode field of rx_ctrl field. + - Channel bandwidth refers to cwb field of rx_ctrl field. + - STBC refers to stbc field of rx_ctrl field. + - Total bytes refers to len field. + - The CSI data corresponding to each Long Training Field type is stored in a buffer starting from the buf field. Each item is stored as two bytes: imaginary part followed by real part. The order is: LLTF, HT-LTF, STBC-HT-LTF. However all 3 items may not be present, depending on the packet type (see above). + - If last_word_invalid field of wifi_csi_info_t is true, it means that the last four bytes of CSI data is invalid due to a hardware limitation in ESP32. + - More information like RSSI, noise floor of RF, receiving time and antenna is in the rx_ctrl field. + +.. note:: + + - For STBC packet, CSI is provided for every space-time stream without CSD (cyclic shift delay). As each cyclic shift on the additional chains shall be -200ns, only the CSD angle of first space-time stream is recorded in sub-carrier 0 of HT-LTF and STBC-HT-LTF for there is no channel frequency response in sub-carrier 0. CSD[10:0] is 11 bits, ranging from -pi to pi. + - If LLTF, HT-LTF or STBC-HT-LTF is not enabled by calling API :cpp:func:`esp_wifi_set_csi_config`, the total bytes of CSI data will be fewer than that in the table. For example, if LLTF and HT-LTF is not enabled and STBC-HT-LTF is enabled, when a packet is received with the condition above/HT/40MHz/STBC, the total bytes of CSI data is 244 ((61 + 60) * 2 + 2 = 244, the result is aligned to four bytes and the last two bytes is invalid). + +Wi-Fi Channel State Information Configure +------------------------------------------- + +To use Wi-Fi CSI, the following steps need to be done. + + - Select Wi-Fi CSI in menuconfig. It is "Menuconfig --> Components config --> Wi-Fi --> WiFi CSI(Channel State Information)". + - Set CSI receiving callback function by calling API :cpp:func:`esp_wifi_set_csi_rx_cb`. + - Configure CSI by calling API :cpp:func:`esp_wifi_set_csi_config`. + - Enable CSI by calling API :cpp:func:`esp_wifi_set_csi`. + +The CSI receiving callback function runs from Wi-Fi task. So, do not do lengthy operations in the callback function. Instead, post necessary data to a queue and handle it from a lower priority task. Because station does not receive any packet when it is disconnected and only receives packets from AP when it is connected, it is suggested to enable sniffer mode to receive more CSI data by calling :cpp:func:`esp_wifi_set_promiscuous`. + Wi-Fi Buffer Usage -------------------------- @@ -1542,26 +1562,73 @@ Wi-Fi Menuconfig Wi-Fi Buffer Configure +++++++++++++++++++++++ -If you are going to modify the default number or type of buffer, it would be helpful to also have an overview of how the buffer is allocated/freed in the data path. The following diagram shows this process in the TX direction:: +If you are going to modify the default number or type of buffer, it would be helpful to also have an overview of how the buffer is allocated/freed in the data path. The following diagram shows this process in the TX direction: + +.. blockdiag:: + :caption: TX Buffer Allocation + :align: center + + blockdiag buffer_allocation_tx { + + # global attributes + node_height = 60; + node_width = 100; + span_width = 50; + span_height = 20; + default_shape = roundedbox; + + # labels of diagram nodes + APPL_TASK [label="Application\n task", fontsize=12]; + LWIP_TASK [label="LwIP\n task", fontsize=12]; + WIFI_TASK [label="Wi-Fi\n task", fontsize=12]; + + # labels of description nodes + APPL_DESC [label="1> User data", width=120, height=25, shape=note, color=yellow]; + LWIP_DESC [label="2> Pbuf", width=120, height=25, shape=note, color=yellow]; + WIFI_DESC [label="3> Dynamic (Static)\n TX Buffer", width=150, height=40, shape=note, color=yellow]; + + # node connections + APPL_TASK -> LWIP_TASK -> WIFI_TASK + APPL_DESC -> LWIP_DESC -> WIFI_DESC [style=none] + } - ------------- ------------- ------------- - | Application | | LwIP | | Wi-Fi | - | task | ---------> | task | ---------> | task | - ------------- ------------- ------------- - 1> User data 2> Pbuf 3> Dynamic (Static) TX Buffer Description: - The application allocates the data which needs to be sent out. - The application calls TCPIP-/Socket-related APIs to send the user data. These APIs will allocate a PBUF used in LwIP, and make a copy of the user data. - When LwIP calls a Wi-Fi API to send the PBUF, the Wi-Fi API will allocate a "Dynamic Tx Buffer" or "Static Tx Buffer", make a copy of the LwIP PBUF, and finally send the data. -The following diagram shows how buffer is allocated/freed in the RX direction:: +The following diagram shows how buffer is allocated/freed in the RX direction: - ------------- ------------- ------------- ------------- - | Application | | LwIP | | Wi-Fi | | Wi-Fi | - | Task | <--------- | task | <--------- | task | <--------- | Interrupt | - ------------- ------------- ------------- ------------- - 4> User data 3> Pbuf 2> Dynamic RX Buffer 1> Static RX Buffer +.. blockdiag:: + :caption: RX Buffer Allocation + :align: center + + blockdiag buffer_allocation_rx { + + # global attributes + node_height = 60; + node_width = 100; + span_width = 40; + span_height = 20; + default_shape = roundedbox; + + # labels of diagram nodes + APPL_TASK [label="Application\n task", fontsize=12]; + LWIP_TASK [label="LwIP\n task", fontsize=12]; + WIFI_TASK [label="Wi-Fi\n task", fontsize=12]; + WIFI_INTR [label="Wi-Fi\n interrupt", fontsize=12]; + + # labels of description nodes + APPL_DESC [label="4> User\n Data Buffer", height=40, shape=note, color=yellow]; + LWIP_DESC [label="3> Pbuf", height=40, shape=note, color=yellow]; + WIFI_DESC [label="2> Dynamic\n RX Buffer", height=40, shape=note, color=yellow]; + INTR_DESC [label="1> Static\n RX Buffer", height=40, shape=note, color=yellow]; + + # node connections + APPL_TASK <- LWIP_TASK <- WIFI_TASK <- WIFI_INTR + APPL_DESC <- LWIP_DESC <- WIFI_DESC <- INTR_DESC [style=none] + } Description: diff --git a/docs/en/api-reference/error-codes.rst b/docs/en/api-reference/error-codes.rst new file mode 100644 index 0000000000..d8e7c4fac4 --- /dev/null +++ b/docs/en/api-reference/error-codes.rst @@ -0,0 +1,8 @@ +Error Codes Reference +===================== + +This section lists various error code constants defined in ESP-IDF. + +For general information about error codes in ESP-IDF, see :doc:`Error Handling <../api-guides/error-handling>`. + +.. include:: /_build/inc/esp_err_defs.inc diff --git a/docs/en/api-reference/index.rst b/docs/en/api-reference/index.rst index 60917a8674..e35c4cc39c 100644 --- a/docs/en/api-reference/index.rst +++ b/docs/en/api-reference/index.rst @@ -14,4 +14,5 @@ API Reference Storage System Configuration Options + Error Codes Reference diff --git a/docs/en/api-reference/peripherals/adc.rst b/docs/en/api-reference/peripherals/adc.rst index 6b17048dc1..ee6f98a6dc 100644 --- a/docs/en/api-reference/peripherals/adc.rst +++ b/docs/en/api-reference/peripherals/adc.rst @@ -12,8 +12,8 @@ However, there're some restrictions for the application to use ADC2: 1. The application can use ADC2 only when Wi-Fi driver is not started, since the ADC is also used by the Wi-Fi driver, which has higher priority. 2. Some of the ADC2 pins are used as strapping pins (GPIO 0, 2, 15), so they cannot be used freely. For examples, for official Develop Kits: - - `ESP32 Core Board V2 / ESP32 DevKitC `_: GPIO 0 cannot be used due to external auto program circuits. - - `ESP-WROVER-KIT V3 `_: GPIO 0, 2, 4 and 15 cannot be used due to external connections for different purposes. + - :ref:`ESP32 Core Board V2 / ESP32 DevKitC `: GPIO 0 cannot be used due to external auto program circuits. + - :ref:`ESP-WROVER-KIT V3 `: GPIO 0, 2, 4 and 15 cannot be used due to external connections for different purposes. Configuration and Reading ADC ----------------------------- diff --git a/docs/en/api-reference/peripherals/spi_master.rst b/docs/en/api-reference/peripherals/spi_master.rst index 05474190d7..3a526fbd54 100644 --- a/docs/en/api-reference/peripherals/spi_master.rst +++ b/docs/en/api-reference/peripherals/spi_master.rst @@ -14,7 +14,7 @@ The spi_master driver ^^^^^^^^^^^^^^^^^^^^^ The spi_master driver allows easy communicating with SPI slave devices, even in a multithreaded environment. -It fully transparently handles DMA transfers to read and write data and automatically takes care of +It fully transparently handles DMA transfers to read and write data and automatically takes care of multiplexing between different SPI slaves on the same master Terminology @@ -22,11 +22,11 @@ Terminology The spi_master driver uses the following terms: -* Host: The SPI peripheral inside the ESP32 initiating the SPI transmissions. One of SPI, HSPI or VSPI. (For - now, only HSPI or VSPI are actually supported in the driver; it will support all 3 peripherals +* Host: The SPI peripheral inside the ESP32 initiating the SPI transmissions. One of SPI, HSPI or VSPI. (For + now, only HSPI or VSPI are actually supported in the driver; it will support all 3 peripherals somewhere in the future.) * Bus: The SPI bus, common to all SPI devices connected to one host. In general the bus consists of the - miso, mosi, sclk and optionally quadwp and quadhd signals. The SPI slaves are connected to these + miso, mosi, sclk and optionally quadwp and quadhd signals. The SPI slaves are connected to these signals in parallel. - miso - Also known as q, this is the input of the serial stream into the ESP32 @@ -58,33 +58,40 @@ A transaction on the SPI bus consists of five phases, any of which may be skippe * The read phase. The slave sends data to the master. In full duplex mode, the read and write phases are combined, and the SPI host reads and -writes data simultaneously. The total transaction length is decided by +writes data simultaneously. The total transaction length is decided by ``command_bits + address_bits + trans_conf.length``, while the ``trans_conf.rx_length`` only determins length of data received into the buffer. While in half duplex mode, the host have independent write and read phases. The length of write phase and read phase are -decided by ``trans_conf.length`` and ``trans_conf.rx_length`` respectively. +decided by ``trans_conf.length`` and ``trans_conf.rx_length`` respectively. The command and address phase are optional in that not every SPI device will need to be sent a command and/or address. This is reflected in the device configuration: when the ``command_bits`` or ``address_bits`` fields are set to zero, no command or address phase is done. Something similar is true for the read and write phase: not every transaction needs both data to be written -as well as data to be read. When ``rx_buffer`` is NULL (and SPI_USE_RXDATA) is not set) the read phase +as well as data to be read. When ``rx_buffer`` is NULL (and SPI_USE_RXDATA) is not set) the read phase is skipped. When ``tx_buffer`` is NULL (and SPI_USE_TXDATA) is not set) the write phase is skipped. -GPIO matrix and native pins +GPIO matrix and IOMUX ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Most peripheral pins in ESP32 can directly connect to a GPIO, which is called *native pin*. When the peripherals are -required to work with other pins than the native pins, ESP32 use a *GPIO matrix* to realize this. If one of the pins is -not native, the driver automatically routes all the signals to the GPIO matrix, which works under 80MHz. The signals are -sampled and sent to peripherals or the GPIOs. +Most peripheral signals in ESP32 can connect directly to a specific GPIO, which is called its IOMUX pin. When a +peripheral signal is routed to a pin other than its IOMUX pin, ESP32 uses the less direct GPIO matrix to make this +connection. -When the GPIO matrix is used, signals cannot propogate to the peripherals over 40MHz, and the setup time of MISO is very -likely violated. Hence the clock frequency limitation is a little lower than the case without GPIO matrix. +If the driver is configured with all SPI signals set to their specific IOMUX pins (or left unconnected), it will bypass +the GPIO matrix. If any SPI signal is configured to a pin other than its IOMUx pin, the driver will automatically route +all the signals via the GPIO Matrix. The GPIO matrix samples all signals at 80MHz and sends them between the GPIO and +the peripheral. -Native pins for SPI controllers are as below: +When the GPIO matrix is used, signals faster than 40MHz cannot propagate and the setup time of MISO is more easily +violated, since the input delay of MISO signal is increased. The maximum clock frequency with GPIO Matrix is 40MHz +or less, whereas using all IOMUX pins allows 80MHz. + +.. note:: More details about influence of input delay on the maximum clock frequency, see :ref:`timing_considerations` below. + +IOMUX pins for SPI controllers are as below: +----------+------+------+ | Pin Name | HSPI | VSPI | @@ -112,11 +119,11 @@ Using the spi_master driver - Initialize a SPI bus by calling ``spi_bus_initialize``. Make sure to set the correct IO pins in the ``bus_config`` struct. Take care to set signals that are not needed to -1. -- Tell the driver about a SPI slave device connected to the bus by calling spi_bus_add_device. +- Tell the driver about a SPI slave device connected to the bus by calling spi_bus_add_device. Make sure to configure any timing requirements the device has in the ``dev_config`` structure. You should now have a handle for the device, to be used when sending it a transaction. -- To interact with the device, fill one or more spi_transaction_t structure with any transaction +- To interact with the device, fill one or more spi_transaction_t structure with any transaction parameters you need. Either queue all transactions by calling ``spi_device_queue_trans``, later quering the result using ``spi_device_get_trans_result``, or handle all requests synchroneously by feeding them into ``spi_device_transmit``. @@ -124,7 +131,7 @@ Using the spi_master driver - Optional: to unload the driver for a device, call ``spi_bus_remove_device`` with the device handle as an argument -- Optional: to remove the driver for a bus, make sure no more drivers are attached and call +- Optional: to remove the driver for a bus, make sure no more drivers are attached and call ``spi_bus_free``. Command and address phases @@ -135,26 +142,26 @@ During the command and address phases, ``cmd`` and ``addr`` field in the same time. The default length of command and address phase are set in the ``spi_device_interface_config_t`` and by ``spi_bus_add_device``. When the the flag ``SPI_TRANS_VARIABLE_CMD`` and ``SPI_TRANS_VARIABLE_ADDR`` are not set in -the ``spi_transaction_t``,the driver automatically set the length of these +the ``spi_transaction_t``,the driver automatically set the length of these phases to the default value as set when the device is initialized respectively. If the length of command and address phases needs to be variable, declare a -``spi_transaction_ext_t`` descriptor, set the flag ``SPI_TRANS_VARIABLE_CMD`` -or/and ``SPI_TRANS_VARIABLE_ADDR`` in the ``flags`` of ``base`` member and -configure the rest part of ``base`` as usual. Then the length of each phases +``spi_transaction_ext_t`` descriptor, set the flag ``SPI_TRANS_VARIABLE_CMD`` +or/and ``SPI_TRANS_VARIABLE_ADDR`` in the ``flags`` of ``base`` member and +configure the rest part of ``base`` as usual. Then the length of each phases will be ``command_bits`` and ``address_bits`` set in the ``spi_transaction_ext_t``. Write and read phases ^^^^^^^^^^^^^^^^^^^^^ Normally, data to be transferred to or from a device will be read from or written to a chunk of memory -indicated by the ``rx_buffer`` and ``tx_buffer`` members of the transaction structure. +indicated by the ``rx_buffer`` and ``tx_buffer`` members of the transaction structure. When DMA is enabled for transfers, these buffers are highly recommended to meet the requirements as below: 1. allocated in DMA-capable memory using ``pvPortMallocCaps(size, MALLOC_CAP_DMA)``; 2. 32-bit aligned (start from the boundary and have length of multiples of 4 bytes). -If these requirements are not satisfied, efficiency of the transaction will suffer due to the allocation and +If these requirements are not satisfied, efficiency of the transaction will suffer due to the allocation and memcpy of temporary buffers. .. note:: Half duplex transactions with both read and write phases are not supported when using DMA. See @@ -179,25 +186,27 @@ speed a lot if small transactions are used. 1. Transaction interval: The interval mainly comes from the cost of FreeRTOS queues and the time switching between tasks and the ISR. It also takes time for the software to setup spi peripheral registers as well as copy data to - FIFOs, or setup DMA links. Depending on whether the DMA is used, the interval of an one-byte transaction is around - 25us typically. - + FIFOs, or setup DMA links. Depending on whether the DMA is used, the interval of an one-byte transaction is around + 25us typically. + 1. The CPU is blocked and switched to other tasks when the - transaction is in flight. This save the cpu time but increase the interval. + transaction is in flight. This save the cpu time but increase the interval. 2. When the DMA is enabled, it needs about 2us per transaction to setup the linked list. When the master is transferring, it automatically read data from the linked list. If the DMA is not enabled, CPU has to write/read each byte to/from the FIFO by itself. Usually this is faster than 2us, but the transaction length is limited to 32 bytes for both write and read. - + Typical transaction interval with one byte data is as below: - +-----------------------+---------+ - | Transaction Time (us) | Typical | - +=======================+=========+ - | DMA | 24 | - +-----------------------+---------+ - | No DMA | 22 | - +-----------------------+---------+ + +--------+------------------+ + | | Transaction Time | + +========+==================+ + | | Typical (us) | + +--------+------------------+ + | DMA | 24 | + +--------+------------------+ + | No DMA | 22 | + +--------+------------------+ 2. SPI clock frequency: Each byte transferred takes 8 times of the clock period *8/fspi*. If the clock frequency is too high, some functions may be limited to use. See :ref:`timing_considerations`. @@ -209,7 +218,7 @@ clock speed: +-----------+----------------------+--------------------+------------+-------------+ | Frequency | Transaction Interval | Transaction Length | Total Time | Total Speed | | | | | | | -| [MHz] | [us] | [bytes] | [us] | [kBps] | +| (MHz) | (us) | (bytes) | (us) | (kBps) | +===========+======================+====================+============+=============+ | 8 | 25 | 1 | 26 | 38.5 | +-----------+----------------------+--------------------+------------+-------------+ @@ -229,9 +238,25 @@ into one transaction if possible to get higher transfer speed. Timing considerations ^^^^^^^^^^^^^^^^^^^^^ -Due to the input delay of MISO pin, ESP32 SPI master cannot read data at very high speed. The frequency allowed is -rather low when the GPIO matrix is used. Currently only frequency not greater than 8.8MHz is fully supported. When the -frequency is higher, you have to use the native pins or the *dummy bit workaround*. + +As shown in the figure below, there is a delay on the MISO signal after SCLK +launch edge and before it's latched by the internal register. As a result, +the MISO pin setup time is the limiting factor for SPI clock speed. When the +delay is too large, setup slack is < 0 and the setup timing requirement is +violated, leads to the failure of reading correctly. + +.. image:: /../_static/spi_miso.png + +.. wavedrom don't support rendering pdflatex till now(1.3.1), so we use the png here + +.. image:: /../_static/miso_timing_waveform.png + +The maximum frequency allowed is related to the *input delay* (maximum valid +time after SCLK on the MISO bus), as well as the usage of GPIO matrix. The +maximum frequency allowed is reduced to about 33~77% (related to existing +*input delay*) when the GPIO matrix is used. To work at higher frequency, you +have to use the IOMUX pins or the *dummy bit workaround*. You can get the +maximum reading frequency of the master by ``spi_get_freq_limit``. .. _dummy_bit_workaround: @@ -240,29 +265,98 @@ actually begins. The slave still sees the dummy clocks and gives out data, but t phase. This compensates the lack of setup time of MISO required by the host, allowing the host reading at higher frequency. -The maximum frequency (in MHz) host can read (or read and write) under different conditions is as below: +In the ideal case (the slave is so fast that the input delay is shorter than an apb clock, 12.5ns), the maximum +frequency host can read (or read and write) under different conditions is as below: -+-------------+-------------+-----------+-----------------------------+ -| Frequency Limit | Dummy Bits| Comments | -+-------------+-------------+ Used + + -| GPIO matrix | Native pins | By Driver | | -+=============+=============+===========+=============================+ -| 8.8 | N.M. | 0 | | -+-------------+-------------+-----------+-----------------------------+ -| N.M. | N.M. | 1 | Half Duplex, no DMA allowed | -+-------------+-------------+-----------+ + -| N.M. | N.M. | 2 | | -+-------------+-------------+-----------+-----------------------------+ - -N.M.: Not Measured Yet. ++-------------+-------------+------------+-----------------------------+ +| Frequency Limit (MHz) | Dummy Bits | Comments | ++-------------+-------------+ Used + + +| GPIO matrix | IOMUX pins | By Driver | | ++=============+=============+============+=============================+ +| 26.6 | 80 | No | | ++-------------+-------------+------------+-----------------------------+ +| 40 | -- | Yes | Half Duplex, no DMA allowed | ++-------------+-------------+------------+-----------------------------+ And if the host only writes, the *dummy bit workaround* is not used and the frequency limit is as below: -+-------------+----------------------+ -| GPIO matrix | Native pins | -+=============+======================+ -| 40 | 80 | -+-------------+----------------------+ ++-------------------+------------------+ +| GPIO matrix (MHz) | IOMUX pins (MHz) | ++===================+==================+ +| 40 | 80 | ++-------------------+------------------+ + +The spi master driver can work even if the *input delay* in the ``spi_device_interface_config_t`` is set to 0. +However, setting a accurate value helps to: (1) calculate the frequency limit in full duplex mode, and (2) compensate +the timing correctly by dummy bits in half duplex mode. You may find the maximum data valid time after the launch edge +of SPI clocks in the AC characteristics chapter of the device specifications, or measure the time on a oscilloscope or +logic analyzer. + +.. wavedrom don't support rendering pdflatex till now(1.3.1), so we use the png here + +.. image:: /../_static/miso_timing_waveform_async.png + +As shown in the figure above, the input delay is usually: + + *[input delay] = [sample delay] + [slave output delay]* + + 1. The sample delay is the maximum random delay due to the + asynchronization of SCLK and peripheral clock of the slave. It's usually + 1 slave peripheral clock if the clock is asynchronize with SCLK, or 0 if + the slave just use the SCLK to latch the SCLK and launch MISO data. e.g. + for ESP32 slaves, the delay is 12.5ns (1 apb clock), while it is reduced + to 0 if the slave is in the same chip as the master. + + 2. The slave output delay is the time for the MOSI to be stable after the + launch edge. e.g. for ESP32 slaves, the output delay is 37.5ns (3 apb + clocks) when IOMUX pins in the slave is used, or 62.5ns (5 apb clocks) if + through the GPIO matrix. + +Some typical delays are shown in the following table: + ++--------------------+------------------+ +| Device | Input delay (ns) | ++====================+==================+ +| Ideal device | 0 | ++--------------------+------------------+ +| ESP32 slave IOMUX* | 50 | ++--------------------+------------------+ +| ESP32 slave GPIO* | 75 | ++--------------------+------------------+ +| ESP32 slave is on an independent | +| chip, 12.5ns sample delay included. | ++---------------------------------------+ + +The MISO path delay(tv), consists of slave *input delay* and master *GPIO matrix delay*, finally determines the +frequency limit, above which the full duplex mode will not work, or dummy bits are used in the half duplex mode. The +frequency limit is: + + *Freq limit[MHz] = 80 / (floor(MISO delay[ns]/12.5) + 1)* + +The figure below shows the relations of frequency limit against the input delay. 2 extra apb clocks should be counted +into the MISO delay if the GPIO matrix in the master is used. + +.. image:: /../_static/spi_master_freq_tv.png + +Corresponding frequency limit for different devices with different *input delay* are shown in the following +table: + ++--------+------------------+----------------------+-------------------+ +| Master | Input delay (ns) | MISO path delay (ns) | Freq. limit (MHz) | ++========+==================+======================+===================+ +| IOMUX | 0 | 0 | 80 | ++ (0ns) +------------------+----------------------+-------------------+ +| | 50 | 50 | 16 | ++ +------------------+----------------------+-------------------+ +| | 75 | 75 | 11.43 | ++--------+------------------+----------------------+-------------------+ +| GPIO | 0 | 25 | 26.67 | ++ (25ns) +------------------+----------------------+-------------------+ +| | 50 | 75 | 11.43 | ++ +------------------+----------------------+-------------------+ +| | 75 | 100 | 8.89 | ++--------+------------------+----------------------+-------------------+ + Thread Safety ------------- @@ -282,7 +376,7 @@ Known Issues 1. use full-duplex mode instead. 2. disable the DMA by setting the last parameter to 0 in bus initialization function just as below: - ``ret=spi_bus_initialize(VSPI_HOST, &buscfg, 0);`` + ``ret=spi_bus_initialize(VSPI_HOST, &buscfg, 0);`` this may prohibit you from transmitting and receiving data longer than 32 bytes. 3. try to use command and address field to replace the write phase. @@ -293,7 +387,7 @@ Known Issues Application Example ------------------- - + Display graphics on the 320x240 LCD of WROVER-Kits: :example:`peripherals/spi_master`. diff --git a/docs/en/api-reference/storage/fatfs.rst b/docs/en/api-reference/storage/fatfs.rst index 9ea2c0685d..6ad0163e12 100644 --- a/docs/en/api-reference/storage/fatfs.rst +++ b/docs/en/api-reference/storage/fatfs.rst @@ -8,27 +8,27 @@ Additionally, FatFs has been modified to support run-time pluggable disk IO laye Using FatFs with VFS -------------------- -``esp_vfs_fat.h`` header file defines functions to connect FatFs with VFS. ``esp_vfs_fat_register`` function allocates a ``FATFS`` structure, and registers a given path prefix in VFS. Subsequent operations on files starting with this prefix are forwarded to FatFs APIs. ``esp_vfs_fat_unregister_path`` function deletes the registration with VFS, and frees the ``FATFS`` structure. +:component_file:`fatfs/src/esp_vfs_fat.h` header file defines functions to connect FatFs with VFS. :cpp:func:`esp_vfs_fat_register` function allocates a ``FATFS`` structure, and registers a given path prefix in VFS. Subsequent operations on files starting with this prefix are forwarded to FatFs APIs. :cpp:func:`esp_vfs_fat_unregister_path` function deletes the registration with VFS, and frees the ``FATFS`` structure. Most applications will use the following flow when working with ``esp_vfs_fat_`` functions: -1. Call ``esp_vfs_fat_register``, specifying path prefix where the filesystem has to be mounted (e.g. ``"/sdcard"``, ``"/spiflash"``), FatFs drive number, and a variable which will receive a pointer to ``FATFS`` structure. +1. Call :cpp:func:`esp_vfs_fat_register`, specifying path prefix where the filesystem has to be mounted (e.g. ``"/sdcard"``, ``"/spiflash"``), FatFs drive number, and a variable which will receive a pointer to ``FATFS`` structure. -2. Call ``ff_diskio_register`` function to register disk IO driver for the drive number used in step 1. +2. Call :cpp:func:`ff_diskio_register` function to register disk IO driver for the drive number used in step 1. -3. Call ``f_mount`` function (and optionally ``f_fdisk``, ``f_mkfs``) to mount the filesystem using the same drive number which was passed to ``esp_vfs_fat_register``. See FatFs documentation for more details. +3. Call FatFs ``f_mount`` function (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`. See `FatFs documentation for more details `. -4. Call POSIX and C standard library functions to open, read, write, erase, copy files, etc. Use paths starting with the prefix passed to ``esp_vfs_register`` (such as ``"/sdcard/hello.txt"``). +4. Call POSIX and C standard library functions to open, read, write, erase, copy files, etc. Use paths starting with the prefix passed to :cpp:func:`esp_vfs_register` (such as ``"/sdcard/hello.txt"``). 5. Optionally, call FatFs library functions directly. Use paths without a VFS prefix in this case (``"/hello.txt"``). 6. Close all open files. -7. Call ``f_mount`` function for the same drive number, with NULL ``FATFS*`` argument, to unmount the filesystem. +7. Call FatFs ``f_mount`` function for the same drive number, with NULL ``FATFS*`` argument, to unmount the filesystem. -8. Call ``ff_diskio_register`` with NULL ``ff_diskio_impl_t*`` argument and the same drive number. +8. Call FatFs :cpp:func:`ff_diskio_register` with NULL ``ff_diskio_impl_t*`` argument and the same drive number. -9. Call ``esp_vfs_fat_unregister_path`` with the path where the file system is mounted to remove FatFs from VFS, and free the ``FATFS`` structure allocated on step 1. +9. Call :cpp:func:`esp_vfs_fat_unregister_path` with the path where the file system is mounted to remove FatFs from VFS, and free the ``FATFS`` structure allocated on step 1. Convenience functions, ``esp_vfs_fat_sdmmc_mount`` and ``esp_vfs_fat_sdmmc_unmount``, which wrap these steps and also handle SD card initialization, are described in the next section. @@ -39,19 +39,28 @@ Convenience functions, ``esp_vfs_fat_sdmmc_mount`` and ``esp_vfs_fat_sdmmc_unmou Using FatFs with VFS and SD cards --------------------------------- -``esp_vfs_fat.h`` header file also provides a convenience function to perform steps 1–3 and 7–9, and also handle SD card initialization: ``esp_vfs_fat_sdmmc_mount``. This function does only limited error handling. Developers are encouraged to look at its source code and incorporate more advanced versions into production applications. ``esp_vfs_fat_sdmmc_unmount`` function unmounts the filesystem and releases resources acquired by ``esp_vfs_fat_sdmmc_mount``. +:component_file:`fatfs/src/esp_vfs_fat.h` header file also provides a convenience function to perform steps 1–3 and 7–9, and also handle SD card initialization: :cpp:func:`esp_vfs_fat_sdmmc_mount`. This function does only limited error handling. Developers are encouraged to look at its source code and incorporate more advanced versions into production applications. :cpp:func:`esp_vfs_fat_sdmmc_unmount` function unmounts the filesystem and releases resources acquired by :cpp:func:`esp_vfs_fat_sdmmc_mount`. .. doxygenfunction:: esp_vfs_fat_sdmmc_mount .. doxygenstruct:: esp_vfs_fat_mount_config_t :members: .. doxygenfunction:: esp_vfs_fat_sdmmc_unmount + +Using FatFs with VFS in read-only mode +-------------------------------------- + +Convenience functions, :cpp:func:`esp_vfs_fat_rawflash_mount` and :cpp:func:`esp_vfs_fat_rawflash_unmount`, are provided by :component_file:`fatfs/src/esp_vfs_fat.h` header file in order to perform steps 1-3 and 7-9 for read-only FAT partitions. These are particularly helpful for data partitions written only once during factory provisioning and need not be changed by production application throughout the lifetime. + +.. doxygenfunction:: esp_vfs_fat_rawflash_mount +.. doxygenfunction:: esp_vfs_fat_rawflash_unmount + FatFS disk IO layer ------------------- FatFs has been extended with an API to register disk IO driver at runtime. -Implementation of disk IO functions for SD/MMC cards is provided. It can be registered for the given FatFs drive number using ``ff_diskio_register_sdmmc`` function. +Implementation of disk IO functions for SD/MMC cards is provided. It can be registered for the given FatFs drive number using :cpp:func:`ff_diskio_register_sdmmc` function. .. doxygenfunction:: ff_diskio_register .. doxygenstruct:: ff_diskio_impl_t diff --git a/docs/en/api-reference/storage/spi_flash.rst b/docs/en/api-reference/storage/spi_flash.rst index 1dbb92bdd5..07f3a3e9b8 100644 --- a/docs/en/api-reference/storage/spi_flash.rst +++ b/docs/en/api-reference/storage/spi_flash.rst @@ -40,7 +40,7 @@ CPU A as well and returns control to the calling code. Additionally, all API functions are protected with a mutex (s_flash_op_mutex). -In a single core environment (:ref:`CONFIG_FREERTOS_UNICORE` enabled), we simply +In a single core environment (:envvar:`CONFIG_FREERTOS_UNICORE` enabled), we simply disable both caches, no inter-CPU communication takes place. API Reference - SPI Flash diff --git a/docs/en/api-reference/system/esp_err.rst b/docs/en/api-reference/system/esp_err.rst new file mode 100644 index 0000000000..a3d4cb69d4 --- /dev/null +++ b/docs/en/api-reference/system/esp_err.rst @@ -0,0 +1,14 @@ +Error Codes and Helper Functions +================================ + +This section lists definitions of common ESP-IDF error codes and several helper functions related to error handling. + +For general information about error codes in ESP-IDF, see :doc:`Error Handling <../../api-guides/error-handling>`. + +For the full list of error codes defined in ESP-IDF, see :doc:`Error Code Reference <../error-codes>`. + +API Reference +------------- + +.. include:: /_build/inc/esp_err.inc + diff --git a/docs/en/api-reference/system/esp_https_ota.rst b/docs/en/api-reference/system/esp_https_ota.rst new file mode 100644 index 0000000000..762de6cf72 --- /dev/null +++ b/docs/en/api-reference/system/esp_https_ota.rst @@ -0,0 +1,35 @@ +ESP HTTPS OTA +============= + +Overview +-------- + +``esp_https_ota`` provides simplified APIs to perform firmware upgrades over HTTPS. +It's an abstraction layer over existing OTA APIs. + +Application Example +------------------- + + .. highlight:: c + + :: + + esp_err_t do_firmware_upgrade() + { + esp_http_client_config_t config = { + .url = CONFIG_FIRMWARE_UPGRADE_URL, + .cert_pem = (char *)server_cert_pem_start, + }; + esp_err_t ret = esp_https_ota(&config); + if (ret == ESP_OK) { + esp_restart(); + } else { + return ESP_FAIL; + } + return ESP_OK; + } + +API Reference +------------- + +.. include:: /_build/inc/esp_https_ota.inc diff --git a/docs/en/api-reference/system/esp_timer.rst b/docs/en/api-reference/system/esp_timer.rst index 53c07a1b8f..a4fdbc28f1 100644 --- a/docs/en/api-reference/system/esp_timer.rst +++ b/docs/en/api-reference/system/esp_timer.rst @@ -43,6 +43,11 @@ Unlike `gettimeofday` function, values returned by :cpp:func:`esp_timer_get_time - Start from zero after the chip wakes up from deep sleep - Do not have timezone or DST adjustments applied +Application Example +------------------- + +The following example illustrates usage of ``esp_timer`` APIs: :example:`system/esp_timer`. + API Reference ------------- diff --git a/docs/en/api-reference/system/freertos_additions.rst b/docs/en/api-reference/system/freertos_additions.rst index 57d25e9a79..24e47a390f 100644 --- a/docs/en/api-reference/system/freertos_additions.rst +++ b/docs/en/api-reference/system/freertos_additions.rst @@ -374,8 +374,8 @@ defined Idle Hook and Tick Hook on every iteration of the Idle Task and Tick Interrupt respectively. Vanilla FreeRTOS hooks are referred to as **Legacy Hooks** in ESP-IDF FreeRTOS. -To enable legacy hooks, :ref:`CONFIG_FREERTOS_LEGACY_HOOKS`, -:ref:`CONFIG_FREERTOS_LEGACY_IDLE_HOOK`, and :ref:`CONFIG_FREERTOS_LEGACY_TICK_HOOK` +To enable legacy hooks, :envvar:`CONFIG_FREERTOS_LEGACY_HOOKS`, +:envvar:`CONFIG_FREERTOS_LEGACY_IDLE_HOOK`, and :envvar:`CONFIG_FREERTOS_LEGACY_TICK_HOOK` should all be enabled in ``make menuconfig``. Due to vanilla FreeRTOS being designed for single core, ``vApplicationIdleHook()`` diff --git a/docs/en/api-reference/system/heap_debug.rst b/docs/en/api-reference/system/heap_debug.rst index 72052b3b38..7769d1cf69 100644 --- a/docs/en/api-reference/system/heap_debug.rst +++ b/docs/en/api-reference/system/heap_debug.rst @@ -62,7 +62,7 @@ Configuration Temporarily increasing the heap corruption detection level can give more detailed information about heap corruption errors. -In ``make menuconfig``, under ``Component config`` there is a menu ``Heap memory debugging``. The setting :ref:`CONFIG_HEAP_CORRUPTION_DETECTION` can be set to one of three levels: +In ``make menuconfig``, under ``Component config`` there is a menu ``Heap memory debugging``. The setting :envvar:`CONFIG_HEAP_CORRUPTION_DETECTION` can be set to one of three levels: Basic (no poisoning) ++++++++++++++++++++ @@ -140,7 +140,7 @@ If you suspect a memory leak, the first step is to figure out which part of the Once you've identified the code which you think is leaking: -- Under ``make menuconfig``, navigate to ``Component settings`` -> ``Heap Memory Debugging`` and set :ref:`CONFIG_HEAP_TRACING`. +- Under ``make menuconfig``, navigate to ``Component settings`` -> ``Heap Memory Debugging`` and set :envvar:`CONFIG_HEAP_TRACING`. - Call the function :cpp:func:`heap_trace_init_standalone` early in the program, to register a buffer which can be used to record the memory trace. - Call the function :cpp:func:`heap_trace_start` to begin recording all mallocs/frees in the system. Call this immediately before the piece of code which you suspect is leaking memory. - Call the function :cpp:func:`heap_trace_stop` to stop the trace once the suspect piece of code has finished executing. diff --git a/docs/en/api-reference/system/index.rst b/docs/en/api-reference/system/index.rst index bdc5d68e22..2b94e6d550 100644 --- a/docs/en/api-reference/system/index.rst +++ b/docs/en/api-reference/system/index.rst @@ -18,7 +18,9 @@ System API Sleep Modes Base MAC address Over The Air Updates (OTA) + ESP HTTPS OTA ESP pthread + Error Codes and Helper Functions Example code for this API section is provided in :example:`system` directory of ESP-IDF examples. diff --git a/docs/en/api-reference/system/ipc.rst b/docs/en/api-reference/system/ipc.rst index 37d416145c..a6a1106a13 100644 --- a/docs/en/api-reference/system/ipc.rst +++ b/docs/en/api-reference/system/ipc.rst @@ -29,7 +29,7 @@ until the IPC Task has completed execution of the given function. Functions executed by IPCs must be functions of type `void func(void *arg)`. To run more complex functions which require a larger stack, the IPC tasks' stack size can be configured by modifying -:ref:`CONFIG_IPC_TASK_STACK_SIZE` in `menuconfig`. The IPC API is protected by a +:envvar:`CONFIG_IPC_TASK_STACK_SIZE` in `menuconfig`. The IPC API is protected by a mutex hence simultaneous IPC calls are not possible. Care should taken to avoid deadlock when writing functions to be executed by diff --git a/docs/en/api-reference/system/ota.rst b/docs/en/api-reference/system/ota.rst index d7dbb5978c..8253354736 100644 --- a/docs/en/api-reference/system/ota.rst +++ b/docs/en/api-reference/system/ota.rst @@ -37,6 +37,7 @@ See also * :doc:`Partition Table documentation <../../api-guides/partition-tables>` * :doc:`Lower-Level SPI Flash/Partition API <../storage/spi_flash>` +* :doc:`ESP HTTPS OTA ` Application Example ------------------- diff --git a/docs/en/api-reference/system/power_management.rst b/docs/en/api-reference/system/power_management.rst index 9ad1e16a99..80fcda64b5 100644 --- a/docs/en/api-reference/system/power_management.rst +++ b/docs/en/api-reference/system/power_management.rst @@ -16,15 +16,15 @@ Naturally, requesting higher APB or CPU frequency or disabling light sleep cause Configuration ------------- -Power management can be enabled at compile time, using :ref:`CONFIG_PM_ENABLE` option. +Power management can be enabled at compile time, using :envvar:`CONFIG_PM_ENABLE` option. Enabling power management features comes at the cost of increased interrupt latency. Extra latency depends on a number of factors, among which are CPU frequency, single/dual core mode, whether frequency switch needs to be performed or not. Minimal extra latency is 0.2us (when CPU frequency is 240MHz, and frequency scaling is not enabled), maximum extra latency is 40us (when frequency scaling is enabled, and a switch from 40MHz to 80MHz is performed on interrupt entry). -Dynamic frequency scaling (DFS) and automatic light sleep can be enabled in the application by calling :cpp:func:`esp_pm_configure` function. Its argument is a structure defining frequency scaling settings (for ESP32, minimum and maximum CPU frequencies). Alternatively, :ref:`CONFIG_PM_DFS_INIT_AUTO` option can be enabled in menuconfig. If enabled, maximal CPU frequency is determined by :ref:`CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ` setting, and minimal CPU frequency is set to the XTAL frequency. +Dynamic frequency scaling (DFS) and automatic light sleep can be enabled in the application by calling :cpp:func:`esp_pm_configure` function. Its argument is a structure defining frequency scaling settings (for ESP32, minimum and maximum CPU frequencies). Alternatively, :envvar:`CONFIG_PM_DFS_INIT_AUTO` option can be enabled in menuconfig. If enabled, maximal CPU frequency is determined by :envvar:`CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ` setting, and minimal CPU frequency is set to the XTAL frequency. .. note:: - Automatic light sleep is based on FreeRTOS Tickless Idle functionality. :cpp:func:`esp_pm_configure` will return an `ESP_ERR_NOT_SUPPORTED` error if :ref:`CONFIG_FREERTOS_USE_TICKLESS_IDLE` option is not enabled in menuconfig, but automatic light sleep is requested. + Automatic light sleep is based on FreeRTOS Tickless Idle functionality. :cpp:func:`esp_pm_configure` will return an `ESP_ERR_NOT_SUPPORTED` error if :envvar:`CONFIG_FREERTOS_USE_TICKLESS_IDLE` option is not enabled in menuconfig, but automatic light sleep is requested. .. note:: @@ -54,7 +54,7 @@ Power Management Algorithm for the ESP32 When dynamic frequency scaling is enabled, CPU frequency will be switched as follows: -- If maximal CPU frequency (set using :cpp:func:`esp_pm_configure` or :ref:`CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ`) is 240 MHz: +- If maximal CPU frequency (set using :cpp:func:`esp_pm_configure` or :envvar:`CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ`) is 240 MHz: 1. When ``ESP_PM_CPU_FREQ_MAX`` or ``ESP_PM_APB_FREQ_MAX`` locks are acquired, CPU frequency will be 240 MHz, and APB frequency will be 80 MHz. diff --git a/docs/en/api-reference/system/sleep_modes.rst b/docs/en/api-reference/system/sleep_modes.rst index bc0033abcb..de56c56e50 100644 --- a/docs/en/api-reference/system/sleep_modes.rst +++ b/docs/en/api-reference/system/sleep_modes.rst @@ -136,6 +136,13 @@ Add the following code before :cpp:func:`esp_deep_sleep_start` to remove this ex rtc_gpio_isolate(GPIO_NUM_12); ``` +UART output handling +-------------------- + +Before entering sleep mode, :cpp:func:`esp_deep_sleep_start` will flush the contents of UART FIFOs. + +When entering light sleep mode using :cpp:func:`esp_light_sleep_start`, UART FIFOs will not be flushed. Instead, UART output will be suspended, and remaining characters in the FIFO will be sent out after wakeup from light sleep. + Checking sleep wakeup cause --------------------------- diff --git a/docs/en/api-reference/system/wdts.rst b/docs/en/api-reference/system/wdts.rst index adfa49693a..e790a5df42 100644 --- a/docs/en/api-reference/system/wdts.rst +++ b/docs/en/api-reference/system/wdts.rst @@ -61,10 +61,10 @@ longer call :cpp:func:`esp_task_wdt_reset`. Once all tasks have unsubscribed form the TWDT, the TWDT can be deinitialized by calling :cpp:func:`esp_task_wdt_deinit()`. -By default :ref:`CONFIG_TASK_WDT` in ``make menuconfig`` will be enabled causing +By default :envvar:`CONFIG_TASK_WDT` in ``make menuconfig`` will be enabled causing the TWDT to be initialized automatically during startup. Likewise -:ref:`CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU0` and -:ref:`CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU1` are also enabled by default causing +:envvar:`CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU0` and +:envvar:`CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU1` are also enabled by default causing the two Idle Tasks to be subscribed to the TWDT during startup. JTAG and watchdogs diff --git a/docs/en/contribute/documenting-code.rst b/docs/en/contribute/documenting-code.rst index 80cbe1cf77..fd7d93866c 100644 --- a/docs/en/contribute/documenting-code.rst +++ b/docs/en/contribute/documenting-code.rst @@ -247,7 +247,7 @@ You can setup environment to build documentation locally on your PC by installin 5. Blockdiag - http://blockdiag.com/en/index.html 6. Recommonmark - https://github.com/rtfd/recommonmark -The package "sphinx_rtd_theme" is added to have the same "look and feel" of `ESP32 Programming Guide `_ documentation like on the "Read the Docs" hosting site. +The package "sphinx_rtd_theme" is added to have the same "look and feel" of `ESP32 Programming Guide `_ documentation like on the "Read the Docs" hosting site. Do not worry about being confronted with several packages to install. Besides Doxygen, all remaining packages are written in Python. Therefore installation of all of them is combined into one simple step. diff --git a/docs/en/get-started/eclipse-setup-windows.rst b/docs/en/get-started/eclipse-setup-windows.rst index 62373485a7..9c6f89564d 100644 --- a/docs/en/get-started/eclipse-setup-windows.rst +++ b/docs/en/get-started/eclipse-setup-windows.rst @@ -43,7 +43,7 @@ Project Properties * Click on the "C/C++ Build" properties page (top-level): - * Uncheck "Use default build command" and enter this for the custom build command: ``python ${IDF_PATH}/tools/windows/eclipse_make.py``. + * Uncheck "Use default build command" and enter this for the custom build command: ``python ${IDF_PATH}/tools/windows/eclipse_make.py`` * Click on the "Environment" properties page under "C/C++ Build": @@ -57,10 +57,15 @@ Project Properties * Click the "Providers" tab - * In the list of providers, click "CDT GCC Built-in Compiler Settings Cygwin". Under "Command to get compiler specs", replace the text ``${COMMAND}`` at the beginning of the line with ``xtensa-esp32-elf-gcc``. This means the full "Command to get compiler specs" should be ``xtensa-esp32-elf-gcc ${FLAGS} -E -P -v -dD "${INPUTS}"``. + * In the list of providers, click "CDT Cross GCC Built-in Compiler Settings". Change "Command to get compiler specs" to ``xtensa-esp32-elf-gcc ${FLAGS} -E -P -v -dD "${INPUTS}"``. - * In the list of providers, click "CDT GCC Build Output Parser" and type ``xtensa-esp32-elf-`` at the beginning of the Compiler command pattern, and wrap remaining part with brackets. This means the full Compiler command pattern should be ``xtensa-esp32-elf-((g?cc)|([gc]\+\+)|(clang))`` + * In the list of providers, click "CDT GCC Build Output Parser" and change the "Compiler command pattern" to ``xtensa-esp32-elf-(gcc|g\+\+|c\+\+|cc|cpp|clang)`` +Navigate to "C/C++ General" -> "Indexer" property page: + +* Check "Enable project specific settings" to enable the rest of the settings on this page. + +* Uncheck "Allow heuristic resolution of includes". When this option is enabled Eclipse sometimes fails to find correct header directories. Building in Eclipse ------------------- diff --git a/docs/en/get-started/eclipse-setup.rst b/docs/en/get-started/eclipse-setup.rst index 7d17d6c159..e07c700e46 100644 --- a/docs/en/get-started/eclipse-setup.rst +++ b/docs/en/get-started/eclipse-setup.rst @@ -59,9 +59,15 @@ Navigate to "C/C++ General" -> "Preprocessor Include Paths" property page: * Click the "Providers" tab -* In the list of providers, click "CDT Cross GCC Built-in Compiler Settings". Under "Command to get compiler specs", replace the text ``${COMMAND}`` at the beginning of the line with ``xtensa-esp32-elf-gcc``. This means the full "Command to get compiler specs" should be ``xtensa-esp32-elf-gcc ${FLAGS} -E -P -v -dD "${INPUTS}"``. +* In the list of providers, click "CDT Cross GCC Built-in Compiler Settings". Change "Command to get compiler specs" to ``xtensa-esp32-elf-gcc ${FLAGS} -E -P -v -dD "${INPUTS}"``. -* In the list of providers, click "CDT GCC Build Output Parser" and type ``xtensa-esp32-elf-`` at the beginning of the Compiler command pattern. This means the full Compiler command pattern should be ``xtensa-esp32-elf-(g?cc)|([gc]\+\+)|(clang)`` +* In the list of providers, click "CDT GCC Build Output Parser" and change the "Compiler command pattern" to ``xtensa-esp32-elf-(gcc|g\+\+|c\+\+|cc|cpp|clang)`` + +Navigate to "C/C++ General" -> "Indexer" property page: + +* Check "Enable project specific settings" to enable the rest of the settings on this page. + +* Uncheck "Allow heuristic resolution of includes". When this option is enabled Eclipse sometimes fails to find correct header directories. .. _eclipse-build-project: diff --git a/docs/en/get-started/idf-monitor.rst b/docs/en/get-started/idf-monitor.rst index 09291a3d3f..d298187c78 100644 --- a/docs/en/get-started/idf-monitor.rst +++ b/docs/en/get-started/idf-monitor.rst @@ -67,7 +67,7 @@ By default, if an esp-idf app crashes then the panic handler prints registers an Optionally, the panic handler can be configured to run a serial "gdb stub" which can communicate with a gdb_ debugger program and allow memory to be read, variables and stack frames examined, etc. This is not as versatile as JTAG debugging, but no special hardware is required. -To enable the gdbstub, run ``make menuconfig`` and set :ref:`CONFIG_ESP32_PANIC` option to ``Invoke GDBStub``. +To enable the gdbstub, run ``make menuconfig`` and set :envvar:`CONFIG_ESP32_PANIC` option to ``Invoke GDBStub``. If this option is enabled and IDF Monitor sees the gdb stub has loaded, it will automatically pause serial monitoring and run GDB with the correct arguments. After GDB exits, the board will be reset via the RTS serial line (if this is connected.) @@ -105,6 +105,90 @@ Sometimes you may want to stop new output printed to screen, to see the log befo toggle the display (discard all serial data when the display is off) so that you can stop to see the log, and revert again quickly without quitting the monitor. +Filtering the Output +==================== + +The IDF monitor can be invoked as ``make monitor PRINT_FILTER=""`` with +specifying a custom ``PRINT_FILTER`` option for filtering outputs. The default +value is an empty string which means that everything will be printed. +Restrictions on what to print can be specified as a series of +``:`` items where ```` is the tag string and +```` is a character from set ``{N, E, W, I, D, V, *}`` referring to +a level for :doc:`logging <../../api-reference/system/log>`. For example, +``PRINT_FILTER="tag1:W"`` will match and print (only) the outputs written with +``ESP_LOGW("tag1", ...)`` or at lower verbosity level, i.e. ``ESP_LOGE("tag1", +...)``. Not specifying a +```` or using ``*`` defaults to Verbose level. + +.. note:: + The primary logging is set up at compilation time through the + :doc:`logging library<../../api-reference/system/log>`. + Output filtering by the IDF monitor is only a secondary solution because + one cannot filter something which has been disabled at compilation time. + The advantage of the secondary filtering is that one can use various + filtering options without recompiling the application. + +A restriction applies to tags when one wants to use them together with output +filtering: they cannot contain spaces, asterisks ``*`` and semicolons ``:``. + +If the last line of the output is written without an end of line then the +output filtering might get confused, i.e. the monitor starts to print the line and only +later finds out that the line should have not been written. This is a known +issue and can be avoided by always adding an end of line after printing +something (especially when no output follows immediately afterwards). + +Examples Of Filtering Rules: +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +- Asterisk can be used to match any tags. However, specifying + ``PRINT_FILTER="*:I tag1:E"`` will print for ``tag1`` only errors because + the rule for ``tag1`` has a precedence over the rule for ``*``. +- The default (empty) rule is equivalent to ``*:V`` because matching every tag + at level Verbose or lower means matching everything. +- Rule ``"tag1:W tag1:E"`` is equivalent to ``"tag1:E"`` because any + consequent occurrence of the same tag name overwrites the previous one. +- Rule ``"tag1:I tag2:W"`` will print only ``tag1`` at verbosity level Info or + lower and ``tag2`` at verbosity level Warning or lower. +- Rule ``"tag1:I tag2:W tag3:N"`` is essentially equivalent to the previous + one because ``tag3:N`` specifies that ``tag3`` should not be printed. +- ``tag3:N`` in rule ``"tag1:I tag2:W tag3:N *:V"`` is more meaningful because + in this context the result will be that ``tag3`` will not be printed, + ``tag1`` and ``tag2`` will be at the specified (or lower) verbosity level + and everything else will be printed by default. +- ``"*:N"`` will suppress all outputs even prints made by something else than + the logging functions, e.g. ``printf``. For printing those outputs one need + to use ``*:E`` or higher verbosity level. +- Rules ``"tag1:V"``, ``"tag1:v"``, ``"tag1:"``, ``"tag1:*"`` and ``"tag1"`` + are all equivalent ones. + +A More Complex Filtering Example +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The following log snippet was acquired using ``make monitor``:: + + load:0x40078000,len:13564 + entry 0x40078d4c + E (31) esp_image: image at 0x30000 has invalid magic byte + W (31) esp_image: image at 0x30000 has invalid SPI mode 255 + E (39) boot: Factory app partition is not bootable + I (568) cpu_start: Pro cpu up. + I (569) heap_init: Initializing. RAM available for dynamic allocation: + I (603) cpu_start: Pro cpu start user code + D (309) light_driver: [light_init, 74]:status: 1, mode: 2 + D (318) vfs: esp_vfs_register_fd_range is successful for range <54; 64) and VFS ID 1 + I (328) wifi: wifi driver task: 3ffdbf84, prio:23, stack:4096, core=0 + +The captured output for ``make monitor PRINT_FILTER="wifi esp_image:E light_driver:I"`` is the following:: + + E (31) esp_image: image at 0x30000 has invalid magic byte + I (328) wifi: wifi driver task: 3ffdbf84, prio:23, stack:4096, core=0 + +``make monitor PRINT_FILTER="light_driver:D esp_image:N boot:N cpu_start:N vfs:N wifi:N *:V"`` gives the following output:: + + load:0x40078000,len:13564 + entry 0x40078d4c + I (569) heap_init: Initializing. RAM available for dynamic allocation: + D (309) light_driver: [light_init, 74]:status: 1, mode: 2 Simple Monitor ============== diff --git a/docs/en/get-started/index.rst b/docs/en/get-started/index.rst index 9e33e63496..188b6938d4 100644 --- a/docs/en/get-started/index.rst +++ b/docs/en/get-started/index.rst @@ -5,6 +5,7 @@ Get Started This document is intended to help users set up the software environment for development of applications using hardware based on the Espressif ESP32. Through a simple example we would like to illustrate how to use ESP-IDF (Espressif IoT Development Framework), including the menu based configuration, compiling the ESP-IDF and firmware download to ESP32 boards. +.. include:: /_build/inc/version-note.inc Introduction ============ @@ -114,19 +115,18 @@ Get ESP-IDF .. highlight:: bash -Besides the toolchain (that contains programs to compile and build the application), you also need ESP32 specific API / libraries. They are provided by Espressif in `ESP-IDF repository `_. To get it, open terminal, navigate to the directory you want to put ESP-IDF, and clone it using ``git clone`` command:: +Besides the toolchain (that contains programs to compile and build the application), you also need ESP32 specific API / libraries. They are provided by Espressif in `ESP-IDF repository `_. - cd ~/esp - git clone --recursive https://github.com/espressif/esp-idf.git +.. include:: /_build/inc/git-clone.inc -ESP-IDF will be downloaded into ``~/esp/esp-idf``. +Consult :doc:`/versions` for information about which version of ESP-IDF to use in a given situation. .. note:: Do not miss the ``--recursive`` option. If you have already cloned ESP-IDF without this option, run another command to get all the submodules:: cd ~/esp/esp-idf - git submodule update --init + git submodule update --init --recursive .. _get-started-setup-path: @@ -286,7 +286,7 @@ To exit the monitor use shortcut ``Ctrl+]``. e���)(Xn@�y.!��(�PW+)��Hn9a؅/9�!�t5��P�~�k��e�ea�5�jA ~zY��Y(1�,1�� e���)(Xn@�y.!Dr�zY(�jpi�|�+z5Ymvp - or monitor fails shortly after upload, your board is likely using 26MHz crystal, while the ESP-IDF assumes default of 40MHz. Exit the monitor, go back to the :ref:`menuconfig `, change :ref:`CONFIG_ESP32_XTAL_FREQ_SEL` to 26MHz, then :ref:`build and flash ` the application again. This is found under ``make menuconfig`` under Component config --> ESP32-specific --> Main XTAL frequency. + or monitor fails shortly after upload, your board is likely using 26MHz crystal, while the ESP-IDF assumes default of 40MHz. Exit the monitor, go back to the :ref:`menuconfig `, change :envvar:`CONFIG_ESP32_XTAL_FREQ_SEL` to 26MHz, then :ref:`build and flash ` the application again. This is found under ``make menuconfig`` under Component config --> ESP32-specific --> Main XTAL frequency. To execute ``make flash`` and ``make monitor`` in one go, type ``make flash monitor``. Check section :doc:`IDF Monitor ` for handy shortcuts and more details on using this application. @@ -300,23 +300,9 @@ Updating ESP-IDF After some time of using ESP-IDF, you may want to update it to take advantage of new features or bug fixes. The simplest way to do so is by deleting existing ``esp-idf`` folder and cloning it again, exactly as when doing initial installation described in sections :ref:`get-started-get-esp-idf`. -Another solution is to update only what has changed. This method is useful if you have a slow connection to GitHub. To do the update run the following commands:: +If downloading to a new path, remember to :doc:`add-idf_path-to-profile` so that the toolchain scripts know where to find the ESP-IDF in its release specific location. - cd ~/esp/esp-idf - git pull - git submodule update --init --recursive - -The ``git pull`` command is fetching and merging changes from ESP-IDF repository on GitHub. Then ``git submodule update --init --recursive`` is updating existing submodules or getting a fresh copy of new ones. On GitHub the submodules are represented as links to other repositories and require this additional command to get them onto your PC. - -If you would like to use specific release of ESP-IDF, e.g. `v2.1`, run:: - - cd ~/esp - git clone https://github.com/espressif/esp-idf.git esp-idf-v2.1 - cd esp-idf-v2.1/ - git checkout v2.1 - git submodule update --init --recursive - -After that remember to :doc:`add-idf_path-to-profile`, so the toolchain scripts know where to find the ESP-IDF in it's release specific location. +Another solution is to update only what has changed. :ref:`The update procedure depends on the version of ESP-IDF you are using `. Related Documents @@ -331,3 +317,7 @@ Related Documents eclipse-setup idf-monitor toolchain-setup-scratch + +.. _Stable version: https://docs.espressif.com/projects/esp-idf/en/stable/ +.. _Releases page: https://github.com/espressif/esp-idf/releases + diff --git a/docs/en/index.rst b/docs/en/index.rst index 80cdfd482b..c1dbe708b3 100644 --- a/docs/en/index.rst +++ b/docs/en/index.rst @@ -45,9 +45,13 @@ The documentation has different language versions (:link_to_translation:`en:Engl H/W Reference API Guides Contribute + Versions Resources Copyrights About [语言/Languages] * :ref:`genindex` + + + diff --git a/docs/en/security/flash-encryption.rst b/docs/en/security/flash-encryption.rst index f44fa18bb5..584a6df252 100644 --- a/docs/en/security/flash-encryption.rst +++ b/docs/en/security/flash-encryption.rst @@ -196,7 +196,7 @@ Flash encryption keys are 32 bytes of random data. You can generate a random key Alternatively, if you're using :doc:`secure boot ` and have a secure boot signing key then you can generate a deterministic SHA-256 digest of the secure boot private signing key and use this as the flash encryption key:: - espsecure.py digest_private-key --keyfile secure_boot_signing_key.pem my_flash_encryption_key.bin + espsecure.py digest_private_key --keyfile secure_boot_signing_key.pem my_flash_encryption_key.bin (The same 32 bytes is used as the secure boot digest key if you enable :ref:`reflashable mode` for secure boot.) diff --git a/docs/en/versions.rst b/docs/en/versions.rst new file mode 100644 index 0000000000..5d6530cb68 --- /dev/null +++ b/docs/en/versions.rst @@ -0,0 +1,178 @@ +ESP-IDF Versions +================ + +The ESP-IDF GitHub repository is updated regularly, especially on the "master branch" where new development happens. There are also stable releases which are recommended for production use. + +Releases +-------- + +Documentation for the current stable version can always be found at this URL: + +https://docs.espressif.com/projects/esp-idf/en/stable/ + +Documentation for the latest version ("master branch") can always be found at this URL: + +https://docs.espressif.com/projects/esp-idf/en/latest/ + +The full history of releases can be found on the GitHub repository `Releases page`_. There you can find release notes, links to each version of the documentation, and instructions for obtaining each version. + +Documentation for all releases can also be found in the HTML documentation by clicking the "versions" pop up in the bottom-left corner of the page. You can use this popup to switch between versions of the documentation. + +.. image:: /../_static/choose_version.png + +Which Version Should I Start With? +---------------------------------- + +- For production purposes, use the `current stable version`_. Stable versions have been manually tested, and are updated with "bugfix releases" which fix bugs without changing other functionality (see `Versioning Scheme`_ for more details). + +- For prototyping, experimentation or for developing new ESP-IDF features, use the `latest version (master branch in Git) `_. The latest version in the master branch has all the latest features and has passed automated testing, but has not been completely manually tested ("bleeding edge"). + +- If a required feature is not yet available in a stable release, but you don't want to use the master branch, it is possible to check out a pre-release version or a release branch. It is recommended to start from a stable version and then follow the instructions for :ref:`updating-pre-release` or :ref:`updating-release-branch`. + +See :ref:`updating` if you already have a local copy of ESP-IDF and wish to update it. + +Versioning Scheme +----------------- + +ESP-IDF uses `Semantic Versioning `_. This means: + +- Major Releases like ``v3.0`` add new functionality and may change functionality. This includes removing deprecated functionality. + + When updating to a new major release (for example, from ``v2.1`` to ``v3.0``), some of your project's code may need updating and functionality will need to be re-tested. The release notes on the `Releases page`_ include lists of Breaking Changes to refer to. +- Minor Releases like ``v3.1`` add new functionality and fix bugs but will not change or remove documented functionality, or make incompatible changes to public APIs. + + If updating to a new minor release (for example, from ``v3.0`` to ``v3.1``) then none of your project's code should need updating, but you should re-test your project. Pay particular attention to items mentioned in the release notes on the `Releases page`_. +- Bugfix Releases like ``v3.0.1`` only fix bugs and do not add new functionality. + + If updating to a new bugfix release (for example, from ``v3.0`` to ``v3.0.1``), you should not need to change any code in your project and should only need to re-test functionality relating directly to bugs listed in the release notes on the `Releases page`_. + +Checking The Current Version +---------------------------- + +The local ESP-IDF version can be checked using git:: + + cd $IDF_PATH + git describe --tags --dirty + +The version is also compiled into the firmware and can be accessed (as a string) via the macro ``IDF_VER``. The default ESP-IDF bootloader will print the version on boot (these versions in code will not always update, it only changes if that particular source file is recompiled). + +Examples of ESP-IDF versions: + +============================ ================================================== +Version String Meaning +============================ ================================================== +``v3.2-dev-306-gbeb3611ca`` Master branch pre-release, in development for + version 3.2. 306 commits after v3.2 development + started. Commit identifier ``beb3611ca``. +``v3.0.2`` Stable release, tagged ``v3.0.2``. +``v3.1-beta1-75-g346d6b0ea`` Beta version in development (on a + :ref:`release branch `). + 75 commits after ``v3.1-beta1`` pre-release tag. + Commit identifier ``346d6b0ea``. +``v3.0.1-dirty`` Stable release, tagged ``v3.0.1``. + There are modifications in the local ESP-IDF + directory ("``dirty``"). +============================ ================================================== + + + +Git Workflow +------------ + +The development (Git) workflow of the Espressif ESP-IDF team is: + +- New work is always added on the master branch (latest version) first. The ESP-IDF version on ``master`` is always tagged with ``-dev`` (for "in development"), for example ``v3.1-dev``. +- Changes are first added to an internal Git repository for code review and testing, but are pushed to GitHub after automated testing passes. +- When a new version (developed on ``master``) becomes feature complete and "beta" quality, a new branch is made for the release, for example ``release/v3.1``. A pre-release tag is also created, for example ``v3.1-beta1``. You can see a full `list of branches`_ and a `list of tags`_ on GitHub. Beta pre-releases have release notes which may include a significant number of Known Issues. +- As testing of the beta version progresses, bug fixes will be added to both the ``master`` branch and the release branch. New features (for the next release) may start being added to ``master`` at the same time. +- Once testing is nearly complete a new release candidate is tagged on the release branch, for example ``v3.1-rc1``. This is still a pre-release version. +- If no more significant bugs are found or reported then the final Major or Minor Version is tagged, for example ``v3.1``. This version appears on the `Releases page`_. +- As bugs are reported in released versions, the fixes will continue to be committed to the same release branch. +- Regular bugfix releases are made from the same release branch. After manual testing is complete, a bugfix release is tagged (i.e. ``v3.1.1``) and appears on the `Releases page`_. + +.. _updating: + +Updating ESP-IDF +---------------- + +Updating ESP-IDF depends on which version(s) you wish to follow: + +- :ref:`updating-stable-releases` is recommended for production use. +- :ref:`updating-master` is recommended for latest features, development use, and testing. +- :ref:`updating-release-branch` is a compromise between these two. + +.. note:: These guides assume you already have a local copy of ESP-IDF. To get one, follow the :doc:`Getting Started ` guide for any ESP-IDF version. + +.. _`updating-stable-releases`: + +Updating to Stable Release +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +To update to new ESP-IDF releases (recommended for production use), this is the process to follow: + +- Check the `Releases page`_ regularly for new releases. +- When a bugfix release for a version you are using is released (for example if using ``v3.0.1`` and ``v3.0.2`` is available), check out the new bugfix version into the existing ESP-IDF directory:: + + cd $IDF_PATH + git fetch + git checkout vX.Y.Z + git submodule update --init --recursive +- When major or minor updates are released, check the Release Notes on the releases page and decide if you would like to update or to stay with your existing release. Updating is via the same Git commands shown above. + +.. note:: If you installed the stable release via zip file rather than using git, it may not be possible to change versions this way. In this case, update by downloading a new zip file and replacing the entire ``IDF_PATH`` directory with its contents. + + +.. _`updating-pre-release`: + +Updating to a Pre-Release Version +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +It is also possible to ``git checkout`` a tag corresponding to a pre-release version or release candidate, the process is the same as :ref:`updating-stable-releases`. + +Pre-release tags are not always found on the `Releases page`_. Consult the `list of tags`_ on GitHub for a full list. Caveats for using a pre-release are similar to :ref:`updating-release-branch`. + +.. _`updating-master`: + +Updating to Master Branch +^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. note:: Using Master branch means living "on the bleeding edge" with the latest ESP-IDF code. + +To use the latest version on the ESP-IDF master branch, this is the process to follow: + +- Check out the master branch locally:: + + cd $IDF_PATH + git checkout master + git pull + git submodule update --init --recursive +- Periodically, re-run ``git pull`` to pull the latest version of master. Note that you may need to change your project or report bugs after updating master branch. +- To switch from ``master`` to a release branch or stable version, run ``git checkout`` as shown in the other sections. + +.. important:: It is strongly recommended to regularly run ``git pull`` and then ``git submodule update --init --recursive`` so a local copy of ``master`` does not get too old. Arbitrary old master branch revisions are effectively unsupportable "snapshots" that may have undocumented bugs. For a semi-stable version, try :ref:`updating-release-branch` instead. + +.. _`updating-release-branch`: + +Updating to a Release Branch +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +In stability terms, using a release branch is part-way between using ``master`` branch and only using stable releases. A release branch is always beta quality or better, and receives bug fixes before they appear in each stable release. + +You can find a `list of branches`_ on GitHub. + +For example, to follow the branch for ESP-IDF v3.1, including any bugfixes for future releases like ``v3.1.1``, etc:: + + cd $IDF_PATH + git fetch + git checkout release/v3.1 + git pull + git submodule --update --init --recursive + +Each time you ``git pull`` this branch, ESP-IDF will be updated with fixes for this release. + +.. note:: The is no dedicated documentation for release branches. It is recommended to use the documentation for the closest version to the branch which is currently checked out. + +.. _`Releases page`: http://github.com/espressif/esp-idf/releases +.. _`list of branches`: https://github.com/espressif/esp-idf/branches +.. _`list of tags`: https://github.com/espressif/esp-idf/tags +.. _`current stable version`: https://docs.espressif.com/projects/esp-idf/en/stable/ diff --git a/docs/gen-version-specific-includes.py b/docs/gen-version-specific-includes.py new file mode 100755 index 0000000000..a295e4b6a7 --- /dev/null +++ b/docs/gen-version-specific-includes.py @@ -0,0 +1,182 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +# Python script to generate ReSTructured Text .inc snippets +# with version-based content for this IDF version + +import subprocess +import os +import sys +import re + +TEMPLATES = { + "en" : { + "git-clone" : { + "template" : """ +To obtain a local copy: open terminal, navigate to the directory you want to put ESP-IDF, and clone the repository using ``git clone`` command:: + + cd ~/esp + git clone %(clone_args)s--recursive https://github.com/espressif/esp-idf.git + +ESP-IDF will be downloaded into ``~/esp/esp-idf``. + +.. 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 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 + "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" : { + "template" : """ +获取本地副本:打开终端,切换到你要存放 ESP-IDF 的工作目录,使用 ``git clone`` 命令克隆远程仓库:: + + cd ~/esp + git clone %(clone_args)s--recursive https://github.com/espressif/esp-idf.git + +ESP-IDF 将会被下载到 ``~/esp/esp-idf`` 目录下。 + +.. 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` 供参考。 + 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:: + 这是ESP-IDF 稳定版本 %s 的文档,还有其他版本的文档 :doc:`/versions` 供参考。 +""" + ,"branch" : """ +.. note:: + 这是ESP-IDF %s ``%s`` 版本的文档,还有其他版本的文档 :doc:`/versions` 供参考。 +""" + }, # version-note + }# zh_CN +} + + +def main(): + if len(sys.argv) != 3: + print("Usage: gen-git-clone.py ") + sys.exit(1) + + language = sys.argv[1] + out_dir = sys.argv[2] + if not os.path.exists(out_dir): + print("Creating directory %s" % out_dir) + os.mkdir(out_dir) + + template = TEMPLATES[language] + + version, ver_type, is_stable = get_version() + + write_git_clone_inc(template["git-clone"], out_dir, version, ver_type, is_stable) + write_version_note(template["version-note"], out_dir, version, ver_type, is_stable) + print("Done") + + +def write_git_clone_inc(template, out_dir, version, ver_type, is_stable): + zipfile = template["zipfile"] + if version == "master": + args = { + "clone_args" : "", + "extra_note" : template["master"], + "zipfile_note" : zipfile["unstable"] + } + else: + args = { + "clone_args" : "-b %s " % version, + "extra_note" : template["branch"] % {"clone_arg" : version, "ver_type" : ver_type}, + "zipfile_note" : zipfile["stable"] if is_stable else zipfile["unstable"] + } + out_file = os.path.join(out_dir, "git-clone.inc") + with open(out_file, "w") as f: + f.write(template["template"] % args) + print("%s written" % out_file) + + +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") as f: + f.write(content) + print("%s written" % out_file) + + +def get_version(): + """ + Returns a tuple of (name of branch/tag, type branch/tag, is_stable) + """ + # Trust what RTD says our version is, if it is set + version = os.environ.get("READTHEDOCS_VERSION", None) + if version == "latest": + return ("master", "branch", False) + + # Otherwise, use git to look for a tag + try: + tag = subprocess.check_output(["git", "describe", "--tags", "--exact-match"]).strip() + is_stable = re.match(r"v[0-9\.]+$", tag) is not None + return (tag, "tag", is_stable) + except subprocess.CalledProcessError: + pass + + # No tag, look for a branch + refs = subprocess.check_output(["git", "for-each-ref", "--points-at", "HEAD", "--format", "%(refname)"]) + print("refs:\n%s" % refs) + refs = refs.split("\n") + # Note: this looks for branches in 'origin' because GitLab CI doesn't check out a local branch + branches = [ r.replace("refs/remotes/origin/","").strip() for r in refs if r.startswith("refs/remotes/origin/") ] + if len(branches) == 0: + # last resort, return the commit (may happen on Gitlab CI sometimes, unclear why) + return (subprocess.check_output(["git", "rev-parse", "--short", "HEAD"]).strip(), "commit", False) + if "master" in branches: + return ("master", "branch", False) + else: + return (branches[0], "branch", False) # take whatever the first branch is + +if __name__ == "__main__": + main() diff --git a/docs/issue_template.md b/docs/issue_template.md index 2273fe3fd7..7f7576572b 100644 --- a/docs/issue_template.md +++ b/docs/issue_template.md @@ -7,7 +7,7 @@ INSTRUCTIONS Before submitting a new issue, please follow the checklist and try to find the answer. -- [ ] I have read the documentation [ESP-IDF Programming Guide](http://esp-idf.readthedocs.io/en/latest/) and the issue is not addressed there. +- [ ] I have read the documentation [ESP-IDF Programming Guide](https://docs.espressif.com/projects/esp-idf/en/latest/) and the issue is not addressed there. - [ ] I have updated my IDF branch (master or release) to the latest version and checked that the issue is present there. - [ ] I have searched the issue tracker for a similar issue and not found a similar issue. @@ -15,7 +15,7 @@ If the issue cannot be solved after the steps before, please follow these instru 1. Fill in all the fields under **Environment** marked with [ ] by picking the correct option for you in each case and deleting the others. 2. Describe your problem. -3. Include [debug logs on the monitor](http://esp-idf.readthedocs.io/en/latest/get-started/idf-monitor.html#automatically-decoding-addresses) or the [coredump](http://esp-idf.readthedocs.io/en/latest/api-guides/core_dump.html). +3. Include [debug logs on the monitor](https://docs.espressif.com/projects/esp-idf/en/latest/get-started/idf-monitor.html#automatically-decoding-addresses) or the [coredump](https://docs.espressif.com/projects/esp-idf/en/latest/api-guides/core_dump.html). 4. Provide more items under **Other items if possible** can help us better locate your problem. 5. Use markup (buttons above) and the Preview tab to check what the issue will look like. 6. Delete these instructions from the above to the below marker lines before submitting this issue. diff --git a/docs/zh_CN/Makefile b/docs/zh_CN/Makefile index cc32abbd51..bf7ce5d14f 100644 --- a/docs/zh_CN/Makefile +++ b/docs/zh_CN/Makefile @@ -1,201 +1,2 @@ -# Makefile for Sphinx documentation -# - -# You can set these variables from the command line. -SPHINXOPTS = -SPHINXBUILD = sphinx-build -PAPER = -BUILDDIR = _build - -# User-friendly check for sphinx-build -ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1) -$(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/) -endif - -# Internal variables. -PAPEROPT_a4 = -D latex_paper_size=a4 -PAPEROPT_letter = -D latex_paper_size=letter -ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) -w sphinx-warning-log.txt . -# the i18n builder cannot share the environment and doctrees with the others -I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . - -.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext - -help: - @echo "Please use \`make ' where is one of" - @echo " html to make standalone HTML files" - @echo " dirhtml to make HTML files named index.html in directories" - @echo " singlehtml to make a single large HTML file" - @echo " pickle to make pickle files" - @echo " json to make JSON files" - @echo " htmlhelp to make HTML files and a HTML help project" - @echo " qthelp to make HTML files and a qthelp project" - @echo " devhelp to make HTML files and a Devhelp project" - @echo " epub to make an epub" - @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" - @echo " latexpdf to make LaTeX files and run them through pdflatex" - @echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx" - @echo " text to make text files" - @echo " man to make manual pages" - @echo " texinfo to make Texinfo files" - @echo " info to make Texinfo files and run them through makeinfo" - @echo " gettext to make PO message catalogs" - @echo " changes to make an overview of all changed/added/deprecated items" - @echo " xml to make Docutils-native XML files" - @echo " pseudoxml to make pseudoxml-XML files for display purposes" - @echo " linkcheck to check all external links for integrity" - @echo " doctest to run all doctests embedded in the documentation (if enabled)" - -clean: - rm -rf $(BUILDDIR)/* - -html: - $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html - @echo - @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." - -dirhtml: - $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml - @echo - @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." - -singlehtml: - $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml - @echo - @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." - -pickle: - $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle - @echo - @echo "Build finished; now you can process the pickle files." - -json: - $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json - @echo - @echo "Build finished; now you can process the JSON files." - -htmlhelp: - $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp - @echo - @echo "Build finished; now you can run HTML Help Workshop with the" \ - ".hhp project file in $(BUILDDIR)/htmlhelp." - -qthelp: - $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp - @echo - @echo "Build finished; now you can run "qcollectiongenerator" with the" \ - ".qhcp project file in $(BUILDDIR)/qthelp, like this:" - @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/ReadtheDocsTemplate.qhcp" - @echo "To view the help file:" - @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/ReadtheDocsTemplate.qhc" - -devhelp: - $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp - @echo - @echo "Build finished." - @echo "To view the help file:" - @echo "# mkdir -p $$HOME/.local/share/devhelp/ReadtheDocsTemplate" - @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/ReadtheDocsTemplate" - @echo "# devhelp" - -epub: - $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub - @echo - @echo "Build finished. The epub file is in $(BUILDDIR)/epub." - -latex: - $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex - @echo - @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." - @echo "Run \`make' in that directory to run these through (pdf)latex" \ - "(use \`make latexpdf' here to do that automatically)." - -latexpdf: - $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex - @echo "Running LaTeX files through pdflatex..." - $(MAKE) -C $(BUILDDIR)/latex all-pdf - @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." - -latexpdfja: - $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex - @echo "Running LaTeX files through platex and dvipdfmx..." - $(MAKE) -C $(BUILDDIR)/latex all-pdf-ja - @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." - -text: - $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text - @echo - @echo "Build finished. The text files are in $(BUILDDIR)/text." - -man: - $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man - @echo - @echo "Build finished. The manual pages are in $(BUILDDIR)/man." - -texinfo: - $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo - @echo - @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." - @echo "Run \`make' in that directory to run these through makeinfo" \ - "(use \`make info' here to do that automatically)." - -info: - $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo - @echo "Running Texinfo files through makeinfo..." - make -C $(BUILDDIR)/texinfo info - @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." - -gettext: - $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale - @echo - @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." - -changes: - $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes - @echo - @echo "The overview file is in $(BUILDDIR)/changes." - -linkcheck: - $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck - @echo - @echo "Link check complete; look for any errors in the above output " \ - "or in $(BUILDDIR)/linkcheck/output.txt." - -gh-linkcheck: - @echo "Checking for hardcoded GitHub links" - @if (find ../ -name '*.rst' | xargs grep \ - 'https://github.com/espressif/esp-idf/tree\|https://github.com/espressif/esp-idf/blob\|https://github.com/espressif/esp-idf/raw'\ - ); \ - then \ - echo "WARNINIG: Some .rst files contain hardcoded Github links."; \ - echo "Please check above output and replace links with one of the following:"; \ - echo "- :idf:\`dir\` - points to directory inside ESP-IDF"; \ - echo "- :idf_file:\`file\` - points to file inside ESP-IDF"; \ - echo "- :idf_raw:\`file\` - points to raw view of the file inside ESP-IDF"; \ - echo "- :component:\`dir\` - points to directory inside ESP-IDF components dir"; \ - echo "- :component_file:\`file\` - points to file inside ESP-IDF components dir"; \ - echo "- :component_raw:\`file\` - points to raw view of the file inside ESP-IDF"; \ - echo " components dir"; \ - echo "- :example:\`dir\` - points to directory inside ESP-IDF examples dir"; \ - echo "- :example_file:\`file\` - points to file inside ESP-IDF examples dir"; \ - echo "- :example_raw:\`file\` - points to raw view of the file inside ESP-IDF"; \ - echo " examples dir"; \ - echo "These link types will point to the correct GitHub version automatically"; \ - exit 1; \ - fi - @echo "No hardcoded links found" - -doctest: - $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest - @echo "Testing of doctests in the sources finished, look at the " \ - "results in $(BUILDDIR)/doctest/output.txt." - -xml: - $(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml - @echo - @echo "Build finished. The XML files are in $(BUILDDIR)/xml." - -pseudoxml: - $(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml - @echo - @echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml." +LANGUAGE=zh_CN +include ../docs_common.mk diff --git a/docs/zh_CN/api-guides/blufi.rst b/docs/zh_CN/api-guides/blufi.rst new file mode 100644 index 0000000000..1f9ec8905f --- /dev/null +++ b/docs/zh_CN/api-guides/blufi.rst @@ -0,0 +1,427 @@ +BluFi +^^^^^ + +概览 +----- +BluFi 是一款基于蓝牙通道的 Wi-Fi 网络配置功能,适用于 ESP32。它通过安全协议将 Wi-Fi 配置和证书传输到 ESP32,然后 ESP32 可基于这些信息连接到 AP 或建立 SoftAP。 + +BluFi 流程的关键部分包括数据的分片、加密、校验和验证。 + +用户可按需自定义用于对称加密、非对称加密和校验的算法。这里我们采用 DH 算法进行密钥协商、128-AES 算法用于数据加密、CRC16 算法用于校验和验证。 + +BluFi 流程 +---------- +BluFi 配网功能包含配置 SoftAP 和 Station 两部分。 + +下面以配置 Station 为例说明配置步骤。 +BluFi 配网的配置 Station 包含广播、连接、服务发现、协商共享密钥、传输数据、回传连接状态等步骤。 + +ESP32 配网流程 +-------------- + +1. ESP32 开启 GATT Server 功能,发送带有特定 *adv data* 的广播。你可以自定义该广播,该广播不属于 BluFi Profile。 + +2. 使用手机 APP 搜索到该特定广播,手机作为 GATT Client 连接 ESP32。你可以决定使用哪款手机 APP。 + +3. GATT 连接建立成功后,手机向 ESP32 发送“协商过程”数据帧(详情见 :ref:`frame_formats` )。 + +4. ESP32 收到“协商过程”数据帧后,会按照使用者自定义的协商过程来解析。 + +5. 手机与 ESP32 进行密钥协商。协商过程可使用 DH/RSA/ECC 等加密算法进行。 + +6. 协商结束后,手机端向 ESP32 发送“设置安全模式”控制帧。 + +7. ESP32 收到“设置安全模式”控制帧后,使用经过协商的共享密钥以及配置的安全策略对通信数据进行加密和解密。 + +8. 手机向 ESP32 发送“BluFi 传输格式”定义的 SSID、Password 等用于 Wi-Fi 连接的必要信息。 + +9. 手机向 ESP32 发送“Wi-Fi 连接请求”控制帧,ESP32 收到之后,识别为手机已将必要的信息传输完毕,准备连接 Wi-Fi。 + +10. ESP32 连接到 Wi-Fi 后,发送“Wi-Fi 连接状态报告”控制帧到手机,以报告连接状态。至此配网结束。 + +.. note:: + + 1. 安全模式设置可在任何时候进行,ESP32 收到安全模式的配置后,会根据安全模式指定的模式进行安全相关的操作。 + + 2. 进行对称加密和解密时,加密和解密前后的数据长度必须一致,支持原地加密和解密。 + +配网流程图 +----------- + +.. seqdiag:: + :caption: BluFi Flow Chart + :align: center + + seqdiag blufi { + activation = none; + node_width = 80; + node_height = 60; + edge_length = 380; + 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: 连接状态报告"]; + } + +.. _frame_formats: + +BluFi 传输格式 +-------------- + +手机 APP 与 ESP32 之间的 BluFi 通信格式定义如下: + +帧不分片情况下的标准格式 (8 bit): + ++------------+---------------+-----------------+-------------+----------------+----------------+ +| LSB - Type | Frame Control | Sequence Number | Data Length | Data | MSB - CheckSum | ++============+===============+=================+=============+================+================+ +| 1 | 1 | 1 | 1 | ${Data Length} | 2 | ++------------+---------------+-----------------+-------------+----------------+----------------+ + +如果 **Frame Control** 帧中的 **More Frag** 使能,则 **Total Content Length** 为数据帧中剩余部分的总长度,用于报告终端需要分配多少内存。 + +帧分片格式(8 bit): + ++------------+--------------------+----------------+------------+-------------------------------------------+----------------+ +| LSB - Type | FrameControl(Frag) | SequenceNumber | DataLength | Data | MSB - CheckSum | ++ + + + +----------------------+--------------------+ + +| | | | | Total Content Length | Content | | ++============+====================+================+============+======================+====================+================+ +| 1 | 1 | 1 | 1 | 2 | ${Data Length} - 2 | 2 | ++------------+--------------------+----------------+------------+----------------------+--------------------+----------------+ + +通常情况下,控制帧不包含数据位,Ack 帧类型除外。 + +Ack 帧格式(8 bit): + ++------------------+---------------+-----------------+-------------+-----------------------+----------------+ +| LSB - Type (Ack) | Frame Control | SequenceNumber | Data Length | Data | MSB - CheckSum | ++ + + + +-----------------------+ + +| | | | | Acked Sequence Number | | ++==================+===============+=================+=============+=======================+================+ +| 1 | 1 | 1 | 1 | 1 | 2 | ++------------------+---------------+-----------------+-------------+-----------------------+----------------+ + +1. Type + + 类型域,占 1 byte。分为 Type 和 Subtype(子类型域)两部分, Type 占低 2 bit,Subtype 占高 6 bit。 + + * 控制帧,暂不进行加密,可校验; + + * 数据帧,可加密,可校验。 + + **1.1 控制帧 (0x0b’00)** + + +------------------+-----------------------------------+----------------------------------------------------------------+----------------------------------------------------------------------+ + | 控制帧 / 0x0b’00 | 含义 | 解释 | 备注 | + +==================+===================================+================================================================+======================================================================+ + | 0x0b’000000 | Ack | 用来回复对方发的帧, | Data 域使用1 byte Sequence 值, | + | | | Ack 帧的 Data 域使用回复对象帧的 Sequence 值。 | 与恢复对象帧的Sequence 值相同。 | + +------------------+-----------------------------------+----------------------------------------------------------------+----------------------------------------------------------------------+ + | 0x1b’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:有校验、有加密。 | + +------------------+-----------------------------------+----------------------------------------------------------------+----------------------------------------------------------------------+ + | 0x2b’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 等。 | + +------------------+-----------------------------------+----------------------------------------------------------------+----------------------------------------------------------------------+ + | 0x3b’000011 | Connect ESP32 to the AP. | 通知 ESP32,必要的信息已经发送完毕,可以连接 AP。 | 不包含 Data 域。 | + +------------------+-----------------------------------+----------------------------------------------------------------+----------------------------------------------------------------------+ + | 0x4b’000100 | Disconnect ESP32 from the AP. | 通知 ESP32 断开与 AP 的连接 | 不包含 Data 域。 | + +------------------+-----------------------------------+----------------------------------------------------------------+----------------------------------------------------------------------+ + | 0x5b’000101 | Get the status of Wi-Fi. | 获取 ESP32 的 Wi-Fi 模式和状态等信息。 | 不包含 Data 域。 | + | | | | ESP32 收到此控制帧后,后续会通过 Wi-Fi 连接状态 | + | | | | 报告 (Wi-Fi Connection State Report) 数据帧来回复手机端当前 | + | | | | 所处的 opmode、连接状态、SSID 等信息。提供给手机端的信息由应用决定。 | + +------------------+-----------------------------------+----------------------------------------------------------------+----------------------------------------------------------------------+ + | 0x6b’000110 | Disconnect the STA device | 处于 SoftAP 模式时,踢掉某个 STA 设备。 | data[0~5] 为 STA 设备的 MAC 地址, | + | | from the SoftAP in SoftAP mode. | | 如有多个 STA,则 [6-11] 为第二个,依次类推。 | + +------------------+-----------------------------------+----------------------------------------------------------------+----------------------------------------------------------------------+ + | 0x7b'000111 | Get the version. | | | + +------------------+-----------------------------------+----------------------------------------------------------------+----------------------------------------------------------------------+ + | 0x8b’001000 | Tell ESP32 to disconnect | 通知 ESP32 断开蓝牙连接。 | ESP32 收到该指令后主动断开蓝牙连接。 | + | | the BLE GATT link. | | | + +------------------+-----------------------------------+----------------------------------------------------------------+----------------------------------------------------------------------+ + | 0x9b’001001 | Tell ESP32 to get the Wi-Fi list. | 通知 ESP32 扫描周围的 Wi-Fi 热点 | 不包含 Data 域。 | + | | | | ESP32 收到此控制帧后,会发送包含 Wi-Fi 热点 | + | | | | 报告 (Wi-Fi List Report) 的数据帧回复 | + | | | | 手机端 ESP32 周围的 Wi-Fi 热点。 | + +------------------+-----------------------------------+----------------------------------------------------------------+----------------------------------------------------------------------+ + + **1.2 数据帧 (0x1b’01)** + + +---------------+----------------------------------------+------------------------------------------------+------------------------------------------------------+ + | 数据帧 | 含义 | 解释 | 备注 | + +===============+========================================+================================================+======================================================+ + | 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 到手机时, | + | | | | 表示向手机端提供信息。 | + +---------------+----------------------------------------+------------------------------------------------+------------------------------------------------------+ + | 0x7b’000111 | Authentication mode for SoftAP mode. | AP 模式的认证模式。 | data[0]: | + + + + +------------------------------------------------------+ + | | | | 0x00: OPEN; | + + + + +------------------------------------------------------+ + | | | | 0x01: WEP; | + + + + +------------------------------------------------------+ + | | | | 0x02: WPA_PSK; | + + + + +------------------------------------------------------+ + | | | | 0x03: WPA2_PSK; | + + + + +------------------------------------------------------+ + | | | | 0x04: WPA_WPA2_PSK. | + + + + +------------------------------------------------------+ + | | | | 当传输方向为 ESP32 到手机时, | + | | | | 表示向手机端提供信息。 | + +---------------+----------------------------------------+------------------------------------------------+------------------------------------------------------+ + | 0x8b’001000 | Channel for SoftAP mode. | SoftAP 模式的通道数量。 | data[0] 表示通道的数量,范围 1~14。 | + + + + +------------------------------------------------------+ + | | | | 当传输方向为 ESP32 到手机时, | + | | | | 表示向手机端提供信息。 | + +---------------+----------------------------------------+------------------------------------------------+------------------------------------------------------+ + | 0x9b’001001 | Username. | 使用企业级加密时,Client 端的用户名。 | 数据长度与 Length 域有关。 | + +---------------+----------------------------------------+------------------------------------------------+------------------------------------------------------+ + | 0xab’001010 | CA certification. | 进行企业级加密时使用的 CA 证书。 | 数据长度与 Length 域有关, | + | | | | 长度不够,可用分片。 | + +---------------+----------------------------------------+------------------------------------------------+------------------------------------------------------+ + | 0xbb’001011 | Client certification. | 进行企业级加密时,Client 端的证书。 | 数据长度与 Length 域有关, | + + + +------------------------------------------------+ 长度不够,可用分片。 + + | | | 可包含或不包含私钥,由证书内容决定。 | | + +---------------+----------------------------------------+------------------------------------------------+------------------------------------------------------+ + | 0xcb’001100 | Server certification. | 进行企业级加密时,Server 端的证书。 | 数据长度与 Length 域有关, | + + + +------------------------------------------------+ 长度不够,可用分片。 + + | | | 可包含或不包含私钥,由证书内容决定。 | | + +---------------+----------------------------------------+------------------------------------------------+------------------------------------------------------+ + | 0xdb’001101 | Client private key. | 进行企业级加密时,Client 端的私钥。 | 数据长度与 Length 域有关, | + | | | | 长度不够,可用分片。 | + +---------------+----------------------------------------+------------------------------------------------+------------------------------------------------------+ + | 0xeb’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. | 用户发送或者接收自定义数据。 | 数据较长时可分片发送。 | + +---------------+----------------------------------------+------------------------------------------------+------------------------------------------------------+ + +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 保留 | | + +----------------+-------------------------------------------------------------------------------------------------------------------------------+ + + +3. Sequence Control + + 序列控制域。帧发送时,无论帧的类型是什么,序列 (Sequence) 都会自动加 1,用来防止重放攻击 (Replay Attack)。每次重现连接后,序列清零。 + +4. Length + + Data 域的长度,不包含 CheckSum。 + +5. Data + + 不同的 Type 或 Subtype,Data 域的含义均不同。请参考上方表格。 + +6. CheckSum + + 此域为 2 byte 的校验,用来校验『序列 + 数据长度 + 明文数据』。 + +ESP32 端的安全实现 +------------------ + +1. 保证数据安全 + + 为了保证 Wi-Fi SSID 和密码的传输过程是安全的,需要使用对称加密算法(例如 AES、DES等)对报文进行加密。在使用对称加密算法之前,需要使用非对称加密算法(DH、RSA、ECC 等)协商出(或生成出)一个共享密钥。 + +2. 保证数据完整性 + + 保证数据完整性,需要加入校验算法(例如 SHA1、MD5、CRC 等)。 + +3. 身份安全(签名) + + 某些算法如 RSA 可以保证身份安全。有些算法如 DH,本身不能保证身份安全,需要添加其他算法来签名。 + +4. 防止重放攻击 (Replay Attack) + + 加入帧发送序列(Sequence),并且序列参与数据校验。 + + 在 ESP32 端的代码中,你可以决定和开发密钥协商等安全处理的流程参考上述流程图)。手机应用向 ESP32 发送协商数据,将传送给应用层处理。如果应用层不处理,可使用 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); + +该函数用来接收协商期间的正常数据 (normal data),处理完成后,需要将待发送的数据使用 output_data 和 output_len 传出。 + +BluFi 会在调用完 negotiate_data_handler 后,发送 negotiate_data_handler 传出的 output_data。 + +这里的两个『*』,因为需要发出去的数据长度未知,所以需要函数自行分配 (malloc) 或者指向全局变量,通过 need_free 通知是否需要释放内存。 + +.. code-block:: c + + typedef int (* esp_blufi_encrypt_func_t)(uint8_t iv8, uint8_t *crypt_data, int cyprt_len); + +加密和解密的数据长度必须一致。其中 iv8 为帧的 8 bit 序列 (sequence),可作为 iv 的某 8 bit 来使用。 + +.. code-block:: c + + typedef int (* esp_blufi_decrypt_func_t)(uint8_t iv8, uint8_t *crypt_data, int crypt_len); + +加密和解密的数据长度必须一致。其中 iv8 为帧的 8 bit 序列 (sequence),可作为 iv 的某 8 bit 来使用。 + +.. code-block:: c + + typedef uint16_t (*esp_blufi_checksum_func_t)(uint8_t iv8, uint8_t *data, int len); + +该函数用来计算 CheckSum,返回值为 CheckSum 的值。BluFi 会使用该函数返回值与包末尾的 CheckSum 做比较。 + +GATT 相关说明 +------------- + +UUID +>>>>> + +BluFi Service UUID: 0xFFFF,16 bit + +BluFi (手机 -> ESP32) 特性:0xFF01,主要权限:可写 + +BluFi (ESP32 -> 手机) 特性:0xFF02,主要权限:可读可通知 + +.. note:: + + 1. 目前 Ack 机制已经在该 Profile 协议中定义,但是还没有代码实现。 + + 2. 其他部分均已实现。 diff --git a/docs/zh_CN/api-guides/error-handling.rst b/docs/zh_CN/api-guides/error-handling.rst new file mode 100644 index 0000000000..7a85b9706f --- /dev/null +++ b/docs/zh_CN/api-guides/error-handling.rst @@ -0,0 +1 @@ +.. include:: ../../en/api-guides/error-handling.rst \ No newline at end of file diff --git a/docs/zh_CN/api-guides/fatal-errors.rst b/docs/zh_CN/api-guides/fatal-errors.rst new file mode 100644 index 0000000000..e9e5b71701 --- /dev/null +++ b/docs/zh_CN/api-guides/fatal-errors.rst @@ -0,0 +1 @@ +.. include:: ../../en/api-guides/fatal-errors.rst \ 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 a6a7d85661..0a0f9c8e9b 100644 --- a/docs/zh_CN/api-guides/index.rst +++ b/docs/zh_CN/api-guides/index.rst @@ -1 +1,30 @@ -.. include:: ../../en/api-guides/index.rst \ No newline at end of file +API Guides +********** + +.. toctree:: + :maxdepth: 1 + + General Notes + Build System + Build System (CMake) + Error Handling + Fatal Errors + Deep Sleep Wake Stubs + ESP32 Core Dump + Flash Encryption <../security/flash-encryption> + FreeRTOS SMP Changes + Thread Local Storage + High Level Interrupts + JTAG Debugging + Bootloader + Partition Tables + Secure Boot <../security/secure-boot> + ULP Coprocessor + Unit Testing + Application Level Tracing + Console Component + ROM debug console + WiFi Driver + Mesh Stack + BluFi + External SPI-connected RAM diff --git a/docs/zh_CN/api-reference/error-codes.rst b/docs/zh_CN/api-reference/error-codes.rst new file mode 100644 index 0000000000..5179dae2cf --- /dev/null +++ b/docs/zh_CN/api-reference/error-codes.rst @@ -0,0 +1 @@ +.. include:: ../../en/api-reference/error-codes.rst \ No newline at end of file diff --git a/docs/zh_CN/api-reference/system/esp_err.rst b/docs/zh_CN/api-reference/system/esp_err.rst new file mode 100644 index 0000000000..1edde443d4 --- /dev/null +++ b/docs/zh_CN/api-reference/system/esp_err.rst @@ -0,0 +1 @@ +.. include:: ../../../en/api-reference/system/esp_err.rst diff --git a/docs/zh_CN/api-reference/system/esp_https_ota.rst b/docs/zh_CN/api-reference/system/esp_https_ota.rst new file mode 100644 index 0000000000..e831ef944b --- /dev/null +++ b/docs/zh_CN/api-reference/system/esp_https_ota.rst @@ -0,0 +1 @@ +.. include:: ../../../en/api-reference/system/esp_https_ota.rst diff --git a/docs/zh_CN/get-started/eclipse-setup-windows.rst b/docs/zh_CN/get-started/eclipse-setup-windows.rst index dbd07b5656..c8497dc64a 100644 --- a/docs/zh_CN/get-started/eclipse-setup-windows.rst +++ b/docs/zh_CN/get-started/eclipse-setup-windows.rst @@ -40,17 +40,17 @@ Windows 平台上的 Eclipse 配置 项目属性 ---------- -* 新项目将出现在 “Project Explorer” 下。请右键选择该项目,并在菜单中选择顶层 “Properties”。 +* 新项目将出现在 “Project Explorer” 下。请右键选择该项目,并在菜单中选 “Properties”。 * 点击 “C/C++ Build” 属性页。 - * 取消选中 “Use default build command”,然后输入命令:``python${IDF_PATH}/tools/windows/eclipse_make.py``,开始自定义创建。 + * 取消选中 “Use default build command”,然后输入命令开始自定义创建:``python ${IDF_PATH}/tools/windows/eclipse_make.py`` * 点击 “C/C++ Build” 下的 “Environment” 属性页面。 * 选择 “Add...”,并在对应位置输入 ``BATCH_BUILD`` 和 ``1``。 - * 再次点击 “Add...”,输入名称 ``IDF_PATH``,并填写 ESP-IDF 的完整安装路径。``IDF_PATH`` 目录路径应使用正斜杠,而非反斜线,即 ``C:/Users/user-name/Development/esp-idf``。 + * 再次点击 “Add...”,输入名称 ``IDF_PATH``,并填写 ESP-IDF 的完整安装路径。``IDF_PATH`` 目录路径应使用正斜杠,而非反斜线,例如 ``C:/Users/user-name/Development/esp-idf``。 * 选择 PATH 环境变量,删除默认值,并将其替换为 ``C:\msys32\usr\bin;C:\msys32\mingw32\bin;C:\msys32\opt\xtensa-esp32-elf\bin`` (如果您已经将 msys32 安装到其他目​​录,这里请自行调整)。 @@ -58,11 +58,18 @@ Windows 平台上的 Eclipse 配置 * 点击 “C/C++ General” -> “Preprocessor Include Paths, Macros, etc.” 属性页。 * 点击 “Providers” 选项卡。 - - * 从 “Providers” 列表中选择 “CDT GCC Built-in Compiler Settings Cygwin”。在 “Command to get compiler specs” 输入框中,用 ``xtensa-esp32-elf-gcc`` 替换行首的 ``${COMMAND}``,最终完整的 ``Command to get compiler specs`` 应为 ``xtensa-esp32-elf-gcc ${FLAGS} -E -P -v -dD "${INPUTS}"``。 + + * 从 “Providers” 列表中选择 “CDT Cross GCC Built-in Compiler Settings”,将 “Command to get compiler specs” 修改为 ``xtensa-esp32-elf-gcc ${FLAGS} -E -P -v -dD "${INPUTS}"`` - * 从 “Providers” 列表中选择 “CDT GCC Build Output Parser”,然后在 Compiler 命令模式的起始位置输入 ``xtensa-esp32-elf-``,并用括号把剩余部分扩起来。最终的完整 Compiler 命令模式应为 ``xtensa-esp32-elf-((g?cc)|([gc]\+\+)|(clang))``。 + * 从 “Providers” 列表中选择 “CDT GCC Build Output Parser”,将 “Compiler command pattern” 修改为 ``xtensa-esp32-elf-(gcc|g\+\+|c\+\+|cc|cpp|clang)`` +点击 “C/C++ General" -> "Indexer” 属性页。 + + * 选择 “Enable project specific settings” 以启用本页上的其他设置。 + +.. note:: + + 取消选中 “Allow heuristic resolution of includes”。因为启用此选项时,有时会导致 Eclipse 无法找到正确的头文件目录。 在 Eclipse IDE 中创建项目 --------------------------- diff --git a/docs/zh_CN/get-started/eclipse-setup.rst b/docs/zh_CN/get-started/eclipse-setup.rst index e2f7be8a3c..566b7de5c5 100644 --- a/docs/zh_CN/get-started/eclipse-setup.rst +++ b/docs/zh_CN/get-started/eclipse-setup.rst @@ -57,9 +57,23 @@ Windows 用户 * 前往 “C/C++ General” -> “Preprocessor Include Paths” 属性页面。 - * 点击 “Providers” 选项卡。从 “Providers” 列表中选择 “CDT Cross GCC Built-in Compiler Settings”。在 “Command to get compiler specs” 输入框中,用 ``xtensa-esp32-elf-gcc`` 替换行首的 ``${COMMAND}``,最终的完整 “Command to get compiler specs” 应为 ``xtensa-esp32-elf-gcc ${FLAGS} -E -P -v -dD "${INPUTS}"``。 + * 点击 “Providers” 选项卡。 + + * 从 “Providers” 列表中选择 “CDT Cross GCC Built-in Compiler Settings”,将 “Command to get compiler specs” 修改为 ``xtensa-esp32-elf-gcc ${FLAGS} -E -P -v -dD "${INPUTS}"`` + + * 从 “Providers” 列表中选择 “CDT GCC Build Output Parser”,将 “Compiler command pattern” 修改为 ``xtensa-esp32-elf-(gcc|g\+\+|c\+\+|cc|cpp|clang)`` - * 从 “Providers” 列表中选择 “CDT GCC Build Output Parser”,然后在 “Compiler command pattern“ 输入框的起始位置输入 ``xtensa-esp32-elf-``,最终的完整编译器命令应为 ``xtensa-esp32-elf-(g?cc)|([gc]\+\+)|(clang)``。 +* 前往 “C/C++ General” -> “Indexer” 属性页面。 + + * 去除 "Allow heuristic resolution of includes" 勾选。启用此选项时,Eclipse 有时无法找到正确的头文件目录。 + +点击 “C/C++ General" -> "Indexer” 属性页。 + + * 选择 “Enable project specific settings” 以启用本页上的其他设置。 + +.. note:: + + 取消选中 “Allow heuristic resolution of includes”。因为启用此选项时,有时会导致 Eclipse 无法找到正确的头文件目录。 .. _eclipse-build-project: @@ -85,11 +99,11 @@ Windows 用户 * 打开 “Project Explorer”,并右击您的项目(请注意右击项目本身,而非项目下的子文件,否则 Eclipse 可能会找到错误的 ``Makefile``)。 -* 从菜单中选择 “Make Targets” -> “Create”。 +* 从菜单中选择 “Build Targets” -> “Create”。 * 输入 “flash” 为目标名称,其他选项使用默认值。 -* 选择 “Project” -> “Make Target” -> “Build (快捷键:Shift + F9)”,创建自定义烧录目标,用于编译、烧录项目。 +* 选择 “Project” -> “Build Target” -> “Build (快捷键:Shift + F9)”,创建自定义烧录目标,用于编译、烧录项目。 注意,您将需要通过 ``make menuconfig``,设置串行端口和其他烧录选项。``make menuconfig`` 仍需通过命令行操作(请见平台的对应指南)。 @@ -104,6 +118,4 @@ Windows 用户 eclipse-setup-windows -.. _eclipse.org: https://www.eclipse.org/ - - +.. _eclipse.org: https://www.eclipse.org/ \ No newline at end of file diff --git a/docs/zh_CN/get-started/idf-monitor.rst b/docs/zh_CN/get-started/idf-monitor.rst index a5b30e2d0a..5d3299d502 100644 --- a/docs/zh_CN/get-started/idf-monitor.rst +++ b/docs/zh_CN/get-started/idf-monitor.rst @@ -65,7 +65,7 @@ IDF Monitor 为转储补充如下信息:: 您可以选择配置 panic 处理函数,使其运行串行的 "gdb stub"。该程序可以与 gdb 调试器通信,提供内存,变量,栈帧读取的功能。虽然这不像 JTAG 调试那样通用,但您不需要使用特殊硬件。 -要启用 gdbstub,运行 ``make menuconfig`` 并将 :ref:`CONFIG_ESP32_PANIC` 选项设置为 ``Invoke GDBStub``。 +要启用 gdbstub,运行 ``make menuconfig`` 并将 :envvar:`CONFIG_ESP32_PANIC` 选项设置为 ``Invoke GDBStub``。 如果启用此选项并且 IDF Monitor 发现 gdbstub 已加载,它将自动暂停串口监控并使用正确的参数运行 GDB。GDB 退出后,电路板将通过 RTS 串行线路复位(如果已连接)。 diff --git a/docs/zh_CN/get-started/index.rst b/docs/zh_CN/get-started/index.rst index 2df0502a97..043569da5d 100644 --- a/docs/zh_CN/get-started/index.rst +++ b/docs/zh_CN/get-started/index.rst @@ -7,6 +7,8 @@ 本文档旨在指导用户创建 ESP32 的软件环境。本文将通过一个简单的例子来说明如何使用 ESP-IDF (Espressif IoT Development Framework),包括配置、编译、下载固件到开发板等步骤。 +.. include:: /_build/inc/version-note.inc + 概述 ====== @@ -75,7 +77,7 @@ ESP32 是一套 Wi-Fi (2.4 GHz) 和蓝牙 (4.2) 双模解决方案,集成了 :hidden: Windows - Linux + Linux MacOS +-------------------+-------------------+-------------------+ @@ -112,12 +114,11 @@ ESP32 是一套 Wi-Fi (2.4 GHz) 和蓝牙 (4.2) 双模解决方案,集成了 .. highlight:: bash -工具链(包括用于编译和构建应用程序的程序)安装完后,你还需要 ESP32 相关的 API/库。API/库在 `ESP-IDF 仓库 `_ 中。要获取这些 API/库,打开一个终端,进入某个你希望存放 ESP-IDF 的目录,然后 ``git clone`` 以下指令: :: +工具链(包括用于编译和构建应用程序的程序)安装完后,你还需要 ESP32 相关的 API/库。API/库在 `ESP-IDF 仓库 `_ 中。 - cd ~/esp - git clone --recursive https://github.com/espressif/esp-idf.git +.. include:: /_build/inc/git-clone.inc -ESP-IDF 将会被下载到 ``~/esp/esp-idf``。 +查看 :doc:/versions 以获取不同情况下选择要使用的分支的帮助。 .. note:: @@ -178,7 +179,7 @@ ESP-IDF 的 :idf:`examples` 目录下有一系列示例工程,都可以按照 :figclass: align-center 工程配置 - 主窗口 - + 在菜单中,进入 ``Serial flasher config`` > ``Default serial port`` 配置串口(工程将会加载到该串口上)。输入回车确认选择,选择 ``< Save >`` 保存配置,然后选择 ``< Exit >`` 退出应用程序。 .. note:: @@ -281,37 +282,23 @@ ESP-IDF 的 :idf:`examples` 目录下有一系列示例工程,都可以按照 e���)(Xn@�y.!��(�PW+)��Hn9a؅/9�!�t5��P�~�k��e�ea�5�jA ~zY��Y(1�,1�� e���)(Xn@�y.!Dr�zY(�jpi�|�+z5Ymvp - 或者监视器程序启动失败,那么可能你的开发板用的是 26 MHz 晶振,而 ESP-IDF 默认的是 40 MHz 晶振。请退出监视器,回到 :ref:`配置 `,将 :ref:`CONFIG_ESP32_XTAL_FREQ_SEL` 改为 26 MHz,然后再次 :ref:`编译和烧写 `。请在 ``make menuconfig`` 的 Component config --> ESP32-specific --> Main XTAL frequency 中配置。 + 或者监视器程序启动失败,那么可能你的开发板用的是 26 MHz 晶振,而 ESP-IDF 默认的是 40 MHz 晶振。请退出监视器,回到 :ref:`配置 `,将 :envvar:`CONFIG_ESP32_XTAL_FREQ_SEL` 改为 26 MHz,然后再次 :ref:`编译和烧写 `。请在 ``make menuconfig`` 的 Component config --> ESP32-specific --> Main XTAL frequency 中配置。 要一次性执行 ``make flash`` 和 ``make monitor``,输入 ``make flash monitor``。参考文档 :doc:`IDF Monitor ` 里的快捷键和更多内容。 你已完成 ESP32 的入门! -现在你可以尝试其他的示例工程 :idf:`examples`,或者直接开发自己的应用程序。 +现在你可以尝试其他的示例工程 :idf:`examples`,或者直接开发自己的应用程序。 更新 ESP-IDF ============= 使用 ESP-IDF 一段时间后,你可能想要进行升级来获得新的性能或者对 bug 进行修复。最简单的更新方式是删除已有的 ``esp-idf`` 文件夹然后再克隆一个,即重复 :ref:`get-started-get-esp-idf` 里的操作。 -另外一种方法是只更新有改动的部分,如果你不容易登陆 GitHub,那么这种方法比较合适。执行以下命令: :: - - cd ~/esp/esp-idf - git pull - git submodule update --init --recursive - -``git pull`` 指令是从 ESP-IDF 仓库中获取合并更新。``git submodule update --init --recursive`` 用来更新现有的子模块或拷贝新的子模块。在 GitHub 上,子模块链接到其他仓库,所以需要这个额外的指令来下载到你的电脑里。 - -如果你想使用某一版本的 ESP-IDF,比如 `v2.1` 版本,请执行以下指令: :: - - cd ~/esp - git clone https://github.com/espressif/esp-idf.git esp-idf-v2.1 - cd esp-idf-v2.1/ - git checkout v2.1 - git submodule update --init --recursive - 然后 :doc:`add-idf_path-to-profile`,这样工具链脚本就能够知道这一版本的 ESP-IDF 的具体位置。 +另外一种方法是只更新有改动的部分。:ref:`更新步骤取决于现在用的ESP-IDF版本 `。 + 相关文档 ================= @@ -325,3 +312,6 @@ ESP-IDF 的 :idf:`examples` 目录下有一系列示例工程,都可以按照 eclipse-setup idf-monitor toolchain-setup-scratch + +.. _Stable version: https://docs.espressif.com/projects/esp-idf/zh_CN/stable/ +.. _Releases page: https://github.com/espressif/esp-idf/releases diff --git a/docs/zh_CN/index.rst b/docs/zh_CN/index.rst index 2a961055b6..2b8a7b3747 100644 --- a/docs/zh_CN/index.rst +++ b/docs/zh_CN/index.rst @@ -45,6 +45,7 @@ ESP-IDF 编程指南 H/W 参考 API 指南 贡献代码 + 版本 相关资源 版权 关于 diff --git a/docs/zh_CN/versions.rst b/docs/zh_CN/versions.rst new file mode 100644 index 0000000000..e060a86d88 --- /dev/null +++ b/docs/zh_CN/versions.rst @@ -0,0 +1 @@ +.. include:: ../en/versions.rst diff --git a/examples/mesh/internal_transceiver/Makefile b/examples/bluetooth/a2dp_gatts_coex/Makefile similarity index 80% rename from examples/mesh/internal_transceiver/Makefile rename to examples/bluetooth/a2dp_gatts_coex/Makefile index c5ade206be..4c3cfbe06a 100644 --- a/examples/mesh/internal_transceiver/Makefile +++ b/examples/bluetooth/a2dp_gatts_coex/Makefile @@ -3,7 +3,7 @@ # project subdirectory. # -PROJECT_NAME := internal_transceiver +PROJECT_NAME := bt_ble_coex include $(IDF_PATH)/make/project.mk diff --git a/examples/bluetooth/a2dp_gatts_coex/main/bt_app_av.c b/examples/bluetooth/a2dp_gatts_coex/main/bt_app_av.c index 0b966ccda7..c015bfa621 100644 --- a/examples/bluetooth/a2dp_gatts_coex/main/bt_app_av.c +++ b/examples/bluetooth/a2dp_gatts_coex/main/bt_app_av.c @@ -53,7 +53,8 @@ void bt_app_a2d_cb(esp_a2d_cb_event_t event, esp_a2d_cb_param_t *param) void bt_app_a2d_data_cb(const uint8_t *data, uint32_t len) { - i2s_write_bytes(0, (const char *)data, len, portMAX_DELAY); + size_t bytes_written; + i2s_write(0, data, len, &bytes_written, portMAX_DELAY); if (++m_pkt_cnt % 100 == 0) { ESP_LOGI(BT_AV_TAG, "Audio packet count %u", m_pkt_cnt); } diff --git a/examples/bluetooth/a2dp_gatts_coex/main/main.c b/examples/bluetooth/a2dp_gatts_coex/main/main.c index b57e4249c2..69e4899305 100644 --- a/examples/bluetooth/a2dp_gatts_coex/main/main.c +++ b/examples/bluetooth/a2dp_gatts_coex/main/main.c @@ -636,7 +636,7 @@ void app_main() // Initialize NVS. ret = nvs_flash_init(); - if (ret == ESP_ERR_NVS_NO_FREE_PAGES) { + 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(); } @@ -703,4 +703,4 @@ void app_main() bt_app_work_dispatch(bt_av_hdl_stack_evt, BT_APP_EVT_STACK_UP, NULL, 0, NULL); //gatt server init ble_gatts_init(); -} \ No newline at end of file +} diff --git a/examples/bluetooth/a2dp_sink/main/main.c b/examples/bluetooth/a2dp_sink/main/main.c index 6fc554fa43..2b1b907fa6 100644 --- a/examples/bluetooth/a2dp_sink/main/main.c +++ b/examples/bluetooth/a2dp_sink/main/main.c @@ -46,7 +46,7 @@ void app_main() { /* Initialize NVS — it is used to store PHY calibration data */ esp_err_t ret = nvs_flash_init(); - if (ret == ESP_ERR_NVS_NO_FREE_PAGES) { + 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(); } diff --git a/examples/bluetooth/a2dp_source/main/main.c b/examples/bluetooth/a2dp_source/main/main.c index eb63362301..32ce1ea4f9 100644 --- a/examples/bluetooth/a2dp_source/main/main.c +++ b/examples/bluetooth/a2dp_source/main/main.c @@ -100,7 +100,7 @@ void app_main() { // Initialize NVS. esp_err_t ret = nvs_flash_init(); - if (ret == ESP_ERR_NVS_NO_FREE_PAGES) { + 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(); } diff --git a/examples/bluetooth/ble_adv/main/app_bt.c b/examples/bluetooth/ble_adv/main/app_bt.c index 246d87b304..0a67c32468 100644 --- a/examples/bluetooth/ble_adv/main/app_bt.c +++ b/examples/bluetooth/ble_adv/main/app_bt.c @@ -214,7 +214,7 @@ void app_main() { /* Initialize NVS — it is used to store PHY calibration data */ esp_err_t ret = nvs_flash_init(); - if (ret == ESP_ERR_NVS_NO_FREE_PAGES) { + 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(); } diff --git a/examples/bluetooth/ble_hid_device_demo/main/ble_hidd_demo_main.c b/examples/bluetooth/ble_hid_device_demo/main/ble_hidd_demo_main.c index 5efc1fb90b..3094f6bc7f 100644 --- a/examples/bluetooth/ble_hid_device_demo/main/ble_hidd_demo_main.c +++ b/examples/bluetooth/ble_hid_device_demo/main/ble_hidd_demo_main.c @@ -185,17 +185,18 @@ static void hidd_event_callback(esp_hidd_cb_event_t event, esp_hidd_cb_param_t * case ESP_HIDD_EVENT_DEINIT_FINISH: break; case ESP_HIDD_EVENT_BLE_CONNECT: { + ESP_LOGI(HID_DEMO_TAG, "ESP_HIDD_EVENT_BLE_CONNECT"); hid_conn_id = param->connect.conn_id; break; } case ESP_HIDD_EVENT_BLE_DISCONNECT: { sec_conn = false; - ESP_LOGE(HID_DEMO_TAG, "%s(), ESP_HIDD_EVENT_BLE_DISCONNECT", __func__); + ESP_LOGI(HID_DEMO_TAG, "ESP_HIDD_EVENT_BLE_DISCONNECT"); esp_ble_gap_start_advertising(&hidd_adv_params); break; } case ESP_HIDD_EVENT_BLE_VENDOR_REPORT_WRITE_EVT: { - ESP_LOGE(HID_DEMO_TAG, "%s, ESP_HIDD_EVENT_BLE_VENDOR_REPORT_WRITE_EVT", __func__); + ESP_LOGI(HID_DEMO_TAG, "%s, ESP_HIDD_EVENT_BLE_VENDOR_REPORT_WRITE_EVT", __func__); ESP_LOG_BUFFER_HEX(HID_DEMO_TAG, param->vendor_write.data, param->vendor_write.length); } default: @@ -218,7 +219,16 @@ static void gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param break; case ESP_GAP_BLE_AUTH_CMPL_EVT: sec_conn = true; - ESP_LOGE(HID_DEMO_TAG, "staus =%s, ESP_GAP_BLE_AUTH_CMPL_EVT",param->ble_security.auth_cmpl.success ? "success" : "fail"); + esp_bd_addr_t bd_addr; + memcpy(bd_addr, param->ble_security.auth_cmpl.bd_addr, sizeof(esp_bd_addr_t)); + ESP_LOGI(HID_DEMO_TAG, "remote BD_ADDR: %08x%04x",\ + (bd_addr[0] << 24) + (bd_addr[1] << 16) + (bd_addr[2] << 8) + bd_addr[3], + (bd_addr[4] << 8) + bd_addr[5]); + ESP_LOGI(HID_DEMO_TAG, "address type = %d", param->ble_security.auth_cmpl.addr_type); + ESP_LOGI(HID_DEMO_TAG, "pair status = %s",param->ble_security.auth_cmpl.success ? "success" : "fail"); + if(!param->ble_security.auth_cmpl.success) { + ESP_LOGE(HID_DEMO_TAG, "fail reason = 0x%x",param->ble_security.auth_cmpl.fail_reason); + } break; default: break; @@ -231,7 +241,7 @@ void hid_demo_task(void *pvParameters) while(1) { vTaskDelay(2000 / portTICK_PERIOD_MS); if (sec_conn) { - ESP_LOGE(HID_DEMO_TAG, "Send the volume"); + ESP_LOGI(HID_DEMO_TAG, "Send the volume"); send_volum_up = true; //uint8_t key_vaule = {HID_KEY_A}; //esp_hidd_send_keyboard_value(hid_conn_id, 0, &key_vaule, 1); @@ -241,6 +251,8 @@ void hid_demo_task(void *pvParameters) send_volum_up = false; esp_hidd_send_consumer_value(hid_conn_id, HID_CONSUMER_VOLUME_UP, false); esp_hidd_send_consumer_value(hid_conn_id, HID_CONSUMER_VOLUME_DOWN, true); + vTaskDelay(3000 / portTICK_PERIOD_MS); + esp_hidd_send_consumer_value(hid_conn_id, HID_CONSUMER_VOLUME_DOWN, false); } } } @@ -253,7 +265,7 @@ void app_main() // Initialize NVS. ret = nvs_flash_init(); - if (ret == ESP_ERR_NVS_NO_FREE_PAGES) { + 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(); } diff --git a/examples/bluetooth/ble_hid_device_demo/main/hid_device_le_prf.c b/examples/bluetooth/ble_hid_device_demo/main/hid_device_le_prf.c index e7482c21b5..8d112fad87 100644 --- a/examples/bluetooth/ble_hid_device_demo/main/hid_device_le_prf.c +++ b/examples/bluetooth/ble_hid_device_demo/main/hid_device_le_prf.c @@ -196,6 +196,15 @@ enum #define HI_UINT16(a) (((a) >> 8) & 0xFF) #define LO_UINT16(a) ((a) & 0xFF) +#define PROFILE_NUM 1 +#define PROFILE_APP_IDX 0 + +struct gatts_profile_inst { + esp_gatts_cb_t gatts_cb; + uint16_t gatts_if; + uint16_t app_id; + uint16_t conn_id; +}; hidd_le_env_t hidd_le_env; @@ -230,7 +239,7 @@ static uint8_t hidReportRefKeyIn[HID_REPORT_REF_LEN] = static uint8_t hidReportRefLedOut[HID_REPORT_REF_LEN] = { HID_RPT_ID_LED_OUT, HID_REPORT_TYPE_OUTPUT }; -static uint8_t hidReportRefVendorOut[HID_REPORT_REF_LEN] = +static uint8_t hidReportRefVendorOut[HID_REPORT_REF_LEN] = {HID_RPT_ID_VENDOR_OUT, HID_REPORT_TYPE_OUTPUT}; // HID Report Reference characteristic descriptor, Feature @@ -271,7 +280,7 @@ static const uint16_t hid_report_ref_descr_uuid = ESP_GATT_UUID_RPT_REF_DESCR; ///the propoty definition static const uint8_t char_prop_notify = ESP_GATT_CHAR_PROP_BIT_NOTIFY; static const uint8_t char_prop_read = ESP_GATT_CHAR_PROP_BIT_READ; -static const uint8_t char_prop_write = ESP_GATT_CHAR_PROP_BIT_WRITE; +static const uint8_t char_prop_write_nr = ESP_GATT_CHAR_PROP_BIT_WRITE_NR; static const uint8_t char_prop_read_write = ESP_GATT_CHAR_PROP_BIT_WRITE|ESP_GATT_CHAR_PROP_BIT_READ; static const uint8_t char_prop_read_notify = ESP_GATT_CHAR_PROP_BIT_READ|ESP_GATT_CHAR_PROP_BIT_NOTIFY; static const uint8_t char_prop_read_write_notify = ESP_GATT_CHAR_PROP_BIT_READ|ESP_GATT_CHAR_PROP_BIT_WRITE|ESP_GATT_CHAR_PROP_BIT_NOTIFY; @@ -294,7 +303,7 @@ static const esp_gatts_attr_db_t bas_att_db[BAS_IDX_NB] = // Battary level Characteristic Declaration [BAS_IDX_BATT_LVL_CHAR] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_declaration_uuid, ESP_GATT_PERM_READ, CHAR_DECLARATION_SIZE,CHAR_DECLARATION_SIZE, (uint8_t *)&char_prop_read_notify}}, - + // Battary level Characteristic Value [BAS_IDX_BATT_LVL_VAL] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&bat_lev_uuid, ESP_GATT_PERM_READ, sizeof(uint8_t),sizeof(uint8_t), &battary_lev}}, @@ -313,8 +322,8 @@ static const esp_gatts_attr_db_t bas_att_db[BAS_IDX_NB] = static esp_gatts_attr_db_t hidd_le_gatt_db[HIDD_LE_IDX_NB] = { // HID Service Declaration - [HIDD_LE_IDX_SVC] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&primary_service_uuid, - ESP_GATT_PERM_READ_ENCRYPTED, sizeof(uint16_t), sizeof(hid_le_svc), + [HIDD_LE_IDX_SVC] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&primary_service_uuid, + ESP_GATT_PERM_READ_ENCRYPTED, sizeof(uint16_t), sizeof(hid_le_svc), (uint8_t *)&hid_le_svc}}, // HID Service Declaration @@ -327,7 +336,7 @@ static esp_gatts_attr_db_t hidd_le_gatt_db[HIDD_LE_IDX_NB] = [HIDD_LE_IDX_HID_INFO_CHAR] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_declaration_uuid, ESP_GATT_PERM_READ, CHAR_DECLARATION_SIZE, CHAR_DECLARATION_SIZE, - (uint8_t *)&char_prop_read_write}}, + (uint8_t *)&char_prop_read}}, // HID Information Characteristic Value [HIDD_LE_IDX_HID_INFO_VAL] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&hid_info_char_uuid, ESP_GATT_PERM_READ, @@ -338,7 +347,7 @@ static esp_gatts_attr_db_t hidd_le_gatt_db[HIDD_LE_IDX_NB] = [HIDD_LE_IDX_HID_CTNL_PT_CHAR] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_declaration_uuid, ESP_GATT_PERM_READ, CHAR_DECLARATION_SIZE, CHAR_DECLARATION_SIZE, - (uint8_t *)&char_prop_write}}, + (uint8_t *)&char_prop_write_nr}}, // HID Control Point Characteristic Value [HIDD_LE_IDX_HID_CTNL_PT_VAL] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&hid_control_point_uuid, ESP_GATT_PERM_WRITE, @@ -372,22 +381,22 @@ static esp_gatts_attr_db_t hidd_le_gatt_db[HIDD_LE_IDX_NB] = (ESP_GATT_PERM_READ|ESP_GATT_PERM_WRITE), sizeof(uint8_t), sizeof(hidProtocolMode), (uint8_t *)&hidProtocolMode}}, - + [HIDD_LE_IDX_REPORT_MOUSE_IN_CHAR] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_declaration_uuid, ESP_GATT_PERM_READ, CHAR_DECLARATION_SIZE, CHAR_DECLARATION_SIZE, (uint8_t *)&char_prop_read_notify}}, - + [HIDD_LE_IDX_REPORT_MOUSE_IN_VAL] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&hid_report_uuid, ESP_GATT_PERM_READ, HIDD_LE_REPORT_MAX_LEN, 0, NULL}}, - + [HIDD_LE_IDX_REPORT_MOUSE_IN_CCC] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_client_config_uuid, (ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE), sizeof(uint16_t), 0, NULL}}, - + [HIDD_LE_IDX_REPORT_MOUSE_REP_REF] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&hid_report_ref_descr_uuid, ESP_GATT_PERM_READ, sizeof(hidReportRefMouseIn), sizeof(hidReportRefMouseIn), @@ -461,7 +470,7 @@ static esp_gatts_attr_db_t hidd_le_gatt_db[HIDD_LE_IDX_NB] = ESP_GATT_PERM_READ, sizeof(hidReportRefCCIn), sizeof(hidReportRefCCIn), hidReportRefCCIn}}, - + // Boot Keyboard Input Report Characteristic Declaration [HIDD_LE_IDX_BOOT_KB_IN_REPORT_CHAR] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_declaration_uuid, ESP_GATT_PERM_READ, @@ -524,7 +533,7 @@ static esp_gatts_attr_db_t hidd_le_gatt_db[HIDD_LE_IDX_NB] = static void hid_add_id_tbl(void); -void esp_hidd_prf_cb_hdl(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, +void esp_hidd_prf_cb_hdl(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param) { switch(event) { @@ -543,23 +552,23 @@ void esp_hidd_prf_cb_hdl(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, if(hidd_le_env.hidd_cb != NULL) { (hidd_le_env.hidd_cb)(ESP_BAT_EVENT_REG, &hidd_param); } - + } - + break; } case ESP_GATTS_CONF_EVT: { break; - } + } case ESP_GATTS_CREATE_EVT: break; case ESP_GATTS_CONNECT_EVT: { esp_hidd_cb_param_t cb_param = {0}; - ESP_LOGE(HID_LE_PRF_TAG, "the connection establish, conn_id = %x",param->connect.conn_id); + ESP_LOGI(HID_LE_PRF_TAG, "HID connection establish, conn_id = %x",param->connect.conn_id); memcpy(cb_param.connect.remote_bda, param->connect.remote_bda, sizeof(esp_bd_addr_t)); cb_param.connect.conn_id = param->connect.conn_id; hidd_clcb_alloc(param->connect.conn_id, param->connect.remote_bda); - //esp_ble_set_encryption(param->connect.remote_bda, ESP_BLE_SEC_ENCRYPT_NO_MITM); + esp_ble_set_encryption(param->connect.remote_bda, ESP_BLE_SEC_ENCRYPT_NO_MITM); if(hidd_le_env.hidd_cb != NULL) { (hidd_le_env.hidd_cb)(ESP_HIDD_EVENT_BLE_CONNECT, &cb_param); } @@ -587,20 +596,20 @@ void esp_hidd_prf_cb_hdl(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, break; } case ESP_GATTS_CREAT_ATTR_TAB_EVT: { - if (param->add_attr_tab.num_handle == BAS_IDX_NB && + if (param->add_attr_tab.num_handle == BAS_IDX_NB && param->add_attr_tab.svc_uuid.uuid.uuid16 == ESP_GATT_UUID_BATTERY_SERVICE_SVC && param->add_attr_tab.status == ESP_GATT_OK) { incl_svc.start_hdl = param->add_attr_tab.handles[BAS_IDX_SVC]; incl_svc.end_hdl = incl_svc.start_hdl + BAS_IDX_NB -1; - ESP_LOGE(HID_LE_PRF_TAG, "%s(), start added the hid service to the stack database. incl_handle = %d", + ESP_LOGI(HID_LE_PRF_TAG, "%s(), start added the hid service to the stack database. incl_handle = %d", __func__, incl_svc.start_hdl); esp_ble_gatts_create_attr_tab(hidd_le_gatt_db, gatts_if, HIDD_LE_IDX_NB, 0); } - if (param->add_attr_tab.num_handle == HIDD_LE_IDX_NB && + if (param->add_attr_tab.num_handle == HIDD_LE_IDX_NB && param->add_attr_tab.status == ESP_GATT_OK) { - memcpy(hidd_le_env.hidd_inst.att_tbl, param->add_attr_tab.handles, + memcpy(hidd_le_env.hidd_inst.att_tbl, param->add_attr_tab.handles, HIDD_LE_IDX_NB*sizeof(uint16_t)); - ESP_LOGE(HID_LE_PRF_TAG, "hid svc handle = %x",hidd_le_env.hidd_inst.att_tbl[HIDD_LE_IDX_SVC]); + ESP_LOGI(HID_LE_PRF_TAG, "hid svc handle = %x",hidd_le_env.hidd_inst.att_tbl[HIDD_LE_IDX_SVC]); hid_add_id_tbl(); esp_ble_gatts_start_service(hidd_le_env.hidd_inst.att_tbl[HIDD_LE_IDX_SVC]); } else { @@ -608,7 +617,7 @@ void esp_hidd_prf_cb_hdl(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, } break; } - + default: break; } @@ -619,12 +628,12 @@ void hidd_le_create_service(esp_gatt_if_t gatts_if) /* Here should added the battery service first, because the hid service should include the battery service. After finish to added the battery service then can added the hid service. */ esp_ble_gatts_create_attr_tab(bas_att_db, gatts_if, BAS_IDX_NB, 0); - + } void hidd_le_init(void) -{ - +{ + // Reset the hid device target environment memset(&hidd_le_env, 0, sizeof(hidd_le_env_t)); } @@ -655,21 +664,58 @@ bool hidd_clcb_dealloc (uint16_t conn_id) memset(p_clcb, 0, sizeof(hidd_clcb_t)); return true; } - + return false; } +static struct gatts_profile_inst heart_rate_profile_tab[PROFILE_NUM] = { + [PROFILE_APP_IDX] = { + .gatts_cb = esp_hidd_prf_cb_hdl, + .gatts_if = ESP_GATT_IF_NONE, /* Not get the gatt_if, so initial is ESP_GATT_IF_NONE */ + }, + +}; + +static void gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, + esp_ble_gatts_cb_param_t *param) +{ + /* If event is register event, store the gatts_if for each profile */ + if (event == ESP_GATTS_REG_EVT) { + if (param->reg.status == ESP_GATT_OK) { + heart_rate_profile_tab[PROFILE_APP_IDX].gatts_if = gatts_if; + } else { + ESP_LOGI(HID_LE_PRF_TAG, "Reg app failed, app_id %04x, status %d\n", + param->reg.app_id, + param->reg.status); + return; + } + } + + do { + int idx; + for (idx = 0; idx < PROFILE_NUM; idx++) { + if (gatts_if == ESP_GATT_IF_NONE || /* ESP_GATT_IF_NONE, not specify a certain gatt_if, need to call every profile cb function */ + gatts_if == heart_rate_profile_tab[idx].gatts_if) { + if (heart_rate_profile_tab[idx].gatts_cb) { + heart_rate_profile_tab[idx].gatts_cb(event, gatts_if, param); + } + } + } + } while (0); +} + + esp_err_t hidd_register_cb(void) { esp_err_t status; - status = esp_ble_gatts_register_callback(esp_hidd_prf_cb_hdl); + status = esp_ble_gatts_register_callback(gatts_event_handler); return status; } void hidd_set_attr_value(uint16_t handle, uint16_t val_len, const uint8_t *value) { hidd_inst_t *hidd_inst = &hidd_le_env.hidd_inst; - if(hidd_inst->att_tbl[HIDD_LE_IDX_HID_INFO_VAL] <= handle && + if(hidd_inst->att_tbl[HIDD_LE_IDX_HID_INFO_VAL] <= handle && hidd_inst->att_tbl[HIDD_LE_IDX_REPORT_REP_REF] >= handle) { esp_ble_gatts_set_attr_value(handle, val_len, value); } else { @@ -681,7 +727,7 @@ void hidd_set_attr_value(uint16_t handle, uint16_t val_len, const uint8_t *value void hidd_get_attr_value(uint16_t handle, uint16_t *length, uint8_t **value) { hidd_inst_t *hidd_inst = &hidd_le_env.hidd_inst; - if(hidd_inst->att_tbl[HIDD_LE_IDX_HID_INFO_VAL] <= handle && + if(hidd_inst->att_tbl[HIDD_LE_IDX_HID_INFO_VAL] <= handle && hidd_inst->att_tbl[HIDD_LE_IDX_REPORT_REP_REF] >= handle){ esp_ble_gatts_get_attr_value(handle, length, (const uint8_t **)value); } else { @@ -699,28 +745,28 @@ static void hid_add_id_tbl(void) hid_rpt_map[0].handle = hidd_le_env.hidd_inst.att_tbl[HIDD_LE_IDX_REPORT_MOUSE_IN_VAL]; hid_rpt_map[0].cccdHandle = hidd_le_env.hidd_inst.att_tbl[HIDD_LE_IDX_REPORT_MOUSE_IN_VAL]; hid_rpt_map[0].mode = HID_PROTOCOL_MODE_REPORT; - + // Key input report hid_rpt_map[1].id = hidReportRefKeyIn[0]; hid_rpt_map[1].type = hidReportRefKeyIn[1]; hid_rpt_map[1].handle = hidd_le_env.hidd_inst.att_tbl[HIDD_LE_IDX_REPORT_KEY_IN_VAL]; hid_rpt_map[1].cccdHandle = hidd_le_env.hidd_inst.att_tbl[HIDD_LE_IDX_REPORT_KEY_IN_CCC]; hid_rpt_map[1].mode = HID_PROTOCOL_MODE_REPORT; - + // Consumer Control input report hid_rpt_map[2].id = hidReportRefCCIn[0]; hid_rpt_map[2].type = hidReportRefCCIn[1]; hid_rpt_map[2].handle = hidd_le_env.hidd_inst.att_tbl[HIDD_LE_IDX_REPORT_CC_IN_VAL]; hid_rpt_map[2].cccdHandle = hidd_le_env.hidd_inst.att_tbl[HIDD_LE_IDX_REPORT_CC_IN_CCC]; hid_rpt_map[2].mode = HID_PROTOCOL_MODE_REPORT; - + // LED output report hid_rpt_map[3].id = hidReportRefLedOut[0]; hid_rpt_map[3].type = hidReportRefLedOut[1]; hid_rpt_map[3].handle = hidd_le_env.hidd_inst.att_tbl[HIDD_LE_IDX_REPORT_LED_OUT_VAL]; hid_rpt_map[3].cccdHandle = 0; hid_rpt_map[3].mode = HID_PROTOCOL_MODE_REPORT; - + // Boot keyboard input report // Use same ID and type as key input report hid_rpt_map[4].id = hidReportRefKeyIn[0]; @@ -728,7 +774,7 @@ static void hid_add_id_tbl(void) hid_rpt_map[4].handle = hidd_le_env.hidd_inst.att_tbl[HIDD_LE_IDX_BOOT_KB_IN_REPORT_VAL]; hid_rpt_map[4].cccdHandle = 0; hid_rpt_map[4].mode = HID_PROTOCOL_MODE_BOOT; - + // Boot keyboard output report // Use same ID and type as LED output report hid_rpt_map[5].id = hidReportRefLedOut[0]; @@ -736,7 +782,7 @@ static void hid_add_id_tbl(void) hid_rpt_map[5].handle = hidd_le_env.hidd_inst.att_tbl[HIDD_LE_IDX_BOOT_KB_OUT_REPORT_VAL]; hid_rpt_map[5].cccdHandle = 0; hid_rpt_map[5].mode = HID_PROTOCOL_MODE_BOOT; - + // Boot mouse input report // Use same ID and type as mouse input report hid_rpt_map[6].id = hidReportRefMouseIn[0]; @@ -744,7 +790,7 @@ static void hid_add_id_tbl(void) hid_rpt_map[6].handle = hidd_le_env.hidd_inst.att_tbl[HIDD_LE_IDX_BOOT_MOUSE_IN_REPORT_VAL]; hid_rpt_map[6].cccdHandle = 0; hid_rpt_map[6].mode = HID_PROTOCOL_MODE_BOOT; - + // Feature report hid_rpt_map[7].id = hidReportRefFeature[0]; hid_rpt_map[7].type = hidReportRefFeature[1]; diff --git a/examples/bluetooth/ble_spp_server/main/ble_spp_server_demo.c b/examples/bluetooth/ble_spp_server/main/ble_spp_server_demo.c index 2da39c5fe8..999b047e78 100644 --- a/examples/bluetooth/ble_spp_server/main/ble_spp_server_demo.c +++ b/examples/bluetooth/ble_spp_server/main/ble_spp_server_demo.c @@ -655,7 +655,7 @@ void app_main() // Initialize NVS ret = nvs_flash_init(); - if (ret == ESP_ERR_NVS_NO_FREE_PAGES) { + 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(); } diff --git a/examples/bluetooth/ble_throughput/throughput_client/README.md b/examples/bluetooth/ble_throughput/throughput_client/README.md index 142f8cff87..48b6b475ba 100644 --- a/examples/bluetooth/ble_throughput/throughput_client/README.md +++ b/examples/bluetooth/ble_throughput/throughput_client/README.md @@ -2,11 +2,12 @@ ESP-IDF BLE throughput GATT CLIENT demo ======================== This is the demo used to test the BLE throughput, this demo should used with throughput server demo together. -The throughput of BLE can up to 720-767 bits/s between to ESP32 board. +The throughput of BLE can up to 720-767 Kbps between to ESP32 board. Note: -1. In order to maximize throughput, we need to set the uart print baud rate at 921600 or more (make menuconfig --> Component config --> ESP32-specific --> UART console baud rate --> 921600(or 1500000)); +1. In order to maximize throughput, we need to set the uart print baud rate at 921600 or more (make menuconfig --> Component config --> ESP32-specific --> UART console baud rate --> 921600(or 1500000)) and don't print too much log. 2. We can only test notify or write throughput at the same time, this demo default to test the notify throughput, if want to test the write throughput, please set: make menuconfig --> Component config --> Example 'GATT CLIENT THROUGHPUT' Config ---> then select the 'test the gattc write throughput' option 3. This demo only test unidirectional throughput, if you want to test the bidirectional throughput please change the demo by yourself. -4. Should change the CPU frequency to 240MHz in the make menuconfig --> Component config ---> ESP32-specific ---> CPU frequency (240 MHz) -5. Should change the bluetooth controller and Bluedroid run in different Core in the make menuconfig --> Component config ---> Bluetooth ---> The cpu core which bluetooth controller run (Core 0 (PRO CPU)) & Bluedroid Enable ---> The cpu core which Bluedroid run (Core 1 (APP CPU)) +4. Should change the CPU frequency to 160MHZ or 240MHz in the make menuconfig --> Component config ---> ESP32-specific ---> CPU frequency (240 MHz or 160 MHz). +5. Should change the bluetooth controller and Bluedroid run in different Core in the make menuconfig --> Component config ---> Bluetooth ---> The cpu core which bluetooth controller run (Core 0 (PRO CPU)) & Bluedroid Enable ---> The cpu core which Bluedroid run (Core 1 (APP CPU)). +6. In order to maximize throughput, please test in a clean environment without many BLE devices working and both test devices are ESP32. diff --git a/examples/bluetooth/ble_throughput/throughput_client/main/example_ble_client_throughput.c b/examples/bluetooth/ble_throughput/throughput_client/main/example_ble_client_throughput.c index 48b61d0d82..56362cac62 100644 --- a/examples/bluetooth/ble_throughput/throughput_client/main/example_ble_client_throughput.c +++ b/examples/bluetooth/ble_throughput/throughput_client/main/example_ble_client_throughput.c @@ -482,14 +482,16 @@ static void throughput_client_task(void *param) while(1) { #if (CONFIG_GATTS_NOTIFY_THROUGHPUT) vTaskDelay(2000 / portTICK_PERIOD_MS); - uint32_t bit_rate = 0; - if (start_time) { - current_time = esp_timer_get_time(); - bit_rate = notify_len * SECOND_TO_USECOND / (current_time - start_time); - ESP_LOGI(GATTC_TAG, "Notify Bit rate = %d Btye/s, = %d bit/s, time = %ds", - bit_rate, bit_rate<<3, (int)((current_time - start_time) / SECOND_TO_USECOND)); - } else { - ESP_LOGI(GATTC_TAG, "Notify Bit rate = 0 Btye/s, = 0 bit/s"); + if(is_connecet){ + uint32_t bit_rate = 0; + if (start_time) { + current_time = esp_timer_get_time(); + bit_rate = notify_len * SECOND_TO_USECOND / (current_time - start_time); + ESP_LOGI(GATTC_TAG, "Notify Bit rate = %d Btye/s, = %d bit/s, time = %ds", + bit_rate, bit_rate<<3, (int)((current_time - start_time) / SECOND_TO_USECOND)); + } else { + ESP_LOGI(GATTC_TAG, "Notify Bit rate = 0 Btye/s, = 0 bit/s"); + } } #endif /* #if (CONFIG_GATTS_NOTIFY_THROUGHPUT) */ #if (CONFIG_GATTC_WRITE_THROUGHPUT) @@ -517,7 +519,7 @@ void app_main() { // Initialize NVS. esp_err_t ret = nvs_flash_init(); - if (ret == ESP_ERR_NVS_NO_FREE_PAGES) { + 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(); } diff --git a/examples/bluetooth/ble_throughput/throughput_client/sdkconfig.defaults b/examples/bluetooth/ble_throughput/throughput_client/sdkconfig.defaults index e4b501910f..fff804e3c1 100644 --- a/examples/bluetooth/ble_throughput/throughput_client/sdkconfig.defaults +++ b/examples/bluetooth/ble_throughput/throughput_client/sdkconfig.defaults @@ -2,3 +2,17 @@ # by default in this example CONFIG_BT_ENABLED=y CONFIG_GATTS_NOTIFY_THROUGHPUT=y +CONFIG_BTDM_CONTROLLER_MODEM_SLEEP=n +CONFIG_BTDM_CONTROLLER_PINNED_TO_CORE_1=y +CONFIG_BTDM_CONTROLLER_PINNED_TO_CORE=1 +# +# Serial flasher config +# +CONFIG_MONITOR_BAUD_921600B=y +CONFIG_MONITOR_BAUD=921600 +# +# ESP32-specific +# +CONFIG_TRACEMEM_RESERVE_DRAM=0x0 +CONFIG_ESP32_ENABLE_COREDUMP_TO_NONE=y +CONFIG_CONSOLE_UART_BAUDRATE=921600 diff --git a/examples/bluetooth/ble_throughput/throughput_server/README.md b/examples/bluetooth/ble_throughput/throughput_server/README.md index dd45acbfc6..47c86410d9 100644 --- a/examples/bluetooth/ble_throughput/throughput_server/README.md +++ b/examples/bluetooth/ble_throughput/throughput_server/README.md @@ -2,12 +2,13 @@ ESP-IDF BLE throughput GATT SERVER demo ======================== This is the demo used to test the BLE throughput, this demo should used with throughput client demo together. -The throughput of BLE can up to 720-767 bits/s between to ESP32 board. +The throughput of BLE can up to 720-767 Kbps between to ESP32 board. Note: -1. In order to maximize throughput, we need to set the uart print baud rate at 921600 or more (make menuconfig --> Component config --> ESP32-specific --> UART console baud rate --> 921600(or 1500000)); +1. In order to maximize throughput, we need to set the uart print baud rate at 921600 or more (make menuconfig --> Component config --> ESP32-specific --> UART console baud rate --> 921600(or 1500000)) and don't print too much log; 2. We can only test notify or write throughput at the same time, this demo default to test the notify throughput, if want to test the write throughput, please set: make menuconfig --> Component config --> Example 'GATT SERVER THROUGHPUT' Config ---> then select the 'test the gattc write throughput' option 3. This demo only test unidirectional throughput, if you want to test the bidirectional throughput please change the demo by yourself. -4. Should change the CPU frequency to 240MHz in the make menuconfig --> Component config ---> ESP32-specific ---> CPU frequency (240 MHz) +4. Should change the CPU frequency to 160MHz or 240MHz in the make menuconfig --> Component config ---> ESP32-specific ---> CPU frequency (160MHz or 240 MHz) 5. Should change the bluetooth controller and Bluedroid run in different Core in the make menuconfig --> Component config ---> Bluetooth ---> The cpu core which bluetooth controller run (Core 0 (PRO CPU)) & Bluedroid Enable ---> The cpu core which Bluedroid run (Core 1 (APP CPU)) +6. In order to maximize throughput, please test in a clean environment without many BLE devices working and both test devices are ESP32. diff --git a/examples/bluetooth/ble_throughput/throughput_server/main/example_ble_server_throughput.c b/examples/bluetooth/ble_throughput/throughput_server/main/example_ble_server_throughput.c index 9bb06a579b..0b245ac676 100644 --- a/examples/bluetooth/ble_throughput/throughput_server/main/example_ble_server_throughput.c +++ b/examples/bluetooth/ble_throughput/throughput_server/main/example_ble_server_throughput.c @@ -541,9 +541,6 @@ static void gatts_profile_a_event_handler(esp_gatts_cb_event_t event, esp_gatt_i break; case ESP_GATTS_CONF_EVT: ESP_LOGI(GATTS_TAG, "ESP_GATTS_CONF_EVT, status %d", param->conf.status); - if (param->conf.status != ESP_GATT_OK){ - esp_log_buffer_hex(GATTS_TAG, param->conf.value, param->conf.len); - } #if (CONFIG_GATTC_WRITE_THROUGHPUT) start_time = false; current_time = 0; @@ -611,7 +608,6 @@ void throughput_server_task(void *param) while(1) { #if (CONFIG_GATTS_NOTIFY_THROUGHPUT) if (!can_send_notify) { - ESP_LOGI(GATTS_TAG, "==="); int res = xSemaphoreTake(gatts_semaphore, portMAX_DELAY); assert(res == pdTRUE); } else { @@ -645,7 +641,7 @@ void app_main() // Initialize NVS. ret = nvs_flash_init(); - if (ret == ESP_ERR_NVS_NO_FREE_PAGES) { + 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(); } diff --git a/examples/bluetooth/ble_throughput/throughput_server/sdkconfig.defaults b/examples/bluetooth/ble_throughput/throughput_server/sdkconfig.defaults index e4b501910f..fff804e3c1 100644 --- a/examples/bluetooth/ble_throughput/throughput_server/sdkconfig.defaults +++ b/examples/bluetooth/ble_throughput/throughput_server/sdkconfig.defaults @@ -2,3 +2,17 @@ # by default in this example CONFIG_BT_ENABLED=y CONFIG_GATTS_NOTIFY_THROUGHPUT=y +CONFIG_BTDM_CONTROLLER_MODEM_SLEEP=n +CONFIG_BTDM_CONTROLLER_PINNED_TO_CORE_1=y +CONFIG_BTDM_CONTROLLER_PINNED_TO_CORE=1 +# +# Serial flasher config +# +CONFIG_MONITOR_BAUD_921600B=y +CONFIG_MONITOR_BAUD=921600 +# +# ESP32-specific +# +CONFIG_TRACEMEM_RESERVE_DRAM=0x0 +CONFIG_ESP32_ENABLE_COREDUMP_TO_NONE=y +CONFIG_CONSOLE_UART_BAUDRATE=921600 diff --git a/examples/bluetooth/blufi/main/blufi_example_main.c b/examples/bluetooth/blufi/main/blufi_example_main.c index 2ad02c198b..bb046306e8 100644 --- a/examples/bluetooth/blufi/main/blufi_example_main.c +++ b/examples/bluetooth/blufi/main/blufi_example_main.c @@ -381,7 +381,7 @@ void app_main() // Initialize NVS ret = nvs_flash_init(); - if (ret == ESP_ERR_NVS_NO_FREE_PAGES) { + 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(); } diff --git a/examples/bluetooth/bt_discovery/main/bt_discovery.c b/examples/bluetooth/bt_discovery/main/bt_discovery.c index 6567114439..ef2b11ef53 100644 --- a/examples/bluetooth/bt_discovery/main/bt_discovery.c +++ b/examples/bluetooth/bt_discovery/main/bt_discovery.c @@ -273,7 +273,7 @@ void app_main() { /* Initialize NVS — it is used to store PHY calibration data */ esp_err_t ret = nvs_flash_init(); - if (ret == ESP_ERR_NVS_NO_FREE_PAGES) { + 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(); } diff --git a/examples/bluetooth/bt_spp_acceptor/main/example_spp_acceptor_demo.c b/examples/bluetooth/bt_spp_acceptor/main/example_spp_acceptor_demo.c index 3d9d95a5f6..c98f757b1d 100644 --- a/examples/bluetooth/bt_spp_acceptor/main/example_spp_acceptor_demo.c +++ b/examples/bluetooth/bt_spp_acceptor/main/example_spp_acceptor_demo.c @@ -108,7 +108,7 @@ static void esp_spp_cb(esp_spp_cb_event_t event, esp_spp_cb_param_t *param) void app_main() { esp_err_t ret = nvs_flash_init(); - if (ret == ESP_ERR_NVS_NO_FREE_PAGES) { + 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(); } diff --git a/examples/bluetooth/bt_spp_initiator/main/example_spp_initiator_demo.c b/examples/bluetooth/bt_spp_initiator/main/example_spp_initiator_demo.c index f4d81a14f2..bc301cfbb4 100644 --- a/examples/bluetooth/bt_spp_initiator/main/example_spp_initiator_demo.c +++ b/examples/bluetooth/bt_spp_initiator/main/example_spp_initiator_demo.c @@ -202,7 +202,7 @@ void app_main() } esp_err_t ret = nvs_flash_init(); - if (ret == ESP_ERR_NVS_NO_FREE_PAGES) { + 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(); } diff --git a/examples/bluetooth/bt_spp_vfs_acceptor/main/example_spp_vfs_acceptor_demo.c b/examples/bluetooth/bt_spp_vfs_acceptor/main/example_spp_vfs_acceptor_demo.c index 76b74552c1..d8cce525a8 100644 --- a/examples/bluetooth/bt_spp_vfs_acceptor/main/example_spp_vfs_acceptor_demo.c +++ b/examples/bluetooth/bt_spp_vfs_acceptor/main/example_spp_vfs_acceptor_demo.c @@ -108,7 +108,7 @@ static void esp_spp_stack_cb(esp_spp_cb_event_t event, esp_spp_cb_param_t *param void app_main() { esp_err_t ret = nvs_flash_init(); - if (ret == ESP_ERR_NVS_NO_FREE_PAGES) { + 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(); } diff --git a/examples/bluetooth/bt_spp_vfs_initiator/main/example_spp_vfs_initiator_demo.c b/examples/bluetooth/bt_spp_vfs_initiator/main/example_spp_vfs_initiator_demo.c index 47089bf0cb..48c4ea660f 100644 --- a/examples/bluetooth/bt_spp_vfs_initiator/main/example_spp_vfs_initiator_demo.c +++ b/examples/bluetooth/bt_spp_vfs_initiator/main/example_spp_vfs_initiator_demo.c @@ -187,7 +187,7 @@ void app_main() } esp_err_t ret = nvs_flash_init(); - if (ret == ESP_ERR_NVS_NO_FREE_PAGES) { + 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(); } diff --git a/examples/bluetooth/controller_hci_uart/main/controller_hci_uart_demo.c b/examples/bluetooth/controller_hci_uart/main/controller_hci_uart_demo.c index 006a951b39..0eb7ef7781 100644 --- a/examples/bluetooth/controller_hci_uart/main/controller_hci_uart_demo.c +++ b/examples/bluetooth/controller_hci_uart/main/controller_hci_uart_demo.c @@ -37,7 +37,7 @@ void app_main() /* Initialize NVS — it is used to store PHY calibration data */ ret = nvs_flash_init(); - if (ret == ESP_ERR_NVS_NO_FREE_PAGES) { + 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(); } diff --git a/examples/bluetooth/gatt_client/main/gattc_demo.c b/examples/bluetooth/gatt_client/main/gattc_demo.c index 1f2cc20e41..ac49348be2 100644 --- a/examples/bluetooth/gatt_client/main/gattc_demo.c +++ b/examples/bluetooth/gatt_client/main/gattc_demo.c @@ -414,7 +414,7 @@ void app_main() { // Initialize NVS. esp_err_t ret = nvs_flash_init(); - if (ret == ESP_ERR_NVS_NO_FREE_PAGES) { + 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(); } diff --git a/examples/bluetooth/gatt_client/tutorial/Gatt_Client_Example_Walkthrough.md b/examples/bluetooth/gatt_client/tutorial/Gatt_Client_Example_Walkthrough.md index 49725751d1..2ed2c86b5e 100644 --- a/examples/bluetooth/gatt_client/tutorial/Gatt_Client_Example_Walkthrough.md +++ b/examples/bluetooth/gatt_client/tutorial/Gatt_Client_Example_Walkthrough.md @@ -41,7 +41,7 @@ void app_main() { // Initialize NVS. esp_err_t ret = nvs_flash_init(); - if (ret == ESP_ERR_NVS_NO_FREE_PAGES) { + 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(); } @@ -103,7 +103,7 @@ The main function starts by initializing the non-volatile storage library. This ```c esp_err_t ret = nvs_flash_init(); -if (ret == ESP_ERR_NVS_NO_FREE_PAGES) { +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(); } diff --git a/examples/bluetooth/gatt_security_client/main/example_ble_sec_gattc_demo.c b/examples/bluetooth/gatt_security_client/main/example_ble_sec_gattc_demo.c index 16a23fdd6a..6a5e4933a5 100644 --- a/examples/bluetooth/gatt_security_client/main/example_ble_sec_gattc_demo.c +++ b/examples/bluetooth/gatt_security_client/main/example_ble_sec_gattc_demo.c @@ -460,7 +460,7 @@ void app_main() { // Initialize NVS. esp_err_t ret = nvs_flash_init(); - if (ret == ESP_ERR_NVS_NO_FREE_PAGES) { + 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(); } diff --git a/examples/bluetooth/gatt_security_server/main/example_ble_sec_gatts_demo.c b/examples/bluetooth/gatt_security_server/main/example_ble_sec_gatts_demo.c index 3f3ce98f0e..e6b2ddd638 100644 --- a/examples/bluetooth/gatt_security_server/main/example_ble_sec_gatts_demo.c +++ b/examples/bluetooth/gatt_security_server/main/example_ble_sec_gatts_demo.c @@ -320,6 +320,9 @@ static void gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param (bd_addr[4] << 8) + bd_addr[5]); ESP_LOGI(GATTS_TABLE_TAG, "address type = %d", param->ble_security.auth_cmpl.addr_type); ESP_LOGI(GATTS_TABLE_TAG, "pair status = %s",param->ble_security.auth_cmpl.success ? "success" : "fail"); + if(!param->ble_security.auth_cmpl.success) { + ESP_LOGI(GATTS_TABLE_TAG, "fail reason = 0x%x",param->ble_security.auth_cmpl.fail_reason); + } show_bonded_devices(); break; } @@ -466,7 +469,7 @@ void app_main() // Initialize NVS. ret = nvs_flash_init(); - if (ret == ESP_ERR_NVS_NO_FREE_PAGES) { + 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(); } diff --git a/examples/bluetooth/gatt_server/main/gatts_demo.c b/examples/bluetooth/gatt_server/main/gatts_demo.c index 76dc104a2b..57f17b1dd2 100644 --- a/examples/bluetooth/gatt_server/main/gatts_demo.c +++ b/examples/bluetooth/gatt_server/main/gatts_demo.c @@ -679,7 +679,7 @@ void app_main() // Initialize NVS. ret = nvs_flash_init(); - if (ret == ESP_ERR_NVS_NO_FREE_PAGES) { + 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(); } diff --git a/examples/bluetooth/gatt_server/tutorial/Gatt_Server_Example_Walkthrough.md b/examples/bluetooth/gatt_server/tutorial/Gatt_Server_Example_Walkthrough.md index 34a44d415c..495a2bde8f 100644 --- a/examples/bluetooth/gatt_server/tutorial/Gatt_Server_Example_Walkthrough.md +++ b/examples/bluetooth/gatt_server/tutorial/Gatt_Server_Example_Walkthrough.md @@ -44,7 +44,7 @@ The entry point to this example is the app_main() function: // Initialize NVS. ret = nvs_flash_init(); - if (ret == ESP_ERR_NVS_NO_FREE_PAGES) { + 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(); } diff --git a/examples/bluetooth/gatt_server_service_table/main/gatts_table_creat_demo.c b/examples/bluetooth/gatt_server_service_table/main/gatts_table_creat_demo.c index cc62e5013e..704e735b90 100644 --- a/examples/bluetooth/gatt_server_service_table/main/gatts_table_creat_demo.c +++ b/examples/bluetooth/gatt_server_service_table/main/gatts_table_creat_demo.c @@ -517,7 +517,7 @@ void app_main() /* Initialize NVS. */ ret = nvs_flash_init(); - if (ret == ESP_ERR_NVS_NO_FREE_PAGES) { + 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(); } diff --git a/examples/bluetooth/gatt_server_service_table/tutorial/Gatt_Server_Service_Table_Example_Walkthrough.md b/examples/bluetooth/gatt_server_service_table/tutorial/Gatt_Server_Service_Table_Example_Walkthrough.md index a317dc8da2..c86d82cc2c 100644 --- a/examples/bluetooth/gatt_server_service_table/tutorial/Gatt_Server_Service_Table_Example_Walkthrough.md +++ b/examples/bluetooth/gatt_server_service_table/tutorial/Gatt_Server_Service_Table_Example_Walkthrough.md @@ -81,7 +81,7 @@ void app_main() // Initialize NVS. ret = nvs_flash_init(); - if (ret == ESP_ERR_NVS_NO_FREE_PAGES) { + 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(); } diff --git a/examples/bluetooth/gattc_multi_connect/main/gattc_multi_connect.c b/examples/bluetooth/gattc_multi_connect/main/gattc_multi_connect.c index 71f70d4701..f7daa44535 100644 --- a/examples/bluetooth/gattc_multi_connect/main/gattc_multi_connect.c +++ b/examples/bluetooth/gattc_multi_connect/main/gattc_multi_connect.c @@ -886,7 +886,7 @@ static void esp_gattc_cb(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if, esp void app_main() { esp_err_t ret = nvs_flash_init(); - if (ret == ESP_ERR_NVS_NO_FREE_PAGES) { + 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(); } diff --git a/examples/mesh/internal_transceiver/CMakeLists.txt b/examples/mesh/internal_communication/CMakeLists.txt similarity index 100% rename from examples/mesh/internal_transceiver/CMakeLists.txt rename to examples/mesh/internal_communication/CMakeLists.txt diff --git a/examples/mesh/internal_communication/Makefile b/examples/mesh/internal_communication/Makefile new file mode 100644 index 0000000000..3e340792b1 --- /dev/null +++ b/examples/mesh/internal_communication/Makefile @@ -0,0 +1,9 @@ +# +# This is a project Makefile. It is assumed the directory this Makefile resides in is a +# project subdirectory. +# + +PROJECT_NAME := internal_communication + +include $(IDF_PATH)/make/project.mk + diff --git a/examples/mesh/internal_transceiver/README.md b/examples/mesh/internal_communication/README.md similarity index 95% rename from examples/mesh/internal_transceiver/README.md rename to examples/mesh/internal_communication/README.md index 6bfb8983a8..4131bef5aa 100644 --- a/examples/mesh/internal_transceiver/README.md +++ b/examples/mesh/internal_communication/README.md @@ -1,4 +1,4 @@ -# Mesh Internal Transceiver Example +# Mesh Internal Communication Example This example demonstrates how to use the mesh APIs to set up a mesh network, send and receive messages over the mesh network and etc. diff --git a/examples/mesh/internal_transceiver/main/Kconfig.projbuild b/examples/mesh/internal_communication/main/Kconfig.projbuild similarity index 100% rename from examples/mesh/internal_transceiver/main/Kconfig.projbuild rename to examples/mesh/internal_communication/main/Kconfig.projbuild diff --git a/examples/mesh/internal_transceiver/main/component.mk b/examples/mesh/internal_communication/main/component.mk similarity index 100% rename from examples/mesh/internal_transceiver/main/component.mk rename to examples/mesh/internal_communication/main/component.mk diff --git a/examples/mesh/internal_transceiver/main/include/mesh_light.h b/examples/mesh/internal_communication/main/include/mesh_light.h similarity index 97% rename from examples/mesh/internal_transceiver/main/include/mesh_light.h rename to examples/mesh/internal_communication/main/include/mesh_light.h index 8290e6d4df..e42a4a3ffc 100644 --- a/examples/mesh/internal_transceiver/main/include/mesh_light.h +++ b/examples/mesh/internal_communication/main/include/mesh_light.h @@ -1,4 +1,4 @@ -/* Mesh Internal Transceiver Example +/* Mesh Internal Communication Example This example code is in the Public Domain (or CC0 licensed, at your option.) diff --git a/examples/mesh/internal_transceiver/main/mesh_light.c b/examples/mesh/internal_communication/main/mesh_light.c similarity index 90% rename from examples/mesh/internal_transceiver/main/mesh_light.c rename to examples/mesh/internal_communication/main/mesh_light.c index 15e5483518..58a66e1527 100644 --- a/examples/mesh/internal_transceiver/main/mesh_light.c +++ b/examples/mesh/internal_communication/main/mesh_light.c @@ -1,4 +1,4 @@ -/* Mesh Internal Transceiver Example +/* Mesh Internal Communication Example This example code is in the Public Domain (or CC0 licensed, at your option.) @@ -26,28 +26,34 @@ /******************************************************* * Variable Definitions *******************************************************/ -static bool bool_light_inited = false; +static bool s_light_inited = false; /******************************************************* * Function Definitions *******************************************************/ esp_err_t mesh_light_init(void) { - if (bool_light_inited == true) { + if (s_light_inited == true) { return ESP_OK; } - bool_light_inited = true; + s_light_inited = true; ledc_timer_config_t ledc_timer = { - .bit_num = LEDC_TIMER_13_BIT, .freq_hz = 5000, .speed_mode = - LEDC_HIGH_SPEED_MODE, .timer_num = LEDC_TIMER_0 + .bit_num = LEDC_TIMER_13_BIT, + .freq_hz = 5000, + .speed_mode = LEDC_HIGH_SPEED_MODE, + .timer_num = LEDC_TIMER_0 }; ledc_timer_config(&ledc_timer); - ledc_channel_config_t ledc_channel = { .channel = LEDC_CHANNEL_0, .duty = - 100, .gpio_num = LEDC_IO_0, .intr_type = LEDC_INTR_FADE_END, - .speed_mode = LEDC_HIGH_SPEED_MODE, .timer_sel = LEDC_TIMER_0 - }; + ledc_channel_config_t ledc_channel = { + .channel = LEDC_CHANNEL_0, + .duty = 100, + .gpio_num = LEDC_IO_0, + .intr_type = LEDC_INTR_FADE_END, + .speed_mode = LEDC_HIGH_SPEED_MODE, + .timer_sel = LEDC_TIMER_0 + }; ledc_channel_config(&ledc_channel); ledc_channel.channel = LEDC_CHANNEL_1; ledc_channel.gpio_num = LEDC_IO_1; diff --git a/examples/mesh/internal_transceiver/main/mesh_main.c b/examples/mesh/internal_communication/main/mesh_main.c similarity index 84% rename from examples/mesh/internal_transceiver/main/mesh_main.c rename to examples/mesh/internal_communication/main/mesh_main.c index 6cbdfc713f..4e6b10901f 100644 --- a/examples/mesh/internal_transceiver/main/mesh_main.c +++ b/examples/mesh/internal_communication/main/mesh_main.c @@ -1,4 +1,4 @@ -/* Mesh Internal Transceiver Example +/* Mesh Internal Communication Example This example code is in the Public Domain (or CC0 licensed, at your option.) @@ -20,7 +20,6 @@ * Macros *******************************************************/ //#define MESH_P2P_TOS_OFF -//#define MESH_ROOT_TO_GROUP /******************************************************* * Constants @@ -61,27 +60,6 @@ mesh_light_ctl_t light_off = { /******************************************************* * Function Definitions *******************************************************/ -void mesh_send_to_group(const mesh_data_t *data, const mesh_addr_t *group, int seqno) -{ - - esp_err_t err = esp_mesh_send(group, data, - MESH_DATA_P2P | MESH_DATA_GROUP, - NULL, 0); - if (err) { - ESP_LOGE(MESH_TAG, - "[GROUP:%d][L:%d][rtableSize:%d]parent:"MACSTR" to "MACSTR", heap:%d[err:0x%x, proto:%d, tos:%d]", - seqno, mesh_layer, esp_mesh_get_routing_table_size(), - MAC2STR(mesh_parent_addr.addr), MAC2STR(group->addr), - esp_get_free_heap_size(), err, data->proto, data->tos); - } else { - ESP_LOGW(MESH_TAG, - "[GROUP:%d][L:%d][rtableSize:%d]parent:"MACSTR" to "MACSTR", heap:%d[err:0x%x, proto:%d, tos:%d]", - seqno, mesh_layer, esp_mesh_get_routing_table_size(), - MAC2STR(mesh_parent_addr.addr), MAC2STR(group->addr), - esp_get_free_heap_size(), err, data->proto, data->tos); - } -} - void esp_mesh_p2p_tx_main(void *arg) { int i; @@ -125,11 +103,6 @@ void esp_mesh_p2p_tx_main(void *arg) memcpy(tx_buf, (uint8_t *)&light_off, sizeof(light_off)); } -#ifdef MESH_ROOT_TO_GROUP - mesh_send_to_group(&data, (mesh_addr_t *)MESH_GROUP_ID, send_count); - vTaskDelay(1 * 1000 / portTICK_RATE_MS); - continue; -#endif for (i = 0; i < route_table_size; i++) { err = esp_mesh_send(&route_table[i], &data, MESH_DATA_P2P, NULL, 0); if (err) { @@ -206,22 +179,21 @@ esp_err_t esp_mesh_comm_p2p_start(void) return ESP_OK; } -void esp_mesh_event_handler(mesh_event_t event) +void mesh_event_handler(mesh_event_t event) { -#ifdef MESH_ROOT_TO_GROUP - mesh_addr_t group; -#endif + mesh_addr_t id = {0,}; static uint8_t last_layer = 0; ESP_LOGD(MESH_TAG, "esp_event_handler:%d", event.id); switch (event.id) { case MESH_EVENT_STARTED: - ESP_LOGI(MESH_TAG, "heap:%d", esp_get_free_heap_size()); + esp_mesh_get_id(&id); + ESP_LOGI(MESH_TAG, "ID:"MACSTR"", MAC2STR(id.addr)); is_mesh_connected = false; mesh_layer = esp_mesh_get_layer(); break; case MESH_EVENT_STOPPED: - ESP_LOGI(MESH_TAG, "heap:%d", esp_get_free_heap_size()); + ESP_LOGI(MESH_TAG, ""); is_mesh_connected = false; mesh_layer = esp_mesh_get_layer(); break; @@ -251,28 +223,20 @@ void esp_mesh_event_handler(mesh_event_t event) /* TODO handler for the failure */ break; case MESH_EVENT_PARENT_CONNECTED: + esp_mesh_get_id(&id); mesh_layer = event.info.connected.self_layer; memcpy(&mesh_parent_addr.addr, event.info.connected.connected.bssid, 6); ESP_LOGI(MESH_TAG, - "layer:%d-->%d, parent:"MACSTR"%s", + "layer:%d-->%d, parent:"MACSTR"%s, ID:"MACSTR"", last_layer, mesh_layer, MAC2STR(mesh_parent_addr.addr), esp_mesh_is_root() ? "" : - (mesh_layer == 2) ? "" : ""); + (mesh_layer == 2) ? "" : "", MAC2STR(id.addr)); last_layer = mesh_layer; mesh_connected_indicator(mesh_layer); is_mesh_connected = true; if (esp_mesh_is_root()) { tcpip_adapter_dhcpc_start(TCPIP_ADAPTER_IF_STA); } -#ifdef MESH_ROOT_TO_GROUP - if (mesh_layer == 3) { - ESP_ERROR_CHECK( - esp_mesh_set_group_id((mesh_addr_t * ) MESH_GROUP_ID, 1)) - ESP_ERROR_CHECK(esp_mesh_get_group_list(&group, 1)) - ESP_LOGI(MESH_TAG, "num:%d, group "MACSTR"\n", - esp_mesh_get_group_num(), MAC2STR(group.addr)); - } -#endif esp_mesh_comm_p2p_start(); break; case MESH_EVENT_PARENT_DISCONNECTED: @@ -281,6 +245,7 @@ void esp_mesh_event_handler(mesh_event_t event) event.info.disconnected.reason); is_mesh_connected = false; mesh_disconnected_indicator(); + mesh_layer = esp_mesh_get_layer(); break; case MESH_EVENT_LAYER_CHANGE: mesh_layer = event.info.layer_change.new_layer; @@ -328,7 +293,6 @@ void esp_mesh_event_handler(mesh_event_t event) esp_mesh_get_parent_bssid(&mesh_parent_addr); ESP_LOGI(MESH_TAG, "layer:%d, parent:"MACSTR"", mesh_layer, MAC2STR(mesh_parent_addr.addr)); break; - case MESH_EVENT_TODS_STATE: ESP_LOGI(MESH_TAG, "state:%d", event.info.toDS_state); @@ -337,6 +301,20 @@ void esp_mesh_event_handler(mesh_event_t event) ESP_LOGI(MESH_TAG, "%s", event.info.root_fixed.is_fixed ? "fixed" : "not fixed"); break; + case MESH_EVENT_ROOT_ASKED_YIELD: + ESP_LOGI(MESH_TAG, + ""MACSTR", rssi:%d, capacity:%d", + MAC2STR(event.info.root_conflict.addr), + event.info.root_conflict.rssi, + event.info.root_conflict.capacity); + break; + case MESH_EVENT_CHANNEL_SWITCH: + ESP_LOGI(MESH_TAG, ""); + break; + case MESH_EVENT_SCAN_DONE: + ESP_LOGI(MESH_TAG, "number:%d", + event.info.scan_done.number); + break; default: ESP_LOGI(MESH_TAG, "unknown id:%d", event.id); break; @@ -382,7 +360,7 @@ void app_main(void) /* mesh ID */ memcpy((uint8_t *) &cfg.mesh_id, MESH_ID, 6); /* mesh event callback */ - cfg.event_cb = &esp_mesh_event_handler; + cfg.event_cb = &mesh_event_handler; /* router */ cfg.channel = CONFIG_MESH_CHANNEL; cfg.router.ssid_len = strlen(CONFIG_MESH_ROUTER_SSID); @@ -394,22 +372,6 @@ void app_main(void) memcpy((uint8_t *) &cfg.mesh_ap.password, CONFIG_MESH_AP_PASSWD, strlen(CONFIG_MESH_AP_PASSWD)); ESP_ERROR_CHECK(esp_mesh_set_config(&cfg)); - /* set RSSI threshold for connecting to the root */ - mesh_switch_parent_t switch_paras ; - ESP_ERROR_CHECK(esp_mesh_get_switch_parent_paras(&switch_paras)); - switch_paras.backoff_rssi = -45; - ESP_ERROR_CHECK(esp_mesh_set_switch_parent_paras(&switch_paras)); - -#ifdef MESH_SET_PARENT - /* parent */ - wifi_config_t parent = { - .sta = { - .ssid = CONFIG_MESH_PARENT_SSID, - .channel = CONFIG_MESH_CHANNEL, - }, - }; - ESP_ERROR_CHECK(esp_mesh_set_parent(&parent, MESH_ROOT, 1)); -#endif /* mesh start */ ESP_ERROR_CHECK(esp_mesh_start()); ESP_LOGI(MESH_TAG, "mesh starts successfully, heap:%d, %s\n", esp_get_free_heap_size(), diff --git a/examples/mesh/manual_networking/README.md b/examples/mesh/manual_networking/README.md new file mode 100644 index 0000000000..8615dbd6de --- /dev/null +++ b/examples/mesh/manual_networking/README.md @@ -0,0 +1,14 @@ +# Mesh Manual Networking Example + +ESP-MESH provides the function of self-organized networking, but if users disable this function on one node, users must designate a parent for this node. + + +This example demonstrates how to scan a list of parent candidates, choose an appropriate parent and set as the parent of this node. + +If no parent is found through this scan, enable the self-organized function to let the ESP-MESH handle it by itself. + +Run `make menuconfig` to configure the mesh network channel, router SSID, router password and mesh softAP settings. + +When the mesh network is established and if you happen to run this example on ESP-WROVER-KIT boards, the RGB light indicator will show you on which layer devices are. The pink reprents root; the yellow reprents layer 2; the red reprents layer 3; the blue reprents layer 4; the green reprents layer 5; the white reprents layer greater than 5. + + diff --git a/examples/peripherals/adc2/main/adc2_example_main.c b/examples/peripherals/adc2/main/adc2_example_main.c index 309053ad1a..3542dad8d9 100644 --- a/examples/peripherals/adc2/main/adc2_example_main.c +++ b/examples/peripherals/adc2/main/adc2_example_main.c @@ -28,8 +28,10 @@ void app_main(void) gpio_num_t adc_gpio_num, dac_gpio_num; - assert( adc2_pad_get_io_num( ADC2_EXAMPLE_CHANNEL, &adc_gpio_num ) == ESP_OK ); - assert( dac_pad_get_io_num( DAC_EXAMPLE_CHANNEL, &dac_gpio_num ) == ESP_OK ); + r = adc2_pad_get_io_num( ADC2_EXAMPLE_CHANNEL, &adc_gpio_num ); + assert( r == ESP_OK ); + r = dac_pad_get_io_num( DAC_EXAMPLE_CHANNEL, &dac_gpio_num ); + assert( r == ESP_OK ); printf("ADC channel %d @ GPIO %d, DAC channel %d @ GPIO %d.\n", ADC2_EXAMPLE_CHANNEL, adc_gpio_num, DAC_EXAMPLE_CHANNEL, dac_gpio_num ); diff --git a/examples/peripherals/pcnt/main/pcnt_example_main.c b/examples/peripherals/pcnt/main/pcnt_example_main.c index 2a4b3695c7..a5da7946b3 100644 --- a/examples/peripherals/pcnt/main/pcnt_example_main.c +++ b/examples/peripherals/pcnt/main/pcnt_example_main.c @@ -54,6 +54,7 @@ #define LEDC_OUTPUT_IO 18 // Output GPIO of a sample 1 Hz pulse generator xQueueHandle pcnt_evt_queue; // A queue to handle pulse counter events +pcnt_isr_handle_t user_isr_handle = NULL; //user's ISR service handle /* A sample structure to pass events from the PCNT * interrupt handler to the main program. @@ -159,7 +160,7 @@ static void pcnt_example_init(void) pcnt_counter_clear(PCNT_TEST_UNIT); /* Register ISR handler and enable interrupts for PCNT unit */ - pcnt_isr_register(pcnt_example_intr_handler, NULL, 0, NULL); + pcnt_isr_register(pcnt_example_intr_handler, NULL, 0, &user_isr_handle); pcnt_intr_enable(PCNT_TEST_UNIT); /* Everything is set up, now go to counting */ @@ -206,4 +207,9 @@ void app_main() printf("Current counter value :%d\n", count); } } + if(user_isr_handle) { + //Free the ISR service handle. + esp_intr_free(user_isr_handle); + user_isr_handle = NULL; + } } diff --git a/examples/peripherals/touch_pad_interrupt/main/tp_interrupt_main.c b/examples/peripherals/touch_pad_interrupt/main/tp_interrupt_main.c index dd0f8c26d4..e3e3cbf212 100644 --- a/examples/peripherals/touch_pad_interrupt/main/tp_interrupt_main.c +++ b/examples/peripherals/touch_pad_interrupt/main/tp_interrupt_main.c @@ -35,14 +35,11 @@ static uint32_t s_pad_init_val[TOUCH_PAD_MAX]; static void tp_example_set_thresholds(void) { uint16_t touch_value; - //delay some time in order to make the filter work and get a initial value - vTaskDelay(500/portTICK_PERIOD_MS); - for (int i = 0; i +#include +#include +#include "esp_timer.h" +#include "esp_log.h" +#include "esp_sleep.h" +#include "sdkconfig.h" + +static void periodic_timer_callback(void* arg); +static void oneshot_timer_callback(void* arg); + +static const char* TAG = "example"; + +void app_main() +{ + /* Create two timers: + * 1. a periodic timer which will run every 0.5s, and print a message + * 2. a one-shot timer which will fire after 5s, and re-start periodic + * timer with period of 1s. + */ + + const esp_timer_create_args_t periodic_timer_args = { + .callback = &periodic_timer_callback, + /* name is optional, but may help identify the timer when debugging */ + .name = "periodic" + }; + + esp_timer_handle_t periodic_timer; + ESP_ERROR_CHECK(esp_timer_create(&periodic_timer_args, &periodic_timer)); + /* The timer has been created but is not running yet */ + + const esp_timer_create_args_t oneshot_timer_args = { + .callback = &oneshot_timer_callback, + /* argument specified here will be passed to timer callback function */ + .arg = (void*) periodic_timer, + .name = "one-shot" + }; + esp_timer_handle_t oneshot_timer; + ESP_ERROR_CHECK(esp_timer_create(&oneshot_timer_args, &oneshot_timer)); + + /* Start the timers */ + ESP_ERROR_CHECK(esp_timer_start_periodic(periodic_timer, 500000)); + ESP_ERROR_CHECK(esp_timer_start_once(oneshot_timer, 5000000)); + ESP_LOGI(TAG, "Started timers, time since boot: %lld us", esp_timer_get_time()); + + /* Print debugging information about timers to console every 2 seconds */ + for (int i = 0; i < 5; ++i) { + ESP_ERROR_CHECK(esp_timer_dump(stdout)); + usleep(2000000); + } + + /* Timekeeping continues in light sleep, and timers are scheduled + * correctly after light sleep. + */ + ESP_LOGI(TAG, "Entering light sleep for 0.5s, time since boot: %lld us", + esp_timer_get_time()); + + ESP_ERROR_CHECK(esp_sleep_enable_timer_wakeup(500000)); + esp_light_sleep_start(); + + ESP_LOGI(TAG, "Woke up from light sleep, time since boot: %lld us", + esp_timer_get_time()); + + /* Let the timer run for a little bit more */ + usleep(2000000); + + /* Clean up and finish the example */ + ESP_ERROR_CHECK(esp_timer_stop(periodic_timer)); + ESP_ERROR_CHECK(esp_timer_delete(periodic_timer)); + ESP_ERROR_CHECK(esp_timer_delete(oneshot_timer)); + ESP_LOGI(TAG, "Stopped and deleted timers"); +} + +static void periodic_timer_callback(void* arg) +{ + int64_t time_since_boot = esp_timer_get_time(); + ESP_LOGI(TAG, "Periodic timer called, time since boot: %lld us", time_since_boot); +} + +static void oneshot_timer_callback(void* arg) +{ + int64_t time_since_boot = esp_timer_get_time(); + ESP_LOGI(TAG, "One-shot timer called, time since boot: %lld us", time_since_boot); + esp_timer_handle_t periodic_timer_handle = (esp_timer_handle_t) arg; + /* To start the timer which is running, need to stop it first */ + ESP_ERROR_CHECK(esp_timer_stop(periodic_timer_handle)); + ESP_ERROR_CHECK(esp_timer_start_periodic(periodic_timer_handle, 1000000)); + time_since_boot = esp_timer_get_time(); + ESP_LOGI(TAG, "Restarted periodic timer with 1s period, time since boot: %lld us", + time_since_boot); +} diff --git a/examples/system/esp_timer/sdkconfig.defaults b/examples/system/esp_timer/sdkconfig.defaults new file mode 100644 index 0000000000..2d504b983f --- /dev/null +++ b/examples/system/esp_timer/sdkconfig.defaults @@ -0,0 +1 @@ +CONFIG_ESP_TIMER_PROFILING=y diff --git a/examples/system/ota/README.md b/examples/system/ota/README.md index 2b0e0202b0..a1d63d5393 100644 --- a/examples/system/ota/README.md +++ b/examples/system/ota/README.md @@ -1,67 +1,94 @@ +# OTA Demo -# Simple OTA Demo +## Introduction -This example demonstrates a working OTA (over the air) firmware update workflow. +Over The Air (OTA) updates can be performed in esp32 in two ways: -This example is a *simplified demonstration*, for production firmware updates you should use a secure protocol such as HTTPS. +- Using native APIs which are part of OTA component. +- Using simplified APIs which are part of `esp_https_ota`, it's an abstraction layer over OTA APIs to perform updates using HTTPS. + +Both these methods are demonstrated in OTA Demo under `native_ota_example` and `simple_ota_example` respectively. + +*Note: This guide is common for both the examples* --- -# Aim +## Aim An app running on ESP32 can upgrade itself by downloading a new app "image" binary file, and storing it in flash. In this example, the ESP32 has 3 images in flash: factory, OTA_0, OTA_1. Each of these is a self-contained partition. The number of OTA image partition is determined by the partition table layout. -Flashing the example over serial with "make flash" updates the factory app image. On first boot, the bootloader loads this factory app image which then performs an OTA update (triggered in the example code). The update downloads a new image from an http server and saves it into the OTA_0 partition. At this point the example code updates the ota_data partition to indicate the new app partition, and resets. The bootloader reads ota_data, determines the new OTA image has been selected, and runs it. +Flashing the example over serial with "make flash" updates the factory app image. On first boot, the bootloader loads this factory app image which then performs an OTA update (triggered in the example code). The update downloads a new image from a HTTPS server and saves it into the OTA_0 partition. At this point the example code updates the ota_data partition to indicate the new app partition, and resets. The bootloader reads ota_data, determines the new OTA image has been selected, and runs it. -# Workflow +## Workflow The OTA_workflow.png diagram demonstrates the overall workflow: ![OTA Workflow diagram](OTA_workflow.png) -## Step 1: Connect to AP +### Step 1: Connect to AP Connect your host PC to the same AP that you will use for the ESP32. -## Step 2: Run HTTP Server - -Python has a built-in HTTP server that can be used for example purposes. +### Step 2: Run HTTPS Server For our upgrade example OTA file, we're going to use the `get-started/hello_world` example. Open a new terminal to run the HTTP server, then run these commands to build the example and start the server: +Build the example: + ``` cd $IDF_PATH/examples/get-started/hello_world make cd build -python -m SimpleHTTPServer 8070 ``` -While the server is running, the contents of the build directory can be browsed at http://localhost:8070/ +Generate self-signed certificate and key: -NB: On some systems, the command may be `python2 -m SimpleHTTPServer`. +*NOTE: `Common Name` of server certificate should be host-name of your server.* + +``` +openssl req -x509 -newkey rsa:2048 -keyout ca_key.pem -out ca_cert.pem -days 365 + +``` + +Copy the certificate to OTA example directory: + +``` +cp ca_cert.pem $IDF_PATH/examples/system/ota/server_certs/ca_cert.pem +``` + + +Start the HTTPS server: + +``` +openssl s_server -WWW -key ca_key.pem -cert ca_cert.pem -port 8070 +``` NB: You've probably noticed there is nothing special about the "hello world" example when used for OTA updates. This is because any .bin app file which is built by esp-idf can be used as an app image for OTA. The only difference is whether it is written to a factory partition or an OTA partition. If you have any firewall software running that will block incoming access to port 8070, configure it to allow access while running the example. -## Step 3: Build OTA Example +### Step 3: Build OTA Example Change back to the OTA example directory, and type `make menuconfig` to configure the OTA example. Under the "Example Configuration" submenu, fill in the following details: * WiFi SSID & Password -* IP address of your host PC as "HTTP Server" -* HTTP Port number (if using the Python HTTP server above, the default is correct) +* Firmware Upgrade URL. The URL will look like this: -If serving the "hello world" example, you can leave the default filename as-is. +``` +https://:/ + +for e.g, +https://192.168.0.3:8070/hello-world.bin +``` Save your changes, and type `make` to build the example. -## Step 4: Flash OTA Example +### Step 4: Flash OTA Example When flashing, use the `erase_flash` target first to erase the entire flash (this deletes any leftover data in the ota_data partition). Then flash the factory image over serial: @@ -71,31 +98,29 @@ make erase_flash flash (The `make erase_flash flash` means "erase everything, then flash". `make flash` only erases the parts of flash which are being rewritten.) -## Step 5: Run the OTA Example +### Step 5: Run the OTA Example -When the example starts up, it will print "ota: Starting OTA example..." then: +When the example starts up, it will print "Starting OTA example..." then: 1. Connect to the AP with configured SSID and password. 2. Connect to the HTTP server and download the new image. 3. Write the image to flash, and configure the next boot from this image. 4. Reboot -# Troubleshooting +## Troubleshooting * Check your PC can ping the ESP32 at its IP, and that the IP, AP and other configuration settings are correct in menuconfig. * Check if any firewall software is preventing incoming connections on the PC. -* Check you can see the configured file (default hello-world.bin) if you browse the file listing at http://127.0.0.1/ +* Check whether you can see the configured file (default hello-world.bin), by checking the output of following command: + + ``` + curl -v https://:/ + ``` + * If you have another PC or a phone, try viewing the file listing from the separate host. -## Error "ota_begin error err=0x104" +### Error "ota_begin error err=0x104" If you see this error then check that the configured (and actual) flash size is large enough for the partitions in the partition table. The default "two OTA slots" partition table only works with 4MB flash size. To use OTA with smaller flash sizes, create a custom partition table CSV (look in components/partition_table) and configure it in menuconfig. If changing partition layout, it is usually wise to run "make erase_flash" between steps. - -## Production Implementation - -If scaling this example for production use, please consider: - -* Using an encrypted communications channel such as HTTPS. -* Dealing with timeouts or WiFi disconnections while flashing. diff --git a/examples/system/ota/Makefile b/examples/system/ota/native_ota_example/Makefile similarity index 85% rename from examples/system/ota/Makefile rename to examples/system/ota/native_ota_example/Makefile index 7ffb10234f..3bcbefac0d 100644 --- a/examples/system/ota/Makefile +++ b/examples/system/ota/native_ota_example/Makefile @@ -3,7 +3,7 @@ # project subdirectory. # -PROJECT_NAME := ota +PROJECT_NAME := native_ota include $(IDF_PATH)/make/project.mk diff --git a/examples/system/ota/native_ota_example/README.md b/examples/system/ota/native_ota_example/README.md new file mode 100644 index 0000000000..be57ce55ec --- /dev/null +++ b/examples/system/ota/native_ota_example/README.md @@ -0,0 +1,7 @@ +# Native OTA example + +This example is based on `app_update` component's APIs. + +## Configuration + +Refer the README.md in the parent directory for the setup details. \ No newline at end of file diff --git a/examples/system/ota/main/Kconfig.projbuild b/examples/system/ota/native_ota_example/main/Kconfig.projbuild similarity index 52% rename from examples/system/ota/main/Kconfig.projbuild rename to examples/system/ota/native_ota_example/main/Kconfig.projbuild index 2d4b8c4360..05965e9426 100644 --- a/examples/system/ota/main/Kconfig.projbuild +++ b/examples/system/ota/native_ota_example/main/Kconfig.projbuild @@ -14,27 +14,12 @@ config WIFI_PASSWORD Can be left blank if the network has no security set. -config SERVER_IP - string "HTTP Server IP" - default "192.168.0.3" +config FIRMWARE_UPG_URL + string "HTTP Server URL" + default "https://192.168.0.3:8070/hello-world.bin" help HTTP Server IP to download the image file from. See example README.md for details. -config SERVER_PORT - string "HTTP Server Port" - default "8070" - help - HTTP Server port to connect to. - Should be chosen not to conflict with any other port used - on the system. - -config EXAMPLE_FILENAME - string "HTTP GET Filename" - default "/hello-world.bin" - help - Filename of the app image file to download for - the OTA update. - endmenu diff --git a/examples/system/ota/native_ota_example/main/component.mk b/examples/system/ota/native_ota_example/main/component.mk new file mode 100644 index 0000000000..93a42f552f --- /dev/null +++ b/examples/system/ota/native_ota_example/main/component.mk @@ -0,0 +1,6 @@ +# +# "main" pseudo-component makefile. +# +# (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.) + +COMPONENT_EMBED_TXTFILES := ${IDF_PATH}/examples/system/ota/server_certs/ca_cert.pem diff --git a/examples/system/ota/main/ota_example_main.c b/examples/system/ota/native_ota_example/main/native_ota_example.c similarity index 50% rename from examples/system/ota/main/ota_example_main.c rename to examples/system/ota/native_ota_example/main/native_ota_example.c index b5e0f60625..1478cbd4e1 100644 --- a/examples/system/ota/main/ota_example_main.c +++ b/examples/system/ota/native_ota_example/main/native_ota_example.c @@ -6,10 +6,6 @@ software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */ -#include -#include -#include - #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "freertos/event_groups.h" @@ -19,27 +15,21 @@ #include "esp_event_loop.h" #include "esp_log.h" #include "esp_ota_ops.h" +#include "esp_http_client.h" #include "nvs.h" #include "nvs_flash.h" #define EXAMPLE_WIFI_SSID CONFIG_WIFI_SSID #define EXAMPLE_WIFI_PASS CONFIG_WIFI_PASSWORD -#define EXAMPLE_SERVER_IP CONFIG_SERVER_IP -#define EXAMPLE_SERVER_PORT CONFIG_SERVER_PORT -#define EXAMPLE_FILENAME CONFIG_EXAMPLE_FILENAME +#define EXAMPLE_SERVER_URL CONFIG_FIRMWARE_UPG_URL #define BUFFSIZE 1024 -#define TEXT_BUFFSIZE 1024 -static const char *TAG = "ota"; +static const char *TAG = "native_ota_example"; /*an ota data write buffer ready to write to the flash*/ static char ota_write_data[BUFFSIZE + 1] = { 0 }; -/*an packet receive buffer*/ -static char text[BUFFSIZE + 1] = { 0 }; -/* an image total length*/ -static int binary_file_length = 0; -/*socket id*/ -static int socket_id = -1; +extern const uint8_t server_cert_pem_start[] asm("_binary_ca_cert_pem_start"); +extern const uint8_t server_cert_pem_end[] asm("_binary_ca_cert_pem_end"); /* FreeRTOS event group to signal when we are connected & ready to make a request */ static EventGroupHandle_t wifi_event_group; @@ -90,85 +80,15 @@ static void initialise_wifi(void) ESP_ERROR_CHECK( esp_wifi_start() ); } -/*read buffer by byte still delim ,return read bytes counts*/ -static int read_until(char *buffer, char delim, int len) +static void http_cleanup(esp_http_client_handle_t client) { -// /*TODO: delim check,buffer check,further: do an buffer length limited*/ - int i = 0; - while (buffer[i] != delim && i < len) { - ++i; - } - return i + 1; -} - -/* resolve a packet from http socket - * return true if packet including \r\n\r\n that means http packet header finished,start to receive packet body - * otherwise return false - * */ -static bool read_past_http_header(char text[], int total_len, esp_ota_handle_t update_handle) -{ - /* i means current position */ - int i = 0, i_read_len = 0; - while (text[i] != 0 && i < total_len) { - i_read_len = read_until(&text[i], '\n', total_len); - // if we resolve \r\n line,we think packet header is finished - if (i_read_len == 2) { - int i_write_len = total_len - (i + 2); - memset(ota_write_data, 0, BUFFSIZE); - /*copy first http packet body to write buffer*/ - memcpy(ota_write_data, &(text[i + 2]), i_write_len); - - esp_err_t err = esp_ota_write( update_handle, (const void *)ota_write_data, i_write_len); - if (err != ESP_OK) { - ESP_LOGE(TAG, "Error: esp_ota_write failed (%s)!", esp_err_to_name(err)); - return false; - } else { - ESP_LOGI(TAG, "esp_ota_write header OK"); - binary_file_length += i_write_len; - } - return true; - } - i += i_read_len; - } - return false; -} - -static bool connect_to_http_server() -{ - ESP_LOGI(TAG, "Server IP: %s Server Port:%s", EXAMPLE_SERVER_IP, EXAMPLE_SERVER_PORT); - - int http_connect_flag = -1; - struct sockaddr_in sock_info; - - socket_id = socket(AF_INET, SOCK_STREAM, 0); - if (socket_id == -1) { - ESP_LOGE(TAG, "Create socket failed!"); - return false; - } - - // set connect info - memset(&sock_info, 0, sizeof(struct sockaddr_in)); - sock_info.sin_family = AF_INET; - sock_info.sin_addr.s_addr = inet_addr(EXAMPLE_SERVER_IP); - sock_info.sin_port = htons(atoi(EXAMPLE_SERVER_PORT)); - - // connect to http server - http_connect_flag = connect(socket_id, (struct sockaddr *)&sock_info, sizeof(sock_info)); - if (http_connect_flag == -1) { - ESP_LOGE(TAG, "Connect to server failed! errno=%d", errno); - close(socket_id); - return false; - } else { - ESP_LOGI(TAG, "Connected to server"); - return true; - } - return false; + esp_http_client_close(client); + esp_http_client_cleanup(client); } static void __attribute__((noreturn)) task_fatal_error() { ESP_LOGE(TAG, "Exiting task due to fatal error..."); - close(socket_id); (void)vTaskDelete(NULL); while (1) { @@ -202,36 +122,23 @@ static void ota_example_task(void *pvParameter) xEventGroupWaitBits(wifi_event_group, CONNECTED_BIT, false, true, portMAX_DELAY); ESP_LOGI(TAG, "Connect to Wifi ! Start to Connect to Server...."); - - /*connect to http server*/ - if (connect_to_http_server()) { - ESP_LOGI(TAG, "Connected to http server"); - } else { - ESP_LOGE(TAG, "Connect to http server failed!"); + + esp_http_client_config_t config = { + .url = EXAMPLE_SERVER_URL, + .cert_pem = (char *)server_cert_pem_start, + }; + esp_http_client_handle_t client = esp_http_client_init(&config); + if (client == NULL) { + ESP_LOGE(TAG, "Failed to initialise HTTP connection"); task_fatal_error(); } - - /*send GET request to http server*/ - const char *GET_FORMAT = - "GET %s HTTP/1.0\r\n" - "Host: %s:%s\r\n" - "User-Agent: esp-idf/1.0 esp32\r\n\r\n"; - - char *http_request = NULL; - int get_len = asprintf(&http_request, GET_FORMAT, EXAMPLE_FILENAME, EXAMPLE_SERVER_IP, EXAMPLE_SERVER_PORT); - if (get_len < 0) { - ESP_LOGE(TAG, "Failed to allocate memory for GET request buffer"); + err = esp_http_client_open(client, 0); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Failed to open HTTP connection: %s", esp_err_to_name(err)); + esp_http_client_cleanup(client); task_fatal_error(); } - int res = send(socket_id, http_request, get_len, 0); - free(http_request); - - if (res < 0) { - ESP_LOGE(TAG, "Send GET request to server failed"); - task_fatal_error(); - } else { - ESP_LOGI(TAG, "Send GET request to server succeeded"); - } + esp_http_client_fetch_headers(client); update_partition = esp_ota_get_next_update_partition(NULL); ESP_LOGI(TAG, "Writing to partition subtype %d at offset 0x%x", @@ -241,55 +148,43 @@ static void ota_example_task(void *pvParameter) err = esp_ota_begin(update_partition, OTA_SIZE_UNKNOWN, &update_handle); if (err != ESP_OK) { ESP_LOGE(TAG, "esp_ota_begin failed (%s)", esp_err_to_name(err)); + http_cleanup(client); task_fatal_error(); } ESP_LOGI(TAG, "esp_ota_begin succeeded"); - bool resp_body_start = false, socket_flag = true, http_200_flag = false; + int binary_file_length = 0; /*deal with all receive packet*/ - while (socket_flag) { - memset(text, 0, TEXT_BUFFSIZE); - memset(ota_write_data, 0, BUFFSIZE); - int buff_len = recv(socket_id, text, TEXT_BUFFSIZE, 0); - if (buff_len < 0) { /*receive error*/ - ESP_LOGE(TAG, "Error: receive data error! errno=%d", errno); + while (1) { + int data_read = esp_http_client_read(client, ota_write_data, BUFFSIZE); + if (data_read < 0) { + ESP_LOGE(TAG, "Error: SSL data read error"); + http_cleanup(client); task_fatal_error(); - } else if (buff_len > 0 && !resp_body_start) { /*deal with response header*/ - // only start ota when server response 200 state code - if (strstr(text, "200") == NULL && !http_200_flag) { - ESP_LOGE(TAG, "ota url is invalid or bin is not exist"); - task_fatal_error(); - } - http_200_flag = true; - memcpy(ota_write_data, text, buff_len); - resp_body_start = read_past_http_header(text, buff_len, update_handle); - } else if (buff_len > 0 && resp_body_start) { /*deal with response body*/ - memcpy(ota_write_data, text, buff_len); - err = esp_ota_write( update_handle, (const void *)ota_write_data, buff_len); + } else if (data_read > 0) { + err = esp_ota_write( update_handle, (const void *)ota_write_data, data_read); if (err != ESP_OK) { - ESP_LOGE(TAG, "Error: esp_ota_write failed (%s)!", esp_err_to_name(err)); + http_cleanup(client); task_fatal_error(); } - binary_file_length += buff_len; - ESP_LOGI(TAG, "Have written image length %d", binary_file_length); - } else if (buff_len == 0) { /*packet over*/ - socket_flag = false; - ESP_LOGI(TAG, "Connection closed, all packets received"); - close(socket_id); - } else { - ESP_LOGE(TAG, "Unexpected recv result"); + binary_file_length += data_read; + ESP_LOGD(TAG, "Written image length %d", binary_file_length); + } else if (data_read == 0) { + ESP_LOGI(TAG, "Connection closed,all data received"); + break; } } - ESP_LOGI(TAG, "Total Write binary data length : %d", binary_file_length); if (esp_ota_end(update_handle) != ESP_OK) { ESP_LOGE(TAG, "esp_ota_end failed!"); + http_cleanup(client); task_fatal_error(); } err = esp_ota_set_boot_partition(update_partition); if (err != ESP_OK) { ESP_LOGE(TAG, "esp_ota_set_boot_partition failed (%s)!", esp_err_to_name(err)); + http_cleanup(client); task_fatal_error(); } ESP_LOGI(TAG, "Prepare to restart system!"); @@ -301,7 +196,7 @@ void app_main() { // Initialize NVS. esp_err_t err = nvs_flash_init(); - if (err == ESP_ERR_NVS_NO_FREE_PAGES) { + if (err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND) { // OTA app partition table has a smaller NVS partition size than the non-OTA // partition table. This size mismatch may cause NVS initialization to fail. // If this happens, we erase NVS partition and initialize NVS again. diff --git a/examples/system/ota/sdkconfig.defaults b/examples/system/ota/native_ota_example/sdkconfig.defaults similarity index 100% rename from examples/system/ota/sdkconfig.defaults rename to examples/system/ota/native_ota_example/sdkconfig.defaults diff --git a/examples/system/ota/server_certs/ca_cert.pem b/examples/system/ota/server_certs/ca_cert.pem new file mode 100644 index 0000000000..e69de29bb2 diff --git a/examples/system/ota/simple_ota_example/Makefile b/examples/system/ota/simple_ota_example/Makefile new file mode 100644 index 0000000000..63bca1abe9 --- /dev/null +++ b/examples/system/ota/simple_ota_example/Makefile @@ -0,0 +1,9 @@ +# +# This is a project Makefile. It is assumed the directory this Makefile resides in is a +# project subdirectory. +# + +PROJECT_NAME := simple_ota + +include $(IDF_PATH)/make/project.mk + diff --git a/examples/system/ota/simple_ota_example/README.md b/examples/system/ota/simple_ota_example/README.md new file mode 100644 index 0000000000..437964f741 --- /dev/null +++ b/examples/system/ota/simple_ota_example/README.md @@ -0,0 +1,7 @@ +# Simple OTA example + +This example is based on `http_firmware_upgrade` component's APIs. + +## Configuration + +Refer README.md in the parent directory for setup details \ No newline at end of file diff --git a/examples/system/ota/simple_ota_example/main/Kconfig.projbuild b/examples/system/ota/simple_ota_example/main/Kconfig.projbuild new file mode 100644 index 0000000000..38bf5cb4d4 --- /dev/null +++ b/examples/system/ota/simple_ota_example/main/Kconfig.projbuild @@ -0,0 +1,21 @@ +menu "Example Configuration" + +config WIFI_SSID + string "WiFi SSID" + default "myssid" + help + SSID (network name) for the example to connect to. + +config WIFI_PASSWORD + string "WiFi Password" + default "mypassword" + help + WiFi password (WPA or WPA2) for the example to use. + +config FIRMWARE_UPGRADE_URL + string "firmware upgrade url endpoint" + default "https://192.168.0.3:8070/hello-world.bin" + help + URL of server which hosts the firmware + image. +endmenu diff --git a/examples/system/ota/simple_ota_example/main/component.mk b/examples/system/ota/simple_ota_example/main/component.mk new file mode 100644 index 0000000000..93a42f552f --- /dev/null +++ b/examples/system/ota/simple_ota_example/main/component.mk @@ -0,0 +1,6 @@ +# +# "main" pseudo-component makefile. +# +# (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.) + +COMPONENT_EMBED_TXTFILES := ${IDF_PATH}/examples/system/ota/server_certs/ca_cert.pem diff --git a/examples/system/ota/simple_ota_example/main/simple_ota_example.c b/examples/system/ota/simple_ota_example/main/simple_ota_example.c new file mode 100644 index 0000000000..7972f8bd57 --- /dev/null +++ b/examples/system/ota/simple_ota_example/main/simple_ota_example.c @@ -0,0 +1,147 @@ +/* OTA example + + This example code is in the Public Domain (or CC0 licensed, at your option.) + + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. +*/ +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/event_groups.h" + +#include "esp_system.h" +#include "esp_wifi.h" +#include "esp_event_loop.h" +#include "esp_log.h" +#include "esp_ota_ops.h" +#include "esp_http_client.h" +#include "esp_https_ota.h" + +#include "nvs.h" +#include "nvs_flash.h" + +static const char *TAG = "simple_ota_example"; +extern const uint8_t server_cert_pem_start[] asm("_binary_ca_cert_pem_start"); +extern const uint8_t server_cert_pem_end[] asm("_binary_ca_cert_pem_end"); + +/* FreeRTOS event group to signal when we are connected & ready to make a request */ +static EventGroupHandle_t wifi_event_group; + +/* The event group allows multiple bits for each event, + but we only care about one event - are we connected + to the AP with an IP? */ +const int CONNECTED_BIT = BIT0; + +esp_err_t _http_event_handler(esp_http_client_event_t *evt) +{ + switch(evt->event_id) { + case HTTP_EVENT_ERROR: + ESP_LOGD(TAG, "HTTP_EVENT_ERROR"); + break; + case HTTP_EVENT_ON_CONNECTED: + ESP_LOGD(TAG, "HTTP_EVENT_ON_CONNECTED"); + break; + case HTTP_EVENT_HEADER_SENT: + ESP_LOGD(TAG, "HTTP_EVENT_HEADER_SENT"); + break; + case HTTP_EVENT_ON_HEADER: + ESP_LOGD(TAG, "HTTP_EVENT_ON_HEADER, key=%s, value=%s", evt->header_key, evt->header_value); + break; + case HTTP_EVENT_ON_DATA: + ESP_LOGD(TAG, "HTTP_EVENT_ON_DATA, len=%d", evt->data_len); + break; + case HTTP_EVENT_ON_FINISH: + ESP_LOGD(TAG, "HTTP_EVENT_ON_FINISH"); + break; + case HTTP_EVENT_DISCONNECTED: + ESP_LOGD(TAG, "HTTP_EVENT_DISCONNECTED"); + break; + } + return ESP_OK; +} + +static esp_err_t event_handler(void *ctx, system_event_t *event) +{ + switch (event->event_id) { + case SYSTEM_EVENT_STA_START: + esp_wifi_connect(); + break; + case SYSTEM_EVENT_STA_GOT_IP: + xEventGroupSetBits(wifi_event_group, CONNECTED_BIT); + break; + case SYSTEM_EVENT_STA_DISCONNECTED: + /* This is a workaround as ESP32 WiFi libs don't currently + auto-reassociate. */ + esp_wifi_connect(); + xEventGroupClearBits(wifi_event_group, CONNECTED_BIT); + break; + default: + break; + } + return ESP_OK; +} + +static void initialise_wifi(void) +{ + tcpip_adapter_init(); + wifi_event_group = xEventGroupCreate(); + ESP_ERROR_CHECK( esp_event_loop_init(event_handler, NULL) ); + wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); + ESP_ERROR_CHECK( esp_wifi_init(&cfg) ); + ESP_ERROR_CHECK( esp_wifi_set_storage(WIFI_STORAGE_RAM) ); + wifi_config_t wifi_config = { + .sta = { + .ssid = CONFIG_WIFI_SSID, + .password = CONFIG_WIFI_PASSWORD, + }, + }; + ESP_LOGI(TAG, "Setting WiFi configuration SSID %s...", wifi_config.sta.ssid); + ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_STA) ); + ESP_ERROR_CHECK( esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config) ); + ESP_ERROR_CHECK( esp_wifi_start() ); +} + +void simple_ota_example_task(void * pvParameter) +{ + ESP_LOGI(TAG, "Starting OTA example..."); + + /* Wait for the callback to set the CONNECTED_BIT in the + event group. + */ + xEventGroupWaitBits(wifi_event_group, CONNECTED_BIT, + false, true, portMAX_DELAY); + ESP_LOGI(TAG, "Connect to Wifi ! Start to Connect to Server...."); + + esp_http_client_config_t config = { + .url = CONFIG_FIRMWARE_UPGRADE_URL, + .cert_pem = (char *)server_cert_pem_start, + .event_handler = _http_event_handler, + }; + esp_err_t ret = esp_https_ota(&config); + if (ret == ESP_OK) { + esp_restart(); + } else { + ESP_LOGE(TAG, "Firmware Upgrades Failed"); + } + while (1) { + vTaskDelay(1000 / portTICK_PERIOD_MS); + } +} + +void app_main() +{ + // Initialize NVS. + esp_err_t err = nvs_flash_init(); + if (err == ESP_ERR_NVS_NO_FREE_PAGES) { + // OTA app partition table has a smaller NVS partition size than the non-OTA + // partition table. This size mismatch may cause NVS initialization to fail. + // If this happens, we erase NVS partition and initialize NVS again. + ESP_ERROR_CHECK(nvs_flash_erase()); + err = nvs_flash_init(); + } + ESP_ERROR_CHECK( err ); + + initialise_wifi(); + xTaskCreate(&simple_ota_example_task, "ota_example_task", 8192, NULL, 5, NULL); +} diff --git a/examples/system/ota/simple_ota_example/sdkconfig.defaults b/examples/system/ota/simple_ota_example/sdkconfig.defaults new file mode 100644 index 0000000000..2289a82300 --- /dev/null +++ b/examples/system/ota/simple_ota_example/sdkconfig.defaults @@ -0,0 +1,4 @@ +# Default sdkconfig parameters to use the OTA +# partition table layout, with a 4MB flash size +CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y +CONFIG_PARTITION_TABLE_TWO_OTA=y diff --git a/examples/system/ulp/main/ulp/pulse_cnt.S b/examples/system/ulp/main/ulp/pulse_cnt.S index e573e3244f..774375e2a1 100644 --- a/examples/system/ulp/main/ulp/pulse_cnt.S +++ b/examples/system/ulp/main/ulp/pulse_cnt.S @@ -66,12 +66,29 @@ io_number: .text .global entry entry: - /* Read the value of lower 16 RTC IOs into R0 */ - READ_RTC_FIELD(RTC_GPIO_IN_REG, RTC_GPIO_IN_NEXT) - /* Load io_number, extract the state of input */ + /* Load io_number */ move r3, io_number ld r3, r3, 0 + + /* Lower 16 IOs and higher need to be handled separately, + * because r0-r3 registers are 16 bit wide. + * Check which IO this is. + */ + move r0, r3 + jumpr read_io_high, 16, ge + + /* Read the value of lower 16 RTC IOs into R0 */ + READ_RTC_REG(RTC_GPIO_IN_REG, RTC_GPIO_IN_NEXT_S, 16) rsh r0, r0, r3 + jump read_done + + /* Read the value of RTC IOs 16-17, into R0 */ +read_io_high: + READ_RTC_REG(RTC_GPIO_IN_REG, RTC_GPIO_IN_NEXT_S + 16, 2) + sub r3, r3, 16 + rsh r0, r0, r3 + +read_done: and r0, r0, 1 /* State of input changed? */ move r3, next_edge diff --git a/examples/system/ulp/main/ulp_example_main.c b/examples/system/ulp/main/ulp_example_main.c index 873a17620a..74c4febe40 100644 --- a/examples/system/ulp/main/ulp_example_main.c +++ b/examples/system/ulp/main/ulp_example_main.c @@ -13,6 +13,7 @@ #include "nvs_flash.h" #include "soc/rtc_cntl_reg.h" #include "soc/sens_reg.h" +#include "soc/rtc_periph.h" #include "driver/gpio.h" #include "driver/rtc_io.h" #include "esp32/ulp.h" @@ -46,6 +47,10 @@ static void init_ulp_program() (ulp_main_bin_end - ulp_main_bin_start) / sizeof(uint32_t)); ESP_ERROR_CHECK(err); + /* GPIO used for pulse counting. */ + gpio_num_t gpio_num = GPIO_NUM_0; + assert(rtc_gpio_desc[gpio_num].reg && "GPIO used for pulse counting must be an RTC IO"); + /* Initialize some variables used by ULP program. * Each 'ulp_xyz' variable corresponds to 'xyz' variable in the ULP program. * These variables are declared in an auto generated header file, @@ -58,11 +63,11 @@ static void init_ulp_program() ulp_debounce_counter = 3; ulp_debounce_max_count = 3; ulp_next_edge = 0; - ulp_io_number = 11; /* GPIO0 is RTC_IO 11 */ + ulp_io_number = rtc_gpio_desc[gpio_num].rtc_num; /* map from GPIO# to RTC_IO# */ ulp_edge_count_to_wake_up = 10; - /* Initialize GPIO0 as RTC IO, input, disable pullup and pulldown */ - gpio_num_t gpio_num = GPIO_NUM_0; + /* Initialize selected GPIO as RTC IO, enable input, disable pullup and pulldown */ + rtc_gpio_init(gpio_num); rtc_gpio_set_direction(gpio_num, RTC_GPIO_MODE_INPUT_ONLY); rtc_gpio_pulldown_dis(gpio_num); rtc_gpio_pullup_dis(gpio_num); @@ -76,13 +81,13 @@ static void init_ulp_program() rtc_gpio_isolate(GPIO_NUM_12); rtc_gpio_isolate(GPIO_NUM_15); - /* Set ULP wake up period to T = 20ms (3095 cycles of RTC_SLOW_CLK clock). + /* Set ULP wake up period to T = 20ms. * Minimum pulse width has to be T * (ulp_debounce_counter + 1) = 80ms. */ - REG_SET_FIELD(SENS_ULP_CP_SLEEP_CYC0_REG, SENS_SLEEP_CYCLES_S0, 3095); + ulp_set_wakeup_period(0, 20000); /* Start the program */ - err = ulp_run((&ulp_entry - RTC_SLOW_MEM) / sizeof(uint32_t)); + err = ulp_run(&ulp_entry - RTC_SLOW_MEM); ESP_ERROR_CHECK(err); } diff --git a/examples/system/ulp_adc/main/ulp_adc_example_main.c b/examples/system/ulp_adc/main/ulp_adc_example_main.c index 29d8eac9af..fd7d4ef438 100644 --- a/examples/system/ulp_adc/main/ulp_adc_example_main.c +++ b/examples/system/ulp_adc/main/ulp_adc_example_main.c @@ -89,6 +89,6 @@ static void start_ulp_program() ulp_sample_counter = 0; /* Start the program */ - esp_err_t err = ulp_run((&ulp_entry - RTC_SLOW_MEM) / sizeof(uint32_t)); + esp_err_t err = ulp_run(&ulp_entry - RTC_SLOW_MEM); ESP_ERROR_CHECK(err); } diff --git a/examples/wifi/espnow/main/espnow_example_main.c b/examples/wifi/espnow/main/espnow_example_main.c index 68e56ff654..afb1428c52 100644 --- a/examples/wifi/espnow/main/espnow_example_main.c +++ b/examples/wifi/espnow/main/espnow_example_main.c @@ -375,7 +375,7 @@ void app_main() { // Initialize NVS esp_err_t ret = nvs_flash_init(); - if (ret == ESP_ERR_NVS_NO_FREE_PAGES) { + 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(); } diff --git a/examples/wifi/iperf/main/main.c b/examples/wifi/iperf/main/main.c index bb4940f79b..ffeeb680b5 100644 --- a/examples/wifi/iperf/main/main.c +++ b/examples/wifi/iperf/main/main.c @@ -71,7 +71,7 @@ static void initialize_console() void app_main(void) { esp_err_t ret = nvs_flash_init(); - if (ret == ESP_ERR_NVS_NO_FREE_PAGES) { + 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(); } diff --git a/examples/wifi/power_save/main/power_save.c b/examples/wifi/power_save/main/power_save.c index f40b898bcf..d2e60fdfd1 100644 --- a/examples/wifi/power_save/main/power_save.c +++ b/examples/wifi/power_save/main/power_save.c @@ -89,7 +89,7 @@ void app_main() { // Initialize NVS esp_err_t ret = nvs_flash_init(); - if (ret == ESP_ERR_NVS_NO_FREE_PAGES) { + 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(); } diff --git a/examples/wifi/scan/main/scan.c b/examples/wifi/scan/main/scan.c index ee82d859df..fa27bf7f21 100644 --- a/examples/wifi/scan/main/scan.c +++ b/examples/wifi/scan/main/scan.c @@ -117,7 +117,7 @@ void app_main() { // Initialize NVS esp_err_t ret = nvs_flash_init(); - if (ret == ESP_ERR_NVS_NO_FREE_PAGES) { + 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(); } diff --git a/examples/wifi/simple_wifi/main/simple_wifi.c b/examples/wifi/simple_wifi/main/simple_wifi.c index ccc5590165..456e880eef 100644 --- a/examples/wifi/simple_wifi/main/simple_wifi.c +++ b/examples/wifi/simple_wifi/main/simple_wifi.c @@ -130,7 +130,7 @@ void app_main() { //Initialize NVS esp_err_t ret = nvs_flash_init(); - if (ret == ESP_ERR_NVS_NO_FREE_PAGES) { + 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(); } diff --git a/examples/wifi/wps/main/wps.c b/examples/wifi/wps/main/wps.c index 6fb8ad2468..50ab8de9bc 100644 --- a/examples/wifi/wps/main/wps.c +++ b/examples/wifi/wps/main/wps.c @@ -112,7 +112,7 @@ void app_main() { /* Initialize NVS — it is used to store PHY calibration data */ esp_err_t ret = nvs_flash_init(); - if (ret == ESP_ERR_NVS_NO_FREE_PAGES) { + 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(); } diff --git a/make/project.mk b/make/project.mk index 01b29bcb38..10556b191f 100644 --- a/make/project.mk +++ b/make/project.mk @@ -153,7 +153,8 @@ COMPONENTS := $(sort $(foreach comp,$(COMPONENTS),$(lastword $(subst /, ,$(comp) endif # After a full manifest of component names is determined, subtract the ones explicitly omitted by the project Makefile. ifdef EXCLUDE_COMPONENTS -COMPONENTS := $(filter-out $(EXCLUDE_COMPONENTS), $(COMPONENTS)) +COMPONENTS := $(filter-out $(subst ",,$(EXCLUDE_COMPONENTS)), $(COMPONENTS)) +# to keep syntax highlighters happy: ")) endif export COMPONENTS @@ -405,15 +406,15 @@ $(APP_ELF): $(foreach libcomp,$(COMPONENT_LIBRARIES),$(BUILD_DIR_BASE)/$(libcomp $(summary) LD $(patsubst $(PWD)/%,%,$@) $(CC) $(LDFLAGS) -o $@ -Wl,-Map=$(APP_MAP) -app: $(APP_BIN) +app: $(APP_BIN) partition_table_get_info ifeq ("$(CONFIG_SECURE_BOOT_ENABLED)$(CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES)","y") # secure boot enabled, but remote sign app image @echo "App built but not signed. Signing step via espsecure.py:" @echo "espsecure.py sign_data --keyfile KEYFILE $(APP_BIN)" @echo "Then flash app command is:" - @echo $(ESPTOOLPY_WRITE_FLASH) $(CONFIG_APP_OFFSET) $(APP_BIN) + @echo $(ESPTOOLPY_WRITE_FLASH) $(APP_OFFSET) $(APP_BIN) else @echo "App built. Default flash app command is:" - @echo $(ESPTOOLPY_WRITE_FLASH) $(CONFIG_APP_OFFSET) $(APP_BIN) + @echo $(ESPTOOLPY_WRITE_FLASH) $(APP_OFFSET) $(APP_BIN) endif all_binaries: $(APP_BIN) @@ -543,7 +544,7 @@ list-components: $(foreach cp,$(COMPONENT_PATHS),$(info $(cp))) # print flash command, so users can dump this to config files and download somewhere without idf -print_flash_cmd: +print_flash_cmd: partition_table_get_info echo $(ESPTOOL_WRITE_FLASH_OPTIONS) $(ESPTOOL_ALL_FLASH_ARGS) | sed -e 's:'$(PWD)/build/'::g' # Check toolchain version using the output of xtensa-esp32-elf-gcc --version command. diff --git a/tools/ci/executable-list.txt b/tools/ci/executable-list.txt index a800ab83b8..54dcfaaffc 100644 --- a/tools/ci/executable-list.txt +++ b/tools/ci/executable-list.txt @@ -4,11 +4,14 @@ components/espcoredump/espcoredump.py components/heap/test_multi_heap_host/test_all_configs.sh components/idf_test/unit_test/TestCaseScript/IDFUnitTest/__init__.py components/partition_table/gen_esp32part.py +components/partition_table/parttool.py components/partition_table/test_gen_esp32part_host/gen_esp32part_tests.py components/ulp/esp32ulp_mapgen.py +components/nvs_flash/nvs_partition_generator/nvs_partition_gen.py docs/check_doc_warnings.sh docs/check_lang_folder_sync.sh docs/gen-kconfig-doc.py +docs/gen-version-specific-includes.py tools/ci/apply_bot_filter.py tools/ci/build_examples.sh tools/ci/check-executable.sh diff --git a/tools/cmake/project.cmake b/tools/cmake/project.cmake index e346bcbf27..e914ac1dac 100644 --- a/tools/cmake/project.cmake +++ b/tools/cmake/project.cmake @@ -108,7 +108,9 @@ macro(project name) # Include any top-level project_include.cmake files from components foreach(component ${BUILD_COMPONENT_PATHS}) + set(COMPONENT_PATH "${component}") include_if_exists("${component}/project_include.cmake") + unset(COMPONENT_PATH) endforeach() # diff --git a/tools/cmake/run_cmake_lint.sh b/tools/cmake/run_cmake_lint.sh index 6cdc4679a8..a21bc1168e 100755 --- a/tools/cmake/run_cmake_lint.sh +++ b/tools/cmake/run_cmake_lint.sh @@ -15,9 +15,11 @@ if [ -z "${IDF_PATH}" ]; then exit 3 fi +cd "$IDF_PATH" + # Only list the "main" IDF repo, don't check any files in submodules (which may contain # third party CMakeLists.txt) - git ls-tree --full-tree --name-only -r HEAD | grep -v "/third_party/" | grep "CMakeLists.txt\|\.cmake$" \ + git ls-tree --full-tree --name-only -r HEAD | grep -v "/third_party/" | grep "^CMakeLists.txt$\|\.cmake$" \ | xargs cmakelint --linelength=120 --spaces=4 diff --git a/tools/gen_esp_err_to_name.py b/tools/gen_esp_err_to_name.py index 7281ed5511..f2c648745e 100755 --- a/tools/gen_esp_err_to_name.py +++ b/tools/gen_esp_err_to_name.py @@ -204,7 +204,7 @@ def max_string_width(): max = x return max -def generate_output(fin, fout): +def generate_c_output(fin, fout): """ Writes the output to fout based on th error dictionary err_dict and template file fin. @@ -264,31 +264,53 @@ def generate_output(fin, fout): else: fout.write(line) +def generate_rst_output(fout): + for k in sorted(err_dict.keys()): + v = err_dict[k][0] + fout.write(':c:macro:`{}` '.format(v.name)) + if k > 0: + fout.write('**(0x{:x})**'.format(k)) + else: + fout.write('({:d})'.format(k)) + if len(v.comment) > 0: + fout.write(': {}'.format(v.comment)) + fout.write('\n\n') + def main(): + if 'IDF_PATH' in os.environ: + idf_path = os.environ['IDF_PATH'] + else: + idf_path = os.path.realpath(os.path.join(os.path.dirname(os.path.abspath(__file__)), '..')) + parser = argparse.ArgumentParser(description='ESP32 esp_err_to_name lookup generator for esp_err_t') - parser.add_argument('input', help='Path to the esp_err_to_name.c.in template input.', default=os.environ['IDF_PATH'] + '/components/esp32/esp_err_to_name.c.in', nargs='?') - parser.add_argument('output', help='Path to the esp_err_to_name.c output.', default=os.environ['IDF_PATH'] + '/components/esp32/esp_err_to_name.c', nargs='?') + parser.add_argument('--c_input', help='Path to the esp_err_to_name.c.in template input.', default=idf_path + '/components/esp32/esp_err_to_name.c.in') + parser.add_argument('--c_output', help='Path to the esp_err_to_name.c output.', default=idf_path + '/components/esp32/esp_err_to_name.c') + parser.add_argument('--rst_output', help='Generate .rst output and save it into this file') args = parser.parse_args() - for root, dirnames, filenames in os.walk(os.environ['IDF_PATH']): + for root, dirnames, filenames in os.walk(idf_path): for filename in fnmatch.filter(filenames, '*.[ch]'): full_path = os.path.join(root, filename) - idf_path = os.path.relpath(full_path, os.environ['IDF_PATH']) - if idf_path in ignore_files: + path_in_idf = os.path.relpath(full_path, idf_path) + if path_in_idf in ignore_files: continue with open(full_path, "r+") as f: for line in f: # match also ESP_OK and ESP_FAIL because some of ESP_ERRs are referencing them if re.match(r"\s*#define\s+(ESP_ERR_|ESP_OK|ESP_FAIL)", line): try: - process(str.strip(line), idf_path) + process(str.strip(line), path_in_idf) except InputError as e: print (e) process_remaining_errors() - with open(args.input, 'r') as fin, open(args.output, 'w') as fout: - generate_output(fin, fout) + if args.rst_output is not None: + with open(args.rst_output, 'w') as fout: + generate_rst_output(fout) + else: + with open(args.c_input, 'r') as fin, open(args.c_output, 'w') as fout: + generate_c_output(fin, fout) if __name__ == "__main__": main() diff --git a/tools/idf_monitor.py b/tools/idf_monitor.py index 278626657f..4dabe21235 100755 --- a/tools/idf_monitor.py +++ b/tools/idf_monitor.py @@ -60,7 +60,7 @@ CTRL_Y = '\x19' CTRL_P = '\x10' CTRL_RBRACKET = '\x1d' # Ctrl+] -# ANSI terminal codes +# ANSI terminal codes (if changed, regular expressions in LineMatcher need to be udpated) ANSI_RED = '\033[1;31m' ANSI_YELLOW = '\033[0;33m' ANSI_NORMAL = '\033[0m' @@ -75,17 +75,20 @@ def yellow_print(message): def red_print(message): color_print(message, ANSI_RED) -__version__ = "1.0" +__version__ = "1.1" # Tags for tuples in queues TAG_KEY = 0 TAG_SERIAL = 1 +TAG_SERIAL_FLUSH = 2 # regex matches an potential PC value (0x4xxxxxxx) MATCH_PCADDR = re.compile(r'0x4[0-9a-f]{7}', re.IGNORECASE) DEFAULT_TOOLCHAIN_PREFIX = "xtensa-esp32-elf-" +DEFAULT_PRINT_FILTER = "" + class StoppableThread(object): """ Provide a Thread-like class which can be 'cancelled' via a subclass-provided @@ -166,7 +169,7 @@ class ConsoleReader(StoppableThread): # this is the way cancel() is implemented in pyserial 3.3 or newer, # older pyserial (3.1+) has cancellation implemented via 'select', # which does not work when console sends an escape sequence response - # + # # even older pyserial (<3.1) does not have this method # # on Windows there is a different (also hacky) fix, applied above. @@ -211,6 +214,57 @@ class SerialReader(StoppableThread): except: pass +class LineMatcher: + """ + Assembles a dictionary of filtering rules based on the --print_filter + argument of idf_monitor. Then later it is used to match lines and + determine whether they should be shown on screen or not. + """ + LEVEL_N = 0 + LEVEL_E = 1 + LEVEL_W = 2 + LEVEL_I = 3 + LEVEL_D = 4 + LEVEL_V = 5 + + level = {'N': LEVEL_N, 'E': LEVEL_E, 'W': LEVEL_W, 'I': LEVEL_I, 'D': LEVEL_D, + 'V': LEVEL_V, '*': LEVEL_V, '': LEVEL_V} + + def __init__(self, print_filter): + self._dict = dict() + self._re = re.compile(r'^(?:\033\[[01];?[0-9]+m?)?([EWIDV]) \([0-9]+\) ([^:]+): ') + items = print_filter.split() + if len(items) == 0: + self._dict["*"] = self.LEVEL_V # default is to print everything + for f in items: + s = f.split(r':') + if len(s) == 1: + # specifying no warning level defaults to verbose level + lev = self.LEVEL_V + elif len(s) == 2: + if len(s[0]) == 0: + raise ValueError('No tag specified in filter ' + f) + try: + lev = self.level[s[1].upper()] + except KeyError: + raise ValueError('Unknown warning level in filter ' + f) + else: + raise ValueError('Missing ":" in filter ' + f) + self._dict[s[0]] = lev + def match(self, line): + try: + m = self._re.search(line) + if m: + lev = self.level[m.group(1)] + if m.group(2) in self._dict: + return self._dict[m.group(2)] >= lev + return self._dict.get("*", self.LEVEL_N) >= lev + except (KeyError, IndexError): + # Regular line written with something else than ESP_LOG* + # or an empty line. + pass + # We need something more than "*.N" for printing. + return self._dict.get("*", self.LEVEL_N) > self.LEVEL_N class Monitor(object): """ @@ -221,7 +275,7 @@ class Monitor(object): Main difference is that all event processing happens in the main thread, not the worker threads. """ - def __init__(self, serial_instance, elf_file, make="make", toolchain_prefix=DEFAULT_TOOLCHAIN_PREFIX, eol="CRLF"): + def __init__(self, serial_instance, elf_file, print_filter, make="make", toolchain_prefix=DEFAULT_TOOLCHAIN_PREFIX, eol="CRLF"): super(Monitor, self).__init__() self.event_queue = queue.Queue() self.console = miniterm.Console() @@ -237,9 +291,9 @@ class Monitor(object): if c == unichr(0x7f): c = unichr(8) # map the BS key (which yields DEL) to backspace return c - - self.console.getkey = types.MethodType(getkey_patched, self.console) - + + self.console.getkey = types.MethodType(getkey_patched, self.console) + self.serial = serial_instance self.console_reader = ConsoleReader(self.console, self.event_queue) self.serial_reader = SerialReader(self.serial, self.event_queue) @@ -260,10 +314,17 @@ class Monitor(object): # internal state self._pressed_menu_key = False - self._read_line = b"" + self._last_line_part = b"" self._gdb_buffer = b"" + self._pc_address_buffer = b"" + self._line_matcher = LineMatcher(print_filter) + self._invoke_processing_last_line_timer = None + self._force_line_print = False self._output_enabled = True + def invoke_processing_last_line(self): + self.event_queue.put((TAG_SERIAL_FLUSH, b''), False) + def main_loop(self): self.console_reader.start() self.serial_reader.start() @@ -274,12 +335,26 @@ class Monitor(object): self.handle_key(data) elif event_tag == TAG_SERIAL: self.handle_serial_input(data) + if self._invoke_processing_last_line_timer is not None: + self._invoke_processing_last_line_timer.cancel() + self._invoke_processing_last_line_timer = threading.Timer(0.1, self.invoke_processing_last_line) + self._invoke_processing_last_line_timer.start() + # If no futher data is received in the next short period + # of time then the _invoke_processing_last_line_timer + # generates an event which will result in the finishing of + # the last line. This is fix for handling lines sent + # without EOL. + elif event_tag == TAG_SERIAL_FLUSH: + self.handle_serial_input(data, finalize_line=True) else: raise RuntimeError("Bad event data %r" % ((event_tag,data),)) finally: try: self.console_reader.stop() self.serial_reader.stop() + # Cancelling _invoke_processing_last_line_timer is not + # important here because receiving empty data doesn't matter. + self._invoke_processing_last_line_timer = None except: pass sys.stderr.write(ANSI_NORMAL + "\n") @@ -302,20 +377,49 @@ class Monitor(object): except UnicodeEncodeError: pass # this can happen if a non-ascii character was passed, ignoring - def handle_serial_input(self, data): - # this may need to be made more efficient, as it pushes out a byte - # at a time to the console - for b in data: - if self._output_enabled: - self.console.write_bytes(b) - if b == b'\n': # end of line - self.handle_serial_input_line(self._read_line.strip()) - self._read_line = b"" - else: - self._read_line += b - self.check_gdbstub_trigger(b) + def handle_serial_input(self, data, finalize_line=False): + sp = data.split(b'\n') + if self._last_line_part != b"": + # add unprocessed part from previous "data" to the first line + sp[0] = self._last_line_part + sp[0] + self._last_line_part = b"" + if sp[-1] != b"": + # last part is not a full line + self._last_line_part = sp.pop() + for line in sp: + if line != b"": + if self._output_enabled and (self._force_line_print or self._line_matcher.match(line)): + self.console.write_bytes(line + b'\n') + self.handle_possible_pc_address_in_line(line) + self.check_gdbstub_trigger(line) + self._force_line_print = False + # Now we have the last part (incomplete line) in _last_line_part. By + # default we don't touch it and just wait for the arrival of the rest + # of the line. But after some time when we didn't received it we need + # to make a decision. + if self._last_line_part != b"": + if self._force_line_print or (finalize_line and self._line_matcher.match(self._last_line_part)): + self._force_line_print = True; + if self._output_enabled: + self.console.write_bytes(self._last_line_part) + self.handle_possible_pc_address_in_line(self._last_line_part) + self.check_gdbstub_trigger(self._last_line_part) + # It is possible that the incomplete line cuts in half the PC + # address. A small buffer is kept and will be used the next time + # handle_possible_pc_address_in_line is invoked to avoid this problem. + # MATCH_PCADDR matches 10 character long addresses. Therefore, we + # keep the last 9 characters. + self._pc_address_buffer = self._last_line_part[-9:] + # GDB sequence can be cut in half also. GDB sequence is 7 + # characters long, therefore, we save the last 6 characters. + self._gdb_buffer = self._last_line_part[-6:] + self._last_line_part = b"" + # else: keeping _last_line_part and it will be processed the next time + # handle_serial_input is invoked - def handle_serial_input_line(self, line): + def handle_possible_pc_address_in_line(self, line): + line = self._pc_address_buffer + line + self._pc_address_buffer = b"" for m in re.finditer(MATCH_PCADDR, line): self.lookup_pc_address(m.group()) @@ -430,9 +534,10 @@ class Monitor(object): if not "?? ??:0" in translation: yellow_print(translation) - def check_gdbstub_trigger(self, c): - self._gdb_buffer = self._gdb_buffer[-6:] + c # keep the last 7 characters seen - m = re.match(b"\\$(T..)#(..)", self._gdb_buffer) # look for a gdb "reason" for a break + def check_gdbstub_trigger(self, line): + line = self._gdb_buffer + line + self._gdb_buffer = b"" + m = re.search(b"\\$(T..)#(..)", line) # look for a gdb "reason" for a break if m is not None: try: chsum = sum(ord(p) for p in m.group(1)) & 0xFF @@ -513,6 +618,11 @@ def main(): 'elf_file', help='ELF file of application', type=argparse.FileType('rb')) + parser.add_argument( + '--print_filter', + help="Filtering string", + default=DEFAULT_PRINT_FILTER) + args = parser.parse_args() if args.port.startswith("/dev/tty."): @@ -538,7 +648,7 @@ def main(): except KeyError: pass # not running a make jobserver - monitor = Monitor(serial_instance, args.elf_file.name, args.make, args.toolchain_prefix, args.eol) + monitor = Monitor(serial_instance, args.elf_file.name, args.print_filter, args.make, args.toolchain_prefix, args.eol) yellow_print('--- idf_monitor on {p.name} {p.baudrate} ---'.format( p=serial_instance)) @@ -547,6 +657,8 @@ def main(): key_description(monitor.menu_key), key_description(monitor.menu_key), key_description(CTRL_H))) + if args.print_filter != DEFAULT_PRINT_FILTER: + yellow_print('--- Print filter: {} ---'.format(args.print_filter)) monitor.main_loop() diff --git a/tools/tiny-test-fw/CIAssignUnitTest.py b/tools/tiny-test-fw/CIAssignUnitTest.py index 9885d4fd7d..a87df781f1 100644 --- a/tools/tiny-test-fw/CIAssignUnitTest.py +++ b/tools/tiny-test-fw/CIAssignUnitTest.py @@ -109,16 +109,22 @@ class UnitTestAssignTest(CIAssignTest.AssignTest): with open(test_case_path, "r") as f: raw_data = yaml.load(f) test_cases = raw_data["test cases"] + # filter keys are lower case. Do map lower case keys with original keys. + try: + key_mapping = {x.lower(): x for x in test_cases[0].keys()} + except IndexError: + key_mapping = dict() if case_filter: for key in case_filter: filtered_cases = [] for case in test_cases: try: + mapped_key = key_mapping[key] # bot converts string to lower case - if isinstance(case[key], str): - _value = case[key].lower() + if isinstance(case[mapped_key], str): + _value = case[mapped_key].lower() else: - _value = case[key] + _value = case[mapped_key] if _value in case_filter[key]: filtered_cases.append(case) except KeyError: diff --git a/tools/tiny-test-fw/DUT.py b/tools/tiny-test-fw/DUT.py index 882afa1f99..0193cb6c70 100644 --- a/tools/tiny-test-fw/DUT.py +++ b/tools/tiny-test-fw/DUT.py @@ -117,7 +117,7 @@ class _DataCache(_queue.Queue): break return ret - def get_data(self, timeout=0): + def get_data(self, timeout=0.0): """ get a copy of data from cache. @@ -154,6 +154,52 @@ class _DataCache(_queue.Queue): self.data_cache = self.data_cache[index:] +class _LogThread(threading.Thread, _queue.Queue): + """ + We found some SD card on Raspberry Pi could have very bad performance. + It could take seconds to save small amount of data. + If the DUT receives data and save it as log, then it stops receiving data until log is saved. + This could lead to expect timeout. + As an workaround to this issue, ``BaseDUT`` class will create a thread to save logs. + Then data will be passed to ``expect`` as soon as received. + """ + def __init__(self): + threading.Thread.__init__(self, name="LogThread") + _queue.Queue.__init__(self, maxsize=0) + self.setDaemon(True) + self.flush_lock = threading.Lock() + + def save_log(self, filename, data): + """ + :param filename: log file name + :param data: log data. Must be ``bytes``. + """ + self.put({"filename": filename, "data": data}) + + def flush_data(self): + with self.flush_lock: + data_cache = dict() + while True: + # move all data from queue to data cache + try: + log = self.get_nowait() + try: + data_cache[log["filename"]] += log["data"] + except KeyError: + data_cache[log["filename"]] = log["data"] + except _queue.Empty: + break + # flush data + for filename in data_cache: + with open(filename, "ab+") as f: + f.write(data_cache[filename]) + + def run(self): + while True: + time.sleep(1) + self.flush_data() + + class _RecvThread(threading.Thread): PERFORMANCE_PATTERN = re.compile(r"\[Performance]\[(\w+)]: ([^\r\n]+)\r?\n") @@ -214,6 +260,10 @@ class BaseDUT(object): """ DEFAULT_EXPECT_TIMEOUT = 5 + MAX_EXPECT_FAILURES_TO_SAVED = 10 + + LOG_THREAD = _LogThread() + LOG_THREAD.start() def __init__(self, name, port, log_file, app, **kwargs): @@ -224,12 +274,33 @@ class BaseDUT(object): self.app = app self.data_cache = _DataCache() self.receive_thread = None + self.expect_failures = [] # open and start during init self.open() def __str__(self): return "DUT({}: {})".format(self.name, str(self.port)) + def _save_expect_failure(self, pattern, data, start_time): + """ + Save expect failure. If the test fails, then it will print the expect failures. + In some cases, user will handle expect exceptions. + The expect failures could be false alarm, and test case might generate a lot of such failures. + Therefore, we don't print the failure immediately and limit the max size of failure list. + """ + self.expect_failures.insert(0, {"pattern": pattern, "data": data, + "start": start_time, "end": time.time()}) + self.expect_failures = self.expect_failures[:self.MAX_EXPECT_FAILURES_TO_SAVED] + + def _save_dut_log(self, data): + """ + Save DUT log into file using another thread. + This is a workaround for some devices takes long time for file system operations. + + See descriptions in ``_LogThread`` for details. + """ + self.LOG_THREAD.save_log(self.log_file, data) + # define for methods need to be overwritten by Port @classmethod def list_available_ports(cls): @@ -329,6 +400,7 @@ class BaseDUT(object): if self.receive_thread: self.receive_thread.exit() self._port_close() + self.LOG_THREAD.flush_data() def write(self, data, eol="\r\n", flush=True): """ @@ -437,14 +509,19 @@ class BaseDUT(object): start_time = time.time() while True: ret, index = method(data, pattern) - if ret is not None or time.time() - start_time > timeout: + if ret is not None: self.data_cache.flush(index) break + time_remaining = start_time + timeout - time.time() + if time_remaining < 0: + break # wait for new data from cache - data = self.data_cache.get_data(time.time() + timeout - start_time) + data = self.data_cache.get_data(time_remaining) if ret is None: - raise ExpectTimeout(self.name + ": " + _pattern_to_string(pattern)) + pattern = _pattern_to_string(pattern) + self._save_expect_failure(pattern, data, start_time) + raise ExpectTimeout(self.name + ": " + pattern) return ret def _expect_multi(self, expect_all, expect_item_list, timeout): @@ -492,10 +569,11 @@ class BaseDUT(object): else: match_succeed = True if matched_expect_items else False - if time.time() - start_time > timeout or match_succeed: + time_remaining = start_time + timeout - time.time() + if time_remaining < 0 or match_succeed: break else: - data = self.data_cache.get_data(time.time() + timeout - start_time) + data = self.data_cache.get_data(time_remaining) if match_succeed: # do callback and flush matched data cache @@ -508,7 +586,9 @@ class BaseDUT(object): # flush already matched data self.data_cache.flush(slice_index) else: - raise ExpectTimeout(self.name + ": " + str([_pattern_to_string(x) for x in expect_items])) + pattern = str([_pattern_to_string(x["pattern"]) for x in expect_items]) + self._save_expect_failure(pattern, data, start_time) + raise ExpectTimeout(self.name + ": " + pattern) @_expect_lock def expect_any(self, *expect_items, **timeout): @@ -554,6 +634,22 @@ class BaseDUT(object): timeout["timeout"] = self.DEFAULT_EXPECT_TIMEOUT return self._expect_multi(True, expect_items, **timeout) + @staticmethod + def _format_ts(ts): + return "{}:{}".format(time.strftime("%m-%d %H:%M:%S", time.localtime(ts)), str(ts % 1)[2:5]) + + def print_debug_info(self): + """ + Print debug info of current DUT. Currently we will print debug info for expect failures. + """ + Utility.console_log("DUT debug info for DUT: {}:".format(self.name), color="orange") + + for failure in self.expect_failures: + Utility.console_log(u"\t[pattern]: {}\r\n\t[data]: {}\r\n\t[time]: {} - {}\r\n" + .format(failure["pattern"], failure["data"], + self._format_ts(failure["start"]), self._format_ts(failure["end"])), + color="orange") + class SerialDUT(BaseDUT): """ serial with logging received data feature """ @@ -574,17 +670,14 @@ class SerialDUT(BaseDUT): self.serial_configs.update(kwargs) super(SerialDUT, self).__init__(name, port, log_file, app, **kwargs) - @staticmethod - def _format_data(data): + def _format_data(self, data): """ format data for logging. do decode and add timestamp. :param data: raw data from read :return: formatted data (str) """ - timestamp = time.time() - timestamp = "[{}:{}]".format(time.strftime("%m-%d %H:%M:%S", time.localtime(timestamp)), - str(timestamp % 1)[2:5]) + timestamp = "[{}]".format(self._format_ts(time.time())) formatted_data = timestamp.encode() + b"\r\n" + data + b"\r\n" return formatted_data @@ -597,8 +690,7 @@ class SerialDUT(BaseDUT): def _port_read(self, size=1): data = self.port_inst.read(size) if data: - with open(self.log_file, "ab+") as _log_file: - _log_file.write(self._format_data(data)) + self._save_dut_log(self._format_data(data)) return data def _port_write(self, data): diff --git a/tools/tiny-test-fw/Env.py b/tools/tiny-test-fw/Env.py index b623847edb..b18df22737 100644 --- a/tools/tiny-test-fw/Env.py +++ b/tools/tiny-test-fw/Env.py @@ -162,14 +162,17 @@ class Env(object): return if_addr[self.PROTO_MAP[proto]][0] @_synced - def close(self): + def close(self, dut_debug=False): """ close() close all DUTs of the Env. + :param dut_debug: if dut_debug is True, then print all dut expect failures before close it :return: None """ for dut_name in self.allocated_duts: dut = self.allocated_duts[dut_name]["dut"] + if dut_debug: + dut.print_debug_info() dut.close() self.allocated_duts = dict() diff --git a/tools/tiny-test-fw/IDF/IDFDUT.py b/tools/tiny-test-fw/IDF/IDFDUT.py index 4c722e06ea..984eca5446 100644 --- a/tools/tiny-test-fw/IDF/IDFDUT.py +++ b/tools/tiny-test-fw/IDF/IDFDUT.py @@ -17,6 +17,10 @@ import os import re import subprocess import functools +import random +import tempfile + +from serial.tools import list_ports import DUT @@ -40,6 +44,8 @@ class IDFDUT(DUT.SerialDUT): """ IDF DUT, extends serial with ESPTool methods """ CHIP_TYPE_PATTERN = re.compile(r"Detecting chip type[.:\s]+(.+)") + # if need to erase NVS partition in start app + ERASE_NVS = True def __init__(self, name, port, log_file, app, **kwargs): self.download_config, self.partition_table = app.process_app_info() @@ -68,24 +74,39 @@ class IDFDUT(DUT.SerialDUT): return cls.get_chip(app, port) is not None @_tool_method - def start_app(self): + def start_app(self, erase_nvs=ERASE_NVS): """ download and start app. + :param: erase_nvs: whether erase NVS partition during flash :return: None """ + if erase_nvs: + address = self.partition_table["nvs"]["offset"] + size = self.partition_table["nvs"]["size"] + nvs_file = tempfile.NamedTemporaryFile() + nvs_file.write(chr(0xFF) * size) + nvs_file.flush() + download_config = self.download_config + [address, nvs_file.name] + else: + download_config = self.download_config + retry_baud_rates = ["921600", "115200"] error = IDFToolError() - for baud_rate in retry_baud_rates: - try: - subprocess.check_output(["python", self.app.esptool, - "--port", self.port, "--baud", baud_rate] - + self.download_config) - break - except subprocess.CalledProcessError as error: - continue - else: - raise error + try: + for baud_rate in retry_baud_rates: + try: + subprocess.check_output(["python", self.app.esptool, + "--port", self.port, "--baud", baud_rate] + + download_config) + break + except subprocess.CalledProcessError as error: + continue + else: + raise error + finally: + if erase_nvs: + nvs_file.close() @_tool_method def reset(self): @@ -96,6 +117,17 @@ class IDFDUT(DUT.SerialDUT): """ subprocess.check_output(["python", self.app.esptool, "--port", self.port, "run"]) + @_tool_method + def erase_partition(self, partition): + """ + :param partition: partition name to erase + :return: None + """ + address = self.partition_table[partition]["offset"] + size = self.partition_table[partition]["size"] + with open(".erase_partition.tmp", "wb") as f: + f.write(chr(0xFF) * size) + @_tool_method def dump_flush(self, output_file, **kwargs): """ diff --git a/tools/tiny-test-fw/IDF/__init__.py b/tools/tiny-test-fw/IDF/__init__.py index 5e1a4d6fc9..c7480c43f6 100644 --- a/tools/tiny-test-fw/IDF/__init__.py +++ b/tools/tiny-test-fw/IDF/__init__.py @@ -20,9 +20,8 @@ from IDF.IDFApp import IDFApp, Example, UT from IDF.IDFDUT import IDFDUT -def idf_example_test(app=Example, dut=IDFDUT, chip="ESP32", - module="examples", execution_time=1, - **kwargs): +def idf_example_test(app=Example, dut=IDFDUT, chip="ESP32", module="examples", execution_time=1, + level="example", erase_nvs=True, **kwargs): """ decorator for testing idf examples (with default values for some keyword args). @@ -31,12 +30,44 @@ def idf_example_test(app=Example, dut=IDFDUT, chip="ESP32", :param chip: chip supported, string or tuple :param module: module, string :param execution_time: execution time in minutes, int + :param level: test level, could be used to filter test cases, string + :param erase_nvs: if need to erase_nvs in DUT.start_app() :param kwargs: other keyword args :return: test method """ - # not use partial function as define as function support auto generating document + try: + # try to config the default behavior of erase nvs + dut.ERASE_NVS = erase_nvs + except AttributeError: + pass + return TinyFW.test_method(app=app, dut=dut, chip=chip, module=module, - execution_time=execution_time, **kwargs) + execution_time=execution_time, level=level, **kwargs) + + +def idf_unit_test(app=UT, dut=IDFDUT, chip="ESP32", module="unit-test", execution_time=1, + level="unit", erase_nvs=True, **kwargs): + """ + decorator for testing idf unit tests (with default values for some keyword args). + + :param app: test application class + :param dut: dut class + :param chip: chip supported, string or tuple + :param module: module, string + :param execution_time: execution time in minutes, int + :param level: test level, could be used to filter test cases, string + :param erase_nvs: if need to erase_nvs in DUT.start_app() + :param kwargs: other keyword args + :return: test method + """ + try: + # try to config the default behavior of erase nvs + dut.ERASE_NVS = erase_nvs + except AttributeError: + pass + + return TinyFW.test_method(app=app, dut=dut, chip=chip, module=module, + execution_time=execution_time, level=level, **kwargs) def log_performance(item, value): diff --git a/tools/tiny-test-fw/TinyFW.py b/tools/tiny-test-fw/TinyFW.py index 34463b2857..c475f3824d 100644 --- a/tools/tiny-test-fw/TinyFW.py +++ b/tools/tiny-test-fw/TinyFW.py @@ -107,6 +107,7 @@ MANDATORY_INFO = { "execution_time": 1, "env_tag": "default", "category": "function", + "ignore": False, } @@ -130,7 +131,7 @@ def test_method(**kwargs): test_func_file_name = frame[1][1] case_info = MANDATORY_INFO.copy() - case_info["name"] = test_func.__name__ + case_info["name"] = case_info["ID"] = test_func.__name__ case_info.update(kwargs) @functools.wraps(test_func) @@ -154,6 +155,7 @@ def test_method(**kwargs): xunit_file = os.path.join(env_inst.app_cls.get_log_folder(env_config["test_suite_name"]), XUNIT_FILE_NAME) XUNIT_RECEIVER.begin_case(test_func.__name__, time.time(), test_func_file_name) + result = False try: Utility.console_log("starting running test: " + test_func.__name__, color="green") # execute test function @@ -163,12 +165,11 @@ def test_method(**kwargs): except Exception as e: # handle all the exceptions here traceback.print_exc() - result = False # log failure XUNIT_RECEIVER.failure(str(e), test_func_file_name) finally: - # do close all DUTs - env_inst.close() + # do close all DUTs, if result is False then print DUT debug info + env_inst.close(dut_debug=(not result)) # end case and output result XUNIT_RECEIVER.end_case(test_func.__name__, time.time()) with open(xunit_file, "ab+") as f: diff --git a/tools/tiny-test-fw/Utility/CIAssignTest.py b/tools/tiny-test-fw/Utility/CIAssignTest.py index d4c5b723db..2df66fe81d 100644 --- a/tools/tiny-test-fw/Utility/CIAssignTest.py +++ b/tools/tiny-test-fw/Utility/CIAssignTest.py @@ -125,6 +125,7 @@ class AssignTest(object): # by default we only run function in CI, as other tests could take long time DEFAULT_FILTER = { "category": "function", + "ignore": False, } def __init__(self, test_case_path, ci_config_file, case_group=Group): @@ -188,6 +189,16 @@ class AssignTest(object): bot_filter = dict() return bot_filter + def _apply_bot_test_count(self): + """ + Bot could also pass test count. + If filtered cases need to be tested for several times, then we do duplicate them here. + """ + test_count = os.getenv("BOT_TEST_COUNT") + if test_count: + test_count = int(test_count) + self.test_cases *= test_count + def assign_cases(self): """ separate test cases to groups and assign test cases to CI jobs. @@ -198,6 +209,7 @@ class AssignTest(object): failed_to_assign = [] case_filter = self._apply_bot_filter() self.test_cases = self._search_cases(self.test_case_path, case_filter) + self._apply_bot_test_count() test_groups = self._group_cases() for group in test_groups: for job in self.jobs: @@ -207,7 +219,7 @@ class AssignTest(object): else: failed_to_assign.append(group) if failed_to_assign: - console_log("Please add the following jobs to .gitlab-ci.yml with specific tags:", "R") + console_log("Too many test cases vs jobs to run. Please add the following jobs to .gitlab-ci.yml with specific tags:", "R") for group in failed_to_assign: console_log("* Add job with: " + ",".join(group.ci_job_match_keys), "R") raise RuntimeError("Failed to assign test case to CI jobs") diff --git a/tools/tiny-test-fw/Utility/CaseConfig.py b/tools/tiny-test-fw/Utility/CaseConfig.py index af013ec282..3260c9b6ee 100644 --- a/tools/tiny-test-fw/Utility/CaseConfig.py +++ b/tools/tiny-test-fw/Utility/CaseConfig.py @@ -68,11 +68,15 @@ def _convert_to_lower_case(item): def _filter_one_case(test_method, case_filter): """ Apply filter for one case (the filter logic is the same as described in ``filter_test_cases``) """ filter_result = True - for key in case_filter: + # filter keys are lower case. Do map lower case keys with original keys. + key_mapping = {x.lower(): x for x in test_method.case_info.keys()} + + for orig_key in case_filter: + key = key_mapping[orig_key] if key in test_method.case_info: # the filter key is both in case and filter # we need to check if they match - filter_item = _convert_to_lower_case(case_filter[key]) + filter_item = _convert_to_lower_case(case_filter[orig_key]) accepted_item = _convert_to_lower_case(test_method.case_info[key]) if isinstance(filter_item, (tuple, list)) \ diff --git a/tools/unit-test-app/Makefile b/tools/unit-test-app/Makefile index 05f1dc3532..222cfb1361 100644 --- a/tools/unit-test-app/Makefile +++ b/tools/unit-test-app/Makefile @@ -5,9 +5,11 @@ PROJECT_NAME := unit-test-app -NON_INTERACTIVE_TARGET += ut-apply-config-% ut-clean-% +ifeq ($(MAKELEVEL),0) +# Set default target +all: -include $(IDF_PATH)/make/project.mk +# Define helper targets only when not recursing # List of unit-test-app configurations. # Each file in configs/ directory defines a configuration. The format is the @@ -21,8 +23,9 @@ CONFIG_CLEAN_TARGETS := $(addprefix ut-clean-,$(CONFIG_NAMES)) CONFIG_APPLY_TARGETS := $(addprefix ut-apply-config-,$(CONFIG_NAMES)) # Build (intermediate) and output (artifact) directories -BUILDS_DIR := $(PROJECT_PATH)/builds -BINARIES_DIR := $(PROJECT_PATH)/output +PROJECT_DIR := $(abspath $(dir $(firstword $(MAKEFILE_LIST)))) +BUILDS_DIR := $(PROJECT_DIR)/builds +BINARIES_DIR := $(PROJECT_DIR)/output # This generates per-config targets (clean, build, apply-config). define GenerateConfigTargets @@ -56,18 +59,28 @@ $(BINARIES_DIR)/%/$(PROJECT_NAME).bin: configs/% mkdir -p $(BINARIES_DIR)/$*/bootloader mkdir -p $(BUILDS_DIR)/$* # Prepare configuration: top-level sdkconfig.defaults file plus the current configuration (configs/$*) - $(summary) CONFIG $(BUILDS_DIR)/$*/sdkconfig + echo CONFIG $(BUILDS_DIR)/$*/sdkconfig rm -f $(BUILDS_DIR)/$*/sdkconfig cat sdkconfig.defaults > $(BUILDS_DIR)/$*/sdkconfig.defaults echo "" >> $(BUILDS_DIR)/$*/sdkconfig.defaults # in case there is no trailing newline in sdkconfig.defaults cat configs/$* >> $(BUILDS_DIR)/$*/sdkconfig.defaults + # Build, tweaking paths to sdkconfig and sdkconfig.defaults - $(summary) BUILD_CONFIG $(BUILDS_DIR)/$* - $(MAKE) defconfig all \ + echo BUILD_CONFIG $(BUILDS_DIR)/$* + # 'TEST_COMPONENTS=names' option can be added to configs/$* to limit the set + # of tests to build for given configuration. + # Build all tests if this option is not present. + test_components=`sed -n 's/^TEST_COMPONENTS=\(.*\)/\1/p' configs/$*`; \ + tests_all=`test -n "$${test_components}"; echo $${?}`; \ + exclude_components=`sed -n 's/^EXCLUDE_COMPONENTS=\(.*\)/\1/p' configs/$*`; \ + $(MAKE) defconfig list-components all \ BUILD_DIR_BASE=$(BUILDS_DIR)/$* \ SDKCONFIG=$(BUILDS_DIR)/$*/sdkconfig \ - SDKCONFIG_DEFAULTS=$(BUILDS_DIR)/$*/sdkconfig.defaults - $(MAKE) print_flash_cmd \ + SDKCONFIG_DEFAULTS=$(BUILDS_DIR)/$*/sdkconfig.defaults \ + TEST_COMPONENTS="$${test_components}" \ + TESTS_ALL=$${tests_all} \ + EXCLUDE_COMPONENTS="$${exclude_components}" + $(MAKE) --silent print_flash_cmd \ BUILD_DIR_BASE=$(BUILDS_DIR)/$* \ SDKCONFIG=$(BUILDS_DIR)/$*/sdkconfig \ | sed -e 's:'$(BUILDS_DIR)/$*/'::g' \ @@ -87,17 +100,44 @@ ut-help: @echo "make ut-build-NAME - Build unit-test-app with configuration provided in configs/NAME." @echo " Build directory will be builds/NAME/, output binaries will be" @echo " under output/NAME/" - @echo "make ut-clean-NAME - Remove build and output directories for configuration NAME." @echo "" @echo "make ut-build-all-configs - Build all configurations defined in configs/ directory." @echo "" + @echo "Above targets determine list of components to be built from configs/NAME files." + @echo "To build custom subset of components use 'make ut-apply-config-NAME' and then 'make all'." + @echo "" @echo "make ut-apply-config-NAME - Generates configuration based on configs/NAME in sdkconfig" @echo " file. After this, normal all/flash targets can be used." @echo " Useful for development/debugging." @echo "" + @echo "make ut-clean-NAME - Remove build and output directories for configuration NAME." + @echo "" help: ut-help -.PHONY: ut-build-all-configs ut-clean-all-configs \ - $(CONFIG_BUILD_TARGETS) $(CONFIG_CLEAN_TARGETS) $(CONFIG_APPLY_TARGETS) \ +LOCAL_TARGETS := ut-build-all-configs ut-clean-all-configs \ + $(CONFIG_BUILD_TARGETS) $(CONFIG_CLEAN_TARGETS) \ ut-help + +.PHONY: $(LOCAL_TARGETS) + +NON_INTERACTIVE_TARGET += ut-apply-config-% ut-clean-% ut-build-% \ + ut-build-all-configs ut-clean-all-configs + +endif # MAKELEVEL == 0 + + +# When targets defined in this makefile are built, don't need to include the main project makefile. +# This prevents some variables which depend on build directory from being set erroneously. +ifeq ($(filter $(LOCAL_TARGETS),$(MAKECMDGOALS)),) + +include $(IDF_PATH)/make/project.mk + +endif + +# If recursing, print the actual list of tests being built +ifneq ($(MAKELEVEL),0) + +$(info TESTS $(foreach comp,$(TEST_COMPONENT_NAMES),$(patsubst %_test,%,$(comp)))) + +endif # MAKELEVEL != 0 diff --git a/tools/unit-test-app/README.md b/tools/unit-test-app/README.md index e9fc7403c1..7c06ad7a69 100644 --- a/tools/unit-test-app/README.md +++ b/tools/unit-test-app/README.md @@ -7,7 +7,7 @@ ESP-IDF unit tests are run using Unit Test App. The app can be built with the un * Follow the setup instructions in the top-level esp-idf README. * Set IDF_PATH environment variable to point to the path to the esp-idf top-level directory. * Change into `tools/unit-test-app` directory -* `idf.py menuconfig` to configure the Unit Test App. +* `make menuconfig` to configure the Unit Test App. * `make TEST_COMPONENTS=` with `TEST_COMPONENTS` set to names of the components to be included in the test app. Or `make TESTS_ALL=1` to build the test app with all the tests for components having `test` subdirectory. * Follow the printed instructions to flash, or run `make flash`. * Unit test have a few preset sdkconfigs. It provides command `make ut-clean-config_name` and `make ut-build-config_name` (where `config_name` is the file name under `unit-test-app/configs` folder) to build with preset configs. For example, you can use `make ut-build-default TESTS_ALL=1` to build with config file `unit-test-app/configs/default`. Built binary for this config will be copied to `unit-test-app/output/config_name` folder. @@ -68,7 +68,7 @@ Unit test jobs will do reset before running each case (because some cases do not Gitlab CI do not support create jobs at runtime. We must maunally add all jobs to CI config file. To make test running in parallel, we limit the number of cases running on each job. When add new unit test cases, it could exceed the limitation that current unit test jobs support. In this case, assign test job will raise error, remind you to add jobs to `.gitlab-ci.yml`. ``` -Please add the following jobs to .gitlab-ci.yml with specific tags: +Too many test cases vs jobs to run. Please add the following jobs to .gitlab-ci.yml with specific tags: * Add job with: UT_T1_1, ESP32_IDF, psram * Add job with: UT_T1_1, ESP32_IDF ``` @@ -103,7 +103,7 @@ If you want to reproduce locally, you need to: 2. Check the following print in CI job to get the config name: `Running unit test for config: config_name`. Then flash the binary of this config to your board. 3. Run the failed case on your board (refer to Running Unit Tests section). * There're some special UT cases (multiple stages case, multiple devices cases) which requires user interaction: - * You can refer to [unit test document](https://esp-idf.readthedocs.io/en/latest/api-guides/unit-tests.html#running-unit-tests) to run test manually. + * You can refer to [unit test document](https://docs.espressif.com/projects/esp-idf/en/latest/api-guides/unit-tests.html#running-unit-tests) to run test manually. * Or, you can use `tools/unit-test-app/unit_test.py` to run the test cases: * read document of tiny-test-fw, set correct `TEST_FW_PATH` and `IDF_PATH` * modify `unit_test.py`, pass the test cases need to test as parameter (refer to test function doc string for supported parameter format) to test functions. diff --git a/tools/unit-test-app/components/unity/Kconfig b/tools/unit-test-app/components/unity/Kconfig new file mode 100644 index 0000000000..642d76f9d5 --- /dev/null +++ b/tools/unit-test-app/components/unity/Kconfig @@ -0,0 +1,15 @@ +menu "Unity test framework" + +config UNITY_FREERTOS_PRIORITY + int "Priority of Unity test task" + default 5 + +config UNITY_FREERTOS_CPU + int "CPU to run Unity test task on" + default 0 + +config UNITY_FREERTOS_STACK_SIZE + int "Stack size of Unity test task, in bytes" + default 8192 + +endmenu diff --git a/tools/unit-test-app/components/unity/include/unity_config.h b/tools/unit-test-app/components/unity/include/unity_config.h index 875bd0fc8b..19f73b1cee 100644 --- a/tools/unit-test-app/components/unity/include/unity_config.h +++ b/tools/unit-test-app/components/unity/include/unity_config.h @@ -8,10 +8,12 @@ // Adapt Unity to our environment, disable FP support #include +#include /* Some definitions applicable to Unity running in FreeRTOS */ -#define UNITY_FREERTOS_PRIORITY 5 -#define UNITY_FREERTOS_CPU 0 +#define UNITY_FREERTOS_PRIORITY CONFIG_UNITY_FREERTOS_PRIORITY +#define UNITY_FREERTOS_CPU CONFIG_UNITY_FREERTOS_CPU +#define UNITY_FREERTOS_STACK_SIZE CONFIG_UNITY_FREERTOS_STACK_SIZE #define UNITY_EXCLUDE_FLOAT #define UNITY_EXCLUDE_DOUBLE @@ -49,7 +51,7 @@ #define UNITY_TEST_FN_SET(...) \ static test_func UNITY_TEST_UID(test_functions)[] = {__VA_ARGS__}; \ - static char* UNITY_TEST_UID(test_fn_name)[] = FN_NAME_SET(PP_NARG(__VA_ARGS__), __VA_ARGS__) + static const char* UNITY_TEST_UID(test_fn_name)[] = FN_NAME_SET(PP_NARG(__VA_ARGS__), __VA_ARGS__) typedef void (* test_func)(void); @@ -62,7 +64,7 @@ struct test_desc_t const char* file; int line; uint8_t test_fn_count; - char ** test_fn_name; + const char ** test_fn_name; struct test_desc_t* next; }; diff --git a/tools/unit-test-app/configs/bt b/tools/unit-test-app/configs/bt new file mode 100644 index 0000000000..cc83ba16df --- /dev/null +++ b/tools/unit-test-app/configs/bt @@ -0,0 +1,3 @@ +TEST_COMPONENTS=bt +CONFIG_BT_ENABLED=y +CONFIG_UNITY_FREERTOS_STACK_SIZE=12288 diff --git a/tools/unit-test-app/configs/default b/tools/unit-test-app/configs/default index bc5fdcd23e..b83aec589e 100644 --- a/tools/unit-test-app/configs/default +++ b/tools/unit-test-app/configs/default @@ -1 +1 @@ -# default config — nothing to set here +EXCLUDE_COMPONENTS=libsodium bt diff --git a/tools/unit-test-app/configs/libsodium b/tools/unit-test-app/configs/libsodium new file mode 100644 index 0000000000..7828480c97 --- /dev/null +++ b/tools/unit-test-app/configs/libsodium @@ -0,0 +1,3 @@ +TEST_COMPONENTS=libsodium +EXCLUDE_COMPONENTS=bt +CONFIG_UNITY_FREERTOS_STACK_SIZE=12288 diff --git a/tools/unit-test-app/configs/psram b/tools/unit-test-app/configs/psram index 9af51eb10c..dc74b5a2d5 100644 --- a/tools/unit-test-app/configs/psram +++ b/tools/unit-test-app/configs/psram @@ -1 +1,2 @@ +EXCLUDE_COMPONENTS=libsodium bt CONFIG_SPIRAM_SUPPORT=y diff --git a/tools/unit-test-app/configs/release b/tools/unit-test-app/configs/release index 6e178910f7..370039d160 100644 --- a/tools/unit-test-app/configs/release +++ b/tools/unit-test-app/configs/release @@ -1,2 +1,3 @@ +EXCLUDE_COMPONENTS=bt CONFIG_OPTIMIZATION_LEVEL_RELEASE=y CONFIG_OPTIMIZATION_ASSERTIONS_SILENT=y diff --git a/tools/unit-test-app/configs/single_core b/tools/unit-test-app/configs/single_core index d9a4763e10..29d0350f5f 100644 --- a/tools/unit-test-app/configs/single_core +++ b/tools/unit-test-app/configs/single_core @@ -1,2 +1,3 @@ +EXCLUDE_COMPONENTS=libsodium bt CONFIG_MEMMAP_SMP=n CONFIG_FREERTOS_UNICORE=y diff --git a/tools/unit-test-app/main/app_main.c b/tools/unit-test-app/main/app_main.c index f1c18fcbfb..1dbcdd3b0c 100644 --- a/tools/unit-test-app/main/app_main.c +++ b/tools/unit-test-app/main/app_main.c @@ -19,6 +19,6 @@ void app_main() // Note: if unpinning this task, change the way run times are calculated in // unity_platform - xTaskCreatePinnedToCore(unityTask, "unityTask", 8192, NULL, + xTaskCreatePinnedToCore(unityTask, "unityTask", UNITY_FREERTOS_STACK_SIZE, NULL, UNITY_FREERTOS_PRIORITY, NULL, UNITY_FREERTOS_CPU); } diff --git a/tools/unit-test-app/sdkconfig.defaults b/tools/unit-test-app/sdkconfig.defaults index a9b24b60e9..db4404ed4e 100644 --- a/tools/unit-test-app/sdkconfig.defaults +++ b/tools/unit-test-app/sdkconfig.defaults @@ -27,3 +27,4 @@ CONFIG_SUPPORT_STATIC_ALLOCATION=y CONFIG_ESP_TIMER_PROFILING=y CONFIG_ADC2_DISABLE_DAC=n CONFIG_WARN_WRITE_STRINGS=y +CONFIG_SPI_MASTER_IN_IRAM=y \ No newline at end of file diff --git a/tools/unit-test-app/tools/UnitTestParser.py b/tools/unit-test-app/tools/UnitTestParser.py index 1898bf6598..aa488bc550 100644 --- a/tools/unit-test-app/tools/UnitTestParser.py +++ b/tools/unit-test-app/tools/UnitTestParser.py @@ -179,28 +179,11 @@ class Parser(object): """ prop = self.parse_case_properities(description) - idf_path = os.getenv("IDF_PATH") - - # use relative file path to IDF_PATH, to make sure file path is consist - relative_file_path = os.path.relpath(file_name, idf_path) - - file_name_hash = int(hashlib.sha256(relative_file_path).hexdigest(), base=16) % 1000 - - if file_name_hash in self.file_name_cache: - self.file_name_cache[file_name_hash] += 1 - else: - self.file_name_cache[file_name_hash] = 1 - - tc_id = "UT_%s_%s_%03d%02d" % (self.module_map[prop["module"]]['module abbr'], - self.module_map[prop["module"]]['sub module abbr'], - file_name_hash, - self.file_name_cache[file_name_hash]) - test_case = deepcopy(TEST_CASE_PATTERN) test_case.update({"config": config_name, "module": self.module_map[prop["module"]]['module'], "CI ready": "No" if prop["ignore"] == "Yes" else "Yes", - "ID": tc_id, + "ID": name, "test point 2": prop["module"], "steps": name, "test environment": prop["test_env"], diff --git a/tools/unit-test-app/unit_test.py b/tools/unit-test-app/unit_test.py index b7453722e5..bf913c2784 100644 --- a/tools/unit-test-app/unit_test.py +++ b/tools/unit-test-app/unit_test.py @@ -105,8 +105,7 @@ def format_test_case_config(test_case_data): return case_config -@TinyFW.test_method(app=UT, dut=IDF.IDFDUT, chip="ESP32", module="unit_test", - execution_time=1, env_tag="UT_T1_1") +@IDF.idf_unit_test(env_tag="UT_T1_1") def run_unit_test_cases(env, extra_data): """ extra_data can be three types of value @@ -339,8 +338,7 @@ def case_run(duts, ut_config, env, one_case, failed_cases): Utility.console_log("Failed: " + one_case["name"], color="red") -@TinyFW.test_method(app=UT, dut=IDF.IDFDUT, chip="ESP32", module="master_slave_test_case", execution_time=1, - env_tag="UT_T2_1") +@IDF.idf_unit_test(env_tag="UT_T2_1") def run_multiple_devices_cases(env, extra_data): """ extra_data can be two types of value @@ -377,8 +375,7 @@ def run_multiple_devices_cases(env, extra_data): raise AssertionError("Unit Test Failed") -@TinyFW.test_method(app=UT, dut=IDF.IDFDUT, chip="ESP32", module="unit_test", - execution_time=1, env_tag="UT_T1_1") +@IDF.idf_unit_test(env_tag="UT_T1_1") def run_multiple_stage_cases(env, extra_data): """ extra_data can be 2 types of value diff --git a/tools/windows/windows_install_prerequisites.sh b/tools/windows/windows_install_prerequisites.sh index 66ee2236df..0960f4a176 100644 --- a/tools/windows/windows_install_prerequisites.sh +++ b/tools/windows/windows_install_prerequisites.sh @@ -5,7 +5,7 @@ # Use of this script is optional, there is also a prebuilt MSYS2 environment available # which can be downloaded and used as-is. # -# See http://esp-idf.readthedocs.io/en/latest/windows-setup.html for full details. +# See https://docs.espressif.com/projects/esp-idf/en/latest/get-started/windows-setup.html for full details. if [ "$OSTYPE" != "msys" ]; then echo "This setup script expects to be run from an MSYS2 environment on Windows."