forked from espressif/esp-idf
Compare commits
180 Commits
fixes
...
v5.3-beta2
Author | SHA1 | Date | |
---|---|---|---|
ae876915ec | |||
e22c101034 | |||
63f019565b | |||
3f632df143 | |||
5ec2be4ba3 | |||
1d3d63c438 | |||
e7ba614a04 | |||
dbf757118a | |||
0c2c962b19 | |||
1f0d27a2c6 | |||
1aaae85ad2 | |||
85048f35e3 | |||
1a7c782905 | |||
cf4cf23741 | |||
236556d1ea | |||
07669b8012 | |||
e13bb3d734 | |||
bb4ba96545 | |||
1bf9c822f9 | |||
bb466097e5 | |||
8b369072f9 | |||
d91dfe3510 | |||
2396dc5ff7 | |||
5ec85c0bfd | |||
7c49b1da55 | |||
8805685f72 | |||
a3d77114b6 | |||
021dc8747c | |||
c7f146b671 | |||
86a49de1eb | |||
51b6d16b43 | |||
9e74564ba5 | |||
7b10c2421f | |||
64c062047f | |||
157c5b52e3 | |||
c97ab134ef | |||
5899701b68 | |||
4ec0065d74 | |||
fe92d9ee60 | |||
4c6cf06838 | |||
464f4c9cc6 | |||
eb8dad2fa6 | |||
856a299ba8 | |||
be9c7145f9 | |||
d638267741 | |||
f3a73cbce3 | |||
41ff5a2f43 | |||
95cfd3987b | |||
520beb865c | |||
e53ca8e018 | |||
68be49d2cf | |||
686878497e | |||
c046d87561 | |||
fdb4197d02 | |||
e11f030427 | |||
beebbada64 | |||
6da7a46bfa | |||
d2551d6e4b | |||
4cf29dfcef | |||
3dbba47d8c | |||
02c2356cb1 | |||
8639f69ed7 | |||
19ab395364 | |||
a7266400be | |||
1847e53909 | |||
285ba1fcf2 | |||
5c9392d177 | |||
6a92c1485a | |||
c91bdda9f3 | |||
f63e544dc3 | |||
0680af1269 | |||
2decfbc007 | |||
3640c1ecba | |||
cbb43bb4c4 | |||
0dc29caf4a | |||
5f07f64802 | |||
e4f1c01197 | |||
2ed780b686 | |||
a9383cb433 | |||
5e817df25f | |||
bd8d7ea76a | |||
352ee6fc26 | |||
8472467721 | |||
f324e75c64 | |||
1a1a708699 | |||
24e5e3aef1 | |||
d8bc05c5d0 | |||
bfa95cdd75 | |||
199dc389cc | |||
b400a8cd72 | |||
4dc565b7d0 | |||
cbcd346171 | |||
f1d1dfd1ef | |||
dd20d1f2b5 | |||
4e850f158e | |||
ea010f84ef | |||
68a9c09c49 | |||
53c4c08283 | |||
89a612aea0 | |||
a9dcc3964d | |||
8503709d85 | |||
4eacfd6ee1 | |||
9eb61ef5a7 | |||
7165a3bdbb | |||
1b331d24b3 | |||
fe4b401ab2 | |||
ebc9d02146 | |||
ec50cd7d7e | |||
0cf4889f22 | |||
b9f15ba3ab | |||
d22f9a97aa | |||
90188040fb | |||
ea1a10da17 | |||
7c54373146 | |||
209fbfc18b | |||
8545eeb4ef | |||
a22d0df155 | |||
c706096f45 | |||
b8ed93eec0 | |||
840ec6579f | |||
7aed3eb3bc | |||
fe628d5951 | |||
855d1eb170 | |||
8ed42582fe | |||
5428555092 | |||
8f091de9c2 | |||
ae0eabec53 | |||
6b0a815b78 | |||
a04f786380 | |||
a6d8251366 | |||
9fd92e8bf4 | |||
d42e894a74 | |||
bf415f580f | |||
55a8a18fb7 | |||
a61a367bc4 | |||
c19e762c89 | |||
6fea6aae8c | |||
027193ca07 | |||
8bd2287233 | |||
aa1c3af4c4 | |||
577a50b02a | |||
b11014a7c6 | |||
901f937698 | |||
39771b6c81 | |||
b026a7c915 | |||
f82fea4c1b | |||
60ab9631d7 | |||
91c4a94f61 | |||
df211933ff | |||
e486f3b944 | |||
ccca8b74eb | |||
7d7d9d7090 | |||
0ee7d4d17a | |||
a246aa2973 | |||
2508d3f23b | |||
b494330381 | |||
ddc357fcca | |||
6a5ab20489 | |||
30fce03e35 | |||
212f316f24 | |||
0fcc940bc1 | |||
b43fc4d63a | |||
7fb317655d | |||
49aaac0013 | |||
d910ca7fa8 | |||
935da554c9 | |||
5b3996885c | |||
7c57624b66 | |||
e56f92aab4 | |||
3386c594b4 | |||
0440d582dc | |||
4fb58d56b4 | |||
665883229e | |||
a85d1e1eca | |||
14315bb751 | |||
fa866b49ca | |||
ebe1141b25 | |||
cb5bc35f2e | |||
55658d4c36 | |||
f1b9b357e4 |
2
.gitignore
vendored
2
.gitignore
vendored
@ -96,6 +96,8 @@ dependencies.lock
|
||||
managed_components
|
||||
|
||||
# pytest log
|
||||
pytest-embedded/
|
||||
# legacy one
|
||||
pytest_embedded_log/
|
||||
list_job*.txt
|
||||
size_info*.txt
|
||||
|
@ -2,239 +2,5 @@
|
||||
#
|
||||
# https://docs.gitlab.com/ee/user/project/code_owners.html#the-syntax-of-code-owners-files
|
||||
#
|
||||
# If more than one rule matches a given file, the latest rule is used.
|
||||
# The file should be generally kept sorted, except when it is necessary
|
||||
# to use a different order due to the fact above. In that case, use
|
||||
# '# sort-order-reset' comment line to reset the sort order.
|
||||
#
|
||||
# Recipes for a few common cases:
|
||||
#
|
||||
# 1. Specific directory with all its contents:
|
||||
#
|
||||
# /components/app_trace/
|
||||
#
|
||||
# Note the trailing slash!
|
||||
#
|
||||
# 2. File with certain extension in any subdirectory of a certain directory:
|
||||
#
|
||||
# /examples/**/*.py
|
||||
#
|
||||
# This includes an *.py files in /examples/ directory as well.
|
||||
#
|
||||
# 3. Contents of a directory with a certain name, anywhere in the tree:
|
||||
#
|
||||
# test_*_host/
|
||||
#
|
||||
# Will match everything under components/efuse/test_efuse_host/,
|
||||
# components/heap/test_multi_heap_host/, components/lwip/test_afl_host/, etc.
|
||||
#
|
||||
# 4. Same as above, except limited to a specific place in the tree:
|
||||
#
|
||||
# /components/esp32*/
|
||||
#
|
||||
# Matches everything under /components/esp32, /components/esp32s2, etc.
|
||||
# Doesn't match /tools/some-test/components/esp32s5.
|
||||
#
|
||||
# 5. Specific file:
|
||||
#
|
||||
# /tools/tools.json
|
||||
#
|
||||
# 6. File with a certain name anywhere in the tree
|
||||
#
|
||||
# .gitignore
|
||||
#
|
||||
|
||||
* @esp-idf-codeowners/other
|
||||
|
||||
/.* @esp-idf-codeowners/tools
|
||||
/.codespellrc @esp-idf-codeowners/ci
|
||||
/.github/workflows/ @esp-idf-codeowners/ci
|
||||
/.gitlab-ci.yml @esp-idf-codeowners/ci
|
||||
/.gitlab/ci/ @esp-idf-codeowners/ci
|
||||
/.pre-commit-config.yaml @esp-idf-codeowners/ci
|
||||
/.readthedocs.yml @esp-idf-codeowners/docs
|
||||
/.vale.ini @esp-idf-codeowners/docs
|
||||
/CMakeLists.txt @esp-idf-codeowners/build-config
|
||||
/COMPATIBILITY*.md @esp-idf-codeowners/peripherals
|
||||
/CONTRIBUTING.md @esp-idf-codeowners/docs
|
||||
/Kconfig @esp-idf-codeowners/build-config
|
||||
/README*.md @esp-idf-codeowners/docs
|
||||
/SUPPORT_POLICY*.md @esp-idf-codeowners/docs
|
||||
/add_path.sh @esp-idf-codeowners/tools
|
||||
/conftest.py @esp-idf-codeowners/ci
|
||||
/export.* @esp-idf-codeowners/tools
|
||||
/install.* @esp-idf-codeowners/tools
|
||||
/pytest.ini @esp-idf-codeowners/ci
|
||||
/sdkconfig.rename @esp-idf-codeowners/build-config
|
||||
/sonar-project.properties @esp-idf-codeowners/ci
|
||||
|
||||
# sort-order-reset
|
||||
|
||||
/components/app_trace/ @esp-idf-codeowners/debugging
|
||||
/components/app_update/ @esp-idf-codeowners/system @esp-idf-codeowners/app-utilities
|
||||
/components/bootloader*/ @esp-idf-codeowners/system @esp-idf-codeowners/security
|
||||
/components/bootloader_support/bootloader_flash/ @esp-idf-codeowners/peripherals
|
||||
/components/bt/ @esp-idf-codeowners/bluetooth
|
||||
/components/cmock/ @esp-idf-codeowners/system
|
||||
/components/console/ @esp-idf-codeowners/system @esp-idf-codeowners/app-utilities/console
|
||||
/components/cxx/ @esp-idf-codeowners/system
|
||||
/components/driver/ @esp-idf-codeowners/peripherals
|
||||
/components/efuse/ @esp-idf-codeowners/system
|
||||
/components/esp_adc/ @esp-idf-codeowners/peripherals
|
||||
/components/esp_app_format/ @esp-idf-codeowners/system @esp-idf-codeowners/app-utilities
|
||||
/components/esp_bootloader_format/ @esp-idf-codeowners/system @esp-idf-codeowners/app-utilities
|
||||
/components/esp_coex/ @esp-idf-codeowners/wifi @esp-idf-codeowners/bluetooth @esp-idf-codeowners/ieee802154
|
||||
/components/esp_common/ @esp-idf-codeowners/system
|
||||
/components/esp_driver_*/ @esp-idf-codeowners/peripherals
|
||||
/components/esp_driver_sdmmc/ @esp-idf-codeowners/peripherals @esp-idf-codeowners/storage
|
||||
/components/esp_eth/ @esp-idf-codeowners/network
|
||||
/components/esp_event/ @esp-idf-codeowners/system
|
||||
/components/esp_gdbstub/ @esp-idf-codeowners/debugging
|
||||
/components/esp_hid/ @esp-idf-codeowners/bluetooth
|
||||
/components/esp_http_client/ @esp-idf-codeowners/app-utilities
|
||||
/components/esp_http_server/ @esp-idf-codeowners/app-utilities
|
||||
/components/esp_https_ota/ @esp-idf-codeowners/app-utilities
|
||||
/components/esp_https_server/ @esp-idf-codeowners/app-utilities
|
||||
/components/esp_hw_support/ @esp-idf-codeowners/system @esp-idf-codeowners/peripherals
|
||||
/components/esp_hw_support/lowpower/ @esp-idf-codeowners/power-management
|
||||
/components/esp_lcd/ @esp-idf-codeowners/peripherals
|
||||
/components/esp_local_ctrl/ @esp-idf-codeowners/app-utilities
|
||||
/components/esp_mm/ @esp-idf-codeowners/peripherals
|
||||
/components/esp_netif/ @esp-idf-codeowners/network
|
||||
/components/esp_netif_stack/ @esp-idf-codeowners/network
|
||||
/components/esp_partition/ @esp-idf-codeowners/storage
|
||||
/components/esp_phy/ @esp-idf-codeowners/bluetooth @esp-idf-codeowners/wifi @esp-idf-codeowners/ieee802154
|
||||
/components/esp_pm/ @esp-idf-codeowners/power-management @esp-idf-codeowners/bluetooth @esp-idf-codeowners/wifi @esp-idf-codeowners/system
|
||||
/components/esp_psram/ @esp-idf-codeowners/peripherals @esp-idf-codeowners/system
|
||||
/components/esp_ringbuf/ @esp-idf-codeowners/system
|
||||
/components/esp_rom/ @esp-idf-codeowners/system @esp-idf-codeowners/bluetooth @esp-idf-codeowners/wifi
|
||||
/components/esp_system/ @esp-idf-codeowners/system
|
||||
/components/esp_timer/ @esp-idf-codeowners/system
|
||||
/components/esp-tls/ @esp-idf-codeowners/app-utilities
|
||||
/components/esp_vfs_*/ @esp-idf-codeowners/storage
|
||||
/components/esp_vfs_console/ @esp-idf-codeowners/storage @esp-idf-codeowners/system
|
||||
/components/esp_wifi/ @esp-idf-codeowners/wifi
|
||||
/components/espcoredump/ @esp-idf-codeowners/debugging
|
||||
/components/esptool_py/ @esp-idf-codeowners/tools
|
||||
/components/fatfs/ @esp-idf-codeowners/storage
|
||||
/components/freertos/ @esp-idf-codeowners/system
|
||||
/components/hal/ @esp-idf-codeowners/peripherals
|
||||
/components/heap/ @esp-idf-codeowners/system
|
||||
/components/http_parser/ @esp-idf-codeowners/app-utilities
|
||||
/components/idf_test/ @esp-idf-codeowners/ci
|
||||
/components/ieee802154/ @esp-idf-codeowners/ieee802154
|
||||
/components/json/ @esp-idf-codeowners/app-utilities
|
||||
/components/linux/ @esp-idf-codeowners/system
|
||||
/components/log/ @esp-idf-codeowners/system
|
||||
/components/lwip/ @esp-idf-codeowners/lwip
|
||||
/components/mbedtls/ @esp-idf-codeowners/app-utilities/mbedtls @esp-idf-codeowners/security
|
||||
/components/mqtt/ @esp-idf-codeowners/network
|
||||
/components/newlib/ @esp-idf-codeowners/system @esp-idf-codeowners/toolchain
|
||||
/components/nvs_flash/ @esp-idf-codeowners/storage
|
||||
/components/nvs_sec_provider/ @esp-idf-codeowners/storage @esp-idf-codeowners/security
|
||||
/components/openthread/ @esp-idf-codeowners/ieee802154
|
||||
/components/partition_table/ @esp-idf-codeowners/system
|
||||
/components/perfmon/ @esp-idf-codeowners/debugging
|
||||
/components/protobuf-c/ @esp-idf-codeowners/app-utilities
|
||||
/components/protocomm/ @esp-idf-codeowners/app-utilities/provisioning
|
||||
/components/pthread/ @esp-idf-codeowners/system
|
||||
/components/riscv/ @esp-idf-codeowners/system
|
||||
/components/sdmmc/ @esp-idf-codeowners/storage
|
||||
/components/soc/ @esp-idf-codeowners/peripherals @esp-idf-codeowners/system
|
||||
/components/spi_flash/ @esp-idf-codeowners/peripherals
|
||||
/components/spiffs/ @esp-idf-codeowners/storage
|
||||
/components/tcp_transport/ @esp-idf-codeowners/network
|
||||
/components/touch_element/ @esp-idf-codeowners/peripherals
|
||||
/components/ulp/ @esp-idf-codeowners/system
|
||||
/components/unity/ @esp-idf-codeowners/ci
|
||||
/components/usb/ @esp-idf-codeowners/peripherals/usb
|
||||
/components/vfs/ @esp-idf-codeowners/storage
|
||||
/components/wear_levelling/ @esp-idf-codeowners/storage
|
||||
/components/wifi_provisioning/ @esp-idf-codeowners/app-utilities/provisioning
|
||||
/components/wpa_supplicant/ @esp-idf-codeowners/wifi @esp-idf-codeowners/app-utilities/mbedtls
|
||||
/components/xtensa/ @esp-idf-codeowners/system
|
||||
|
||||
/docs/ @esp-idf-codeowners/docs
|
||||
/docs/**/api-guides/tools/ @esp-idf-codeowners/tools
|
||||
/docs/en/api-guides/core_dump.rst @esp-idf-codeowners/debugging
|
||||
/docs/en/api-guides/jtag-debugging/ @esp-idf-codeowners/debugging
|
||||
/docs/**/api-reference/bluetooth/ @esp-idf-codeowners/bluetooth
|
||||
/docs/**/api-reference/network/ @esp-idf-codeowners/network @esp-idf-codeowners/wifi
|
||||
/docs/**/api-reference/peripherals/ @esp-idf-codeowners/peripherals
|
||||
/docs/**/api-reference/peripherals/usb* @esp-idf-codeowners/peripherals @esp-idf-codeowners/peripherals/usb
|
||||
/docs/**/api-reference/protocols/ @esp-idf-codeowners/network @esp-idf-codeowners/app-utilities
|
||||
/docs/**/api-reference/provisioning/ @esp-idf-codeowners/app-utilities/provisioning
|
||||
/docs/**/api-reference/storage/ @esp-idf-codeowners/storage
|
||||
/docs/**/api-reference/system/ @esp-idf-codeowners/system
|
||||
/docs/**/security/ @esp-idf-codeowners/security
|
||||
/docs/**/migration-guides/ @esp-idf-codeowners/docs @esp-idf-codeowners/all-maintainers
|
||||
|
||||
/examples/README.md @esp-idf-codeowners/docs @esp-idf-codeowners/ci
|
||||
/examples/**/*.py @esp-idf-codeowners/ci @esp-idf-codeowners/tools
|
||||
/examples/bluetooth/ @esp-idf-codeowners/bluetooth
|
||||
/examples/build_system/ @esp-idf-codeowners/build-config
|
||||
/examples/common_components/ @esp-idf-codeowners/system @esp-idf-codeowners/wifi @esp-idf-codeowners/lwip @esp-idf-codeowners/network
|
||||
/examples/custom_bootloader/ @esp-idf-codeowners/system
|
||||
/examples/cxx/ @esp-idf-codeowners/system
|
||||
/examples/ethernet/ @esp-idf-codeowners/network
|
||||
/examples/get-started/ @esp-idf-codeowners/system
|
||||
/examples/ieee802154/ @esp-idf-codeowners/ieee802154
|
||||
/examples/mesh/ @esp-idf-codeowners/wifi
|
||||
/examples/network/ @esp-idf-codeowners/network @esp-idf-codeowners/wifi
|
||||
/examples/openthread/ @esp-idf-codeowners/ieee802154
|
||||
/examples/peripherals/ @esp-idf-codeowners/peripherals
|
||||
/examples/peripherals/usb/ @esp-idf-codeowners/peripherals @esp-idf-codeowners/peripherals/usb
|
||||
/examples/phy/ @esp-idf-codeowners/bluetooth @esp-idf-codeowners/wifi @esp-idf-codeowners/ieee802154
|
||||
/examples/protocols/ @esp-idf-codeowners/network @esp-idf-codeowners/app-utilities
|
||||
/examples/provisioning/ @esp-idf-codeowners/app-utilities/provisioning
|
||||
/examples/security/ @esp-idf-codeowners/security
|
||||
/examples/storage/ @esp-idf-codeowners/storage
|
||||
/examples/system/ @esp-idf-codeowners/system
|
||||
/examples/system/ota/ @esp-idf-codeowners/app-utilities
|
||||
/examples/wifi/ @esp-idf-codeowners/wifi
|
||||
/examples/zigbee/ @esp-idf-codeowners/ieee802154
|
||||
|
||||
/tools/ @esp-idf-codeowners/tools
|
||||
/tools/ble/ @esp-idf-codeowners/app-utilities
|
||||
/tools/catch/ @esp-idf-codeowners/ci
|
||||
/tools/ci/ @esp-idf-codeowners/ci
|
||||
/tools/cmake/ @esp-idf-codeowners/build-config
|
||||
/tools/cmake/toolchain-*.cmake @esp-idf-codeowners/toolchain
|
||||
/tools/esp_app_trace/ @esp-idf-codeowners/debugging
|
||||
/tools/esp_prov/ @esp-idf-codeowners/app-utilities
|
||||
/tools/gdb_panic_server.py @esp-idf-codeowners/debugging
|
||||
/tools/kconfig*/ @esp-idf-codeowners/build-config
|
||||
/tools/ldgen/ @esp-idf-codeowners/build-config
|
||||
/tools/mass_mfg/ @esp-idf-codeowners/app-utilities
|
||||
/tools/mocks/ @esp-idf-codeowners/system
|
||||
|
||||
/tools/test_apps/ @esp-idf-codeowners/ci
|
||||
/tools/test_apps/README.md @esp-idf-codeowners/docs @esp-idf-codeowners/ci
|
||||
|
||||
## Note: owners here should be the same as the owners for the same example subdir, above
|
||||
/tools/test_apps/build_system/ @esp-idf-codeowners/build-config
|
||||
/tools/test_apps/configs/ @esp-idf-codeowners/system
|
||||
/tools/test_apps/linux_compatible/ @esp-idf-codeowners/system
|
||||
/tools/test_apps/peripherals/ @esp-idf-codeowners/peripherals
|
||||
/tools/test_apps/phy/ @esp-idf-codeowners/bluetooth @esp-idf-codeowners/wifi @esp-idf-codeowners/ieee802154
|
||||
/tools/test_apps/protocols/ @esp-idf-codeowners/network @esp-idf-codeowners/app-utilities
|
||||
/tools/test_apps/security/ @esp-idf-codeowners/security
|
||||
/tools/test_apps/storage/ @esp-idf-codeowners/storage
|
||||
/tools/test_apps/system/ @esp-idf-codeowners/system
|
||||
|
||||
/tools/test_apps/**/*.py @esp-idf-codeowners/ci @esp-idf-codeowners/tools
|
||||
|
||||
/tools/test_build_system/ @esp-idf-codeowners/tools @esp-idf-codeowners/build-config
|
||||
|
||||
/tools/tools.json @esp-idf-codeowners/tools @esp-idf-codeowners/toolchain @esp-idf-codeowners/debugging
|
||||
|
||||
/tools/unit-test-app/ @esp-idf-codeowners/system @esp-idf-codeowners/tools
|
||||
|
||||
# sort-order-reset
|
||||
|
||||
/components/**/test_apps/**/*.py @esp-idf-codeowners/ci @esp-idf-codeowners/tools
|
||||
|
||||
# ignore lists
|
||||
/tools/ci/check_copyright_config.yaml @esp-idf-codeowners/all-maintainers
|
||||
/tools/ci/check_copyright_ignore.txt @esp-idf-codeowners/all-maintainers
|
||||
/tools/ci/mypy_ignore_list.txt @esp-idf-codeowners/tools
|
||||
* @esp-idf-codeowners/all-maintainers
|
||||
|
@ -84,7 +84,7 @@ variables:
|
||||
CI_PYTHON_TOOL_BRANCH: ""
|
||||
|
||||
# Set this variable to specify the file name for the known failure cases.
|
||||
KNOWN_FAILURE_CASES_FILE_NAME: "master.txt"
|
||||
KNOWN_FAILURE_CASES_FILE_NAME: "5.3.txt"
|
||||
|
||||
IDF_CI_BUILD: 1
|
||||
|
||||
|
@ -133,7 +133,7 @@ test_cli_installer:
|
||||
script:
|
||||
# Tools must be downloaded for testing
|
||||
# We could use "idf_tools.py download all", but we don't want to install clang because of its huge size
|
||||
- python3 ${IDF_PATH}/tools/idf_tools.py download required qemu-riscv32 qemu-xtensa
|
||||
- python3 ${IDF_PATH}/tools/idf_tools.py download required qemu-riscv32 qemu-xtensa cmake
|
||||
- cd ${IDF_PATH}/tools/test_idf_tools
|
||||
- python3 -m pip install jsonschema
|
||||
- python3 ./test_idf_tools.py -v
|
||||
@ -228,6 +228,8 @@ test_tools:
|
||||
- pytest --noconftest test_idf_qemu.py --junitxml=${IDF_PATH}/XUNIT_IDF_PY_QEMU.xml || stat=1
|
||||
- cd ${IDF_PATH}/tools/test_mkdfu
|
||||
- pytest --noconftest test_mkdfu.py --junitxml=${IDF_PATH}/XUNIT_MKDFU.xml || stat=1
|
||||
- cd ${IDF_PATH}/tools/test_idf_size
|
||||
- pytest --noconftest test_idf_size.py --junitxml=${IDF_PATH}/XUNIT_IDF_SIZE.xml || stat=1
|
||||
- cd ${IDF_PATH}
|
||||
- shellcheck -s sh tools/detect_python.sh || stat=1
|
||||
- shellcheck -s bash tools/detect_python.sh || stat=1
|
||||
@ -296,7 +298,7 @@ test_pytest_qemu:
|
||||
artifacts:
|
||||
paths:
|
||||
- XUNIT_RESULT.xml
|
||||
- pytest_embedded_log/
|
||||
- pytest-embedded/
|
||||
reports:
|
||||
junit: XUNIT_RESULT.xml
|
||||
allow_failure: true # IDFCI-1752
|
||||
@ -330,7 +332,7 @@ test_pytest_linux:
|
||||
artifacts:
|
||||
paths:
|
||||
- XUNIT_RESULT.xml
|
||||
- pytest_embedded_log/
|
||||
- pytest-embedded/
|
||||
- "**/build*/build_log.txt"
|
||||
reports:
|
||||
junit: XUNIT_RESULT.xml
|
||||
|
@ -86,6 +86,7 @@
|
||||
- "tools/test_idf_py/**/*"
|
||||
|
||||
- "tools/idf_size.py"
|
||||
- "tools/test_idf_size/**/*"
|
||||
|
||||
- "tools/tools.json"
|
||||
- "tools/tools_schema.json"
|
||||
|
@ -31,7 +31,7 @@ test_cli_installer_win:
|
||||
IDF_PATH: "$CI_PROJECT_DIR"
|
||||
script:
|
||||
# Tools must be downloaded for testing
|
||||
- python ${IDF_PATH}\tools\idf_tools.py download required qemu-riscv32 qemu-xtensa
|
||||
- python ${IDF_PATH}\tools\idf_tools.py download required qemu-riscv32 qemu-xtensa cmake
|
||||
- cd ${IDF_PATH}\tools\test_idf_tools
|
||||
- python -m pip install jsonschema
|
||||
- python .\test_idf_tools.py
|
||||
|
@ -103,10 +103,10 @@ repos:
|
||||
name: Check type annotations in python files
|
||||
entry: tools/ci/check_type_comments.py
|
||||
additional_dependencies:
|
||||
- 'mypy==0.940'
|
||||
- 'mypy-extensions==0.4.3'
|
||||
- 'types-setuptools==57.4.14'
|
||||
- 'types-PyYAML==0.1.9'
|
||||
- 'mypy'
|
||||
- 'mypy-extensions'
|
||||
- 'types-setuptools'
|
||||
- 'types-PyYAML'
|
||||
- 'types-requests'
|
||||
exclude: >
|
||||
(?x)^(
|
||||
|
@ -2,6 +2,6 @@
|
||||
|
||||
components/app_update/test_apps:
|
||||
disable:
|
||||
- if: IDF_TARGET in ["esp32c6", "esp32h2", "esp32p4", "esp32c5"]
|
||||
- if: IDF_TARGET in ["esp32c6", "esp32h2", "esp32c5"]
|
||||
temporary: true
|
||||
reason: target esp32c6, esp32h2, esp32p4, esp32c5 is not supported yet # TODO: IDF-8068, [ESP32C5] IDF-8638
|
||||
reason: target esp32c6, esp32h2 esp32c5 is not supported yet # TODO: [ESP32C5] IDF-8638
|
||||
|
@ -1,2 +1,2 @@
|
||||
| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-S2 | ESP32-S3 |
|
||||
| ----------------- | ----- | -------- | -------- | -------- | -------- |
|
||||
| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-P4 | ESP32-S2 | ESP32-S3 |
|
||||
| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- |
|
||||
|
@ -19,7 +19,7 @@ def run_multiple_stages(dut: Dut, test_case_num: int, stages: int) -> None:
|
||||
|
||||
|
||||
@pytest.mark.supported_targets
|
||||
@pytest.mark.temp_skip_ci(targets=['esp32c6', 'esp32h2', 'esp32p4'], reason='c6/h2/p4 support TBD') # TODO: IDF-8959
|
||||
@pytest.mark.temp_skip_ci(targets=['esp32c6', 'esp32h2'], reason='c6/h2 support TBD')
|
||||
@pytest.mark.generic
|
||||
def test_app_update(dut: Dut) -> None:
|
||||
extra_data = dut.parse_test_menu()
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@ -29,6 +29,7 @@
|
||||
#include "bootloader_flash_config.h"
|
||||
#include "bootloader_mem.h"
|
||||
#include "esp_private/regi2c_ctrl.h"
|
||||
#include "soc/chip_revision.h"
|
||||
#include "soc/regi2c_lp_bias.h"
|
||||
#include "soc/regi2c_bias.h"
|
||||
#include "bootloader_console.h"
|
||||
@ -90,14 +91,14 @@ static void bootloader_super_wdt_auto_feed(void)
|
||||
static inline void bootloader_hardware_init(void)
|
||||
{
|
||||
// regi2c is enabled by default on ESP32P4, do nothing
|
||||
|
||||
// On ESP32P4 ECO0, the default (power on reset) CPLL and SPLL frequencies are very high, lower them to avoid bias may not be enough in bootloader
|
||||
// And we are fixing SPLL to be 480MHz at all runtime
|
||||
// Suppose to fix the issue on ECO1, will check when chip comes back
|
||||
// TODO: IDF-8939
|
||||
REGI2C_WRITE_MASK(I2C_CPLL, I2C_CPLL_OC_DIV_7_0, 6); // lower default cpu_pll freq to 400M
|
||||
REGI2C_WRITE_MASK(I2C_SYSPLL, I2C_SYSPLL_OC_DIV_7_0, 8); // lower default sys_pll freq to 480M
|
||||
esp_rom_delay_us(100);
|
||||
unsigned chip_version = efuse_hal_chip_revision();
|
||||
if (!ESP_CHIP_REV_ABOVE(chip_version, 1)) {
|
||||
// On ESP32P4 ECO0, the default (power on reset) CPLL and SPLL frequencies are very high, lower them to avoid bias may not be enough in bootloader
|
||||
// And we are fixing SPLL to be 480MHz after app is up
|
||||
REGI2C_WRITE_MASK(I2C_CPLL, I2C_CPLL_OC_DIV_7_0, 6); // lower default cpu_pll freq to 400M
|
||||
REGI2C_WRITE_MASK(I2C_SYSPLL, I2C_SYSPLL_OC_DIV_7_0, 8); // lower default sys_pll freq to 480M
|
||||
esp_rom_delay_us(100);
|
||||
}
|
||||
REGI2C_WRITE_MASK(I2C_BIAS, I2C_BIAS_DREG_1P1, 10);
|
||||
REGI2C_WRITE_MASK(I2C_BIAS, I2C_BIAS_DREG_1P1_PVT, 10);
|
||||
}
|
||||
@ -170,7 +171,7 @@ esp_err_t bootloader_init(void)
|
||||
}
|
||||
#endif // !CONFIG_APP_BUILD_TYPE_RAM
|
||||
|
||||
// check whether a WDT reset happend
|
||||
// check whether a WDT reset happened
|
||||
bootloader_check_wdt_reset();
|
||||
// config WDT
|
||||
bootloader_config_wdt();
|
||||
|
@ -18,6 +18,7 @@
|
||||
|
||||
#if SOC_KEY_MANAGER_SUPPORTED
|
||||
#include "hal/key_mgr_hal.h"
|
||||
#include "hal/mspi_timing_tuning_ll.h"
|
||||
#include "soc/keymng_reg.h"
|
||||
#endif
|
||||
|
||||
@ -217,8 +218,15 @@ static esp_err_t check_and_generate_encryption_keys(void)
|
||||
}
|
||||
|
||||
#if SOC_KEY_MANAGER_SUPPORTED
|
||||
#if CONFIG_IDF_TARGET_ESP32C5 && SOC_KEY_MANAGER_SUPPORTED
|
||||
// TODO: [ESP32C5] IDF-8622 find a more proper place for these codes
|
||||
REG_SET_BIT(KEYMNG_STATIC_REG, KEYMNG_USE_EFUSE_KEY_FLASH);
|
||||
REG_SET_BIT(PCR_MSPI_CLK_CONF_REG, PCR_MSPI_AXI_RST_EN);
|
||||
REG_CLR_BIT(PCR_MSPI_CLK_CONF_REG, PCR_MSPI_AXI_RST_EN);
|
||||
#endif
|
||||
// Force Key Manager to use eFuse key for XTS-AES operation
|
||||
key_mgr_hal_set_key_usage(ESP_KEY_MGR_XTS_AES_128_KEY, ESP_KEY_MGR_USE_EFUSE_KEY);
|
||||
_mspi_timing_ll_reset_mspi();
|
||||
#endif
|
||||
|
||||
return ESP_OK;
|
||||
@ -263,13 +271,6 @@ esp_err_t esp_flash_encrypt_contents(void)
|
||||
esp_partition_info_t partition_table[ESP_PARTITION_TABLE_MAX_ENTRIES];
|
||||
int num_partitions;
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32C5 && SOC_KEY_MANAGER_SUPPORTED
|
||||
// TODO: [ESP32C5] IDF-8622 find a more proper place for these codes
|
||||
REG_SET_BIT(KEYMNG_STATIC_REG, KEYMNG_USE_EFUSE_KEY_FLASH);
|
||||
REG_SET_BIT(PCR_MSPI_CLK_CONF_REG, PCR_MSPI_AXI_RST_EN);
|
||||
REG_CLR_BIT(PCR_MSPI_CLK_CONF_REG, PCR_MSPI_AXI_RST_EN);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SOC_EFUSE_CONSISTS_OF_ONE_KEY_BLOCK
|
||||
REG_WRITE(SENSITIVE_XTS_AES_KEY_UPDATE_REG, 1);
|
||||
#endif
|
||||
|
@ -349,7 +349,6 @@ config BT_LE_CRYPTO_STACK_MBEDTLS
|
||||
bool "Override TinyCrypt with mbedTLS for crypto computations"
|
||||
default y
|
||||
depends on !BT_NIMBLE_ENABLED
|
||||
select MBEDTLS_ECP_RESTARTABLE
|
||||
select MBEDTLS_CMAC_C
|
||||
help
|
||||
Enable this option to choose mbedTLS instead of TinyCrypt for crypto
|
||||
|
@ -365,7 +365,6 @@ config BT_LE_CRYPTO_STACK_MBEDTLS
|
||||
bool "Override TinyCrypt with mbedTLS for crypto computations"
|
||||
default y
|
||||
depends on !BT_NIMBLE_ENABLED
|
||||
select MBEDTLS_ECP_RESTARTABLE
|
||||
select MBEDTLS_CMAC_C
|
||||
help
|
||||
Enable this option to choose mbedTLS instead of TinyCrypt for crypto
|
||||
|
@ -365,7 +365,6 @@ config BT_LE_CRYPTO_STACK_MBEDTLS
|
||||
bool "Override TinyCrypt with mbedTLS for crypto computations"
|
||||
default y
|
||||
depends on !BT_NIMBLE_ENABLED
|
||||
select MBEDTLS_ECP_RESTARTABLE
|
||||
select MBEDTLS_CMAC_C
|
||||
help
|
||||
Enable this option to choose mbedTLS instead of TinyCrypt for crypto
|
||||
|
@ -356,7 +356,6 @@ config BT_LE_CRYPTO_STACK_MBEDTLS
|
||||
bool "Override TinyCrypt with mbedTLS for crypto computations"
|
||||
default y
|
||||
depends on !BT_NIMBLE_ENABLED
|
||||
select MBEDTLS_ECP_RESTARTABLE
|
||||
select MBEDTLS_CMAC_C
|
||||
help
|
||||
Enable this option to choose mbedTLS instead of TinyCrypt for crypto
|
||||
|
Submodule components/bt/controller/lib_esp32 updated: 44341b15e5...45e3280535
Submodule components/bt/controller/lib_esp32c6/esp32c6-bt-lib updated: 0af472c6f9...6663362597
Submodule components/bt/controller/lib_esp32h2/esp32h2-bt-lib updated: 70612d08d1...9bf31906cd
@ -722,6 +722,26 @@ extern void bta_hd_exit_suspend_act(tBTA_HD_DATA *p_data)
|
||||
bta_sys_idle(BTA_ID_HD, 1, p_cback->addr);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function bta_hd_open_failure
|
||||
*
|
||||
* Description
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
extern void bta_hd_open_failure(tBTA_HD_DATA *p_data)
|
||||
{
|
||||
tBTA_HD_CBACK_DATA *p_cback = (tBTA_HD_CBACK_DATA *)p_data;
|
||||
tBTA_HD cback_data = {0};
|
||||
|
||||
bdcpy(cback_data.conn.bda, p_cback->addr);
|
||||
cback_data.conn.status = BTA_HD_ERROR;
|
||||
cback_data.conn.conn_status = BTA_HD_CONN_STATE_DISCONNECTED;
|
||||
bta_hd_cb.p_cback(BTA_HD_OPEN_EVT, &cback_data);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function bta_hd_cback
|
||||
|
@ -62,6 +62,7 @@ enum {
|
||||
BTA_HD_VC_UNPLUG_DONE_ACT,
|
||||
BTA_HD_SUSPEND_ACT,
|
||||
BTA_HD_EXIT_SUSPEND_ACT,
|
||||
BTA_HD_OPEN_FAILURE,
|
||||
BTA_HD_NUM_ACTIONS
|
||||
};
|
||||
|
||||
@ -74,7 +75,7 @@ const tBTA_HD_ACTION bta_hd_action[] = {
|
||||
bta_hd_disconnect_act, bta_hd_add_device_act, bta_hd_remove_device_act, bta_hd_send_report_act,
|
||||
bta_hd_report_error_act, bta_hd_vc_unplug_act, bta_hd_open_act, bta_hd_close_act,
|
||||
bta_hd_intr_data_act, bta_hd_get_report_act, bta_hd_set_report_act, bta_hd_set_protocol_act,
|
||||
bta_hd_vc_unplug_done_act, bta_hd_suspend_act, bta_hd_exit_suspend_act,
|
||||
bta_hd_vc_unplug_done_act, bta_hd_suspend_act, bta_hd_exit_suspend_act, bta_hd_open_failure
|
||||
};
|
||||
|
||||
/* state table information */
|
||||
@ -118,7 +119,7 @@ const uint8_t bta_hd_st_idle[][BTA_HD_NUM_COLS] = {
|
||||
/* BTA_HD_API_REPORT_ERROR_EVT */ {BTA_HD_IGNORE, BTA_HD_IDLE_ST},
|
||||
/* BTA_HD_API_VC_UNPLUG_EVT */ {BTA_HD_VC_UNPLUG_ACT, BTA_HD_IDLE_ST},
|
||||
/* BTA_HD_INT_OPEN_EVT */ {BTA_HD_OPEN_ACT, BTA_HD_CONN_ST},
|
||||
/* BTA_HD_INT_CLOSE_EVT */ {BTA_HD_IGNORE, BTA_HD_IDLE_ST},
|
||||
/* BTA_HD_INT_CLOSE_EVT */ {BTA_HD_OPEN_FAILURE, BTA_HD_IDLE_ST},
|
||||
/* BTA_HD_INT_INTR_DATA_EVT */ {BTA_HD_IGNORE, BTA_HD_IDLE_ST},
|
||||
/* BTA_HD_INT_GET_REPORT_EVT */ {BTA_HD_IGNORE, BTA_HD_IDLE_ST},
|
||||
/* BTA_HD_INT_SET_REPORT_EVT */ {BTA_HD_IGNORE, BTA_HD_IDLE_ST},
|
||||
|
@ -164,5 +164,6 @@ extern void bta_hd_set_protocol_act(tBTA_HD_DATA *p_data);
|
||||
extern void bta_hd_vc_unplug_done_act(tBTA_HD_DATA *p_data);
|
||||
extern void bta_hd_suspend_act(tBTA_HD_DATA *p_data);
|
||||
extern void bta_hd_exit_suspend_act(tBTA_HD_DATA *p_data);
|
||||
extern void bta_hd_open_failure(tBTA_HD_DATA *p_data);
|
||||
|
||||
#endif
|
||||
|
@ -261,7 +261,7 @@ static void btc_hd_deinit(void)
|
||||
}
|
||||
|
||||
btc_hd_cb.service_dereg_active = FALSE;
|
||||
// unresgister app will also relase the connection
|
||||
// unregister app will also release the connection
|
||||
// and disable after receiving unregister event from lower layer
|
||||
if (is_hidd_app_register()) {
|
||||
btc_hd_unregister_app(true);
|
||||
@ -844,6 +844,8 @@ void btc_hd_cb_handler(btc_msg_t *msg)
|
||||
// }
|
||||
// btc_storage_set_hidd((bt_bdaddr_t *)&p_data->conn.bda);
|
||||
btc_hd_cb.status = BTC_HD_CONNECTED;
|
||||
} else if (p_data->conn.conn_status == BTA_HD_CONN_STATE_DISCONNECTED) {
|
||||
btc_hd_cb.status = BTC_HD_DISCONNECTED;
|
||||
}
|
||||
param.open.status = p_data->conn.status;
|
||||
param.open.conn_status = p_data->conn.conn_status;
|
||||
|
@ -1252,6 +1252,9 @@ static void btu_hcif_command_complete_evt(BT_HDR *response, void *context)
|
||||
static void btu_hcif_hdl_command_status (UINT16 opcode, UINT8 status, UINT8 *p_cmd,
|
||||
void *p_vsc_status_cback)
|
||||
{
|
||||
if (status != HCI_SUCCESS){
|
||||
HCI_TRACE_WARNING("%s,opcode:0x%04x,status:0x%02x", __func__, opcode,status);
|
||||
}
|
||||
BD_ADDR bd_addr;
|
||||
UINT16 handle;
|
||||
#if BTM_SCO_INCLUDED == TRUE
|
||||
|
@ -231,7 +231,7 @@ static void hidd_l2cif_connect_cfm(uint16_t cid, uint16_t result)
|
||||
tHID_CONN *p_hcon = &hd_cb.device.conn;
|
||||
HIDD_TRACE_EVENT("%s: cid=%04x result=%d, conn_state=%d", __func__, cid, result, p_hcon->conn_state);
|
||||
if (p_hcon->ctrl_cid != cid && p_hcon->intr_cid != cid) {
|
||||
HIDD_TRACE_WARNING("%s: unknown cid", __func__);
|
||||
HIDD_TRACE_WARNING("%s: unknown cid=%04x", __func__, cid);
|
||||
return;
|
||||
}
|
||||
if (!(p_hcon->conn_flags & HID_CONN_FLAGS_IS_ORIG) ||
|
||||
@ -243,10 +243,12 @@ static void hidd_l2cif_connect_cfm(uint16_t cid, uint16_t result)
|
||||
}
|
||||
if (result != L2CAP_CONN_OK) {
|
||||
HIDD_TRACE_WARNING("%s: connection failed, now disconnect", __func__);
|
||||
if (cid == p_hcon->ctrl_cid)
|
||||
if (cid == p_hcon->ctrl_cid) {
|
||||
p_hcon->ctrl_cid = 0;
|
||||
else
|
||||
} else {
|
||||
p_hcon->intr_cid = 0;
|
||||
}
|
||||
|
||||
hidd_conn_disconnect();
|
||||
hd_cb.callback(hd_cb.device.addr, HID_DHOST_EVT_CLOSE, HID_L2CAP_CONN_FAIL | (uint32_t)result, NULL);
|
||||
return;
|
||||
@ -278,7 +280,7 @@ static void hidd_l2cif_config_ind(uint16_t cid, tL2CAP_CFG_INFO *p_cfg)
|
||||
HIDD_TRACE_EVENT("%s: cid=%04x", __func__, cid);
|
||||
p_hcon = &hd_cb.device.conn;
|
||||
if (p_hcon->ctrl_cid != cid && p_hcon->intr_cid != cid) {
|
||||
HIDD_TRACE_WARNING("%s: unknown cid", __func__);
|
||||
HIDD_TRACE_WARNING("%s: unknown cid=%04x", __func__, cid);
|
||||
return;
|
||||
}
|
||||
if ((!p_cfg->mtu_present) || (p_cfg->mtu > HID_DEV_MTU_SIZE))
|
||||
@ -297,7 +299,8 @@ static void hidd_l2cif_config_ind(uint16_t cid, tL2CAP_CFG_INFO *p_cfg)
|
||||
// update flags
|
||||
if (cid == p_hcon->ctrl_cid) {
|
||||
p_hcon->conn_flags |= HID_CONN_FLAGS_HIS_CTRL_CFG_DONE;
|
||||
if ((p_hcon->conn_flags & HID_CONN_FLAGS_IS_ORIG) && (p_hcon->conn_flags & HID_CONN_FLAGS_MY_CTRL_CFG_DONE)) {
|
||||
if ((p_hcon->conn_flags & HID_CONN_FLAGS_IS_ORIG) && (p_hcon->conn_flags & HID_CONN_FLAGS_MY_CTRL_CFG_DONE) &&
|
||||
(p_hcon->conn_state != HID_CONN_STATE_CONNECTING_INTR)) {
|
||||
p_hcon->disc_reason = HID_L2CAP_CONN_FAIL;
|
||||
if ((p_hcon->intr_cid = L2CA_ConnectReq(HID_PSM_INTERRUPT, hd_cb.device.addr)) == 0) {
|
||||
p_hcon->conn_state = HID_CONN_STATE_UNUSED;
|
||||
@ -330,7 +333,7 @@ static void hidd_l2cif_config_cfm(uint16_t cid, tL2CAP_CFG_INFO *p_cfg)
|
||||
HIDD_TRACE_EVENT("%s: cid=%04x pcfg->result=%d", __func__, cid, p_cfg->result);
|
||||
p_hcon = &hd_cb.device.conn;
|
||||
if (p_hcon->ctrl_cid != cid && p_hcon->intr_cid != cid) {
|
||||
HIDD_TRACE_WARNING("%s: unknown cid", __func__);
|
||||
HIDD_TRACE_WARNING("%s: unknown cid=%04x", __func__, cid);
|
||||
return;
|
||||
}
|
||||
if (p_hcon->intr_cid == cid && p_cfg->result == L2CAP_CFG_UNACCEPTABLE_PARAMS && p_cfg->qos_present) {
|
||||
@ -357,7 +360,8 @@ static void hidd_l2cif_config_cfm(uint16_t cid, tL2CAP_CFG_INFO *p_cfg)
|
||||
// update flags
|
||||
if (cid == p_hcon->ctrl_cid) {
|
||||
p_hcon->conn_flags |= HID_CONN_FLAGS_MY_CTRL_CFG_DONE;
|
||||
if ((p_hcon->conn_flags & HID_CONN_FLAGS_IS_ORIG) && (p_hcon->conn_flags & HID_CONN_FLAGS_HIS_CTRL_CFG_DONE)) {
|
||||
if ((p_hcon->conn_flags & HID_CONN_FLAGS_IS_ORIG) && (p_hcon->conn_flags & HID_CONN_FLAGS_HIS_CTRL_CFG_DONE) &&
|
||||
(p_hcon->conn_state != HID_CONN_STATE_CONNECTING_INTR)) {
|
||||
p_hcon->disc_reason = HID_L2CAP_CONN_FAIL;
|
||||
if ((p_hcon->intr_cid = L2CA_ConnectReq(HID_PSM_INTERRUPT, hd_cb.device.addr)) == 0) {
|
||||
p_hcon->conn_state = HID_CONN_STATE_UNUSED;
|
||||
@ -389,11 +393,14 @@ static void hidd_l2cif_disconnect_ind(uint16_t cid, bool ack_needed)
|
||||
HIDD_TRACE_EVENT("%s: cid=%04x ack_needed=%d", __func__, cid, ack_needed);
|
||||
p_hcon = &hd_cb.device.conn;
|
||||
if (p_hcon->conn_state == HID_CONN_STATE_UNUSED || (p_hcon->ctrl_cid != cid && p_hcon->intr_cid != cid)) {
|
||||
HIDD_TRACE_WARNING("%s: unknown cid", __func__);
|
||||
HIDD_TRACE_WARNING("%s: unknown cid=%04x", __func__, cid);
|
||||
return;
|
||||
}
|
||||
if (ack_needed)
|
||||
|
||||
if (ack_needed) {
|
||||
L2CA_DisconnectRsp(cid);
|
||||
}
|
||||
|
||||
if (cid == p_hcon->ctrl_cid) {
|
||||
p_hcon->ctrl_cid = 0;
|
||||
p_hcon->conn_state = HID_CONN_STATE_DISCONNECTING_CTRL;
|
||||
@ -417,7 +424,7 @@ static void hidd_l2cif_disconnect_ind(uint16_t cid, bool ack_needed)
|
||||
*
|
||||
* Function hidd_l2cif_disconnect_cfm
|
||||
*
|
||||
* Description Handles L2CAP disconection response
|
||||
* Description Handles L2CAP disconnection response
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
@ -428,7 +435,7 @@ static void hidd_l2cif_disconnect_cfm(uint16_t cid, uint16_t result)
|
||||
HIDD_TRACE_EVENT("%s: cid=%04x result=%d", __func__, cid, result);
|
||||
p_hcon = &hd_cb.device.conn;
|
||||
if (p_hcon->conn_state == HID_CONN_STATE_UNUSED || (p_hcon->ctrl_cid != cid && p_hcon->intr_cid != cid)) {
|
||||
HIDD_TRACE_WARNING("%s: unknown cid", __func__);
|
||||
HIDD_TRACE_WARNING("%s: unknown cid=%04x", __func__, cid);
|
||||
return;
|
||||
}
|
||||
if (cid == p_hcon->ctrl_cid) {
|
||||
@ -465,7 +472,7 @@ static void hidd_l2cif_cong_ind(uint16_t cid, bool congested)
|
||||
HIDD_TRACE_EVENT("%s: cid=%04x congested=%d", __func__, cid, congested);
|
||||
p_hcon = &hd_cb.device.conn;
|
||||
if (p_hcon->conn_state == HID_CONN_STATE_UNUSED || (p_hcon->ctrl_cid != cid && p_hcon->intr_cid != cid)) {
|
||||
HIDD_TRACE_WARNING("%s: unknown cid", __func__);
|
||||
HIDD_TRACE_WARNING("%s: unknown cid=%04x", __func__, cid);
|
||||
return;
|
||||
}
|
||||
if (congested) {
|
||||
@ -492,7 +499,7 @@ static void hidd_l2cif_data_ind(uint16_t cid, BT_HDR *p_msg)
|
||||
HIDD_TRACE_EVENT("%s: cid=%04x", __func__, cid);
|
||||
p_hcon = &hd_cb.device.conn;
|
||||
if (p_hcon->conn_state == HID_CONN_STATE_UNUSED || (p_hcon->ctrl_cid != cid && p_hcon->intr_cid != cid)) {
|
||||
HIDD_TRACE_WARNING("%s: unknown cid", __func__);
|
||||
HIDD_TRACE_WARNING("%s: unknown cid=%04x", __func__, cid);
|
||||
osi_free(p_msg);
|
||||
return;
|
||||
}
|
||||
@ -645,7 +652,7 @@ tHID_STATUS hidd_conn_initiate(void)
|
||||
p_dev->conn.ctrl_cid = 0;
|
||||
p_dev->conn.intr_cid = 0;
|
||||
p_dev->conn.disc_reason = HID_L2CAP_CONN_FAIL;
|
||||
p_dev->conn.conn_flags = HID_CONN_FLAGS_IS_ORIG;
|
||||
p_dev->conn.conn_flags |= HID_CONN_FLAGS_IS_ORIG;
|
||||
BTM_SetOutService(p_dev->addr, BTM_SEC_SERVICE_HIDD_SEC_CTRL, HIDD_SEC_CHN);
|
||||
/* Check if L2CAP started the connection process */
|
||||
if ((p_dev->conn.ctrl_cid = L2CA_ConnectReq(HID_PSM_CONTROL, p_dev->addr)) == 0) {
|
||||
|
@ -379,7 +379,6 @@ tHID_STATUS HID_HostAddDev ( BD_ADDR addr, UINT16 attr_mask, UINT8 *handle )
|
||||
if (!hh_cb.devices[i].in_use) {
|
||||
hh_cb.devices[i].in_use = TRUE;
|
||||
hh_cb.devices[i].delay_remove = FALSE;
|
||||
hh_cb.devices[i].is_orig = FALSE;
|
||||
memcpy( hh_cb.devices[i].addr, addr, sizeof( BD_ADDR ) ) ;
|
||||
hh_cb.devices[i].state = HID_DEV_NO_CONN;
|
||||
hh_cb.devices[i].conn_tries = 0 ;
|
||||
@ -487,7 +486,6 @@ tHID_STATUS HID_HostOpenDev ( UINT8 dev_handle )
|
||||
}
|
||||
|
||||
hh_cb.devices[dev_handle].conn_tries = 1;
|
||||
hh_cb.devices[dev_handle].is_orig = TRUE;
|
||||
return hidh_conn_initiate( dev_handle );
|
||||
}
|
||||
|
||||
@ -666,7 +664,7 @@ BOOLEAN HID_HostConnectOrig(UINT8 dev_handle)
|
||||
break;
|
||||
}
|
||||
|
||||
ret = hh_cb.devices[dev_handle].is_orig;
|
||||
ret = hidh_conn_is_orig(dev_handle);
|
||||
} while (0);
|
||||
|
||||
return ret;
|
||||
|
@ -457,8 +457,8 @@ static void hidh_l2cif_config_ind (UINT16 l2cap_cid, tL2CAP_CFG_INFO *p_cfg)
|
||||
|
||||
if (l2cap_cid == p_hcon->ctrl_cid) {
|
||||
p_hcon->conn_flags |= HID_CONN_FLAGS_HIS_CTRL_CFG_DONE;
|
||||
if ((p_hcon->conn_flags & HID_CONN_FLAGS_IS_ORIG) &&
|
||||
(p_hcon->conn_flags & HID_CONN_FLAGS_MY_CTRL_CFG_DONE)) {
|
||||
if ((p_hcon->conn_flags & HID_CONN_FLAGS_IS_ORIG) && (p_hcon->conn_flags & HID_CONN_FLAGS_MY_CTRL_CFG_DONE) &&
|
||||
(p_hcon->conn_state != HID_CONN_STATE_CONNECTING_INTR)) {
|
||||
/* Connect interrupt channel */
|
||||
p_hcon->disc_reason = HID_L2CAP_CONN_FAIL; /* Reset initial reason for CLOSE_EVT: Connection Attempt was made but failed */
|
||||
if ((p_hcon->intr_cid = L2CA_ConnectReq (HID_PSM_INTERRUPT, hh_cb.devices[dhandle].addr)) == 0) {
|
||||
@ -528,8 +528,8 @@ static void hidh_l2cif_config_cfm (UINT16 l2cap_cid, tL2CAP_CFG_INFO *p_cfg)
|
||||
|
||||
if (l2cap_cid == p_hcon->ctrl_cid) {
|
||||
p_hcon->conn_flags |= HID_CONN_FLAGS_MY_CTRL_CFG_DONE;
|
||||
if ((p_hcon->conn_flags & HID_CONN_FLAGS_IS_ORIG) &&
|
||||
(p_hcon->conn_flags & HID_CONN_FLAGS_HIS_CTRL_CFG_DONE)) {
|
||||
if ((p_hcon->conn_flags & HID_CONN_FLAGS_IS_ORIG) && (p_hcon->conn_flags & HID_CONN_FLAGS_HIS_CTRL_CFG_DONE) &&
|
||||
(p_hcon->conn_state != HID_CONN_STATE_CONNECTING_INTR)) {
|
||||
/* Connect interrupt channel */
|
||||
p_hcon->disc_reason = HID_L2CAP_CONN_FAIL; /* Reset initial reason for CLOSE_EVT: Connection Attempt was made but failed */
|
||||
if ((p_hcon->intr_cid = L2CA_ConnectReq (HID_PSM_INTERRUPT, hh_cb.devices[dhandle].addr)) == 0) {
|
||||
@ -968,7 +968,7 @@ tHID_STATUS hidh_conn_initiate (UINT8 dhandle)
|
||||
p_dev->conn.disc_reason = HID_L2CAP_CONN_FAIL; /* Reset initial reason for CLOSE_EVT: Connection Attempt was made but failed */
|
||||
|
||||
/* We are the originator of this connection */
|
||||
p_dev->conn.conn_flags = HID_CONN_FLAGS_IS_ORIG;
|
||||
p_dev->conn.conn_flags |= HID_CONN_FLAGS_IS_ORIG;
|
||||
|
||||
if (p_dev->attr_mask & HID_SEC_REQUIRED) {
|
||||
service_id = BTM_SEC_SERVICE_HIDH_SEC_CTRL;
|
||||
@ -989,6 +989,20 @@ tHID_STATUS hidh_conn_initiate (UINT8 dhandle)
|
||||
return ( HID_SUCCESS );
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function hidh_conn_is_orig
|
||||
**
|
||||
** Description This function check if we are the originator of this connection
|
||||
**
|
||||
** Returns BOOLEAN
|
||||
**
|
||||
*******************************************************************************/
|
||||
BOOLEAN hidh_conn_is_orig(UINT8 dhandle)
|
||||
{
|
||||
tHID_HOST_DEV_CTB *p_dev = &hh_cb.devices[dhandle];
|
||||
return (p_dev->conn.conn_flags & HID_CONN_FLAGS_IS_ORIG);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
|
@ -35,7 +35,6 @@ enum { HID_DEV_NO_CONN, HID_DEV_CONNECTED };
|
||||
typedef struct per_device_ctb {
|
||||
BOOLEAN in_use;
|
||||
BOOLEAN delay_remove;
|
||||
BOOLEAN is_orig;
|
||||
BD_ADDR addr; /* BD-Addr of the host device */
|
||||
UINT16 attr_mask; /* 0x01- virtual_cable; 0x02- normally_connectable; 0x03- reconn_initiate;
|
||||
0x04- sdp_disable; */
|
||||
@ -66,6 +65,7 @@ extern tHID_STATUS hidh_conn_reg (void);
|
||||
extern void hidh_conn_dereg( void );
|
||||
extern tHID_STATUS hidh_conn_disconnect (UINT8 dhandle);
|
||||
extern tHID_STATUS hidh_conn_initiate (UINT8 dhandle);
|
||||
extern BOOLEAN hidh_conn_is_orig(UINT8 dhandle);
|
||||
extern void hidh_proc_repage_timeout (TIMER_LIST_ENT *p_tle);
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
@ -498,7 +498,6 @@ config BT_NIMBLE_CRYPTO_STACK_MBEDTLS
|
||||
bool "Override TinyCrypt with mbedTLS for crypto computations"
|
||||
default y
|
||||
depends on BT_NIMBLE_ENABLED
|
||||
select MBEDTLS_ECP_RESTARTABLE
|
||||
select MBEDTLS_CMAC_C
|
||||
help
|
||||
Enable this option to choose mbedTLS instead of TinyCrypt for crypto
|
||||
@ -597,7 +596,7 @@ if BT_NIMBLE_EXT_ADV
|
||||
Enable this option to start periodic advertisement.
|
||||
|
||||
config BT_NIMBLE_PERIODIC_ADV_SYNC_TRANSFER
|
||||
bool "Enable Transer Sync Events"
|
||||
bool "Enable Transfer Sync Events"
|
||||
depends on BT_NIMBLE_ENABLE_PERIODIC_ADV
|
||||
default y
|
||||
help
|
||||
@ -666,7 +665,7 @@ config BT_NIMBLE_GATT_CACHING_MAX_DSCS
|
||||
depends on BT_NIMBLE_GATT_CACHING
|
||||
default 64
|
||||
help
|
||||
Set this option to set the upper limit on number of discriptors per connection to be cached.
|
||||
Set this option to set the upper limit on number of descriptors per connection to be cached.
|
||||
|
||||
config BT_NIMBLE_WHITELIST_SIZE
|
||||
int "BLE white list size"
|
||||
|
Submodule components/bt/host/nimble/nimble updated: cc997ecc33...fdc3526193
@ -39,7 +39,9 @@ if(NOT CONFIG_CXX_EXCEPTIONS)
|
||||
_Unwind_Resume_or_Rethrow
|
||||
_Unwind_Backtrace
|
||||
__cxa_call_unexpected
|
||||
__gxx_personality_v0)
|
||||
__gxx_personality_v0
|
||||
__cxa_throw
|
||||
__cxa_allocate_exception)
|
||||
|
||||
foreach(wrap ${WRAP_FUNCTIONS})
|
||||
target_link_libraries(${COMPONENT_LIB} INTERFACE "-Wl,--wrap=${wrap}")
|
||||
|
@ -178,4 +178,16 @@ extern "C" _Unwind_Reason_Code __wrap___gxx_personality_v0(int version,
|
||||
return abort_return<_Unwind_Reason_Code>();
|
||||
}
|
||||
|
||||
// Reduces binary size since the linker will drop some code due to --gc-sections.
|
||||
extern "C" void __wrap___cxa_allocate_exception(void)
|
||||
{
|
||||
abort();
|
||||
}
|
||||
|
||||
// Reduces binary size since the linker will drop some code due to --gc-sections.
|
||||
extern "C" void __wrap___cxa_throw(void)
|
||||
{
|
||||
abort();
|
||||
}
|
||||
|
||||
#endif // CONFIG_COMPILER_CXX_EXCEPTIONS
|
||||
|
@ -1,4 +1,4 @@
|
||||
set(srcs esp_tls.c esp-tls-crypto/esp_tls_crypto.c esp_tls_error_capture.c)
|
||||
set(srcs esp_tls.c esp-tls-crypto/esp_tls_crypto.c esp_tls_error_capture.c esp_tls_platform_port.c)
|
||||
if(CONFIG_ESP_TLS_USING_MBEDTLS)
|
||||
list(APPEND srcs
|
||||
"esp_tls_mbedtls.c")
|
||||
@ -9,7 +9,7 @@ if(CONFIG_ESP_TLS_USING_WOLFSSL)
|
||||
"esp_tls_wolfssl.c")
|
||||
endif()
|
||||
|
||||
set(priv_req http_parser)
|
||||
set(priv_req http_parser esp_timer)
|
||||
if(NOT ${IDF_TARGET} STREQUAL "linux")
|
||||
list(APPEND priv_req lwip)
|
||||
endif()
|
||||
@ -17,7 +17,7 @@ endif()
|
||||
idf_component_register(SRCS "${srcs}"
|
||||
INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR} esp-tls-crypto
|
||||
PRIV_INCLUDE_DIRS "private_include"
|
||||
# mbedtls is public requirements becasue esp_tls.h
|
||||
# mbedtls is public requirements because esp_tls.h
|
||||
# includes mbedtls header files.
|
||||
REQUIRES mbedtls
|
||||
PRIV_REQUIRES ${priv_req})
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_tls.h"
|
||||
#include "esp_tls_private.h"
|
||||
#include "esp_tls_platform_port.h"
|
||||
#include "esp_tls_error_capture_internal.h"
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
@ -537,9 +538,8 @@ int esp_tls_conn_new_sync(const char *hostname, int hostlen, int port, const esp
|
||||
if (!cfg || !tls || !hostname || hostlen < 0) {
|
||||
return -1;
|
||||
}
|
||||
struct timeval time = {};
|
||||
gettimeofday(&time, NULL);
|
||||
uint32_t start_time_ms = (time.tv_sec * 1000) + (time.tv_usec / 1000);
|
||||
uint64_t start_time_us;
|
||||
start_time_us = esp_tls_get_platform_time();
|
||||
while (1) {
|
||||
int ret = esp_tls_low_level_conn(hostname, hostlen, port, cfg, tls);
|
||||
if (ret == 1) {
|
||||
@ -548,10 +548,8 @@ int esp_tls_conn_new_sync(const char *hostname, int hostlen, int port, const esp
|
||||
ESP_LOGE(TAG, "Failed to open new connection");
|
||||
return -1;
|
||||
} else if (ret == 0 && cfg->timeout_ms >= 0) {
|
||||
gettimeofday(&time, NULL);
|
||||
uint32_t current_time_ms = (time.tv_sec * 1000) + (time.tv_usec / 1000);
|
||||
uint32_t elapsed_time_ms = current_time_ms - start_time_ms;
|
||||
if (elapsed_time_ms >= cfg->timeout_ms) {
|
||||
uint64_t elapsed_time_us = esp_tls_get_platform_time() - start_time_us;
|
||||
if ((elapsed_time_us / 1000) >= cfg->timeout_ms) {
|
||||
ESP_LOGW(TAG, "Failed to open new connection in specified timeout");
|
||||
ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_ESP, ESP_ERR_ESP_TLS_CONNECTION_TIMEOUT);
|
||||
return 0;
|
||||
|
28
components/esp-tls/esp_tls_platform_port.c
Normal file
28
components/esp-tls/esp_tls_platform_port.c
Normal file
@ -0,0 +1,28 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "sdkconfig.h"
|
||||
#include <stdint.h>
|
||||
#if CONFIG_IDF_TARGET_LINUX
|
||||
#include <sys/time.h>
|
||||
#include <time.h>
|
||||
#else
|
||||
#include "esp_timer.h"
|
||||
#endif
|
||||
|
||||
uint64_t esp_tls_get_platform_time(void)
|
||||
{
|
||||
#if CONFIG_IDF_TARGET_LINUX
|
||||
// Use gettimeofday for Linux/MacOS, Ideally esp_timer should be used but it is not implemented for Linux/MacOS.
|
||||
struct timeval time = {};
|
||||
gettimeofday(&time, NULL);
|
||||
uint64_t curr_time = ((uint64_t)time.tv_sec * 1000000) + (time.tv_usec);
|
||||
return curr_time;
|
||||
#else
|
||||
// For all other esp targets use esp_timer
|
||||
return esp_timer_get_time();
|
||||
#endif
|
||||
}
|
24
components/esp-tls/private_include/esp_tls_platform_port.h
Normal file
24
components/esp-tls/private_include/esp_tls_platform_port.h
Normal file
@ -0,0 +1,24 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
// This file contains APIs which have different implementation across different targets e.g., Linux, ESP.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/* @brief
|
||||
*
|
||||
* Behaviour
|
||||
* Linux:
|
||||
* Returns the system time (64 bit) using gettimeofday in microseconds. This shall get changed if someone changes the system time using settimeofday
|
||||
* ESP targets:
|
||||
* Returns the time (64 bit) since boot obtained using esp_timer_get_time() in microseconds
|
||||
* @return
|
||||
* time uint64_t bit time value
|
||||
*
|
||||
*/
|
||||
uint64_t esp_tls_get_platform_time(void);
|
@ -32,5 +32,12 @@ menu "Wireless Coexistence"
|
||||
This function depends on BT-off
|
||||
because currently we do not support external coex and internal coex simultaneously.
|
||||
|
||||
config ESP_COEX_POWER_MANAGEMENT
|
||||
bool "Support power management under coexistence"
|
||||
default n
|
||||
depends on (ESP_COEX_SW_COEXIST_ENABLE)
|
||||
help
|
||||
If enabled, coexist power management will be enabled.
|
||||
endif
|
||||
|
||||
endmenu # Wireless Coexistence
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2018-2023 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2018-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@ -313,7 +313,7 @@ esp_err_t esp_coex_adapter_register(coex_adapter_funcs_t *funcs);
|
||||
|
||||
#if CONFIG_EXTERNAL_COEX_ENABLE
|
||||
/**
|
||||
* @brief Set external coexistence advanced informations, like working mode.
|
||||
* @brief Set external coexistence advanced information, like working mode.
|
||||
*
|
||||
* @param out_pti1 This parameter no longer works, will be deprecated and later removed in future releases.
|
||||
* @param out_pti2 This parameter no longer works, will be deprecated and later removed in future releases.
|
||||
@ -365,6 +365,25 @@ void esp_coex_external_set_txline(bool en);
|
||||
#endif /*SOC_EXTERNAL_COEX_LEADER_TX_LINE*/
|
||||
#endif /*External Coex*/
|
||||
|
||||
#if CONFIG_ESP_COEX_POWER_MANAGEMENT
|
||||
/**
|
||||
* @brief Set coexist scheme flexible period
|
||||
*
|
||||
* @param period flexible period
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: succeed
|
||||
*/
|
||||
int coex_schm_flexible_period_set(uint8_t period);
|
||||
|
||||
/**
|
||||
* @brief Get coexist scheme flexible period
|
||||
*
|
||||
* @return Coexist scheme flexible period
|
||||
*/
|
||||
uint8_t coex_schm_flexible_period_get(void);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Check the MD5 values of the coexistence adapter header files in IDF and WiFi library
|
||||
*
|
||||
|
Submodule components/esp_coex/lib updated: 87eecbdf13...2363239dde
@ -300,6 +300,7 @@ static bool csi_dma_trans_done_callback(dw_gdma_channel_handle_t chan, const dw_
|
||||
bool need_yield = false;
|
||||
BaseType_t high_task_woken = pdFALSE;
|
||||
csi_controller_t *ctlr = (csi_controller_t *)user_data;
|
||||
bool has_new_trans = false;
|
||||
bool use_backup = false;
|
||||
|
||||
dw_gdma_block_transfer_config_t csi_dma_transfer_config = {};
|
||||
@ -328,12 +329,14 @@ static bool csi_dma_trans_done_callback(dw_gdma_channel_handle_t chan, const dw_
|
||||
use_backup = true;
|
||||
} else {
|
||||
csi_dma_transfer_config.dst.addr = (uint32_t)(new_trans.buffer);
|
||||
has_new_trans = true;
|
||||
}
|
||||
} else if (xQueueReceiveFromISR(ctlr->trans_que, &new_trans, &high_task_woken) == pdTRUE) {
|
||||
if (!(new_trans.buffer) || new_trans.buflen < ctlr->fb_size_in_bytes) {
|
||||
use_backup = true;
|
||||
} else {
|
||||
csi_dma_transfer_config.dst.addr = (uint32_t)(new_trans.buffer);
|
||||
has_new_trans = true;
|
||||
}
|
||||
} else if (!ctlr->bk_buffer_dis) {
|
||||
use_backup = true;
|
||||
@ -344,7 +347,9 @@ static bool csi_dma_trans_done_callback(dw_gdma_channel_handle_t chan, const dw_
|
||||
new_trans.buflen = ctlr->fb_size_in_bytes;
|
||||
ESP_EARLY_LOGD(TAG, "no new buffer or no long enough new buffer, use driver internal buffer");
|
||||
csi_dma_transfer_config.dst.addr = (uint32_t)ctlr->backup_buffer;
|
||||
} else {
|
||||
}
|
||||
|
||||
if (!has_new_trans) {
|
||||
assert(false && "no new buffer, and no driver internal buffer");
|
||||
}
|
||||
|
||||
|
@ -84,7 +84,7 @@ esp_err_t esp_cam_ctlr_get_frame_buffer_len(esp_cam_ctlr_handle_t handle, size_t
|
||||
return handle->get_buffer_len(handle, ret_fb_len);
|
||||
}
|
||||
|
||||
esp_err_t esp_cam_del_ctlr(esp_cam_ctlr_handle_t handle)
|
||||
esp_err_t esp_cam_ctlr_del(esp_cam_ctlr_handle_t handle)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(handle, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer");
|
||||
ESP_RETURN_ON_FALSE(handle->del, ESP_ERR_NOT_SUPPORTED, TAG, "controller driver function not supported");
|
||||
|
@ -87,7 +87,7 @@ esp_err_t esp_cam_ctlr_receive(esp_cam_ctlr_handle_t handle, esp_cam_ctlr_trans_
|
||||
* - ESP_ERR_INVALID_ARG: Invalid argument
|
||||
* - ESP_ERR_INVALID_STATE: Invalid state
|
||||
*/
|
||||
esp_err_t esp_cam_del_ctlr(esp_cam_ctlr_handle_t handle);
|
||||
esp_err_t esp_cam_ctlr_del(esp_cam_ctlr_handle_t handle);
|
||||
|
||||
/**
|
||||
* @brief Register ESP CAM controller event callbacks
|
||||
|
@ -32,7 +32,7 @@ TEST_CASE("TEST CSI driver allocation", "[csi]")
|
||||
TEST_ESP_OK(esp_cam_ctlr_get_frame_buffer_len(handle, &bk_buffer_len));
|
||||
TEST_ASSERT_NOT_NULL(bk_buffer);
|
||||
TEST_ASSERT_EQUAL((csi_config.h_res * csi_config.v_res * 2), bk_buffer_len); // out type RGB565 using 2 byte / pixel
|
||||
TEST_ESP_OK(esp_cam_del_ctlr(handle));
|
||||
TEST_ESP_OK(esp_cam_ctlr_del(handle));
|
||||
}
|
||||
|
||||
TEST_CASE("TEST CSI driver no backup buffer usage", "[csi]")
|
||||
@ -59,5 +59,5 @@ TEST_CASE("TEST CSI driver no backup buffer usage", "[csi]")
|
||||
TEST_ESP_ERR(ESP_ERR_INVALID_STATE, esp_cam_ctlr_get_frame_buffer_len(handle, &bk_buffer_len));
|
||||
TEST_ASSERT_NULL(bk_buffer);
|
||||
TEST_ASSERT_EQUAL(0, bk_buffer_len);
|
||||
TEST_ESP_OK(esp_cam_del_ctlr(handle));
|
||||
TEST_ESP_OK(esp_cam_ctlr_del(handle));
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@ -13,20 +13,29 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define GPIO_ETM_EVENT_EDGE_TYPES 3 /*!< GPIO ETM edge events are POS/NEG/ANY */
|
||||
#define GPIO_ETM_TASK_ACTION_TYPES 3 /*!< GPIO ETM action tasks are SET/CLEAR/TOGGLE */
|
||||
|
||||
/**
|
||||
* @brief GPIO edges that can be used as ETM event
|
||||
*/
|
||||
typedef enum {
|
||||
GPIO_ETM_EVENT_EDGE_POS, /*!< A rising edge on the GPIO will generate an ETM event signal */
|
||||
GPIO_ETM_EVENT_EDGE_NEG, /*!< A falling edge on the GPIO will generate an ETM event signal */
|
||||
GPIO_ETM_EVENT_EDGE_ANY, /*!< Any edge on the GPIO can generate an ETM event signal */
|
||||
GPIO_ETM_EVENT_EDGE_POS = 1, /*!< A rising edge on the GPIO will generate an ETM event signal */
|
||||
GPIO_ETM_EVENT_EDGE_NEG, /*!< A falling edge on the GPIO will generate an ETM event signal */
|
||||
GPIO_ETM_EVENT_EDGE_ANY, /*!< Any edge on the GPIO can generate an ETM event signal */
|
||||
} gpio_etm_event_edge_t;
|
||||
|
||||
/**
|
||||
* @brief GPIO ETM event configuration
|
||||
*
|
||||
* If more than one kind of ETM edge event want to be triggered on the same GPIO pin, you can configure them together.
|
||||
* It helps to save GPIO ETM event channel resources for other GPIOs.
|
||||
*/
|
||||
typedef struct {
|
||||
gpio_etm_event_edge_t edge; /*!< Which kind of edge can trigger the ETM event module */
|
||||
union {
|
||||
gpio_etm_event_edge_t edge; /*!< Which kind of edge can trigger the ETM event module */
|
||||
gpio_etm_event_edge_t edges[GPIO_ETM_EVENT_EDGE_TYPES]; /*!< Array of kinds of edges to trigger the ETM event module on the same GPIO */
|
||||
};
|
||||
} gpio_etm_event_config_t;
|
||||
|
||||
/**
|
||||
@ -34,9 +43,11 @@ typedef struct {
|
||||
*
|
||||
* @note The created ETM event object can be deleted later by calling `esp_etm_del_event`
|
||||
* @note The newly created ETM event object is not bind to any GPIO, you need to call `gpio_etm_event_bind_gpio` to bind the wanted GPIO
|
||||
* @note Every success call to this function will acquire a free GPIO ETM event channel
|
||||
*
|
||||
* @param[in] config GPIO ETM event configuration
|
||||
* @param[out] ret_event Returned ETM event handle
|
||||
* @param[out] ... Other returned ETM event handles if any (the order of the returned event handles is aligned with the array order in field `edges` in `gpio_etm_event_config_t`)
|
||||
* @return
|
||||
* - ESP_OK: Create ETM event successfully
|
||||
* - ESP_ERR_INVALID_ARG: Create ETM event failed because of invalid argument
|
||||
@ -44,7 +55,7 @@ typedef struct {
|
||||
* - ESP_ERR_NOT_FOUND: Create ETM event failed because all events are used up and no more free one
|
||||
* - ESP_FAIL: Create ETM event failed because of other reasons
|
||||
*/
|
||||
esp_err_t gpio_new_etm_event(const gpio_etm_event_config_t *config, esp_etm_event_handle_t *ret_event);
|
||||
esp_err_t gpio_new_etm_event(const gpio_etm_event_config_t *config, esp_etm_event_handle_t *ret_event, ...);
|
||||
|
||||
/**
|
||||
* @brief Bind the GPIO with the ETM event
|
||||
@ -65,16 +76,21 @@ esp_err_t gpio_etm_event_bind_gpio(esp_etm_event_handle_t event, int gpio_num);
|
||||
* @brief GPIO actions that can be taken by the ETM task
|
||||
*/
|
||||
typedef enum {
|
||||
GPIO_ETM_TASK_ACTION_SET, /*!< Set the GPIO level to high */
|
||||
GPIO_ETM_TASK_ACTION_CLR, /*!< Clear the GPIO level to low */
|
||||
GPIO_ETM_TASK_ACTION_TOG, /*!< Toggle the GPIO level */
|
||||
GPIO_ETM_TASK_ACTION_SET = 1, /*!< Set the GPIO level to high */
|
||||
GPIO_ETM_TASK_ACTION_CLR, /*!< Clear the GPIO level to low */
|
||||
GPIO_ETM_TASK_ACTION_TOG, /*!< Toggle the GPIO level */
|
||||
} gpio_etm_task_action_t;
|
||||
|
||||
/**
|
||||
* @brief GPIO ETM task configuration
|
||||
*
|
||||
* If multiple actions wants to be added to the same GPIO pin, you have to configure all the GPIO ETM tasks together.
|
||||
*/
|
||||
typedef struct {
|
||||
gpio_etm_task_action_t action; /*!< Which action to take by the ETM task module */
|
||||
union {
|
||||
gpio_etm_task_action_t action; /*!< Action to take by the ETM task module */
|
||||
gpio_etm_task_action_t actions[GPIO_ETM_TASK_ACTION_TYPES]; /*!< Array of actions to take by the ETM task module on the same GPIO */
|
||||
};
|
||||
} gpio_etm_task_config_t;
|
||||
|
||||
/**
|
||||
@ -83,9 +99,11 @@ typedef struct {
|
||||
* @note The created ETM task object can be deleted later by calling `esp_etm_del_task`
|
||||
* @note The GPIO ETM task works like a container, a newly created ETM task object doesn't have GPIO members to be managed.
|
||||
* You need to call `gpio_etm_task_add_gpio` to put one or more GPIOs to the container.
|
||||
* @note Every success call to this function will acquire a free GPIO ETM task channel
|
||||
*
|
||||
* @param[in] config GPIO ETM task configuration
|
||||
* @param[out] ret_task Returned ETM task handle
|
||||
* @param[out] ... Other returned ETM task handles if any (the order of the returned task handles is aligned with the array order in field `actions` in `gpio_etm_task_config_t`)
|
||||
* @return
|
||||
* - ESP_OK: Create ETM task successfully
|
||||
* - ESP_ERR_INVALID_ARG: Create ETM task failed because of invalid argument
|
||||
@ -93,7 +111,7 @@ typedef struct {
|
||||
* - ESP_ERR_NOT_FOUND: Create ETM task failed because all tasks are used up and no more free one
|
||||
* - ESP_FAIL: Create ETM task failed because of other reasons
|
||||
*/
|
||||
esp_err_t gpio_new_etm_task(const gpio_etm_task_config_t *config, esp_etm_task_handle_t *ret_task);
|
||||
esp_err_t gpio_new_etm_task(const gpio_etm_task_config_t *config, esp_etm_task_handle_t *ret_task, ...);
|
||||
|
||||
/**
|
||||
* @brief Add GPIO to the ETM task.
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@ -34,19 +34,23 @@ typedef struct gpio_etm_event_t gpio_etm_event_t;
|
||||
typedef struct gpio_etm_group_t {
|
||||
portMUX_TYPE spinlock;
|
||||
gpio_etm_dev_t *dev;
|
||||
gpio_etm_task_t *tasks[SOC_GPIO_ETM_TASKS_PER_GROUP];
|
||||
gpio_etm_event_t *events[SOC_GPIO_ETM_EVENTS_PER_GROUP];
|
||||
uint8_t tasks[GPIO_LL_ETM_TASK_CHANNELS_PER_GROUP]; // Array of the acquired action masks in each GPIO ETM task channel
|
||||
uint8_t events[GPIO_LL_ETM_EVENT_CHANNELS_PER_GROUP]; // Array of the acquired event masks in each GPIO ETM event channel
|
||||
uint8_t actions[SOC_GPIO_PIN_COUNT]; // Array of the masks of the added actions to each GPIO
|
||||
uint8_t edges[GPIO_LL_ETM_EVENT_CHANNELS_PER_GROUP]; // Array of the masks of the bound event edges in each GPIO ETM event channel
|
||||
} gpio_etm_group_t;
|
||||
|
||||
struct gpio_etm_event_t {
|
||||
esp_etm_event_t base;
|
||||
int chan_id;
|
||||
gpio_etm_event_edge_t edge_id;
|
||||
gpio_etm_group_t *group;
|
||||
};
|
||||
|
||||
struct gpio_etm_task_t {
|
||||
esp_etm_task_t base;
|
||||
int chan_id;
|
||||
gpio_etm_task_action_t action_id;
|
||||
gpio_etm_group_t *group;
|
||||
size_t num_of_gpios; // record the number of GPIOs that are bound to the etm task
|
||||
};
|
||||
@ -56,81 +60,65 @@ static gpio_etm_group_t s_gpio_etm_group = {
|
||||
.spinlock = portMUX_INITIALIZER_UNLOCKED,
|
||||
};
|
||||
|
||||
static esp_err_t gpio_etm_event_register_to_group(gpio_etm_event_t *event)
|
||||
static esp_err_t gpio_etm_acquire_event_channel(uint8_t event_mask, int *chan_id)
|
||||
{
|
||||
assert(chan_id);
|
||||
gpio_etm_group_t *group = &s_gpio_etm_group;
|
||||
int chan_id = -1;
|
||||
// loop to search free one in the group
|
||||
|
||||
int free_chan_id = -1;
|
||||
// loop to search free event channel in the group
|
||||
portENTER_CRITICAL(&group->spinlock);
|
||||
for (int j = 0; j < SOC_GPIO_ETM_EVENTS_PER_GROUP; j++) {
|
||||
for (int j = 0; j < GPIO_LL_ETM_EVENT_CHANNELS_PER_GROUP; j++) {
|
||||
if (!group->events[j]) {
|
||||
chan_id = j;
|
||||
group->events[j] = event;
|
||||
free_chan_id = j;
|
||||
group->events[j] = event_mask;
|
||||
break;
|
||||
}
|
||||
}
|
||||
portEXIT_CRITICAL(&group->spinlock);
|
||||
|
||||
ESP_RETURN_ON_FALSE(chan_id != -1, ESP_ERR_NOT_FOUND, TAG, "no free event channel");
|
||||
event->group = group;
|
||||
event->chan_id = chan_id;
|
||||
ESP_RETURN_ON_FALSE(free_chan_id != -1, ESP_ERR_NOT_FOUND, TAG, "no free event channel");
|
||||
*chan_id = free_chan_id;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t gpio_etm_task_register_to_group(gpio_etm_task_t *task)
|
||||
static esp_err_t gpio_etm_release_event_channel(int chan_id, uint8_t event_mask)
|
||||
{
|
||||
gpio_etm_group_t *group = &s_gpio_etm_group;
|
||||
int chan_id = -1;
|
||||
// loop to search free one in the group
|
||||
portENTER_CRITICAL(&group->spinlock);
|
||||
for (int j = 0; j < SOC_GPIO_ETM_TASKS_PER_GROUP; j++) {
|
||||
group->events[chan_id] &= ~event_mask;
|
||||
portEXIT_CRITICAL(&group->spinlock);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t gpio_etm_acquire_task_channel(uint8_t task_mask, int *chan_id)
|
||||
{
|
||||
assert(chan_id);
|
||||
gpio_etm_group_t *group = &s_gpio_etm_group;
|
||||
|
||||
int free_chan_id = -1;
|
||||
// loop to search free task channel in the group
|
||||
portENTER_CRITICAL(&group->spinlock);
|
||||
for (int j = 0; j < GPIO_LL_ETM_TASK_CHANNELS_PER_GROUP; j++) {
|
||||
if (!group->tasks[j]) {
|
||||
chan_id = j;
|
||||
group->tasks[j] = task;
|
||||
free_chan_id = j;
|
||||
group->tasks[j] = task_mask;
|
||||
break;
|
||||
}
|
||||
}
|
||||
portEXIT_CRITICAL(&group->spinlock);
|
||||
|
||||
ESP_RETURN_ON_FALSE(chan_id != -1, ESP_ERR_NOT_FOUND, TAG, "no free task channel");
|
||||
task->group = group;
|
||||
task->chan_id = chan_id;
|
||||
ESP_RETURN_ON_FALSE(free_chan_id != -1, ESP_ERR_NOT_FOUND, TAG, "no free task channel");
|
||||
*chan_id = free_chan_id;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static void gpio_etm_event_unregister_from_group(gpio_etm_event_t *event)
|
||||
static esp_err_t gpio_etm_release_task_channel(int chan_id, uint8_t task_mask)
|
||||
{
|
||||
gpio_etm_group_t *group = event->group;
|
||||
int chan_id = event->chan_id;
|
||||
gpio_etm_group_t *group = &s_gpio_etm_group;
|
||||
portENTER_CRITICAL(&group->spinlock);
|
||||
group->events[chan_id] = NULL;
|
||||
group->tasks[chan_id] &= ~task_mask;
|
||||
portEXIT_CRITICAL(&group->spinlock);
|
||||
}
|
||||
|
||||
static void gpio_etm_task_unregister_from_group(gpio_etm_task_t *task)
|
||||
{
|
||||
gpio_etm_group_t *group = task->group;
|
||||
int chan_id = task->chan_id;
|
||||
portENTER_CRITICAL(&group->spinlock);
|
||||
group->tasks[chan_id] = NULL;
|
||||
portEXIT_CRITICAL(&group->spinlock);
|
||||
}
|
||||
|
||||
static esp_err_t gpio_etm_event_destroy(gpio_etm_event_t *event)
|
||||
{
|
||||
if (event->group) {
|
||||
gpio_etm_event_unregister_from_group(event);
|
||||
}
|
||||
free(event);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t gpio_etm_task_destroy(gpio_etm_task_t *task)
|
||||
{
|
||||
if (task->group) {
|
||||
gpio_etm_task_unregister_from_group(task);
|
||||
}
|
||||
free(task);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
@ -138,9 +126,16 @@ static esp_err_t gpio_del_etm_event(esp_etm_event_t *event)
|
||||
{
|
||||
gpio_etm_event_t *gpio_event = __containerof(event, gpio_etm_event_t, base);
|
||||
gpio_etm_group_t *group = gpio_event->group;
|
||||
// disable event channel
|
||||
gpio_ll_etm_enable_event_channel(group->dev, gpio_event->chan_id, false);
|
||||
gpio_etm_event_destroy(gpio_event);
|
||||
// unbind it from the GPIO and check if the GPIO ETM event channel can be disabled
|
||||
portENTER_CRITICAL(&group->spinlock);
|
||||
group->edges[gpio_event->chan_id] &= ~(1 << gpio_event->edge_id);
|
||||
if (!group->edges[gpio_event->chan_id]) {
|
||||
gpio_ll_etm_enable_event_channel(group->dev, gpio_event->chan_id, false);
|
||||
}
|
||||
portEXIT_CRITICAL(&group->spinlock);
|
||||
|
||||
gpio_etm_release_event_channel(gpio_event->chan_id, 1 << gpio_event->edge_id);
|
||||
free(gpio_event);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
@ -149,95 +144,192 @@ static esp_err_t gpio_del_etm_task(esp_etm_task_t *task)
|
||||
gpio_etm_task_t *gpio_task = __containerof(task, gpio_etm_task_t, base);
|
||||
// make sure user has called `gpio_etm_task_rm_gpio` to clean the etm task channel
|
||||
ESP_RETURN_ON_FALSE(gpio_task->num_of_gpios == 0, ESP_ERR_INVALID_STATE, TAG, "some GPIO till bounded to the etm task");
|
||||
gpio_etm_task_destroy(gpio_task);
|
||||
gpio_etm_release_task_channel(gpio_task->chan_id, 1 << gpio_task->action_id);
|
||||
free(gpio_task);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t gpio_new_etm_event(const gpio_etm_event_config_t *config, esp_etm_event_handle_t *ret_event)
|
||||
esp_err_t gpio_new_etm_event(const gpio_etm_event_config_t *config, esp_etm_event_handle_t *ret_event, ...)
|
||||
{
|
||||
#if CONFIG_ETM_ENABLE_DEBUG_LOG
|
||||
esp_log_level_set(TAG, ESP_LOG_DEBUG);
|
||||
#endif
|
||||
esp_err_t ret = ESP_OK;
|
||||
gpio_etm_event_t *event = NULL;
|
||||
ESP_GOTO_ON_FALSE(config && ret_event, ESP_ERR_INVALID_ARG, err, TAG, "invalid argument");
|
||||
int chan_id = -1;
|
||||
uint8_t event_mask = 0;
|
||||
esp_etm_event_handle_t *ret_event_itor = ret_event;
|
||||
va_list args;
|
||||
ESP_RETURN_ON_FALSE(config && ret_event, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
|
||||
for (int i = 0; i < GPIO_ETM_EVENT_EDGE_TYPES; i++) {
|
||||
if (config->edges[i]) {
|
||||
uint8_t msk = (1 << config->edges[i]);
|
||||
ESP_RETURN_ON_FALSE(!(msk & event_mask), ESP_ERR_INVALID_ARG, TAG, "no identical edge event allowed in one call");
|
||||
event_mask |= msk;
|
||||
}
|
||||
}
|
||||
ESP_RETURN_ON_FALSE(event_mask, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
|
||||
uint32_t event_num = __builtin_popcount(event_mask);
|
||||
gpio_etm_event_t *events[event_num];
|
||||
|
||||
event = heap_caps_calloc(1, sizeof(gpio_etm_event_t), ETM_MEM_ALLOC_CAPS);
|
||||
ESP_GOTO_ON_FALSE(event, ESP_ERR_NO_MEM, err, TAG, "no mem for event channel");
|
||||
// register the event channel to the group
|
||||
ESP_GOTO_ON_ERROR(gpio_etm_event_register_to_group(event), err, TAG, "register event channel to group failed");
|
||||
int chan_id = event->chan_id;
|
||||
|
||||
uint32_t event_id = 0;
|
||||
switch (config->edge) {
|
||||
case GPIO_ETM_EVENT_EDGE_ANY:
|
||||
event_id = GPIO_LL_ETM_EVENT_ID_ANY_EDGE(chan_id);
|
||||
break;
|
||||
case GPIO_ETM_EVENT_EDGE_POS:
|
||||
event_id = GPIO_LL_ETM_EVENT_ID_POS_EDGE(chan_id);
|
||||
break;
|
||||
case GPIO_ETM_EVENT_EDGE_NEG:
|
||||
event_id = GPIO_LL_ETM_EVENT_ID_NEG_EDGE(chan_id);
|
||||
break;
|
||||
default:
|
||||
ESP_GOTO_ON_FALSE(false, ESP_ERR_INVALID_ARG, err, TAG, "invalid edge");
|
||||
for (int i = 0; i < event_num; i++) {
|
||||
events[i] = (gpio_etm_event_t *)heap_caps_calloc(1, sizeof(gpio_etm_event_t), ETM_MEM_ALLOC_CAPS);
|
||||
ESP_GOTO_ON_FALSE(events[i], ESP_ERR_NO_MEM, err, TAG, "no mem for event channel(s)");
|
||||
}
|
||||
|
||||
event->base.del = gpio_del_etm_event;
|
||||
event->base.event_id = event_id;
|
||||
event->base.trig_periph = ETM_TRIG_PERIPH_GPIO;
|
||||
ESP_LOGD(TAG, "new event @%p, event_id=%"PRIu32", chan_id=%d", event, event_id, chan_id);
|
||||
*ret_event = &event->base;
|
||||
// register the event channel to the group
|
||||
ESP_GOTO_ON_ERROR(gpio_etm_acquire_event_channel(event_mask, &chan_id), err, TAG, "register event channel to group failed");
|
||||
|
||||
bool no_avail_ret_arg = false;
|
||||
va_start(args, ret_event);
|
||||
for (int i = 0, j = 0; i < event_num; i++, j++) {
|
||||
if (!ret_event_itor) {
|
||||
no_avail_ret_arg = true;
|
||||
break;
|
||||
}
|
||||
// assign to the ret_event handles in the configuration order
|
||||
gpio_etm_event_edge_t event_edge;
|
||||
do {
|
||||
event_edge = config->edges[j];
|
||||
} while (!event_edge && ++j);
|
||||
uint32_t event_id = 0;
|
||||
switch (event_edge) {
|
||||
case GPIO_ETM_EVENT_EDGE_ANY:
|
||||
event_id = GPIO_LL_ETM_EVENT_ID_ANY_EDGE(chan_id);
|
||||
break;
|
||||
case GPIO_ETM_EVENT_EDGE_POS:
|
||||
event_id = GPIO_LL_ETM_EVENT_ID_POS_EDGE(chan_id);
|
||||
break;
|
||||
case GPIO_ETM_EVENT_EDGE_NEG:
|
||||
event_id = GPIO_LL_ETM_EVENT_ID_NEG_EDGE(chan_id);
|
||||
break;
|
||||
default:
|
||||
va_end(args);
|
||||
ESP_GOTO_ON_FALSE(false, ESP_ERR_INVALID_ARG, err, TAG, "invalid edge");
|
||||
}
|
||||
|
||||
gpio_etm_event_t *event = events[i];
|
||||
event->base.del = gpio_del_etm_event;
|
||||
event->base.event_id = event_id;
|
||||
event->base.trig_periph = ETM_TRIG_PERIPH_GPIO;
|
||||
event->group = &s_gpio_etm_group;
|
||||
event->chan_id = chan_id;
|
||||
event->edge_id = event_edge;
|
||||
ESP_LOGD(TAG, "new event @%p, event_id=%"PRIu32", chan_id=%d", event, event_id, chan_id);
|
||||
*ret_event_itor = &event->base;
|
||||
ret_event_itor = va_arg(args, esp_etm_event_handle_t *);
|
||||
}
|
||||
va_end(args);
|
||||
ESP_GOTO_ON_FALSE(!no_avail_ret_arg, ESP_ERR_INVALID_ARG, err, TAG, "mismatch number of events with number of pointers to store event handles");
|
||||
return ESP_OK;
|
||||
|
||||
err:
|
||||
if (event) {
|
||||
gpio_etm_event_destroy(event);
|
||||
if (chan_id != -1) {
|
||||
gpio_etm_release_event_channel(chan_id, event_mask);
|
||||
}
|
||||
for (int i = 0; i < event_num; i++) {
|
||||
if (events[i]) {
|
||||
free(events[i]);
|
||||
}
|
||||
}
|
||||
ret_event_itor = ret_event;
|
||||
va_start(args, ret_event);
|
||||
while (ret_event_itor) {
|
||||
*ret_event_itor = NULL;
|
||||
ret_event_itor = va_arg(args, esp_etm_event_handle_t *);
|
||||
}
|
||||
va_end(args);
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t gpio_new_etm_task(const gpio_etm_task_config_t *config, esp_etm_task_handle_t *ret_task)
|
||||
esp_err_t gpio_new_etm_task(const gpio_etm_task_config_t *config, esp_etm_task_handle_t *ret_task, ...)
|
||||
{
|
||||
#if CONFIG_ETM_ENABLE_DEBUG_LOG
|
||||
esp_log_level_set(TAG, ESP_LOG_DEBUG);
|
||||
#endif
|
||||
esp_err_t ret = ESP_OK;
|
||||
gpio_etm_task_t *task = NULL;
|
||||
ESP_GOTO_ON_FALSE(config && ret_task, ESP_ERR_INVALID_ARG, err, TAG, "invalid argument");
|
||||
int chan_id = -1;
|
||||
uint8_t task_mask = 0;
|
||||
esp_etm_task_handle_t *ret_task_itor = ret_task;
|
||||
va_list args;
|
||||
ESP_RETURN_ON_FALSE(config && ret_task, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
|
||||
for (int i = 0; i < GPIO_ETM_TASK_ACTION_TYPES; i++) {
|
||||
if (config->actions[i]) {
|
||||
uint8_t msk = (1 << config->actions[i]);
|
||||
ESP_RETURN_ON_FALSE(!(msk & task_mask), ESP_ERR_INVALID_ARG, TAG, "no identical action allowed in one call");
|
||||
task_mask |= msk;
|
||||
}
|
||||
}
|
||||
ESP_RETURN_ON_FALSE(task_mask, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
|
||||
uint32_t task_num = __builtin_popcount(task_mask);
|
||||
gpio_etm_task_t *tasks[task_num];
|
||||
|
||||
task = heap_caps_calloc(1, sizeof(gpio_etm_task_t), ETM_MEM_ALLOC_CAPS);
|
||||
ESP_GOTO_ON_FALSE(task, ESP_ERR_NO_MEM, err, TAG, "no mem for task channel");
|
||||
// register the task channel to the group
|
||||
ESP_GOTO_ON_ERROR(gpio_etm_task_register_to_group(task), err, TAG, "register task channel to group failed");
|
||||
int chan_id = task->chan_id;
|
||||
|
||||
uint32_t task_id = 0;
|
||||
switch (config->action) {
|
||||
case GPIO_ETM_TASK_ACTION_SET:
|
||||
task_id = GPIO_LL_ETM_TASK_ID_SET(chan_id);
|
||||
break;
|
||||
case GPIO_ETM_TASK_ACTION_CLR:
|
||||
task_id = GPIO_LL_ETM_TASK_ID_CLR(chan_id);
|
||||
break;
|
||||
case GPIO_ETM_TASK_ACTION_TOG:
|
||||
task_id = GPIO_LL_ETM_TASK_ID_TOG(chan_id);
|
||||
break;
|
||||
default:
|
||||
ESP_GOTO_ON_FALSE(false, ESP_ERR_INVALID_ARG, err, TAG, "invalid action");
|
||||
for (int i = 0; i < task_num; i++) {
|
||||
tasks[i] = (gpio_etm_task_t *)heap_caps_calloc(1, sizeof(gpio_etm_task_t), ETM_MEM_ALLOC_CAPS);
|
||||
ESP_GOTO_ON_FALSE(tasks[i], ESP_ERR_NO_MEM, err, TAG, "no mem for task channel(s)");
|
||||
}
|
||||
|
||||
task->base.del = gpio_del_etm_task;
|
||||
task->base.task_id = task_id;
|
||||
task->base.trig_periph = ETM_TRIG_PERIPH_GPIO;
|
||||
ESP_LOGD(TAG, "new task @%p, task_id=%"PRIu32", chan_id=%d", task, task_id, chan_id);
|
||||
*ret_task = &task->base;
|
||||
// register the task channel to the group
|
||||
ESP_GOTO_ON_ERROR(gpio_etm_acquire_task_channel(task_mask, &chan_id), err, TAG, "register task channel to group failed");
|
||||
|
||||
bool no_avail_ret_arg = false;
|
||||
va_start(args, ret_task);
|
||||
for (int i = 0, j = 0; i < task_num; i++, j++) {
|
||||
if (!ret_task_itor) {
|
||||
no_avail_ret_arg = true;
|
||||
break;
|
||||
}
|
||||
// assign to the ret_task handles in the configuration order
|
||||
gpio_etm_task_action_t action;
|
||||
do {
|
||||
action = config->actions[i];
|
||||
} while (!action && ++j);
|
||||
uint32_t task_id = 0;
|
||||
switch (action) {
|
||||
case GPIO_ETM_TASK_ACTION_SET:
|
||||
task_id = GPIO_LL_ETM_TASK_ID_SET(chan_id);
|
||||
break;
|
||||
case GPIO_ETM_TASK_ACTION_CLR:
|
||||
task_id = GPIO_LL_ETM_TASK_ID_CLR(chan_id);
|
||||
break;
|
||||
case GPIO_ETM_TASK_ACTION_TOG:
|
||||
task_id = GPIO_LL_ETM_TASK_ID_TOG(chan_id);
|
||||
break;
|
||||
default:
|
||||
va_end(args);
|
||||
ESP_GOTO_ON_FALSE(false, ESP_ERR_INVALID_ARG, err, TAG, "invalid action");
|
||||
}
|
||||
|
||||
gpio_etm_task_t *task = tasks[i];
|
||||
task->base.del = gpio_del_etm_task;
|
||||
task->base.task_id = task_id;
|
||||
task->base.trig_periph = ETM_TRIG_PERIPH_GPIO;
|
||||
task->group = &s_gpio_etm_group;
|
||||
task->chan_id = chan_id;
|
||||
task->action_id = action;
|
||||
ESP_LOGD(TAG, "new task @%p, task_id=%"PRIu32", gpio_etm_task_chan_id=%d", task, task_id, chan_id);
|
||||
*ret_task_itor = &task->base;
|
||||
ret_task_itor = va_arg(args, esp_etm_task_handle_t *);
|
||||
}
|
||||
va_end(args);
|
||||
ESP_GOTO_ON_FALSE(!no_avail_ret_arg, ESP_ERR_INVALID_ARG, err, TAG, "mismatch number of tasks with number of pointers to store task handles");
|
||||
return ESP_OK;
|
||||
|
||||
err:
|
||||
if (task) {
|
||||
gpio_etm_task_destroy(task);
|
||||
if (chan_id != -1) {
|
||||
gpio_etm_release_task_channel(chan_id, task_mask);
|
||||
}
|
||||
for (int i = 0; i < task_num; i++) {
|
||||
if (tasks[i]) {
|
||||
free(tasks[i]);
|
||||
}
|
||||
}
|
||||
ret_task_itor = ret_task;
|
||||
va_start(args, ret_task);
|
||||
while (ret_task_itor) {
|
||||
*ret_task_itor = NULL;
|
||||
ret_task_itor = va_arg(args, esp_etm_task_handle_t *);
|
||||
}
|
||||
va_end(args);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -248,12 +340,27 @@ esp_err_t gpio_etm_event_bind_gpio(esp_etm_event_handle_t event, int gpio_num)
|
||||
ESP_RETURN_ON_FALSE(GPIO_IS_VALID_GPIO(gpio_num), ESP_ERR_INVALID_ARG, TAG, "gpio is not input capable");
|
||||
gpio_etm_event_t *gpio_event = __containerof(event, gpio_etm_event_t, base);
|
||||
gpio_etm_group_t *group = gpio_event->group;
|
||||
// disable gpio etm event channel first
|
||||
gpio_ll_etm_enable_event_channel(group->dev, gpio_event->chan_id, false);
|
||||
// then set the gpio number
|
||||
gpio_ll_etm_event_channel_set_gpio(group->dev, gpio_event->chan_id, gpio_num);
|
||||
// enable gpio etm event channel again
|
||||
gpio_ll_etm_enable_event_channel(group->dev, gpio_event->chan_id, true);
|
||||
|
||||
bool allowed = true;
|
||||
portENTER_CRITICAL(&group->spinlock);
|
||||
// check if the GPIO ETM event channel where the new event belongs to has previously been bound to another GPIO
|
||||
// one GPIO ETM event channel can only be bound to one GPIO
|
||||
if (group->edges[gpio_event->chan_id]) {
|
||||
if (gpio_ll_etm_event_channel_get_gpio(group->dev, gpio_event->chan_id) != gpio_num) {
|
||||
allowed = false;
|
||||
}
|
||||
} else {
|
||||
// set the GPIO number
|
||||
gpio_ll_etm_event_channel_set_gpio(group->dev, gpio_event->chan_id, gpio_num);
|
||||
// enable GPIO ETM event channel
|
||||
gpio_ll_etm_enable_event_channel(group->dev, gpio_event->chan_id, true);
|
||||
}
|
||||
|
||||
if (allowed) {
|
||||
group->edges[gpio_event->chan_id] |= (1 << gpio_event->edge_id);
|
||||
}
|
||||
portEXIT_CRITICAL(&group->spinlock);
|
||||
ESP_RETURN_ON_FALSE(allowed, ESP_ERR_INVALID_ARG, TAG, "the GPIO ETM event channel where the event belongs to has already been bound to another GPIO");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
@ -264,19 +371,28 @@ esp_err_t gpio_etm_task_add_gpio(esp_etm_task_handle_t task, int gpio_num)
|
||||
ESP_RETURN_ON_FALSE(GPIO_IS_VALID_OUTPUT_GPIO(gpio_num), ESP_ERR_INVALID_ARG, TAG, "gpio is not output capable");
|
||||
gpio_etm_task_t *gpio_task = __containerof(task, gpio_etm_task_t, base);
|
||||
gpio_etm_group_t *group = gpio_task->group;
|
||||
bool gpio_not_enabled = true;
|
||||
|
||||
bool allowed = true;
|
||||
// use spinlock as this function may be called with different task object in different threads
|
||||
// and the gpio_num might reside in the same register
|
||||
portENTER_CRITICAL(&group->spinlock);
|
||||
// check if the gpio has been enabled
|
||||
if (!gpio_ll_etm_is_task_gpio_enabled(group->dev, gpio_num)) {
|
||||
// check if the new task is compatible with the tasks that has previously been added to the GPIO
|
||||
// the tasks have to be from the same GPIO ETM task channel
|
||||
if (group->actions[gpio_num]) {
|
||||
if (gpio_ll_etm_gpio_get_task_channel(group->dev, gpio_num) != gpio_task->chan_id) {
|
||||
allowed = false;
|
||||
}
|
||||
} else {
|
||||
// first action added to the GPIO
|
||||
gpio_ll_etm_gpio_set_task_channel(group->dev, gpio_num, gpio_task->chan_id);
|
||||
gpio_ll_etm_enable_task_gpio(group->dev, gpio_num, true);
|
||||
} else {
|
||||
gpio_not_enabled = false;
|
||||
}
|
||||
|
||||
if (allowed) {
|
||||
group->actions[gpio_num] |= (1 << gpio_task->action_id);
|
||||
}
|
||||
portEXIT_CRITICAL(&group->spinlock);
|
||||
ESP_RETURN_ON_FALSE(gpio_not_enabled, ESP_ERR_INVALID_STATE, TAG, "gpio already enabled by other task channel");
|
||||
ESP_RETURN_ON_FALSE(allowed, ESP_ERR_INVALID_ARG, TAG, "the task does not belong to the GPIO ETM task channel that the GPIO has already binded to");
|
||||
gpio_task->num_of_gpios++;
|
||||
return ESP_OK;
|
||||
}
|
||||
@ -287,19 +403,24 @@ esp_err_t gpio_etm_task_rm_gpio(esp_etm_task_handle_t task, int gpio_num)
|
||||
ESP_RETURN_ON_FALSE(GPIO_IS_VALID_OUTPUT_GPIO(gpio_num), ESP_ERR_INVALID_ARG, TAG, "gpio is not output capable");
|
||||
gpio_etm_task_t *gpio_task = __containerof(task, gpio_etm_task_t, base);
|
||||
gpio_etm_group_t *group = gpio_task->group;
|
||||
bool gpio_enabled_by_this_task = true;
|
||||
|
||||
bool allowed = true;
|
||||
// use spinlock as this function may be called with different task object in different threads
|
||||
// and the gpio_num might reside in the same register
|
||||
portENTER_CRITICAL(&group->spinlock);
|
||||
// check if the gpio is managed by this etm task channel
|
||||
if (gpio_ll_etm_is_task_gpio_enabled(group->dev, gpio_num) &&
|
||||
if ((group->actions[gpio_num] & (1 << gpio_task->action_id)) &&
|
||||
gpio_ll_etm_is_task_gpio_enabled(group->dev, gpio_num) &&
|
||||
(gpio_ll_etm_gpio_get_task_channel(group->dev, gpio_num) == gpio_task->chan_id)) {
|
||||
gpio_ll_etm_enable_task_gpio(group->dev, gpio_num, false);
|
||||
group->actions[gpio_num] &= ~(1 << gpio_task->action_id);
|
||||
if (!group->actions[gpio_num]) {
|
||||
// all actions removed from the GPIO
|
||||
gpio_ll_etm_enable_task_gpio(group->dev, gpio_num, false);
|
||||
}
|
||||
} else {
|
||||
gpio_enabled_by_this_task = false;
|
||||
allowed = false;
|
||||
}
|
||||
portEXIT_CRITICAL(&group->spinlock);
|
||||
ESP_RETURN_ON_FALSE(gpio_enabled_by_this_task, ESP_ERR_INVALID_STATE, TAG, "gpio is not enabled by this task channel");
|
||||
ESP_RETURN_ON_FALSE(allowed, ESP_ERR_INVALID_ARG, TAG, "the task was not added to the GPIO");
|
||||
gpio_task->num_of_gpios--;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
@ -3,10 +3,11 @@ set(srcs)
|
||||
set(public_include "include")
|
||||
|
||||
if(CONFIG_SOC_ISP_SUPPORTED)
|
||||
list(APPEND srcs "src/isp.c"
|
||||
list(APPEND srcs "src/isp_core.c"
|
||||
"src/isp_af.c")
|
||||
endif()
|
||||
|
||||
idf_component_register(SRCS ${srcs}
|
||||
INCLUDE_DIRS ${public_include}
|
||||
PRIV_REQUIRES esp_driver_gpio
|
||||
)
|
||||
|
@ -4,84 +4,12 @@
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief ISP peripheral contains many submodules, whose drivers are scattered in different header files.
|
||||
* This header file serves as a prelude, contains every thing that is needed to work with the ISP peripheral.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "esp_err.h"
|
||||
#include "driver/isp_types.h"
|
||||
#include "driver/isp_core.h"
|
||||
#include "driver/isp_af.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief ISP configurations
|
||||
*/
|
||||
typedef struct {
|
||||
isp_clk_src_t clk_src; ///< Clock source
|
||||
uint32_t clk_hz; ///< Clock frequency in Hz, suggest twice higher than cam sensor speed
|
||||
isp_input_data_source_t input_data_source; ///< Input data source
|
||||
isp_color_t input_data_color_type; ///< Input color type
|
||||
isp_color_t output_data_color_type; ///< Output color type
|
||||
bool has_line_start_packet; ///< Enable line start packet
|
||||
bool has_line_end_packet; ///< Enable line end packet
|
||||
uint32_t h_res; ///< Input horizontal resolution, i.e. the number of pixels in a line
|
||||
uint32_t v_res; ///< Input vertical resolution, i.e. the number of lines in a frame
|
||||
} esp_isp_processor_cfg_t;
|
||||
|
||||
/**
|
||||
* @brief New an ISP processor
|
||||
*
|
||||
* @param[in] proc_config Pointer to ISP config. Refer to ``esp_isp_processor_cfg_t``.
|
||||
* @param[out] ret_proc Processor handle
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK On success
|
||||
* - ESP_ERR_INVALID_ARG If the combination of arguments is invalid.
|
||||
* - ESP_ERR_NOT_FOUND No free interrupt found with the specified flags
|
||||
* - ESP_ERR_NOT_SUPPORTED Not supported mode
|
||||
* - ESP_ERR_NO_MEM If out of memory
|
||||
*/
|
||||
esp_err_t esp_isp_new_processor(const esp_isp_processor_cfg_t *proc_config, isp_proc_handle_t *ret_proc);
|
||||
|
||||
/**
|
||||
* @brief Delete an ISP processor
|
||||
*
|
||||
* @param[in] proc Processor handle
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK On success
|
||||
* - ESP_ERR_INVALID_ARG If the combination of arguments is invalid.
|
||||
* - ESP_ERR_INVALID_STATE Driver state is invalid.
|
||||
*/
|
||||
esp_err_t esp_isp_del_processor(isp_proc_handle_t proc);
|
||||
|
||||
/**
|
||||
* @brief Enable an ISP processor
|
||||
*
|
||||
* @param[in] proc Processor handle
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK On success
|
||||
* - ESP_ERR_INVALID_ARG If the combination of arguments is invalid.
|
||||
* - ESP_ERR_INVALID_STATE Driver state is invalid.
|
||||
*/
|
||||
esp_err_t esp_isp_enable(isp_proc_handle_t proc);
|
||||
|
||||
/**
|
||||
* @brief Disable an ISP processor
|
||||
*
|
||||
* @param[in] proc Processor handle
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK On success
|
||||
* - ESP_ERR_INVALID_ARG If the combination of arguments is invalid.
|
||||
* - ESP_ERR_INVALID_STATE Driver state is invalid.
|
||||
*/
|
||||
esp_err_t esp_isp_disable(isp_proc_handle_t proc);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -10,8 +10,6 @@
|
||||
#include <stdbool.h>
|
||||
#include "esp_err.h"
|
||||
#include "driver/isp_types.h"
|
||||
#include "driver/isp.h"
|
||||
#include "soc/soc_caps.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@ -21,10 +19,9 @@ extern "C" {
|
||||
* @brief AF controller config
|
||||
*/
|
||||
typedef struct {
|
||||
#if SOC_ISP_AF_WINDOW_NUMS
|
||||
isp_af_window_t window[SOC_ISP_AF_WINDOW_NUMS]; ///< AF window settings
|
||||
#endif
|
||||
isp_af_window_t window[ISP_AF_WINDOW_NUM]; ///< The sampling windows of AF
|
||||
int edge_thresh; ///< Edge threshold, definition higher than this value will be counted as a valid pixel for calculating AF result
|
||||
int intr_priority; ///< The interrupt priority, range 0~7, if set to 0, the driver will try to allocate an interrupt with a relative low priority (1,2,3) otherwise the larger the higher, 7 is NMI
|
||||
} esp_isp_af_config_t;
|
||||
|
||||
/**
|
||||
@ -80,17 +77,57 @@ esp_err_t esp_isp_af_controller_enable(isp_af_ctrlr_t af_ctrlr);
|
||||
esp_err_t esp_isp_af_controller_disable(isp_af_ctrlr_t af_ctrlr);
|
||||
|
||||
/**
|
||||
* @brief Get AF result
|
||||
* @brief Trigger AF luminance and definition statistics for one time and get the result
|
||||
* @note This function is a synchronous and block function,
|
||||
* it only returns when AF luminance and definition statistics is done or timeout.
|
||||
* It's a simple method to get the result directly for one time.
|
||||
*
|
||||
* @param[in] af_ctrlr AF controller handle
|
||||
* @param[out] out_res AF result
|
||||
* @param[in] af_ctrlr AF controller handle
|
||||
* @param[in] timeout_ms Timeout in millisecond
|
||||
* - timeout_ms < 0: Won't return until finished
|
||||
* - timeout_ms = 0: No timeout, trigger one time statistics and return immediately,
|
||||
* in this case, the result won't be assigned in this function,
|
||||
* but you can get the result in the callback `esp_isp_af_env_detector_evt_cbs_t::on_env_statistics_done`
|
||||
* - timeout_ms > 0: Wait for specified milliseconds, if not finished, then return timeout error
|
||||
* @param[out] out_res AF luminance and definition statistics result, can be NULL if `timeout_ms = 0`
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK On success
|
||||
* - ESP_ERR_TIMEOUT If the waiting time exceeds the specified timeout.
|
||||
* - ESP_ERR_INVALID_ARG If the combination of arguments is invalid.
|
||||
* - ESP_ERR_INVALID_STATE Driver state is invalid.
|
||||
*/
|
||||
esp_err_t esp_isp_af_controller_get_oneshot_result(isp_af_ctrlr_t af_ctrlr, isp_af_result_t *out_res);
|
||||
esp_err_t esp_isp_af_controller_get_oneshot_statistics(isp_af_ctrlr_t af_ctrlr, int timeout_ms, isp_af_result_t *out_res);
|
||||
|
||||
/** @cond */
|
||||
#define esp_isp_af_controller_get_oneshot_result(af_ctrlr, out_res) \
|
||||
esp_isp_af_controller_get_oneshot_statistics(af_ctrlr, -1, out_res) // Alias
|
||||
/** @endcond */
|
||||
|
||||
/**
|
||||
* @brief Start AF continuous statistics of the luminance and definition in the windows
|
||||
* @note This function is an asynchronous and non-block function,
|
||||
* it will start the continuous statistics and return immediately.
|
||||
* You have to register the AF callback and get the result from the callback event data.
|
||||
*
|
||||
* @param[in] af_ctrlr AF controller handle
|
||||
* @return
|
||||
* - ESP_OK On success
|
||||
* - ESP_ERR_INVALID_ARG Null pointer
|
||||
* - ESP_ERR_INVALID_STATE Driver state is invalid.
|
||||
*/
|
||||
esp_err_t esp_isp_af_controller_start_continuous_statistics(isp_af_ctrlr_t af_ctrlr);
|
||||
|
||||
/**
|
||||
* @brief Stop AF continuous statistics of the luminance and definition in the windows
|
||||
*
|
||||
* @param[in] af_ctrlr AF controller handle
|
||||
* @return
|
||||
* - ESP_OK On success
|
||||
* - ESP_ERR_INVALID_ARG Null pointer
|
||||
* - ESP_ERR_INVALID_STATE Driver state is invalid.
|
||||
*/
|
||||
esp_err_t esp_isp_af_controller_stop_continuous_statistics(isp_af_ctrlr_t af_ctrlr);
|
||||
|
||||
/*---------------------------------------------
|
||||
AF Env Monitor
|
||||
@ -99,7 +136,9 @@ esp_err_t esp_isp_af_controller_get_oneshot_result(isp_af_ctrlr_t af_ctrlr, isp_
|
||||
* @brief AF environment detector config
|
||||
*/
|
||||
typedef struct {
|
||||
int interval; ///< Interval between environment detection, in frames
|
||||
int interval; /*!< Interval between environment detection, in frames.
|
||||
* i.e., AF controller will trigger the statistic periodically to detect the environment change.
|
||||
*/
|
||||
} esp_isp_af_env_config_t;
|
||||
|
||||
/**
|
||||
@ -133,7 +172,7 @@ esp_err_t esp_isp_af_controller_set_env_detector_threshold(isp_af_ctrlr_t af_ctr
|
||||
* @brief Event data structure
|
||||
*/
|
||||
typedef struct {
|
||||
//empty for future proof
|
||||
isp_af_result_t af_result; /*!< The AF statistics result */
|
||||
} esp_isp_af_env_detector_evt_data_t;
|
||||
|
||||
/**
|
||||
@ -155,7 +194,8 @@ typedef bool (*esp_isp_af_env_detector_callback_t)(isp_af_ctrlr_t af_ctrlr, cons
|
||||
* Involved variables should be in internal RAM as well.
|
||||
*/
|
||||
typedef struct {
|
||||
esp_isp_af_env_detector_callback_t on_env_change; ///< Event callback, invoked when environment change happens.
|
||||
esp_isp_af_env_detector_callback_t on_env_statistics_done; ///< Event callback, invoked when environment sample done.
|
||||
esp_isp_af_env_detector_callback_t on_env_change; ///< Event callback, invoked when environment change happens.
|
||||
} esp_isp_af_env_detector_evt_cbs_t;
|
||||
|
||||
/**
|
||||
|
86
components/esp_driver_isp/include/driver/isp_core.h
Normal file
86
components/esp_driver_isp/include/driver/isp_core.h
Normal file
@ -0,0 +1,86 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "esp_err.h"
|
||||
#include "driver/isp_types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief ISP configurations
|
||||
*/
|
||||
typedef struct {
|
||||
isp_clk_src_t clk_src; ///< Clock source
|
||||
uint32_t clk_hz; ///< Clock frequency in Hz, suggest twice higher than cam sensor speed
|
||||
isp_input_data_source_t input_data_source; ///< Input data source
|
||||
isp_color_t input_data_color_type; ///< Input color type
|
||||
isp_color_t output_data_color_type; ///< Output color type
|
||||
bool has_line_start_packet; ///< Enable line start packet
|
||||
bool has_line_end_packet; ///< Enable line end packet
|
||||
uint32_t h_res; ///< Input horizontal resolution, i.e. the number of pixels in a line
|
||||
uint32_t v_res; ///< Input vertical resolution, i.e. the number of lines in a frame
|
||||
} esp_isp_processor_cfg_t;
|
||||
|
||||
/**
|
||||
* @brief New an ISP processor
|
||||
*
|
||||
* @param[in] proc_config Pointer to ISP config. Refer to ``esp_isp_processor_cfg_t``.
|
||||
* @param[out] ret_proc Processor handle
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK On success
|
||||
* - ESP_ERR_INVALID_ARG If the combination of arguments is invalid.
|
||||
* - ESP_ERR_NOT_FOUND No free interrupt found with the specified flags
|
||||
* - ESP_ERR_NOT_SUPPORTED Not supported mode
|
||||
* - ESP_ERR_NO_MEM If out of memory
|
||||
*/
|
||||
esp_err_t esp_isp_new_processor(const esp_isp_processor_cfg_t *proc_config, isp_proc_handle_t *ret_proc);
|
||||
|
||||
/**
|
||||
* @brief Delete an ISP processor
|
||||
*
|
||||
* @param[in] proc Processor handle
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK On success
|
||||
* - ESP_ERR_INVALID_ARG If the combination of arguments is invalid.
|
||||
* - ESP_ERR_INVALID_STATE Driver state is invalid.
|
||||
*/
|
||||
esp_err_t esp_isp_del_processor(isp_proc_handle_t proc);
|
||||
|
||||
/**
|
||||
* @brief Enable an ISP processor
|
||||
*
|
||||
* @param[in] proc Processor handle
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK On success
|
||||
* - ESP_ERR_INVALID_ARG If the combination of arguments is invalid.
|
||||
* - ESP_ERR_INVALID_STATE Driver state is invalid.
|
||||
*/
|
||||
esp_err_t esp_isp_enable(isp_proc_handle_t proc);
|
||||
|
||||
/**
|
||||
* @brief Disable an ISP processor
|
||||
*
|
||||
* @param[in] proc Processor handle
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK On success
|
||||
* - ESP_ERR_INVALID_ARG If the combination of arguments is invalid.
|
||||
* - ESP_ERR_INVALID_STATE Driver state is invalid.
|
||||
*/
|
||||
esp_err_t esp_isp_disable(isp_proc_handle_t proc);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -11,23 +11,29 @@
|
||||
#include "esp_check.h"
|
||||
#include "esp_heap_caps.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "driver/isp.h"
|
||||
#include "hal/isp_hal.h"
|
||||
#include "hal/isp_ll.h"
|
||||
#include "driver/isp_af.h"
|
||||
#include "isp_internal.h"
|
||||
|
||||
#if CONFIG_ISP_ISR_IRAM_SAFE
|
||||
#define ISP_AF_MEM_ALLOC_CAPS (MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT)
|
||||
#else
|
||||
#define ISP_AF_MEM_ALLOC_CAPS MALLOC_CAP_DEFAULT
|
||||
#endif
|
||||
|
||||
static const char *TAG = "ISP_AF";
|
||||
|
||||
typedef struct isp_af_controller_t {
|
||||
int id;
|
||||
isp_fsm_t fsm;
|
||||
portMUX_TYPE spinlock;
|
||||
intr_handle_t intr_handle;
|
||||
isp_proc_handle_t isp_proc;
|
||||
QueueHandle_t evt_que;
|
||||
esp_isp_af_env_config_t config;
|
||||
esp_isp_af_env_detector_evt_cbs_t cbs;
|
||||
void *user_data;
|
||||
} isp_af_controller_t;
|
||||
|
||||
static void s_isp_af_default_isr(void *arg);
|
||||
|
||||
/*---------------------------------------------
|
||||
AF
|
||||
----------------------------------------------*/
|
||||
static esp_err_t s_isp_claim_af_controller(isp_proc_handle_t isp_proc, isp_af_controller_t *af_ctlr)
|
||||
static esp_err_t s_isp_claim_af_controller(isp_proc_handle_t isp_proc, isp_af_ctrlr_t af_ctlr)
|
||||
{
|
||||
assert(isp_proc && af_ctlr);
|
||||
|
||||
@ -50,15 +56,26 @@ static esp_err_t s_isp_claim_af_controller(isp_proc_handle_t isp_proc, isp_af_co
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t s_isp_declaim_af_controller(isp_af_controller_t *af_ctlr)
|
||||
static void s_isp_declaim_af_controller(isp_af_ctrlr_t af_ctlr)
|
||||
{
|
||||
assert(af_ctlr && af_ctlr->isp_proc);
|
||||
|
||||
portENTER_CRITICAL(&af_ctlr->isp_proc->spinlock);
|
||||
af_ctlr->isp_proc->af_ctlr[af_ctlr->id] = NULL;
|
||||
portEXIT_CRITICAL(&af_ctlr->isp_proc->spinlock);
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
static void s_isp_af_free_controller(isp_af_ctrlr_t af_ctlr)
|
||||
{
|
||||
if (af_ctlr) {
|
||||
if (af_ctlr->intr_handle) {
|
||||
esp_intr_free(af_ctlr->intr_handle);
|
||||
}
|
||||
if (af_ctlr->evt_que) {
|
||||
vQueueDelete(af_ctlr->evt_que);
|
||||
}
|
||||
free(af_ctlr);
|
||||
}
|
||||
}
|
||||
|
||||
esp_err_t esp_isp_new_af_controller(isp_proc_handle_t isp_proc, const esp_isp_af_config_t *af_config, isp_af_ctrlr_t *ret_hdl)
|
||||
@ -85,16 +102,23 @@ esp_err_t esp_isp_new_af_controller(isp_proc_handle_t isp_proc, const esp_isp_af
|
||||
}
|
||||
ESP_RETURN_ON_FALSE(af_config->edge_thresh > 0, ESP_ERR_INVALID_ARG, TAG, "edge threshold should be larger than 0");
|
||||
|
||||
isp_af_controller_t *af_ctlr = heap_caps_calloc(1, sizeof(isp_af_controller_t), ISP_AF_MEM_ALLOC_CAPS);
|
||||
isp_af_ctrlr_t af_ctlr = heap_caps_calloc(1, sizeof(isp_af_controller_t), ISP_MEM_ALLOC_CAPS);
|
||||
ESP_RETURN_ON_FALSE(af_ctlr, ESP_ERR_NO_MEM, TAG, "no mem");
|
||||
|
||||
//claim an AF controller
|
||||
ESP_GOTO_ON_ERROR(s_isp_claim_af_controller(isp_proc, af_ctlr), err, TAG, "no available controller");
|
||||
|
||||
af_ctlr->evt_que = xQueueCreateWithCaps(1, sizeof(isp_af_result_t), ISP_MEM_ALLOC_CAPS);
|
||||
ESP_GOTO_ON_FALSE(af_ctlr->evt_que, ESP_ERR_NO_MEM, err1, TAG, "no mem for af event queue");
|
||||
af_ctlr->fsm = ISP_FSM_INIT;
|
||||
af_ctlr->spinlock = (portMUX_TYPE)portMUX_INITIALIZER_UNLOCKED;
|
||||
af_ctlr->isp_proc = isp_proc;
|
||||
|
||||
//claim an AF controller
|
||||
ESP_GOTO_ON_ERROR(s_isp_claim_af_controller(isp_proc, af_ctlr), err1, TAG, "no available controller");
|
||||
|
||||
// Register the AF ISR
|
||||
uint32_t intr_st_reg_addr = isp_ll_get_intr_status_reg_addr(isp_proc->hal.hw);
|
||||
int intr_priority = af_config->intr_priority > 0 && af_config->intr_priority <= 7 ? BIT(af_config->intr_priority) : ESP_INTR_FLAG_LOWMED;
|
||||
ESP_GOTO_ON_ERROR(esp_intr_alloc_intrstatus(isp_hw_info.instances[isp_proc->proc_id].irq, ISP_INTR_ALLOC_FLAGS | intr_priority, intr_st_reg_addr, ISP_LL_EVENT_AF_MASK,
|
||||
s_isp_af_default_isr, af_ctlr, &af_ctlr->intr_handle), err2, TAG, "allocate interrupt failed");
|
||||
|
||||
isp_ll_af_enable_auto_update(isp_proc->hal.hw, false);
|
||||
isp_ll_af_enable(isp_proc->hal.hw, false);
|
||||
|
||||
@ -109,9 +133,10 @@ esp_err_t esp_isp_new_af_controller(isp_proc_handle_t isp_proc, const esp_isp_af
|
||||
*ret_hdl = af_ctlr;
|
||||
|
||||
return ESP_OK;
|
||||
|
||||
err:
|
||||
free(af_ctlr);
|
||||
err2:
|
||||
s_isp_declaim_af_controller(af_ctlr);
|
||||
err1:
|
||||
s_isp_af_free_controller(af_ctlr);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -119,10 +144,17 @@ err:
|
||||
esp_err_t esp_isp_del_af_controller(isp_af_ctrlr_t af_ctlr)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(af_ctlr && af_ctlr->isp_proc, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer");
|
||||
ESP_RETURN_ON_ERROR(s_isp_declaim_af_controller(af_ctlr), TAG, "controller isn't in use");
|
||||
ESP_RETURN_ON_FALSE(af_ctlr->fsm == ISP_FSM_INIT, ESP_ERR_INVALID_STATE, TAG, "controller isn't in init state");
|
||||
|
||||
free(af_ctlr);
|
||||
bool exist = false;
|
||||
for (int i = 0; i < SOC_ISP_AF_CTLR_NUMS; i++) {
|
||||
if (af_ctlr->isp_proc->af_ctlr[i] == af_ctlr) {
|
||||
exist = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
ESP_RETURN_ON_FALSE(exist, ESP_ERR_INVALID_ARG, TAG, "controller isn't in use");
|
||||
s_isp_declaim_af_controller(af_ctlr);
|
||||
s_isp_af_free_controller(af_ctlr);
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
@ -132,7 +164,9 @@ esp_err_t esp_isp_af_controller_enable(isp_af_ctrlr_t af_ctlr)
|
||||
ESP_RETURN_ON_FALSE(af_ctlr && af_ctlr->isp_proc, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer");
|
||||
ESP_RETURN_ON_FALSE(af_ctlr->fsm == ISP_FSM_INIT, ESP_ERR_INVALID_STATE, TAG, "controller isn't in init state");
|
||||
|
||||
esp_intr_enable(af_ctlr->intr_handle);
|
||||
isp_ll_af_clk_enable(af_ctlr->isp_proc->hal.hw, true);
|
||||
isp_ll_enable_intr(af_ctlr->isp_proc->hal.hw, ISP_LL_EVENT_AF_MASK, true);
|
||||
isp_ll_af_enable(af_ctlr->isp_proc->hal.hw, true);
|
||||
af_ctlr->fsm = ISP_FSM_ENABLE;
|
||||
|
||||
@ -145,18 +179,51 @@ esp_err_t esp_isp_af_controller_disable(isp_af_ctrlr_t af_ctlr)
|
||||
ESP_RETURN_ON_FALSE(af_ctlr->fsm == ISP_FSM_ENABLE, ESP_ERR_INVALID_STATE, TAG, "controller isn't in enable state");
|
||||
|
||||
isp_ll_af_clk_enable(af_ctlr->isp_proc->hal.hw, false);
|
||||
isp_ll_enable_intr(af_ctlr->isp_proc->hal.hw, ISP_LL_EVENT_AF_MASK, false);
|
||||
isp_ll_af_enable(af_ctlr->isp_proc->hal.hw, false);
|
||||
esp_intr_disable(af_ctlr->intr_handle);
|
||||
af_ctlr->fsm = ISP_FSM_INIT;
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_isp_af_controller_get_oneshot_result(isp_af_ctrlr_t af_ctlr, isp_af_result_t *out_res)
|
||||
esp_err_t esp_isp_af_controller_get_oneshot_statistics(isp_af_ctrlr_t af_ctrlr, int timeout_ms, isp_af_result_t *out_res)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE_ISR(af_ctlr && out_res, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer");
|
||||
ESP_RETURN_ON_FALSE_ISR(af_ctlr->fsm == ISP_FSM_ENABLE, ESP_ERR_INVALID_STATE, TAG, "controller isn't in enable state");
|
||||
ESP_RETURN_ON_FALSE_ISR(af_ctrlr && (out_res || timeout_ms == 0), ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer");
|
||||
ESP_RETURN_ON_FALSE_ISR(af_ctrlr->fsm == ISP_FSM_ENABLE, ESP_ERR_INVALID_STATE, TAG, "controller isn't enabled or continuous statistics has started");
|
||||
|
||||
isp_hal_af_get_oneshot_result(&af_ctlr->isp_proc->hal, out_res);
|
||||
esp_err_t ret = ESP_OK;
|
||||
TickType_t ticks = timeout_ms < 0 ? portMAX_DELAY : pdMS_TO_TICKS(timeout_ms);
|
||||
// Reset the queue in case receiving the legacy data in the queue
|
||||
xQueueReset(af_ctrlr->evt_que);
|
||||
// Trigger the AF statistics manually
|
||||
isp_ll_af_manual_update(af_ctrlr->isp_proc->hal.hw);
|
||||
// Wait the statistics to finish and receive the result from the queue
|
||||
if ((ticks > 0) && xQueueReceive(af_ctrlr->evt_que, out_res, ticks) != pdTRUE) {
|
||||
ret = ESP_ERR_TIMEOUT;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t esp_isp_af_controller_start_continuous_statistics(isp_af_ctrlr_t af_ctrlr)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE_ISR(af_ctrlr, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer");
|
||||
ESP_RETURN_ON_FALSE_ISR(af_ctrlr->fsm == ISP_FSM_ENABLE, ESP_ERR_INVALID_STATE, TAG, "controller isn't in enable state");
|
||||
|
||||
af_ctrlr->fsm = ISP_FSM_START;
|
||||
isp_ll_af_enable_auto_update(af_ctrlr->isp_proc->hal.hw, true);
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_isp_af_controller_stop_continuous_statistics(isp_af_ctrlr_t af_ctrlr)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE_ISR(af_ctrlr, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer");
|
||||
ESP_RETURN_ON_FALSE_ISR(af_ctrlr->fsm == ISP_FSM_START, ESP_ERR_INVALID_STATE, TAG, "controller isn't in continuous state");
|
||||
|
||||
isp_ll_af_enable_auto_update(af_ctrlr->isp_proc->hal.hw, false);
|
||||
af_ctrlr->fsm = ISP_FSM_ENABLE;
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
@ -174,6 +241,10 @@ esp_err_t esp_isp_af_controller_set_env_detector(isp_af_ctrlr_t af_ctrlr, const
|
||||
isp_ll_af_env_monitor_set_period(af_ctrlr->isp_proc->hal.hw, 0);
|
||||
isp_ll_clear_intr(af_ctrlr->isp_proc->hal.hw, ISP_LL_EVENT_AF_ENV);
|
||||
|
||||
isp_ll_af_env_monitor_set_mode(af_ctrlr->isp_proc->hal.hw, ISP_LL_AF_ENV_MONITOR_MODE_ABS);
|
||||
isp_ll_af_env_monitor_set_period(af_ctrlr->isp_proc->hal.hw, af_ctrlr->config.interval);
|
||||
isp_ll_enable_intr(af_ctrlr->isp_proc->hal.hw, ISP_LL_EVENT_AF_ENV, true);
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
@ -183,20 +254,24 @@ esp_err_t esp_isp_af_env_detector_register_event_callbacks(isp_af_ctrlr_t af_ctr
|
||||
ESP_RETURN_ON_FALSE(af_ctrlr->fsm == ISP_FSM_INIT, ESP_ERR_INVALID_STATE, TAG, "detector isn't in the init state");
|
||||
|
||||
#if CONFIG_ISP_ISR_IRAM_SAFE
|
||||
if (cbs->on_env_statistics_done) {
|
||||
ESP_RETURN_ON_FALSE(esp_ptr_in_iram(cbs->on_env_statistics_done), ESP_ERR_INVALID_ARG, TAG, "on_env_statistics_done callback not in IRAM");
|
||||
}
|
||||
if (cbs->on_env_change) {
|
||||
ESP_RETURN_ON_FALSE(esp_ptr_in_iram(cbs->on_env_change), ESP_ERR_INVALID_ARG, TAG, "on_env_change callback not in IRAM");
|
||||
}
|
||||
if (user_data) {
|
||||
ESP_RETURN_ON_FALSE(esp_ptr_internal(user_data), ESP_ERR_INVALID_ARG, TAG, "user context not in internal RAM");
|
||||
}
|
||||
#endif
|
||||
|
||||
ESP_RETURN_ON_ERROR(esp_isp_register_isr(af_ctrlr->isp_proc, ISP_SUBMODULE_AF), TAG, "fail to register ISR");
|
||||
|
||||
af_ctrlr->cbs.on_env_statistics_done = cbs->on_env_statistics_done;
|
||||
af_ctrlr->cbs.on_env_change = cbs->on_env_change;
|
||||
af_ctrlr->user_data = user_data;
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_isp_af_env_detector_set_threshold(isp_af_ctrlr_t af_ctrlr, int definition_thresh, int luminance_thresh)
|
||||
esp_err_t esp_isp_af_controller_set_env_detector_threshold(isp_af_ctrlr_t af_ctrlr, int definition_thresh, int luminance_thresh)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE_ISR(af_ctrlr, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
|
||||
ESP_RETURN_ON_FALSE_ISR(af_ctrlr->fsm == ISP_FSM_ENABLE, ESP_ERR_INVALID_STATE, TAG, "detector isn't in enable state");
|
||||
@ -209,36 +284,47 @@ esp_err_t esp_isp_af_env_detector_set_threshold(isp_af_ctrlr_t af_ctrlr, int def
|
||||
/*---------------------------------------------------------------
|
||||
INTR
|
||||
---------------------------------------------------------------*/
|
||||
static bool IRAM_ATTR s_af_env_isr(isp_af_ctrlr_t af_ctrlr)
|
||||
static void IRAM_ATTR s_isp_af_default_isr(void *arg)
|
||||
{
|
||||
bool need_yield = false;
|
||||
isp_af_ctrlr_t af_ctrlr = (isp_af_ctrlr_t)arg;
|
||||
isp_proc_handle_t proc = af_ctrlr->isp_proc;
|
||||
|
||||
uint32_t af_events = isp_hal_check_clear_intr_event(&proc->hal, ISP_LL_EVENT_AF_MASK);
|
||||
|
||||
bool need_yield = false;
|
||||
esp_isp_af_env_detector_evt_data_t edata = {};
|
||||
if (af_ctrlr->cbs.on_env_change(af_ctrlr, &edata, af_ctrlr->user_data)) {
|
||||
need_yield |= true;
|
||||
|
||||
if (af_events) {
|
||||
// Get the statistics result
|
||||
for (int i = 0; i < SOC_ISP_AF_WINDOW_NUMS; i++) {
|
||||
edata.af_result.definition[i] = isp_ll_af_get_window_sum(proc->hal.hw, i);
|
||||
edata.af_result.luminance[i] = isp_ll_af_get_window_lum(proc->hal.hw, i);
|
||||
}
|
||||
}
|
||||
|
||||
return need_yield;
|
||||
}
|
||||
|
||||
bool IRAM_ATTR esp_isp_af_isr(isp_proc_handle_t proc, uint32_t af_events)
|
||||
{
|
||||
/**
|
||||
* HW events are cleared in the ISP ISR dispatcher.
|
||||
* We only deal with HW events
|
||||
* Deal with the interrupts.
|
||||
* Now only one detector.
|
||||
* Should decide a detector instance according to the hw event.
|
||||
*/
|
||||
|
||||
bool need_yield = false;
|
||||
|
||||
if (af_events & ISP_LL_EVENT_AF_FDONE) {
|
||||
BaseType_t high_task_awake = false;
|
||||
// Send the event data to the queue, overwrite the legacy one if exist
|
||||
xQueueOverwriteFromISR(af_ctrlr->evt_que, &edata.af_result, &high_task_awake);
|
||||
// Invoke the callback if the callback is registered
|
||||
need_yield |= high_task_awake == pdTRUE;
|
||||
if (af_ctrlr->cbs.on_env_statistics_done) {
|
||||
need_yield |= af_ctrlr->cbs.on_env_statistics_done(af_ctrlr, &edata, af_ctrlr->user_data);
|
||||
}
|
||||
}
|
||||
if (af_events & ISP_LL_EVENT_AF_ENV) {
|
||||
/**
|
||||
* Now only one detector.
|
||||
* Should decide a detector instance according to the hw event.
|
||||
*/
|
||||
isp_af_ctrlr_t af_ctrlr = proc->af_ctlr[0];
|
||||
|
||||
need_yield |= s_af_env_isr(af_ctrlr);
|
||||
// Invoke the callback if the callback is registered
|
||||
if (af_ctrlr->cbs.on_env_change) {
|
||||
need_yield |= af_ctrlr->cbs.on_env_change(af_ctrlr, &edata, af_ctrlr->user_data);
|
||||
}
|
||||
}
|
||||
|
||||
return need_yield;
|
||||
if (need_yield) {
|
||||
portYIELD_FROM_ISR();
|
||||
}
|
||||
}
|
||||
|
@ -12,29 +12,14 @@
|
||||
#include "esp_heap_caps.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "esp_clk_tree.h"
|
||||
#include "driver/isp.h"
|
||||
#include "driver/isp_core.h"
|
||||
#include "esp_private/periph_ctrl.h"
|
||||
#include "esp_private/mipi_csi_share_hw_ctrl.h"
|
||||
#include "hal/hal_utils.h"
|
||||
#include "hal/isp_types.h"
|
||||
#include "hal/isp_hal.h"
|
||||
#include "hal/isp_ll.h"
|
||||
#include "soc/mipi_csi_bridge_struct.h"
|
||||
#include "soc/isp_periph.h"
|
||||
#include "isp_internal.h"
|
||||
|
||||
#if CONFIG_ISP_ISR_IRAM_SAFE
|
||||
#define ISP_INTR_ALLOC_FLAGS (ESP_INTR_FLAG_IRAM)
|
||||
#else
|
||||
#define ISP_INTR_ALLOC_FLAGS 0
|
||||
#endif
|
||||
|
||||
#if CONFIG_ISP_ISR_IRAM_SAFE
|
||||
#define ISP_MEM_ALLOC_CAPS (MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT)
|
||||
#else
|
||||
#define ISP_MEM_ALLOC_CAPS MALLOC_CAP_DEFAULT
|
||||
#endif
|
||||
|
||||
typedef struct isp_platform_t {
|
||||
_lock_t mutex;
|
||||
isp_processor_t *processors[SOC_ISP_NUMS];
|
||||
@ -88,6 +73,7 @@ esp_err_t esp_isp_new_processor(const esp_isp_processor_cfg_t *proc_config, isp_
|
||||
esp_err_t ret = ESP_FAIL;
|
||||
ESP_RETURN_ON_FALSE(proc_config && ret_proc, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer");
|
||||
ESP_RETURN_ON_FALSE(proc_config->input_data_source == ISP_INPUT_DATA_SOURCE_CSI, ESP_ERR_NOT_SUPPORTED, TAG, "only support CSI as input source at this moment");
|
||||
ESP_RETURN_ON_FALSE(proc_config->input_data_color_type == ISP_COLOR_RAW8, ESP_ERR_NOT_SUPPORTED, TAG, "input data type not supported");
|
||||
|
||||
isp_processor_t *proc = heap_caps_calloc(1, sizeof(isp_processor_t), ISP_MEM_ALLOC_CAPS);
|
||||
ESP_RETURN_ON_FALSE(proc, ESP_ERR_NO_MEM, TAG, "no mem");
|
||||
@ -202,100 +188,3 @@ esp_err_t esp_isp_disable(isp_proc_handle_t proc)
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------
|
||||
INTR
|
||||
---------------------------------------------------------------*/
|
||||
static void IRAM_ATTR s_isp_isr_dispatcher(void *arg)
|
||||
{
|
||||
isp_processor_t *proc = (isp_processor_t *)arg;
|
||||
bool need_yield = false;
|
||||
|
||||
//Check and clear hw events
|
||||
uint32_t af_events = isp_hal_check_clear_intr_event(&proc->hal, ISP_LL_EVENT_AF_MASK);
|
||||
|
||||
bool do_dispatch = false;
|
||||
//Deal with hw events
|
||||
if (af_events) {
|
||||
portENTER_CRITICAL_ISR(&proc->spinlock);
|
||||
do_dispatch = proc->af_isr_added;
|
||||
portEXIT_CRITICAL_ISR(&proc->spinlock);
|
||||
|
||||
if (do_dispatch) {
|
||||
need_yield |= esp_isp_af_isr(proc, af_events);
|
||||
}
|
||||
do_dispatch = false;
|
||||
}
|
||||
|
||||
if (need_yield) {
|
||||
portYIELD_FROM_ISR();
|
||||
}
|
||||
}
|
||||
|
||||
esp_err_t esp_isp_register_isr(isp_proc_handle_t proc, isp_submodule_t submodule)
|
||||
{
|
||||
esp_err_t ret = ESP_FAIL;
|
||||
ESP_RETURN_ON_FALSE(proc, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer");
|
||||
|
||||
bool do_alloc = false;
|
||||
portENTER_CRITICAL(&proc->spinlock);
|
||||
proc->isr_ref_counts++;
|
||||
if (proc->isr_ref_counts == 1) {
|
||||
assert(!proc->intr_hdl);
|
||||
do_alloc = true;
|
||||
}
|
||||
|
||||
switch (submodule) {
|
||||
case ISP_SUBMODULE_AF:
|
||||
proc->af_isr_added = true;
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
portEXIT_CRITICAL(&proc->spinlock);
|
||||
|
||||
if (do_alloc) {
|
||||
ret = esp_intr_alloc(isp_hw_info.instances[proc->proc_id].irq, ISP_INTR_ALLOC_FLAGS, s_isp_isr_dispatcher, (void *)proc, &proc->intr_hdl);
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE(TAG, "no intr source");
|
||||
return ret;
|
||||
}
|
||||
esp_intr_enable(proc->intr_hdl);
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_isp_deregister_isr(isp_proc_handle_t proc, isp_submodule_t submodule)
|
||||
{
|
||||
esp_err_t ret = ESP_FAIL;
|
||||
ESP_RETURN_ON_FALSE(proc, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer");
|
||||
|
||||
bool do_free = false;
|
||||
portENTER_CRITICAL(&proc->spinlock);
|
||||
proc->isr_ref_counts--;
|
||||
assert(proc->isr_ref_counts >= 0);
|
||||
if (proc->isr_ref_counts == 0) {
|
||||
assert(proc->intr_hdl);
|
||||
do_free = true;
|
||||
}
|
||||
|
||||
switch (submodule) {
|
||||
case ISP_SUBMODULE_AF:
|
||||
proc->af_isr_added = false;
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
portEXIT_CRITICAL(&proc->spinlock);
|
||||
|
||||
if (do_free) {
|
||||
esp_intr_disable(proc->intr_hdl);
|
||||
ret = esp_intr_free(proc->intr_hdl);
|
||||
if (ret != ESP_OK) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
@ -16,7 +16,11 @@
|
||||
#include "esp_heap_caps.h"
|
||||
#include "esp_intr_alloc.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/queue.h"
|
||||
#include "freertos/idf_additions.h"
|
||||
#include "driver/isp_types.h"
|
||||
#include "hal/isp_hal.h"
|
||||
#include "hal/isp_ll.h"
|
||||
#include "hal/isp_types.h"
|
||||
#include "soc/isp_periph.h"
|
||||
#include "soc/soc_caps.h"
|
||||
@ -25,32 +29,24 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if CONFIG_ISP_ISR_IRAM_SAFE
|
||||
#define ISP_INTR_ALLOC_FLAGS (ESP_INTR_FLAG_SHARED | ESP_INTR_FLAG_INTRDISABLED | ESP_INTR_FLAG_IRAM)
|
||||
#define ISP_MEM_ALLOC_CAPS (MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT)
|
||||
#else
|
||||
#define ISP_INTR_ALLOC_FLAGS (ESP_INTR_FLAG_SHARED | ESP_INTR_FLAG_INTRDISABLED)
|
||||
#define ISP_MEM_ALLOC_CAPS MALLOC_CAP_DEFAULT
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
ISP_FSM_INIT,
|
||||
ISP_FSM_ENABLE,
|
||||
ISP_FSM_START,
|
||||
} isp_fsm_t;
|
||||
|
||||
/*---------------------------------------------------------------
|
||||
Driver Context
|
||||
---------------------------------------------------------------*/
|
||||
typedef enum {
|
||||
ISP_SUBMODULE_AF,
|
||||
} isp_submodule_t;
|
||||
|
||||
typedef struct isp_af_controller_t isp_af_controller_t;
|
||||
typedef struct isp_processor_t isp_processor_t;
|
||||
|
||||
struct isp_af_controller_t {
|
||||
int id;
|
||||
isp_fsm_t fsm;
|
||||
portMUX_TYPE spinlock;
|
||||
isp_processor_t *isp_proc;
|
||||
esp_isp_af_env_config_t config;
|
||||
esp_isp_af_env_detector_evt_cbs_t cbs;
|
||||
void *user_data;
|
||||
};
|
||||
|
||||
struct isp_processor_t {
|
||||
typedef struct isp_processor_t {
|
||||
int proc_id;
|
||||
isp_hal_context_t hal;
|
||||
#if SOC_ISP_SHARE_CSI_BRG
|
||||
@ -59,22 +55,10 @@ struct isp_processor_t {
|
||||
#endif
|
||||
isp_fsm_t isp_fsm;
|
||||
portMUX_TYPE spinlock;
|
||||
intr_handle_t intr_hdl;
|
||||
|
||||
/* sub module contexts */
|
||||
isp_af_controller_t *af_ctlr[SOC_ISP_AF_CTLR_NUMS];
|
||||
|
||||
/* should be accessed within isp_processor_t spinlock */
|
||||
int isr_ref_counts;
|
||||
bool af_isr_added;
|
||||
};
|
||||
|
||||
/*---------------------------------------------------------------
|
||||
INTR
|
||||
---------------------------------------------------------------*/
|
||||
esp_err_t esp_isp_register_isr(isp_proc_handle_t proc, isp_submodule_t submodule);
|
||||
esp_err_t esp_isp_deregister_isr(isp_proc_handle_t proc, isp_submodule_t submodule);
|
||||
bool esp_isp_af_isr(isp_proc_handle_t proc, uint32_t af_events);
|
||||
isp_af_ctrlr_t af_ctlr[SOC_ISP_AF_CTLR_NUMS];
|
||||
} isp_processor_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -271,7 +271,6 @@ err:
|
||||
esp_err_t jpeg_del_decoder_engine(jpeg_decoder_handle_t decoder_engine)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(decoder_engine, ESP_ERR_INVALID_ARG, TAG, "jpeg decode handle is null");
|
||||
ESP_RETURN_ON_ERROR(jpeg_release_codec_handle(decoder_engine->codec_base), TAG, "release codec failed");
|
||||
|
||||
if (decoder_engine) {
|
||||
if (decoder_engine->rxlink) {
|
||||
@ -295,6 +294,7 @@ esp_err_t jpeg_del_decoder_engine(jpeg_decoder_handle_t decoder_engine)
|
||||
if (decoder_engine->intr_handle) {
|
||||
jpeg_isr_deregister(decoder_engine->codec_base, decoder_engine->intr_handle);
|
||||
}
|
||||
ESP_RETURN_ON_ERROR(jpeg_release_codec_handle(decoder_engine->codec_base), TAG, "release codec failed");
|
||||
free(decoder_engine);
|
||||
}
|
||||
return ESP_OK;
|
||||
|
@ -262,6 +262,7 @@ esp_err_t jpeg_encoder_process(jpeg_encoder_handle_t encoder_engine, const jpeg_
|
||||
}
|
||||
|
||||
if (s_rcv_event.dma_evt & JPEG_DMA2D_RX_EOF) {
|
||||
ESP_GOTO_ON_ERROR(esp_cache_msync((void*)encoder_engine->rxlink, encoder_engine->dma_desc_size, ESP_CACHE_MSYNC_FLAG_DIR_M2C), err, TAG, "sync memory to cache failed");
|
||||
compressed_size = s_dma_desc_get_len(encoder_engine->rxlink);
|
||||
uint32_t _compressed_size = JPEG_ALIGN_UP(compressed_size, cache_hal_get_cache_line_size(CACHE_LL_LEVEL_EXT_MEM, CACHE_TYPE_DATA));
|
||||
ESP_GOTO_ON_ERROR(esp_cache_msync((void*)(bit_stream + encoder_engine->header_info->header_len), _compressed_size, ESP_CACHE_MSYNC_FLAG_DIR_M2C), err, TAG, "sync memory to cache failed");
|
||||
@ -283,7 +284,6 @@ err:
|
||||
esp_err_t jpeg_del_encoder_engine(jpeg_encoder_handle_t encoder_engine)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(encoder_engine, ESP_ERR_INVALID_ARG, TAG, "jpeg encoder handle is null");
|
||||
ESP_RETURN_ON_ERROR(jpeg_release_codec_handle(encoder_engine->codec_base), TAG, "release codec failed");
|
||||
|
||||
if (encoder_engine) {
|
||||
if (encoder_engine->rxlink) {
|
||||
@ -307,6 +307,7 @@ esp_err_t jpeg_del_encoder_engine(jpeg_encoder_handle_t encoder_engine)
|
||||
if (encoder_engine->intr_handle) {
|
||||
jpeg_isr_deregister(encoder_engine->codec_base, encoder_engine->intr_handle);
|
||||
}
|
||||
ESP_RETURN_ON_ERROR(jpeg_release_codec_handle(encoder_engine->codec_base), TAG, "release codec failed");
|
||||
free(encoder_engine);
|
||||
}
|
||||
return ESP_OK;
|
||||
|
@ -130,10 +130,10 @@ esp_err_t jpeg_parse_sof_marker(jpeg_dec_header_info_t *header_info)
|
||||
|
||||
// The vertical and horizontal in process must be divided by mcu block.
|
||||
if (header_info->origin_v % header_info->mcuy != 0) {
|
||||
header_info->process_v = (ceil(header_info->origin_v / header_info->mcuy) + 1) * header_info->mcuy;
|
||||
header_info->process_v = (uint32_t)(ceil(header_info->origin_v / header_info->mcuy) + 1) * header_info->mcuy;
|
||||
}
|
||||
if (header_info->origin_h % header_info->mcux != 0) {
|
||||
header_info->process_h = (ceil(header_info->origin_h / header_info->mcux) + 1) * header_info->mcux;
|
||||
header_info->process_h = (uint32_t)(ceil(header_info->origin_h / header_info->mcux) + 1) * header_info->mcux;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
|
@ -87,7 +87,7 @@ typedef struct {
|
||||
uint8_t huffcode[2][2][JPEG_HUFFMAN_AC_VALUE_TABLE_LEN]; // Huffman decoded data tables [id][dcac]
|
||||
uint32_t tmp_huff[JPEG_HUFFMAN_AC_VALUE_TABLE_LEN]; // temp buffer to store huffman code
|
||||
bool dri_marker; // If we have dri marker in table
|
||||
uint8_t ri; // Restart interval
|
||||
uint16_t ri; // Restart interval
|
||||
} jpeg_dec_header_info_t;
|
||||
|
||||
struct jpeg_decoder_t {
|
||||
|
@ -52,7 +52,7 @@ static void IRAM_ATTR usb_serial_jtag_sof_tick_hook(void)
|
||||
#if CONFIG_USJ_NO_AUTO_LS_ON_CONNECTION
|
||||
esp_pm_lock_release(s_usb_serial_jtag_pm_lock);
|
||||
#endif
|
||||
#if !CONFIG_IDF_TARGET_ESP32P4 // TODO: IDF-7496 SOC_USB_SERIAL_JTAG_PHY_ON_BBPLL
|
||||
#if USB_SERIAL_JTAG_LL_PHY_DEPENDS_ON_BBPLL
|
||||
rtc_clk_bbpll_remove_consumer();
|
||||
#endif
|
||||
s_usb_serial_jtag_conn_status = false;
|
||||
@ -62,7 +62,7 @@ static void IRAM_ATTR usb_serial_jtag_sof_tick_hook(void)
|
||||
#if CONFIG_USJ_NO_AUTO_LS_ON_CONNECTION
|
||||
esp_pm_lock_acquire(s_usb_serial_jtag_pm_lock);
|
||||
#endif
|
||||
#if !CONFIG_IDF_TARGET_ESP32P4 // TODO: IDF-7496 SOC_USB_SERIAL_JTAG_PHY_ON_BBPLL
|
||||
#if USB_SERIAL_JTAG_LL_PHY_DEPENDS_ON_BBPLL
|
||||
rtc_clk_bbpll_add_consumer();
|
||||
#endif
|
||||
s_usb_serial_jtag_conn_status = true;
|
||||
@ -79,8 +79,8 @@ ESP_SYSTEM_INIT_FN(usb_serial_jtag_conn_status_init, SECONDARY, BIT(0), 230)
|
||||
// We always assume it is connected at first, so acquires the lock to avoid auto light sleep
|
||||
esp_pm_lock_acquire(s_usb_serial_jtag_pm_lock);
|
||||
#endif
|
||||
#if !CONFIG_IDF_TARGET_ESP32P4 // TODO: IDF-7496 SOC_USB_SERIAL_JTAG_PHY_ON_BBPLL
|
||||
// TODO: esp32p4 USJ rely on SPLL, if it will also be disabled during sleep, we need to call spll_add_consumer?
|
||||
#if USB_SERIAL_JTAG_LL_PHY_DEPENDS_ON_BBPLL
|
||||
// TODO: esp32p4 USJ rely on SPLL, if it will also be disabled during sleep, we need to call spll_add_consumer? IDF-9947
|
||||
rtc_clk_bbpll_add_consumer();
|
||||
#endif
|
||||
s_usb_serial_jtag_conn_status = true;
|
||||
|
@ -3,6 +3,10 @@
|
||||
components/esp_driver_usb_serial_jtag/test_apps/usb_serial_jtag:
|
||||
disable:
|
||||
- if: SOC_USB_SERIAL_JTAG_SUPPORTED != 1
|
||||
disable_test:
|
||||
- if: IDF_TARGET in ["esp32p4"]
|
||||
temporary: true
|
||||
reason: No runners.
|
||||
depends_components:
|
||||
- vfs
|
||||
- esp_driver_gpio
|
||||
|
@ -1,2 +1,2 @@
|
||||
| Supported Targets | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-S3 |
|
||||
| ----------------- | -------- | -------- | -------- | -------- |
|
||||
| Supported Targets | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-P4 | ESP32-S3 |
|
||||
| ----------------- | -------- | -------- | -------- | -------- | -------- |
|
||||
|
@ -77,13 +77,15 @@ static esp_err_t dp83848_update_link_duplex_speed(phy_dp83848_t *dp83848)
|
||||
uint32_t peer_pause_ability = false;
|
||||
anlpar_reg_t anlpar;
|
||||
physts_reg_t physts;
|
||||
ESP_GOTO_ON_ERROR(eth->phy_reg_read(eth, addr, ETH_PHY_ANLPAR_REG_ADDR, &(anlpar.val)), err, TAG, "read ANLPAR failed");
|
||||
ESP_GOTO_ON_ERROR(eth->phy_reg_read(eth, addr, ETH_PHY_STS_REG_ADDR, &(physts.val)), err, TAG, "read PHYSTS failed");
|
||||
eth_link_t link = physts.link_status ? ETH_LINK_UP : ETH_LINK_DOWN;
|
||||
bmsr_reg_t bmsr;
|
||||
ESP_GOTO_ON_ERROR(eth->phy_reg_read(eth, addr, ETH_PHY_BMSR_REG_ADDR, &(bmsr.val)), err, TAG, "read BMSR failed");
|
||||
eth_link_t link = bmsr.link_status ? ETH_LINK_UP : ETH_LINK_DOWN;
|
||||
/* check if link status changed */
|
||||
if (dp83848->phy_802_3.link_status != link) {
|
||||
/* when link up, read negotiation result */
|
||||
if (link == ETH_LINK_UP) {
|
||||
ESP_GOTO_ON_ERROR(eth->phy_reg_read(eth, addr, ETH_PHY_ANLPAR_REG_ADDR, &(anlpar.val)), err, TAG, "read ANLPAR failed");
|
||||
ESP_GOTO_ON_ERROR(eth->phy_reg_read(eth, addr, ETH_PHY_STS_REG_ADDR, &(physts.val)), err, TAG, "read PHYSTS failed");
|
||||
if (physts.speed_status) {
|
||||
speed = ETH_SPEED_10M;
|
||||
} else {
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@ -957,9 +957,19 @@ esp_err_t esp_http_client_set_redirection(esp_http_client_handle_t client)
|
||||
return err;
|
||||
}
|
||||
|
||||
esp_err_t esp_http_client_reset_redirect_counter(esp_http_client_handle_t client)
|
||||
{
|
||||
if (client == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
client->redirect_counter = 0;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t esp_http_check_response(esp_http_client_handle_t client)
|
||||
{
|
||||
if (client->response->status_code >= HttpStatus_Ok && client->response->status_code < HttpStatus_MultipleChoices) {
|
||||
client->redirect_counter = 0;
|
||||
return ESP_OK;
|
||||
}
|
||||
if (client->redirect_counter >= client->max_redirection_count) {
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@ -36,7 +36,7 @@ typedef enum {
|
||||
HTTP_EVENT_ERROR = 0, /*!< This event occurs when there are any errors during execution */
|
||||
HTTP_EVENT_ON_CONNECTED, /*!< Once the HTTP has been connected to the server, no data exchange has been performed */
|
||||
HTTP_EVENT_HEADERS_SENT, /*!< After sending all the headers to the server */
|
||||
HTTP_EVENT_HEADER_SENT = HTTP_EVENT_HEADERS_SENT, /*!< This header has been kept for backward compatability
|
||||
HTTP_EVENT_HEADER_SENT = HTTP_EVENT_HEADERS_SENT, /*!< This header has been kept for backward compatibility
|
||||
and will be deprecated in future versions esp-idf */
|
||||
HTTP_EVENT_ON_HEADER, /*!< Occurs when receiving each header sent from the server */
|
||||
HTTP_EVENT_ON_DATA, /*!< Occurs when receiving data from the server, possibly multiple portions of the packet */
|
||||
@ -125,7 +125,7 @@ typedef enum {
|
||||
typedef enum {
|
||||
HTTP_AUTH_TYPE_NONE = 0, /*!< No authention */
|
||||
HTTP_AUTH_TYPE_BASIC, /*!< HTTP Basic authentication */
|
||||
HTTP_AUTH_TYPE_DIGEST, /*!< HTTP Disgest authentication */
|
||||
HTTP_AUTH_TYPE_DIGEST, /*!< HTTP Digest authentication */
|
||||
} esp_http_client_auth_type_t;
|
||||
|
||||
/**
|
||||
@ -249,7 +249,7 @@ esp_http_client_handle_t esp_http_client_init(const esp_http_client_config_t *co
|
||||
* must be set while making a call to esp_http_client_init() API.
|
||||
* You can do any amount of calls to esp_http_client_perform while using the same esp_http_client_handle_t. The underlying connection may be kept open if the server allows it.
|
||||
* If you intend to transfer more than one file, you are even encouraged to do so.
|
||||
* esp_http_client will then attempt to re-use the same connection for the following transfers, thus making the operations faster, less CPU intense and using less network resources.
|
||||
* esp_http_client will then attempt to reuse the same connection for the following transfers, thus making the operations faster, less CPU intense and using less network resources.
|
||||
* Just note that you will have to use `esp_http_client_set_**` between the invokes to set options for the following esp_http_client_perform.
|
||||
*
|
||||
* @note You must never call this function simultaneously from two places using the same client handle.
|
||||
@ -612,7 +612,7 @@ esp_http_client_transport_t esp_http_client_get_transport_type(esp_http_client_h
|
||||
* @brief Set redirection URL.
|
||||
* When received the 30x code from the server, the client stores the redirect URL provided by the server.
|
||||
* This function will set the current URL to redirect to enable client to execute the redirection request.
|
||||
* When `disable_auto_redirect` is set, the client will not call this function but the event `HTTP_EVENT_REDIRECT` will be dispatched giving the user contol over the redirection event.
|
||||
* When `disable_auto_redirect` is set, the client will not call this function but the event `HTTP_EVENT_REDIRECT` will be dispatched giving the user control over the redirection event.
|
||||
*
|
||||
* @param[in] client The esp_http_client handle
|
||||
*
|
||||
@ -622,6 +622,18 @@ esp_http_client_transport_t esp_http_client_get_transport_type(esp_http_client_h
|
||||
*/
|
||||
esp_err_t esp_http_client_set_redirection(esp_http_client_handle_t client);
|
||||
|
||||
/**
|
||||
* @brief Reset the redirection counter.
|
||||
* This is useful to reset redirect counter in cases where the same handle is used for multiple requests.
|
||||
*
|
||||
* @param[in] client The esp_http_client handle
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK
|
||||
* - ESP_ERR_INVALID_ARG
|
||||
*/
|
||||
esp_err_t esp_http_client_reset_redirect_counter(esp_http_client_handle_t client);
|
||||
|
||||
/**
|
||||
* @brief On receiving a custom authentication header, this API can be invoked to set the
|
||||
* authentication information from the header. This API can be called from the event
|
||||
@ -676,7 +688,7 @@ int esp_http_client_read_response(esp_http_client_handle_t client, char *buffer,
|
||||
/**
|
||||
* @brief Process all remaining response data
|
||||
* This uses an internal buffer to repeatedly receive, parse, and discard response data until complete data is processed.
|
||||
* As no additional user-supplied buffer is required, this may be preferrable to `esp_http_client_read_response` in situations where the content of the response may be ignored.
|
||||
* As no additional user-supplied buffer is required, this may be preferable to `esp_http_client_read_response` in situations where the content of the response may be ignored.
|
||||
*
|
||||
* @param[in] client The esp_http_client handle
|
||||
* @param len Length of data discarded
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2018-2021 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2018-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@ -11,7 +11,7 @@
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#include "esp_log.h"
|
||||
#include "ctrl_sock.h"
|
||||
|
||||
#if CONFIG_IDF_TARGET_LINUX
|
||||
@ -22,11 +22,20 @@
|
||||
#define IPV6_ENABLED CONFIG_LWIP_IPV6
|
||||
#endif // !CONFIG_IDF_TARGET_LINUX
|
||||
|
||||
#if !CONFIG_LWIP_NETIF_LOOPBACK
|
||||
static const char *TAG = "esp_http_server";
|
||||
#endif
|
||||
|
||||
/* Control socket, because in some network stacks select can't be woken up any
|
||||
* other way
|
||||
*/
|
||||
int cs_create_ctrl_sock(int port)
|
||||
{
|
||||
#if !CONFIG_LWIP_NETIF_LOOPBACK
|
||||
ESP_LOGE(TAG, "Please enable LWIP_NETIF_LOOPBACK for %s API", __func__);
|
||||
return -1;
|
||||
#endif
|
||||
|
||||
int fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
||||
if (fd < 0) {
|
||||
return -1;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2018-2023 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2018-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@ -366,7 +366,6 @@ exit:
|
||||
free((void *) cfg->cacert_buf);
|
||||
}
|
||||
free(cfg);
|
||||
free(*ssl_ctx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -379,14 +378,17 @@ esp_err_t httpd_ssl_start(httpd_handle_t *pHandle, struct httpd_ssl_config *conf
|
||||
ESP_LOGI(TAG, "Starting server");
|
||||
|
||||
esp_err_t ret = ESP_OK;
|
||||
httpd_ssl_ctx_t *ssl_ctx = NULL;
|
||||
|
||||
if (HTTPD_SSL_TRANSPORT_SECURE == config->transport_mode) {
|
||||
httpd_ssl_ctx_t *ssl_ctx = calloc(1, sizeof(httpd_ssl_ctx_t));
|
||||
ssl_ctx = calloc(1, sizeof(httpd_ssl_ctx_t));
|
||||
if (!ssl_ctx) {
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
|
||||
ret = create_secure_context(config, &ssl_ctx);
|
||||
if (ret != ESP_OK) {
|
||||
free(ssl_ctx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -411,7 +413,11 @@ esp_err_t httpd_ssl_start(httpd_handle_t *pHandle, struct httpd_ssl_config *conf
|
||||
httpd_handle_t handle = NULL;
|
||||
|
||||
ret = httpd_start(&handle, &config->httpd);
|
||||
if (ret != ESP_OK) return ret;
|
||||
if (ret != ESP_OK) {
|
||||
free(ssl_ctx);
|
||||
ssl_ctx = NULL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
*pHandle = handle;
|
||||
|
||||
|
@ -214,18 +214,6 @@ menu "Hardware Settings"
|
||||
callback and hence it is highly recommended to keep them as short as possible.
|
||||
endmenu
|
||||
|
||||
menu "ESP_SLEEP_WORKAROUND"
|
||||
# No visible menu/configs for workaround
|
||||
visible if 0
|
||||
config ESP_SLEEP_SYSTIMER_STALL_WORKAROUND
|
||||
bool "ESP32C3 SYSTIMER Stall Issue Workaround"
|
||||
depends on IDF_TARGET_ESP32C3
|
||||
help
|
||||
Its not able to stall ESP32C3 systimer in sleep.
|
||||
To fix related RTOS TICK issue, select it to disable related systimer during sleep.
|
||||
TODO: IDF-7036
|
||||
endmenu
|
||||
|
||||
menu "RTC Clock Config"
|
||||
orsource "./port/$IDF_TARGET/Kconfig.rtc"
|
||||
endmenu
|
||||
|
@ -19,7 +19,7 @@ menu "GDMA Configurations"
|
||||
bool "Enable debug log"
|
||||
default n
|
||||
help
|
||||
Wether to enable the debug log message for GDMA driver.
|
||||
Whether to enable the debug log message for GDMA driver.
|
||||
Note that, this option only controls the GDMA driver log, won't affect other drivers.
|
||||
endmenu # GDMA Configurations
|
||||
|
||||
@ -40,6 +40,13 @@ menu "DW_GDMA Configurations"
|
||||
Place DW_GDMA setter functions (e.g. dw_gdma_channel_set_block_markers) into IRAM,
|
||||
so that these functions can be IRAM-safe and able to be called in the other IRAM interrupt context.
|
||||
|
||||
config DW_GDMA_GETTER_FUNC_IN_IRAM
|
||||
bool
|
||||
default n
|
||||
help
|
||||
Place DW_GDMA getter functions (e.g. dw_gdma_link_list_get_item) into IRAM,
|
||||
so that these functions can be IRAM-safe and able to be called in the other IRAM interrupt context.
|
||||
|
||||
config DW_GDMA_ISR_IRAM_SAFE
|
||||
bool
|
||||
default n
|
||||
@ -52,7 +59,7 @@ menu "DW_GDMA Configurations"
|
||||
bool "Enable debug log"
|
||||
default n
|
||||
help
|
||||
Wether to enable the debug log message for DW_GDMA driver.
|
||||
Whether to enable the debug log message for DW_GDMA driver.
|
||||
Note that, this option only controls the DW_GDMA driver log, won't affect other drivers.
|
||||
endmenu # DW_GDMA Configurations
|
||||
|
||||
|
@ -78,10 +78,15 @@ entries:
|
||||
# put DW_GDMA control functions in IRAM
|
||||
if DW_GDMA_CTRL_FUNC_IN_IRAM = y:
|
||||
dw_gdma: dw_gdma_channel_continue (noflash)
|
||||
dw_gdma: dw_gdma_channel_enable_ctrl (noflash)
|
||||
|
||||
if DW_GDMA_SETTER_FUNC_IN_IRAM = y:
|
||||
dw_gdma: dw_gdma_channel_set_block_markers (noflash)
|
||||
dw_gdma: dw_gdma_lli_set_block_markers (noflash)
|
||||
dw_gdma: dw_gdma_channel_use_link_list (noflash)
|
||||
|
||||
if DW_GDMA_GETTER_FUNC_IN_IRAM = y:
|
||||
dw_gdma: dw_gdma_link_list_get_item (noflash)
|
||||
|
||||
[mapping:dma2d_driver]
|
||||
archive: libesp_hw_support.a
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include <stdbool.h>
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_err.h"
|
||||
#include "esp_sleep.h"
|
||||
#include "soc/soc_caps.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
@ -21,7 +22,7 @@ extern "C" {
|
||||
* This file contains declarations of cpu retention related functions in light sleep mode.
|
||||
*/
|
||||
|
||||
#if CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP || SOC_PM_SUPPORT_CPU_PD
|
||||
#if ESP_SLEEP_POWER_DOWN_CPU || SOC_PM_SUPPORT_CPU_PD
|
||||
/**
|
||||
* @brief Whether to allow the cpu power domain to be powered off.
|
||||
*
|
||||
@ -31,7 +32,7 @@ extern "C" {
|
||||
bool cpu_domain_pd_allowed(void);
|
||||
#endif
|
||||
|
||||
#if CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP
|
||||
#if ESP_SLEEP_POWER_DOWN_CPU
|
||||
/**
|
||||
* @brief Configure the parameters of the CPU domain during the sleep process
|
||||
*
|
||||
@ -64,9 +65,9 @@ void sleep_disable_cpu_retention(void);
|
||||
esp_err_t esp_sleep_cpu_retention(uint32_t (*goto_sleep)(uint32_t, uint32_t, uint32_t, bool),
|
||||
uint32_t wakeup_opt, uint32_t reject_opt, uint32_t lslp_mem_inf_fpu, bool dslp);
|
||||
#endif // SOC_PM_CPU_RETENTION_BY_SW
|
||||
#endif // CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP
|
||||
#endif // ESP_SLEEP_POWER_DOWN_CPU
|
||||
|
||||
#if !CONFIG_FREERTOS_UNICORE && CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP
|
||||
#if !CONFIG_FREERTOS_UNICORE && ESP_SLEEP_POWER_DOWN_CPU
|
||||
/**
|
||||
* Do sleep prepare for other smp cores
|
||||
*/
|
||||
@ -77,13 +78,11 @@ void sleep_smp_cpu_sleep_prepare(void);
|
||||
*/
|
||||
void sleep_smp_cpu_wakeup_prepare(void);
|
||||
|
||||
#if CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP
|
||||
/**
|
||||
* Notify the other core that this sleep does not require retention.
|
||||
*/
|
||||
void esp_sleep_cpu_skip_retention(void);
|
||||
#endif // CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP
|
||||
#endif // !CONFIG_FREERTOS_UNICORE && CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP
|
||||
#endif // !CONFIG_FREERTOS_UNICORE && ESP_SLEEP_POWER_DOWN_CPU
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@ -133,6 +133,8 @@ enum {
|
||||
ESP_ERR_SLEEP_TOO_SHORT_SLEEP_DURATION = ESP_ERR_INVALID_ARG,
|
||||
};
|
||||
|
||||
#define ESP_SLEEP_POWER_DOWN_CPU (CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP || (SOC_CPU_IN_TOP_DOMAIN && CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP))
|
||||
|
||||
/**
|
||||
* @brief Disable wakeup source
|
||||
*
|
||||
@ -713,7 +715,7 @@ void esp_default_wake_deep_sleep(void);
|
||||
*/
|
||||
void esp_deep_sleep_disable_rom_logging(void);
|
||||
|
||||
#if CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP
|
||||
#if ESP_SLEEP_POWER_DOWN_CPU
|
||||
|
||||
#if SOC_PM_CPU_RETENTION_BY_RTCCNTL
|
||||
/**
|
||||
@ -752,7 +754,7 @@ esp_err_t esp_sleep_cpu_retention_init(void);
|
||||
* Release system retention memory.
|
||||
*/
|
||||
esp_err_t esp_sleep_cpu_retention_deinit(void);
|
||||
#endif // CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP
|
||||
#endif // ESP_SLEEP_POWER_DOWN_CPU
|
||||
|
||||
/**
|
||||
* @brief Configure to isolate all GPIO pins in sleep state
|
||||
|
@ -4,7 +4,8 @@ endif()
|
||||
|
||||
set(srcs)
|
||||
|
||||
if(CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP)
|
||||
if(CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP OR
|
||||
(CONFIG_SOC_CPU_IN_TOP_DOMAIN AND CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP))
|
||||
list(APPEND srcs "cpu_retention/port/${target}/sleep_cpu.c")
|
||||
if(CONFIG_SOC_PM_CPU_RETENTION_BY_SW)
|
||||
list(APPEND srcs "cpu_retention/port/${target}/sleep_cpu_asm.S")
|
||||
|
@ -102,7 +102,7 @@ bool cpu_domain_pd_allowed(void)
|
||||
|
||||
esp_err_t sleep_cpu_configure(bool light_sleep_enable)
|
||||
{
|
||||
#if CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP
|
||||
#if ESP_SLEEP_POWER_DOWN_CPU
|
||||
if (light_sleep_enable) {
|
||||
ESP_RETURN_ON_ERROR(esp_sleep_cpu_retention_init(), TAG, "Failed to enable CPU power down during light sleep.");
|
||||
} else {
|
||||
|
@ -489,7 +489,7 @@ bool cpu_domain_pd_allowed(void)
|
||||
|
||||
esp_err_t sleep_cpu_configure(bool light_sleep_enable)
|
||||
{
|
||||
#if CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP
|
||||
#if ESP_SLEEP_POWER_DOWN_CPU
|
||||
if (light_sleep_enable) {
|
||||
ESP_RETURN_ON_ERROR(esp_sleep_cpu_retention_init(), TAG, "Failed to enable CPU power down during light sleep.");
|
||||
} else {
|
||||
|
@ -532,7 +532,7 @@ bool cpu_domain_pd_allowed(void)
|
||||
|
||||
esp_err_t sleep_cpu_configure(bool light_sleep_enable)
|
||||
{
|
||||
#if CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP
|
||||
#if ESP_SLEEP_POWER_DOWN_CPU
|
||||
if (light_sleep_enable) {
|
||||
ESP_RETURN_ON_ERROR(esp_sleep_cpu_retention_init(), TAG, "Failed to enable CPU power down during light sleep.");
|
||||
} else {
|
||||
|
@ -532,7 +532,7 @@ bool cpu_domain_pd_allowed(void)
|
||||
|
||||
esp_err_t sleep_cpu_configure(bool light_sleep_enable)
|
||||
{
|
||||
#if CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP
|
||||
#if ESP_SLEEP_POWER_DOWN_CPU
|
||||
if (light_sleep_enable) {
|
||||
ESP_RETURN_ON_ERROR(esp_sleep_cpu_retention_init(), TAG, "Failed to enable CPU power down during light sleep.");
|
||||
} else {
|
||||
|
@ -41,7 +41,7 @@
|
||||
#endif
|
||||
|
||||
|
||||
#if CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP && !CONFIG_FREERTOS_UNICORE
|
||||
#if ESP_SLEEP_POWER_DOWN_CPU && !CONFIG_FREERTOS_UNICORE
|
||||
#include <stdatomic.h>
|
||||
#include "soc/hp_system_reg.h"
|
||||
typedef enum {
|
||||
@ -81,7 +81,7 @@ typedef struct {
|
||||
} retent;
|
||||
} sleep_cpu_retention_t;
|
||||
|
||||
static DRAM_ATTR __attribute__((unused)) sleep_cpu_retention_t s_cpu_retention;
|
||||
static TCM_DRAM_ATTR __attribute__((unused)) sleep_cpu_retention_t s_cpu_retention;
|
||||
|
||||
extern RvCoreCriticalSleepFrame *rv_core_critical_regs_frame[portNUM_PROCESSORS];
|
||||
|
||||
@ -162,7 +162,7 @@ static esp_err_t esp_sleep_cpu_retention_init_impl(void)
|
||||
s_cpu_retention.retent.clic_frame[core_id] = (cpu_domain_dev_sleep_frame_t *)frame;
|
||||
}
|
||||
}
|
||||
#if CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP && !CONFIG_FREERTOS_UNICORE
|
||||
#if ESP_SLEEP_POWER_DOWN_CPU && !CONFIG_FREERTOS_UNICORE
|
||||
for (uint8_t core_id = 0; core_id < portNUM_PROCESSORS; ++core_id) {
|
||||
atomic_init(&s_smp_retention_state[core_id], SMP_IDLE);
|
||||
}
|
||||
@ -209,7 +209,7 @@ FORCE_INLINE_ATTR void restore_mstatus(uint32_t mstatus_val)
|
||||
RV_WRITE_CSR(mstatus, mstatus_val);
|
||||
}
|
||||
|
||||
static IRAM_ATTR RvCoreNonCriticalSleepFrame * rv_core_noncritical_regs_save(void)
|
||||
static TCM_IRAM_ATTR RvCoreNonCriticalSleepFrame * rv_core_noncritical_regs_save(void)
|
||||
{
|
||||
RvCoreNonCriticalSleepFrame *frame = s_cpu_retention.retent.non_critical_frame[esp_cpu_get_core_id()];
|
||||
|
||||
@ -277,7 +277,7 @@ static IRAM_ATTR RvCoreNonCriticalSleepFrame * rv_core_noncritical_regs_save(voi
|
||||
return frame;
|
||||
}
|
||||
|
||||
static IRAM_ATTR void rv_core_noncritical_regs_restore(void)
|
||||
static TCM_IRAM_ATTR void rv_core_noncritical_regs_restore(void)
|
||||
{
|
||||
RvCoreNonCriticalSleepFrame *frame = s_cpu_retention.retent.non_critical_frame[esp_cpu_get_core_id()];
|
||||
|
||||
@ -343,7 +343,7 @@ static IRAM_ATTR void rv_core_noncritical_regs_restore(void)
|
||||
RV_WRITE_CSR(mcycle, frame->mcycle);
|
||||
}
|
||||
|
||||
static IRAM_ATTR void cpu_domain_dev_regs_save(cpu_domain_dev_sleep_frame_t *frame)
|
||||
static TCM_IRAM_ATTR void cpu_domain_dev_regs_save(cpu_domain_dev_sleep_frame_t *frame)
|
||||
{
|
||||
assert(frame);
|
||||
cpu_domain_dev_regs_region_t *region = frame->region;
|
||||
@ -357,7 +357,7 @@ static IRAM_ATTR void cpu_domain_dev_regs_save(cpu_domain_dev_sleep_frame_t *fra
|
||||
}
|
||||
}
|
||||
|
||||
static IRAM_ATTR void cpu_domain_dev_regs_restore(cpu_domain_dev_sleep_frame_t *frame)
|
||||
static TCM_IRAM_ATTR void cpu_domain_dev_regs_restore(cpu_domain_dev_sleep_frame_t *frame)
|
||||
{
|
||||
assert(frame);
|
||||
cpu_domain_dev_regs_region_t *region = frame->region;
|
||||
@ -372,12 +372,12 @@ static IRAM_ATTR void cpu_domain_dev_regs_restore(cpu_domain_dev_sleep_frame_t *
|
||||
}
|
||||
|
||||
#if CONFIG_PM_CHECK_SLEEP_RETENTION_FRAME
|
||||
static IRAM_ATTR void update_retention_frame_crc(uint32_t *frame_ptr, uint32_t frame_check_size, uint32_t *frame_crc_ptr)
|
||||
static TCM_IRAM_ATTR void update_retention_frame_crc(uint32_t *frame_ptr, uint32_t frame_check_size, uint32_t *frame_crc_ptr)
|
||||
{
|
||||
*(frame_crc_ptr) = esp_crc32_le(0, (void *)frame_ptr, frame_check_size);
|
||||
}
|
||||
|
||||
static IRAM_ATTR void validate_retention_frame_crc(uint32_t *frame_ptr, uint32_t frame_check_size, uint32_t *frame_crc_ptr)
|
||||
static TCM_IRAM_ATTR void validate_retention_frame_crc(uint32_t *frame_ptr, uint32_t frame_check_size, uint32_t *frame_crc_ptr)
|
||||
{
|
||||
if(*(frame_crc_ptr) != esp_crc32_le(0, (void *)(frame_ptr), frame_check_size)){
|
||||
// resume uarts
|
||||
@ -399,7 +399,7 @@ extern RvCoreCriticalSleepFrame * rv_core_critical_regs_save(void);
|
||||
extern RvCoreCriticalSleepFrame * rv_core_critical_regs_restore(void);
|
||||
typedef uint32_t (* sleep_cpu_entry_cb_t)(uint32_t, uint32_t, uint32_t, bool);
|
||||
|
||||
static IRAM_ATTR esp_err_t do_cpu_retention(sleep_cpu_entry_cb_t goto_sleep,
|
||||
static TCM_IRAM_ATTR esp_err_t do_cpu_retention(sleep_cpu_entry_cb_t goto_sleep,
|
||||
uint32_t wakeup_opt, uint32_t reject_opt, uint32_t lslp_mem_inf_fpu, bool dslp)
|
||||
{
|
||||
uint8_t core_id = esp_cpu_get_core_id();
|
||||
@ -410,11 +410,11 @@ static IRAM_ATTR esp_err_t do_cpu_retention(sleep_cpu_entry_cb_t goto_sleep,
|
||||
esp_sleep_execute_event_callbacks(SLEEP_EVENT_SW_CPU_TO_MEM_END, (void *)0);
|
||||
#if CONFIG_PM_CHECK_SLEEP_RETENTION_FRAME
|
||||
/* Minus 2 * sizeof(long) is for bypass `pmufunc` and `frame_crc` field */
|
||||
update_retention_frame_crc((uint32_t*)frame, RV_SLEEP_CTX_FRMSZ - 2 * sizeof(long), (uint32_t *)(&frame->frame_crc));
|
||||
update_retention_frame_crc((uint32_t*)frame, RV_SLEEP_CTX_SZ1 - 2 * sizeof(long), (uint32_t *)(&frame->frame_crc));
|
||||
#endif
|
||||
REG_WRITE(RTC_SLEEP_WAKE_STUB_ADDR_REG, (uint32_t)rv_core_critical_regs_restore);
|
||||
|
||||
#if CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP && !CONFIG_FREERTOS_UNICORE
|
||||
#if ESP_SLEEP_POWER_DOWN_CPU && !CONFIG_FREERTOS_UNICORE
|
||||
atomic_store(&s_smp_retention_state[core_id], SMP_BACKUP_DONE);
|
||||
while (atomic_load(&s_smp_retention_state[!core_id]) != SMP_BACKUP_DONE) {
|
||||
;
|
||||
@ -425,20 +425,20 @@ static IRAM_ATTR esp_err_t do_cpu_retention(sleep_cpu_entry_cb_t goto_sleep,
|
||||
}
|
||||
#if CONFIG_PM_CHECK_SLEEP_RETENTION_FRAME
|
||||
else {
|
||||
validate_retention_frame_crc((uint32_t*)frame, RV_SLEEP_CTX_FRMSZ - 2 * sizeof(long), (uint32_t *)(&frame->frame_crc));
|
||||
validate_retention_frame_crc((uint32_t*)frame, RV_SLEEP_CTX_SZ1 - 2 * sizeof(long), (uint32_t *)(&frame->frame_crc));
|
||||
}
|
||||
#endif
|
||||
|
||||
return pmu_sleep_finish();
|
||||
}
|
||||
|
||||
esp_err_t IRAM_ATTR esp_sleep_cpu_retention(uint32_t (*goto_sleep)(uint32_t, uint32_t, uint32_t, bool),
|
||||
esp_err_t TCM_IRAM_ATTR esp_sleep_cpu_retention(uint32_t (*goto_sleep)(uint32_t, uint32_t, uint32_t, bool),
|
||||
uint32_t wakeup_opt, uint32_t reject_opt, uint32_t lslp_mem_inf_fpu, bool dslp)
|
||||
{
|
||||
esp_sleep_execute_event_callbacks(SLEEP_EVENT_SW_CPU_TO_MEM_START, (void *)0);
|
||||
uint32_t mstatus = save_mstatus_and_disable_global_int();
|
||||
uint8_t core_id = esp_cpu_get_core_id();
|
||||
#if CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP && !CONFIG_FREERTOS_UNICORE
|
||||
#if ESP_SLEEP_POWER_DOWN_CPU && !CONFIG_FREERTOS_UNICORE
|
||||
atomic_store(&s_smp_retention_state[core_id], SMP_BACKUP_START);
|
||||
#endif
|
||||
cpu_domain_dev_regs_save(s_cpu_retention.retent.clic_frame[core_id]);
|
||||
@ -457,7 +457,7 @@ esp_err_t IRAM_ATTR esp_sleep_cpu_retention(uint32_t (*goto_sleep)(uint32_t, uin
|
||||
validate_retention_frame_crc((uint32_t*)frame, sizeof(RvCoreNonCriticalSleepFrame) - sizeof(long), (uint32_t *)(&frame->frame_crc));
|
||||
#endif
|
||||
|
||||
#if CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP && !CONFIG_FREERTOS_UNICORE
|
||||
#if ESP_SLEEP_POWER_DOWN_CPU && !CONFIG_FREERTOS_UNICORE
|
||||
// Start core1
|
||||
if (core_id == 0) {
|
||||
REG_SET_BIT(HP_SYS_CLKRST_SOC_CLK_CTRL0_REG, HP_SYS_CLKRST_REG_CORE1_CPU_CLK_EN);
|
||||
@ -472,7 +472,7 @@ esp_err_t IRAM_ATTR esp_sleep_cpu_retention(uint32_t (*goto_sleep)(uint32_t, uin
|
||||
cpu_domain_dev_regs_restore(s_cpu_retention.retent.clic_frame[core_id]);
|
||||
restore_mstatus(mstatus);
|
||||
|
||||
#if CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP && !CONFIG_FREERTOS_UNICORE
|
||||
#if ESP_SLEEP_POWER_DOWN_CPU && !CONFIG_FREERTOS_UNICORE
|
||||
atomic_store(&s_smp_retention_state[core_id], SMP_RESTORE_DONE);
|
||||
#endif
|
||||
return err;
|
||||
@ -504,7 +504,7 @@ bool cpu_domain_pd_allowed(void)
|
||||
|
||||
esp_err_t sleep_cpu_configure(bool light_sleep_enable)
|
||||
{
|
||||
#if CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP
|
||||
#if ESP_SLEEP_POWER_DOWN_CPU
|
||||
if (light_sleep_enable) {
|
||||
ESP_RETURN_ON_ERROR(esp_sleep_cpu_retention_init(), TAG, "Failed to enable CPU power down during light sleep.");
|
||||
} else {
|
||||
@ -515,7 +515,7 @@ esp_err_t sleep_cpu_configure(bool light_sleep_enable)
|
||||
}
|
||||
|
||||
#if !CONFIG_FREERTOS_UNICORE
|
||||
#if CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP
|
||||
#if ESP_SLEEP_POWER_DOWN_CPU
|
||||
static TCM_IRAM_ATTR void smp_core_do_retention(void)
|
||||
{
|
||||
uint8_t core_id = esp_cpu_get_core_id();
|
||||
@ -572,14 +572,14 @@ static TCM_IRAM_ATTR void smp_core_do_retention(void)
|
||||
}
|
||||
|
||||
|
||||
IRAM_ATTR void esp_sleep_cpu_skip_retention(void) {
|
||||
TCM_IRAM_ATTR void esp_sleep_cpu_skip_retention(void) {
|
||||
atomic_store(&s_smp_retention_state[esp_cpu_get_core_id()], SMP_SKIP_RETENTION);
|
||||
}
|
||||
#endif
|
||||
|
||||
void sleep_smp_cpu_sleep_prepare(void)
|
||||
{
|
||||
#if CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP
|
||||
#if ESP_SLEEP_POWER_DOWN_CPU
|
||||
while (atomic_load(&s_smp_retention_state[!esp_cpu_get_core_id()]) != SMP_IDLE) {
|
||||
;
|
||||
}
|
||||
@ -591,7 +591,7 @@ void sleep_smp_cpu_sleep_prepare(void)
|
||||
|
||||
void sleep_smp_cpu_wakeup_prepare(void)
|
||||
{
|
||||
#if CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP
|
||||
#if ESP_SLEEP_POWER_DOWN_CPU
|
||||
uint8_t core_id = esp_cpu_get_core_id();
|
||||
if (atomic_load(&s_smp_retention_state[core_id]) == SMP_RESTORE_DONE) {
|
||||
while (atomic_load(&s_smp_retention_state[!core_id]) != SMP_RESTORE_DONE) {
|
||||
|
@ -117,28 +117,6 @@ rv_core_critical_regs_save:
|
||||
mv t3, t0
|
||||
csrr t0, mscratch
|
||||
sw t0, RV_SLP_CTX_T0(t3)
|
||||
|
||||
/* writeback dcache is required here!!! */
|
||||
la t0, CACHE_SYNC_MAP_REG
|
||||
li t1, 0x10 /* map l1 dcache */
|
||||
sw t1, 0x0(t0) /* set EXTMEM_CACHE_SYNC_MAP_REG bit 4 */
|
||||
la t2, CACHE_SYNC_ADDR_REG
|
||||
sw zero, 0x0(t2) /* clear EXTMEM_CACHE_SYNC_ADDR_REG */
|
||||
la t0, CACHE_SYNC_SIZE_REG
|
||||
sw zero, 0x0(t0) /* clear EXTMEM_CACHE_SYNC_SIZE_REG */
|
||||
|
||||
la t1, CACHE_SYNC_CTRL_REG
|
||||
lw t2, 0x0(t1)
|
||||
ori t2, t2, 0x4
|
||||
sw t2, 0x0(t1)
|
||||
|
||||
li t0, 0x10 /* SYNC_DONE bit */
|
||||
wait_sync_done:
|
||||
lw t2, 0x0(t1)
|
||||
and t2, t0, t2
|
||||
beqz t2, wait_sync_done
|
||||
|
||||
lw t0, RV_SLP_CTX_T0(t3)
|
||||
lw t1, RV_SLP_CTX_T1(t3)
|
||||
lw t2, RV_SLP_CTX_T2(t3)
|
||||
lw t3, RV_SLP_CTX_T3(t3)
|
||||
|
@ -232,7 +232,7 @@ bool cpu_domain_pd_allowed(void)
|
||||
|
||||
esp_err_t sleep_cpu_configure(bool light_sleep_enable)
|
||||
{
|
||||
#if CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP
|
||||
#if ESP_SLEEP_POWER_DOWN_CPU
|
||||
if (light_sleep_enable) {
|
||||
ESP_RETURN_ON_ERROR(esp_sleep_cpu_retention_init(), TAG, "Failed to enable CPU power down during light sleep.");
|
||||
} else {
|
||||
|
@ -454,7 +454,7 @@ void modem_clock_deselect_lp_clock_source(periph_module_t module)
|
||||
pmu_sleep_enable_hp_sleep_sysclk(false);
|
||||
}
|
||||
modem_clock_hal_enable_wifipwr_clock(MODEM_CLOCK_instance()->hal, false);
|
||||
modem_clock_domain_clk_gate_enable(MODEM_CLOCK_DOMAIN_WIFI, PMU_HP_ICG_MODEM_CODE_SLEEP);
|
||||
modem_clock_domain_clk_gate_enable(MODEM_CLOCK_DOMAIN_WIFIPWR, PMU_HP_ICG_MODEM_CODE_SLEEP);
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
|
@ -646,18 +646,6 @@ void rtc_sleep_init(rtc_sleep_config_t cfg);
|
||||
*/
|
||||
void rtc_sleep_low_init(uint32_t slowclk_period);
|
||||
|
||||
#if CONFIG_ESP_SLEEP_SYSTIMER_STALL_WORKAROUND
|
||||
/**
|
||||
* @brief Configure systimer for esp32c3 systimer stall issue workaround
|
||||
*
|
||||
* This function configures related systimer for esp32c3 systimer stall issue.
|
||||
* Only apply workaround when xtal powered up.
|
||||
*
|
||||
* @param en enable systimer or not
|
||||
*/
|
||||
void rtc_sleep_systimer_enable(bool en);
|
||||
#endif
|
||||
|
||||
#define RTC_GPIO_TRIG_EN BIT(2) //!< GPIO wakeup
|
||||
#define RTC_TIMER_TRIG_EN BIT(3) //!< Timer wakeup
|
||||
#define RTC_WIFI_TRIG_EN BIT(5) //!< WIFI wakeup (light sleep only)
|
||||
|
@ -24,7 +24,7 @@
|
||||
#include "soc/regi2c_dig_reg.h"
|
||||
#include "soc/regi2c_lp_bias.h"
|
||||
#include "hal/efuse_hal.h"
|
||||
#if CONFIG_ESP_SLEEP_SYSTIMER_STALL_WORKAROUND
|
||||
#if SOC_SLEEP_SYSTIMER_STALL_WORKAROUND
|
||||
#include "soc/systimer_reg.h"
|
||||
#endif
|
||||
|
||||
@ -252,17 +252,6 @@ void rtc_sleep_low_init(uint32_t slowclk_period)
|
||||
REG_SET_FIELD(RTC_CNTL_TIMER1_REG, RTC_CNTL_CK8M_WAIT, RTC_CNTL_CK8M_WAIT_SLP_CYCLES);
|
||||
}
|
||||
|
||||
#if CONFIG_ESP_SLEEP_SYSTIMER_STALL_WORKAROUND
|
||||
void rtc_sleep_systimer_enable(bool en)
|
||||
{
|
||||
if (en) {
|
||||
REG_SET_BIT(SYSTIMER_CONF_REG, SYSTIMER_TIMER_UNIT1_WORK_EN);
|
||||
} else {
|
||||
REG_CLR_BIT(SYSTIMER_CONF_REG, SYSTIMER_TIMER_UNIT1_WORK_EN);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static uint32_t rtc_sleep_finish(uint32_t lslp_mem_inf_fpu);
|
||||
|
||||
uint32_t rtc_sleep_start(uint32_t wakeup_opt, uint32_t reject_opt, uint32_t lslp_mem_inf_fpu)
|
||||
|
@ -11,11 +11,14 @@ choice ESP32P4_REV_MIN
|
||||
|
||||
config ESP32P4_REV_MIN_0
|
||||
bool "Rev v0.0"
|
||||
config ESP32P4_REV_MIN_1
|
||||
bool "Rev v0.1"
|
||||
endchoice
|
||||
|
||||
config ESP32P4_REV_MIN_FULL
|
||||
int
|
||||
default 0 if ESP32P4_REV_MIN_0
|
||||
default 1 if ESP32P4_REV_MIN_1
|
||||
|
||||
config ESP_REV_MIN_FULL
|
||||
int
|
||||
|
@ -12,10 +12,13 @@
|
||||
#include "esp_err.h"
|
||||
#include "esp_attr.h"
|
||||
#include "esp_private/regi2c_ctrl.h"
|
||||
#include "esp32p4/rom/cache.h"
|
||||
#include "soc/chip_revision.h"
|
||||
#include "soc/soc.h"
|
||||
#include "soc/regi2c_syspll.h"
|
||||
#include "soc/regi2c_cpll.h"
|
||||
#include "soc/rtc.h"
|
||||
#include "soc/cache_reg.h"
|
||||
#include "soc/pau_reg.h"
|
||||
#include "soc/pmu_reg.h"
|
||||
#include "soc/pmu_struct.h"
|
||||
@ -27,6 +30,7 @@
|
||||
#include "pmu_param.h"
|
||||
#include "esp_rom_sys.h"
|
||||
#include "esp_rom_uart.h"
|
||||
#include "hal/efuse_hal.h"
|
||||
|
||||
#define HP(state) (PMU_MODE_HP_ ## state)
|
||||
#define LP(state) (PMU_MODE_LP_ ## state)
|
||||
@ -283,6 +287,11 @@ void pmu_sleep_shutdown_ldo(void) {
|
||||
CLEAR_PERI_REG_MASK(PMU_HP_ACTIVE_HP_REGULATOR0_REG, PMU_HP_ACTIVE_HP_REGULATOR_XPD);
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR void sleep_writeback_l1_dcache(void) {
|
||||
Cache_WriteBack_All(CACHE_MAP_L1_DCACHE);
|
||||
while (!REG_GET_BIT(CACHE_SYNC_CTRL_REG, CACHE_SYNC_DONE));
|
||||
}
|
||||
|
||||
TCM_IRAM_ATTR uint32_t pmu_sleep_start(uint32_t wakeup_opt, uint32_t reject_opt, uint32_t lslp_mem_inf_fpu, bool dslp)
|
||||
{
|
||||
lp_aon_hal_inform_wakeup_type(dslp);
|
||||
@ -295,6 +304,8 @@ TCM_IRAM_ATTR uint32_t pmu_sleep_start(uint32_t wakeup_opt, uint32_t reject_opt,
|
||||
pmu_ll_hp_clear_reject_intr_status(PMU_instance()->hal->dev);
|
||||
pmu_ll_hp_clear_reject_cause(PMU_instance()->hal->dev);
|
||||
|
||||
sleep_writeback_l1_dcache();
|
||||
|
||||
/* Start entry into sleep mode */
|
||||
pmu_ll_hp_set_sleep_enable(PMU_instance()->hal->dev);
|
||||
|
||||
@ -317,8 +328,11 @@ TCM_IRAM_ATTR bool pmu_sleep_finish(void)
|
||||
}
|
||||
pmu_sleep_shutdown_ldo();
|
||||
|
||||
REGI2C_WRITE_MASK(I2C_CPLL, I2C_CPLL_OC_DIV_7_0, 6); // lower default cpu_pll freq to 400M
|
||||
REGI2C_WRITE_MASK(I2C_SYSPLL, I2C_SYSPLL_OC_DIV_7_0, 8); // lower default sys_pll freq to 480M
|
||||
unsigned chip_version = efuse_hal_chip_revision();
|
||||
if (!ESP_CHIP_REV_ABOVE(chip_version, 1)) {
|
||||
REGI2C_WRITE_MASK(I2C_CPLL, I2C_CPLL_OC_DIV_7_0, 6); // lower default cpu_pll freq to 400M
|
||||
REGI2C_WRITE_MASK(I2C_SYSPLL, I2C_SYSPLL_OC_DIV_7_0, 8); // lower default sys_pll freq to 480M
|
||||
}
|
||||
return pmu_ll_hp_is_sleep_reject(PMU_instance()->hal->dev);
|
||||
}
|
||||
|
||||
|
@ -17,13 +17,16 @@ static void __attribute__((constructor)) esp_random_init(void) { }
|
||||
uint32_t esp_random(void)
|
||||
{
|
||||
uint32_t random_number;
|
||||
assert(getentropy(&random_number, sizeof(random_number)) == 0);
|
||||
int result = getentropy(&random_number, sizeof(random_number));
|
||||
assert(result == 0);
|
||||
(void)result;
|
||||
return random_number;
|
||||
}
|
||||
|
||||
void esp_fill_random(void *buf, size_t len)
|
||||
{
|
||||
assert(buf != NULL);
|
||||
int result;
|
||||
|
||||
// Note that we can't use getentropy() with len > 256 directly (see getentropy man page),
|
||||
// hence reading in chunks
|
||||
@ -31,8 +34,12 @@ void esp_fill_random(void *buf, size_t len)
|
||||
const size_t REST_CHUNK_SIZE = len % GETENTROPY_MAX_LEN;
|
||||
|
||||
for (size_t chunk_num = 0; chunk_num < FULL_CHUNKS_NUM; chunk_num++) {
|
||||
assert(getentropy(buf + chunk_num * GETENTROPY_MAX_LEN, GETENTROPY_MAX_LEN) == 0);
|
||||
result = getentropy(buf + chunk_num * GETENTROPY_MAX_LEN, GETENTROPY_MAX_LEN);
|
||||
assert(result == 0);
|
||||
(void)result;
|
||||
}
|
||||
|
||||
assert(getentropy(buf + FULL_CHUNKS_NUM * GETENTROPY_MAX_LEN, REST_CHUNK_SIZE) == 0);
|
||||
result = getentropy(buf + FULL_CHUNKS_NUM * GETENTROPY_MAX_LEN, REST_CHUNK_SIZE);
|
||||
assert(result == 0);
|
||||
(void)result;
|
||||
}
|
||||
|
@ -30,6 +30,15 @@
|
||||
#include "hal/rtc_io_hal.h"
|
||||
#include "hal/clk_tree_hal.h"
|
||||
|
||||
#if SOC_SLEEP_SYSTIMER_STALL_WORKAROUND
|
||||
#include "hal/systimer_ll.h"
|
||||
#endif
|
||||
|
||||
#if SOC_SLEEP_TGWDT_STOP_WORKAROUND
|
||||
#include "hal/mwdt_ll.h"
|
||||
#include "hal/timer_ll.h"
|
||||
#endif
|
||||
|
||||
#if SOC_PM_SUPPORT_PMU_MODEM_STATE
|
||||
#include "esp_private/pm_impl.h"
|
||||
#endif
|
||||
@ -489,6 +498,52 @@ static void IRAM_ATTR resume_cache(void) {
|
||||
}
|
||||
}
|
||||
|
||||
#if SOC_SLEEP_TGWDT_STOP_WORKAROUND
|
||||
static uint32_t s_stopped_tgwdt_bmap = 0;
|
||||
#endif
|
||||
|
||||
// Must be called from critical sections.
|
||||
static void IRAM_ATTR suspend_timers(uint32_t pd_flags) {
|
||||
if (!(pd_flags & RTC_SLEEP_PD_XTAL)) {
|
||||
#if SOC_SLEEP_TGWDT_STOP_WORKAROUND
|
||||
/* If timegroup implemented task watchdog or interrupt watchdog is running, we have to stop it. */
|
||||
for (uint32_t tg_num = 0; tg_num < SOC_TIMER_GROUPS; ++tg_num) {
|
||||
if (mwdt_ll_check_if_enabled(TIMER_LL_GET_HW(tg_num))) {
|
||||
mwdt_ll_write_protect_disable(TIMER_LL_GET_HW(tg_num));
|
||||
mwdt_ll_disable(TIMER_LL_GET_HW(tg_num));
|
||||
mwdt_ll_write_protect_enable(TIMER_LL_GET_HW(tg_num));
|
||||
s_stopped_tgwdt_bmap |= BIT(tg_num);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if SOC_SLEEP_SYSTIMER_STALL_WORKAROUND
|
||||
for (uint32_t counter_id = 0; counter_id < SOC_SYSTIMER_COUNTER_NUM; ++counter_id) {
|
||||
systimer_ll_enable_counter(&SYSTIMER, counter_id, false);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
// Must be called from critical sections.
|
||||
static void IRAM_ATTR resume_timers(uint32_t pd_flags) {
|
||||
if (!(pd_flags & RTC_SLEEP_PD_XTAL)) {
|
||||
#if SOC_SLEEP_SYSTIMER_STALL_WORKAROUND
|
||||
for (uint32_t counter_id = 0; counter_id < SOC_SYSTIMER_COUNTER_NUM; ++counter_id) {
|
||||
systimer_ll_enable_counter(&SYSTIMER, counter_id, true);
|
||||
}
|
||||
#endif
|
||||
#if SOC_SLEEP_TGWDT_STOP_WORKAROUND
|
||||
for (uint32_t tg_num = 0; tg_num < SOC_TIMER_GROUPS; ++tg_num) {
|
||||
if (s_stopped_tgwdt_bmap & BIT(tg_num)) {
|
||||
mwdt_ll_write_protect_disable(TIMER_LL_GET_HW(tg_num));
|
||||
mwdt_ll_enable(TIMER_LL_GET_HW(tg_num));
|
||||
mwdt_ll_write_protect_enable(TIMER_LL_GET_HW(tg_num));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
// [refactor-todo] provide target logic for body of uart functions below
|
||||
static void IRAM_ATTR flush_uarts(void)
|
||||
{
|
||||
@ -870,22 +925,17 @@ static esp_err_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags, esp_sleep_mode_t m
|
||||
}
|
||||
}
|
||||
|
||||
#if CONFIG_ESP_SLEEP_SYSTIMER_STALL_WORKAROUND
|
||||
if (!(pd_flags & RTC_SLEEP_PD_XTAL)) {
|
||||
rtc_sleep_systimer_enable(false);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (should_skip_sleep) {
|
||||
result = ESP_ERR_SLEEP_REJECT;
|
||||
#if CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP && !CONFIG_FREERTOS_UNICORE && SOC_PM_CPU_RETENTION_BY_SW
|
||||
#if ESP_SLEEP_POWER_DOWN_CPU && !CONFIG_FREERTOS_UNICORE && SOC_PM_CPU_RETENTION_BY_SW
|
||||
esp_sleep_cpu_skip_retention();
|
||||
#endif
|
||||
} else {
|
||||
#if CONFIG_ESP_SLEEP_DEBUG
|
||||
if (s_sleep_ctx != NULL) {
|
||||
s_sleep_ctx->wakeup_triggers = s_config.wakeup_triggers;
|
||||
}
|
||||
if (s_sleep_ctx != NULL) {
|
||||
s_sleep_ctx->wakeup_triggers = s_config.wakeup_triggers;
|
||||
}
|
||||
#endif
|
||||
if (deep_sleep) {
|
||||
#if !SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP
|
||||
@ -913,6 +963,7 @@ static esp_err_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags, esp_sleep_mode_t m
|
||||
result = rtc_deep_sleep_start(s_config.wakeup_triggers, reject_triggers);
|
||||
#endif
|
||||
} else {
|
||||
suspend_timers(pd_flags);
|
||||
/* Cache Suspend 1: will wait cache idle in cache suspend */
|
||||
suspend_cache();
|
||||
/* On esp32c6, only the lp_aon pad hold function can only hold the GPIO state in the active mode.
|
||||
@ -942,14 +993,14 @@ static esp_err_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags, esp_sleep_mode_t m
|
||||
#endif
|
||||
|
||||
#if SOC_PMU_SUPPORTED
|
||||
#if SOC_PM_CPU_RETENTION_BY_SW && CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP
|
||||
#if SOC_PM_CPU_RETENTION_BY_SW && ESP_SLEEP_POWER_DOWN_CPU
|
||||
esp_sleep_execute_event_callbacks(SLEEP_EVENT_HW_GOTO_SLEEP, (void *)0);
|
||||
if (pd_flags & (PMU_SLEEP_PD_CPU | PMU_SLEEP_PD_TOP)) {
|
||||
result = esp_sleep_cpu_retention(pmu_sleep_start, s_config.wakeup_triggers, reject_triggers, config.power.hp_sys.dig_power.mem_dslp, deep_sleep);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
#if !CONFIG_FREERTOS_UNICORE && CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP && SOC_PM_CPU_RETENTION_BY_SW
|
||||
#if !CONFIG_FREERTOS_UNICORE && ESP_SLEEP_POWER_DOWN_CPU && SOC_PM_CPU_RETENTION_BY_SW
|
||||
// Skip smp retention if CPU power domain power-down is not allowed
|
||||
esp_sleep_cpu_skip_retention();
|
||||
#endif
|
||||
@ -977,13 +1028,8 @@ static esp_err_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags, esp_sleep_mode_t m
|
||||
#endif
|
||||
/* Cache Resume 1: Resume cache for continue running*/
|
||||
resume_cache();
|
||||
resume_timers(pd_flags);
|
||||
}
|
||||
|
||||
#if CONFIG_ESP_SLEEP_SYSTIMER_STALL_WORKAROUND
|
||||
if (!(pd_flags & RTC_SLEEP_PD_XTAL)) {
|
||||
rtc_sleep_systimer_enable(true);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#if CONFIG_ESP_SLEEP_CACHE_SAFE_ASSERTION
|
||||
if (pd_flags & RTC_SLEEP_PD_VDDSDIO) {
|
||||
@ -1256,7 +1302,7 @@ esp_err_t esp_light_sleep_start(void)
|
||||
#endif
|
||||
|
||||
#if !CONFIG_FREERTOS_UNICORE
|
||||
#if CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP && SOC_PM_CPU_RETENTION_BY_SW
|
||||
#if ESP_SLEEP_POWER_DOWN_CPU && SOC_PM_CPU_RETENTION_BY_SW
|
||||
sleep_smp_cpu_sleep_prepare();
|
||||
#else
|
||||
esp_ipc_isr_stall_other_cpu();
|
||||
@ -1374,7 +1420,7 @@ esp_err_t esp_light_sleep_start(void)
|
||||
// Enter sleep, then wait for flash to be ready on wakeup
|
||||
err = esp_light_sleep_inner(pd_flags, flash_enable_time_us);
|
||||
}
|
||||
#if !CONFIG_FREERTOS_UNICORE && CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP && SOC_PM_CPU_RETENTION_BY_SW
|
||||
#if !CONFIG_FREERTOS_UNICORE && ESP_SLEEP_POWER_DOWN_CPU && SOC_PM_CPU_RETENTION_BY_SW
|
||||
if (err != ESP_OK) {
|
||||
esp_sleep_cpu_skip_retention();
|
||||
}
|
||||
@ -1412,7 +1458,7 @@ esp_err_t esp_light_sleep_start(void)
|
||||
|
||||
#if !CONFIG_FREERTOS_UNICORE
|
||||
esp_ipc_isr_stall_resume();
|
||||
#if CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP && SOC_PM_CPU_RETENTION_BY_SW
|
||||
#if ESP_SLEEP_POWER_DOWN_CPU && SOC_PM_CPU_RETENTION_BY_SW
|
||||
sleep_smp_cpu_wakeup_prepare();
|
||||
#else
|
||||
esp_ipc_isr_release_other_cpu();
|
||||
@ -2063,7 +2109,7 @@ esp_err_t esp_sleep_pd_config(esp_sleep_pd_domain_t domain, esp_sleep_pd_option_
|
||||
#if SOC_PM_SUPPORT_TOP_PD
|
||||
FORCE_INLINE_ATTR bool top_domain_pd_allowed(void) {
|
||||
bool top_pd_allowed = true;
|
||||
#if CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP
|
||||
#if ESP_SLEEP_POWER_DOWN_CPU
|
||||
top_pd_allowed &= cpu_domain_pd_allowed();
|
||||
#else
|
||||
top_pd_allowed = false;
|
||||
@ -2179,7 +2225,7 @@ static uint32_t get_power_down_flags(void)
|
||||
}
|
||||
#endif
|
||||
|
||||
#if SOC_PM_SUPPORT_CPU_PD
|
||||
#if SOC_PM_SUPPORT_CPU_PD && ESP_SLEEP_POWER_DOWN_CPU
|
||||
if ((s_config.domain[ESP_PD_DOMAIN_CPU].pd_option != ESP_PD_OPTION_ON) && cpu_domain_pd_allowed()) {
|
||||
pd_flags |= RTC_SLEEP_PD_CPU;
|
||||
}
|
||||
|
@ -8,12 +8,20 @@ if(CONFIG_SOC_GDMA_SUPPORTED)
|
||||
list(APPEND srcs "test_gdma.c")
|
||||
endif()
|
||||
|
||||
if(CONFIG_SOC_ETM_SUPPORTED AND CONFIG_SOC_GDMA_SUPPORT_ETM)
|
||||
list(APPEND srcs "test_gdma_etm.c")
|
||||
endif()
|
||||
|
||||
if(CONFIG_SOC_DW_GDMA_SUPPORTED)
|
||||
list(APPEND srcs "test_dw_gdma.c")
|
||||
endif()
|
||||
|
||||
if(CONFIG_SOC_GDMA_SUPPORT_CRC)
|
||||
list(APPEND srcs "test_gdma_crc.c")
|
||||
endif()
|
||||
|
||||
# In order for the cases defined by `TEST_CASE` to be linked into the final elf,
|
||||
# the component can be registered as WHOLE_ARCHIVE
|
||||
idf_component_register(SRCS ${srcs}
|
||||
PRIV_REQUIRES unity esp_mm
|
||||
PRIV_REQUIRES unity esp_mm esp_driver_gpio
|
||||
WHOLE_ARCHIVE)
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include "esp_async_memcpy.h"
|
||||
#include "soc/soc_caps.h"
|
||||
#include "hal/dma_types.h"
|
||||
#include "esp_dma_utils.h"
|
||||
|
||||
#define IDF_LOG_PERFORMANCE(item, value_fmt, value, ...) \
|
||||
printf("[Performance][%s]: " value_fmt "\n", item, value, ##__VA_ARGS__)
|
||||
@ -26,10 +27,7 @@
|
||||
#define ALIGN_DOWN(size, align) ((size) & ~((align) - 1))
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32P4
|
||||
#define TEST_MEMCPY_DST_BASE_ALIGN 64
|
||||
#define TEST_MEMCPY_BUFFER_SIZE_MUST_ALIGN_CACHE 1
|
||||
#else
|
||||
#define TEST_MEMCPY_DST_BASE_ALIGN 4
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
@ -56,23 +54,23 @@ static void async_memcpy_setup_testbench(memcpy_testbench_context_t *test_contex
|
||||
uint8_t *dst_buf = NULL;
|
||||
uint8_t *from_addr = NULL;
|
||||
uint8_t *to_addr = NULL;
|
||||
#if CONFIG_SPIRAM && SOC_AHB_GDMA_SUPPORT_PSRAM
|
||||
|
||||
esp_dma_mem_info_t mem_info = {
|
||||
.dma_alignment_bytes = test_context->align,
|
||||
};
|
||||
if (test_context->src_in_psram) {
|
||||
src_buf = heap_caps_aligned_alloc(test_context->align, buffer_size, MALLOC_CAP_SPIRAM);
|
||||
mem_info.extra_heap_caps = MALLOC_CAP_SPIRAM;
|
||||
} else {
|
||||
src_buf = heap_caps_aligned_alloc(test_context->align, buffer_size, MALLOC_CAP_8BIT | MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL);
|
||||
mem_info.extra_heap_caps = 0;
|
||||
}
|
||||
TEST_ESP_OK(esp_dma_capable_calloc(1, buffer_size, &mem_info, (void **)&src_buf, NULL));
|
||||
if (test_context->dst_in_psram) {
|
||||
dst_buf = heap_caps_aligned_alloc(test_context->align, buffer_size, MALLOC_CAP_SPIRAM);
|
||||
mem_info.extra_heap_caps = MALLOC_CAP_SPIRAM;
|
||||
} else {
|
||||
dst_buf = heap_caps_aligned_alloc(test_context->align, buffer_size, MALLOC_CAP_8BIT | MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL);
|
||||
mem_info.extra_heap_caps = 0;
|
||||
}
|
||||
#else
|
||||
src_buf = heap_caps_aligned_alloc(test_context->align, buffer_size, MALLOC_CAP_8BIT | MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL);
|
||||
dst_buf = heap_caps_aligned_alloc(test_context->align, buffer_size, MALLOC_CAP_8BIT | MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL);
|
||||
#endif
|
||||
TEST_ASSERT_NOT_NULL_MESSAGE(src_buf, "allocate source buffer failed");
|
||||
TEST_ASSERT_NOT_NULL_MESSAGE(dst_buf, "allocate destination buffer failed");
|
||||
TEST_ESP_OK(esp_dma_capable_calloc(1, buffer_size, &mem_info, (void **)&dst_buf, NULL));
|
||||
|
||||
// adding extra offset
|
||||
from_addr = src_buf + test_context->offset;
|
||||
to_addr = dst_buf;
|
||||
@ -113,8 +111,13 @@ TEST_CASE("memory copy the same buffer with different content", "[async mcp]")
|
||||
async_memcpy_config_t config = ASYNC_MEMCPY_DEFAULT_CONFIG();
|
||||
async_memcpy_handle_t driver = NULL;
|
||||
TEST_ESP_OK(esp_async_memcpy_install(&config, &driver));
|
||||
uint8_t *sbuf = heap_caps_aligned_alloc(TEST_MEMCPY_DST_BASE_ALIGN, 256, MALLOC_CAP_8BIT | MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL);
|
||||
uint8_t *dbuf = heap_caps_aligned_alloc(TEST_MEMCPY_DST_BASE_ALIGN, 256, MALLOC_CAP_8BIT | MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL);
|
||||
uint8_t *sbuf = NULL;
|
||||
uint8_t *dbuf = NULL;
|
||||
esp_dma_mem_info_t mem_info = {
|
||||
.dma_alignment_bytes = 4,
|
||||
};
|
||||
TEST_ESP_OK(esp_dma_capable_calloc(1, 256, &mem_info, (void **)&sbuf, NULL));
|
||||
TEST_ESP_OK(esp_dma_capable_calloc(1, 256, &mem_info, (void **)&dbuf, NULL));
|
||||
for (int j = 0; j < 20; j++) {
|
||||
TEST_ESP_OK(esp_async_memcpy(driver, dbuf, sbuf, 256, NULL, NULL));
|
||||
vTaskDelay(pdMS_TO_TICKS(10));
|
||||
@ -136,7 +139,7 @@ static void test_memory_copy_one_by_one(async_memcpy_handle_t driver)
|
||||
{
|
||||
uint32_t aligned_test_buffer_size[] = {256, 512, 1024, 2048, 4096};
|
||||
memcpy_testbench_context_t test_context = {
|
||||
.align = TEST_MEMCPY_DST_BASE_ALIGN,
|
||||
.align = 4,
|
||||
};
|
||||
|
||||
for (int i = 0; i < sizeof(aligned_test_buffer_size) / sizeof(aligned_test_buffer_size[0]); i++) {
|
||||
@ -216,9 +219,13 @@ TEST_CASE("memory copy done callback", "[async mcp]")
|
||||
async_memcpy_handle_t driver = NULL;
|
||||
TEST_ESP_OK(esp_async_memcpy_install(&config, &driver));
|
||||
|
||||
uint8_t *src_buf = heap_caps_aligned_alloc(TEST_MEMCPY_DST_BASE_ALIGN, 256, MALLOC_CAP_8BIT | MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL);
|
||||
// destination address should aligned to data cache line
|
||||
uint8_t *dst_buf = heap_caps_aligned_alloc(TEST_MEMCPY_DST_BASE_ALIGN, 256, MALLOC_CAP_8BIT | MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL);
|
||||
uint8_t *src_buf = NULL;
|
||||
uint8_t *dst_buf = NULL;
|
||||
esp_dma_mem_info_t mem_info = {
|
||||
.dma_alignment_bytes = 4,
|
||||
};
|
||||
TEST_ESP_OK(esp_dma_capable_calloc(1, 256, &mem_info, (void **)&src_buf, NULL));
|
||||
TEST_ESP_OK(esp_dma_capable_calloc(1, 256, &mem_info, (void **)&dst_buf, NULL));
|
||||
|
||||
SemaphoreHandle_t sem = xSemaphoreCreateBinary();
|
||||
TEST_ESP_OK(esp_async_memcpy(driver, dst_buf, src_buf, 256, test_async_memcpy_cb_v1, sem));
|
||||
@ -235,38 +242,39 @@ TEST_CASE("memory copy by DMA on the fly", "[async mcp]")
|
||||
async_memcpy_handle_t driver = NULL;
|
||||
TEST_ESP_OK(esp_async_memcpy_install(&config, &driver));
|
||||
|
||||
uint32_t test_buffer_len[] = {512, 1024, 2048, 4096, 5011};
|
||||
uint32_t aligned_test_buffer_size[] = {512, 1024, 2048, 4096, 4608};
|
||||
memcpy_testbench_context_t test_context[5] = {
|
||||
[0 ... 4] = {
|
||||
.align = TEST_MEMCPY_DST_BASE_ALIGN,
|
||||
.align = 4,
|
||||
}
|
||||
};
|
||||
|
||||
// Aligned case
|
||||
for (int i = 0; i < sizeof(test_buffer_len) / sizeof(test_buffer_len[0]); i++) {
|
||||
for (int i = 0; i < sizeof(aligned_test_buffer_size) / sizeof(aligned_test_buffer_size[0]); i++) {
|
||||
test_context[i].seed = i;
|
||||
test_context[i].buffer_size = test_buffer_len[i];
|
||||
test_context[i].buffer_size = aligned_test_buffer_size[i];
|
||||
async_memcpy_setup_testbench(&test_context[i]);
|
||||
}
|
||||
for (int i = 0; i < sizeof(test_buffer_len) / sizeof(test_buffer_len[0]); i++) {
|
||||
for (int i = 0; i < sizeof(aligned_test_buffer_size) / sizeof(aligned_test_buffer_size[0]); i++) {
|
||||
TEST_ESP_OK(esp_async_memcpy(driver, test_context[i].to_addr, test_context[i].from_addr, test_context[i].copy_size, NULL, NULL));
|
||||
}
|
||||
for (int i = 0; i < sizeof(test_buffer_len) / sizeof(test_buffer_len[0]); i++) {
|
||||
for (int i = 0; i < sizeof(aligned_test_buffer_size) / sizeof(aligned_test_buffer_size[0]); i++) {
|
||||
async_memcpy_verify_and_clear_testbench(i, test_context[i].copy_size, test_context[i].src_buf, test_context[i].dst_buf, test_context[i].from_addr, test_context[i].to_addr);
|
||||
}
|
||||
|
||||
#if !TEST_MEMCPY_BUFFER_SIZE_MUST_ALIGN_CACHE
|
||||
uint32_t unaligned_test_buffer_size[] = {511, 1023, 2047, 4095, 5011};
|
||||
// Non-aligned case
|
||||
for (int i = 0; i < sizeof(test_buffer_len) / sizeof(test_buffer_len[0]); i++) {
|
||||
for (int i = 0; i < sizeof(unaligned_test_buffer_size) / sizeof(unaligned_test_buffer_size[0]); i++) {
|
||||
test_context[i].seed = i;
|
||||
test_context[i].buffer_size = test_buffer_len[i];
|
||||
test_context[i].buffer_size = unaligned_test_buffer_size[i];
|
||||
test_context[i].offset = 3;
|
||||
async_memcpy_setup_testbench(&test_context[i]);
|
||||
}
|
||||
for (int i = 0; i < sizeof(test_buffer_len) / sizeof(test_buffer_len[0]); i++) {
|
||||
for (int i = 0; i < sizeof(unaligned_test_buffer_size) / sizeof(unaligned_test_buffer_size[0]); i++) {
|
||||
TEST_ESP_OK(esp_async_memcpy(driver, test_context[i].to_addr, test_context[i].from_addr, test_context[i].copy_size, NULL, NULL));
|
||||
}
|
||||
for (int i = 0; i < sizeof(test_buffer_len) / sizeof(test_buffer_len[0]); i++) {
|
||||
for (int i = 0; i < sizeof(unaligned_test_buffer_size) / sizeof(unaligned_test_buffer_size[0]); i++) {
|
||||
async_memcpy_verify_and_clear_testbench(i, test_context[i].copy_size, test_context[i].src_buf, test_context[i].dst_buf, test_context[i].from_addr, test_context[i].to_addr);
|
||||
}
|
||||
#endif
|
||||
@ -328,7 +336,7 @@ static void memcpy_performance_test(uint32_t buffer_size)
|
||||
IDF_LOG_PERFORMANCE("CPU_COPY", "%.2f MB/s, dir: SRAM->SRAM, size: %zu Bytes", throughput, test_context.buffer_size);
|
||||
async_memcpy_verify_and_clear_testbench(test_context.seed, test_context.copy_size, test_context.src_buf, test_context.dst_buf, test_context.from_addr, test_context.to_addr);
|
||||
|
||||
#if CONFIG_SPIRAM && SOC_AHB_GDMA_SUPPORT_PSRAM
|
||||
#if SOC_AHB_GDMA_SUPPORT_PSRAM
|
||||
// 2. PSRAM->PSRAM
|
||||
test_context.src_in_psram = true;
|
||||
test_context.dst_in_psram = true;
|
||||
|
@ -56,17 +56,20 @@ TEST_CASE("DW_GDMA M2M Test: Contiguous Mode", "[DW_GDMA]")
|
||||
TEST_ASSERT_NOT_NULL(done_sem);
|
||||
|
||||
printf("prepare the source and destination buffers\r\n");
|
||||
uint8_t *src_buf = heap_caps_aligned_calloc(64, 1, 256, MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
|
||||
uint8_t *dst_buf = heap_caps_aligned_calloc(64, 1, 256, MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
|
||||
size_t sram_alignment = 0;
|
||||
TEST_ESP_OK(esp_cache_get_alignment(0, &sram_alignment));
|
||||
size_t alignment = MAX(sram_alignment, 8);
|
||||
uint8_t *src_buf = heap_caps_aligned_calloc(alignment, 1, 256, MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
|
||||
uint8_t *dst_buf = heap_caps_aligned_calloc(alignment, 1, 256, MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
|
||||
TEST_ASSERT_NOT_NULL(src_buf);
|
||||
TEST_ASSERT_NOT_NULL(dst_buf);
|
||||
for (int i = 0; i < 256; i++) {
|
||||
src_buf[i] = i;
|
||||
}
|
||||
#if CONFIG_IDF_TARGET_ESP32P4
|
||||
// do write-back for the source data because it's in the cache
|
||||
TEST_ESP_OK(esp_cache_msync((void *)src_buf, 256, ESP_CACHE_MSYNC_FLAG_DIR_C2M));
|
||||
#endif
|
||||
if (sram_alignment) {
|
||||
// do write-back for the source data because it's in the cache
|
||||
TEST_ESP_OK(esp_cache_msync((void *)src_buf, 256, ESP_CACHE_MSYNC_FLAG_DIR_C2M));
|
||||
}
|
||||
|
||||
printf("allocate a channel for memory copy\r\n");
|
||||
dw_gdma_channel_static_config_t static_config = {
|
||||
@ -117,10 +120,10 @@ TEST_CASE("DW_GDMA M2M Test: Contiguous Mode", "[DW_GDMA]")
|
||||
TEST_ASSERT_EQUAL(pdFALSE, xSemaphoreTake(done_sem, pdMS_TO_TICKS(100)));
|
||||
|
||||
printf("check the memory copy result\r\n");
|
||||
#if CONFIG_IDF_TARGET_ESP32P4
|
||||
// the destination data are not reflected to the cache, so do an invalidate to ask the cache load new data
|
||||
TEST_ESP_OK(esp_cache_msync((void *)dst_buf, 256, ESP_CACHE_MSYNC_FLAG_DIR_M2C));
|
||||
#endif
|
||||
if (sram_alignment) {
|
||||
// the destination data are not reflected to the cache, so do an invalidate to ask the cache load new data
|
||||
TEST_ESP_OK(esp_cache_msync((void *)dst_buf, 256, ESP_CACHE_MSYNC_FLAG_DIR_M2C));
|
||||
}
|
||||
for (int i = 0; i < 256; i++) {
|
||||
TEST_ASSERT_EQUAL_UINT8(i, dst_buf[i]);
|
||||
}
|
||||
@ -145,17 +148,20 @@ TEST_CASE("DW_GDMA M2M Test: Reload Mode", "[DW_GDMA]")
|
||||
TEST_ASSERT_NOT_NULL(done_sem);
|
||||
|
||||
printf("prepare the source and destination buffers\r\n");
|
||||
uint8_t *src_buf = heap_caps_aligned_calloc(64, 1, 256, MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
|
||||
uint8_t *dst_buf = heap_caps_aligned_calloc(64, 1, 256, MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
|
||||
size_t sram_alignment = 0;
|
||||
TEST_ESP_OK(esp_cache_get_alignment(0, &sram_alignment));
|
||||
size_t alignment = MAX(sram_alignment, 8);
|
||||
uint8_t *src_buf = heap_caps_aligned_calloc(alignment, 1, 256, MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
|
||||
uint8_t *dst_buf = heap_caps_aligned_calloc(alignment, 1, 256, MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
|
||||
TEST_ASSERT_NOT_NULL(src_buf);
|
||||
TEST_ASSERT_NOT_NULL(dst_buf);
|
||||
for (int i = 0; i < 256; i++) {
|
||||
src_buf[i] = i;
|
||||
}
|
||||
#if CONFIG_IDF_TARGET_ESP32P4
|
||||
// do write-back for the source data because it's in the cache
|
||||
TEST_ESP_OK(esp_cache_msync((void *)src_buf, 256, ESP_CACHE_MSYNC_FLAG_DIR_C2M));
|
||||
#endif
|
||||
if (sram_alignment) {
|
||||
// do write-back for the source data because it's in the cache
|
||||
TEST_ESP_OK(esp_cache_msync((void *)src_buf, 256, ESP_CACHE_MSYNC_FLAG_DIR_C2M));
|
||||
}
|
||||
|
||||
printf("allocate a channel for memory copy\r\n");
|
||||
dw_gdma_channel_static_config_t static_config = {
|
||||
@ -212,10 +218,10 @@ TEST_CASE("DW_GDMA M2M Test: Reload Mode", "[DW_GDMA]")
|
||||
TEST_ASSERT_EQUAL(pdTRUE, xSemaphoreTake(done_sem, pdMS_TO_TICKS(100)));
|
||||
|
||||
printf("check the memory copy result\r\n");
|
||||
#if CONFIG_IDF_TARGET_ESP32P4
|
||||
// the destination data are not reflected to the cache, so do an invalidate to ask the cache load new data
|
||||
TEST_ESP_OK(esp_cache_msync((void *)dst_buf, 256, ESP_CACHE_MSYNC_FLAG_DIR_M2C));
|
||||
#endif
|
||||
if (sram_alignment) {
|
||||
// the destination data are not reflected to the cache, so do an invalidate to ask the cache load new data
|
||||
TEST_ESP_OK(esp_cache_msync((void *)dst_buf, 256, ESP_CACHE_MSYNC_FLAG_DIR_M2C));
|
||||
}
|
||||
for (int i = 0; i < 256; i++) {
|
||||
TEST_ASSERT_EQUAL_UINT8(i, dst_buf[i]);
|
||||
}
|
||||
@ -264,17 +270,20 @@ TEST_CASE("DW_GDMA M2M Test: Shadow Mode", "[DW_GDMA]")
|
||||
TEST_ASSERT_NOT_NULL(done_sem);
|
||||
|
||||
printf("prepare the source and destination buffers\r\n");
|
||||
uint8_t *src_buf = heap_caps_aligned_calloc(64, 1, 256, MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
|
||||
uint8_t *dst_buf = heap_caps_aligned_calloc(64, 1, 256, MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
|
||||
size_t sram_alignment = 0;
|
||||
TEST_ESP_OK(esp_cache_get_alignment(0, &sram_alignment));
|
||||
size_t alignment = MAX(sram_alignment, 8);
|
||||
uint8_t *src_buf = heap_caps_aligned_calloc(alignment, 1, 256, MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
|
||||
uint8_t *dst_buf = heap_caps_aligned_calloc(alignment, 1, 256, MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
|
||||
TEST_ASSERT_NOT_NULL(src_buf);
|
||||
TEST_ASSERT_NOT_NULL(dst_buf);
|
||||
for (int i = 0; i < 256; i++) {
|
||||
src_buf[i] = i;
|
||||
}
|
||||
#if CONFIG_IDF_TARGET_ESP32P4
|
||||
// do write-back for the source data because it's in the cache
|
||||
TEST_ESP_OK(esp_cache_msync((void *)src_buf, 256, ESP_CACHE_MSYNC_FLAG_DIR_C2M));
|
||||
#endif
|
||||
if (sram_alignment) {
|
||||
// do write-back for the source data because it's in the cache
|
||||
TEST_ESP_OK(esp_cache_msync((void *)src_buf, 256, ESP_CACHE_MSYNC_FLAG_DIR_C2M));
|
||||
}
|
||||
|
||||
printf("allocate a channel for memory copy\r\n");
|
||||
dw_gdma_channel_static_config_t static_config = {
|
||||
@ -334,10 +343,10 @@ TEST_CASE("DW_GDMA M2M Test: Shadow Mode", "[DW_GDMA]")
|
||||
TEST_ASSERT_EQUAL_UINT8(1, user_data.count);
|
||||
|
||||
printf("check the memory copy result\r\n");
|
||||
#if CONFIG_IDF_TARGET_ESP32P4
|
||||
// the destination data are not reflected to the cache, so do an invalidate to ask the cache load new data
|
||||
TEST_ESP_OK(esp_cache_msync((void *)dst_buf, 256, ESP_CACHE_MSYNC_FLAG_DIR_M2C));
|
||||
#endif
|
||||
if (sram_alignment) {
|
||||
// the destination data are not reflected to the cache, so do an invalidate to ask the cache load new data
|
||||
TEST_ESP_OK(esp_cache_msync((void *)dst_buf, 256, ESP_CACHE_MSYNC_FLAG_DIR_M2C));
|
||||
}
|
||||
for (int i = 0; i < 256; i++) {
|
||||
TEST_ASSERT_EQUAL_UINT8(i, dst_buf[i]);
|
||||
}
|
||||
@ -387,17 +396,20 @@ TEST_CASE("DW_GDMA M2M Test: Link-List Mode", "[DW_GDMA]")
|
||||
TEST_ASSERT_NOT_NULL(done_sem);
|
||||
|
||||
printf("prepare the source and destination buffers\r\n");
|
||||
uint8_t *src_buf = heap_caps_aligned_calloc(64, 1, 256, MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
|
||||
uint8_t *dst_buf = heap_caps_aligned_calloc(64, 1, 256, MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
|
||||
size_t sram_alignment = 0;
|
||||
TEST_ESP_OK(esp_cache_get_alignment(0, &sram_alignment));
|
||||
size_t alignment = MAX(sram_alignment, 8);
|
||||
uint8_t *src_buf = heap_caps_aligned_calloc(alignment, 1, 256, MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
|
||||
uint8_t *dst_buf = heap_caps_aligned_calloc(alignment, 1, 256, MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
|
||||
TEST_ASSERT_NOT_NULL(src_buf);
|
||||
TEST_ASSERT_NOT_NULL(dst_buf);
|
||||
for (int i = 0; i < 256; i++) {
|
||||
src_buf[i] = i;
|
||||
}
|
||||
#if CONFIG_IDF_TARGET_ESP32P4
|
||||
// do write-back for the source data because it's in the cache
|
||||
TEST_ESP_OK(esp_cache_msync((void *)src_buf, 256, ESP_CACHE_MSYNC_FLAG_DIR_C2M));
|
||||
#endif
|
||||
if (sram_alignment) {
|
||||
// do write-back for the source data because it's in the cache
|
||||
TEST_ESP_OK(esp_cache_msync((void *)src_buf, 256, ESP_CACHE_MSYNC_FLAG_DIR_C2M));
|
||||
}
|
||||
|
||||
printf("allocate a channel for memory copy\r\n");
|
||||
dw_gdma_channel_static_config_t static_config = {
|
||||
@ -472,10 +484,10 @@ TEST_CASE("DW_GDMA M2M Test: Link-List Mode", "[DW_GDMA]")
|
||||
TEST_ASSERT_EQUAL(pdTRUE, xSemaphoreTake(done_sem, pdMS_TO_TICKS(1000)));
|
||||
|
||||
printf("check the memory copy result\r\n");
|
||||
#if CONFIG_IDF_TARGET_ESP32P4
|
||||
// the destination data are not reflected to the cache, so do an invalidate to ask the cache load new data
|
||||
TEST_ESP_OK(esp_cache_msync((void *)dst_buf, 256, ESP_CACHE_MSYNC_FLAG_DIR_M2C));
|
||||
#endif
|
||||
if (sram_alignment) {
|
||||
// the destination data are not reflected to the cache, so do an invalidate to ask the cache load new data
|
||||
TEST_ESP_OK(esp_cache_msync((void *)dst_buf, 256, ESP_CACHE_MSYNC_FLAG_DIR_M2C));
|
||||
}
|
||||
for (int i = 0; i < 256; i++) {
|
||||
TEST_ASSERT_EQUAL_UINT8(i, dst_buf[i]);
|
||||
}
|
||||
@ -504,10 +516,10 @@ TEST_CASE("DW_GDMA M2M Test: Link-List Mode", "[DW_GDMA]")
|
||||
TEST_ASSERT_EQUAL_UINT8(1, user_data.count);
|
||||
|
||||
printf("check the memory copy result\r\n");
|
||||
#if CONFIG_IDF_TARGET_ESP32P4
|
||||
// the destination data are not reflected to the cache, so do an invalidate to ask the cache load new data
|
||||
TEST_ESP_OK(esp_cache_msync((void *)dst_buf, 256, ESP_CACHE_MSYNC_FLAG_DIR_M2C));
|
||||
#endif
|
||||
if (sram_alignment) {
|
||||
// the destination data are not reflected to the cache, so do an invalidate to ask the cache load new data
|
||||
TEST_ESP_OK(esp_cache_msync((void *)dst_buf, 256, ESP_CACHE_MSYNC_FLAG_DIR_M2C));
|
||||
}
|
||||
for (int i = 0; i < 256; i++) {
|
||||
TEST_ASSERT_EQUAL_UINT8(i, dst_buf[i]);
|
||||
}
|
||||
@ -536,10 +548,10 @@ TEST_CASE("DW_GDMA M2M Test: memory set with fixed address", "[DW_GDMA]")
|
||||
src_buf[i] = 0;
|
||||
}
|
||||
src_buf[0] = 66;
|
||||
#if CONFIG_IDF_TARGET_ESP32P4
|
||||
// do write-back for the source data because it's in the cache
|
||||
TEST_ESP_OK(esp_cache_msync((void *)src_buf, 256, ESP_CACHE_MSYNC_FLAG_DIR_C2M));
|
||||
#endif
|
||||
if (ext_mem_alignment) {
|
||||
// do write-back for the source data because it's in the cache
|
||||
TEST_ESP_OK(esp_cache_msync((void *)src_buf, 256, ESP_CACHE_MSYNC_FLAG_DIR_C2M));
|
||||
}
|
||||
|
||||
printf("allocate a channel for memory set\r\n");
|
||||
dw_gdma_channel_static_config_t static_config = {
|
||||
@ -581,10 +593,10 @@ TEST_CASE("DW_GDMA M2M Test: memory set with fixed address", "[DW_GDMA]")
|
||||
vTaskDelay(pdMS_TO_TICKS(100));
|
||||
|
||||
printf("check the memory set result\r\n");
|
||||
#if CONFIG_IDF_TARGET_ESP32P4
|
||||
// the destination data are not reflected to the cache, so do an invalidate to ask the cache load new data
|
||||
TEST_ESP_OK(esp_cache_msync((void *)dst_buf, 256, ESP_CACHE_MSYNC_FLAG_DIR_M2C));
|
||||
#endif
|
||||
if (int_mem_alignment) {
|
||||
// the destination data are not reflected to the cache, so do an invalidate to ask the cache load new data
|
||||
TEST_ESP_OK(esp_cache_msync((void *)dst_buf, 256, ESP_CACHE_MSYNC_FLAG_DIR_M2C));
|
||||
}
|
||||
for (int i = 0; i < 256; i++) {
|
||||
TEST_ASSERT_EQUAL_UINT8(66, dst_buf[i]);
|
||||
}
|
||||
|
@ -1,10 +1,11 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
#include <sys/param.h>
|
||||
#include "sdkconfig.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
@ -16,6 +17,7 @@
|
||||
#include "soc/soc_caps.h"
|
||||
#include "hal/gdma_ll.h"
|
||||
#include "hal/cache_ll.h"
|
||||
#include "hal/cache_hal.h"
|
||||
#include "esp_cache.h"
|
||||
|
||||
TEST_CASE("GDMA channel allocation", "[GDMA]")
|
||||
@ -174,80 +176,71 @@ static void test_gdma_m2m_mode(gdma_channel_handle_t tx_chan, gdma_channel_handl
|
||||
TEST_ESP_OK(gdma_connect(tx_chan, m2m_trigger));
|
||||
TEST_ESP_OK(gdma_connect(rx_chan, m2m_trigger));
|
||||
|
||||
uint8_t *src_buf = heap_caps_aligned_alloc(64, 256, MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
|
||||
uint8_t *dst_buf = heap_caps_aligned_alloc(64, 256, MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
|
||||
// allocate the source and destination buffer from SRAM
|
||||
// |--------------------------------------------------|
|
||||
// | 128 bytes DMA descriptor | 128 bytes data buffer |
|
||||
// |--------------------------------------------------|
|
||||
size_t sram_alignment = cache_hal_get_cache_line_size(CACHE_LL_LEVEL_INT_MEM, CACHE_TYPE_DATA);
|
||||
size_t alignment = MAX(sram_alignment, 8);
|
||||
uint8_t *src_buf = heap_caps_aligned_calloc(alignment, 1, 256, MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
|
||||
uint8_t *dst_buf = heap_caps_aligned_calloc(alignment, 1, 256, MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
|
||||
TEST_ASSERT_NOT_NULL(src_buf);
|
||||
TEST_ASSERT_NOT_NULL(dst_buf);
|
||||
memset(src_buf, 0, 256);
|
||||
memset(dst_buf, 0, 256);
|
||||
|
||||
dma_descriptor_align8_t *tx_descs = (dma_descriptor_align8_t *) src_buf;
|
||||
dma_descriptor_align8_t *rx_descs = (dma_descriptor_align8_t *) dst_buf;
|
||||
uint8_t *src_data = src_buf + 64;
|
||||
uint8_t *dst_data = dst_buf + 64;
|
||||
uint8_t *src_data = src_buf + 128;
|
||||
uint8_t *dst_data = dst_buf + 128;
|
||||
|
||||
// prepare the source data
|
||||
for (int i = 0; i < 128; i++) {
|
||||
src_data[i] = i;
|
||||
}
|
||||
if (sram_alignment) {
|
||||
// do write-back for the source data because it's in the cache
|
||||
TEST_ESP_OK(esp_cache_msync((void *)src_data, 128, ESP_CACHE_MSYNC_FLAG_DIR_C2M));
|
||||
}
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32P4
|
||||
// CPU and DMA both can write to the DMA descriptor, so if there is a cache, multiple descriptors may reside in the same cache line
|
||||
// causing data inconsistency. To avoid this, we want to access the descriptor memory without the cache.
|
||||
dma_descriptor_align8_t *tx_descs_noncache = (dma_descriptor_align8_t *)(CACHE_LL_L2MEM_NON_CACHE_ADDR(tx_descs));
|
||||
dma_descriptor_align8_t *rx_descs_noncache = (dma_descriptor_align8_t *)(CACHE_LL_L2MEM_NON_CACHE_ADDR(rx_descs));
|
||||
|
||||
tx_descs_noncache[0].buffer = src_data;
|
||||
tx_descs_noncache[0].dw0.size = 64;
|
||||
tx_descs_noncache[0].dw0.length = 64;
|
||||
tx_descs_noncache[0].dw0.owner = DMA_DESCRIPTOR_BUFFER_OWNER_DMA;
|
||||
tx_descs_noncache[0].dw0.suc_eof = 0;
|
||||
tx_descs_noncache[0].next = &tx_descs[1]; // Note, the DMA doesn't recognize a non-cacheable address, here must be the cached address
|
||||
|
||||
tx_descs_noncache[1].buffer = src_data + 64;
|
||||
tx_descs_noncache[1].dw0.size = 64;
|
||||
tx_descs_noncache[1].dw0.length = 64;
|
||||
tx_descs_noncache[1].dw0.owner = DMA_DESCRIPTOR_BUFFER_OWNER_DMA;
|
||||
tx_descs_noncache[1].dw0.suc_eof = 1;
|
||||
tx_descs_noncache[1].next = NULL;
|
||||
|
||||
rx_descs_noncache->buffer = dst_data;
|
||||
rx_descs_noncache->dw0.size = 128;
|
||||
rx_descs_noncache->dw0.owner = DMA_DESCRIPTOR_BUFFER_OWNER_DMA;
|
||||
rx_descs_noncache->dw0.suc_eof = 1;
|
||||
rx_descs_noncache->next = NULL;
|
||||
#ifdef CACHE_LL_L2MEM_NON_CACHE_ADDR
|
||||
dma_descriptor_align8_t *tx_descs_nc = (dma_descriptor_align8_t *)(CACHE_LL_L2MEM_NON_CACHE_ADDR(tx_descs));
|
||||
dma_descriptor_align8_t *rx_descs_nc = (dma_descriptor_align8_t *)(CACHE_LL_L2MEM_NON_CACHE_ADDR(rx_descs));
|
||||
#else
|
||||
tx_descs->buffer = src_data;
|
||||
tx_descs->dw0.size = 128;
|
||||
tx_descs->dw0.length = 128;
|
||||
tx_descs->dw0.owner = DMA_DESCRIPTOR_BUFFER_OWNER_DMA;
|
||||
tx_descs->dw0.suc_eof = 1;
|
||||
tx_descs->next = NULL;
|
||||
|
||||
rx_descs->buffer = dst_data;
|
||||
rx_descs->dw0.size = 128;
|
||||
rx_descs->dw0.owner = DMA_DESCRIPTOR_BUFFER_OWNER_DMA;
|
||||
rx_descs->next = NULL;
|
||||
dma_descriptor_align8_t *tx_descs_nc = tx_descs;
|
||||
dma_descriptor_align8_t *rx_descs_nc = rx_descs;
|
||||
#endif
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32P4
|
||||
// do write-back for the source data because it's in the cache
|
||||
TEST_ESP_OK(esp_cache_msync((void *)src_data, 128, ESP_CACHE_MSYNC_FLAG_DIR_C2M));
|
||||
#endif
|
||||
tx_descs_nc[0].buffer = src_data;
|
||||
tx_descs_nc[0].dw0.size = 64;
|
||||
tx_descs_nc[0].dw0.length = 64;
|
||||
tx_descs_nc[0].dw0.owner = DMA_DESCRIPTOR_BUFFER_OWNER_DMA;
|
||||
tx_descs_nc[0].dw0.suc_eof = 0;
|
||||
tx_descs_nc[0].next = &tx_descs[1]; // Note, the DMA doesn't recognize a non-cacheable address, here must be the cached address
|
||||
|
||||
tx_descs_nc[1].buffer = src_data + 64;
|
||||
tx_descs_nc[1].dw0.size = 64;
|
||||
tx_descs_nc[1].dw0.length = 64;
|
||||
tx_descs_nc[1].dw0.owner = DMA_DESCRIPTOR_BUFFER_OWNER_DMA;
|
||||
tx_descs_nc[1].dw0.suc_eof = 1;
|
||||
tx_descs_nc[1].next = NULL;
|
||||
|
||||
rx_descs_nc->buffer = dst_data;
|
||||
rx_descs_nc->dw0.size = 128;
|
||||
rx_descs_nc->dw0.owner = DMA_DESCRIPTOR_BUFFER_OWNER_DMA;
|
||||
rx_descs_nc->dw0.suc_eof = 1;
|
||||
rx_descs_nc->next = NULL;
|
||||
|
||||
TEST_ESP_OK(gdma_start(rx_chan, (intptr_t)rx_descs));
|
||||
TEST_ESP_OK(gdma_start(tx_chan, (intptr_t)tx_descs));
|
||||
|
||||
xSemaphoreTake(done_sem, portMAX_DELAY);
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32P4
|
||||
// the destination data are not reflected to the cache, so do an invalidate to ask the cache load new data
|
||||
TEST_ESP_OK(esp_cache_msync((void *)dst_data, 128, ESP_CACHE_MSYNC_FLAG_DIR_M2C));
|
||||
#endif
|
||||
if (sram_alignment) {
|
||||
// the destination data are not reflected to the cache, so do an invalidate to ask the cache load new data
|
||||
TEST_ESP_OK(esp_cache_msync((void *)dst_data, 128, ESP_CACHE_MSYNC_FLAG_DIR_M2C));
|
||||
}
|
||||
|
||||
// check the DMA descriptor write-back feature
|
||||
TEST_ASSERT_EQUAL(DMA_DESCRIPTOR_BUFFER_OWNER_CPU, tx_descs[0].dw0.owner);
|
||||
TEST_ASSERT_EQUAL(DMA_DESCRIPTOR_BUFFER_OWNER_CPU, rx_descs[0].dw0.owner);
|
||||
TEST_ASSERT_EQUAL(DMA_DESCRIPTOR_BUFFER_OWNER_CPU, tx_descs_nc[0].dw0.owner);
|
||||
TEST_ASSERT_EQUAL(DMA_DESCRIPTOR_BUFFER_OWNER_CPU, rx_descs_nc[0].dw0.owner);
|
||||
|
||||
for (int i = 0; i < 128; i++) {
|
||||
TEST_ASSERT_EQUAL(i, dst_data[i]);
|
||||
@ -257,7 +250,7 @@ static void test_gdma_m2m_mode(gdma_channel_handle_t tx_chan, gdma_channel_handl
|
||||
vSemaphoreDelete(done_sem);
|
||||
}
|
||||
|
||||
TEST_CASE("GDMA M2M Mode", "[GDMA]")
|
||||
TEST_CASE("GDMA M2M Mode", "[GDMA][M2M]")
|
||||
{
|
||||
gdma_channel_handle_t tx_chan = NULL;
|
||||
gdma_channel_handle_t rx_chan = NULL;
|
||||
@ -300,117 +293,3 @@ TEST_CASE("GDMA M2M Mode", "[GDMA]")
|
||||
TEST_ESP_OK(gdma_del_channel(rx_chan));
|
||||
#endif // SOC_AXI_GDMA_SUPPORTED
|
||||
}
|
||||
|
||||
#if SOC_GDMA_SUPPORT_CRC
|
||||
typedef struct {
|
||||
uint32_t init_value;
|
||||
uint32_t crc_bit_width;
|
||||
uint32_t poly_hex;
|
||||
bool reverse_data_mask;
|
||||
uint32_t expected_result;
|
||||
} test_crc_case_t;
|
||||
static test_crc_case_t crc_test_cases[] = {
|
||||
// CRC8, x^8+x^2+x+1
|
||||
[0] = {
|
||||
.crc_bit_width = 8,
|
||||
.init_value = 0x00,
|
||||
.poly_hex = 0x07,
|
||||
.expected_result = 0xC6,
|
||||
},
|
||||
[1] = {
|
||||
.crc_bit_width = 8,
|
||||
.init_value = 0x00,
|
||||
.poly_hex = 0x07,
|
||||
.reverse_data_mask = true, // refin = true
|
||||
.expected_result = 0xDE,
|
||||
},
|
||||
// CRC16, x^16+x^12+x^5+1
|
||||
[2] = {
|
||||
.crc_bit_width = 16,
|
||||
.init_value = 0xFFFF,
|
||||
.poly_hex = 0x1021,
|
||||
.expected_result = 0x5289,
|
||||
},
|
||||
// CRC32, x32+x26+x23+x22+x16+x12+x11+x10+x8+x7+x5+x4+x2+x+1
|
||||
[3] = {
|
||||
.crc_bit_width = 32,
|
||||
.init_value = 0xFFFFFFFF,
|
||||
.poly_hex = 0x04C11DB7,
|
||||
.expected_result = 0x63B3E283,
|
||||
}
|
||||
};
|
||||
|
||||
// CRC online: https://www.lddgo.net/en/encrypt/crc
|
||||
static void test_gdma_crc_calculation(gdma_channel_handle_t tx_chan, int test_num_crc_algorithm)
|
||||
{
|
||||
uint32_t crc_result = 0;
|
||||
const char *test_input_string = "Share::Connect::Innovate";
|
||||
size_t input_data_size = strlen(test_input_string);
|
||||
printf("Calculate CRC value for string: \"%s\"\r\n", test_input_string);
|
||||
|
||||
gdma_trigger_t m2m_trigger = GDMA_MAKE_TRIGGER(GDMA_TRIG_PERIPH_M2M, 0);
|
||||
// get a free DMA trigger ID
|
||||
uint32_t free_m2m_id_mask = 0;
|
||||
gdma_get_free_m2m_trig_id_mask(tx_chan, &free_m2m_id_mask);
|
||||
m2m_trigger.instance_id = __builtin_ctz(free_m2m_id_mask);
|
||||
TEST_ESP_OK(gdma_connect(tx_chan, m2m_trigger));
|
||||
|
||||
uint8_t *src_buf = heap_caps_aligned_calloc(64, 1, 256, MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
|
||||
TEST_ASSERT_NOT_NULL(src_buf);
|
||||
dma_descriptor_align8_t *tx_descs = (dma_descriptor_align8_t *) src_buf;
|
||||
uint8_t *src_data = src_buf + 64;
|
||||
memcpy(src_data, test_input_string, input_data_size);
|
||||
|
||||
tx_descs->buffer = src_data;
|
||||
tx_descs->dw0.size = 256 - 64;
|
||||
tx_descs->dw0.length = input_data_size;
|
||||
tx_descs->dw0.owner = DMA_DESCRIPTOR_BUFFER_OWNER_DMA;
|
||||
tx_descs->dw0.suc_eof = 1;
|
||||
tx_descs->next = NULL;
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32P4
|
||||
// do write-back for the buffer because it's in the cache
|
||||
Cache_WriteBack_Addr(CACHE_MAP_L1_DCACHE, (uint32_t)src_buf, 256);
|
||||
#endif
|
||||
|
||||
for (int i = 0; i < test_num_crc_algorithm; i++) {
|
||||
gdma_crc_calculator_config_t crc_config = {
|
||||
.crc_bit_width = crc_test_cases[i].crc_bit_width,
|
||||
.init_value = crc_test_cases[i].init_value,
|
||||
.poly_hex = crc_test_cases[i].poly_hex,
|
||||
.reverse_data_mask = crc_test_cases[i].reverse_data_mask,
|
||||
};
|
||||
TEST_ESP_OK(gdma_config_crc_calculator(tx_chan, &crc_config));
|
||||
TEST_ESP_OK(gdma_reset(tx_chan));
|
||||
TEST_ESP_OK(gdma_start(tx_chan, (intptr_t)tx_descs));
|
||||
// simply wait for the transfer done
|
||||
vTaskDelay(pdMS_TO_TICKS(100));
|
||||
TEST_ESP_OK(gdma_crc_get_result(tx_chan, &crc_result));
|
||||
printf("CRC Result: 0x%"PRIx32"\r\n", crc_result);
|
||||
TEST_ASSERT_EQUAL(crc_test_cases[i].expected_result, crc_result);
|
||||
}
|
||||
|
||||
free(src_buf);
|
||||
}
|
||||
|
||||
TEST_CASE("GDMA CRC Calculation", "[GDMA]")
|
||||
{
|
||||
gdma_channel_handle_t tx_chan = NULL;
|
||||
gdma_channel_alloc_config_t tx_chan_alloc_config = {
|
||||
.direction = GDMA_CHANNEL_DIRECTION_TX,
|
||||
};
|
||||
#if SOC_AHB_GDMA_SUPPORTED
|
||||
printf("Test CRC calculation for AHB GDMA\r\n");
|
||||
TEST_ESP_OK(gdma_new_ahb_channel(&tx_chan_alloc_config, &tx_chan));
|
||||
test_gdma_crc_calculation(tx_chan, 4);
|
||||
TEST_ESP_OK(gdma_del_channel(tx_chan));
|
||||
#endif // SOC_AHB_GDMA_SUPPORTED
|
||||
|
||||
#if SOC_AXI_GDMA_SUPPORTED
|
||||
printf("Test CRC calculation for AXI GDMA\r\n");
|
||||
TEST_ESP_OK(gdma_new_axi_channel(&tx_chan_alloc_config, &tx_chan));
|
||||
test_gdma_crc_calculation(tx_chan, 3);
|
||||
TEST_ESP_OK(gdma_del_channel(tx_chan));
|
||||
#endif // SOC_AXI_GDMA_SUPPORTED
|
||||
}
|
||||
#endif // SOC_GDMA_SUPPORT_CRC
|
||||
|
134
components/esp_hw_support/test_apps/dma/main/test_gdma_crc.c
Normal file
134
components/esp_hw_support/test_apps/dma/main/test_gdma_crc.c
Normal file
@ -0,0 +1,134 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
#include "sdkconfig.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/semphr.h"
|
||||
#include "unity.h"
|
||||
#include "esp_heap_caps.h"
|
||||
#include "esp_memory_utils.h"
|
||||
#include "esp_private/gdma.h"
|
||||
#include "hal/dma_types.h"
|
||||
#include "soc/soc_caps.h"
|
||||
#include "hal/cache_hal.h"
|
||||
#include "hal/cache_ll.h"
|
||||
#include "esp_cache.h"
|
||||
|
||||
typedef struct {
|
||||
uint32_t init_value;
|
||||
uint32_t crc_bit_width;
|
||||
uint32_t poly_hex;
|
||||
bool reverse_data_mask;
|
||||
uint32_t expected_result;
|
||||
} test_crc_case_t;
|
||||
static test_crc_case_t crc_test_cases[] = {
|
||||
// CRC8, x^8+x^2+x+1
|
||||
[0] = {
|
||||
.crc_bit_width = 8,
|
||||
.init_value = 0x00,
|
||||
.poly_hex = 0x07,
|
||||
.expected_result = 0xC6,
|
||||
},
|
||||
[1] = {
|
||||
.crc_bit_width = 8,
|
||||
.init_value = 0x00,
|
||||
.poly_hex = 0x07,
|
||||
.reverse_data_mask = true, // refin = true
|
||||
.expected_result = 0xDE,
|
||||
},
|
||||
// CRC16, x^16+x^12+x^5+1
|
||||
[2] = {
|
||||
.crc_bit_width = 16,
|
||||
.init_value = 0xFFFF,
|
||||
.poly_hex = 0x1021,
|
||||
.expected_result = 0x5289,
|
||||
},
|
||||
// CRC32, x32+x26+x23+x22+x16+x12+x11+x10+x8+x7+x5+x4+x2+x+1
|
||||
[3] = {
|
||||
.crc_bit_width = 32,
|
||||
.init_value = 0xFFFFFFFF,
|
||||
.poly_hex = 0x04C11DB7,
|
||||
.expected_result = 0x63B3E283,
|
||||
}
|
||||
};
|
||||
|
||||
// CRC online: https://www.lddgo.net/en/encrypt/crc
|
||||
static void test_gdma_crc_calculation(gdma_channel_handle_t tx_chan, int test_num_crc_algorithm)
|
||||
{
|
||||
uint32_t crc_result = 0;
|
||||
const char *test_input_string = "Share::Connect::Innovate";
|
||||
size_t input_data_size = strlen(test_input_string);
|
||||
// this test case also test the GDMA can fetch data from MSPI Flash
|
||||
TEST_ASSERT_TRUE(esp_ptr_in_drom(test_input_string));
|
||||
printf("Calculate CRC value for string: \"%s\"\r\n", test_input_string);
|
||||
|
||||
gdma_trigger_t m2m_trigger = GDMA_MAKE_TRIGGER(GDMA_TRIG_PERIPH_M2M, 0);
|
||||
// get a free DMA trigger ID
|
||||
uint32_t free_m2m_id_mask = 0;
|
||||
gdma_get_free_m2m_trig_id_mask(tx_chan, &free_m2m_id_mask);
|
||||
m2m_trigger.instance_id = __builtin_ctz(free_m2m_id_mask);
|
||||
TEST_ESP_OK(gdma_connect(tx_chan, m2m_trigger));
|
||||
|
||||
size_t sram_cache_line_size = cache_hal_get_cache_line_size(CACHE_LL_LEVEL_INT_MEM, CACHE_TYPE_DATA);
|
||||
size_t alignment = MAX(sram_cache_line_size, 8);
|
||||
dma_descriptor_align8_t *tx_descs = heap_caps_aligned_calloc(alignment, 1, sizeof(dma_descriptor_align8_t),
|
||||
MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
|
||||
TEST_ASSERT_NOT_NULL(tx_descs);
|
||||
|
||||
tx_descs->buffer = (void *)test_input_string;
|
||||
tx_descs->dw0.size = input_data_size + 1; // +1 for '\0'
|
||||
tx_descs->dw0.length = input_data_size;
|
||||
tx_descs->dw0.owner = DMA_DESCRIPTOR_BUFFER_OWNER_DMA;
|
||||
tx_descs->dw0.suc_eof = 1;
|
||||
tx_descs->next = NULL;
|
||||
|
||||
if (sram_cache_line_size) {
|
||||
// do write-back for the buffer because it's in the cache
|
||||
TEST_ESP_OK(esp_cache_msync((void *)tx_descs, sizeof(dma_descriptor_align8_t), ESP_CACHE_MSYNC_FLAG_DIR_C2M | ESP_CACHE_MSYNC_FLAG_UNALIGNED));
|
||||
}
|
||||
|
||||
for (int i = 0; i < test_num_crc_algorithm; i++) {
|
||||
gdma_crc_calculator_config_t crc_config = {
|
||||
.crc_bit_width = crc_test_cases[i].crc_bit_width,
|
||||
.init_value = crc_test_cases[i].init_value,
|
||||
.poly_hex = crc_test_cases[i].poly_hex,
|
||||
.reverse_data_mask = crc_test_cases[i].reverse_data_mask,
|
||||
};
|
||||
TEST_ESP_OK(gdma_config_crc_calculator(tx_chan, &crc_config));
|
||||
TEST_ESP_OK(gdma_reset(tx_chan));
|
||||
TEST_ESP_OK(gdma_start(tx_chan, (intptr_t)tx_descs));
|
||||
// simply wait for the transfer done
|
||||
vTaskDelay(pdMS_TO_TICKS(100));
|
||||
TEST_ESP_OK(gdma_crc_get_result(tx_chan, &crc_result));
|
||||
printf("CRC Result: 0x%"PRIx32"\r\n", crc_result);
|
||||
TEST_ASSERT_EQUAL(crc_test_cases[i].expected_result, crc_result);
|
||||
}
|
||||
|
||||
free(tx_descs);
|
||||
}
|
||||
|
||||
TEST_CASE("GDMA CRC Calculation", "[GDMA][CRC]")
|
||||
{
|
||||
gdma_channel_handle_t tx_chan = NULL;
|
||||
gdma_channel_alloc_config_t tx_chan_alloc_config = {
|
||||
.direction = GDMA_CHANNEL_DIRECTION_TX,
|
||||
};
|
||||
#if SOC_AHB_GDMA_SUPPORTED
|
||||
printf("Test CRC calculation for AHB GDMA\r\n");
|
||||
TEST_ESP_OK(gdma_new_ahb_channel(&tx_chan_alloc_config, &tx_chan));
|
||||
test_gdma_crc_calculation(tx_chan, 4);
|
||||
TEST_ESP_OK(gdma_del_channel(tx_chan));
|
||||
#endif // SOC_AHB_GDMA_SUPPORTED
|
||||
|
||||
#if SOC_AXI_GDMA_SUPPORTED
|
||||
printf("Test CRC calculation for AXI GDMA\r\n");
|
||||
TEST_ESP_OK(gdma_new_axi_channel(&tx_chan_alloc_config, &tx_chan));
|
||||
test_gdma_crc_calculation(tx_chan, 3);
|
||||
TEST_ESP_OK(gdma_del_channel(tx_chan));
|
||||
#endif // SOC_AXI_GDMA_SUPPORTED
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@ -15,7 +15,7 @@
|
||||
#include "driver/gpio.h"
|
||||
#include "esp_async_memcpy.h"
|
||||
|
||||
TEST_CASE("async_memcpy_eof_event", "[etm]")
|
||||
TEST_CASE("async_memcpy_eof_event", "[GDMA][ETM]")
|
||||
{
|
||||
const uint32_t output_gpio = 1;
|
||||
// async_memcpy done ---> ETM channel A ---> GPIO toggle
|
@ -13,10 +13,6 @@ if(CONFIG_SOC_SYSTIMER_SUPPORT_ETM)
|
||||
list(APPEND srcs "test_systimer_etm.c")
|
||||
endif()
|
||||
|
||||
if(CONFIG_SOC_GDMA_SUPPORT_ETM)
|
||||
list(APPEND srcs "test_gdma_etm.c")
|
||||
endif()
|
||||
|
||||
if(CONFIG_SOC_MCPWM_SUPPORT_ETM)
|
||||
list(APPEND srcs "test_mcpwm_etm.c")
|
||||
endif()
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@ -81,7 +81,7 @@ TEST_CASE("gpio_etm_self_trigger", "[etm]")
|
||||
// delete gpio etm task without remove all bounded GPIOs should fail
|
||||
TEST_ESP_ERR(ESP_ERR_INVALID_STATE, esp_etm_del_task(gpio_task));
|
||||
// remove unrelated GPIO from the task should fail
|
||||
TEST_ESP_ERR(ESP_ERR_INVALID_STATE, gpio_etm_task_rm_gpio(gpio_task, 10));
|
||||
TEST_ESP_ERR(ESP_ERR_INVALID_ARG, gpio_etm_task_rm_gpio(gpio_task, 10));
|
||||
|
||||
// delete etm primitives
|
||||
TEST_ESP_OK(gpio_etm_task_rm_gpio(gpio_task, output_gpio));
|
||||
@ -90,3 +90,118 @@ TEST_CASE("gpio_etm_self_trigger", "[etm]")
|
||||
TEST_ESP_OK(esp_etm_del_event(gpio_event));
|
||||
TEST_ESP_OK(esp_etm_del_channel(etm_channel_a));
|
||||
}
|
||||
|
||||
TEST_CASE("gpio_etm_self_trigger_multi_action", "[etm]")
|
||||
{
|
||||
// GPIO 0 pos edge event ---> GPIO 1 set level task
|
||||
// GPIO 22 pos edge event ---> GPIO 1 clear level task
|
||||
|
||||
const uint32_t input_gpio1 = 0;
|
||||
const uint32_t input_gpio2 = 22;
|
||||
const uint32_t output_gpio = 1;
|
||||
printf("allocate etm channels\r\n");
|
||||
esp_etm_channel_config_t etm_config = {};
|
||||
esp_etm_channel_handle_t etm_channel_a = NULL;
|
||||
esp_etm_channel_handle_t etm_channel_b = NULL;
|
||||
TEST_ESP_OK(esp_etm_new_channel(&etm_config, &etm_channel_a));
|
||||
TEST_ESP_OK(esp_etm_new_channel(&etm_config, &etm_channel_b));
|
||||
|
||||
printf("allocate GPIO etm event and task\r\n");
|
||||
esp_etm_task_handle_t gpio_task_a = NULL;
|
||||
esp_etm_event_handle_t gpio_event_a = NULL;
|
||||
esp_etm_task_handle_t gpio_task_b = NULL;
|
||||
esp_etm_event_handle_t gpio_event_b = NULL;
|
||||
gpio_etm_event_config_t gpio_event_config = {};
|
||||
gpio_event_config.edges[0] = GPIO_ETM_EVENT_EDGE_POS;
|
||||
TEST_ESP_OK(gpio_new_etm_event(&gpio_event_config, &gpio_event_a));
|
||||
esp_etm_event_handle_t gpio_event_c = NULL; // an extra event only used for testing binding
|
||||
gpio_event_config.edges[1] = GPIO_ETM_EVENT_EDGE_ANY;
|
||||
TEST_ESP_OK(gpio_new_etm_event(&gpio_event_config, &gpio_event_b, &gpio_event_c));
|
||||
gpio_etm_task_config_t gpio_task_config = {};
|
||||
gpio_task_config.actions[0] = GPIO_ETM_TASK_ACTION_CLR;
|
||||
gpio_task_config.actions[1] = GPIO_ETM_TASK_ACTION_SET;
|
||||
TEST_ESP_OK(gpio_new_etm_task(&gpio_task_config, &gpio_task_b, &gpio_task_a));
|
||||
|
||||
// bind GPIO to the event and task
|
||||
TEST_ESP_OK(gpio_etm_event_bind_gpio(gpio_event_a, input_gpio1));
|
||||
TEST_ESP_OK(gpio_etm_event_bind_gpio(gpio_event_b, input_gpio2));
|
||||
TEST_ESP_OK(gpio_etm_task_add_gpio(gpio_task_a, output_gpio));
|
||||
TEST_ESP_OK(gpio_etm_task_add_gpio(gpio_task_b, output_gpio));
|
||||
|
||||
// try an infeasible bind of second event to a GPIO
|
||||
TEST_ESP_ERR(ESP_ERR_INVALID_ARG, gpio_etm_event_bind_gpio(gpio_event_c, input_gpio1));
|
||||
// try a feasible bind of second event to a GPIO
|
||||
TEST_ESP_OK(gpio_etm_event_bind_gpio(gpio_event_c, input_gpio2));
|
||||
// delete the event to unbind it from the GPIO
|
||||
TEST_ESP_OK(esp_etm_del_event(gpio_event_c));
|
||||
|
||||
printf("initialize gpio\r\n");
|
||||
gpio_config_t task_gpio_config = {
|
||||
.intr_type = GPIO_INTR_DISABLE,
|
||||
.mode = GPIO_MODE_INPUT_OUTPUT, // we want to read the GPIO value, so it should be input and output
|
||||
.pin_bit_mask = 1ULL << output_gpio,
|
||||
};
|
||||
TEST_ESP_OK(gpio_config(&task_gpio_config));
|
||||
// set the initial level
|
||||
TEST_ESP_OK(gpio_set_level(output_gpio, 0));
|
||||
|
||||
gpio_config_t event_gpio_config = {
|
||||
.intr_type = GPIO_INTR_DISABLE,
|
||||
.mode = GPIO_MODE_INPUT_OUTPUT, // we want to simulate the edge signal by software, so it should be input and output
|
||||
.pull_up_en = GPIO_PULLUP_ENABLE,
|
||||
.pull_down_en = GPIO_PULLDOWN_DISABLE,
|
||||
.pin_bit_mask = (1ULL << input_gpio1) | (1ULL << input_gpio2),
|
||||
};
|
||||
TEST_ESP_OK(gpio_config(&event_gpio_config));
|
||||
// set the initial level
|
||||
TEST_ESP_OK(gpio_set_level(input_gpio1, 0));
|
||||
TEST_ESP_OK(gpio_set_level(input_gpio2, 0));
|
||||
|
||||
printf("connect event and task to the channel\r\n");
|
||||
TEST_ESP_OK(esp_etm_channel_connect(etm_channel_a, gpio_event_a, gpio_task_a));
|
||||
TEST_ESP_OK(esp_etm_channel_connect(etm_channel_b, gpio_event_b, gpio_task_b));
|
||||
|
||||
TEST_ESP_OK(esp_etm_channel_enable(etm_channel_a));
|
||||
TEST_ESP_OK(esp_etm_channel_enable(etm_channel_b));
|
||||
|
||||
// input_gpio1 pos edge ---> output_gpio level being set
|
||||
TEST_ESP_OK(gpio_set_level(input_gpio1, 1));
|
||||
vTaskDelay(pdMS_TO_TICKS(100));
|
||||
TEST_ASSERT_EQUAL(1, gpio_get_level(output_gpio));
|
||||
|
||||
// input_gpio1 neg edge does not affect output_gpio level
|
||||
TEST_ESP_OK(gpio_set_level(input_gpio1, 0));
|
||||
vTaskDelay(pdMS_TO_TICKS(100));
|
||||
TEST_ASSERT_EQUAL(1, gpio_get_level(output_gpio));
|
||||
|
||||
// input_gpio2 pos edge ---> output_gpio level being cleared
|
||||
TEST_ESP_OK(gpio_set_level(input_gpio2, 1));
|
||||
vTaskDelay(pdMS_TO_TICKS(100));
|
||||
TEST_ASSERT_EQUAL(0, gpio_get_level(output_gpio));
|
||||
|
||||
// input_gpio2 neg edge does not affect output_gpio level
|
||||
TEST_ESP_OK(gpio_set_level(input_gpio2, 0));
|
||||
vTaskDelay(pdMS_TO_TICKS(100));
|
||||
TEST_ASSERT_EQUAL(0, gpio_get_level(output_gpio));
|
||||
|
||||
// Create a new gpio etm task separately, and add it to the output_gpio should fail (the task does not belong to the same GPIO ETM task channel as gpio_task_a and gpio_task_b)
|
||||
esp_etm_task_handle_t gpio_task_c = NULL;
|
||||
gpio_etm_task_config_t gpio_task_config_2 = {
|
||||
.action = GPIO_ETM_TASK_ACTION_TOG,
|
||||
};
|
||||
TEST_ESP_OK(gpio_new_etm_task(&gpio_task_config_2, &gpio_task_c));
|
||||
TEST_ESP_ERR(ESP_ERR_INVALID_ARG, gpio_etm_task_add_gpio(gpio_task_c, output_gpio));
|
||||
|
||||
// delete etm primitives
|
||||
TEST_ESP_OK(gpio_etm_task_rm_gpio(gpio_task_a, output_gpio));
|
||||
TEST_ESP_OK(gpio_etm_task_rm_gpio(gpio_task_b, output_gpio));
|
||||
TEST_ESP_OK(esp_etm_channel_disable(etm_channel_a));
|
||||
TEST_ESP_OK(esp_etm_channel_disable(etm_channel_b));
|
||||
TEST_ESP_OK(esp_etm_del_task(gpio_task_a));
|
||||
TEST_ESP_OK(esp_etm_del_task(gpio_task_b));
|
||||
TEST_ESP_OK(esp_etm_del_task(gpio_task_c));
|
||||
TEST_ESP_OK(esp_etm_del_event(gpio_event_a));
|
||||
TEST_ESP_OK(esp_etm_del_event(gpio_event_b));
|
||||
TEST_ESP_OK(esp_etm_del_channel(etm_channel_a));
|
||||
TEST_ESP_OK(esp_etm_del_channel(etm_channel_b));
|
||||
}
|
||||
|
@ -36,5 +36,20 @@ menu "LCD and Touch Panel"
|
||||
Only need to enable it when in your application, the DMA can't deliver data
|
||||
as fast as the LCD consumes it.
|
||||
endif # SOC_LCD_RGB_SUPPORTED
|
||||
|
||||
if SOC_MIPI_DSI_SUPPORTED
|
||||
config LCD_DSI_ISR_IRAM_SAFE
|
||||
bool "DSI LCD ISR IRAM-Safe"
|
||||
default n
|
||||
select DW_GDMA_ISR_IRAM_SAFE
|
||||
select DW_GDMA_CTRL_FUNC_IN_IRAM
|
||||
select DW_GDMA_SETTER_FUNC_IN_IRAM
|
||||
select DW_GDMA_GETTER_FUNC_IN_IRAM
|
||||
help
|
||||
Ensure the LCD interrupt is IRAM-Safe by allowing the interrupt handler to be
|
||||
executable when the cache is disabled (e.g. SPI Flash write).
|
||||
If you want the LCD driver to keep flushing the screen even when cache ops disabled,
|
||||
you can enable this option. Note, this will also increase the IRAM usage.
|
||||
endif # SOC_MIPI_DSI_SUPPORTED
|
||||
endmenu
|
||||
endmenu
|
||||
|
@ -21,6 +21,8 @@ esp_err_t esp_lcd_new_dsi_bus(const esp_lcd_dsi_bus_config_t *bus_config, esp_lc
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
ESP_RETURN_ON_FALSE(bus_config && ret_bus, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
|
||||
ESP_RETURN_ON_FALSE(bus_config->num_data_lanes <= MIPI_DSI_LL_MAX_DATA_LANES,
|
||||
ESP_ERR_INVALID_ARG, TAG, "invalid number of data lanes %d", bus_config->num_data_lanes);
|
||||
ESP_RETURN_ON_FALSE(bus_config->lane_bit_rate_mbps >= MIPI_DSI_LL_MIN_PHY_MBPS &&
|
||||
bus_config->lane_bit_rate_mbps <= MIPI_DSI_LL_MAX_PHY_MBPS, ESP_ERR_INVALID_ARG, TAG,
|
||||
"invalid lane bit rate %"PRIu32, bus_config->lane_bit_rate_mbps);
|
||||
@ -55,11 +57,25 @@ esp_err_t esp_lcd_new_dsi_bus(const esp_lcd_dsi_bus_config_t *bus_config, esp_lc
|
||||
mipi_dsi_ll_enable_phy_reference_clock(bus_id, true);
|
||||
}
|
||||
|
||||
#if CONFIG_PM_ENABLE
|
||||
// When MIPI DSI is working, we don't expect the clock source would be turned off
|
||||
esp_pm_lock_type_t pm_lock_type = ESP_PM_NO_LIGHT_SLEEP;
|
||||
ret = esp_pm_lock_create(pm_lock_type, 0, "dsi_phy", &dsi_bus->pm_lock);
|
||||
ESP_GOTO_ON_ERROR(ret, err, TAG, "create PM lock failed");
|
||||
// before we configure the PLL, we want the clock source to be stable
|
||||
esp_pm_lock_acquire(dsi_bus->pm_lock);
|
||||
#endif
|
||||
|
||||
// if the number of data lanes is not assigned, fallback to the maximum number of data lanes
|
||||
int num_data_lanes = bus_config->num_data_lanes;
|
||||
if (num_data_lanes == 0) {
|
||||
num_data_lanes = MIPI_DSI_LL_MAX_DATA_LANES;
|
||||
}
|
||||
// initialize HAL context
|
||||
mipi_dsi_hal_config_t hal_config = {
|
||||
.bus_id = bus_id,
|
||||
.lane_bit_rate_mbps = bus_config->lane_bit_rate_mbps,
|
||||
.num_data_lanes = bus_config->num_data_lanes,
|
||||
.num_data_lanes = num_data_lanes,
|
||||
};
|
||||
mipi_dsi_hal_init(&dsi_bus->hal, &hal_config);
|
||||
mipi_dsi_hal_context_t *hal = &dsi_bus->hal;
|
||||
@ -75,7 +91,7 @@ esp_err_t esp_lcd_new_dsi_bus(const esp_lcd_dsi_bus_config_t *bus_config, esp_lc
|
||||
while (!mipi_dsi_phy_ll_is_pll_locked(hal->host)) {
|
||||
vTaskDelay(pdMS_TO_TICKS(1));
|
||||
}
|
||||
while (!mipi_dsi_phy_ll_are_lanes_stopped(hal->host)) {
|
||||
while (!mipi_dsi_phy_ll_are_lanes_stopped(hal->host, num_data_lanes)) {
|
||||
vTaskDelay(pdMS_TO_TICKS(1));
|
||||
}
|
||||
|
||||
@ -125,6 +141,10 @@ esp_err_t esp_lcd_del_dsi_bus(esp_lcd_dsi_bus_handle_t bus)
|
||||
DSI_RCC_ATOMIC() {
|
||||
mipi_dsi_ll_enable_bus_clock(bus_id, false);
|
||||
}
|
||||
if (bus->pm_lock) {
|
||||
esp_pm_lock_release(bus->pm_lock);
|
||||
esp_pm_lock_delete(bus->pm_lock);
|
||||
}
|
||||
free(bus);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
@ -3,6 +3,7 @@
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include <sys/param.h>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/semphr.h"
|
||||
@ -14,6 +15,7 @@
|
||||
#include "esp_cache.h"
|
||||
#include "mipi_dsi_priv.h"
|
||||
#include "esp_async_fbcpy.h"
|
||||
#include "esp_memory_utils.h"
|
||||
#include "esp_private/dw_gdma.h"
|
||||
#include "hal/cache_hal.h"
|
||||
#include "hal/cache_ll.h"
|
||||
@ -42,6 +44,7 @@ struct esp_lcd_dpi_panel_t {
|
||||
dw_gdma_link_list_handle_t link_lists[DPI_PANEL_MAX_FB_NUM]; // DMA link list
|
||||
esp_async_fbcpy_handle_t fbcpy_handle; // Use DMA2D to do frame buffer copy
|
||||
SemaphoreHandle_t draw_sem; // A semaphore used to synchronize the draw operations when DMA2D is used
|
||||
esp_pm_lock_handle_t pm_lock; // Power management lock
|
||||
esp_lcd_dpi_panel_color_trans_done_cb_t on_color_trans_done; // Callback invoked when color data transfer has finished
|
||||
esp_lcd_dpi_panel_refresh_done_cb_t on_refresh_done; // Callback invoked when one refresh operation finished (kinda like a vsync end)
|
||||
void *user_ctx; // User context for the callback
|
||||
@ -232,6 +235,14 @@ esp_err_t esp_lcd_new_panel_dpi(esp_lcd_dsi_bus_handle_t bus, const esp_lcd_dpi_
|
||||
mipi_dsi_ll_enable_dpi_clock(bus_id, true);
|
||||
}
|
||||
|
||||
#if CONFIG_PM_ENABLE
|
||||
// When MIPI DSI is working, we don't expect the clock source would be turned off
|
||||
esp_pm_lock_type_t pm_lock_type = ESP_PM_NO_LIGHT_SLEEP;
|
||||
ret = esp_pm_lock_create(pm_lock_type, 0, "dsi_dpi", &dpi_panel->pm_lock);
|
||||
ESP_GOTO_ON_ERROR(ret, err, TAG, "create PM lock failed");
|
||||
esp_pm_lock_acquire(dpi_panel->pm_lock);
|
||||
#endif
|
||||
|
||||
// create DMA resources
|
||||
ESP_GOTO_ON_ERROR(dpi_panel_create_dma_link(dpi_panel), err, TAG, "initialize DMA link failed");
|
||||
|
||||
@ -318,6 +329,10 @@ static esp_err_t dpi_panel_del(esp_lcd_panel_t *panel)
|
||||
if (dpi_panel->draw_sem) {
|
||||
vSemaphoreDelete(dpi_panel->draw_sem);
|
||||
}
|
||||
if (dpi_panel->pm_lock) {
|
||||
esp_pm_lock_release(dpi_panel->pm_lock);
|
||||
esp_pm_lock_delete(dpi_panel->pm_lock);
|
||||
}
|
||||
free(dpi_panel);
|
||||
return ESP_OK;
|
||||
}
|
||||
@ -403,6 +418,14 @@ static esp_err_t dpi_panel_draw_bitmap(esp_lcd_panel_t *panel, int x_start, int
|
||||
size_t frame_buffer_size = dpi_panel->frame_buffer_size;
|
||||
size_t bytes_per_pixel = dpi_panel->bytes_per_pixel;
|
||||
|
||||
// clip to boundaries
|
||||
int h_res = dpi_panel->h_pixels;
|
||||
int v_res = dpi_panel->v_pixels;
|
||||
x_start = MAX(x_start, 0);
|
||||
x_end = MIN(x_end, h_res);
|
||||
y_start = MAX(y_start, 0);
|
||||
y_end = MIN(y_end, v_res);
|
||||
|
||||
bool do_copy = false;
|
||||
uint8_t draw_buf_fb_index = 0;
|
||||
// check if the user draw buffer resides in any frame buffer's memory range
|
||||
@ -515,6 +538,17 @@ esp_err_t esp_lcd_dpi_panel_register_event_callbacks(esp_lcd_panel_handle_t pane
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(panel && cbs, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
|
||||
esp_lcd_dpi_panel_t *dpi_panel = __containerof(panel, esp_lcd_dpi_panel_t, base);
|
||||
#if CONFIG_LCD_DSI_ISR_IRAM_SAFE
|
||||
if (cbs->on_color_trans_done) {
|
||||
ESP_RETURN_ON_FALSE(esp_ptr_in_iram(cbs->on_color_trans_done), ESP_ERR_INVALID_ARG, TAG, "on_color_trans_done callback not in IRAM");
|
||||
}
|
||||
if (cbs->on_refresh_done) {
|
||||
ESP_RETURN_ON_FALSE(esp_ptr_in_iram(cbs->on_refresh_done), ESP_ERR_INVALID_ARG, TAG, "on_refresh_done callback not in IRAM");
|
||||
}
|
||||
if (user_ctx) {
|
||||
ESP_RETURN_ON_FALSE(esp_ptr_internal(user_ctx), ESP_ERR_INVALID_ARG, TAG, "user context not in internal RAM");
|
||||
}
|
||||
#endif // CONFIG_LCD_RGB_ISR_IRAM_SAFE
|
||||
dpi_panel->on_color_trans_done = cbs->on_color_trans_done;
|
||||
dpi_panel->on_refresh_done = cbs->on_refresh_done;
|
||||
dpi_panel->user_ctx = user_ctx;
|
||||
|
@ -21,7 +21,7 @@ extern "C" {
|
||||
*/
|
||||
typedef struct {
|
||||
int bus_id; /*!< Select which DSI controller, index from 0 */
|
||||
uint8_t num_data_lanes; /*!< Number of data lanes */
|
||||
uint8_t num_data_lanes; /*!< Number of data lanes, if set to 0, the driver will fallback to use maximum number of lanes */
|
||||
mipi_dsi_phy_clock_source_t phy_clk_src; /*!< MIPI DSI PHY clock source */
|
||||
uint32_t lane_bit_rate_mbps; /*!< Lane bit rate in Mbps */
|
||||
} esp_lcd_dsi_bus_config_t;
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include "hal/mipi_dsi_ll.h"
|
||||
#include "esp_heap_caps.h"
|
||||
#include "esp_private/periph_ctrl.h"
|
||||
#include "esp_pm.h"
|
||||
|
||||
#if SOC_PERIPH_CLK_CTRL_SHARED
|
||||
#define DSI_CLOCK_SRC_ATOMIC() PERIPH_RCC_ATOMIC()
|
||||
@ -22,7 +23,11 @@
|
||||
#define DSI_RCC_ATOMIC()
|
||||
#endif
|
||||
|
||||
#define DSI_MEM_ALLOC_CAPS MALLOC_CAP_DEFAULT
|
||||
#if CONFIG_LCD_DSI_ISR_IRAM_SAFE
|
||||
#define DSI_MEM_ALLOC_CAPS (MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT)
|
||||
#else
|
||||
#define DSI_MEM_ALLOC_CAPS MALLOC_CAP_DEFAULT
|
||||
#endif
|
||||
|
||||
#define DPI_PANEL_MAX_FB_NUM 3 // maximum number of supported frame buffers for DPI panel
|
||||
|
||||
@ -35,6 +40,7 @@ extern "C" {
|
||||
typedef struct esp_lcd_dsi_bus_t {
|
||||
int bus_id;
|
||||
mipi_dsi_hal_context_t hal;
|
||||
esp_pm_lock_handle_t pm_lock;
|
||||
} esp_lcd_dsi_bus_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -706,7 +706,6 @@ static esp_err_t rgb_panel_draw_bitmap(esp_lcd_panel_t *panel, int x_start, int
|
||||
{
|
||||
esp_rgb_panel_t *rgb_panel = __containerof(panel, esp_rgb_panel_t, base);
|
||||
ESP_RETURN_ON_FALSE(rgb_panel->num_fbs > 0, ESP_ERR_NOT_SUPPORTED, TAG, "no frame buffer installed");
|
||||
assert((x_start < x_end) && (y_start < y_end) && "start position must be smaller than end position");
|
||||
|
||||
// check if we need to copy the draw buffer (pointed by the color_data) to the driver's frame buffer
|
||||
bool do_copy = false;
|
||||
@ -726,18 +725,19 @@ static esp_err_t rgb_panel_draw_bitmap(esp_lcd_panel_t *panel, int x_start, int
|
||||
y_start += rgb_panel->y_gap;
|
||||
x_end += rgb_panel->x_gap;
|
||||
y_end += rgb_panel->y_gap;
|
||||
// round the boundary
|
||||
|
||||
// clip to boundaries
|
||||
int h_res = rgb_panel->timings.h_res;
|
||||
int v_res = rgb_panel->timings.v_res;
|
||||
if (rgb_panel->rotate_mask & ROTATE_MASK_SWAP_XY) {
|
||||
x_start = MIN(x_start, v_res);
|
||||
x_start = MAX(x_start, 0);
|
||||
x_end = MIN(x_end, v_res);
|
||||
y_start = MIN(y_start, h_res);
|
||||
y_start = MAX(y_start, 0);
|
||||
y_end = MIN(y_end, h_res);
|
||||
} else {
|
||||
x_start = MIN(x_start, h_res);
|
||||
x_start = MAX(x_start, 0);
|
||||
x_end = MIN(x_end, h_res);
|
||||
y_start = MIN(y_start, v_res);
|
||||
y_start = MAX(y_start, 0);
|
||||
y_end = MIN(y_end, v_res);
|
||||
}
|
||||
|
||||
|
@ -188,7 +188,6 @@ static esp_err_t panel_nt35510_draw_bitmap(esp_lcd_panel_t *panel, int x_start,
|
||||
const void *color_data)
|
||||
{
|
||||
nt35510_panel_t *nt35510 = __containerof(panel, nt35510_panel_t, base);
|
||||
assert((x_start < x_end) && (y_start < y_end) && "start position must be smaller than end position");
|
||||
esp_lcd_panel_io_handle_t io = nt35510->io;
|
||||
|
||||
x_start += nt35510->x_gap;
|
||||
|
@ -32,6 +32,7 @@ esp_err_t esp_lcd_panel_del(esp_lcd_panel_handle_t panel)
|
||||
esp_err_t esp_lcd_panel_draw_bitmap(esp_lcd_panel_handle_t panel, int x_start, int y_start, int x_end, int y_end, const void *color_data)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(panel, ESP_ERR_INVALID_ARG, TAG, "invalid panel handle");
|
||||
ESP_RETURN_ON_FALSE((x_start < x_end) && (y_start < y_end), ESP_ERR_INVALID_ARG, TAG, "start position must be smaller than end position");
|
||||
ESP_RETURN_ON_FALSE(panel->draw_bitmap, ESP_ERR_NOT_SUPPORTED, TAG, "draw_bitmap is not supported by this panel");
|
||||
return panel->draw_bitmap(panel, x_start, y_start, x_end, y_end, color_data);
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user