forked from espressif/esp-idf
Compare commits
381 Commits
uart_parti
...
v5.5
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8c750b088c | ||
|
|
25c7c11970 | ||
|
|
280a2f9307 | ||
|
|
94c643ba87 | ||
|
|
b43b2001a2 | ||
|
|
ddfb59657c | ||
|
|
e67274f0ff | ||
|
|
7bed0d3937 | ||
|
|
b8f555c16b | ||
|
|
f6826dda7e | ||
|
|
11bbb25dc4 | ||
|
|
8755edfb3a | ||
|
|
8f6e0f4cc3 | ||
|
|
9f19124bd8 | ||
|
|
e8052de6b4 | ||
|
|
c66052e5dd | ||
|
|
12191f266f | ||
|
|
b7887b052e | ||
|
|
a441cad4b7 | ||
|
|
d5ff5d3f46 | ||
|
|
4451649760 | ||
|
|
66ddf66e64 | ||
|
|
7a329d5e91 | ||
|
|
ebaece4dff | ||
|
|
97888e2152 | ||
|
|
8588446859 | ||
|
|
cf8dad0746 | ||
|
|
577d650d83 | ||
|
|
c844ba4f7f | ||
|
|
65d4e3f06f | ||
|
|
adb3f2a580 | ||
|
|
d2299ef3c6 | ||
|
|
aae5e12d77 | ||
|
|
d468522078 | ||
|
|
a6f092516a | ||
|
|
3fcb964577 | ||
|
|
f3579cee33 | ||
|
|
a714eb84b5 | ||
|
|
7c79d6e663 | ||
|
|
fbc18b2c1d | ||
|
|
cbe9388f45 | ||
|
|
1d9e0ac834 | ||
|
|
b37d4b338c | ||
|
|
5986566708 | ||
|
|
20ec15edff | ||
|
|
60e884b438 | ||
|
|
589c2516c8 | ||
|
|
5210e576d5 | ||
|
|
e7a76ff71e | ||
|
|
8694f893ea | ||
|
|
5c6701aad0 | ||
|
|
4d06a6ec9d | ||
|
|
6cb9214520 | ||
|
|
b62e55db0b | ||
|
|
8ac432ec0a | ||
|
|
6fd5f51432 | ||
|
|
0eb2407a26 | ||
|
|
85c77bdb82 | ||
|
|
391c39414e | ||
|
|
df19d0421f | ||
|
|
5558a08c07 | ||
|
|
8aa235a9a5 | ||
|
|
9c61e31be4 | ||
|
|
f0d7baae5e | ||
|
|
9189406b05 | ||
|
|
30c24b2f31 | ||
|
|
23bc0a51fb | ||
|
|
16985bfd3c | ||
|
|
e454c9be2d | ||
|
|
4fd109860b | ||
|
|
88f234f1ef | ||
|
|
e44e7ce2f9 | ||
|
|
06268a4efc | ||
|
|
4684d3dffc | ||
|
|
d8f3e05201 | ||
|
|
0104bcde1a | ||
|
|
aac26c847e | ||
|
|
4a21060839 | ||
|
|
9671a5d3b0 | ||
|
|
2f3351f1a9 | ||
|
|
39ebd0b143 | ||
|
|
cfe6cbaaa0 | ||
|
|
c7990e649e | ||
|
|
adc3a80381 | ||
|
|
e0f7f4e539 | ||
|
|
42a3c9b024 | ||
|
|
a468bbcadd | ||
|
|
d0d04bd986 | ||
|
|
7b1cbb89e0 | ||
|
|
e17993b175 | ||
|
|
36749445f4 | ||
|
|
a644e9073e | ||
|
|
191a24cb6d | ||
|
|
24e323685a | ||
|
|
7bbaba909f | ||
|
|
f7046307a5 | ||
|
|
cd7c97e6eb | ||
|
|
624175fc01 | ||
|
|
8cf17632c2 | ||
|
|
9a74093e98 | ||
|
|
fa889bf5b6 | ||
|
|
c4747aae02 | ||
|
|
0ea73a9273 | ||
|
|
80d191e797 | ||
|
|
ba0da6f2a6 | ||
|
|
c943797004 | ||
|
|
1a40b106b4 | ||
|
|
10a210d08a | ||
|
|
56a4c70c31 | ||
|
|
5a04cfded1 | ||
|
|
3fe9252c3f | ||
|
|
c837712306 | ||
|
|
80abd1c7e4 | ||
|
|
3da3f6f2e2 | ||
|
|
8d7aefa890 | ||
|
|
ef71aad834 | ||
|
|
73058bfca0 | ||
|
|
d5323cfaaa | ||
|
|
6e82c7a061 | ||
|
|
6cf1a6f297 | ||
|
|
95b7c023da | ||
|
|
f4669e3377 | ||
|
|
7e28275ac1 | ||
|
|
da534bf462 | ||
|
|
59434db045 | ||
|
|
2e7a9174fc | ||
|
|
fc77b58ced | ||
|
|
770052e859 | ||
|
|
71f83ca625 | ||
|
|
156ead0cd5 | ||
|
|
5555ef7425 | ||
|
|
4b93bde59b | ||
|
|
04f5e591c0 | ||
|
|
2d5d7b819f | ||
|
|
908ff6e5df | ||
|
|
0dd5b0b979 | ||
|
|
e536aa670b | ||
|
|
1df4f13b2e | ||
|
|
bb72c42611 | ||
|
|
d8fa0886b0 | ||
|
|
08d78dcd7e | ||
|
|
849c74b2b9 | ||
|
|
e32bd2502d | ||
|
|
666f3db1a3 | ||
|
|
79da851a4c | ||
|
|
3f8da22ae0 | ||
|
|
f523943972 | ||
|
|
fc71a8643e | ||
|
|
0e585a2994 | ||
|
|
f5be149eb2 | ||
|
|
ccef14fad2 | ||
|
|
bb8338b17a | ||
|
|
53534bc5ce | ||
|
|
ace361e7e1 | ||
|
|
ec2f1c0023 | ||
|
|
5584880376 | ||
|
|
ebdafe8e0c | ||
|
|
addc2101dc | ||
|
|
6078213bcd | ||
|
|
4869e83855 | ||
|
|
37f017585d | ||
|
|
8f57d672d2 | ||
|
|
881c5a9795 | ||
|
|
2e760d374e | ||
|
|
e22c523b55 | ||
|
|
7c2734dc02 | ||
|
|
9e7325a3d6 | ||
|
|
29ba5469ef | ||
|
|
20d66da972 | ||
|
|
4c3d086c13 | ||
|
|
d0e0c188fb | ||
|
|
19b0d6c13c | ||
|
|
e9e995bd0a | ||
|
|
7914e75525 | ||
|
|
90b3d29223 | ||
|
|
30d77f494e | ||
|
|
7557ec0951 | ||
|
|
e29823cfe0 | ||
|
|
f0a4d73ea1 | ||
|
|
22aeb00462 | ||
|
|
fd3178eb6b | ||
|
|
7cf59adc0c | ||
|
|
96b43c9797 | ||
|
|
168808248d | ||
|
|
fc72303490 | ||
|
|
6b74032d2e | ||
|
|
39c6c703b1 | ||
|
|
ce09a8c037 | ||
|
|
370ac37623 | ||
|
|
98cd765953 | ||
|
|
73747da716 | ||
|
|
18b6997e32 | ||
|
|
693a5393b2 | ||
|
|
23892d857a | ||
|
|
087727a693 | ||
|
|
49b5cc9e50 | ||
|
|
33c71ea033 | ||
|
|
5961670d06 | ||
|
|
07ae83249a | ||
|
|
fa75a4dd67 | ||
|
|
b002e50857 | ||
|
|
f19263a97c | ||
|
|
7f8290e911 | ||
|
|
0170c56e04 | ||
|
|
7b66ed489f | ||
|
|
35876be5e6 | ||
|
|
e2b524c609 | ||
|
|
30859ceaff | ||
|
|
99e5203d89 | ||
|
|
c48b74805f | ||
|
|
a2cd564044 | ||
|
|
ad5d36257b | ||
|
|
52e3d9bb5f | ||
|
|
d881dda91c | ||
|
|
ecb5fc3075 | ||
|
|
cd1601f408 | ||
|
|
4d83f1b8af | ||
|
|
0fe8891e3a | ||
|
|
b1a379d574 | ||
|
|
84973428b2 | ||
|
|
41a17b71ad | ||
|
|
253ca4267a | ||
|
|
60ab2598c5 | ||
|
|
b9c586ebd1 | ||
|
|
3d09da9251 | ||
|
|
fddf34d7b0 | ||
|
|
2e761da92a | ||
|
|
b045635cea | ||
|
|
3b596bb602 | ||
|
|
45fed1d225 | ||
|
|
d7216d221b | ||
|
|
80c5fd1836 | ||
|
|
b3843ea09a | ||
|
|
6687749fae | ||
|
|
2b0c548593 | ||
|
|
59496b4927 | ||
|
|
b977a13796 | ||
|
|
0a3cc83a86 | ||
|
|
d5d713cff2 | ||
|
|
80c92bae34 | ||
|
|
0904640409 | ||
|
|
b0f107b69a | ||
|
|
1c81d11ec3 | ||
|
|
059a675e5c | ||
|
|
4c7a13b570 | ||
|
|
5be9ac3d93 | ||
|
|
e100fc790c | ||
|
|
a73197e886 | ||
|
|
9e0c4d226a | ||
|
|
68dd2c9a3c | ||
|
|
3d3b7caf95 | ||
|
|
0e59feac9d | ||
|
|
c0f77d8993 | ||
|
|
3092578b4a | ||
|
|
fafc25b8b9 | ||
|
|
e7c8f555e7 | ||
|
|
5f71d958c3 | ||
|
|
e26be2be8f | ||
|
|
e8475d7796 | ||
|
|
31149354a9 | ||
|
|
833df30063 | ||
|
|
1cc377a373 | ||
|
|
a74197c552 | ||
|
|
d482206483 | ||
|
|
27496e47f0 | ||
|
|
eca7c7296c | ||
|
|
039cc1ac80 | ||
|
|
ee3baa4ca7 | ||
|
|
ba70c7f3d1 | ||
|
|
c5b725fc50 | ||
|
|
10a690fe10 | ||
|
|
758da73338 | ||
|
|
27b85137c7 | ||
|
|
06ee44ef46 | ||
|
|
f4add076a8 | ||
|
|
5e6ecd81b5 | ||
|
|
45fb5fb793 | ||
|
|
63f72f659d | ||
|
|
7910ea8571 | ||
|
|
7f46f6152e | ||
|
|
5da8865f9b | ||
|
|
c771e4508e | ||
|
|
375d675cdc | ||
|
|
2252a4166a | ||
|
|
1f4fbd060c | ||
|
|
f97fd7490f | ||
|
|
dbfb663b66 | ||
|
|
429183de1e | ||
|
|
1ba8abd8b7 | ||
|
|
5b1588e0db | ||
|
|
3ded40b276 | ||
|
|
a6db9d402f | ||
|
|
693dfe6b0e | ||
|
|
d738d889d8 | ||
|
|
ce340fcce7 | ||
|
|
b1218adfae | ||
|
|
aff86ba14b | ||
|
|
c85c74f54b | ||
|
|
0778748506 | ||
|
|
8a54378b95 | ||
|
|
43ff2531ab | ||
|
|
a3edce572a | ||
|
|
4aa47aacc3 | ||
|
|
379f4de500 | ||
|
|
048d03e94d | ||
|
|
29520e982c | ||
|
|
527e2f38b8 | ||
|
|
9cf4ddf797 | ||
|
|
3052ad53e7 | ||
|
|
1adbeceb27 | ||
|
|
d1c131f649 | ||
|
|
7b52c11661 | ||
|
|
5bb83afac7 | ||
|
|
669e677ba3 | ||
|
|
1909105acf | ||
|
|
afcb8199b0 | ||
|
|
0a17f79cc7 | ||
|
|
de17b6ff94 | ||
|
|
046479c23f | ||
|
|
79d2bedbf9 | ||
|
|
6514df1ba9 | ||
|
|
692f7df5aa | ||
|
|
f6cb4422db | ||
|
|
60adcc5980 | ||
|
|
a544a33131 | ||
|
|
4f56bba225 | ||
|
|
5273ba9731 | ||
|
|
eb0cf524c0 | ||
|
|
6ba1a3a427 | ||
|
|
f9597a06f4 | ||
|
|
f056662cd5 | ||
|
|
e1aee3ff2b | ||
|
|
2e02c26b81 | ||
|
|
f5748f3d9b | ||
|
|
8a138cbd22 | ||
|
|
c18e53b672 | ||
|
|
28ac0243bb | ||
|
|
c61f36de13 | ||
|
|
6fdcf9efc1 | ||
|
|
a652a8473e | ||
|
|
6f82f332fd | ||
|
|
b095331a51 | ||
|
|
084dfefd6f | ||
|
|
04d83433c3 | ||
|
|
dd1a331f4f | ||
|
|
0f7b621d47 | ||
|
|
72ae023a42 | ||
|
|
84e62daedc | ||
|
|
0d5d31b343 | ||
|
|
05617e458b | ||
|
|
f8284e1733 | ||
|
|
b9e03c3cf4 | ||
|
|
4498eea285 | ||
|
|
af9e528409 | ||
|
|
d35923141d | ||
|
|
81f5d899f6 | ||
|
|
2eac57a1da | ||
|
|
2fd71413f0 | ||
|
|
b8badb85d1 | ||
|
|
f8cdf02b55 | ||
|
|
ac12d560a2 | ||
|
|
18cd0fa030 | ||
|
|
269f1d110d | ||
|
|
f03b0fe0c5 | ||
|
|
a0fc3e68a8 | ||
|
|
0993f1e67b | ||
|
|
45831351fa | ||
|
|
37e28522c2 | ||
|
|
8ea6b3170b | ||
|
|
2de265b3e7 | ||
|
|
953fe222ec | ||
|
|
70f19793f8 | ||
|
|
0b2f639c62 | ||
|
|
a3cb7f4404 | ||
|
|
b264d7f89b | ||
|
|
14c29c467e | ||
|
|
3b7f4e2341 | ||
|
|
3a6e5dba88 | ||
|
|
27e1a30acc | ||
|
|
c0d91e33d0 | ||
|
|
a4d0ab04c5 |
@@ -1,4 +1,4 @@
|
||||
[codespell]
|
||||
skip = build,*.yuv,components/fatfs/src/*,alice.txt,*.rgb,components/wpa_supplicant/*,components/esp_wifi/*,*.pem,components/newlib/COPYING.*,docs/sphinx-known-warnings.txt
|
||||
skip = build,*.yuv,components/fatfs/src/*,alice.txt,*.rgb,components/wpa_supplicant/*,components/esp_wifi/*,*.pem,components/newlib/COPYING.*
|
||||
ignore-words-list = ser,dout,rsource,fram,inout,shs,ans,aci,unstall,unstalling,hart,wheight,wel,ot,fane,assertIn,registr,oen,parms
|
||||
write-changes = true
|
||||
|
||||
2
.github/workflows/release_zips.yml
vendored
2
.github/workflows/release_zips.yml
vendored
@@ -8,7 +8,7 @@ on:
|
||||
jobs:
|
||||
release_zips:
|
||||
name: Create release zip file
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- name: Create a recursive clone source zip
|
||||
uses: espressif/release-zips-action@v1
|
||||
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -37,7 +37,6 @@ components/**/build/
|
||||
components/**/build_*_*/
|
||||
components/**/sdkconfig
|
||||
components/**/sdkconfig.old
|
||||
components/**/test_apps/wifi_nvs_config/nvs_data_suffix.csv
|
||||
|
||||
# Example project files
|
||||
examples/**/build/
|
||||
|
||||
@@ -2,253 +2,5 @@
|
||||
#
|
||||
# https://docs.gitlab.com/ee/user/project/code_owners.html#the-syntax-of-code-owners-files
|
||||
#
|
||||
# If more than one rule matches a given file, the latest rule is used.
|
||||
# The file should be generally kept sorted, except when it is necessary
|
||||
# to use a different order due to the fact above. In that case, use
|
||||
# '# sort-order-reset' comment line to reset the sort order.
|
||||
#
|
||||
# Recipes for a few common cases:
|
||||
#
|
||||
# 1. Specific directory with all its contents:
|
||||
#
|
||||
# /components/app_trace/
|
||||
#
|
||||
# Note the trailing slash!
|
||||
#
|
||||
# 2. File with certain extension in any subdirectory of a certain directory:
|
||||
#
|
||||
# /examples/**/*.py
|
||||
#
|
||||
# This includes an *.py files in /examples/ directory as well.
|
||||
#
|
||||
# 3. Contents of a directory with a certain name, anywhere in the tree:
|
||||
#
|
||||
# test_*_host/
|
||||
#
|
||||
# Will match everything under components/efuse/test_efuse_host/,
|
||||
# components/heap/test_multi_heap_host/, components/lwip/test_afl_host/, etc.
|
||||
#
|
||||
# 4. Same as above, except limited to a specific place in the tree:
|
||||
#
|
||||
# /components/esp32*/
|
||||
#
|
||||
# Matches everything under /components/esp32, /components/esp32s2, etc.
|
||||
# Doesn't match /tools/some-test/components/esp32s5.
|
||||
#
|
||||
# 5. Specific file:
|
||||
#
|
||||
# /tools/tools.json
|
||||
#
|
||||
# 6. File with a certain name anywhere in the tree
|
||||
#
|
||||
# .gitignore
|
||||
#
|
||||
|
||||
* @esp-idf-codeowners/other
|
||||
|
||||
/.* @esp-idf-codeowners/tools
|
||||
/.codespellrc @esp-idf-codeowners/ci
|
||||
/.github/workflows/ @esp-idf-codeowners/ci
|
||||
/.gitlab-ci.yml @esp-idf-codeowners/ci
|
||||
/.gitlab/ci/ @esp-idf-codeowners/ci
|
||||
/.pre-commit-config.yaml @esp-idf-codeowners/ci
|
||||
/.readthedocs.yml @esp-idf-codeowners/docs
|
||||
/.vale.ini @esp-idf-codeowners/docs
|
||||
/CMakeLists.txt @esp-idf-codeowners/build-config
|
||||
/COMPATIBILITY*.md @esp-idf-codeowners/peripherals
|
||||
/CONTRIBUTING.md @esp-idf-codeowners/docs
|
||||
/Kconfig @esp-idf-codeowners/build-config
|
||||
/README*.md @esp-idf-codeowners/docs
|
||||
/ROADMAP*.md @esp-idf-codeowners/docs
|
||||
/SUPPORT_POLICY*.md @esp-idf-codeowners/docs
|
||||
/add_path.sh @esp-idf-codeowners/tools
|
||||
/conftest.py @esp-idf-codeowners/ci
|
||||
/export.* @esp-idf-codeowners/tools
|
||||
/install.* @esp-idf-codeowners/tools
|
||||
/pytest.ini @esp-idf-codeowners/ci
|
||||
/ruff.toml @esp-idf-codeowners/tools
|
||||
/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
|
||||
/components/esp_psram/system_layer/ @esp-idf-codeowners/peripherals @esp-idf-codeowners/system
|
||||
/components/esp_ringbuf/ @esp-idf-codeowners/system
|
||||
/components/esp_rom/ @esp-idf-codeowners/system @esp-idf-codeowners/bluetooth @esp-idf-codeowners/wifi
|
||||
/components/esp_security/ @esp-idf-codeowners/security
|
||||
/components/esp_system/ @esp-idf-codeowners/system
|
||||
/components/esp_tee/ @esp-idf-codeowners/security
|
||||
/components/esp_timer/ @esp-idf-codeowners/system
|
||||
/components/esp-tls/ @esp-idf-codeowners/app-utilities
|
||||
/components/esp_vfs_*/ @esp-idf-codeowners/storage
|
||||
/components/esp_vfs_console/ @esp-idf-codeowners/storage @esp-idf-codeowners/system
|
||||
/components/esp_wifi/ @esp-idf-codeowners/wifi
|
||||
/components/espcoredump/ @esp-idf-codeowners/debugging
|
||||
/components/esptool_py/ @esp-idf-codeowners/tools
|
||||
/components/fatfs/ @esp-idf-codeowners/storage
|
||||
/components/freertos/ @esp-idf-codeowners/system
|
||||
/components/hal/ @esp-idf-codeowners/peripherals
|
||||
/components/hal/test_apps/crypto/ @esp-idf-codeowners/peripherals @esp-idf-codeowners/security
|
||||
/components/heap/ @esp-idf-codeowners/system
|
||||
/components/http_parser/ @esp-idf-codeowners/app-utilities
|
||||
/components/idf_test/ @esp-idf-codeowners/peripherals @esp-idf-codeowners/system
|
||||
/components/ieee802154/ @esp-idf-codeowners/ieee802154
|
||||
/components/json/ @esp-idf-codeowners/app-utilities
|
||||
/components/linux/ @esp-idf-codeowners/system
|
||||
/components/log/ @esp-idf-codeowners/system
|
||||
/components/lwip/ @esp-idf-codeowners/lwip
|
||||
/components/mbedtls/ @esp-idf-codeowners/app-utilities/mbedtls @esp-idf-codeowners/security
|
||||
/components/mqtt/ @esp-idf-codeowners/network
|
||||
/components/newlib/ @esp-idf-codeowners/system @esp-idf-codeowners/toolchain
|
||||
/components/nvs_flash/ @esp-idf-codeowners/storage
|
||||
/components/nvs_sec_provider/ @esp-idf-codeowners/storage @esp-idf-codeowners/security
|
||||
/components/openthread/ @esp-idf-codeowners/ieee802154
|
||||
/components/partition_table/ @esp-idf-codeowners/system
|
||||
/components/perfmon/ @esp-idf-codeowners/debugging
|
||||
/components/protobuf-c/ @esp-idf-codeowners/app-utilities
|
||||
/components/protocomm/ @esp-idf-codeowners/app-utilities/provisioning
|
||||
/components/pthread/ @esp-idf-codeowners/system
|
||||
/components/riscv/ @esp-idf-codeowners/system
|
||||
/components/rt/ @esp-idf-codeowners/system
|
||||
/components/sdmmc/ @esp-idf-codeowners/storage
|
||||
/components/soc/ @esp-idf-codeowners/peripherals @esp-idf-codeowners/system
|
||||
/components/spi_flash/ @esp-idf-codeowners/peripherals
|
||||
/components/spiffs/ @esp-idf-codeowners/storage
|
||||
/components/tcp_transport/ @esp-idf-codeowners/network
|
||||
/components/touch_element/ @esp-idf-codeowners/peripherals
|
||||
/components/ulp/ @esp-idf-codeowners/system
|
||||
/components/unity/ @esp-idf-codeowners/peripherals @esp-idf-codeowners/system
|
||||
/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/docs_not_updated/ @esp-idf-codeowners/all-maintainers
|
||||
/docs/**/api-guides/tools/ @esp-idf-codeowners/tools
|
||||
/docs/en/api-guides/core_dump.rst @esp-idf-codeowners/debugging
|
||||
/docs/**/api-guides/wifi* @esp-idf-codeowners/wifi
|
||||
/docs/**/api-guides/esp-wifi-mesh.rst @esp-idf-codeowners/wifi
|
||||
/docs/en/api-guides/jtag-debugging/ @esp-idf-codeowners/debugging
|
||||
/docs/**/api-reference/bluetooth/ @esp-idf-codeowners/bluetooth
|
||||
/docs/**/api-reference/network/ @esp-idf-codeowners/network @esp-idf-codeowners/wifi
|
||||
/docs/**/api-reference/peripherals/ @esp-idf-codeowners/peripherals
|
||||
/docs/**/api-reference/peripherals/usb* @esp-idf-codeowners/peripherals @esp-idf-codeowners/peripherals/usb
|
||||
/docs/**/api-reference/peripherals/usb*/ @esp-idf-codeowners/peripherals @esp-idf-codeowners/peripherals/usb
|
||||
/docs/**/api-reference/protocols/ @esp-idf-codeowners/network @esp-idf-codeowners/app-utilities
|
||||
/docs/**/api-reference/provisioning/ @esp-idf-codeowners/app-utilities/provisioning
|
||||
/docs/**/api-reference/storage/ @esp-idf-codeowners/storage
|
||||
/docs/**/api-reference/system/ @esp-idf-codeowners/system
|
||||
/docs/**/security/ @esp-idf-codeowners/security
|
||||
/docs/**/migration-guides/ @esp-idf-codeowners/docs @esp-idf-codeowners/all-maintainers
|
||||
/docs/**/contribute/install-pre-commit-hook.rst @esp-idf-codeowners/ci @esp-idf-codeowners/tools
|
||||
|
||||
/examples/README.md @esp-idf-codeowners/docs @esp-idf-codeowners/ci
|
||||
/examples/**/*.py @esp-idf-codeowners/ci @esp-idf-codeowners/tools
|
||||
/examples/bluetooth/ @esp-idf-codeowners/bluetooth
|
||||
/examples/build_system/ @esp-idf-codeowners/build-config
|
||||
/examples/common_components/ @esp-idf-codeowners/system @esp-idf-codeowners/wifi @esp-idf-codeowners/lwip @esp-idf-codeowners/network
|
||||
/examples/custom_bootloader/ @esp-idf-codeowners/system
|
||||
/examples/cxx/ @esp-idf-codeowners/system
|
||||
/examples/ethernet/ @esp-idf-codeowners/network
|
||||
/examples/get-started/ @esp-idf-codeowners/system
|
||||
/examples/ieee802154/ @esp-idf-codeowners/ieee802154
|
||||
/examples/lowpower/ @esp-idf-codeowners/power-management @esp-idf-codeowners/system
|
||||
/examples/mesh/ @esp-idf-codeowners/wifi
|
||||
/examples/network/ @esp-idf-codeowners/network @esp-idf-codeowners/wifi
|
||||
/examples/openthread/ @esp-idf-codeowners/ieee802154
|
||||
/examples/peripherals/ @esp-idf-codeowners/peripherals
|
||||
/examples/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/bt/ @esp-idf-codeowners/bluetooth
|
||||
/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
|
||||
|
||||
@@ -231,18 +231,13 @@ pytest_build_system_macos:
|
||||
- .after_script:build:macos:upload-failed-job-logs:ccache-show-stats
|
||||
- .rules:build:macos
|
||||
tags:
|
||||
- macos
|
||||
- macos_shell
|
||||
parallel: 3
|
||||
variables:
|
||||
PYENV_VERSION: "3.9"
|
||||
# CCACHE_DIR: "/cache/idf_ccache". On macOS, you cannot write to this folder due to insufficient permissions.
|
||||
CCACHE_DIR: "" # ccache will use "$HOME/Library/Caches/ccache".
|
||||
CCACHE_MAXSIZE: "5G" # To preserve the limited Macbook storage. CCACHE automatically prunes old caches to fit the set limit.
|
||||
# Workaround for a bug in Parallels executor where CI_PROJECT_DIR is not an absolute path,
|
||||
# but a relative path to the build directory (builds/espressif/esp-idf instead of ~/builds/espressif/esp-idf.
|
||||
# GitLab sets the project dir to this template `<builds_dir>/<namespace>/<project_name>`
|
||||
IDF_PATH: "/Users/espressif/builds/espressif/esp-idf"
|
||||
|
||||
build_docker:
|
||||
extends:
|
||||
- .before_script:minimal
|
||||
|
||||
@@ -40,7 +40,7 @@ variables:
|
||||
GIT_FETCH_EXTRA_FLAGS: "--no-recurse-submodules --prune --prune-tags"
|
||||
# we're using .cache folder for caches
|
||||
GIT_CLEAN_FLAGS: -ffdx -e .cache/
|
||||
LATEST_GIT_TAG: v6.0-dev
|
||||
LATEST_GIT_TAG: v5.5
|
||||
|
||||
SUBMODULE_FETCH_TOOL: "tools/ci/ci_fetch_submodule.py"
|
||||
# by default we will fetch all submodules
|
||||
@@ -55,9 +55,9 @@ variables:
|
||||
CHECKOUT_REF_SCRIPT: "$CI_PROJECT_DIR/tools/ci/checkout_project_ref.py"
|
||||
|
||||
# Docker images
|
||||
ESP_ENV_IMAGE: "${CI_DOCKER_REGISTRY}/esp-env-v6.0:1"
|
||||
ESP_IDF_DOC_ENV_IMAGE: "${CI_DOCKER_REGISTRY}/esp-idf-doc-env-v6.0:1-1"
|
||||
TARGET_TEST_ENV_IMAGE: "${CI_DOCKER_REGISTRY}/target-test-env-v6.0:1"
|
||||
ESP_ENV_IMAGE: "${CI_DOCKER_REGISTRY}/esp-env-v5.5:3"
|
||||
ESP_IDF_DOC_ENV_IMAGE: "${CI_DOCKER_REGISTRY}/esp-idf-doc-env-v5.5:3-1"
|
||||
TARGET_TEST_ENV_IMAGE: "${CI_DOCKER_REGISTRY}/target-test-env-v5.5:2"
|
||||
SONARQUBE_SCANNER_IMAGE: "${CI_DOCKER_REGISTRY}/sonarqube-scanner:5"
|
||||
PRE_COMMIT_IMAGE: "${CI_DOCKER_REGISTRY}/esp-idf-pre-commit:1"
|
||||
|
||||
@@ -70,7 +70,7 @@ variables:
|
||||
CI_PYTHON_CONSTRAINT_BRANCH: ""
|
||||
|
||||
# Update the filename for a specific ESP-IDF release. It is used only with CI_PYTHON_CONSTRAINT_BRANCH.
|
||||
CI_PYTHON_CONSTRAINT_FILE: "espidf.constraints.v6.0.txt"
|
||||
CI_PYTHON_CONSTRAINT_FILE: "espidf.constraints.v5.5.txt"
|
||||
|
||||
# Set this variable to repository name of a Python tool you wish to install and test in the context of ESP-IDF CI.
|
||||
# Keep the variable empty when not used.
|
||||
@@ -140,13 +140,6 @@ variables:
|
||||
if [[ -n "$IDF_DONT_USE_MIRRORS" ]]; then
|
||||
export IDF_MIRROR_PREFIX_MAP=
|
||||
fi
|
||||
# Optimize pip install
|
||||
if echo "${CI_RUNNER_TAGS}" | grep "shiny"; then
|
||||
export PIP_INDEX_URL="${PIP_INDEX_URL_SHINY}"
|
||||
fi
|
||||
if [[ "$(uname -m)" == "x86_64" ]] || [[ "$(uname -m)" == "aarch64" ]]; then
|
||||
export IDF_PIP_WHEELS_URL=""
|
||||
fi
|
||||
|
||||
if [[ "${CI_JOB_STAGE}" != "target_test" ]]; then
|
||||
section_start "running_install_sh" "Running install.sh"
|
||||
@@ -243,6 +236,8 @@ variables:
|
||||
# Ensure pyenv and PYENV_VERSION installed
|
||||
- eval "$(pyenv init -)"
|
||||
- *common-before_scripts
|
||||
# On macOS, these tools need to be installed
|
||||
- export IDF_TOOLS_PATH="${HOME}/.espressif_runner_${CI_RUNNER_ID}_${CI_CONCURRENT_ID}"
|
||||
# remove idf-env.json, since it may contains enabled "features"
|
||||
- rm -f $IDF_TOOLS_PATH/idf-env.json
|
||||
# This adds tools (compilers) and the version-specific Python environment to PATH
|
||||
|
||||
@@ -14,9 +14,9 @@ extra_default_build_targets:
|
||||
|
||||
bypass_check_test_targets:
|
||||
- esp32h21
|
||||
- esp32c61
|
||||
- esp32h4
|
||||
- esp32c5
|
||||
- esp32c61
|
||||
|
||||
#
|
||||
# These lines would
|
||||
|
||||
@@ -91,4 +91,4 @@
|
||||
specific_rules:
|
||||
- if-schedule-test-build-system-windows
|
||||
patterns:
|
||||
- build_system_win
|
||||
- build_system
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
image: $ESP_ENV_IMAGE
|
||||
tags: [ deploy ]
|
||||
|
||||
# Check this before push_to_github
|
||||
check_submodule_sync:
|
||||
extends:
|
||||
- .deploy_job_template
|
||||
@@ -30,9 +31,8 @@ push_to_github:
|
||||
extends:
|
||||
- .deploy_job_template
|
||||
- .before_script:minimal
|
||||
- .rules:protected:deploy
|
||||
- .rules:push_to_github
|
||||
needs:
|
||||
# submodule must be synced before pushing to github
|
||||
- check_submodule_sync
|
||||
tags: [ brew, github_sync ]
|
||||
variables:
|
||||
@@ -45,16 +45,12 @@ push_to_github:
|
||||
- git remote remove github &>/dev/null || true
|
||||
- git remote add github git@github.com:espressif/esp-idf.git
|
||||
- tools/ci/push_to_github.sh
|
||||
environment:
|
||||
name: push_to_github_production
|
||||
deployment_tier: production
|
||||
url: "https://github.com/espressif/esp-idf"
|
||||
|
||||
deploy_update_SHA_in_esp-dockerfiles:
|
||||
extends:
|
||||
- .deploy_job_template
|
||||
- .before_script:minimal
|
||||
- .rules:protected:deploy
|
||||
- .rules:protected-no_label-always
|
||||
dependencies: []
|
||||
variables:
|
||||
GIT_DEPTH: 2
|
||||
@@ -63,6 +59,3 @@ deploy_update_SHA_in_esp-dockerfiles:
|
||||
- 'curl --header "PRIVATE-TOKEN: ${ESPCI_SCRIPTS_TOKEN}" -o create_MR_in_esp_dockerfile.sh $GITLAB_HTTP_SERVER/api/v4/projects/1260/repository/files/create_MR_in_esp_dockerfile%2Fcreate_MR_in_esp_dockerfile.sh/raw\?ref\=master'
|
||||
- chmod +x create_MR_in_esp_dockerfile.sh
|
||||
- ./create_MR_in_esp_dockerfile.sh
|
||||
environment:
|
||||
name: eploy_update_SHA_in_esp-dockerfiles_production
|
||||
deployment_tier: production
|
||||
|
||||
@@ -4,10 +4,10 @@
|
||||
- "**/*.rst"
|
||||
- "CONTRIBUTING.rst"
|
||||
- "**/soc_caps.h"
|
||||
- "**/Kconfig*"
|
||||
|
||||
.patterns-docs-partial: &patterns-docs-partial
|
||||
- "components/**/*.h"
|
||||
- "components/**/Kconfig*"
|
||||
- "components/**/CMakeList.txt"
|
||||
- "components/**/sdkconfig*"
|
||||
- "tools/tools.json"
|
||||
@@ -19,9 +19,12 @@
|
||||
.patterns-docs-preview: &patterns-docs-preview
|
||||
- "docs/**/*"
|
||||
|
||||
.if-protected-check: &if-protected-check
|
||||
.if-protected: &if-protected
|
||||
if: '($CI_COMMIT_REF_NAME == "master" || $CI_COMMIT_BRANCH =~ /^release\/v/ || $CI_COMMIT_TAG =~ /^v\d+\.\d+(\.\d+)?($|-)/)'
|
||||
|
||||
.if-protected-no_label: &if-protected-no_label
|
||||
if: '($CI_COMMIT_REF_NAME == "master" || $CI_COMMIT_BRANCH =~ /^release\/v/ || $CI_COMMIT_TAG =~ /^v\d+\.\d+(\.\d+)?($|-)/) && $BOT_TRIGGER_WITH_LABEL == null'
|
||||
|
||||
.if-qa-test-tag: &if-qa-test-tag
|
||||
if: '$CI_COMMIT_TAG =~ /^qa-test/'
|
||||
|
||||
@@ -38,7 +41,7 @@
|
||||
rules:
|
||||
- <<: *if-qa-test-tag
|
||||
when: never
|
||||
- <<: *if-protected-check
|
||||
- <<: *if-protected
|
||||
- <<: *if-label-build_docs
|
||||
- <<: *if-label-docs_full
|
||||
- <<: *if-dev-push
|
||||
@@ -61,7 +64,7 @@ check_readme_links:
|
||||
tags: ["build", "amd64", "internet"]
|
||||
allow_failure: true
|
||||
rules:
|
||||
- <<: *if-protected-check
|
||||
- <<: *if-protected
|
||||
- <<: *if-dev-push
|
||||
changes: *patterns-example-readme
|
||||
script:
|
||||
@@ -93,7 +96,7 @@ check_docs_lang_sync:
|
||||
parallel:
|
||||
matrix:
|
||||
- DOCLANG: ["en", "zh_CN"]
|
||||
DOCTGT: ["esp32", "esp32s2", "esp32s3", "esp32c3", "esp32c2", "esp32c6", "esp32c61", "esp32c5", "esp32h2", "esp32h4", "esp32h21", "esp32p4"]
|
||||
DOCTGT: ["esp32", "esp32s2", "esp32s3", "esp32c3", "esp32c2", "esp32c6", "esp32c61", "esp32c5","esp32h2", "esp32h21", "esp32p4"]
|
||||
|
||||
check_docs_gh_links:
|
||||
image: $ESP_IDF_DOC_ENV_IMAGE
|
||||
@@ -179,17 +182,14 @@ deploy_docs_preview:
|
||||
DOCS_DEPLOY_SERVER_USER: "$DOCS_SERVER_USER"
|
||||
DOCS_DEPLOY_PATH: "$DOCS_PATH"
|
||||
DOCS_DEPLOY_URL_BASE: "https://$DOCS_PREVIEW_SERVER_URL/docs/esp-idf"
|
||||
environment:
|
||||
name: deploy_docs_preview
|
||||
deployment_tier: staging
|
||||
url: "https://$DOCS_PREVIEW_SERVER_URL/docs/esp-idf"
|
||||
|
||||
# stage: post_deploy
|
||||
deploy_docs_production:
|
||||
# The DOCS_PROD_* variables used by this job are "Protected" so these branches must all be marked "Protected" in Gitlab settings
|
||||
extends:
|
||||
- .deploy_docs_template
|
||||
- .rules:protected:deploy
|
||||
rules:
|
||||
- <<: *if-protected-no_label
|
||||
stage: post_deploy
|
||||
dependencies: # set dependencies to null to avoid missing artifacts issue
|
||||
needs: # ensure runs after push_to_github succeeded
|
||||
@@ -204,15 +204,12 @@ deploy_docs_production:
|
||||
DOCS_DEPLOY_PATH: "$DOCS_PROD_PATH"
|
||||
DOCS_DEPLOY_URL_BASE: "https://docs.espressif.com/projects/esp-idf"
|
||||
DEPLOY_STABLE: 1
|
||||
environment:
|
||||
name: deploy_docs_production
|
||||
deployment_tier: production
|
||||
url: "https://docs.espressif.com/projects/esp-idf"
|
||||
|
||||
check_doc_links:
|
||||
extends:
|
||||
- .build_docs_template
|
||||
- .rules:protected:deploy
|
||||
rules:
|
||||
- <<: *if-protected-no_label
|
||||
stage: post_deploy
|
||||
needs:
|
||||
- job: deploy_docs_production
|
||||
|
||||
@@ -113,8 +113,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
|
||||
# cmake@version that is supported
|
||||
- python3 ${IDF_PATH}/tools/idf_tools.py download required qemu-riscv32 qemu-xtensa cmake cmake@3.16.3
|
||||
- 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
|
||||
@@ -349,7 +348,7 @@ test_pytest_macos:
|
||||
- .host_test_template
|
||||
- .before_script:build:macos
|
||||
tags:
|
||||
- macos
|
||||
- macos_shell
|
||||
artifacts:
|
||||
paths:
|
||||
- XUNIT_RESULT.xml
|
||||
@@ -360,22 +359,18 @@ test_pytest_macos:
|
||||
variables:
|
||||
PYENV_VERSION: "3.9"
|
||||
PYTEST_IGNORE_COLLECT_IMPORT_ERROR: "1"
|
||||
# Workaround for a bug in Parallels executor where CI_PROJECT_DIR is not an absolute path,
|
||||
# but a relative path to the build directory (builds/espressif/esp-idf instead of ~/builds/espressif/esp-idf.
|
||||
# GitLab sets the project dir to this template `<builds_dir>/<namespace>/<project_name>`
|
||||
IDF_PATH: "/Users/espressif/builds/espressif/esp-idf"
|
||||
script:
|
||||
- run_cmd python tools/ci/ci_build_apps.py components examples tools/test_apps -v
|
||||
--target linux
|
||||
--pytest-apps
|
||||
-m \"host_test and macos\"
|
||||
-m \"host_test and macos_shell\"
|
||||
--collect-app-info "list_job_${CI_JOB_NAME_SLUG}.txt"
|
||||
--modified-components ${MR_MODIFIED_COMPONENTS}
|
||||
--modified-files ${MR_MODIFIED_FILES}
|
||||
- python tools/ci/get_known_failure_cases_file.py
|
||||
- run_cmd pytest
|
||||
--target linux
|
||||
-m \"host_test and macos\"
|
||||
-m \"host_test and macos_shell\"
|
||||
--junitxml=XUNIT_RESULT.xml
|
||||
--ignore-result-files ${KNOWN_FAILURE_CASES_FILE_NAME}
|
||||
--app-info-filepattern \"list_job_*.txt\"
|
||||
|
||||
@@ -1,15 +1,11 @@
|
||||
.post_deploy_template:
|
||||
stage: post_deploy
|
||||
image: $ESP_ENV_IMAGE
|
||||
|
||||
generate_failed_jobs_report:
|
||||
extends:
|
||||
- .post_deploy_template
|
||||
stage: post_deploy
|
||||
tags: [build, shiny]
|
||||
image: $ESP_ENV_IMAGE
|
||||
when: always
|
||||
dependencies: [] # Do not download artifacts from the previous stages
|
||||
artifacts:
|
||||
expire_in: 2 week
|
||||
expire_in: 1 week
|
||||
when: always
|
||||
paths:
|
||||
- job_report.html
|
||||
@@ -17,16 +13,12 @@ generate_failed_jobs_report:
|
||||
- python tools/ci/dynamic_pipelines/scripts/generate_report.py --report-type job
|
||||
|
||||
sync_support_status:
|
||||
stage: post_deploy
|
||||
extends:
|
||||
- .post_deploy_template
|
||||
- .rules:master:push
|
||||
tags: [ brew, github_sync ]
|
||||
- .rules:sync_support_status
|
||||
needs:
|
||||
- push_to_github
|
||||
cache: []
|
||||
before_script: []
|
||||
image: $ESP_ENV_IMAGE
|
||||
tags: [ brew, github_sync ]
|
||||
script:
|
||||
- curl --fail --request POST --form token="$IDF_STATUS_TRIG_TOKEN" --form ref="$IDF_STATUS_BRANCH" --form "variables[UPLOAD_TO_S3]=true" "$IDF_STATUS_TRIG_URL"
|
||||
environment:
|
||||
name: sync_support_status_production
|
||||
deployment_tier: production
|
||||
|
||||
@@ -10,7 +10,7 @@ check_version:
|
||||
# esp_idf_version.h in a branch before tagging the next version.
|
||||
extends:
|
||||
- .pre_check_template
|
||||
- .rules:protected:check
|
||||
- .rules:protected
|
||||
tags: [ brew, github_sync ]
|
||||
variables:
|
||||
# need a full clone to get the latest tag
|
||||
|
||||
@@ -56,9 +56,6 @@
|
||||
- "tools/ci/ci_build_apps.py"
|
||||
- "tools/test_build_system/**/*"
|
||||
|
||||
.patterns-build_system_win: &patterns-build_system_win
|
||||
- "tools/test_build_system/**/*"
|
||||
|
||||
.patterns-build_macos: &patterns-build_macos
|
||||
- "tools/ci/test_configure_ci_environment.sh"
|
||||
|
||||
@@ -170,19 +167,22 @@
|
||||
##############
|
||||
# if anchors #
|
||||
##############
|
||||
.if-master-push: &if-master-push
|
||||
if: '$CI_COMMIT_REF_NAME == "master" && $CI_PIPELINE_SOURCE == "push"'
|
||||
.if-ref-master: &if-ref-master
|
||||
if: '$CI_COMMIT_REF_NAME == "master"'
|
||||
|
||||
.if-release-tag: &if-release-tag
|
||||
.if-ref-master-no_label: &if-ref-master-no_label
|
||||
if: '$CI_COMMIT_REF_NAME == "master" && $BOT_TRIGGER_WITH_LABEL == null'
|
||||
|
||||
.if-tag-release: &if-tag-release
|
||||
if: '$CI_COMMIT_TAG =~ /^v\d+\.\d+(\.\d+)?($|-)/'
|
||||
|
||||
.if-protected-check: &if-protected-check
|
||||
.if-protected: &if-protected
|
||||
if: '($CI_COMMIT_REF_NAME == "master" || $CI_COMMIT_BRANCH =~ /^release\/v/ || $CI_COMMIT_TAG =~ /^v\d+\.\d+(\.\d+)?($|-)/) || $CI_COMMIT_TAG =~ /^qa-test/'
|
||||
|
||||
.if-protected-deploy: &if-protected-deploy
|
||||
if: '($CI_COMMIT_REF_NAME == "master" || $CI_COMMIT_BRANCH =~ /^release\/v/ || $CI_COMMIT_TAG =~ /^v\d+\.\d+(\.\d+)?($|-)/) && ($CI_PIPELINE_SOURCE == "push" || $CI_PIPELINE_SOURCE == "api")'
|
||||
.if-protected-no_label: &if-protected-no_label
|
||||
if: '($CI_COMMIT_REF_NAME == "master" || $CI_COMMIT_BRANCH =~ /^release\/v/ || $CI_COMMIT_TAG =~ /^v\d+\.\d+(\.\d+)?($|-)/) && $BOT_TRIGGER_WITH_LABEL == null'
|
||||
|
||||
.if-protected-branch-push: &if-protected-branch-push
|
||||
.if-protected-ref-push: &if-protected-ref-push
|
||||
# rules:changes always evaluates to true for new branch pipelines or when there is no Git push event
|
||||
if: '($CI_COMMIT_REF_NAME == "master" || $CI_COMMIT_BRANCH =~ /^release\/v/) && $CI_PIPELINE_SOURCE == "push"'
|
||||
|
||||
@@ -192,6 +192,9 @@
|
||||
.if-dev-push: &if-dev-push
|
||||
if: '$CI_COMMIT_REF_NAME != "master" && $CI_COMMIT_BRANCH !~ /^release\/v/ && $CI_COMMIT_TAG !~ /^v\d+\.\d+(\.\d+)?($|-)/ && $CI_COMMIT_TAG !~ /^qa-test/ && ($CI_PIPELINE_SOURCE == "push" || $CI_PIPELINE_SOURCE == "merge_request_event")'
|
||||
|
||||
.if-schedule: &if-schedule
|
||||
if: '$CI_PIPELINE_SOURCE == "schedule"'
|
||||
|
||||
.if-schedule-nightly: &if-schedule-nightly
|
||||
if: '$CI_PIPELINE_SOURCE == "schedule" && $INCLUDE_NIGHTLY_RUN == "1"'
|
||||
|
||||
@@ -211,41 +214,51 @@
|
||||
# Rules #
|
||||
#########
|
||||
### Branches ###
|
||||
.rules:protected:check:
|
||||
.rules:protected:
|
||||
rules:
|
||||
- <<: *if-protected-check
|
||||
- <<: *if-protected
|
||||
|
||||
.rules:protected:deploy:
|
||||
.rules:push_to_github:
|
||||
rules:
|
||||
- <<: *if-qa-test-tag
|
||||
when: never
|
||||
- <<: *if-protected-deploy
|
||||
- <<: *if-protected-no_label
|
||||
|
||||
.rules:master:push:
|
||||
# Not uploading on release branches
|
||||
.rules:sync_support_status:
|
||||
rules:
|
||||
- <<: *if-master-push
|
||||
- <<: *if-ref-master-no_label
|
||||
|
||||
.rules:protected-no_label-always:
|
||||
rules:
|
||||
- <<: *if-qa-test-tag
|
||||
when: never
|
||||
- <<: *if-protected-no_label
|
||||
when: always
|
||||
|
||||
.rules:tag:release:
|
||||
rules:
|
||||
- <<: *if-release-tag
|
||||
- <<: *if-tag-release
|
||||
|
||||
.rules:dev-push:
|
||||
rules:
|
||||
- <<: *if-dev-push
|
||||
|
||||
# Do not upload caches on dev branches by default
|
||||
.rules:upload-python-cache:
|
||||
rules:
|
||||
- <<: *if-release-tag
|
||||
- <<: *if-tag-release
|
||||
- <<: *if-schedule-nightly
|
||||
- <<: *if-protected-branch-push
|
||||
- <<: *if-protected-ref-push
|
||||
changes: *patterns-python-cache
|
||||
- <<: *if-label-upload_cache
|
||||
when: manual
|
||||
|
||||
.rules:upload-submodule-cache:
|
||||
rules:
|
||||
- <<: *if-release-tag
|
||||
- <<: *if-protected-branch-push
|
||||
# Needn't upload submodule cache in schedule pipeline
|
||||
- <<: *if-tag-release
|
||||
- <<: *if-protected-ref-push
|
||||
changes: *patterns-submodule
|
||||
- <<: *if-label-upload_cache
|
||||
when: manual
|
||||
@@ -253,10 +266,11 @@
|
||||
### Patterns ###
|
||||
.rules:patterns:clang_tidy:
|
||||
rules:
|
||||
- <<: *if-protected-check
|
||||
- <<: *if-protected
|
||||
- <<: *if-dev-push
|
||||
changes: *patterns-c-files
|
||||
|
||||
|
||||
#.rules:patterns:static-code-analysis-preview:
|
||||
# rules:
|
||||
# - <<: *if-dev-push
|
||||
@@ -268,7 +282,7 @@
|
||||
|
||||
.rules:patterns:idf-pytest-plugin:
|
||||
rules:
|
||||
- <<: *if-protected-check
|
||||
- <<: *if-protected
|
||||
- <<: *if-dev-push
|
||||
changes: *patterns-idf-pytest-plugin
|
||||
|
||||
@@ -312,7 +326,7 @@
|
||||
rules:
|
||||
- <<: *if-revert-branch
|
||||
when: never
|
||||
- <<: *if-protected-check
|
||||
- <<: *if-protected
|
||||
- <<: *if-label-build
|
||||
- <<: *if-dev-push
|
||||
changes: *patterns-build_components
|
||||
@@ -325,7 +339,7 @@
|
||||
rules:
|
||||
- <<: *if-revert-branch
|
||||
when: never
|
||||
- <<: *if-protected-check
|
||||
- <<: *if-protected
|
||||
- <<: *if-label-build
|
||||
- <<: *if-dev-push
|
||||
changes: *patterns-build_check
|
||||
@@ -340,7 +354,7 @@
|
||||
rules:
|
||||
- <<: *if-revert-branch
|
||||
when: never
|
||||
- <<: *if-protected-check
|
||||
- <<: *if-protected
|
||||
- <<: *if-label-build
|
||||
- <<: *if-label-docker
|
||||
- <<: *if-dev-push
|
||||
@@ -356,7 +370,7 @@
|
||||
rules:
|
||||
- <<: *if-revert-branch
|
||||
when: never
|
||||
- <<: *if-protected-check
|
||||
- <<: *if-protected
|
||||
- <<: *if-label-build
|
||||
- <<: *if-label-macos
|
||||
- <<: *if-label-macos_test
|
||||
@@ -371,7 +385,7 @@
|
||||
rules:
|
||||
- <<: *if-revert-branch
|
||||
when: never
|
||||
- <<: *if-protected-check
|
||||
- <<: *if-protected
|
||||
- <<: *if-label-build
|
||||
- <<: *if-dev-push
|
||||
changes: *patterns-build_components
|
||||
@@ -395,13 +409,13 @@
|
||||
- <<: *if-schedule-test-build-system-windows
|
||||
- <<: *if-label-windows
|
||||
- <<: *if-dev-push
|
||||
changes: *patterns-build_system_win
|
||||
changes: *patterns-build_system
|
||||
|
||||
.rules:test:host_test:
|
||||
rules:
|
||||
- <<: *if-revert-branch
|
||||
when: never
|
||||
- <<: *if-protected-check
|
||||
- <<: *if-protected
|
||||
- <<: *if-label-build-only
|
||||
when: never
|
||||
- <<: *if-label-host_test
|
||||
@@ -412,7 +426,7 @@
|
||||
rules:
|
||||
- <<: *if-revert-branch
|
||||
when: never
|
||||
- <<: *if-protected-check
|
||||
- <<: *if-protected
|
||||
- <<: *if-label-build-only
|
||||
when: never
|
||||
- <<: *if-label-submodule
|
||||
|
||||
@@ -85,7 +85,7 @@ clang_tidy_check:
|
||||
#code_quality_report:
|
||||
# extends:
|
||||
# - .sonar_scan_template
|
||||
# - .rules:protected:check
|
||||
# - .rules:protected
|
||||
# allow_failure: true # it's using exit code to indicate the code analysis result,
|
||||
# # we don't want to block ci when critical issues founded
|
||||
# script:
|
||||
|
||||
@@ -18,12 +18,9 @@
|
||||
after_script: []
|
||||
|
||||
test_cli_installer_win:
|
||||
rules:
|
||||
- when: never
|
||||
extends:
|
||||
- .host_test_win_template
|
||||
- .rules:labels:windows_pytest_build_system
|
||||
allow_failure: true
|
||||
artifacts:
|
||||
when: on_failure
|
||||
paths:
|
||||
@@ -33,10 +30,10 @@ test_cli_installer_win:
|
||||
variables:
|
||||
IDF_PATH: "$CI_PROJECT_DIR"
|
||||
timeout: 3h
|
||||
allow_failure: true
|
||||
script:
|
||||
# Tools must be downloaded for testing
|
||||
# cmake@version that is supported
|
||||
- python ${IDF_PATH}\tools\idf_tools.py download required qemu-riscv32 qemu-xtensa cmake cmake@3.16.3
|
||||
- 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
|
||||
|
||||
@@ -70,6 +70,7 @@ repos:
|
||||
rev: v2.3.0
|
||||
hooks:
|
||||
- id: codespell
|
||||
exclude: ^docs/sphinx-known-warnings\.txt$
|
||||
- repo: local
|
||||
hooks:
|
||||
- id: check-executables
|
||||
@@ -212,7 +213,7 @@ repos:
|
||||
- id: check-copyright
|
||||
args: ['--ignore', 'tools/ci/check_copyright_ignore.txt', '--config', 'tools/ci/check_copyright_config.yaml']
|
||||
- repo: https://github.com/espressif/conventional-precommit-linter
|
||||
rev: v1.10.0
|
||||
rev: v1.7.0
|
||||
hooks:
|
||||
- id: conventional-precommit-linter
|
||||
stages: [commit-msg]
|
||||
|
||||
@@ -8,9 +8,9 @@ This document describes the compatibility between ESP-IDF releases and Espressif
|
||||
|
||||
NOTE: This document on release branches may be out-of-date. Check the [Compatibility file on master](https://github.com/espressif/esp-idf/blob/master/COMPATIBILITY.md) for the most accurate information.
|
||||
|
||||
See [Compatibility Advisory for Chip Revision Numbering Scheme](https://www.espressif.com/sites/default/files/advisory_downloads/AR2022-005%20Compatibility%20Advisory%20for%20Chip%20Revision%20Numbering%20%20Scheme.pdf) on the versioning of Espressif SoC revisions.
|
||||
See [Compatibility Advisory for Chip Revision Numbering Scheme](https://www.espressif.com.cn/sites/default/files/advisory_downloads/AR2022-005%20Compatibility%20Advisory%20for%20Chip%20Revision%20Numbering%20%20Scheme.pdf) on the versioning of Espressif SoC revisions.
|
||||
|
||||
You can run `esptool chip_id` to detect the series and revision of an SoC. See [SoC Errata](https://www.espressif.com/en/support/documents/technical-documents?keys=errata) for more on how to distinguish between chip revisions, and the improvements provided by chip revisions. And run `idf.py --version` to know the version of current ESP-IDF.
|
||||
You can run `esptool chip_id` to detect the series and revision of an SoC. See [SoC Errata](https://www.espressif.com.cn/en/support/documents/technical-documents?keys=errata) for more on how to distinguish between chip revisions, and the improvements provided by chip revisions. And run `idf.py --version` to know the version of current ESP-IDF.
|
||||
|
||||
## ESP-IDF Support for Different Chip Revisions
|
||||
|
||||
|
||||
12
Kconfig
12
Kconfig
@@ -118,6 +118,8 @@ mainmenu "Espressif IoT Development Framework Configuration"
|
||||
default "y" if IDF_TARGET="esp32c5"
|
||||
select FREERTOS_UNICORE
|
||||
select IDF_TARGET_ARCH_RISCV
|
||||
# TODO: [ESPTOOL-1044] remove when stub supported
|
||||
select IDF_ENV_BRINGUP
|
||||
|
||||
config IDF_TARGET_ESP32P4
|
||||
bool
|
||||
@@ -141,11 +143,13 @@ mainmenu "Espressif IoT Development Framework Configuration"
|
||||
default "y" if IDF_TARGET="esp32h21"
|
||||
select FREERTOS_UNICORE
|
||||
select IDF_TARGET_ARCH_RISCV
|
||||
select IDF_ENV_FPGA
|
||||
select IDF_ENV_BRINGUP
|
||||
|
||||
config IDF_TARGET_ESP32H4
|
||||
bool
|
||||
default "y" if IDF_TARGET="esp32h4"
|
||||
select FREERTOS_UNICORE # TODO: [ESP32H4] IDF-12319, need remove
|
||||
select IDF_TARGET_ARCH_RISCV
|
||||
select IDF_ENV_FPGA
|
||||
select IDF_ENV_BRINGUP
|
||||
@@ -646,7 +650,7 @@ mainmenu "Espressif IoT Development Framework Configuration"
|
||||
|
||||
choice COMPILER_ORPHAN_SECTIONS
|
||||
prompt "Orphan sections handling"
|
||||
default COMPILER_ORPHAN_SECTIONS_ERROR
|
||||
default COMPILER_ORPHAN_SECTIONS_WARNING
|
||||
depends on !IDF_TARGET_LINUX
|
||||
help
|
||||
If the linker finds orphan sections, it attempts to place orphan sections after sections of the same
|
||||
@@ -654,11 +658,6 @@ mainmenu "Espressif IoT Development Framework Configuration"
|
||||
That means that orphan sections could placed between sections defined in IDF linker scripts.
|
||||
This could lead to corruption of the binary image. Configure the linker action here.
|
||||
|
||||
config COMPILER_ORPHAN_SECTIONS_ERROR
|
||||
bool "Fail if orphan sections found"
|
||||
help
|
||||
Fails the link step with an error if orphan sections are detected.
|
||||
|
||||
config COMPILER_ORPHAN_SECTIONS_WARNING
|
||||
bool "Place with warning"
|
||||
help
|
||||
@@ -708,4 +707,3 @@ mainmenu "Espressif IoT Development Framework Configuration"
|
||||
- CONFIG_ESP_WIFI_ENABLE_ROAMING_APP
|
||||
- CONFIG_USB_HOST_EXT_PORT_RESET_ATTEMPTS
|
||||
- CONFIG_LIBC_PICOLIBC
|
||||
- CONFIG_GDMA_ENABLE_WEIGHTED_ARBITRATION
|
||||
|
||||
24
README.md
24
README.md
@@ -15,18 +15,18 @@ ESP-IDF is the development framework for Espressif SoCs supported on Windows, Li
|
||||
|
||||
The following table shows ESP-IDF support of Espressif SoCs where ![alt text][preview] and ![alt text][supported] denote preview status and support, respectively. The preview support is usually limited in time and intended for beta versions of chips. Please use an ESP-IDF release where the desired SoC is already supported.
|
||||
|
||||
|Chip | v5.0 | v5.1 | v5.2 | v5.3 | v5.4 | |
|
||||
|:----------- | :---------------------:| :--------------------: | :--------------------: | :--------------------: | :--------------------: |:------------------------------------------------------------------- |
|
||||
|ESP32 | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | |
|
||||
|ESP32-S2 | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | |
|
||||
|ESP32-C3 | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | |
|
||||
|ESP32-S3 | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] |[Announcement](https://www.espressif.com/en/news/ESP32_S3) |
|
||||
|ESP32-C2 | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] |[Announcement](https://www.espressif.com/en/news/ESP32-C2) |
|
||||
|ESP32-C6 | | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] |[Announcement](https://www.espressif.com/en/news/ESP32_C6) |
|
||||
|ESP32-H2 | | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] |[Announcement](https://www.espressif.com/en/news/ESP32_H2) |
|
||||
|ESP32-P4 | | | | ![alt text][supported] | ![alt text][supported] |[Announcement](https://www.espressif.com/en/news/ESP32-P4) |
|
||||
|ESP32-C5 | | | | | ![alt text][preview] |[Announcement](https://www.espressif.com/en/news/ESP32-C5) |
|
||||
|ESP32-C61 | | | | | ![alt text][preview] |[Announcement](https://www.espressif.com/en/products/socs/esp32-c61) |
|
||||
|Chip | v5.1 | v5.2 | v5.3 | v5.4 | v5.5 | |
|
||||
|:----------- |:--------------------: | :--------------------: | :--------------------: | :--------------------: | :--------------------: |:------------------------------------------------------------------- |
|
||||
|ESP32 | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | |
|
||||
|ESP32-S2 |![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | |
|
||||
|ESP32-C3 | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | |
|
||||
|ESP32-S3 | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] |[Announcement](https://www.espressif.com/en/news/ESP32_S3) |
|
||||
|ESP32-C2 | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] |[Announcement](https://www.espressif.com/en/news/ESP32-C2) |
|
||||
|ESP32-C6 | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] |[Announcement](https://www.espressif.com/en/news/ESP32_C6) |
|
||||
|ESP32-H2 |![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] |[Announcement](https://www.espressif.com/en/news/ESP32_H2) |
|
||||
|ESP32-P4 | | | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] |[Announcement](https://www.espressif.com/en/news/ESP32-P4) |
|
||||
|ESP32-C5 | | | | |![alt text][preview] |[Announcement](https://www.espressif.com/en/news/ESP32-C5) |
|
||||
|ESP32-C61 | | | | |![alt text][preview] |[Announcement](https://www.espressif.com/en/products/socs/esp32-c61) |
|
||||
|
||||
[supported]: https://img.shields.io/badge/-supported-green "supported"
|
||||
[preview]: https://img.shields.io/badge/-preview-orange "preview"
|
||||
|
||||
25
README_CN.md
25
README_CN.md
@@ -15,18 +15,19 @@ ESP-IDF 是乐鑫官方推出的物联网开发框架,支持 Windows、Linux
|
||||
|
||||
下表总结了乐鑫芯片在 ESP-IDF 各版本中的支持状态,其中 ![alt text][supported] 代表已支持,![alt text][preview] 代表目前处于预览支持状态。预览支持状态通常有时间限制,而且仅适用于测试版芯片。请确保使用与芯片相匹配的 ESP-IDF 版本。
|
||||
|
||||
|芯片 | v5.0 | v5.1 | v5.2 | v5.3 | v5.4 | |
|
||||
|:----------- | :---------------------:| :--------------------: | :--------------------: | :--------------------: | :--------------------: | :------------------------------------------------------------------------ |
|
||||
|ESP32 | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | |
|
||||
|ESP32-S2 | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | |
|
||||
|ESP32-C3 | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | |
|
||||
|ESP32-S3 | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | [芯片发布公告](https://www.espressif.com/zh-hans/news/ESP32_S3) |
|
||||
|ESP32-C2 | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | [芯片发布公告](https://www.espressif.com/zh-hans/news/ESP32-C2) |
|
||||
|ESP32-C6 | | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | [芯片发布公告](https://www.espressif.com/zh-hans/news/ESP32_C6) |
|
||||
|ESP32-H2 | | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | [芯片发布公告](https://www.espressif.com/zh-hans/news/ESP32_H2) |
|
||||
|ESP32-P4 | | | | ![alt text][supported] | ![alt text][supported] | [芯片发布公告](https://www.espressif.com/zh-hans/news/ESP32-P4) |
|
||||
|ESP32-C5 | | | | | ![alt text][preview] | [芯片发布公告](https://www.espressif.com/zh-hans/news/ESP32-C5) |
|
||||
|ESP32-C61 | | | | | ![alt text][preview] | [芯片发布公告](https://www.espressif.com/zh-hans/products/socs/esp32-c61) |
|
||||
芯片 | v5.1 | v5.2 | v5.3 | v5.4 | v5.5 | |
|
||||
|:----------- | :--------------------: | :--------------------: | :--------------------: | :--------------------: | :--------------------: |:------------------------------------------------------------------------ |
|
||||
|ESP32 |![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] |![alt text][supported] | |
|
||||
|ESP32-S2 |![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | |
|
||||
|ESP32-C3 |![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | |
|
||||
|ESP32-S3 |![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] |![alt text][supported] | [芯片发布公告](https://www.espressif.com/zh-hans/news/ESP32_S3) |
|
||||
|ESP32-C2 |![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] |![alt text][supported] | [芯片发布公告](https://www.espressif.com/zh-hans/news/ESP32-C2) |
|
||||
|ESP32-C6 |![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] |![alt text][supported] | [芯片发布公告](https://www.espressif.com/zh-hans/news/ESP32_C6) |
|
||||
|ESP32-H2 |![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] |![alt text][supported] | [芯片发布公告](https://www.espressif.com/zh-hans/news/ESP32_H2) |
|
||||
|ESP32-P4 | | | ![alt text][supported] | ![alt text][supported] |![alt text][supported] | [芯片发布公告](https://www.espressif.com/zh-hans/news/ESP32-P4) |
|
||||
|ESP32-C5 | | | | |![alt text][preview] | [芯片发布公告](https://www.espressif.com/zh-hans/news/ESP32-C5) |
|
||||
|ESP32-C61 | | | | |![alt text][preview] | [芯片发布公告](https://www.espressif.com/zh-hans/products/socs/esp32-c61) |
|
||||
|
||||
|
||||
[supported]: https://img.shields.io/badge/-%E6%94%AF%E6%8C%81-green "supported"
|
||||
[preview]: https://img.shields.io/badge/-%E9%A2%84%E8%A7%88-orange "preview"
|
||||
|
||||
@@ -92,7 +92,7 @@ static esp_err_t esp_apptrace_membufs_swap(esp_apptrace_membufs_proto_data_t *pr
|
||||
// switch to new block
|
||||
proto->state.in_block++;
|
||||
|
||||
proto->hw->swap(new_block_num, proto->state.markers[prev_block_num]);
|
||||
proto->hw->swap(new_block_num);
|
||||
|
||||
// handle data from host
|
||||
esp_hostdata_hdr_t *hdr = (esp_hostdata_hdr_t *)proto->blocks[new_block_num].start;
|
||||
|
||||
@@ -50,7 +50,7 @@ static uint8_t *esp_apptrace_riscv_down_buffer_get(esp_apptrace_riscv_data_t *hw
|
||||
static esp_err_t esp_apptrace_riscv_down_buffer_put(esp_apptrace_riscv_data_t *hw_data, uint8_t *ptr, esp_apptrace_tmo_t *tmo);
|
||||
static bool esp_apptrace_riscv_host_is_connected(esp_apptrace_riscv_data_t *hw_data);
|
||||
static esp_err_t esp_apptrace_riscv_buffer_swap_start(uint32_t curr_block_id);
|
||||
static esp_err_t esp_apptrace_riscv_buffer_swap(uint32_t new_block_id, uint32_t prev_block_len);
|
||||
static esp_err_t esp_apptrace_riscv_buffer_swap(uint32_t new_block_id);
|
||||
static esp_err_t esp_apptrace_riscv_buffer_swap_end(uint32_t new_block_id, uint32_t prev_block_len);
|
||||
static bool esp_apptrace_riscv_host_data_pending(void);
|
||||
|
||||
@@ -353,7 +353,7 @@ static esp_err_t esp_apptrace_riscv_buffer_swap_end(uint32_t new_block_id, uint3
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t esp_apptrace_riscv_buffer_swap(uint32_t new_block_id, uint32_t prev_block_len)
|
||||
static esp_err_t esp_apptrace_riscv_buffer_swap(uint32_t new_block_id)
|
||||
{
|
||||
/* do nothing */
|
||||
return ESP_OK;
|
||||
|
||||
@@ -208,7 +208,7 @@ static uint8_t *esp_apptrace_trax_down_buffer_get(esp_apptrace_trax_data_t *hw_d
|
||||
static esp_err_t esp_apptrace_trax_down_buffer_put(esp_apptrace_trax_data_t *hw_data, uint8_t *ptr, esp_apptrace_tmo_t *tmo);
|
||||
static bool esp_apptrace_trax_host_is_connected(esp_apptrace_trax_data_t *hw_data);
|
||||
static esp_err_t esp_apptrace_trax_buffer_swap_start(uint32_t curr_block_id);
|
||||
static esp_err_t esp_apptrace_trax_buffer_swap(uint32_t new_block_id, uint32_t prev_block_len);
|
||||
static esp_err_t esp_apptrace_trax_buffer_swap(uint32_t new_block_id);
|
||||
static esp_err_t esp_apptrace_trax_buffer_swap_end(uint32_t new_block_id, uint32_t prev_block_len);
|
||||
static bool esp_apptrace_trax_host_data_pending(void);
|
||||
|
||||
@@ -526,21 +526,21 @@ static esp_err_t esp_apptrace_trax_buffer_swap_end(uint32_t new_block_id, uint32
|
||||
uint32_t ctrl_reg = eri_read(ESP_APPTRACE_TRAX_CTRL_REG);
|
||||
uint32_t host_connected = ESP_APPTRACE_TRAX_HOST_CONNECT & ctrl_reg;
|
||||
|
||||
eri_write(ESP_APPTRACE_TRAX_CTRL_REG, ESP_APPTRACE_TRAX_BLOCK_ID(new_block_id) |
|
||||
host_connected | ESP_APPTRACE_TRAX_BLOCK_LEN(prev_block_len));
|
||||
esp_apptrace_trax_buffer_swap_unlock();
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t esp_apptrace_trax_buffer_swap(uint32_t new_block_id, uint32_t prev_block_len)
|
||||
{
|
||||
/* Before switching to the new block, calculate CRC16 of the current block */
|
||||
/* calculate CRC16 of the already switched block */
|
||||
if (prev_block_len > 0) {
|
||||
const uint8_t *prev_block_start = s_trax_blocks[!((new_block_id % 2))];
|
||||
uint16_t crc16 = esp_rom_crc16_le(0, prev_block_start, prev_block_len);
|
||||
eri_write(ESP_APPTRACE_TRAX_CRC16_REG, crc16 | ESP_APPTRACE_CRC_INDICATOR);
|
||||
ESP_APPTRACE_LOGD("CRC16:%x %d @%x", crc16, prev_block_len, prev_block_start);
|
||||
}
|
||||
eri_write(ESP_APPTRACE_TRAX_CTRL_REG, ESP_APPTRACE_TRAX_BLOCK_ID(new_block_id) |
|
||||
host_connected | ESP_APPTRACE_TRAX_BLOCK_LEN(prev_block_len));
|
||||
esp_apptrace_trax_buffer_swap_unlock();
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t esp_apptrace_trax_buffer_swap(uint32_t new_block_id)
|
||||
{
|
||||
esp_apptrace_trax_select_memory_block(new_block_id);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ typedef struct {
|
||||
|
||||
typedef struct {
|
||||
esp_err_t (*swap_start)(uint32_t curr_block_id);
|
||||
esp_err_t (*swap)(uint32_t new_block_id, uint32_t prev_block_len);
|
||||
esp_err_t (*swap)(uint32_t new_block_id);
|
||||
esp_err_t (*swap_end)(uint32_t new_block_id, uint32_t prev_block_len);
|
||||
bool (*host_data_pending)(void);
|
||||
} esp_apptrace_membufs_proto_hw_t;
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
#include "esp_flash.h"
|
||||
#include "esp_flash_internal.h"
|
||||
|
||||
#define OTA_SLOT(i) (i & 0x0F)
|
||||
#define SUB_TYPE_ID(i) (i & 0x0F)
|
||||
#define ALIGN_UP(num, align) (((num) + ((align) - 1)) & ~((align) - 1))
|
||||
|
||||
/* Partial_data is word aligned so no reallocation is necessary for encrypted flash write */
|
||||
@@ -539,69 +539,6 @@ static esp_err_t rewrite_ota_seq(esp_ota_select_entry_t *two_otadata, uint32_t s
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Calculate the next OTA sequence number that will boot the given OTA slot.
|
||||
*
|
||||
* Based on the ESP-IDF OTA boot scheme, the system selects the OTA slot to boot by:
|
||||
* boot_slot = (seq - 1) % ota_app_count
|
||||
*
|
||||
* This function determines the required seq value that would cause the given ota_slot_idx
|
||||
* to be selected on next boot.
|
||||
*
|
||||
* @param current_seq Current active OTA sequence number
|
||||
* @param ota_slot_idx Target OTA slot index (0-based)
|
||||
* @param ota_app_count Total number of OTA slots
|
||||
*
|
||||
* @return New sequence number that will result in booting ota_slot_idx
|
||||
*/
|
||||
static uint32_t compute_ota_seq_for_target_slot(uint32_t current_seq, uint32_t ota_slot_idx, uint8_t ota_app_count)
|
||||
{
|
||||
if (ota_app_count == 0) {
|
||||
return 0;
|
||||
}
|
||||
/* ESP-IDF stores OTA boot information in the OTA data partition, which consists of two sectors.
|
||||
* Each sector holds an esp_ota_select_entry_t structure: otadata[0] and otadata[1].
|
||||
* These structures record the OTA sequence number (ota_seq) used to determine the current boot partition.
|
||||
*
|
||||
* Boot selection logic:
|
||||
* - If both otadata[0].ota_seq and otadata[1].ota_seq are 0xFFFFFFFF (invalid), it is the initial state:
|
||||
* → Boot the factory app, if it exists.
|
||||
* → Otherwise, fall back to booting ota[0].
|
||||
*
|
||||
* - If both otadata entries have valid sequence numbers and CRCs:
|
||||
* → Choose the higher sequence number (max_seq).
|
||||
* → Determine the OTA partition for boot (or running partition) using:
|
||||
* running_ota_slot = (max_seq - 1) % ota_app_count
|
||||
* where ota_app_count is the total number of OTA app partitions.
|
||||
*
|
||||
* Example:
|
||||
* otadata[0].ota_seq = 4
|
||||
* otadata[1].ota_seq = 5
|
||||
* ota_app_count = 8 (available OTA slots: ota_0 to ota_7)
|
||||
* → max_seq = 5
|
||||
* → running slot = (5 - 1) % 8 = 4
|
||||
* → So ota_4 is currently running
|
||||
*
|
||||
* If you want to switch to boot a different OTA slot (e.g., ota_7):
|
||||
* → You need to compute a new sequence number such that:
|
||||
* (new_seq - 1) % ota_app_count == 7
|
||||
* while ensuring new_seq > current_seq.
|
||||
*
|
||||
* General formula:
|
||||
* x = current OTA slot ID
|
||||
* ota_slot_idx = desired OTA slot ID
|
||||
* seq = current ota_seq
|
||||
*
|
||||
* To find the next ota_seq that will boot ota_y, use:
|
||||
* new_seq = ((ota_slot_idx + 1) % ota_app_count) + ota_app_count * i;
|
||||
* // where i is the smallest non-negative integer such that new_seq > seq
|
||||
*/
|
||||
uint32_t i = 0;
|
||||
uint32_t base = (ota_slot_idx + 1) % ota_app_count;
|
||||
while (current_seq > (base + i * ota_app_count)) { i++; };
|
||||
return base + i * ota_app_count;
|
||||
}
|
||||
|
||||
uint8_t esp_ota_get_app_partition_count(void)
|
||||
{
|
||||
uint16_t ota_app_count = 0;
|
||||
@@ -612,30 +549,6 @@ uint8_t esp_ota_get_app_partition_count(void)
|
||||
return ota_app_count;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Update the OTA data partition to set the given OTA app subtype as the next boot target.
|
||||
*
|
||||
* ESP-IDF uses the OTA data partition to track which OTA app should boot.
|
||||
* This partition contains two entries (otadata[0] and otadata[1]), each storing an esp_ota_select_entry_t struct,
|
||||
* which includes the OTA sequence number (ota_seq).
|
||||
*
|
||||
* On boot, the chip determines the current running OTA slot using:
|
||||
* current_slot = (max(ota_seq) - 1) % ota_app_count
|
||||
*
|
||||
* This function updates the OTA data to switch the next boot to the partition with the given subtype.
|
||||
*
|
||||
* Behavior:
|
||||
* - If the currently selected OTA slot already matches the requested subtype,
|
||||
* only the state field is updated (e.g., to mark the app as newly downloaded).
|
||||
* - Otherwise, it calculates the next valid ota_seq that will cause the bootloader to select
|
||||
* the requested OTA slot on reboot, and writes it to the inactive OTA data sector.
|
||||
*
|
||||
* @param subtype The OTA partition subtype (e.g., ESP_PARTITION_SUBTYPE_APP_OTA_0, ..._OTA_1, ...)
|
||||
* @return
|
||||
* - ESP_OK if update was successful
|
||||
* - ESP_ERR_NOT_FOUND if OTA data partition not found
|
||||
* - ESP_ERR_INVALID_ARG if subtype is out of range
|
||||
*/
|
||||
static esp_err_t esp_rewrite_ota_data(esp_partition_subtype_t subtype)
|
||||
{
|
||||
esp_ota_select_entry_t otadata[2];
|
||||
@@ -645,31 +558,42 @@ static esp_err_t esp_rewrite_ota_data(esp_partition_subtype_t subtype)
|
||||
}
|
||||
|
||||
uint8_t ota_app_count = esp_ota_get_app_partition_count();
|
||||
if (OTA_SLOT(subtype) >= ota_app_count) {
|
||||
if (SUB_TYPE_ID(subtype) >= ota_app_count) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
//esp32_idf use two sector for store information about which partition is running
|
||||
//it defined the two sector as ota data partition,two structure esp_ota_select_entry_t is saved in the two sector
|
||||
//named data in first sector as otadata[0], second sector data as otadata[1]
|
||||
//e.g.
|
||||
//if otadata[0].ota_seq == otadata[1].ota_seq == 0xFFFFFFFF,means ota info partition is in init status
|
||||
//so it will boot factory application(if there is),if there's no factory application,it will boot ota[0] application
|
||||
//if otadata[0].ota_seq != 0 and otadata[1].ota_seq != 0,it will choose a max seq ,and get value of max_seq%max_ota_app_number
|
||||
//and boot a subtype (mask 0x0F) value is (max_seq - 1)%max_ota_app_number,so if want switch to run ota[x],can use next formulas.
|
||||
//for example, if otadata[0].ota_seq = 4, otadata[1].ota_seq = 5, and there are 8 ota application,
|
||||
//current running is (5-1)%8 = 4,running ota[4],so if we want to switch to run ota[7],
|
||||
//we should add otadata[0].ota_seq (is 4) to 4 ,(8-1)%8=7,then it will boot ota[7]
|
||||
//if A=(B - C)%D
|
||||
//then B=(A + C)%D + D*n ,n= (0,1,2...)
|
||||
//so current ota app sub type id is x , dest bin subtype is y,total ota app count is n
|
||||
//seq will add (x + n*1 + 1 - seq)%n
|
||||
|
||||
int active_otadata = bootloader_common_get_active_otadata(otadata);
|
||||
int next_otadata;
|
||||
uint32_t new_seq;
|
||||
if (active_otadata != -1) {
|
||||
uint32_t ota_slot = (otadata[active_otadata].ota_seq - 1) % ota_app_count;
|
||||
if (ota_slot == OTA_SLOT(subtype)) {
|
||||
// ota_data is already valid and points to the correct OTA slot.
|
||||
// So after reboot the requested partition will be selected for boot.
|
||||
// Only update the ota_state of the requested partition.
|
||||
next_otadata = active_otadata;
|
||||
new_seq = otadata[active_otadata].ota_seq;
|
||||
} else {
|
||||
next_otadata = (~active_otadata) & 1; // if 0 -> will be next 1. and if 1 -> will be next 0.
|
||||
new_seq = compute_ota_seq_for_target_slot(otadata[active_otadata].ota_seq, OTA_SLOT(subtype), ota_app_count);
|
||||
uint32_t seq = otadata[active_otadata].ota_seq;
|
||||
uint32_t i = 0;
|
||||
while (seq > (SUB_TYPE_ID(subtype) + 1) % ota_app_count + i * ota_app_count) {
|
||||
i++;
|
||||
}
|
||||
int next_otadata = (~active_otadata)&1; // if 0 -> will be next 1. and if 1 -> will be next 0.
|
||||
otadata[next_otadata].ota_state = set_new_state_otadata();
|
||||
return rewrite_ota_seq(otadata, (SUB_TYPE_ID(subtype) + 1) % ota_app_count + i * ota_app_count, next_otadata, otadata_partition);
|
||||
} else {
|
||||
/* Both OTA slots are invalid, probably because unformatted... */
|
||||
next_otadata = 0;
|
||||
new_seq = OTA_SLOT(subtype) + 1;
|
||||
int next_otadata = 0;
|
||||
otadata[next_otadata].ota_state = set_new_state_otadata();
|
||||
return rewrite_ota_seq(otadata, SUB_TYPE_ID(subtype) + 1, next_otadata, otadata_partition);
|
||||
}
|
||||
otadata[next_otadata].ota_state = set_new_state_otadata();
|
||||
return rewrite_ota_seq(otadata, new_seq, next_otadata, otadata_partition);
|
||||
}
|
||||
|
||||
esp_err_t esp_ota_set_boot_partition(const esp_partition_t *partition)
|
||||
|
||||
@@ -7,7 +7,6 @@ components/app_update/test_apps:
|
||||
- if: CONFIG_NAME == "xip_psram" and SOC_SPIRAM_XIP_SUPPORTED == 1
|
||||
# S2 doesn't have ROM for flash
|
||||
- if: CONFIG_NAME == "xip_psram_with_rom_impl" and (SOC_SPIRAM_XIP_SUPPORTED == 1 and IDF_TARGET != "esp32s2")
|
||||
- if: CONFIG_NAME == "recovery_bootloader" and SOC_RECOVERY_BOOTLOADER_SUPPORTED == 1
|
||||
disable:
|
||||
- if: IDF_TARGET in ["esp32h21", "esp32h4"]
|
||||
temporary: true
|
||||
@@ -15,7 +14,3 @@ components/app_update/test_apps:
|
||||
- if: IDF_TARGET == "esp32c61" and CONFIG_NAME == "xip_psram_with_rom_impl"
|
||||
temporary: true
|
||||
reason: not supported yet # TODO: [ESP32C61] IDF-12784
|
||||
disable_test:
|
||||
- if: CONFIG_NAME == "recovery_bootloader" and SOC_RECOVERY_BOOTLOADER_SUPPORTED == 1 and IDF_TARGET == "esp32c61"
|
||||
temporary: true
|
||||
reason: lack of runners # TODO: [ESP32C61] IDF-13165
|
||||
|
||||
@@ -1,15 +1,4 @@
|
||||
idf_component_register(
|
||||
SRC_DIRS "."
|
||||
PRIV_INCLUDE_DIRS "."
|
||||
PRIV_REQUIRES
|
||||
cmock
|
||||
test_utils
|
||||
app_update
|
||||
bootloader_support
|
||||
nvs_flash
|
||||
driver
|
||||
spi_flash
|
||||
esp_psram
|
||||
efuse
|
||||
WHOLE_ARCHIVE
|
||||
)
|
||||
idf_component_register(SRC_DIRS "."
|
||||
PRIV_INCLUDE_DIRS "."
|
||||
PRIV_REQUIRES cmock test_utils app_update bootloader_support nvs_flash driver spi_flash esp_psram
|
||||
WHOLE_ARCHIVE)
|
||||
|
||||
@@ -1,87 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
/*
|
||||
* Tests bootloader update.
|
||||
*/
|
||||
|
||||
#include "unity.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_efuse.h"
|
||||
#include "esp_flash_internal.h"
|
||||
#include "esp_rom_sys.h"
|
||||
#include "utils_update.h"
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#define BOOT_COUNT_NAMESPACE "boot_count"
|
||||
|
||||
static __attribute__((unused)) const char *TAG = "btldr_update";
|
||||
|
||||
#if CONFIG_BOOTLOADER_RECOVERY_ENABLE
|
||||
|
||||
/* @brief Checks and prepares the partition so that the factory app is launched after that.
|
||||
*/
|
||||
static void start_test(void)
|
||||
{
|
||||
ESP_LOGI(TAG, "boot count 1 - reset");
|
||||
set_boot_count_in_nvs(1);
|
||||
erase_ota_data();
|
||||
ESP_LOGI(TAG, "ota_data erased");
|
||||
ESP_LOGI(TAG, "Bootloader offset: 0x%x", esp_rom_get_bootloader_offset());
|
||||
reboot_as_deep_sleep();
|
||||
}
|
||||
|
||||
static void test_flow1(void)
|
||||
{
|
||||
uint8_t boot_count = get_boot_count_from_nvs();
|
||||
boot_count++;
|
||||
set_boot_count_in_nvs(boot_count);
|
||||
ESP_LOGI(TAG, "boot count %d", boot_count);
|
||||
|
||||
ESP_LOGI(TAG, "Bootloader offset: 0x%x", esp_rom_get_bootloader_offset());
|
||||
|
||||
const esp_partition_t *primary_bootloader;
|
||||
TEST_ESP_OK(esp_partition_register_external(NULL, ESP_PRIMARY_BOOTLOADER_OFFSET, ESP_BOOTLOADER_SIZE, "PrimaryBTLDR", ESP_PARTITION_TYPE_BOOTLOADER, ESP_PARTITION_SUBTYPE_BOOTLOADER_PRIMARY, &primary_bootloader));
|
||||
const esp_partition_t *recovery_bootloader;
|
||||
TEST_ESP_OK(esp_partition_register_external(NULL, CONFIG_BOOTLOADER_RECOVERY_OFFSET, ESP_BOOTLOADER_SIZE, "RecoveryBTLDR", ESP_PARTITION_TYPE_BOOTLOADER, ESP_PARTITION_SUBTYPE_BOOTLOADER_RECOVERY, &recovery_bootloader));
|
||||
ESP_LOGI(TAG, "Bootloaders are registered");
|
||||
|
||||
// Remove write protection for the bootloader
|
||||
esp_flash_set_dangerous_write_protection(esp_flash_default_chip, false);
|
||||
switch (boot_count) {
|
||||
case 2:
|
||||
TEST_ASSERT_EQUAL_HEX32(ESP_PRIMARY_BOOTLOADER_OFFSET, esp_rom_get_bootloader_offset());
|
||||
|
||||
TEST_ESP_OK(esp_partition_erase_range(recovery_bootloader, 0, recovery_bootloader->size));
|
||||
ESP_LOGI(TAG, "Erase recovery bootloader");
|
||||
|
||||
TEST_ESP_OK(esp_efuse_set_recovery_bootloader_offset(CONFIG_BOOTLOADER_RECOVERY_OFFSET));
|
||||
|
||||
ESP_LOGI(TAG, "Backup, copy <%s> -> <%s>", primary_bootloader->label, recovery_bootloader->label);
|
||||
TEST_ESP_OK(esp_partition_copy(recovery_bootloader, 0, primary_bootloader, 0, primary_bootloader->size));
|
||||
|
||||
TEST_ESP_OK(esp_partition_erase_range(primary_bootloader, 0, primary_bootloader->size));
|
||||
ESP_LOGI(TAG, "Erase primary bootloader");
|
||||
reboot_as_deep_sleep();
|
||||
break;
|
||||
case 3:
|
||||
TEST_ASSERT_EQUAL_HEX32(CONFIG_BOOTLOADER_RECOVERY_OFFSET, esp_rom_get_bootloader_offset());
|
||||
|
||||
ESP_LOGI(TAG, "Return to primary bootloader...");
|
||||
ESP_LOGI(TAG, "Copy <%s> -> <%s>", recovery_bootloader->label, primary_bootloader->label);
|
||||
TEST_ESP_OK(esp_partition_copy(primary_bootloader, 0, recovery_bootloader, 0, primary_bootloader->size));
|
||||
|
||||
TEST_ESP_OK(esp_partition_erase_range(recovery_bootloader, 0, recovery_bootloader->size));
|
||||
ESP_LOGI(TAG, "Erase recovery bootloader");
|
||||
break;
|
||||
default:
|
||||
TEST_FAIL_MESSAGE("Unexpected stage");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE_MULTIPLE_STAGES("Recovery bootloader feature", "[recovery_bootloader][timeout=90][reset=DEEPSLEEP_RESET, DEEPSLEEP_RESET]", start_test, test_flow1, test_flow1);
|
||||
|
||||
#endif // CONFIG_BOOTLOADER_RECOVERY_ENABLE
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -7,16 +7,314 @@
|
||||
* Tests for switching between partitions: factory, OTAx, test.
|
||||
*/
|
||||
|
||||
#include "esp_system.h"
|
||||
#include <esp_types.h>
|
||||
#include <stdio.h>
|
||||
#include "string.h"
|
||||
#include <inttypes.h>
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#include "esp_rom_spiflash.h"
|
||||
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/semphr.h"
|
||||
#include "freertos/queue.h"
|
||||
#include "unity.h"
|
||||
|
||||
#include "bootloader_common.h"
|
||||
#include "../bootloader_flash/include/bootloader_flash_priv.h"
|
||||
|
||||
#include "esp_err.h"
|
||||
#include "esp_log.h"
|
||||
#include "unity.h"
|
||||
#include "utils_update.h"
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_ota_ops.h"
|
||||
#include "esp_partition.h"
|
||||
#include "esp_flash_partitions.h"
|
||||
#include "esp_image_format.h"
|
||||
#include "nvs_flash.h"
|
||||
|
||||
#include "driver/gpio.h"
|
||||
#include "esp_sleep.h"
|
||||
#include "test_utils.h"
|
||||
|
||||
#define BOOT_COUNT_NAMESPACE "boot_count"
|
||||
|
||||
static const char *TAG = "ota_test";
|
||||
|
||||
static void set_boot_count_in_nvs(uint8_t boot_count)
|
||||
{
|
||||
nvs_handle_t boot_count_handle;
|
||||
esp_err_t err = nvs_open(BOOT_COUNT_NAMESPACE, NVS_READWRITE, &boot_count_handle);
|
||||
if (err != ESP_OK) {
|
||||
TEST_ESP_OK(nvs_flash_erase());
|
||||
TEST_ESP_OK(nvs_flash_init());
|
||||
TEST_ESP_OK(nvs_open(BOOT_COUNT_NAMESPACE, NVS_READWRITE, &boot_count_handle));
|
||||
}
|
||||
TEST_ESP_OK(nvs_set_u8(boot_count_handle, "boot_count", boot_count));
|
||||
TEST_ESP_OK(nvs_commit(boot_count_handle));
|
||||
nvs_close(boot_count_handle);
|
||||
}
|
||||
|
||||
static uint8_t get_boot_count_from_nvs(void)
|
||||
{
|
||||
nvs_handle_t boot_count_handle;
|
||||
esp_err_t err = nvs_open(BOOT_COUNT_NAMESPACE, NVS_READONLY, &boot_count_handle);
|
||||
if (err == ESP_ERR_NVS_NOT_FOUND) {
|
||||
set_boot_count_in_nvs(0);
|
||||
}
|
||||
uint8_t boot_count;
|
||||
TEST_ESP_OK(nvs_get_u8(boot_count_handle, "boot_count", &boot_count));
|
||||
nvs_close(boot_count_handle);
|
||||
return boot_count;
|
||||
}
|
||||
|
||||
/* @brief Copies a current app to next partition using handle.
|
||||
*
|
||||
* @param[in] update_handle - Handle of API ota.
|
||||
* @param[in] cur_app - Current app.
|
||||
*/
|
||||
static void copy_app_partition(esp_ota_handle_t update_handle, const esp_partition_t *curr_app)
|
||||
{
|
||||
const void *partition_bin = NULL;
|
||||
esp_partition_mmap_handle_t data_map;
|
||||
ESP_LOGI(TAG, "start the copy process");
|
||||
TEST_ESP_OK(esp_partition_mmap(curr_app, 0, curr_app->size, ESP_PARTITION_MMAP_DATA, &partition_bin, &data_map));
|
||||
TEST_ESP_OK(esp_ota_write(update_handle, (const void *)partition_bin, curr_app->size));
|
||||
esp_partition_munmap(data_map);
|
||||
ESP_LOGI(TAG, "finish the copy process");
|
||||
}
|
||||
|
||||
/* @brief Copies a current app to next partition using handle.
|
||||
*
|
||||
* @param[in] update_handle - Handle of API ota.
|
||||
* @param[in] cur_app - Current app.
|
||||
*/
|
||||
static void copy_app_partition_with_offset(esp_ota_handle_t update_handle, const esp_partition_t *curr_app)
|
||||
{
|
||||
const void *partition_bin = NULL;
|
||||
esp_partition_mmap_handle_t data_map;
|
||||
ESP_LOGI(TAG, "start the copy process");
|
||||
uint32_t offset = 0, bytes_to_write = curr_app->size;
|
||||
uint32_t write_bytes;
|
||||
while (bytes_to_write > 0) {
|
||||
write_bytes = (bytes_to_write > (4 * 1024)) ? (4 * 1024) : bytes_to_write;
|
||||
TEST_ESP_OK(esp_partition_mmap(curr_app, offset, write_bytes, ESP_PARTITION_MMAP_DATA, &partition_bin, &data_map));
|
||||
TEST_ESP_OK(esp_ota_write_with_offset(update_handle, (const void *)partition_bin, write_bytes, offset));
|
||||
esp_partition_munmap(data_map);
|
||||
bytes_to_write -= write_bytes;
|
||||
offset += write_bytes;
|
||||
}
|
||||
ESP_LOGI(TAG, "finish the copy process");
|
||||
}
|
||||
|
||||
/* @brief Get the next partition of OTA for the update.
|
||||
*
|
||||
* @return The next partition of OTA(OTA0-15).
|
||||
*/
|
||||
static const esp_partition_t * get_next_update_partition(void)
|
||||
{
|
||||
const esp_partition_t *update_partition = esp_ota_get_next_update_partition(NULL);
|
||||
TEST_ASSERT_NOT_EQUAL(NULL, update_partition);
|
||||
ESP_LOGI(TAG, "Writing to partition subtype %d at offset 0x%"PRIx32, update_partition->subtype, update_partition->address);
|
||||
return update_partition;
|
||||
}
|
||||
|
||||
/* @brief Copies a current app to next partition (OTA0-15) and then configure OTA data for a new boot partition.
|
||||
*
|
||||
* @param[in] cur_app_partition - Current app.
|
||||
* @param[in] next_app_partition - Next app for boot.
|
||||
*/
|
||||
static void copy_current_app_to_next_part(const esp_partition_t *cur_app_partition, const esp_partition_t *next_app_partition)
|
||||
{
|
||||
esp_ota_get_next_update_partition(NULL);
|
||||
TEST_ASSERT_NOT_EQUAL(NULL, next_app_partition);
|
||||
ESP_LOGI(TAG, "Writing to partition subtype %d at offset 0x%"PRIx32, next_app_partition->subtype, next_app_partition->address);
|
||||
|
||||
esp_ota_handle_t update_handle = 0;
|
||||
TEST_ESP_OK(esp_ota_begin(next_app_partition, OTA_SIZE_UNKNOWN, &update_handle));
|
||||
|
||||
copy_app_partition(update_handle, cur_app_partition);
|
||||
|
||||
TEST_ESP_OK(esp_ota_end(update_handle));
|
||||
TEST_ESP_OK(esp_ota_set_boot_partition(next_app_partition));
|
||||
}
|
||||
|
||||
/* @brief Copies a current app to next partition (OTA0-15) and then configure OTA data for a new boot partition.
|
||||
*
|
||||
* @param[in] cur_app_partition - Current app.
|
||||
* @param[in] next_app_partition - Next app for boot.
|
||||
*/
|
||||
static void copy_current_app_to_next_part_with_offset(const esp_partition_t *cur_app_partition, const esp_partition_t *next_app_partition)
|
||||
{
|
||||
esp_ota_get_next_update_partition(NULL);
|
||||
TEST_ASSERT_NOT_EQUAL(NULL, next_app_partition);
|
||||
ESP_LOGI(TAG, "Writing to partition subtype %d at offset 0x%"PRIx32, next_app_partition->subtype, next_app_partition->address);
|
||||
|
||||
esp_ota_handle_t update_handle = 0;
|
||||
TEST_ESP_OK(esp_ota_begin(next_app_partition, OTA_SIZE_UNKNOWN, &update_handle));
|
||||
|
||||
copy_app_partition_with_offset(update_handle, cur_app_partition);
|
||||
|
||||
TEST_ESP_OK(esp_ota_end(update_handle));
|
||||
TEST_ESP_OK(esp_ota_set_boot_partition(next_app_partition));
|
||||
}
|
||||
|
||||
/* @brief Erase otadata partition
|
||||
*/
|
||||
static void erase_ota_data(void)
|
||||
{
|
||||
const esp_partition_t *data_partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_OTA, NULL);
|
||||
TEST_ASSERT_NOT_EQUAL(NULL, data_partition);
|
||||
TEST_ESP_OK(esp_partition_erase_range(data_partition, 0, 2 * data_partition->erase_size));
|
||||
}
|
||||
|
||||
/* @brief Reboots ESP using mode deep sleep. This mode guaranty that RTC_DATA_ATTR variables is not reset.
|
||||
*/
|
||||
static void reboot_as_deep_sleep(void)
|
||||
{
|
||||
ESP_LOGI(TAG, "reboot as deep sleep");
|
||||
esp_deep_sleep(20000);
|
||||
TEST_FAIL_MESSAGE("Should never be reachable except when sleep is rejected, abort");
|
||||
}
|
||||
|
||||
/* @brief Copies a current app to next partition (OTA0-15), after that ESP is rebooting and run this (the next) OTAx.
|
||||
*/
|
||||
static void copy_current_app_to_next_part_and_reboot(void)
|
||||
{
|
||||
const esp_partition_t *cur_app = esp_ota_get_running_partition();
|
||||
ESP_LOGI(TAG, "copy current app to next part");
|
||||
copy_current_app_to_next_part(cur_app, get_next_update_partition());
|
||||
reboot_as_deep_sleep();
|
||||
}
|
||||
|
||||
/* @brief Copies a current app to next partition (OTA0-15) using esp_ota_write_with_offest(), after that ESP is rebooting and run this (the next) OTAx.
|
||||
*/
|
||||
static void copy_current_app_to_next_part_with_offset_and_reboot(void)
|
||||
{
|
||||
const esp_partition_t *cur_app = esp_ota_get_running_partition();
|
||||
ESP_LOGI(TAG, "copy current app to next part");
|
||||
copy_current_app_to_next_part_with_offset(cur_app, get_next_update_partition());
|
||||
reboot_as_deep_sleep();
|
||||
}
|
||||
|
||||
/* @brief Get running app.
|
||||
*
|
||||
* @return The next partition of OTA(OTA0-15).
|
||||
*/
|
||||
static const esp_partition_t* get_running_firmware(void)
|
||||
{
|
||||
const esp_partition_t *configured = esp_ota_get_boot_partition();
|
||||
const esp_partition_t *running = esp_ota_get_running_partition();
|
||||
ESP_LOGI(TAG, "Running partition type %d subtype %d (offset 0x%08"PRIx32")",
|
||||
running->type, running->subtype, running->address);
|
||||
ESP_LOGI(TAG, "Configured partition type %d subtype %d (offset 0x%08"PRIx32")",
|
||||
configured->type, configured->subtype, configured->address);
|
||||
TEST_ASSERT_NOT_EQUAL(NULL, configured);
|
||||
TEST_ASSERT_NOT_EQUAL(NULL, running);
|
||||
if (running->subtype != ESP_PARTITION_SUBTYPE_APP_TEST) {
|
||||
TEST_ASSERT_EQUAL_PTR(running, configured);
|
||||
}
|
||||
return running;
|
||||
}
|
||||
|
||||
// type of a corrupt ota_data
|
||||
typedef enum {
|
||||
CORR_CRC_1_SECTOR_OTA_DATA = (1 << 0), /*!< Corrupt CRC only 1 sector of ota_data */
|
||||
CORR_CRC_2_SECTOR_OTA_DATA = (1 << 1), /*!< Corrupt CRC only 2 sector of ota_data */
|
||||
} corrupt_ota_data_t;
|
||||
|
||||
/* @brief Get two copies ota_data from otadata partition.
|
||||
*
|
||||
* @param[in] otadata_partition - otadata partition.
|
||||
* @param[out] ota_data_0 - First copy from otadata_partition.
|
||||
* @param[out] ota_data_1 - Second copy from otadata_partition.
|
||||
*/
|
||||
static void get_ota_data(const esp_partition_t *otadata_partition, esp_ota_select_entry_t *ota_data_0, esp_ota_select_entry_t *ota_data_1)
|
||||
{
|
||||
uint32_t offset = otadata_partition->address;
|
||||
uint32_t size = otadata_partition->size;
|
||||
if (offset != 0) {
|
||||
const esp_ota_select_entry_t *ota_select_map;
|
||||
ota_select_map = bootloader_mmap(offset, size);
|
||||
TEST_ASSERT_NOT_EQUAL(NULL, ota_select_map);
|
||||
|
||||
memcpy(ota_data_0, ota_select_map, sizeof(esp_ota_select_entry_t));
|
||||
memcpy(ota_data_1, (uint8_t *)ota_select_map + otadata_partition->erase_size, sizeof(esp_ota_select_entry_t));
|
||||
bootloader_munmap(ota_select_map);
|
||||
}
|
||||
}
|
||||
|
||||
/* @brief Writes a ota_data into required sector of otadata_partition.
|
||||
*
|
||||
* @param[in] otadata_partition - Partition information otadata.
|
||||
* @param[in] ota_data - otadata structure.
|
||||
* @param[in] sec_id - Sector number 0 or 1.
|
||||
*/
|
||||
static void write_ota_data(const esp_partition_t *otadata_partition, esp_ota_select_entry_t *ota_data, int sec_id)
|
||||
{
|
||||
esp_partition_write(otadata_partition, otadata_partition->erase_size * sec_id, &ota_data[sec_id], sizeof(esp_ota_select_entry_t));
|
||||
}
|
||||
|
||||
/* @brief Makes a corrupt of ota_data.
|
||||
* @param[in] err - type error
|
||||
*/
|
||||
static void corrupt_ota_data(corrupt_ota_data_t err)
|
||||
{
|
||||
esp_ota_select_entry_t ota_data[2];
|
||||
|
||||
const esp_partition_t *otadata_partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_OTA, NULL);
|
||||
TEST_ASSERT_NOT_EQUAL(NULL, otadata_partition);
|
||||
get_ota_data(otadata_partition, &ota_data[0], &ota_data[1]);
|
||||
|
||||
if (err & CORR_CRC_1_SECTOR_OTA_DATA) {
|
||||
ota_data[0].crc = 0;
|
||||
}
|
||||
if (err & CORR_CRC_2_SECTOR_OTA_DATA) {
|
||||
ota_data[1].crc = 0;
|
||||
}
|
||||
TEST_ESP_OK(esp_partition_erase_range(otadata_partition, 0, otadata_partition->size));
|
||||
write_ota_data(otadata_partition, &ota_data[0], 0);
|
||||
write_ota_data(otadata_partition, &ota_data[1], 1);
|
||||
}
|
||||
|
||||
#if defined(CONFIG_BOOTLOADER_FACTORY_RESET) || defined(CONFIG_BOOTLOADER_APP_TEST)
|
||||
/* @brief Sets the pin number to output and sets output level as low. After reboot (deep sleep) this pin keep the same level.
|
||||
*
|
||||
* The output level of the pad will be force locked and can not be changed.
|
||||
* Power down or call gpio_hold_dis will disable this function.
|
||||
*
|
||||
* @param[in] num_pin - Pin number
|
||||
*/
|
||||
static void set_output_pin(uint32_t num_pin)
|
||||
{
|
||||
TEST_ESP_OK(gpio_hold_dis(num_pin));
|
||||
|
||||
gpio_config_t io_conf;
|
||||
io_conf.intr_type = GPIO_INTR_DISABLE;
|
||||
io_conf.mode = GPIO_MODE_OUTPUT;
|
||||
io_conf.pin_bit_mask = (1ULL << num_pin);
|
||||
io_conf.pull_down_en = 0;
|
||||
io_conf.pull_up_en = 0;
|
||||
TEST_ESP_OK(gpio_config(&io_conf));
|
||||
|
||||
TEST_ESP_OK(gpio_set_level(num_pin, 0));
|
||||
TEST_ESP_OK(gpio_hold_en(num_pin));
|
||||
}
|
||||
|
||||
/* @brief Unset the pin number hold function.
|
||||
*/
|
||||
static void reset_output_pin(uint32_t num_pin)
|
||||
{
|
||||
TEST_ESP_OK(gpio_hold_dis(num_pin));
|
||||
TEST_ESP_OK(gpio_reset_pin(num_pin));
|
||||
}
|
||||
#endif
|
||||
|
||||
static void mark_app_valid(void)
|
||||
{
|
||||
#ifdef CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE
|
||||
TEST_ESP_OK(esp_ota_mark_app_valid_cancel_rollback());
|
||||
#endif
|
||||
}
|
||||
|
||||
/* @brief Checks and prepares the partition so that the factory app is launched after that.
|
||||
*/
|
||||
@@ -248,6 +546,20 @@ static void test_flow5(void)
|
||||
TEST_CASE_MULTIPLE_STAGES("Switching between factory, test, factory", "[app_update][timeout=90][reset=SW_CPU_RESET, SW_CPU_RESET, DEEPSLEEP_RESET]", start_test, test_flow5, test_flow5, test_flow5);
|
||||
#endif
|
||||
|
||||
static const esp_partition_t* app_update(void)
|
||||
{
|
||||
const esp_partition_t *cur_app = get_running_firmware();
|
||||
const esp_partition_t* update_partition = esp_ota_get_next_update_partition(NULL);
|
||||
TEST_ASSERT_NOT_NULL(update_partition);
|
||||
esp_ota_handle_t update_handle = 0;
|
||||
TEST_ESP_OK(esp_ota_begin(update_partition, OTA_SIZE_UNKNOWN, &update_handle));
|
||||
copy_app_partition(update_handle, cur_app);
|
||||
TEST_ESP_OK(esp_ota_end(update_handle));
|
||||
TEST_ESP_OK(esp_ota_set_boot_partition(update_partition));
|
||||
return update_partition;
|
||||
}
|
||||
|
||||
|
||||
static void test_rollback1(void)
|
||||
{
|
||||
uint8_t boot_count = get_boot_count_from_nvs();
|
||||
@@ -618,51 +930,3 @@ static void test_rollback3_1(void)
|
||||
}
|
||||
|
||||
TEST_CASE_MULTIPLE_STAGES("Test rollback. Updated partition invalidated after esp_ota_begin", "[app_update][timeout=90][reset=DEEPSLEEP_RESET, DEEPSLEEP_RESET, DEEPSLEEP_RESET, SW_CPU_RESET]", start_test, test_rollback3, test_rollback3, test_rollback3, test_rollback3_1);
|
||||
|
||||
static void test_rollback4(void)
|
||||
{
|
||||
uint8_t boot_count = get_boot_count_from_nvs();
|
||||
boot_count++;
|
||||
set_boot_count_in_nvs(boot_count);
|
||||
ESP_LOGI(TAG, "boot count %d", boot_count);
|
||||
const esp_partition_t *cur_app = get_running_firmware();
|
||||
switch (boot_count) {
|
||||
case 2:
|
||||
ESP_LOGI(TAG, "Factory");
|
||||
TEST_ASSERT_EQUAL(ESP_PARTITION_SUBTYPE_APP_FACTORY, cur_app->subtype);
|
||||
app_update();
|
||||
reboot_as_deep_sleep();
|
||||
break;
|
||||
case 3:
|
||||
ESP_LOGI(TAG, "OTA0");
|
||||
TEST_ASSERT_EQUAL(ESP_PARTITION_SUBTYPE_APP_OTA_0, cur_app->subtype);
|
||||
TEST_ESP_OK(esp_ota_mark_app_valid_cancel_rollback());
|
||||
app_update();
|
||||
|
||||
// Do not reboot and call app_update again.
|
||||
// This will not change the running partition since we haven't rebooted.
|
||||
// The esp_rewrite_otadata() will update the otadata for the non-running partition only.
|
||||
app_update();
|
||||
#ifdef CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE
|
||||
// The last call to esp_rewrite_otadata should have updated the otadata for the non-running partition only.
|
||||
// Therefore, calling esp_ota_get_state_partition on the running partition should succeed and not return ESP_ERR_NOT_FOUND
|
||||
const esp_partition_t* running_partition;
|
||||
running_partition = esp_ota_get_running_partition();
|
||||
esp_ota_img_states_t ota_state;
|
||||
TEST_ESP_OK(esp_ota_get_state_partition(running_partition, &ota_state));
|
||||
#endif
|
||||
reboot_as_deep_sleep();
|
||||
break;
|
||||
case 4:
|
||||
ESP_LOGI(TAG, "OTA1");
|
||||
TEST_ASSERT_EQUAL(ESP_PARTITION_SUBTYPE_APP_OTA_1, cur_app->subtype);
|
||||
TEST_ESP_OK(esp_ota_mark_app_valid_cancel_rollback());
|
||||
break;
|
||||
default:
|
||||
erase_ota_data();
|
||||
TEST_FAIL_MESSAGE("Unexpected stage");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE_MULTIPLE_STAGES("Test esp_rewrite_otadata. Updated sequence number for non-running partition always", "[app_update][timeout=90][reset=DEEPSLEEP_RESET, DEEPSLEEP_RESET, DEEPSLEEP_RESET, SW_CPU_RESET]", start_test, test_rollback4, test_rollback4, test_rollback4);
|
||||
|
||||
@@ -1,307 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "esp_rom_spiflash.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "nvs_flash.h"
|
||||
#include "esp_partition.h"
|
||||
#include "esp_flash_partitions.h"
|
||||
#include "esp_image_format.h"
|
||||
#include "../bootloader_flash/include/bootloader_flash_priv.h"
|
||||
#include "esp_sleep.h"
|
||||
#include "esp_ota_ops.h"
|
||||
#include "esp_err.h"
|
||||
#include "esp_log.h"
|
||||
#include "test_utils.h"
|
||||
#include "utils_update.h"
|
||||
#include "unity.h"
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#define BOOT_COUNT_NAMESPACE "boot_count"
|
||||
|
||||
static const char *TAG = "ota_test";
|
||||
|
||||
|
||||
void set_boot_count_in_nvs(uint8_t boot_count)
|
||||
{
|
||||
nvs_handle_t boot_count_handle;
|
||||
esp_err_t err = nvs_open(BOOT_COUNT_NAMESPACE, NVS_READWRITE, &boot_count_handle);
|
||||
if (err != ESP_OK) {
|
||||
TEST_ESP_OK(nvs_flash_erase());
|
||||
TEST_ESP_OK(nvs_flash_init());
|
||||
TEST_ESP_OK(nvs_open(BOOT_COUNT_NAMESPACE, NVS_READWRITE, &boot_count_handle));
|
||||
}
|
||||
TEST_ESP_OK(nvs_set_u8(boot_count_handle, "boot_count", boot_count));
|
||||
TEST_ESP_OK(nvs_commit(boot_count_handle));
|
||||
nvs_close(boot_count_handle);
|
||||
}
|
||||
|
||||
uint8_t get_boot_count_from_nvs(void)
|
||||
{
|
||||
nvs_handle_t boot_count_handle;
|
||||
esp_err_t err = nvs_open(BOOT_COUNT_NAMESPACE, NVS_READONLY, &boot_count_handle);
|
||||
if (err == ESP_ERR_NVS_NOT_FOUND) {
|
||||
set_boot_count_in_nvs(0);
|
||||
}
|
||||
uint8_t boot_count;
|
||||
TEST_ESP_OK(nvs_get_u8(boot_count_handle, "boot_count", &boot_count));
|
||||
nvs_close(boot_count_handle);
|
||||
return boot_count;
|
||||
}
|
||||
|
||||
/* @brief Copies a current app to next partition using handle.
|
||||
*
|
||||
* @param[in] update_handle - Handle of API ota.
|
||||
* @param[in] cur_app - Current app.
|
||||
*/
|
||||
void copy_app_partition(esp_ota_handle_t update_handle, const esp_partition_t *curr_app)
|
||||
{
|
||||
const void *partition_bin = NULL;
|
||||
esp_partition_mmap_handle_t data_map;
|
||||
ESP_LOGI(TAG, "start the copy process");
|
||||
TEST_ESP_OK(esp_partition_mmap(curr_app, 0, curr_app->size, ESP_PARTITION_MMAP_DATA, &partition_bin, &data_map));
|
||||
TEST_ESP_OK(esp_ota_write(update_handle, (const void *)partition_bin, curr_app->size));
|
||||
esp_partition_munmap(data_map);
|
||||
ESP_LOGI(TAG, "finish the copy process");
|
||||
}
|
||||
|
||||
/* @brief Copies a current app to next partition using handle.
|
||||
*
|
||||
* @param[in] update_handle - Handle of API ota.
|
||||
* @param[in] cur_app - Current app.
|
||||
*/
|
||||
void copy_app_partition_with_offset(esp_ota_handle_t update_handle, const esp_partition_t *curr_app)
|
||||
{
|
||||
const void *partition_bin = NULL;
|
||||
esp_partition_mmap_handle_t data_map;
|
||||
ESP_LOGI(TAG, "start the copy process");
|
||||
uint32_t offset = 0, bytes_to_write = curr_app->size;
|
||||
uint32_t write_bytes;
|
||||
while (bytes_to_write > 0) {
|
||||
write_bytes = (bytes_to_write > (4 * 1024)) ? (4 * 1024) : bytes_to_write;
|
||||
TEST_ESP_OK(esp_partition_mmap(curr_app, offset, write_bytes, ESP_PARTITION_MMAP_DATA, &partition_bin, &data_map));
|
||||
TEST_ESP_OK(esp_ota_write_with_offset(update_handle, (const void *)partition_bin, write_bytes, offset));
|
||||
esp_partition_munmap(data_map);
|
||||
bytes_to_write -= write_bytes;
|
||||
offset += write_bytes;
|
||||
}
|
||||
ESP_LOGI(TAG, "finish the copy process");
|
||||
}
|
||||
|
||||
/* @brief Get the next partition of OTA for the update.
|
||||
*
|
||||
* @return The next partition of OTA(OTA0-15).
|
||||
*/
|
||||
const esp_partition_t * get_next_update_partition(void)
|
||||
{
|
||||
const esp_partition_t *update_partition = esp_ota_get_next_update_partition(NULL);
|
||||
TEST_ASSERT_NOT_EQUAL(NULL, update_partition);
|
||||
ESP_LOGI(TAG, "Writing to partition subtype %d at offset 0x%"PRIx32, update_partition->subtype, update_partition->address);
|
||||
return update_partition;
|
||||
}
|
||||
|
||||
/* @brief Copies a current app to next partition (OTA0-15) and then configure OTA data for a new boot partition.
|
||||
*
|
||||
* @param[in] cur_app_partition - Current app.
|
||||
* @param[in] next_app_partition - Next app for boot.
|
||||
*/
|
||||
void copy_current_app_to_next_part(const esp_partition_t *cur_app_partition, const esp_partition_t *next_app_partition)
|
||||
{
|
||||
esp_ota_get_next_update_partition(NULL);
|
||||
TEST_ASSERT_NOT_EQUAL(NULL, next_app_partition);
|
||||
ESP_LOGI(TAG, "Writing to partition subtype %d at offset 0x%"PRIx32, next_app_partition->subtype, next_app_partition->address);
|
||||
|
||||
esp_ota_handle_t update_handle = 0;
|
||||
TEST_ESP_OK(esp_ota_begin(next_app_partition, OTA_SIZE_UNKNOWN, &update_handle));
|
||||
|
||||
copy_app_partition(update_handle, cur_app_partition);
|
||||
|
||||
TEST_ESP_OK(esp_ota_end(update_handle));
|
||||
TEST_ESP_OK(esp_ota_set_boot_partition(next_app_partition));
|
||||
}
|
||||
|
||||
/* @brief Copies a current app to next partition (OTA0-15) and then configure OTA data for a new boot partition.
|
||||
*
|
||||
* @param[in] cur_app_partition - Current app.
|
||||
* @param[in] next_app_partition - Next app for boot.
|
||||
*/
|
||||
void copy_current_app_to_next_part_with_offset(const esp_partition_t *cur_app_partition, const esp_partition_t *next_app_partition)
|
||||
{
|
||||
esp_ota_get_next_update_partition(NULL);
|
||||
TEST_ASSERT_NOT_EQUAL(NULL, next_app_partition);
|
||||
ESP_LOGI(TAG, "Writing to partition subtype %d at offset 0x%"PRIx32, next_app_partition->subtype, next_app_partition->address);
|
||||
|
||||
esp_ota_handle_t update_handle = 0;
|
||||
TEST_ESP_OK(esp_ota_begin(next_app_partition, OTA_SIZE_UNKNOWN, &update_handle));
|
||||
|
||||
copy_app_partition_with_offset(update_handle, cur_app_partition);
|
||||
|
||||
TEST_ESP_OK(esp_ota_end(update_handle));
|
||||
TEST_ESP_OK(esp_ota_set_boot_partition(next_app_partition));
|
||||
}
|
||||
|
||||
/* @brief Erase otadata partition
|
||||
*/
|
||||
void erase_ota_data(void)
|
||||
{
|
||||
const esp_partition_t *data_partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_OTA, NULL);
|
||||
TEST_ASSERT_NOT_EQUAL(NULL, data_partition);
|
||||
TEST_ESP_OK(esp_partition_erase_range(data_partition, 0, 2 * data_partition->erase_size));
|
||||
}
|
||||
|
||||
/* @brief Reboots ESP using mode deep sleep. This mode guaranty that RTC_DATA_ATTR variables is not reset.
|
||||
*/
|
||||
void reboot_as_deep_sleep(void)
|
||||
{
|
||||
ESP_LOGI(TAG, "reboot as deep sleep");
|
||||
esp_deep_sleep(20000);
|
||||
TEST_FAIL_MESSAGE("Should never be reachable except when sleep is rejected, abort");
|
||||
}
|
||||
|
||||
/* @brief Copies a current app to next partition (OTA0-15), after that ESP is rebooting and run this (the next) OTAx.
|
||||
*/
|
||||
void copy_current_app_to_next_part_and_reboot(void)
|
||||
{
|
||||
const esp_partition_t *cur_app = esp_ota_get_running_partition();
|
||||
ESP_LOGI(TAG, "copy current app to next part");
|
||||
copy_current_app_to_next_part(cur_app, get_next_update_partition());
|
||||
reboot_as_deep_sleep();
|
||||
}
|
||||
|
||||
/* @brief Copies a current app to next partition (OTA0-15) using esp_ota_write_with_offest(), after that ESP is rebooting and run this (the next) OTAx.
|
||||
*/
|
||||
void copy_current_app_to_next_part_with_offset_and_reboot(void)
|
||||
{
|
||||
const esp_partition_t *cur_app = esp_ota_get_running_partition();
|
||||
ESP_LOGI(TAG, "copy current app to next part");
|
||||
copy_current_app_to_next_part_with_offset(cur_app, get_next_update_partition());
|
||||
reboot_as_deep_sleep();
|
||||
}
|
||||
|
||||
/* @brief Get running app.
|
||||
*
|
||||
* @return The next partition of OTA(OTA0-15).
|
||||
*/
|
||||
const esp_partition_t* get_running_firmware(void)
|
||||
{
|
||||
const esp_partition_t *configured = esp_ota_get_boot_partition();
|
||||
const esp_partition_t *running = esp_ota_get_running_partition();
|
||||
// If a reboot hasn't occurred after app_update(), the configured and running partitions may differ
|
||||
ESP_LOGI(TAG, "Running partition type %d subtype %d (offset 0x%08"PRIx32")",
|
||||
running->type, running->subtype, running->address);
|
||||
ESP_LOGI(TAG, "Configured partition type %d subtype %d (offset 0x%08"PRIx32")",
|
||||
configured->type, configured->subtype, configured->address);
|
||||
TEST_ASSERT_NOT_EQUAL(NULL, configured);
|
||||
TEST_ASSERT_NOT_EQUAL(NULL, running);
|
||||
return running;
|
||||
}
|
||||
|
||||
/* @brief Get two copies ota_data from otadata partition.
|
||||
*
|
||||
* @param[in] otadata_partition - otadata partition.
|
||||
* @param[out] ota_data_0 - First copy from otadata_partition.
|
||||
* @param[out] ota_data_1 - Second copy from otadata_partition.
|
||||
*/
|
||||
void get_ota_data(const esp_partition_t *otadata_partition, esp_ota_select_entry_t *ota_data_0, esp_ota_select_entry_t *ota_data_1)
|
||||
{
|
||||
uint32_t offset = otadata_partition->address;
|
||||
uint32_t size = otadata_partition->size;
|
||||
if (offset != 0) {
|
||||
const esp_ota_select_entry_t *ota_select_map;
|
||||
ota_select_map = bootloader_mmap(offset, size);
|
||||
TEST_ASSERT_NOT_EQUAL(NULL, ota_select_map);
|
||||
|
||||
memcpy(ota_data_0, ota_select_map, sizeof(esp_ota_select_entry_t));
|
||||
memcpy(ota_data_1, (uint8_t *)ota_select_map + otadata_partition->erase_size, sizeof(esp_ota_select_entry_t));
|
||||
bootloader_munmap(ota_select_map);
|
||||
}
|
||||
}
|
||||
|
||||
/* @brief Writes a ota_data into required sector of otadata_partition.
|
||||
*
|
||||
* @param[in] otadata_partition - Partition information otadata.
|
||||
* @param[in] ota_data - otadata structure.
|
||||
* @param[in] sec_id - Sector number 0 or 1.
|
||||
*/
|
||||
void write_ota_data(const esp_partition_t *otadata_partition, esp_ota_select_entry_t *ota_data, int sec_id)
|
||||
{
|
||||
esp_partition_write(otadata_partition, otadata_partition->erase_size * sec_id, &ota_data[sec_id], sizeof(esp_ota_select_entry_t));
|
||||
}
|
||||
|
||||
/* @brief Makes a corrupt of ota_data.
|
||||
* @param[in] err - type error
|
||||
*/
|
||||
void corrupt_ota_data(corrupt_ota_data_t err)
|
||||
{
|
||||
esp_ota_select_entry_t ota_data[2];
|
||||
|
||||
const esp_partition_t *otadata_partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_OTA, NULL);
|
||||
TEST_ASSERT_NOT_EQUAL(NULL, otadata_partition);
|
||||
get_ota_data(otadata_partition, &ota_data[0], &ota_data[1]);
|
||||
|
||||
if (err & CORR_CRC_1_SECTOR_OTA_DATA) {
|
||||
ota_data[0].crc = 0;
|
||||
}
|
||||
if (err & CORR_CRC_2_SECTOR_OTA_DATA) {
|
||||
ota_data[1].crc = 0;
|
||||
}
|
||||
TEST_ESP_OK(esp_partition_erase_range(otadata_partition, 0, otadata_partition->size));
|
||||
write_ota_data(otadata_partition, &ota_data[0], 0);
|
||||
write_ota_data(otadata_partition, &ota_data[1], 1);
|
||||
}
|
||||
|
||||
#if defined(CONFIG_BOOTLOADER_FACTORY_RESET) || defined(CONFIG_BOOTLOADER_APP_TEST)
|
||||
/* @brief Sets the pin number to output and sets output level as low. After reboot (deep sleep) this pin keep the same level.
|
||||
*
|
||||
* The output level of the pad will be force locked and can not be changed.
|
||||
* Power down or call gpio_hold_dis will disable this function.
|
||||
*
|
||||
* @param[in] num_pin - Pin number
|
||||
*/
|
||||
void set_output_pin(uint32_t num_pin)
|
||||
{
|
||||
TEST_ESP_OK(gpio_hold_dis(num_pin));
|
||||
|
||||
gpio_config_t io_conf;
|
||||
io_conf.intr_type = GPIO_INTR_DISABLE;
|
||||
io_conf.mode = GPIO_MODE_OUTPUT;
|
||||
io_conf.pin_bit_mask = (1ULL << num_pin);
|
||||
io_conf.pull_down_en = 0;
|
||||
io_conf.pull_up_en = 0;
|
||||
TEST_ESP_OK(gpio_config(&io_conf));
|
||||
|
||||
TEST_ESP_OK(gpio_set_level(num_pin, 0));
|
||||
TEST_ESP_OK(gpio_hold_en(num_pin));
|
||||
}
|
||||
|
||||
/* @brief Unset the pin number hold function.
|
||||
*/
|
||||
void reset_output_pin(uint32_t num_pin)
|
||||
{
|
||||
TEST_ESP_OK(gpio_hold_dis(num_pin));
|
||||
TEST_ESP_OK(gpio_reset_pin(num_pin));
|
||||
}
|
||||
#endif
|
||||
|
||||
void mark_app_valid(void)
|
||||
{
|
||||
#ifdef CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE
|
||||
TEST_ESP_OK(esp_ota_mark_app_valid_cancel_rollback());
|
||||
#endif
|
||||
}
|
||||
|
||||
const esp_partition_t* app_update(void)
|
||||
{
|
||||
const esp_partition_t *cur_app = get_running_firmware();
|
||||
const esp_partition_t* update_partition = esp_ota_get_next_update_partition(NULL);
|
||||
TEST_ASSERT_NOT_NULL(update_partition);
|
||||
esp_ota_handle_t update_handle = 0;
|
||||
TEST_ESP_OK(esp_ota_begin(update_partition, OTA_SIZE_UNKNOWN, &update_handle));
|
||||
copy_app_partition(update_handle, cur_app);
|
||||
TEST_ESP_OK(esp_ota_end(update_handle));
|
||||
TEST_ESP_OK(esp_ota_set_boot_partition(update_partition));
|
||||
return update_partition;
|
||||
}
|
||||
@@ -1,148 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include "esp_ota_ops.h"
|
||||
#include "esp_partition.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* @brief Enumeration for specifying which OTA data sectors' CRCs to corrupt.
|
||||
*/
|
||||
typedef enum {
|
||||
CORR_CRC_1_SECTOR_OTA_DATA = (1 << 0), /*!< Corrupt CRC only 1 sector of ota_data */
|
||||
CORR_CRC_2_SECTOR_OTA_DATA = (1 << 1), /*!< Corrupt CRC only 2 sector of ota_data */
|
||||
} corrupt_ota_data_t;
|
||||
|
||||
/**
|
||||
* @brief Set boot count value in NVS.
|
||||
* @param boot_count Value to set.
|
||||
*/
|
||||
void set_boot_count_in_nvs(uint8_t boot_count);
|
||||
|
||||
/**
|
||||
* @brief Get boot count value from NVS.
|
||||
* @return Boot count value.
|
||||
*/
|
||||
uint8_t get_boot_count_from_nvs(void);
|
||||
|
||||
/**
|
||||
* @brief Copy current app to next partition using OTA handle.
|
||||
* @param update_handle OTA update handle.
|
||||
* @param curr_app Current app partition.
|
||||
*/
|
||||
void copy_app_partition(esp_ota_handle_t update_handle, const esp_partition_t *curr_app);
|
||||
|
||||
/**
|
||||
* @brief Copy current app to next partition using OTA handle with offset.
|
||||
* @param update_handle OTA update handle.
|
||||
* @param curr_app Current app partition.
|
||||
*/
|
||||
void copy_app_partition_with_offset(esp_ota_handle_t update_handle, const esp_partition_t *curr_app);
|
||||
|
||||
/**
|
||||
* @brief Get the next OTA update partition.
|
||||
* @return Pointer to next OTA partition.
|
||||
*/
|
||||
const esp_partition_t * get_next_update_partition(void);
|
||||
|
||||
/**
|
||||
* @brief Copy current app to next partition and set boot partition.
|
||||
* @param cur_app_partition Current app partition.
|
||||
* @param next_app_partition Next app partition.
|
||||
*/
|
||||
void copy_current_app_to_next_part(const esp_partition_t *cur_app_partition, const esp_partition_t *next_app_partition);
|
||||
|
||||
/**
|
||||
* @brief Copy current app to next partition with offset and set boot partition.
|
||||
* @param cur_app_partition Current app partition.
|
||||
* @param next_app_partition Next app partition.
|
||||
*/
|
||||
void copy_current_app_to_next_part_with_offset(const esp_partition_t *cur_app_partition, const esp_partition_t *next_app_partition);
|
||||
|
||||
/**
|
||||
* @brief Erase OTA data partition.
|
||||
*/
|
||||
void erase_ota_data(void);
|
||||
|
||||
/**
|
||||
* @brief Reboot ESP using deep sleep mode.
|
||||
*/
|
||||
void reboot_as_deep_sleep(void);
|
||||
|
||||
/**
|
||||
* @brief Copy current app to next partition and reboot.
|
||||
*/
|
||||
void copy_current_app_to_next_part_and_reboot(void);
|
||||
|
||||
/**
|
||||
* @brief Copy current app to next partition with offset and reboot.
|
||||
*/
|
||||
void copy_current_app_to_next_part_with_offset_and_reboot(void);
|
||||
|
||||
/**
|
||||
* @brief Get running firmware partition.
|
||||
* @return Pointer to running firmware partition.
|
||||
*/
|
||||
const esp_partition_t* get_running_firmware(void);
|
||||
|
||||
/**
|
||||
* @brief Get two OTA data copies from OTA data partition.
|
||||
* @param otadata_partition OTA data partition.
|
||||
* @param ota_data_0 First OTA data copy.
|
||||
* @param ota_data_1 Second OTA data copy.
|
||||
*/
|
||||
void get_ota_data(const esp_partition_t *otadata_partition, esp_ota_select_entry_t *ota_data_0, esp_ota_select_entry_t *ota_data_1);
|
||||
|
||||
/**
|
||||
* @brief Write OTA data into required sector of OTA data partition.
|
||||
* @param otadata_partition OTA data partition.
|
||||
* @param ota_data OTA data structure.
|
||||
* @param sec_id Sector number (0 or 1).
|
||||
*/
|
||||
void write_ota_data(const esp_partition_t *otadata_partition, esp_ota_select_entry_t *ota_data, int sec_id);
|
||||
|
||||
/**
|
||||
* @brief Corrupt OTA data for testing.
|
||||
* @param err Type of corruption.
|
||||
*/
|
||||
void corrupt_ota_data(corrupt_ota_data_t err);
|
||||
|
||||
#if defined(CONFIG_BOOTLOADER_FACTORY_RESET) || defined(CONFIG_BOOTLOADER_APP_TEST)
|
||||
/**
|
||||
* @brief Set output pin to low and hold state.
|
||||
* @param num_pin Pin number.
|
||||
*/
|
||||
void set_output_pin(uint32_t num_pin);
|
||||
|
||||
/**
|
||||
* @brief Reset output pin hold function.
|
||||
* @param num_pin Pin number.
|
||||
*/
|
||||
void reset_output_pin(uint32_t num_pin);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Mark app as valid and cancel rollback.
|
||||
*/
|
||||
void mark_app_valid(void);
|
||||
|
||||
/**
|
||||
* @brief Perform app update and set new boot partition.
|
||||
* @return Pointer to updated partition.
|
||||
*/
|
||||
const esp_partition_t* app_update(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -20,7 +20,7 @@ TEST_SUBMENU_PATTERN_PYTEST = re.compile(rb'\s+\((\d+)\)\s+"([^"]+)"\r?\n')
|
||||
)
|
||||
@idf_parametrize('target', ['supported_targets'], indirect=['target'])
|
||||
def test_app_update(dut: Dut) -> None:
|
||||
dut.run_all_single_board_cases(timeout=180)
|
||||
dut.run_all_single_board_cases(timeout=90)
|
||||
|
||||
|
||||
@pytest.mark.generic
|
||||
@@ -33,7 +33,7 @@ def test_app_update(dut: Dut) -> None:
|
||||
)
|
||||
@idf_parametrize('target', ['supported_targets'], indirect=['target'])
|
||||
def test_app_update_xip_psram(dut: Dut) -> None:
|
||||
dut.run_all_single_board_cases(timeout=180)
|
||||
dut.run_all_single_board_cases(timeout=90)
|
||||
|
||||
|
||||
@pytest.mark.generic
|
||||
@@ -46,7 +46,7 @@ def test_app_update_xip_psram(dut: Dut) -> None:
|
||||
)
|
||||
@idf_parametrize('target', ['supported_targets'], indirect=['target'])
|
||||
def test_app_update_xip_psram_rom_impl(dut: Dut) -> None:
|
||||
dut.run_all_single_board_cases(timeout=180)
|
||||
dut.run_all_single_board_cases(timeout=90)
|
||||
|
||||
|
||||
@pytest.mark.generic
|
||||
@@ -59,19 +59,4 @@ def test_app_update_xip_psram_rom_impl(dut: Dut) -> None:
|
||||
)
|
||||
@idf_parametrize('target', ['esp32', 'esp32c3', 'esp32s3', 'esp32p4'], indirect=['target'])
|
||||
def test_app_update_with_rollback(dut: Dut) -> None:
|
||||
dut.run_all_single_board_cases(timeout=180)
|
||||
|
||||
|
||||
@pytest.mark.recovery_bootloader
|
||||
@pytest.mark.parametrize(
|
||||
'config',
|
||||
['recovery_bootloader'],
|
||||
indirect=True,
|
||||
)
|
||||
@idf_parametrize('target', ['esp32c5'], indirect=['target'])
|
||||
def test_recovery_bootloader_update(dut: Dut) -> None:
|
||||
try:
|
||||
dut.run_all_single_board_cases(group='recovery_bootloader', timeout=90)
|
||||
finally:
|
||||
# Erase recovery bootloader after test because it may interfere with other tests using this runner
|
||||
dut.serial.erase_flash()
|
||||
dut.run_all_single_board_cases(timeout=90)
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
CONFIG_BOOTLOADER_RECOVERY_ENABLE=y
|
||||
CONFIG_BOOTLOADER_RECOVERY_OFFSET=0x3F0000
|
||||
CONFIG_PARTITION_TABLE_OFFSET=0x9000
|
||||
@@ -1,2 +0,0 @@
|
||||
# ESP32C5 supports the Recovery bootloader feature in ROM starting from v1.0 (ECO2)
|
||||
CONFIG_IDF_TARGET="esp32c5"
|
||||
@@ -1,2 +0,0 @@
|
||||
# ESP32C61 supports the Recovery bootloader feature in ROM starting from v1.0 (ECO3)
|
||||
CONFIG_IDF_TARGET="esp32c61"
|
||||
@@ -1,37 +1,8 @@
|
||||
menu "Recovery Bootloader and Rollback"
|
||||
|
||||
config BOOTLOADER_RECOVERY_ENABLE
|
||||
bool "Enable Recovery Bootloader"
|
||||
depends on SOC_RECOVERY_BOOTLOADER_SUPPORTED
|
||||
default n
|
||||
help
|
||||
The recovery bootloader feature is implemented in the ROM bootloader. It is required for safe OTA
|
||||
updates of the bootloader. The feature is activated when the eFuse field
|
||||
(ESP_EFUSE_RECOVERY_BOOTLOADER_FLASH_SECTOR) is set, which defines the flash address of the
|
||||
recovery bootloader. If activated and the primary bootloader fails to load, the ROM bootloader
|
||||
will attempt to load the recovery bootloader from the address specified in eFuse.
|
||||
|
||||
config BOOTLOADER_RECOVERY_OFFSET
|
||||
hex "Recovery Bootloader Flash Offset"
|
||||
depends on BOOTLOADER_RECOVERY_ENABLE
|
||||
default 0x3F0000
|
||||
range 0x0 0xFFE000
|
||||
help
|
||||
Flash address where the recovery bootloader is stored.
|
||||
This value must be written to the eFuse field (ESP_EFUSE_RECOVERY_BOOTLOADER_FLASH_SECTOR)
|
||||
to activate the recovery bootloader in the ROM bootloader. The eFuse can be programmed
|
||||
using espefuse.py or in the user application with the API esp_efuse_set_recovery_bootloader_offset().
|
||||
Setting this value in the config allows parttool.py to verify that it does not overlap with existing
|
||||
partitions in the partition table.
|
||||
|
||||
The address must be a multiple of the flash sector size (0x1000 bytes).
|
||||
The eFuse field stores the offset in sectors.
|
||||
If the feature is no longer needed or unused, you can burn the 0xFFF value to disable this feature in
|
||||
the ROM bootloader.
|
||||
menu "Bootloader Rollback"
|
||||
|
||||
config BOOTLOADER_ANTI_ROLLBACK_ENABLE
|
||||
bool "Enable bootloader rollback support"
|
||||
depends on BOOTLOADER_RECOVERY_ENABLE
|
||||
depends on SOC_RECOVERY_BOOTLOADER_SUPPORTED
|
||||
default n
|
||||
help
|
||||
This option prevents rollback to previous bootloader image with lower security version.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -18,7 +18,6 @@
|
||||
#include "hal/cache_hal.h"
|
||||
#include "hal/cache_ll.h"
|
||||
#include "hal/mspi_ll.h"
|
||||
#include "hal/clk_tree_ll.h"
|
||||
#include "soc/pcr_reg.h"
|
||||
|
||||
static const char *TAG = "boot.esp32h21";
|
||||
@@ -81,9 +80,7 @@ void IRAM_ATTR bootloader_configure_spi_pins(int drv)
|
||||
|
||||
static void IRAM_ATTR bootloader_flash_clock_init(void)
|
||||
{
|
||||
// To raise the MSPI clock to 64MHz, needs to enable the 64MHz clock source, which is XTAL_X2_CLK
|
||||
// (FPGA image fixed MSPI0/1 clock to 64MHz)
|
||||
clk_ll_xtal_x2_enable();
|
||||
// At this moment, BBPLL should be enabled, safe to switch MSPI clock source to PLL_F64M (default clock src) to raise speed
|
||||
_mspi_timing_ll_set_flash_clk_src(0, FLASH_CLK_SRC_PLL_F64M);
|
||||
}
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
#include "soc/pmu_reg.h"
|
||||
#endif
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32C5
|
||||
#include "hal/clk_tree_ll.h"
|
||||
#endif
|
||||
#include "esp_rom_sys.h"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -19,7 +19,6 @@
|
||||
#include "hal/wdt_hal.h"
|
||||
#include "hal/efuse_hal.h"
|
||||
#include "esp_bootloader_desc.h"
|
||||
#include "esp_rom_sys.h"
|
||||
|
||||
static const char *TAG = "boot";
|
||||
|
||||
@@ -35,12 +34,7 @@ void bootloader_clear_bss_section(void)
|
||||
esp_err_t bootloader_read_bootloader_header(void)
|
||||
{
|
||||
/* load bootloader image header */
|
||||
#if SOC_RECOVERY_BOOTLOADER_SUPPORTED
|
||||
const uint32_t bootloader_flash_offset = esp_rom_get_bootloader_offset();
|
||||
#else
|
||||
const uint32_t bootloader_flash_offset = ESP_PRIMARY_BOOTLOADER_OFFSET;
|
||||
#endif
|
||||
if (bootloader_flash_read(bootloader_flash_offset, &bootloader_image_hdr, sizeof(esp_image_header_t), true) != ESP_OK) {
|
||||
if (bootloader_flash_read(ESP_BOOTLOADER_OFFSET, &bootloader_image_hdr, sizeof(esp_image_header_t), true) != ESP_OK) {
|
||||
ESP_EARLY_LOGE(TAG, "failed to load bootloader image header!");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
@@ -25,19 +25,20 @@ void bootloader_init_mem(void)
|
||||
* So, at boot disabling these filters. They will enable as per the
|
||||
* use case by TEE initialization code.
|
||||
*/
|
||||
#if SOC_APM_CTRL_FILTER_SUPPORTED
|
||||
apm_hal_enable_ctrl_filter_all(false);
|
||||
/* [APM] On power-up, only the HP CPU starts in TEE mode; others
|
||||
* default to REE2. APM blocks REE0–REE2 access by default.
|
||||
* Thus, all masters are set to TEE mode.
|
||||
#ifdef SOC_APM_CTRL_FILTER_SUPPORTED
|
||||
apm_hal_apm_ctrl_filter_enable_all(false);
|
||||
/* [APM] On power-up, only the HP CPU starts in TEE mode; others default to REE2.
|
||||
* APM blocks REE0–REE2 access by default. C5 ECO2 adds per-peripheral control
|
||||
* (default REEx blocking), but config support is pending. As a workaround,
|
||||
* all masters are set to TEE mode.
|
||||
*/
|
||||
#if SOC_APM_SUPPORT_TEE_PERI_ACCESS_CTRL
|
||||
apm_hal_set_master_sec_mode_all(APM_SEC_MODE_TEE);
|
||||
apm_tee_hal_set_master_secure_mode_all(APM_LL_SECURE_MODE_TEE);
|
||||
#endif // SOC_APM_SUPPORT_TEE_PERI_ACCESS_CTRL
|
||||
#endif // SOC_APM_CTRL_FILTER_SUPPORTED
|
||||
#endif
|
||||
|
||||
#if CONFIG_BOOTLOADER_REGION_PROTECTION_ENABLE
|
||||
#ifdef CONFIG_BOOTLOADER_REGION_PROTECTION_ENABLE
|
||||
// protect memory region
|
||||
esp_cpu_configure_region_protection();
|
||||
#endif
|
||||
|
||||
@@ -10,8 +10,6 @@
|
||||
#include "hal/adc_types.h"
|
||||
#include "esp_private/regi2c_ctrl.h"
|
||||
|
||||
#define I2C_SAR_ADC_INIT_CODE_VAL 2150
|
||||
|
||||
void bootloader_random_enable(void)
|
||||
{
|
||||
adc_ll_reset_register();
|
||||
@@ -31,8 +29,8 @@ void bootloader_random_enable(void)
|
||||
ANALOG_CLOCK_ENABLE();
|
||||
|
||||
adc_ll_regi2c_init();
|
||||
adc_ll_set_calibration_param(ADC_UNIT_1, I2C_SAR_ADC_INIT_CODE_VAL);
|
||||
adc_ll_set_calibration_param(ADC_UNIT_2, I2C_SAR_ADC_INIT_CODE_VAL);
|
||||
adc_ll_set_calibration_param(ADC_UNIT_1, 0x866);
|
||||
adc_ll_set_calibration_param(ADC_UNIT_2, 0x866);
|
||||
|
||||
adc_digi_pattern_config_t pattern_config = {};
|
||||
pattern_config.unit = ADC_UNIT_1;
|
||||
|
||||
@@ -10,8 +10,6 @@
|
||||
#include "hal/adc_types.h"
|
||||
#include "esp_private/regi2c_ctrl.h"
|
||||
|
||||
#define I2C_SAR_ADC_INIT_CODE_VAL 2150
|
||||
|
||||
void bootloader_random_enable(void)
|
||||
{
|
||||
adc_ll_reset_register();
|
||||
@@ -31,8 +29,8 @@ void bootloader_random_enable(void)
|
||||
ANALOG_CLOCK_ENABLE();
|
||||
|
||||
adc_ll_regi2c_init();
|
||||
adc_ll_set_calibration_param(ADC_UNIT_1, I2C_SAR_ADC_INIT_CODE_VAL);
|
||||
adc_ll_set_calibration_param(ADC_UNIT_2, I2C_SAR_ADC_INIT_CODE_VAL);
|
||||
adc_ll_set_calibration_param(ADC_UNIT_1, 0x866);
|
||||
adc_ll_set_calibration_param(ADC_UNIT_2, 0x866);
|
||||
|
||||
adc_digi_pattern_config_t pattern_config = {};
|
||||
pattern_config.unit = ADC_UNIT_2;
|
||||
|
||||
@@ -10,8 +10,6 @@
|
||||
#include "hal/adc_types.h"
|
||||
#include "esp_private/regi2c_ctrl.h"
|
||||
|
||||
#define I2C_SAR_ADC_INIT_CODE_VAL 2150
|
||||
|
||||
void bootloader_random_enable(void)
|
||||
{
|
||||
adc_ll_reset_register();
|
||||
@@ -31,8 +29,8 @@ void bootloader_random_enable(void)
|
||||
ANALOG_CLOCK_ENABLE();
|
||||
|
||||
adc_ll_regi2c_init();
|
||||
adc_ll_set_calibration_param(ADC_UNIT_1, I2C_SAR_ADC_INIT_CODE_VAL);
|
||||
adc_ll_set_calibration_param(ADC_UNIT_2, I2C_SAR_ADC_INIT_CODE_VAL);
|
||||
adc_ll_set_calibration_param(ADC_UNIT_1, 0x866);
|
||||
adc_ll_set_calibration_param(ADC_UNIT_2, 0x866);
|
||||
|
||||
adc_digi_pattern_config_t pattern_config = {};
|
||||
pattern_config.unit = ADC_UNIT_1;
|
||||
|
||||
@@ -10,8 +10,6 @@
|
||||
#include "hal/adc_types.h"
|
||||
#include "esp_private/regi2c_ctrl.h"
|
||||
|
||||
#define I2C_SAR_ADC_INIT_CODE_VAL 2150
|
||||
|
||||
void bootloader_random_enable(void)
|
||||
{
|
||||
adc_ll_reset_register();
|
||||
@@ -31,8 +29,8 @@ void bootloader_random_enable(void)
|
||||
ANALOG_CLOCK_ENABLE();
|
||||
|
||||
adc_ll_regi2c_init();
|
||||
adc_ll_set_calibration_param(ADC_UNIT_1, I2C_SAR_ADC_INIT_CODE_VAL);
|
||||
adc_ll_set_calibration_param(ADC_UNIT_2, I2C_SAR_ADC_INIT_CODE_VAL);
|
||||
adc_ll_set_calibration_param(ADC_UNIT_1, 0x866);
|
||||
adc_ll_set_calibration_param(ADC_UNIT_2, 0x866);
|
||||
|
||||
adc_digi_pattern_config_t pattern_config = {};
|
||||
pattern_config.atten = ADC_ATTEN_DB_2_5;
|
||||
|
||||
@@ -1,72 +1,108 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include "sdkconfig.h"
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include "bootloader_random.h"
|
||||
#include "hal/regi2c_ctrl_ll.h"
|
||||
#include "hal/adc_ll.h"
|
||||
#include "hal/adc_types.h"
|
||||
#include "soc/soc.h"
|
||||
#include "soc/adc_reg.h"
|
||||
#include "soc/pmu_reg.h"
|
||||
#include "soc/regi2c_saradc.h"
|
||||
#include "soc/hp_sys_clkrst_reg.h"
|
||||
#include "soc/lp_adc_reg.h"
|
||||
#include "esp_private/regi2c_ctrl.h"
|
||||
#include "esp_rom_regi2c.h"
|
||||
|
||||
#include "esp_private/periph_ctrl.h"
|
||||
#include "esp_private/adc_share_hw_ctrl.h"
|
||||
// TODO IDF-6497: once ADC API is supported, use the API instead of defining functions and constants here
|
||||
|
||||
#define I2C_SAR_ADC_INIT_CODE_VAL 2166
|
||||
|
||||
typedef struct {
|
||||
int atten;
|
||||
int channel;
|
||||
} pattern_item;
|
||||
|
||||
typedef struct {
|
||||
pattern_item item[4];
|
||||
} pattern_table;
|
||||
|
||||
static void adc1_fix_initcode_set(uint32_t initcode_value)
|
||||
{
|
||||
uint32_t msb = initcode_value >> 8;
|
||||
uint32_t lsb = initcode_value & 0xff;
|
||||
REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR1_INITIAL_CODE_HIGH_ADDR, msb);
|
||||
REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR1_INITIAL_CODE_LOW_ADDR, lsb);
|
||||
}
|
||||
|
||||
//total 4 tables
|
||||
static void hpadc_sar1_pattern_table_cfg(unsigned int table_idx, pattern_table table)
|
||||
{
|
||||
uint32_t wdata = 0;
|
||||
wdata = (table.item[0].channel << 20 | table.item[0].atten << 18 |
|
||||
table.item[1].channel << 14|table.item[1].atten << 12 |
|
||||
table.item[2].channel << 8 |table.item[2].atten << 6 |
|
||||
table.item[3].channel << 2 |table.item[3].atten);
|
||||
WRITE_PERI_REG(ADC_SAR1_PATT_TAB1_REG + table_idx * 4, wdata);
|
||||
}
|
||||
|
||||
void bootloader_random_enable(void)
|
||||
{
|
||||
_adc_ll_reset_register();
|
||||
_adc_ll_enable_bus_clock(true);
|
||||
pattern_table sar1_table[4] = {};
|
||||
uint32_t pattern_len = 0;
|
||||
|
||||
adc_ll_digi_clk_sel(ADC_DIGI_CLK_SRC_XTAL);
|
||||
adc_ll_digi_controller_clk_div(0, 0, 0);
|
||||
SET_PERI_REG_MASK(HP_SYS_CLKRST_SOC_CLK_CTRL2_REG, HP_SYS_CLKRST_REG_ADC_APB_CLK_EN);
|
||||
SET_PERI_REG_MASK(HP_SYS_CLKRST_PERI_CLK_CTRL23_REG, HP_SYS_CLKRST_REG_ADC_CLK_EN);
|
||||
|
||||
// some ADC sensor registers are in power group PERIF_I2C and need to be enabled via PMU
|
||||
#ifndef BOOTLOADER_BUILD
|
||||
regi2c_saradc_enable();
|
||||
#else
|
||||
regi2c_ctrl_ll_i2c_sar_periph_enable();
|
||||
#endif
|
||||
SET_PERI_REG_MASK(RTCADC_MEAS1_MUX_REG, RTCADC_SAR1_DIG_FORCE);
|
||||
SET_PERI_REG_MASK(PMU_RF_PWC_REG,PMU_XPD_PERIF_I2C);
|
||||
|
||||
uint32_t sar1_clk_div_num = GET_PERI_REG_BITS2((HP_SYS_CLKRST_PERI_CLK_CTRL24_REG),
|
||||
(HP_SYS_CLKRST_REG_ADC_SAR1_CLK_DIV_NUM_M),
|
||||
(HP_SYS_CLKRST_REG_ADC_SAR1_CLK_DIV_NUM_S));
|
||||
|
||||
SET_PERI_REG_MASK(ADC_CTRL_REG_REG, ADC_START_FORCE); //start force 1
|
||||
|
||||
// enable analog i2c master clock for RNG runtime
|
||||
ANALOG_CLOCK_ENABLE();
|
||||
|
||||
adc_ll_regi2c_init();
|
||||
adc_ll_set_calibration_param(ADC_UNIT_1, I2C_SAR_ADC_INIT_CODE_VAL);
|
||||
adc1_fix_initcode_set(I2C_SAR_ADC_INIT_CODE_VAL);
|
||||
|
||||
adc_digi_pattern_config_t pattern_config = {};
|
||||
pattern_config.unit = ADC_UNIT_1;
|
||||
pattern_config.atten = ADC_ATTEN_DB_12;
|
||||
pattern_config.channel = ADC_CHANNEL_10;
|
||||
adc_ll_digi_set_pattern_table(ADC_UNIT_1, 0, pattern_config);
|
||||
adc_ll_digi_set_pattern_table(ADC_UNIT_1, 1, pattern_config);
|
||||
adc_ll_digi_set_pattern_table(ADC_UNIT_1, 2, pattern_config);
|
||||
adc_ll_digi_set_pattern_table(ADC_UNIT_1, 3, pattern_config);
|
||||
adc_ll_digi_set_pattern_table_len(ADC_UNIT_1, 1);
|
||||
// cfg pattern table
|
||||
sar1_table[0].item[0].channel = 10; //rand() % 6;
|
||||
sar1_table[0].item[0].atten = 3;
|
||||
sar1_table[0].item[1].channel = 10;
|
||||
sar1_table[0].item[1].atten = 3;
|
||||
sar1_table[0].item[2].channel = 10;
|
||||
sar1_table[0].item[2].atten = 3;
|
||||
sar1_table[0].item[3].channel = 10;
|
||||
sar1_table[0].item[3].atten = 3;
|
||||
|
||||
adc_ll_set_controller(ADC_UNIT_1, ADC_LL_CTRL_DIG);
|
||||
adc_ll_digi_set_power_manage(ADC_UNIT_1, ADC_LL_POWER_SW_ON);
|
||||
hpadc_sar1_pattern_table_cfg(0, sar1_table[0]);
|
||||
SET_PERI_REG_BITS(ADC_CTRL_REG_REG, ADC_SAR1_PATT_LEN, pattern_len, ADC_SAR1_PATT_LEN_S);
|
||||
|
||||
adc_ll_digi_set_clk_div(15);
|
||||
adc_ll_digi_set_trigger_interval(100);
|
||||
adc_ll_digi_trigger_enable();
|
||||
SET_PERI_REG_BITS(ADC_CTRL_REG_REG, ADC_XPD_SAR1_FORCE, 3, ADC_XPD_SAR1_FORCE_S);
|
||||
SET_PERI_REG_BITS(ADC_CTRL_REG_REG, ADC_XPD_SAR2_FORCE, 3, ADC_XPD_SAR2_FORCE_S);
|
||||
|
||||
REGI2C_WRITE_MASK(I2C_SAR_ADC, I2C_SAR_ADC_ENT_VDD_GRP1, 1);
|
||||
REGI2C_WRITE_MASK(I2C_SAR_ADC, I2C_SAR_ADC_DTEST_VDD_GRP1, 0);
|
||||
|
||||
CLEAR_PERI_REG_MASK(ADC_CTRL_REG_REG, ADC_START_FORCE);
|
||||
SET_PERI_REG_MASK(ADC_CTRL2_REG, ADC_TIMER_EN);
|
||||
SET_PERI_REG_BITS(ADC_CTRL2_REG, ADC_TIMER_TARGET, sar1_clk_div_num * 25, ADC_TIMER_TARGET_S);
|
||||
|
||||
while (GET_PERI_REG_MASK(ADC_INT_RAW_REG, ADC_SAR1_DONE_INT_RAW) == 0) { }
|
||||
|
||||
SET_PERI_REG_MASK(ADC_INT_CLR_REG, ADC_APB_SARADC1_DONE_INT_CLR);
|
||||
}
|
||||
|
||||
void bootloader_random_disable(void)
|
||||
{
|
||||
adc_ll_digi_trigger_disable();
|
||||
adc_ll_digi_reset_pattern_table();
|
||||
adc_ll_set_calibration_param(ADC_UNIT_1, 0x0);
|
||||
adc_ll_set_calibration_param(ADC_UNIT_2, 0x0);
|
||||
adc_ll_regi2c_adc_deinit();
|
||||
|
||||
#ifndef BOOTLOADER_BUILD
|
||||
regi2c_saradc_disable();
|
||||
#endif
|
||||
|
||||
// disable analog i2c master clock
|
||||
ANALOG_CLOCK_DISABLE();
|
||||
adc_ll_digi_controller_clk_div(4, 0, 0);
|
||||
adc_ll_digi_clk_sel(ADC_DIGI_CLK_SRC_XTAL);
|
||||
|
||||
REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR1_INITIAL_CODE_LOW_ADDR, 0);
|
||||
REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR1_INITIAL_CODE_HIGH_ADDR, 0);
|
||||
|
||||
REGI2C_WRITE_MASK(I2C_SAR_ADC, I2C_SAR_ADC_ENT_VDD_GRP1, 0);
|
||||
REGI2C_WRITE_MASK(I2C_SAR_ADC, I2C_SAR_ADC_DTEST_VDD_GRP1, 0);
|
||||
}
|
||||
|
||||
@@ -167,7 +167,7 @@ esp_err_t bootloader_init(void)
|
||||
|
||||
#if XCHAL_ERRATUM_572
|
||||
uint32_t memctl = XCHAL_CACHE_MEMCTL_DEFAULT;
|
||||
WSR(XT_REG_MEMCTL, memctl);
|
||||
WSR(MEMCTL, memctl);
|
||||
#endif // XCHAL_ERRATUM_572
|
||||
|
||||
// In RAM_APP, memory will be initialized in `call_start_cpu0`
|
||||
|
||||
@@ -86,6 +86,7 @@ static void bootloader_super_wdt_auto_feed(void)
|
||||
static inline void bootloader_hardware_init(void)
|
||||
{
|
||||
_regi2c_ctrl_ll_master_enable_clock(true); // keep ana i2c mst clock always enabled in bootloader
|
||||
regi2c_ctrl_ll_master_force_enable_clock(true); // TODO: IDF-8667 Remove this?
|
||||
regi2c_ctrl_ll_master_configure_clock();
|
||||
}
|
||||
|
||||
|
||||
@@ -87,6 +87,7 @@ static void bootloader_super_wdt_auto_feed(void)
|
||||
static inline void bootloader_hardware_init(void)
|
||||
{
|
||||
_regi2c_ctrl_ll_master_enable_clock(true); // keep ana i2c mst clock always enabled in bootloader
|
||||
regi2c_ctrl_ll_master_force_enable_clock(true); // TODO: IDF-9274 Remove this?
|
||||
regi2c_ctrl_ll_master_configure_clock();
|
||||
}
|
||||
|
||||
|
||||
@@ -89,7 +89,8 @@ static inline void bootloader_hardware_init(void)
|
||||
CLEAR_PERI_REG_MASK(PMU_RF_PWC_REG, PMU_XPD_RFPLL);
|
||||
SET_PERI_REG_MASK(PMU_RF_PWC_REG, PMU_XPD_FORCE_RFPLL);
|
||||
|
||||
_regi2c_ctrl_ll_master_enable_clock(true); // keep ana i2c mst clock always enabled in bootloader
|
||||
//TODO: [ESP32H21] IDF-11550, regi2c atomic clock
|
||||
regi2c_ctrl_ll_master_enable_clock(true); // keep ana i2c mst clock always enabled in bootloader
|
||||
regi2c_ctrl_ll_master_configure_clock();
|
||||
}
|
||||
|
||||
|
||||
@@ -144,7 +144,7 @@ esp_err_t bootloader_init(void)
|
||||
|
||||
#if XCHAL_ERRATUM_572
|
||||
uint32_t memctl = XCHAL_CACHE_MEMCTL_DEFAULT;
|
||||
WSR(XT_REG_MEMCTL, memctl);
|
||||
WSR(MEMCTL, memctl);
|
||||
#endif // XCHAL_ERRATUM_572
|
||||
|
||||
bootloader_ana_reset_config();
|
||||
|
||||
@@ -23,7 +23,6 @@
|
||||
#include "soc/soc_caps.h"
|
||||
#include "hal/cache_ll.h"
|
||||
#include "spi_flash_mmap.h"
|
||||
#include "hal/efuse_hal.h"
|
||||
|
||||
#define ALIGN_UP(num, align) (((num) + ((align) - 1)) & ~((align) - 1))
|
||||
|
||||
@@ -120,26 +119,11 @@ void esp_image_bootloader_offset_set(const uint32_t offset)
|
||||
{
|
||||
s_bootloader_partition_offset = offset;
|
||||
ESP_LOGI(TAG, "Bootloader offsets for PRIMARY: 0x%x, Secondary: 0x%" PRIx32, ESP_PRIMARY_BOOTLOADER_OFFSET, s_bootloader_partition_offset);
|
||||
#if SOC_RECOVERY_BOOTLOADER_SUPPORTED
|
||||
uint32_t recovery_offset = efuse_hal_get_recovery_bootloader_address();
|
||||
if (efuse_hal_recovery_bootloader_enabled()) {
|
||||
ESP_LOGI(TAG, "Bootloader offset for RECOVERY: 0x%" PRIx32, recovery_offset);
|
||||
} else if (recovery_offset == 0) {
|
||||
ESP_LOGI(TAG, "Bootloader offset for RECOVERY: has not been set yet");
|
||||
} else {
|
||||
ESP_LOGI(TAG, "Bootloader offset for RECOVERY: is disabled");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static bool is_bootloader(uint32_t offset)
|
||||
{
|
||||
return ((offset == ESP_PRIMARY_BOOTLOADER_OFFSET)
|
||||
|| (offset == s_bootloader_partition_offset)
|
||||
#if SOC_RECOVERY_BOOTLOADER_SUPPORTED
|
||||
|| (efuse_hal_recovery_bootloader_enabled() ? offset == efuse_hal_get_recovery_bootloader_address() : false)
|
||||
#endif
|
||||
);
|
||||
return ((offset == ESP_PRIMARY_BOOTLOADER_OFFSET) || (offset == s_bootloader_partition_offset));
|
||||
}
|
||||
|
||||
static esp_err_t image_load(esp_image_load_mode_t mode, const esp_partition_pos_t *part, esp_image_metadata_t *data)
|
||||
|
||||
@@ -29,6 +29,7 @@ set(common_include_dirs
|
||||
|
||||
set(ble_mesh_include_dirs
|
||||
"esp_ble_mesh/common/include"
|
||||
"esp_ble_mesh/common/tinycrypt/include"
|
||||
"esp_ble_mesh/core"
|
||||
"esp_ble_mesh/core/include"
|
||||
"esp_ble_mesh/core/storage"
|
||||
@@ -41,10 +42,6 @@ set(ble_mesh_include_dirs
|
||||
"esp_ble_mesh/api"
|
||||
)
|
||||
|
||||
set(ble_mesh_tinycrypt_dirs
|
||||
"esp_ble_mesh/common/tinycrypt/include"
|
||||
)
|
||||
|
||||
set(ble_mesh_v11_include_dirs
|
||||
"esp_ble_mesh/lib/include"
|
||||
"esp_ble_mesh/v1.1/api/core/include"
|
||||
@@ -503,6 +500,21 @@ if(CONFIG_BT_ENABLED)
|
||||
"esp_ble_mesh/btc/btc_ble_mesh_prov.c"
|
||||
"esp_ble_mesh/btc/btc_ble_mesh_sensor_model.c"
|
||||
"esp_ble_mesh/btc/btc_ble_mesh_time_scene_model.c"
|
||||
"esp_ble_mesh/common/tinycrypt/src/aes_decrypt.c"
|
||||
"esp_ble_mesh/common/tinycrypt/src/aes_encrypt.c"
|
||||
"esp_ble_mesh/common/tinycrypt/src/cbc_mode.c"
|
||||
"esp_ble_mesh/common/tinycrypt/src/ccm_mode.c"
|
||||
"esp_ble_mesh/common/tinycrypt/src/cmac_mode.c"
|
||||
"esp_ble_mesh/common/tinycrypt/src/ctr_mode.c"
|
||||
"esp_ble_mesh/common/tinycrypt/src/ctr_prng.c"
|
||||
"esp_ble_mesh/common/tinycrypt/src/ecc_dh.c"
|
||||
"esp_ble_mesh/common/tinycrypt/src/ecc_dsa.c"
|
||||
"esp_ble_mesh/common/tinycrypt/src/ecc_platform_specific.c"
|
||||
"esp_ble_mesh/common/tinycrypt/src/ecc.c"
|
||||
"esp_ble_mesh/common/tinycrypt/src/hmac_prng.c"
|
||||
"esp_ble_mesh/common/tinycrypt/src/hmac.c"
|
||||
"esp_ble_mesh/common/tinycrypt/src/sha256.c"
|
||||
"esp_ble_mesh/common/tinycrypt/src/utils.c"
|
||||
"esp_ble_mesh/common/atomic.c"
|
||||
"esp_ble_mesh/common/buf.c"
|
||||
"esp_ble_mesh/common/common.c"
|
||||
@@ -553,26 +565,6 @@ if(CONFIG_BT_ENABLED)
|
||||
"esp_ble_mesh/models/server/state_binding.c"
|
||||
"esp_ble_mesh/models/server/state_transition.c"
|
||||
"esp_ble_mesh/models/server/time_scene_server.c")
|
||||
|
||||
if(NOT CONFIG_BLE_MESH_USE_UNIFIED_CRYPTO)
|
||||
list(APPEND include_dirs ${ble_mesh_tinycrypt_dirs})
|
||||
list(APPEND srcs
|
||||
"esp_ble_mesh/common/tinycrypt/src/aes_decrypt.c"
|
||||
"esp_ble_mesh/common/tinycrypt/src/aes_encrypt.c"
|
||||
"esp_ble_mesh/common/tinycrypt/src/cbc_mode.c"
|
||||
"esp_ble_mesh/common/tinycrypt/src/ccm_mode.c"
|
||||
"esp_ble_mesh/common/tinycrypt/src/cmac_mode.c"
|
||||
"esp_ble_mesh/common/tinycrypt/src/ctr_mode.c"
|
||||
"esp_ble_mesh/common/tinycrypt/src/ctr_prng.c"
|
||||
"esp_ble_mesh/common/tinycrypt/src/ecc_dh.c"
|
||||
"esp_ble_mesh/common/tinycrypt/src/ecc_dsa.c"
|
||||
"esp_ble_mesh/common/tinycrypt/src/ecc_platform_specific.c"
|
||||
"esp_ble_mesh/common/tinycrypt/src/ecc.c"
|
||||
"esp_ble_mesh/common/tinycrypt/src/hmac_prng.c"
|
||||
"esp_ble_mesh/common/tinycrypt/src/hmac.c"
|
||||
"esp_ble_mesh/common/tinycrypt/src/sha256.c"
|
||||
"esp_ble_mesh/common/tinycrypt/src/utils.c")
|
||||
endif()
|
||||
if(CONFIG_BLE_MESH_V11_SUPPORT)
|
||||
list(APPEND include_dirs ${ble_mesh_v11_include_dirs})
|
||||
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
#define SPI_OUT_PACKET_LOSS_FRAME_SIZE (6)
|
||||
#define SPI_OUT_TRANS_ITVL_MIN_US (30)
|
||||
#define SPI_OUT_UL_LOG_STR_BUF_SIZE (100)
|
||||
#define SPI_OUT_MALLOC(size) heap_caps_malloc(size, MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT)
|
||||
|
||||
#if SPI_OUT_TS_SYNC_ENABLED
|
||||
#define SPI_OUT_TS_SYNC_TIMEOUT (1000 * 1000)
|
||||
@@ -233,13 +234,13 @@ static void spi_out_le_audio_log_deinit(void);
|
||||
static int spi_out_init_trans(spi_out_trans_cb_t **trans_cb, uint16_t buf_size)
|
||||
{
|
||||
// Memory allocations
|
||||
*trans_cb = (spi_out_trans_cb_t *)malloc(sizeof(spi_out_trans_cb_t));
|
||||
*trans_cb = (spi_out_trans_cb_t *)SPI_OUT_MALLOC(sizeof(spi_out_trans_cb_t));
|
||||
if (!(*trans_cb)) {
|
||||
return -1;
|
||||
}
|
||||
memset(*trans_cb, 0, sizeof(spi_out_trans_cb_t));
|
||||
|
||||
uint8_t *buf = (uint8_t *)spi_bus_dma_memory_alloc(SPI_OUT_BUS, (size_t)buf_size, 0);
|
||||
uint8_t *buf = (uint8_t *)SPI_OUT_MALLOC((size_t)buf_size);
|
||||
if (!buf) {
|
||||
free(*trans_cb);
|
||||
*trans_cb = NULL;
|
||||
@@ -311,7 +312,7 @@ recycle:
|
||||
static int spi_out_log_cb_init(spi_out_log_cb_t **log_cb, uint16_t buf_size, uint8_t type)
|
||||
{
|
||||
// Initialize log control block
|
||||
*log_cb = (spi_out_log_cb_t *)malloc(sizeof(spi_out_log_cb_t));
|
||||
*log_cb = (spi_out_log_cb_t *)SPI_OUT_MALLOC(sizeof(spi_out_log_cb_t));
|
||||
if (!(*log_cb)) {
|
||||
ESP_LOGE(BLE_LOG_TAG, "Failed to initialize log control block!");
|
||||
return -1;
|
||||
@@ -427,7 +428,7 @@ IRAM_ATTR static bool spi_out_log_cb_write(spi_out_log_cb_t *log_cb, const uint8
|
||||
|
||||
memcpy(buf, (const uint8_t *)&head, SPI_OUT_FRAME_HEAD_LEN);
|
||||
memcpy(buf + SPI_OUT_FRAME_HEAD_LEN, addr, len);
|
||||
if (len_append) {
|
||||
if (len_append && addr_append) {
|
||||
memcpy(buf + SPI_OUT_FRAME_HEAD_LEN + len, addr_append, len_append);
|
||||
}
|
||||
memcpy(buf + SPI_OUT_FRAME_HEAD_LEN + total_length, &checksum, SPI_OUT_FRAME_TAIL_LEN);
|
||||
@@ -520,7 +521,7 @@ static int spi_out_ul_log_init(void)
|
||||
}
|
||||
|
||||
// Initialize string buffer
|
||||
ul_log_str_buf = (uint8_t *)malloc(SPI_OUT_UL_LOG_STR_BUF_SIZE);
|
||||
ul_log_str_buf = (uint8_t *)SPI_OUT_MALLOC(SPI_OUT_UL_LOG_STR_BUF_SIZE);
|
||||
if (!ul_log_str_buf) {
|
||||
ESP_LOGE(BLE_LOG_TAG, "Failed to initialize string buffer for upper layer task log!");
|
||||
goto str_buf_init_failed;
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include "esp_timer.h"
|
||||
#include "esp_log.h"
|
||||
#include "freertos/semphr.h"
|
||||
#include "esp_heap_caps.h"
|
||||
|
||||
// Public enums
|
||||
enum {
|
||||
|
||||
@@ -490,10 +490,10 @@ static bt_status_t btc_init_mem(void) {
|
||||
#endif
|
||||
|
||||
#if BTC_HF_INCLUDED == TRUE && HFP_DYNAMIC_MEMORY == TRUE
|
||||
if ((hf_local_param_ptr = (hf_local_param_t *)osi_malloc(sizeof(hf_local_param_t))) == NULL) {
|
||||
if ((hf_local_param_ptr = (hf_local_param_t *)osi_malloc(BTC_HF_NUM_CB * sizeof(hf_local_param_t))) == NULL) {
|
||||
goto error_exit;
|
||||
}
|
||||
memset((void *)hf_local_param_ptr, 0, sizeof(hf_local_param_t));
|
||||
memset((void *)hf_local_param_ptr, 0, BTC_HF_NUM_CB * sizeof(hf_local_param_t));
|
||||
#endif
|
||||
|
||||
#if BTC_HF_CLIENT_INCLUDED == TRUE && HFP_DYNAMIC_MEMORY == TRUE
|
||||
|
||||
@@ -57,17 +57,17 @@ xt_highint4:
|
||||
wsr a0, CCOMPARE2
|
||||
|
||||
/* Enable Timer 2 interrupt */
|
||||
rsr a0, XT_REG_INTENABLE
|
||||
rsr a0, INTENABLE
|
||||
extui a0, a0, 16, 1
|
||||
bnez a0, 1f
|
||||
movi a0, 0
|
||||
xsr a0, XT_REG_INTENABLE /* disable all interrupts */
|
||||
xsr a0, INTENABLE /* disable all interrupts */
|
||||
/* And a0 with (1 << 16) for Timer 2 interrupt mask */
|
||||
addmi a0, a0, (1<<14)
|
||||
addmi a0, a0, (1<<14)
|
||||
addmi a0, a0, (1<<14)
|
||||
addmi a0, a0, (1<<14)
|
||||
wsr a0, XT_REG_INTENABLE /* Enable Timer 2 */
|
||||
wsr a0, INTENABLE /* Enable Timer 2 */
|
||||
1:
|
||||
#endif
|
||||
|
||||
@@ -76,37 +76,37 @@ xt_highint4:
|
||||
s32i a1, a0, 4
|
||||
s32i a2, a0, 8
|
||||
s32i a3, a0, 12
|
||||
rsr a2, XT_REG_EXCSAVE_4 /* holds the value of a0 */
|
||||
rsr a2, EXCSAVE_4 /* holds the value of a0 */
|
||||
s32i a2, a0, 0
|
||||
|
||||
/* Save special registers */
|
||||
addi a0, a0, SPECREG_OFFSET
|
||||
rsr a2, XT_REG_WINDOWBASE
|
||||
rsr a2, WINDOWBASE
|
||||
s32i a2, a0, 0
|
||||
rsr a2, XT_REG_WINDOWSTART
|
||||
rsr a2, WINDOWSTART
|
||||
s32i a2, a0, 4
|
||||
rsr a2, XT_REG_SAR
|
||||
rsr a2, SAR
|
||||
s32i a2, a0, 8
|
||||
rsr a2, XT_REG_LBEG
|
||||
rsr a2, LBEG
|
||||
s32i a2, a0, 12
|
||||
rsr a2, XT_REG_LEND
|
||||
rsr a2, LEND
|
||||
s32i a2, a0, 16
|
||||
rsr a2, XT_REG_LCOUNT
|
||||
rsr a2, LCOUNT
|
||||
s32i a2, a0, 20
|
||||
rsr a2, EPC1
|
||||
s32i a2, a0, 24
|
||||
|
||||
#if CONFIG_ESP32_ECO3_CACHE_LOCK_FIX
|
||||
movi a0, 0
|
||||
xsr a0, XT_REG_INTENABLE /* disable all interrupts */
|
||||
xsr a0, INTENABLE /* disable all interrupts */
|
||||
movi a2, ~(1<<16)
|
||||
and a0, a2, a0
|
||||
wsr a0, XT_REG_INTENABLE
|
||||
wsr a0, INTENABLE
|
||||
#endif
|
||||
|
||||
/* disable exception mode, window overflow */
|
||||
movi a0, PS_INTLEVEL(5) | PS_EXCM
|
||||
wsr a0, XT_REG_PS
|
||||
wsr a0, PS
|
||||
rsync
|
||||
|
||||
/* Save the remaining physical registers.
|
||||
@@ -153,12 +153,12 @@ xt_highint4:
|
||||
/* a0 still points to _l4_save_ctx */
|
||||
|
||||
/* Can clear WINDOWSTART now, all registers are saved */
|
||||
rsr a2, XT_REG_WINDOWBASE
|
||||
rsr a2, WINDOWBASE
|
||||
/* WINDOWSTART = (1 << WINDOWBASE) */
|
||||
movi a3, 1
|
||||
ssl a2
|
||||
sll a3, a3
|
||||
wsr a3, XT_REG_WINDOWSTART
|
||||
wsr a3, WINDOWSTART
|
||||
|
||||
_highint4_stack_switch:
|
||||
movi a0, 0
|
||||
@@ -169,7 +169,7 @@ _highint4_stack_switch:
|
||||
|
||||
/* Set up PS for C, disable all interrupts except NMI and debug, and clear EXCM. */
|
||||
movi a6, PS_INTLEVEL(4) | PS_UM | PS_WOE
|
||||
wsr a6, XT_REG_PS
|
||||
wsr a6, PS
|
||||
rsync
|
||||
|
||||
/* Call C handler */
|
||||
@@ -180,7 +180,7 @@ _highint4_stack_switch:
|
||||
|
||||
/* Done with C handler; re-enable exception mode, disabling window overflow */
|
||||
movi a2, PS_INTLEVEL(5) | PS_EXCM /* TOCHECK */
|
||||
wsr a2, XT_REG_PS
|
||||
wsr a2, PS
|
||||
rsync
|
||||
|
||||
/* Restore the special registers.
|
||||
@@ -188,13 +188,13 @@ _highint4_stack_switch:
|
||||
*/
|
||||
movi a0, _l4_save_ctx + SPECREG_OFFSET
|
||||
l32i a2, a0, 8
|
||||
wsr a2, XT_REG_SAR
|
||||
wsr a2, SAR
|
||||
l32i a2, a0, 12
|
||||
wsr a2, XT_REG_LBEG
|
||||
wsr a2, LBEG
|
||||
l32i a2, a0, 16
|
||||
wsr a2, XT_REG_LEND
|
||||
wsr a2, LEND
|
||||
l32i a2, a0, 20
|
||||
wsr a2, XT_REG_LCOUNT
|
||||
wsr a2, LCOUNT
|
||||
l32i a2, a0, 24
|
||||
wsr a2, EPC1
|
||||
|
||||
@@ -247,12 +247,12 @@ _highint4_stack_switch:
|
||||
movi a0, _l4_save_ctx
|
||||
|
||||
l32i a2, a0, SPECREG_OFFSET + 4
|
||||
wsr a2, XT_REG_WINDOWSTART
|
||||
wsr a2, WINDOWSTART
|
||||
|
||||
l32i a1, a0, 4
|
||||
l32i a2, a0, 8
|
||||
l32i a3, a0, 12
|
||||
rsr a0, XT_REG_EXCSAVE_4 /* holds the value of a0 before the interrupt handler */
|
||||
rsr a0, EXCSAVE_4 /* holds the value of a0 before the interrupt handler */
|
||||
|
||||
/* Return from the interrupt, restoring PS from EPS_4 */
|
||||
rfi 4
|
||||
|
||||
Submodule components/bt/controller/lib_esp32 updated: b0ebfcf639...6d007b7167
@@ -22,14 +22,6 @@ if BLE_MESH
|
||||
for mesh packets. And this could help avoid collision of
|
||||
advertising packets.
|
||||
|
||||
config BLE_MESH_USE_UNIFIED_CRYPTO
|
||||
bool "Use the unified BLE tinycrypt implementation"
|
||||
depends on !BT_LE_CRYPTO_STACK_MBEDTLS && !BT_NIMBLE_CRYPTO_STACK_MBEDTLS
|
||||
default n
|
||||
help
|
||||
Enable this option to use the unified BLE tinycrypt solution
|
||||
instead of the default one in BLE Mesh stack.
|
||||
|
||||
menuconfig BLE_MESH_USE_BLE_50
|
||||
bool "Support using BLE 5.0 APIs for BLE Mesh"
|
||||
depends on BLE_MESH_EXPERIMENTAL
|
||||
|
||||
@@ -1724,11 +1724,9 @@ void btc_avrc_get_profile_status(esp_avrc_profile_status_t *param)
|
||||
if (btc_avrc_ct_init_p()) {
|
||||
param->avrc_ct_inited = true;
|
||||
}
|
||||
#if BTC_AV_CA_INCLUDED
|
||||
if (btc_rc_cb.rc_cover_art_connected) {
|
||||
param->ct_cover_art_conn_num++;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -66,7 +66,7 @@
|
||||
static UINT16 btc_max_hf_clients = BTC_HF_NUM_CB;
|
||||
/* HF Param Definition */
|
||||
#if HFP_DYNAMIC_MEMORY == FALSE
|
||||
static hf_local_param_t hf_local_param;
|
||||
static hf_local_param_t hf_local_param[BTC_HF_NUM_CB];
|
||||
#else
|
||||
hf_local_param_t *hf_local_param_ptr = NULL;
|
||||
#endif
|
||||
@@ -117,7 +117,7 @@ do {
|
||||
if ((idx < 0) || (idx >= BTC_HF_NUM_CB)) { \
|
||||
return BT_STATUS_FAIL; \
|
||||
} \
|
||||
if (!hf_local_param.initialized) { \
|
||||
if (!hf_local_param[idx].btc_hf_cb.initialized) { \
|
||||
BTIF_TRACE_WARNING("CHECK_HF_INIT: %s: HF AG not initialized", __FUNCTION__); \
|
||||
return BT_STATUS_NOT_READY; \
|
||||
} else { \
|
||||
@@ -130,8 +130,8 @@ do {
|
||||
if ((idx < 0) || (idx >= BTC_HF_NUM_CB)) { \
|
||||
return BT_STATUS_FAIL; \
|
||||
} \
|
||||
if (!hf_local_param.initialized || \
|
||||
hf_local_param.btc_hf_cb[idx].connection_state != ESP_HF_CONNECTION_STATE_SLC_CONNECTED) { \
|
||||
if (!hf_local_param[idx].btc_hf_cb.initialized || \
|
||||
hf_local_param[idx].btc_hf_cb.connection_state != ESP_HF_CONNECTION_STATE_SLC_CONNECTED) { \
|
||||
BTIF_TRACE_WARNING("CHECK_HF_SLC_CONNECTED: %s: HF AG SLC not connected", __FUNCTION__); \
|
||||
return BT_STATUS_NOT_READY; \
|
||||
} else { \
|
||||
@@ -141,10 +141,10 @@ do {
|
||||
|
||||
|
||||
#define clear_phone_state() \
|
||||
hf_local_param.btc_hf_cb[idx].call_state = ESP_HF_CALL_STATUS_NO_CALLS; \
|
||||
hf_local_param.btc_hf_cb[idx].call_setup_state = ESP_HF_CALL_SETUP_STATUS_IDLE;\
|
||||
hf_local_param.btc_hf_cb[idx].num_active = 0; \
|
||||
hf_local_param.btc_hf_cb[idx].num_held = 0;
|
||||
hf_local_param[idx].btc_hf_cb.call_state = ESP_HF_CALL_STATUS_NO_CALLS; \
|
||||
hf_local_param[idx].btc_hf_cb.call_setup_state = ESP_HF_CALL_SETUP_STATUS_IDLE;\
|
||||
hf_local_param[idx].btc_hf_cb.num_active = 0; \
|
||||
hf_local_param[idx].btc_hf_cb.num_held = 0;
|
||||
|
||||
#define CHECK_HF_IDX(idx) \
|
||||
do { \
|
||||
@@ -160,7 +160,7 @@ do {
|
||||
static int btc_hf_idx_by_bdaddr(bt_bdaddr_t *bd_addr)
|
||||
{
|
||||
for (int i = 0; i < btc_max_hf_clients; ++i) {
|
||||
if (bdcmp(bd_addr->address, hf_local_param.btc_hf_cb[i].connected_bda.address) == 0) {
|
||||
if (bdcmp(bd_addr->address, hf_local_param[i].btc_hf_cb.connected_bda.address) == 0) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
@@ -170,8 +170,8 @@ static int btc_hf_idx_by_bdaddr(bt_bdaddr_t *bd_addr)
|
||||
static int btc_hf_find_free_idx(void)
|
||||
{
|
||||
for (int idx = 0; idx < btc_max_hf_clients; ++idx) {
|
||||
if (hf_local_param.initialized &&
|
||||
hf_local_param.btc_hf_cb[idx].connection_state == ESP_HF_CONNECTION_STATE_DISCONNECTED) {
|
||||
if (hf_local_param[idx].btc_hf_cb.initialized &&
|
||||
hf_local_param[idx].btc_hf_cb.connection_state == ESP_HF_CONNECTION_STATE_DISCONNECTED) {
|
||||
return idx;
|
||||
}
|
||||
}
|
||||
@@ -180,9 +180,9 @@ static int btc_hf_find_free_idx(void)
|
||||
|
||||
static BOOLEAN is_connected(int idx, bt_bdaddr_t *bd_addr)
|
||||
{
|
||||
if ((bdcmp(bd_addr->address,hf_local_param.btc_hf_cb[idx].connected_bda.address) == 0) &&
|
||||
((hf_local_param.btc_hf_cb[idx].connection_state == ESP_HF_CONNECTION_STATE_CONNECTED) ||
|
||||
(hf_local_param.btc_hf_cb[idx].connection_state == ESP_HF_CONNECTION_STATE_SLC_CONNECTED))) {
|
||||
if ((bdcmp(bd_addr->address,hf_local_param[idx].btc_hf_cb.connected_bda.address) == 0) &&
|
||||
((hf_local_param[idx].btc_hf_cb.connection_state == ESP_HF_CONNECTION_STATE_CONNECTED) ||
|
||||
(hf_local_param[idx].btc_hf_cb.connection_state == ESP_HF_CONNECTION_STATE_SLC_CONNECTED))) {
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
@@ -196,9 +196,9 @@ static int btc_hf_latest_connected_idx(void)
|
||||
conn_time_delta.tv_sec = now.tv_sec;
|
||||
|
||||
for (int i = 0; i < btc_max_hf_clients; i++) {
|
||||
if (hf_local_param.btc_hf_cb[i].connection_state == ESP_HF_CONNECTION_STATE_SLC_CONNECTED) {
|
||||
if ((now.tv_sec - hf_local_param.btc_hf_cb[i].connected_timestamp.tv_sec) < conn_time_delta.tv_sec) {
|
||||
conn_time_delta.tv_sec = now.tv_sec - hf_local_param.btc_hf_cb[i].connected_timestamp.tv_sec;
|
||||
if (hf_local_param[i].btc_hf_cb.connection_state == ESP_HF_CONNECTION_STATE_SLC_CONNECTED) {
|
||||
if ((now.tv_sec - hf_local_param[i].btc_hf_cb.connected_timestamp.tv_sec) < conn_time_delta.tv_sec) {
|
||||
conn_time_delta.tv_sec = now.tv_sec - hf_local_param[i].btc_hf_cb.connected_timestamp.tv_sec;
|
||||
latest_conn_idx = i;
|
||||
}
|
||||
}
|
||||
@@ -264,24 +264,24 @@ static void bte_hf_evt(tBTA_AG_EVT event, tBTA_AG *param)
|
||||
************************************************************************************/
|
||||
void btc_hf_reg_data_cb(esp_hf_incoming_data_cb_t recv, esp_hf_outgoing_data_cb_t send)
|
||||
{
|
||||
hf_local_param.btc_hf_incoming_data_cb = recv;
|
||||
hf_local_param.btc_hf_outgoing_data_cb = send;
|
||||
hf_local_param[0].btc_hf_incoming_data_cb = recv;
|
||||
hf_local_param[0].btc_hf_outgoing_data_cb = send;
|
||||
}
|
||||
|
||||
void btc_hf_reg_audio_data_cb(esp_hf_ag_audio_data_cb_t callback)
|
||||
{
|
||||
hf_local_param.btc_hf_audio_data_cb = callback;
|
||||
hf_local_param[0].btc_hf_audio_data_cb = callback;
|
||||
}
|
||||
|
||||
void btc_hf_audio_data_cb_to_app(uint8_t *buf, uint8_t *data, uint16_t len, bool is_bad_frame)
|
||||
{
|
||||
if (hf_local_param.btc_hf_audio_data_cb) {
|
||||
if (hf_local_param[0].btc_hf_audio_data_cb) {
|
||||
/* we always have sizeof(BT_HDR) bytes free space before data, it is enough for esp_hf_audio_buff_t */
|
||||
esp_hf_audio_buff_t *audio_buff = (esp_hf_audio_buff_t *)buf;
|
||||
audio_buff->buff_size = len;
|
||||
audio_buff->data_len = len;
|
||||
audio_buff->data = data;
|
||||
hf_local_param.btc_hf_audio_data_cb(hf_local_param.btc_hf_cb[0].sync_conn_hdl, audio_buff, is_bad_frame);
|
||||
hf_local_param[0].btc_hf_audio_data_cb(hf_local_param[0].btc_hf_cb.sync_conn_hdl, audio_buff, is_bad_frame);
|
||||
}
|
||||
else {
|
||||
osi_free(buf);
|
||||
@@ -290,17 +290,19 @@ void btc_hf_audio_data_cb_to_app(uint8_t *buf, uint8_t *data, uint16_t len, bool
|
||||
|
||||
void btc_hf_incoming_data_cb_to_app(const uint8_t *data, uint32_t len)
|
||||
{
|
||||
int idx = 0;
|
||||
// todo: critical section protection
|
||||
if (hf_local_param.btc_hf_incoming_data_cb) {
|
||||
hf_local_param.btc_hf_incoming_data_cb(data, len);
|
||||
if (hf_local_param[idx].btc_hf_incoming_data_cb) {
|
||||
hf_local_param[idx].btc_hf_incoming_data_cb(data, len);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t btc_hf_outgoing_data_cb_to_app(uint8_t *data, uint32_t len)
|
||||
{
|
||||
int idx = 0;
|
||||
// todo: critical section protection
|
||||
if (hf_local_param.btc_hf_outgoing_data_cb) {
|
||||
return hf_local_param.btc_hf_outgoing_data_cb(data, len);
|
||||
if (hf_local_param[idx].btc_hf_outgoing_data_cb) {
|
||||
return hf_local_param[idx].btc_hf_outgoing_data_cb(data, len);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
@@ -319,7 +321,7 @@ bt_status_t btc_hf_execute_service(BOOLEAN b_enable)
|
||||
} else {
|
||||
/* De-register AG */
|
||||
for (idx = 0; idx < btc_max_hf_clients; idx++) {
|
||||
BTA_AgDeregister(hf_local_param.btc_hf_cb[idx].handle);
|
||||
BTA_AgDeregister(hf_local_param[idx].btc_hf_cb.handle);
|
||||
}
|
||||
/* Disable AG */
|
||||
BTA_AgDisable();
|
||||
@@ -337,29 +339,30 @@ bt_status_t btc_hf_init(void)
|
||||
{
|
||||
int idx = 0;
|
||||
|
||||
if (hf_local_param.initialized) {
|
||||
esp_hf_cb_param_t param = {
|
||||
.prof_stat.state = ESP_HF_INIT_ALREADY,
|
||||
};
|
||||
btc_hf_cb_to_app(ESP_HF_PROF_STATE_EVT, ¶m);
|
||||
return BT_STATUS_SUCCESS;
|
||||
#if HFP_DYNAMIC_MEMORY == TRUE
|
||||
if (hf_local_param)
|
||||
#endif
|
||||
{
|
||||
if (hf_local_param[idx].btc_hf_cb.initialized) {
|
||||
esp_hf_cb_param_t param = {
|
||||
.prof_stat.state = ESP_HF_INIT_ALREADY,
|
||||
};
|
||||
btc_hf_cb_to_app(ESP_HF_PROF_STATE_EVT, ¶m);
|
||||
return BT_STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
BTC_TRACE_DEBUG("%s - max_hf_clients=%d", __func__, btc_max_hf_clients);
|
||||
|
||||
if (hf_local_param.btc_hf_cb == NULL) {
|
||||
hf_local_param.btc_hf_cb = (btc_hf_cb_t *)osi_malloc(BTC_HF_NUM_CB * sizeof(btc_hf_cb_t));
|
||||
if (hf_local_param.btc_hf_cb == NULL) {
|
||||
#if HFP_DYNAMIC_MEMORY == TRUE
|
||||
if (hf_local_param == NULL) {
|
||||
if ((hf_local_param = (hf_local_param_t *)osi_malloc(BTC_HF_NUM_CB * sizeof(hf_local_param_t))) == NULL) {
|
||||
BTC_TRACE_ERROR("%s malloc failed!", __func__);
|
||||
return BT_STATUS_NOMEM;
|
||||
}
|
||||
}
|
||||
|
||||
memset(hf_local_param.btc_hf_cb, 0, BTC_HF_NUM_CB * sizeof(btc_hf_cb_t));
|
||||
for (int i = 0; i < BTC_HF_NUM_CB; i++) {
|
||||
hf_local_param.btc_hf_cb[i].sync_conn_hdl = ESP_INVALID_CONN_HANDLE;
|
||||
}
|
||||
hf_local_param.hf_idx = BTC_HF_INVALID_IDX;
|
||||
memset((void *)hf_local_param, 0, BTC_HF_NUM_CB * sizeof(hf_local_param_t));
|
||||
#endif
|
||||
|
||||
/* Invoke the enable service API to the core to set the appropriate service_id
|
||||
* Internally, the HSP_SERVICE_ID shall also be enabled if HFP is enabled (phone)
|
||||
@@ -370,7 +373,10 @@ bt_status_t btc_hf_init(void)
|
||||
btc_dm_enable_service(BTA_HSP_SERVICE_ID);
|
||||
#endif
|
||||
clear_phone_state();
|
||||
|
||||
memset(&hf_local_param[idx].btc_hf_cb, 0, sizeof(btc_hf_cb_t));
|
||||
for (int i = 0; i < BTC_HF_NUM_CB; i++) {
|
||||
hf_local_param[i].btc_hf_cb.sync_conn_hdl = ESP_INVALID_CONN_HANDLE;
|
||||
}
|
||||
// set audio path
|
||||
#if (BT_CONTROLLER_INCLUDED == TRUE)
|
||||
#if BTM_SCO_HCI_INCLUDED
|
||||
@@ -388,12 +394,19 @@ void btc_hf_deinit(void)
|
||||
{
|
||||
BTC_TRACE_EVENT("%s", __FUNCTION__);
|
||||
|
||||
if (!hf_local_param.initialized) {
|
||||
esp_hf_cb_param_t param = {
|
||||
.prof_stat.state = ESP_HF_DEINIT_ALREADY,
|
||||
};
|
||||
btc_hf_cb_to_app(ESP_HF_PROF_STATE_EVT, ¶m);
|
||||
return;
|
||||
int idx = 0;
|
||||
|
||||
#if HFP_DYNAMIC_MEMORY == TRUE
|
||||
if (hf_local_param)
|
||||
#endif
|
||||
{
|
||||
if (!hf_local_param[idx].btc_hf_cb.initialized) {
|
||||
esp_hf_cb_param_t param = {
|
||||
.prof_stat.state = ESP_HF_DEINIT_ALREADY,
|
||||
};
|
||||
btc_hf_cb_to_app(ESP_HF_PROF_STATE_EVT, ¶m);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
btc_dm_disable_service(BTA_HFP_SERVICE_ID);
|
||||
@@ -401,8 +414,12 @@ void btc_hf_deinit(void)
|
||||
|
||||
static void btc_hf_cb_release(void)
|
||||
{
|
||||
osi_free(hf_local_param.btc_hf_cb);
|
||||
hf_local_param.btc_hf_cb = NULL;
|
||||
#if HFP_DYNAMIC_MEMORY == TRUE
|
||||
if (hf_local_param) {
|
||||
osi_free(hf_local_param);
|
||||
hf_local_param = NULL;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static bt_status_t connect_init(bt_bdaddr_t *bd_addr, uint16_t uuid)
|
||||
@@ -414,9 +431,9 @@ static bt_status_t connect_init(bt_bdaddr_t *bd_addr, uint16_t uuid)
|
||||
}
|
||||
|
||||
if (!is_connected(idx, bd_addr)) {
|
||||
hf_local_param.btc_hf_cb[idx].connection_state = ESP_HF_CONNECTION_STATE_CONNECTING;
|
||||
bdcpy(hf_local_param.btc_hf_cb[idx].connected_bda.address, bd_addr->address);
|
||||
BTA_AgOpen(hf_local_param.btc_hf_cb[idx].handle, hf_local_param.btc_hf_cb[idx].connected_bda.address, BTC_HF_SECURITY, BTC_HF_SERVICES);
|
||||
hf_local_param[idx].btc_hf_cb.connection_state = ESP_HF_CONNECTION_STATE_CONNECTING;
|
||||
bdcpy(hf_local_param[idx].btc_hf_cb.connected_bda.address, bd_addr->address);
|
||||
BTA_AgOpen(hf_local_param[idx].btc_hf_cb.handle, hf_local_param[idx].btc_hf_cb.connected_bda.address, BTC_HF_SECURITY, BTC_HF_SERVICES);
|
||||
return BT_STATUS_SUCCESS;
|
||||
}
|
||||
return BT_STATUS_BUSY;
|
||||
@@ -436,7 +453,7 @@ bt_status_t btc_hf_disconnect(bt_bdaddr_t *bd_addr)
|
||||
}
|
||||
|
||||
if (is_connected(idx, bd_addr)) {
|
||||
BTA_AgClose(hf_local_param.btc_hf_cb[idx].handle);
|
||||
BTA_AgClose(hf_local_param[idx].btc_hf_cb.handle);
|
||||
return BT_STATUS_SUCCESS;
|
||||
}
|
||||
return BT_STATUS_FAIL;
|
||||
@@ -448,13 +465,13 @@ bt_status_t btc_hf_connect_audio(bt_bdaddr_t *bd_addr)
|
||||
CHECK_HF_SLC_CONNECTED(idx);
|
||||
|
||||
if (is_connected(idx, bd_addr)) {
|
||||
BTA_AgAudioOpen(hf_local_param.btc_hf_cb[idx].handle);
|
||||
BTA_AgAudioOpen(hf_local_param[idx].btc_hf_cb.handle);
|
||||
/* Inform the application that the audio connection has been initiated successfully */
|
||||
do {
|
||||
esp_hf_cb_param_t param;
|
||||
memset(¶m, 0, sizeof(esp_hf_cb_param_t));
|
||||
param.audio_stat.state = ESP_HF_AUDIO_STATE_CONNECTING;
|
||||
memcpy(param.audio_stat.remote_addr, &hf_local_param.btc_hf_cb[idx].connected_bda, sizeof(esp_bd_addr_t));
|
||||
memcpy(param.audio_stat.remote_addr, &hf_local_param[idx].btc_hf_cb.connected_bda, sizeof(esp_bd_addr_t));
|
||||
btc_hf_cb_to_app(ESP_HF_AUDIO_STATE_EVT, ¶m);
|
||||
} while (0);
|
||||
return BT_STATUS_SUCCESS;
|
||||
@@ -468,7 +485,7 @@ bt_status_t btc_hf_disconnect_audio(bt_bdaddr_t *bd_addr)
|
||||
CHECK_HF_SLC_CONNECTED(idx);
|
||||
|
||||
if (is_connected(idx, bd_addr)) {
|
||||
BTA_AgAudioClose(hf_local_param.btc_hf_cb[idx].handle);
|
||||
BTA_AgAudioClose(hf_local_param[idx].btc_hf_cb.handle);
|
||||
return BT_STATUS_SUCCESS;
|
||||
}
|
||||
return BT_STATUS_FAIL;
|
||||
@@ -482,7 +499,7 @@ static bt_status_t btc_hf_pkt_stat_nums_get(UINT16 sync_conn_handle)
|
||||
CHECK_HF_SLC_CONNECTED(idx);
|
||||
|
||||
if (idx != BTC_HF_INVALID_IDX) {
|
||||
BTA_AgPktStatsNumsGet(hf_local_param.btc_hf_cb[idx].handle, sync_conn_handle);
|
||||
BTA_AgPktStatsNumsGet(hf_local_param[idx].btc_hf_cb.handle, sync_conn_handle);
|
||||
status = BT_STATUS_SUCCESS;
|
||||
}
|
||||
#endif /*#if (BTM_SCO_HCI_INCLUDED == TRUE) */
|
||||
@@ -499,11 +516,11 @@ static bt_status_t btc_hf_vra(bt_bdaddr_t *bd_addr, esp_hf_vr_state_t value)
|
||||
CHECK_HF_SLC_CONNECTED(idx);
|
||||
|
||||
if (is_connected(idx, bd_addr)) {
|
||||
if (hf_local_param.btc_hf_cb[idx].peer_feat & BTA_AG_PEER_FEAT_VREC) {
|
||||
if (hf_local_param[idx].btc_hf_cb.peer_feat & BTA_AG_PEER_FEAT_VREC) {
|
||||
tBTA_AG_RES_DATA ag_res;
|
||||
memset(&ag_res, 0, sizeof(ag_res));
|
||||
ag_res.state = value;
|
||||
BTA_AgResult(hf_local_param.btc_hf_cb[idx].handle, BTA_AG_BVRA_RES, &ag_res);
|
||||
BTA_AgResult(hf_local_param[idx].btc_hf_cb.handle, BTA_AG_BVRA_RES, &ag_res);
|
||||
return BT_STATUS_SUCCESS;
|
||||
} else {
|
||||
return BT_STATUS_UNSUPPORTED;
|
||||
@@ -521,7 +538,7 @@ static bt_status_t btc_hf_volume_control(bt_bdaddr_t *bd_addr, esp_hf_volume_typ
|
||||
|
||||
if (is_connected(idx, bd_addr)) {
|
||||
ag_res.num = volume;
|
||||
BTA_AgResult(hf_local_param.btc_hf_cb[idx].handle, (type == ESP_HF_VOLUME_TYPE_SPK) ? BTA_AG_SPK_RES : BTA_AG_MIC_RES, &ag_res);
|
||||
BTA_AgResult(hf_local_param[idx].btc_hf_cb.handle, (type == ESP_HF_VOLUME_TYPE_SPK) ? BTA_AG_SPK_RES : BTA_AG_MIC_RES, &ag_res);
|
||||
return BT_STATUS_SUCCESS;
|
||||
}
|
||||
return BT_STATUS_FAIL;
|
||||
@@ -545,7 +562,7 @@ static bt_status_t btc_hf_unat_response(bt_bdaddr_t *bd_addr, const char *unat)
|
||||
ag_res.errcode = BTA_AG_ERR_OP_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
BTA_AgResult(hf_local_param.btc_hf_cb[idx].handle, BTA_AG_UNAT_RES, &ag_res);
|
||||
BTA_AgResult(hf_local_param[idx].btc_hf_cb.handle, BTA_AG_UNAT_RES, &ag_res);
|
||||
return BT_STATUS_SUCCESS;
|
||||
}
|
||||
return BT_STATUS_FAIL;
|
||||
@@ -566,7 +583,7 @@ static bt_status_t btc_hf_cmee_response(bt_bdaddr_t *bd_addr, esp_hf_at_response
|
||||
ag_res.ok_flag = BTA_AG_OK_ERROR;
|
||||
ag_res.errcode = error_code;
|
||||
}
|
||||
BTA_AgResult(hf_local_param.btc_hf_cb[idx].handle, BTA_AG_UNAT_RES, &ag_res);
|
||||
BTA_AgResult(hf_local_param[idx].btc_hf_cb.handle, BTA_AG_UNAT_RES, &ag_res);
|
||||
return BT_STATUS_SUCCESS;
|
||||
}
|
||||
return BT_STATUS_FAIL;
|
||||
@@ -627,7 +644,7 @@ static bt_status_t btc_hf_cind_response(bt_bdaddr_t *bd_addr,
|
||||
batt_lev, /* Battery level */
|
||||
call_held_status /* Callheld state */
|
||||
);
|
||||
BTA_AgResult(hf_local_param.btc_hf_cb[idx].handle, BTA_AG_CIND_RES, &ag_res);
|
||||
BTA_AgResult(hf_local_param[idx].btc_hf_cb.handle, BTA_AG_CIND_RES, &ag_res);
|
||||
return BT_STATUS_SUCCESS;
|
||||
}
|
||||
return BT_STATUS_FAIL;
|
||||
@@ -645,7 +662,7 @@ static bt_status_t btc_hf_cops_response(bt_bdaddr_t *bd_addr, const char *name)
|
||||
/* Format the response */
|
||||
sprintf(ag_res.str, "0,0,\"%s\"", name);
|
||||
ag_res.ok_flag = BTA_AG_OK_DONE;
|
||||
BTA_AgResult(hf_local_param.btc_hf_cb[idx].handle, BTA_AG_COPS_RES, &ag_res);
|
||||
BTA_AgResult(hf_local_param[idx].btc_hf_cb.handle, BTA_AG_COPS_RES, &ag_res);
|
||||
return BT_STATUS_SUCCESS;
|
||||
}
|
||||
return BT_STATUS_FAIL;
|
||||
@@ -677,7 +694,7 @@ static bt_status_t btc_hf_clcc_response(bt_bdaddr_t *bd_addr, int index, esp_hf_
|
||||
}
|
||||
}
|
||||
}
|
||||
BTA_AgResult(hf_local_param.btc_hf_cb[idx].handle, BTA_AG_CLCC_RES, &ag_res);
|
||||
BTA_AgResult(hf_local_param[idx].btc_hf_cb.handle, BTA_AG_CLCC_RES, &ag_res);
|
||||
return BT_STATUS_SUCCESS;
|
||||
}
|
||||
return BT_STATUS_FAIL;
|
||||
@@ -699,7 +716,7 @@ static bt_status_t btc_hf_cnum_response(bt_bdaddr_t *bd_addr, const char *number
|
||||
sprintf(ag_res.str, ",\"%s\",%d,,",number, number_type);
|
||||
}
|
||||
ag_res.ok_flag = BTA_AG_OK_DONE;
|
||||
BTA_AgResult(hf_local_param.btc_hf_cb[idx].handle, BTA_AG_CNUM_RES, &ag_res);
|
||||
BTA_AgResult(hf_local_param[idx].btc_hf_cb.handle, BTA_AG_CNUM_RES, &ag_res);
|
||||
return BT_STATUS_SUCCESS;
|
||||
}
|
||||
return BT_STATUS_FAIL;
|
||||
@@ -715,7 +732,7 @@ static bt_status_t btc_hf_inband_ring(bt_bdaddr_t *bd_addr, esp_hf_in_band_ring_
|
||||
tBTA_AG_RES_DATA ag_res;
|
||||
memset (&ag_res, 0, sizeof (ag_res));
|
||||
ag_res.state = state;
|
||||
BTA_AgResult(hf_local_param.btc_hf_cb[idx].handle, BTA_AG_INBAND_RING_RES, &ag_res);
|
||||
BTA_AgResult(hf_local_param[idx].btc_hf_cb.handle, BTA_AG_INBAND_RING_RES, &ag_res);
|
||||
return BT_STATUS_SUCCESS;
|
||||
}
|
||||
return BT_STATUS_FAIL;
|
||||
@@ -733,8 +750,8 @@ static bt_status_t btc_hf_phone_state_update(bt_bdaddr_t *bd_addr,int num_active
|
||||
int idx = btc_hf_idx_by_bdaddr(bd_addr), i;
|
||||
|
||||
/* hf_idx is index of connected HS that sent ATA/BLDN, otherwise index of latest connected HS */
|
||||
if (hf_local_param.hf_idx != BTC_HF_INVALID_IDX) {
|
||||
idx = hf_local_param.hf_idx;
|
||||
if (hf_local_param->hf_idx != BTC_HF_INVALID_IDX) {
|
||||
idx = hf_local_param->hf_idx;
|
||||
} else {
|
||||
idx = btc_hf_latest_connected_idx();
|
||||
}
|
||||
@@ -742,28 +759,28 @@ static bt_status_t btc_hf_phone_state_update(bt_bdaddr_t *bd_addr,int num_active
|
||||
BTC_TRACE_DEBUG("phone_state_change: idx = %d", idx);
|
||||
CHECK_HF_SLC_CONNECTED(idx);
|
||||
BTC_TRACE_DEBUG("phone_state_change: num_active=%d [prev: %d] num_held=%d[prev: %d] call =%s [prev: %s] call_setup=%s [prev: %s]",
|
||||
num_active, hf_local_param.btc_hf_cb[idx].num_active,
|
||||
num_held, hf_local_param.btc_hf_cb[idx].num_held,
|
||||
dump_hf_call_state(call_state), dump_hf_call_state(hf_local_param.btc_hf_cb[idx].call_state),
|
||||
dump_hf_call_setup_state(call_setup_state), dump_hf_call_setup_state(hf_local_param.btc_hf_cb[idx].call_setup_state));
|
||||
num_active, hf_local_param[idx].btc_hf_cb.num_active,
|
||||
num_held, hf_local_param[idx].btc_hf_cb.num_held,
|
||||
dump_hf_call_state(call_state), dump_hf_call_state(hf_local_param[idx].btc_hf_cb.call_state),
|
||||
dump_hf_call_setup_state(call_setup_state), dump_hf_call_setup_state(hf_local_param[idx].btc_hf_cb.call_setup_state));
|
||||
|
||||
/* If all indicators are 0, send end call and return */
|
||||
if (num_active == 0 && num_held == 0 && call_state == ESP_HF_CALL_STATUS_NO_CALLS && call_setup_state == ESP_HF_CALL_SETUP_STATUS_IDLE) {
|
||||
BTC_TRACE_DEBUG("%s: Phone on hook", __FUNCTION__);
|
||||
|
||||
/* Record call termination timestamp if there was an active/held call or call_setup_state > ESP_HF_CALL_SETUP_STATUS_IDLE */
|
||||
if ((hf_local_param.btc_hf_cb[idx].call_state != ESP_HF_CALL_STATUS_NO_CALLS) ||
|
||||
(hf_local_param.btc_hf_cb[idx].call_setup_state != ESP_HF_CALL_SETUP_STATUS_IDLE) ||
|
||||
(hf_local_param.btc_hf_cb[idx].num_active) ||
|
||||
(hf_local_param.btc_hf_cb[idx].num_held)) {
|
||||
if ((hf_local_param[idx].btc_hf_cb.call_state != ESP_HF_CALL_STATUS_NO_CALLS) ||
|
||||
(hf_local_param[idx].btc_hf_cb.call_setup_state != ESP_HF_CALL_SETUP_STATUS_IDLE) ||
|
||||
(hf_local_param[idx].btc_hf_cb.num_active) ||
|
||||
(hf_local_param[idx].btc_hf_cb.num_held)) {
|
||||
BTC_TRACE_DEBUG("%s: Record call termination timestamp", __FUNCTION__);
|
||||
clock_gettime(CLOCK_MONOTONIC, &hf_local_param.btc_hf_cb[idx].call_end_timestamp);
|
||||
clock_gettime(CLOCK_MONOTONIC, &hf_local_param[0].btc_hf_cb.call_end_timestamp);
|
||||
}
|
||||
BTA_AgResult(BTA_AG_HANDLE_ALL, BTA_AG_END_CALL_RES, NULL);
|
||||
hf_local_param.hf_idx = BTC_HF_INVALID_IDX;
|
||||
hf_local_param->hf_idx = BTC_HF_INVALID_IDX;
|
||||
|
||||
/* If held call was present, reset that as well. */
|
||||
if (hf_local_param.btc_hf_cb[idx].num_held) {
|
||||
if (hf_local_param[idx].btc_hf_cb.num_held) {
|
||||
send_indicator_update(BTA_AG_IND_CALLHELD, 0);
|
||||
}
|
||||
goto update_call_states;
|
||||
@@ -777,13 +794,13 @@ static bt_status_t btc_hf_phone_state_update(bt_bdaddr_t *bd_addr,int num_active
|
||||
|
||||
/* Handle case(3) here prior to call setup handling.*/
|
||||
if (((num_active + num_held) > 0) &&
|
||||
(hf_local_param.btc_hf_cb[idx].num_active == 0) &&
|
||||
(hf_local_param.btc_hf_cb[idx].num_held == 0) &&
|
||||
(hf_local_param.btc_hf_cb[idx].call_setup_state == ESP_HF_CALL_SETUP_STATUS_IDLE)) {
|
||||
(hf_local_param[idx].btc_hf_cb.num_active == 0) &&
|
||||
(hf_local_param[idx].btc_hf_cb.num_held == 0) &&
|
||||
(hf_local_param[idx].btc_hf_cb.call_setup_state == ESP_HF_CALL_SETUP_STATUS_IDLE)) {
|
||||
BTC_TRACE_DEBUG("%s: Active/Held call notification received without call setup update", __FUNCTION__);
|
||||
|
||||
memset(&ag_res, 0, sizeof(tBTA_AG_RES_DATA));
|
||||
ag_res.audio_handle = hf_local_param.btc_hf_cb[idx].handle;
|
||||
ag_res.audio_handle = hf_local_param[idx].btc_hf_cb.handle;
|
||||
|
||||
/* Addition callsetup with the Active call. */
|
||||
if (call_setup_state != ESP_HF_CALL_SETUP_STATUS_IDLE) {
|
||||
@@ -799,9 +816,9 @@ static bt_status_t btc_hf_phone_state_update(bt_bdaddr_t *bd_addr,int num_active
|
||||
}
|
||||
|
||||
/* Handle call_setup indicator change. */
|
||||
if (call_setup_state != hf_local_param.btc_hf_cb[idx].call_setup_state) {
|
||||
if (call_setup_state != hf_local_param[idx].btc_hf_cb.call_setup_state) {
|
||||
BTC_TRACE_DEBUG("%s: Call setup states changed. old: %s new: %s", __FUNCTION__,
|
||||
dump_hf_call_setup_state(hf_local_param.btc_hf_cb[idx].call_setup_state),
|
||||
dump_hf_call_setup_state(hf_local_param[idx].btc_hf_cb.call_setup_state),
|
||||
dump_hf_call_setup_state(call_setup_state));
|
||||
memset(&ag_res, 0, sizeof(tBTA_AG_RES_DATA));
|
||||
|
||||
@@ -809,14 +826,14 @@ static bt_status_t btc_hf_phone_state_update(bt_bdaddr_t *bd_addr,int num_active
|
||||
{
|
||||
case ESP_HF_CALL_SETUP_STATUS_IDLE:
|
||||
{
|
||||
switch(hf_local_param.btc_hf_cb[idx].call_setup_state)
|
||||
switch(hf_local_param[idx].btc_hf_cb.call_setup_state)
|
||||
{
|
||||
case ESP_HF_CALL_SETUP_STATUS_INCOMING:
|
||||
{
|
||||
if (num_active > hf_local_param.btc_hf_cb[idx].num_active) {
|
||||
if (num_active > hf_local_param[idx].btc_hf_cb.num_active) {
|
||||
res = BTA_AG_IN_CALL_CONN_RES;
|
||||
ag_res.audio_handle = hf_local_param.btc_hf_cb[idx].handle;
|
||||
} else if (num_held > hf_local_param.btc_hf_cb[idx].num_held) {
|
||||
ag_res.audio_handle = hf_local_param[idx].btc_hf_cb.handle;
|
||||
} else if (num_held > hf_local_param[idx].btc_hf_cb.num_held) {
|
||||
res = BTA_AG_IN_CALL_HELD_RES;
|
||||
} else {
|
||||
res = BTA_AG_CALL_CANCEL_RES;
|
||||
@@ -827,7 +844,7 @@ static bt_status_t btc_hf_phone_state_update(bt_bdaddr_t *bd_addr,int num_active
|
||||
case ESP_HF_CALL_SETUP_STATUS_OUTGOING_DIALING:
|
||||
case ESP_HF_CALL_SETUP_STATUS_OUTGOING_ALERTING:
|
||||
{
|
||||
if (num_active > hf_local_param.btc_hf_cb[idx].num_active) {
|
||||
if (num_active > hf_local_param[idx].btc_hf_cb.num_active) {
|
||||
res = BTA_AG_OUT_CALL_CONN_RES;
|
||||
ag_res.audio_handle = BTA_AG_HANDLE_SCO_NO_CHANGE;
|
||||
} else {
|
||||
@@ -870,7 +887,7 @@ static bt_status_t btc_hf_phone_state_update(bt_bdaddr_t *bd_addr,int num_active
|
||||
case ESP_HF_CALL_SETUP_STATUS_OUTGOING_DIALING:
|
||||
{
|
||||
if (!(num_active + num_held)) {
|
||||
ag_res.audio_handle = hf_local_param.btc_hf_cb[idx].handle;
|
||||
ag_res.audio_handle = hf_local_param[idx].btc_hf_cb.handle;
|
||||
}
|
||||
res = BTA_AG_OUT_CALL_ORIG_RES;
|
||||
break;
|
||||
@@ -878,9 +895,9 @@ static bt_status_t btc_hf_phone_state_update(bt_bdaddr_t *bd_addr,int num_active
|
||||
|
||||
case ESP_HF_CALL_SETUP_STATUS_OUTGOING_ALERTING:
|
||||
{
|
||||
if ((hf_local_param.btc_hf_cb[idx].call_setup_state == ESP_HF_CALL_SETUP_STATUS_IDLE) &&
|
||||
if ((hf_local_param[idx].btc_hf_cb.call_setup_state == ESP_HF_CALL_SETUP_STATUS_IDLE) &&
|
||||
!(num_active + num_held)) {
|
||||
ag_res.audio_handle = hf_local_param.btc_hf_cb[idx].handle;
|
||||
ag_res.audio_handle = hf_local_param[idx].btc_hf_cb.handle;
|
||||
/* Force SCO setup here.*/
|
||||
BTA_AgAudioOpen(ag_res.audio_handle);
|
||||
}
|
||||
@@ -910,34 +927,34 @@ static bt_status_t btc_hf_phone_state_update(bt_bdaddr_t *bd_addr,int num_active
|
||||
|
||||
/* Handle call_state indicator change. */
|
||||
if (!activeCallUpdated &&
|
||||
((num_active + num_held) != (hf_local_param.btc_hf_cb[idx].num_active + hf_local_param.btc_hf_cb[idx].num_held))) {
|
||||
BTC_TRACE_DEBUG("%s: Active call states changed. old: %d new: %d", __FUNCTION__, hf_local_param.btc_hf_cb[idx].num_active, num_active);
|
||||
((num_active + num_held) != (hf_local_param[idx].btc_hf_cb.num_active + hf_local_param[idx].btc_hf_cb.num_held))) {
|
||||
BTC_TRACE_DEBUG("%s: Active call states changed. old: %d new: %d", __FUNCTION__, hf_local_param[idx].btc_hf_cb.num_active, num_active);
|
||||
send_indicator_update(BTA_AG_IND_CALL, ((num_active + num_held) > 0) ? 1 : 0);
|
||||
}
|
||||
|
||||
/* Handle call_held_state indicator change. */
|
||||
if (num_held != hf_local_param.btc_hf_cb[idx].num_held ||
|
||||
((num_active == 0) && ((num_held + hf_local_param.btc_hf_cb[idx].num_held) > 1))) {
|
||||
BTC_TRACE_DEBUG("%s: Held call states changed. old: %d new: %d", __FUNCTION__, hf_local_param.btc_hf_cb[idx].num_held, num_held);
|
||||
if (num_held != hf_local_param[idx].btc_hf_cb.num_held ||
|
||||
((num_active == 0) && ((num_held + hf_local_param[idx].btc_hf_cb.num_held) > 1))) {
|
||||
BTC_TRACE_DEBUG("%s: Held call states changed. old: %d new: %d", __FUNCTION__, hf_local_param[idx].btc_hf_cb.num_held, num_held);
|
||||
send_indicator_update(BTA_AG_IND_CALLHELD, ((num_held == 0) ? 0 : ((num_active == 0) ? 2 : 1)));
|
||||
}
|
||||
|
||||
/* Handle Call Active/Held Swap indicator update.*/
|
||||
if ((call_setup_state == hf_local_param.btc_hf_cb[idx].call_setup_state) &&
|
||||
if ((call_setup_state == hf_local_param[idx].btc_hf_cb.call_setup_state) &&
|
||||
(num_active) &&
|
||||
(num_held) &&
|
||||
(num_active == hf_local_param.btc_hf_cb[idx].num_active) &&
|
||||
(num_held == hf_local_param.btc_hf_cb[idx].num_held)) {
|
||||
(num_active == hf_local_param[idx].btc_hf_cb.num_active) &&
|
||||
(num_held == hf_local_param[idx].btc_hf_cb.num_held)) {
|
||||
BTC_TRACE_DEBUG("%s: Calls swapped", __FUNCTION__);
|
||||
send_indicator_update(BTA_AG_IND_CALLHELD, 1);
|
||||
}
|
||||
|
||||
update_call_states:
|
||||
for (i = 0; i < btc_max_hf_clients; i++) {
|
||||
hf_local_param.btc_hf_cb[i].num_active = num_active;
|
||||
hf_local_param.btc_hf_cb[i].num_held = num_held;
|
||||
hf_local_param.btc_hf_cb[i].call_state = call_state;
|
||||
hf_local_param.btc_hf_cb[i].call_setup_state = call_setup_state;
|
||||
hf_local_param[i].btc_hf_cb.num_active = num_active;
|
||||
hf_local_param[i].btc_hf_cb.num_held = num_held;
|
||||
hf_local_param[i].btc_hf_cb.call_state = call_state;
|
||||
hf_local_param[i].btc_hf_cb.call_setup_state = call_setup_state;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
@@ -950,7 +967,7 @@ bt_status_t btc_hf_ci_sco_data(void)
|
||||
CHECK_HF_SLC_CONNECTED(idx);
|
||||
|
||||
if (idx != BTC_HF_INVALID_IDX) {
|
||||
BTA_AgCiData(hf_local_param.btc_hf_cb[idx].handle);
|
||||
BTA_AgCiData(hf_local_param[idx].btc_hf_cb.handle);
|
||||
return status;
|
||||
}
|
||||
status = BT_STATUS_FAIL;
|
||||
@@ -965,7 +982,7 @@ bool btc_hf_ag_audio_data_send(uint16_t sync_conn_hdl, uint8_t *p_buff_start, ui
|
||||
int idx = btc_hf_latest_connected_idx();
|
||||
CHECK_HF_SLC_CONNECTED(idx);
|
||||
if (idx != BTC_HF_INVALID_IDX) {
|
||||
BTA_AgAudioDataSend(hf_local_param.btc_hf_cb[idx].handle, p_buff_start, p_data, data_len);
|
||||
BTA_AgAudioDataSend(hf_local_param[idx].btc_hf_cb.handle, p_buff_start, p_data, data_len);
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
@@ -1325,11 +1342,17 @@ void btc_hf_cb_handler(btc_msg_t *msg)
|
||||
break;
|
||||
case BTA_AG_DISABLE_EVT:
|
||||
{
|
||||
if (hf_local_param.initialized) {
|
||||
hf_local_param.initialized = false;
|
||||
btc_hf_cb_release();
|
||||
param.prof_stat.state = ESP_HF_DEINIT_SUCCESS;
|
||||
btc_hf_cb_to_app(ESP_HF_PROF_STATE_EVT, ¶m);
|
||||
idx = 0;
|
||||
#if HFP_DYNAMIC_MEMORY == TRUE
|
||||
if (hf_local_param)
|
||||
#endif
|
||||
{
|
||||
if (hf_local_param[idx].btc_hf_cb.initialized) {
|
||||
hf_local_param[idx].btc_hf_cb.initialized = false;
|
||||
btc_hf_cb_release();
|
||||
param.prof_stat.state = ESP_HF_DEINIT_SUCCESS;
|
||||
btc_hf_cb_to_app(ESP_HF_PROF_STATE_EVT, ¶m);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -1337,14 +1360,14 @@ void btc_hf_cb_handler(btc_msg_t *msg)
|
||||
{
|
||||
idx = p_data->hdr.handle - 1;
|
||||
CHECK_HF_IDX(idx);
|
||||
hf_local_param.btc_hf_cb[idx].handle = p_data->reg.hdr.handle;
|
||||
BTC_TRACE_DEBUG("%s: BTA_AG_REGISTER_EVT," "hf_hf_cb[%d].btc_hf_cb.handle = %d",
|
||||
__FUNCTION__, idx, hf_local_param.btc_hf_cb[idx].handle);
|
||||
if (!hf_local_param.initialized) {
|
||||
hf_local_param[idx].btc_hf_cb.handle = p_data->reg.hdr.handle;
|
||||
BTC_TRACE_DEBUG("%s: BTA_AG_REGISTER_EVT," "hf_local_param[%d].btc_hf_cb.handle = %d",
|
||||
__FUNCTION__, idx, hf_local_param[idx].btc_hf_cb.handle);
|
||||
if (!hf_local_param[idx].btc_hf_cb.initialized) {
|
||||
param.prof_stat.state = ESP_HF_INIT_SUCCESS;
|
||||
btc_hf_cb_to_app(ESP_HF_PROF_STATE_EVT, ¶m);
|
||||
}
|
||||
hf_local_param.initialized = true;
|
||||
hf_local_param[idx].btc_hf_cb.initialized = true;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1354,30 +1377,30 @@ void btc_hf_cb_handler(btc_msg_t *msg)
|
||||
CHECK_HF_IDX(idx);
|
||||
if (p_data->open.hdr.status == BTA_AG_SUCCESS)
|
||||
{
|
||||
bdcpy(hf_local_param.btc_hf_cb[idx].connected_bda.address, p_data->open.bd_addr);
|
||||
hf_local_param.btc_hf_cb[idx].connection_state = ESP_HF_CONNECTION_STATE_CONNECTED;
|
||||
hf_local_param.btc_hf_cb[idx].peer_feat = 0;
|
||||
hf_local_param.btc_hf_cb[idx].chld_feat = 0;
|
||||
bdcpy(hf_local_param[idx].btc_hf_cb.connected_bda.address, p_data->open.bd_addr);
|
||||
hf_local_param[idx].btc_hf_cb.connection_state = ESP_HF_CONNECTION_STATE_CONNECTED;
|
||||
hf_local_param[idx].btc_hf_cb.peer_feat = 0;
|
||||
hf_local_param[idx].btc_hf_cb.chld_feat = 0;
|
||||
//clear_phone_state();
|
||||
} else if (hf_local_param.btc_hf_cb[idx].connection_state == ESP_HF_CONNECTION_STATE_CONNECTING) {
|
||||
hf_local_param.btc_hf_cb[idx].connection_state = ESP_HF_CONNECTION_STATE_DISCONNECTED;
|
||||
} else if (hf_local_param[idx].btc_hf_cb.connection_state == ESP_HF_CONNECTION_STATE_CONNECTING) {
|
||||
hf_local_param[idx].btc_hf_cb.connection_state = ESP_HF_CONNECTION_STATE_DISCONNECTED;
|
||||
} else {
|
||||
BTC_TRACE_WARNING("%s: AG open failed, but another device connected. status=%d state=%d connected device=%s", __FUNCTION__,
|
||||
p_data->open.hdr.status, hf_local_param.btc_hf_cb[idx].connection_state,
|
||||
bdaddr_to_string(&hf_local_param.btc_hf_cb[idx].connected_bda, bdstr, sizeof(bdstr)));
|
||||
p_data->open.hdr.status, hf_local_param[idx].btc_hf_cb.connection_state,
|
||||
bdaddr_to_string(&hf_local_param[idx].btc_hf_cb.connected_bda, bdstr, sizeof(bdstr)));
|
||||
break;
|
||||
}
|
||||
|
||||
do {
|
||||
memcpy(param.conn_stat.remote_bda, &hf_local_param.btc_hf_cb[idx].connected_bda, sizeof(esp_bd_addr_t));
|
||||
param.conn_stat.state = hf_local_param.btc_hf_cb[idx].connection_state;
|
||||
memcpy(param.conn_stat.remote_bda, &hf_local_param[idx].btc_hf_cb.connected_bda, sizeof(esp_bd_addr_t));
|
||||
param.conn_stat.state = hf_local_param[idx].btc_hf_cb.connection_state;
|
||||
param.conn_stat.peer_feat = 0;
|
||||
param.conn_stat.chld_feat = 0;
|
||||
btc_hf_cb_to_app(ESP_HF_CONNECTION_STATE_EVT, ¶m);
|
||||
} while (0);
|
||||
|
||||
if (hf_local_param.btc_hf_cb[idx].connection_state == ESP_HF_CONNECTION_STATE_DISCONNECTED)
|
||||
bdsetany(hf_local_param.btc_hf_cb[idx].connected_bda.address);
|
||||
if (hf_local_param[idx].btc_hf_cb.connection_state == ESP_HF_CONNECTION_STATE_DISCONNECTED)
|
||||
bdsetany(hf_local_param[idx].btc_hf_cb.connected_bda.address);
|
||||
|
||||
if (p_data->open.hdr.status != BTA_AG_SUCCESS)
|
||||
btc_queue_advance();
|
||||
@@ -1388,20 +1411,20 @@ void btc_hf_cb_handler(btc_msg_t *msg)
|
||||
{
|
||||
idx = p_data->hdr.handle - 1;
|
||||
CHECK_HF_IDX(idx);
|
||||
clock_gettime(CLOCK_MONOTONIC, &(hf_local_param.btc_hf_cb[idx].connected_timestamp));
|
||||
clock_gettime(CLOCK_MONOTONIC, &(hf_local_param[idx].btc_hf_cb.connected_timestamp));
|
||||
BTC_TRACE_DEBUG("%s: BTA_AG_CONN_EVT, idx = %d ", __FUNCTION__, idx);
|
||||
hf_local_param.btc_hf_cb[idx].peer_feat = p_data->conn.peer_feat;
|
||||
hf_local_param.btc_hf_cb[idx].chld_feat = p_data->conn.chld_feat;
|
||||
hf_local_param.btc_hf_cb[idx].connection_state = ESP_HF_CONNECTION_STATE_SLC_CONNECTED;
|
||||
hf_local_param[idx].btc_hf_cb.peer_feat = p_data->conn.peer_feat;
|
||||
hf_local_param[idx].btc_hf_cb.chld_feat = p_data->conn.chld_feat;
|
||||
hf_local_param[idx].btc_hf_cb.connection_state = ESP_HF_CONNECTION_STATE_SLC_CONNECTED;
|
||||
|
||||
do {
|
||||
param.conn_stat.state = hf_local_param.btc_hf_cb[idx].connection_state;
|
||||
param.conn_stat.peer_feat = hf_local_param.btc_hf_cb[idx].peer_feat;
|
||||
param.conn_stat.chld_feat = hf_local_param.btc_hf_cb[idx].chld_feat;
|
||||
memcpy(param.conn_stat.remote_bda, &hf_local_param.btc_hf_cb[idx].connected_bda, sizeof(esp_bd_addr_t));
|
||||
param.conn_stat.state = hf_local_param[idx].btc_hf_cb.connection_state;
|
||||
param.conn_stat.peer_feat = hf_local_param[idx].btc_hf_cb.peer_feat;
|
||||
param.conn_stat.chld_feat = hf_local_param[idx].btc_hf_cb.chld_feat;
|
||||
memcpy(param.conn_stat.remote_bda, &hf_local_param[idx].btc_hf_cb.connected_bda, sizeof(esp_bd_addr_t));
|
||||
btc_hf_cb_to_app(ESP_HF_CONNECTION_STATE_EVT, ¶m);
|
||||
} while(0);
|
||||
hf_local_param.hf_idx = btc_hf_latest_connected_idx();
|
||||
hf_local_param[idx].hf_idx = btc_hf_latest_connected_idx();
|
||||
btc_queue_advance();
|
||||
break;
|
||||
}
|
||||
@@ -1410,20 +1433,20 @@ void btc_hf_cb_handler(btc_msg_t *msg)
|
||||
{
|
||||
idx = p_data->hdr.handle - 1;
|
||||
CHECK_HF_IDX(idx);
|
||||
hf_local_param.btc_hf_cb[idx].connected_timestamp.tv_sec = 0;
|
||||
hf_local_param.btc_hf_cb[idx].connection_state = ESP_HF_CONNECTION_STATE_DISCONNECTED;
|
||||
BTC_TRACE_DEBUG("%s: BTA_AG_CLOSE_EVT," "hf_local_param.btc_hf_cb[%d].handle = %d", __FUNCTION__,
|
||||
idx, hf_local_param.btc_hf_cb[idx].handle);
|
||||
hf_local_param[idx].btc_hf_cb.connected_timestamp.tv_sec = 0;
|
||||
hf_local_param[idx].btc_hf_cb.connection_state = ESP_HF_CONNECTION_STATE_DISCONNECTED;
|
||||
BTC_TRACE_DEBUG("%s: BTA_AG_CLOSE_EVT," "hf_local_param[%d].btc_hf_cb.handle = %d", __FUNCTION__,
|
||||
idx, hf_local_param[idx].btc_hf_cb.handle);
|
||||
do {
|
||||
param.conn_stat.state = ESP_HF_CONNECTION_STATE_DISCONNECTED;
|
||||
param.conn_stat.peer_feat = 0;
|
||||
param.conn_stat.chld_feat = 0;
|
||||
memcpy(param.conn_stat.remote_bda, &hf_local_param.btc_hf_cb[idx].connected_bda, sizeof(esp_bd_addr_t));
|
||||
memcpy(param.conn_stat.remote_bda, &hf_local_param[idx].btc_hf_cb.connected_bda, sizeof(esp_bd_addr_t));
|
||||
btc_hf_cb_to_app(ESP_HF_CONNECTION_STATE_EVT, ¶m);
|
||||
} while(0);
|
||||
bdsetany(hf_local_param.btc_hf_cb[idx].connected_bda.address);
|
||||
bdsetany(hf_local_param[idx].btc_hf_cb.connected_bda.address);
|
||||
clear_phone_state();
|
||||
hf_local_param.hf_idx = btc_hf_latest_connected_idx();
|
||||
hf_local_param[idx].hf_idx = btc_hf_latest_connected_idx();
|
||||
btc_queue_advance();
|
||||
break;
|
||||
}
|
||||
@@ -1434,8 +1457,8 @@ void btc_hf_cb_handler(btc_msg_t *msg)
|
||||
CHECK_HF_IDX(idx);
|
||||
do {
|
||||
param.audio_stat.state = ESP_HF_AUDIO_STATE_CONNECTED;
|
||||
memcpy(param.audio_stat.remote_addr, &hf_local_param.btc_hf_cb[idx].connected_bda,sizeof(esp_bd_addr_t));
|
||||
hf_local_param.btc_hf_cb[idx].sync_conn_hdl = p_data->hdr.sync_conn_handle;
|
||||
memcpy(param.audio_stat.remote_addr, &hf_local_param[idx].btc_hf_cb.connected_bda,sizeof(esp_bd_addr_t));
|
||||
hf_local_param[idx].btc_hf_cb.sync_conn_hdl = p_data->hdr.sync_conn_handle;
|
||||
param.audio_stat.sync_conn_handle = p_data->hdr.sync_conn_handle;
|
||||
param.audio_stat.preferred_frame_size = p_data->audio_stat.preferred_frame_size;
|
||||
btc_hf_cb_to_app(ESP_HF_AUDIO_STATE_EVT, ¶m);
|
||||
@@ -1449,8 +1472,8 @@ void btc_hf_cb_handler(btc_msg_t *msg)
|
||||
CHECK_HF_IDX(idx);
|
||||
do {
|
||||
param.audio_stat.state = ESP_HF_AUDIO_STATE_CONNECTED_MSBC;
|
||||
memcpy(param.audio_stat.remote_addr, &hf_local_param.btc_hf_cb[idx].connected_bda,sizeof(esp_bd_addr_t));
|
||||
hf_local_param.btc_hf_cb[idx].sync_conn_hdl = p_data->hdr.sync_conn_handle;
|
||||
memcpy(param.audio_stat.remote_addr, &hf_local_param[idx].btc_hf_cb.connected_bda,sizeof(esp_bd_addr_t));
|
||||
hf_local_param[idx].btc_hf_cb.sync_conn_hdl = p_data->hdr.sync_conn_handle;
|
||||
param.audio_stat.sync_conn_handle = p_data->hdr.sync_conn_handle;
|
||||
param.audio_stat.preferred_frame_size = p_data->audio_stat.preferred_frame_size;
|
||||
btc_hf_cb_to_app(ESP_HF_AUDIO_STATE_EVT, ¶m);
|
||||
@@ -1463,8 +1486,8 @@ void btc_hf_cb_handler(btc_msg_t *msg)
|
||||
CHECK_HF_IDX(idx);
|
||||
do {
|
||||
param.audio_stat.state = ESP_HF_AUDIO_STATE_DISCONNECTED;
|
||||
hf_local_param.btc_hf_cb[idx].sync_conn_hdl = ESP_INVALID_CONN_HANDLE;
|
||||
memcpy(param.audio_stat.remote_addr, &hf_local_param.btc_hf_cb[idx].connected_bda, sizeof(esp_bd_addr_t));
|
||||
hf_local_param[idx].btc_hf_cb.sync_conn_hdl = ESP_INVALID_CONN_HANDLE;
|
||||
memcpy(param.audio_stat.remote_addr, &hf_local_param[idx].btc_hf_cb.connected_bda, sizeof(esp_bd_addr_t));
|
||||
param.audio_stat.sync_conn_handle = p_data->hdr.sync_conn_handle;
|
||||
btc_hf_cb_to_app(ESP_HF_AUDIO_STATE_EVT, ¶m);
|
||||
} while(0);
|
||||
@@ -1477,12 +1500,12 @@ void btc_hf_cb_handler(btc_msg_t *msg)
|
||||
CHECK_HF_IDX(idx);
|
||||
do {
|
||||
param.vra_rep.value = p_data->val.num;
|
||||
memcpy(param.vra_rep.remote_addr, &hf_local_param.btc_hf_cb[idx].connected_bda,sizeof(esp_bd_addr_t));
|
||||
memcpy(param.vra_rep.remote_addr, &hf_local_param[idx].btc_hf_cb.connected_bda,sizeof(esp_bd_addr_t));
|
||||
btc_hf_cb_to_app(ESP_HF_BVRA_RESPONSE_EVT, ¶m);
|
||||
if (p_data->val.num) {
|
||||
btc_hf_connect_audio(&hf_local_param.btc_hf_cb[idx].connected_bda);
|
||||
btc_hf_connect_audio(&hf_local_param[idx].btc_hf_cb.connected_bda);
|
||||
} else {
|
||||
btc_hf_disconnect_audio(&hf_local_param.btc_hf_cb[idx].connected_bda);
|
||||
btc_hf_disconnect_audio(&hf_local_param[idx].btc_hf_cb.connected_bda);
|
||||
}
|
||||
} while (0);
|
||||
break;
|
||||
@@ -1494,7 +1517,7 @@ void btc_hf_cb_handler(btc_msg_t *msg)
|
||||
idx = p_data->hdr.handle - 1;
|
||||
CHECK_HF_IDX(idx);
|
||||
do {
|
||||
memcpy(param.volume_control.remote_addr, &hf_local_param.btc_hf_cb[idx].connected_bda,sizeof(esp_bd_addr_t));
|
||||
memcpy(param.volume_control.remote_addr, &hf_local_param[idx].btc_hf_cb.connected_bda,sizeof(esp_bd_addr_t));
|
||||
param.volume_control.type = (event == BTA_AG_SPK_EVT) ? ESP_HF_VOLUME_CONTROL_TARGET_SPK : ESP_HF_VOLUME_CONTROL_TARGET_MIC;
|
||||
param.volume_control.volume = p_data->val.num;
|
||||
btc_hf_cb_to_app(ESP_HF_VOLUME_CONTROL_EVT, ¶m);
|
||||
@@ -1507,7 +1530,7 @@ void btc_hf_cb_handler(btc_msg_t *msg)
|
||||
idx = p_data->hdr.handle - 1;
|
||||
CHECK_HF_IDX(idx);
|
||||
do {
|
||||
memcpy(param.unat_rep.remote_addr, &hf_local_param.btc_hf_cb[idx].connected_bda,sizeof(esp_bd_addr_t));
|
||||
memcpy(param.unat_rep.remote_addr, &hf_local_param[idx].btc_hf_cb.connected_bda,sizeof(esp_bd_addr_t));
|
||||
param.unat_rep.unat = p_data->val.str;
|
||||
btc_hf_cb_to_app(ESP_HF_UNAT_RESPONSE_EVT, ¶m);
|
||||
} while (0);
|
||||
@@ -1518,7 +1541,7 @@ void btc_hf_cb_handler(btc_msg_t *msg)
|
||||
{
|
||||
idx = p_data->hdr.handle - 1;
|
||||
CHECK_HF_IDX(idx);
|
||||
memcpy(param.ind_upd.remote_addr, &hf_local_param.btc_hf_cb[idx].connected_bda,sizeof(esp_bd_addr_t));
|
||||
memcpy(param.ind_upd.remote_addr, &hf_local_param[idx].btc_hf_cb.connected_bda,sizeof(esp_bd_addr_t));
|
||||
btc_hf_cb_to_app(ESP_HF_IND_UPDATE_EVT, ¶m);
|
||||
break;
|
||||
}
|
||||
@@ -1527,7 +1550,7 @@ void btc_hf_cb_handler(btc_msg_t *msg)
|
||||
{
|
||||
idx = p_data->hdr.handle - 1;
|
||||
CHECK_HF_IDX(idx);
|
||||
memcpy(param.cind_rep.remote_addr, &hf_local_param.btc_hf_cb[idx].connected_bda,sizeof(esp_bd_addr_t));
|
||||
memcpy(param.cind_rep.remote_addr, &hf_local_param[idx].btc_hf_cb.connected_bda,sizeof(esp_bd_addr_t));
|
||||
btc_hf_cb_to_app(ESP_HF_CIND_RESPONSE_EVT, ¶m);
|
||||
break;
|
||||
}
|
||||
@@ -1536,7 +1559,7 @@ void btc_hf_cb_handler(btc_msg_t *msg)
|
||||
{
|
||||
idx = p_data->hdr.handle - 1;
|
||||
CHECK_HF_IDX(idx);
|
||||
memcpy(param.cops_rep.remote_addr, &hf_local_param.btc_hf_cb[idx].connected_bda,sizeof(esp_bd_addr_t));
|
||||
memcpy(param.cops_rep.remote_addr, &hf_local_param[idx].btc_hf_cb.connected_bda,sizeof(esp_bd_addr_t));
|
||||
btc_hf_cb_to_app(ESP_HF_COPS_RESPONSE_EVT, ¶m);
|
||||
break;
|
||||
}
|
||||
@@ -1545,7 +1568,7 @@ void btc_hf_cb_handler(btc_msg_t *msg)
|
||||
{
|
||||
idx = p_data->hdr.handle - 1;
|
||||
CHECK_HF_IDX(idx);
|
||||
memcpy(param.clcc_rep.remote_addr, &hf_local_param.btc_hf_cb[idx].connected_bda,sizeof(esp_bd_addr_t));
|
||||
memcpy(param.clcc_rep.remote_addr, &hf_local_param[idx].btc_hf_cb.connected_bda,sizeof(esp_bd_addr_t));
|
||||
btc_hf_cb_to_app(ESP_HF_CLCC_RESPONSE_EVT, ¶m);
|
||||
break;
|
||||
}
|
||||
@@ -1554,7 +1577,7 @@ void btc_hf_cb_handler(btc_msg_t *msg)
|
||||
{
|
||||
idx = p_data->hdr.handle - 1;
|
||||
CHECK_HF_IDX(idx);
|
||||
memcpy(param.cnum_rep.remote_addr, &hf_local_param.btc_hf_cb[idx].connected_bda,sizeof(esp_bd_addr_t));
|
||||
memcpy(param.cnum_rep.remote_addr, &hf_local_param[idx].btc_hf_cb.connected_bda,sizeof(esp_bd_addr_t));
|
||||
btc_hf_cb_to_app(ESP_HF_CNUM_RESPONSE_EVT, ¶m);
|
||||
break;
|
||||
}
|
||||
@@ -1564,7 +1587,7 @@ void btc_hf_cb_handler(btc_msg_t *msg)
|
||||
idx = p_data->hdr.handle - 1;
|
||||
CHECK_HF_IDX(idx);
|
||||
do {
|
||||
memcpy(param.vts_rep.remote_addr, &hf_local_param.btc_hf_cb[idx].connected_bda,sizeof(esp_bd_addr_t));
|
||||
memcpy(param.vts_rep.remote_addr, &hf_local_param[idx].btc_hf_cb.connected_bda,sizeof(esp_bd_addr_t));
|
||||
param.vts_rep.code = p_data->val.str;
|
||||
btc_hf_cb_to_app(ESP_HF_VTS_RESPONSE_EVT, ¶m);
|
||||
} while(0);
|
||||
@@ -1576,7 +1599,7 @@ void btc_hf_cb_handler(btc_msg_t *msg)
|
||||
idx = p_data->hdr.handle - 1;
|
||||
CHECK_HF_IDX(idx);
|
||||
do {
|
||||
memcpy(param.nrec.remote_addr, &hf_local_param.btc_hf_cb[idx].connected_bda,sizeof(esp_bd_addr_t));
|
||||
memcpy(param.nrec.remote_addr, &hf_local_param[idx].btc_hf_cb.connected_bda,sizeof(esp_bd_addr_t));
|
||||
param.nrec.state = p_data->val.num;
|
||||
btc_hf_cb_to_app(ESP_HF_NREC_RESPONSE_EVT, ¶m);
|
||||
} while(0);
|
||||
@@ -1587,7 +1610,7 @@ void btc_hf_cb_handler(btc_msg_t *msg)
|
||||
{
|
||||
idx = p_data->hdr.handle - 1;
|
||||
CHECK_HF_IDX(idx);
|
||||
memcpy(param.ata_rep.remote_addr, &hf_local_param.btc_hf_cb[idx].connected_bda,sizeof(esp_bd_addr_t));
|
||||
memcpy(param.ata_rep.remote_addr, &hf_local_param[idx].btc_hf_cb.connected_bda,sizeof(esp_bd_addr_t));
|
||||
btc_hf_cb_to_app(ESP_HF_ATA_RESPONSE_EVT, ¶m);
|
||||
break;
|
||||
}
|
||||
@@ -1596,7 +1619,7 @@ void btc_hf_cb_handler(btc_msg_t *msg)
|
||||
{
|
||||
idx = p_data->hdr.handle - 1;
|
||||
CHECK_HF_IDX(idx);
|
||||
memcpy(param.chup_rep.remote_addr, &hf_local_param.btc_hf_cb[idx].connected_bda,sizeof(esp_bd_addr_t));
|
||||
memcpy(param.chup_rep.remote_addr, &hf_local_param[idx].btc_hf_cb.connected_bda,sizeof(esp_bd_addr_t));
|
||||
btc_hf_cb_to_app(ESP_HF_CHUP_RESPONSE_EVT, ¶m);
|
||||
break;
|
||||
}
|
||||
@@ -1608,14 +1631,14 @@ void btc_hf_cb_handler(btc_msg_t *msg)
|
||||
CHECK_HF_IDX(idx);
|
||||
do {
|
||||
if (event == BTA_AG_AT_D_EVT) { // dial_number_or_memory
|
||||
memcpy(param.out_call.remote_addr, &hf_local_param.btc_hf_cb[idx].connected_bda,sizeof(esp_bd_addr_t));
|
||||
memcpy(param.out_call.remote_addr, &hf_local_param[idx].btc_hf_cb.connected_bda,sizeof(esp_bd_addr_t));
|
||||
param.out_call.type = p_data->val.value;
|
||||
param.out_call.num_or_loc = osi_malloc((strlen(p_data->val.str) + 1) * sizeof(char));
|
||||
sprintf(param.out_call.num_or_loc, "%s", p_data->val.str);
|
||||
btc_hf_cb_to_app(ESP_HF_DIAL_EVT, ¶m);
|
||||
osi_free(param.out_call.num_or_loc);
|
||||
} else if (event == BTA_AG_AT_BLDN_EVT) { //dial_last
|
||||
memcpy(param.out_call.remote_addr, &hf_local_param.btc_hf_cb[idx].connected_bda,sizeof(esp_bd_addr_t));
|
||||
memcpy(param.out_call.remote_addr, &hf_local_param[idx].btc_hf_cb.connected_bda,sizeof(esp_bd_addr_t));
|
||||
param.out_call.num_or_loc = NULL;
|
||||
btc_hf_cb_to_app(ESP_HF_DIAL_EVT, ¶m);
|
||||
}
|
||||
@@ -1632,7 +1655,7 @@ void btc_hf_cb_handler(btc_msg_t *msg)
|
||||
memset(&ag_res, 0, sizeof(ag_res));
|
||||
ag_res.ok_flag = BTA_AG_OK_ERROR;
|
||||
ag_res.errcode = BTA_AG_ERR_OP_NOT_SUPPORTED;
|
||||
BTA_AgResult(hf_local_param.btc_hf_cb[idx].handle, BTA_AG_UNAT_RES, &ag_res);
|
||||
BTA_AgResult(hf_local_param[idx].btc_hf_cb.handle, BTA_AG_UNAT_RES, &ag_res);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1647,11 +1670,11 @@ void btc_hf_cb_handler(btc_msg_t *msg)
|
||||
** of SCO connection establishment */
|
||||
if ((btc_conf_hf_force_wbs == TRUE) && (p_data->val.num & BTA_AG_CODEC_MSBC)) {
|
||||
BTC_TRACE_DEBUG("%s btc_hf override-Preferred Codec to MSBC", __FUNCTION__);
|
||||
BTA_AgSetCodec(hf_local_param.btc_hf_cb[idx].handle,BTA_AG_CODEC_MSBC);
|
||||
BTA_AgSetCodec(hf_local_param[idx].btc_hf_cb.handle,BTA_AG_CODEC_MSBC);
|
||||
}
|
||||
else {
|
||||
BTC_TRACE_DEBUG("%s btc_hf override-Preferred Codec to CVSD", __FUNCTION__);
|
||||
BTA_AgSetCodec(hf_local_param.btc_hf_cb[idx].handle,BTA_AG_CODEC_CVSD);
|
||||
BTA_AgSetCodec(hf_local_param[idx].btc_hf_cb.handle,BTA_AG_CODEC_CVSD);
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
@@ -1663,7 +1686,7 @@ void btc_hf_cb_handler(btc_msg_t *msg)
|
||||
CHECK_HF_IDX(idx);
|
||||
do {
|
||||
BTC_TRACE_DEBUG("Set codec status %d codec %d 1=CVSD 2=MSBC", p_data->val.hdr.status, p_data->val.num);
|
||||
memcpy(param.wbs_rep.remote_addr, &hf_local_param.btc_hf_cb[idx].connected_bda,sizeof(esp_bd_addr_t));
|
||||
memcpy(param.wbs_rep.remote_addr, &hf_local_param[idx].btc_hf_cb.connected_bda,sizeof(esp_bd_addr_t));
|
||||
param.wbs_rep.codec = p_data->val.num;
|
||||
btc_hf_cb_to_app(ESP_HF_WBS_RESPONSE_EVT, ¶m);
|
||||
} while (0);
|
||||
@@ -1676,7 +1699,7 @@ void btc_hf_cb_handler(btc_msg_t *msg)
|
||||
CHECK_HF_IDX(idx);
|
||||
do {
|
||||
BTC_TRACE_DEBUG("AG final seleded codec is %d 1=CVSD 2=MSBC", p_data->val.num);
|
||||
memcpy(param.bcs_rep.remote_addr, &hf_local_param.btc_hf_cb[idx].connected_bda,sizeof(esp_bd_addr_t));
|
||||
memcpy(param.bcs_rep.remote_addr, &hf_local_param[idx].btc_hf_cb.connected_bda,sizeof(esp_bd_addr_t));
|
||||
param.bcs_rep.mode = p_data->val.num;
|
||||
/* No ESP_HF_WBS_NONE case, because HFP 1.6 supported device can send BCS */
|
||||
btc_hf_cb_to_app(ESP_HF_BCS_RESPONSE_EVT, ¶m);
|
||||
@@ -1700,16 +1723,18 @@ void btc_hf_get_profile_status(esp_hf_profile_status_t *param)
|
||||
{
|
||||
param->hfp_ag_inited = false; // Not initialized by default
|
||||
|
||||
if (hf_local_param.initialized) {
|
||||
param->hfp_ag_inited = true;
|
||||
}
|
||||
|
||||
if (hf_local_param.btc_hf_cb != NULL) {
|
||||
#if HFP_DYNAMIC_MEMORY == TRUE
|
||||
if (hf_local_param)
|
||||
#endif
|
||||
{
|
||||
for (int idx = 0; idx < BTC_HF_NUM_CB; idx++) {
|
||||
if (hf_local_param.btc_hf_cb[idx].connection_state == ESP_HF_CONNECTION_STATE_SLC_CONNECTED) {
|
||||
param->slc_conn_num++;
|
||||
if (hf_local_param.btc_hf_cb[idx].sync_conn_hdl != ESP_INVALID_CONN_HANDLE) {
|
||||
param->sync_conn_num++;
|
||||
if (hf_local_param[idx].btc_hf_cb.initialized) {
|
||||
param->hfp_ag_inited = true;
|
||||
if (hf_local_param[idx].btc_hf_cb.connection_state == ESP_HF_CONNECTION_STATE_SLC_CONNECTED) {
|
||||
param->slc_conn_num++;
|
||||
if (hf_local_param[idx].btc_hf_cb.sync_conn_hdl != ESP_INVALID_CONN_HANDLE) {
|
||||
param->sync_conn_num++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -215,6 +215,7 @@ typedef union
|
||||
/* BTC-AG control block to map bdaddr to BTA handle */
|
||||
typedef struct
|
||||
{
|
||||
bool initialized;
|
||||
UINT16 handle;
|
||||
UINT16 sync_conn_hdl;
|
||||
bt_bdaddr_t connected_bda;
|
||||
@@ -232,9 +233,9 @@ typedef struct
|
||||
|
||||
typedef struct
|
||||
{
|
||||
bool initialized;
|
||||
int hf_idx;
|
||||
btc_hf_cb_t *btc_hf_cb;
|
||||
UINT32 btc_hf_features;
|
||||
btc_hf_cb_t btc_hf_cb;
|
||||
esp_hf_incoming_data_cb_t btc_hf_incoming_data_cb;
|
||||
esp_hf_outgoing_data_cb_t btc_hf_outgoing_data_cb;
|
||||
esp_hf_ag_audio_data_cb_t btc_hf_audio_data_cb;
|
||||
@@ -242,7 +243,7 @@ typedef struct
|
||||
|
||||
#if HFP_DYNAMIC_MEMORY == TRUE
|
||||
extern hf_local_param_t *hf_local_param_ptr;
|
||||
#define hf_local_param (*hf_local_param_ptr)
|
||||
#define hf_local_param (hf_local_param_ptr)
|
||||
#endif
|
||||
|
||||
/*******************************************************************************
|
||||
|
||||
@@ -751,11 +751,9 @@ config BT_NIMBLE_GATT_CACHING_INCLUDE_SERVICES
|
||||
Enable this option to include *included services* (e.g., services referenced by other services)
|
||||
in the GATT database cache. Disabling this will skip caching of included service entries.
|
||||
config BT_NIMBLE_INCL_SVC_DISCOVERY
|
||||
bool
|
||||
default y if BT_NIMBLE_GATT_CACHING && BT_NIMBLE_GATT_CACHING_INCLUDE_SERVICES
|
||||
default n if BT_NIMBLE_GATT_CACHING && !BT_NIMBLE_GATT_CACHING_INCLUDE_SERVICES
|
||||
default n if !BT_NIMBLE_GATT_CACHING
|
||||
prompt "Enable Included service discovery" if !BT_NIMBLE_GATT_CACHING
|
||||
bool "Enable Included service discovery"
|
||||
default y if BT_NIMBLE_GATT_CACHING_INCLUDE_SERVICES
|
||||
default n
|
||||
help
|
||||
Enable this option to start discovery for included service.
|
||||
config BT_NIMBLE_GATT_CACHING_MAX_CONNS
|
||||
@@ -901,7 +899,7 @@ menu "BLE Services"
|
||||
Enable HeartRate Service support
|
||||
|
||||
menuconfig BT_NIMBLE_HID_SERVICE
|
||||
bool "Human Interface Device service"
|
||||
bool "HID service"
|
||||
default n
|
||||
help
|
||||
Enable HID service support
|
||||
@@ -933,10 +931,10 @@ menu "BLE Services"
|
||||
Enable/Disable notifications on BAS Battery Level Characteristic
|
||||
|
||||
menuconfig BT_NIMBLE_DIS_SERVICE
|
||||
bool "Device Information Service"
|
||||
bool "DIS service"
|
||||
default y
|
||||
help
|
||||
Enable Device Information service support
|
||||
Enable DIS service support
|
||||
|
||||
config BT_NIMBLE_SVC_DIS_MANUFACTURER_NAME
|
||||
depends on BT_NIMBLE_DIS_SERVICE
|
||||
@@ -1078,6 +1076,7 @@ menu "BLE Services"
|
||||
default 0 if BT_NIMBLE_SVC_GAP_CAR_NOT_SUPP
|
||||
default 1 if BT_NIMBLE_SVC_GAP_CAR_SUPP
|
||||
|
||||
|
||||
menu "GAP device name write permissions"
|
||||
depends on BT_NIMBLE_GAP_SERVICE
|
||||
config BT_NIMBLE_SVC_GAP_NAME_WRITE
|
||||
@@ -1108,7 +1107,7 @@ menu "BLE Services"
|
||||
Enable write with authorisation permission (BLE_GATT_CHR_F_WRITE_AUTHOR)
|
||||
endmenu
|
||||
|
||||
menu "Peripheral Preferred Connection Parameters (PPCP) settings"
|
||||
menu "PPCP settings"
|
||||
depends on BT_NIMBLE_GAP_SERVICE
|
||||
config BT_NIMBLE_SVC_GAP_PPCP_MAX_CONN_INTERVAL
|
||||
int "PPCP Connection Interval Max (Unit: 1.25 ms)"
|
||||
@@ -1234,15 +1233,6 @@ config BT_NIMBLE_GATTC_PROC_PREEMPTION_PROTECT
|
||||
can disrupt the GATT context,causing the service discovery callback to not be invoked.
|
||||
A temporary list is maintained to preserve the GATT context and use it in case of preemption.
|
||||
|
||||
config BT_NIMBLE_GATTC_AUTO_PAIR
|
||||
bool "Automatically pair upon receiving service request failure"
|
||||
depends on BT_NIMBLE_ENABLED
|
||||
default n
|
||||
help
|
||||
If enabled, when a service request (e.g. read, write) to a server fails, and the ATT
|
||||
error suggests insufficient security, then the central will initiate pairing and retry
|
||||
the service request.
|
||||
|
||||
menu "Host-controller Transport"
|
||||
config BT_NIMBLE_TRANSPORT_UART
|
||||
bool "Enable Uart Transport"
|
||||
|
||||
Submodule components/bt/host/nimble/nimble updated: 0e3d2d39bb...cc3ac5416b
@@ -2010,14 +2010,6 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_GATTC_AUTO_PAIR
|
||||
#ifdef CONFIG_BT_NIMBLE_GATTC_AUTO_PAIR
|
||||
#define MYNEWT_VAL_BLE_GATTC_AUTO_PAIR CONFIG_BT_NIMBLE_GATTC_AUTO_PAIR
|
||||
#else
|
||||
#define MYNEWT_VAL_BLE_GATTC_AUTO_PAIR (0)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef MYNEWT_VAL_BLE_HOST_ALLOW_CONNECT_WITH_SCAN
|
||||
#ifdef CONFIG_BT_NIMBLE_HOST_ALLOW_CONNECT_WITH_SCAN
|
||||
#define MYNEWT_VAL_BLE_HOST_ALLOW_CONNECT_WITH_SCAN CONFIG_BT_NIMBLE_HOST_ALLOW_CONNECT_WITH_SCAN
|
||||
|
||||
@@ -16,16 +16,46 @@ set(includes "deprecated"
|
||||
# Always included linker fragments
|
||||
set(ldfragments "")
|
||||
|
||||
# ADC related source files (deprecated)
|
||||
if(CONFIG_SOC_ADC_SUPPORTED)
|
||||
list(APPEND srcs "deprecated/adc_legacy.c")
|
||||
|
||||
if(CONFIG_SOC_ADC_DMA_SUPPORTED)
|
||||
list(APPEND srcs "deprecated/adc_dma_legacy.c")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# DAC related source files
|
||||
if(CONFIG_SOC_DAC_SUPPORTED)
|
||||
list(APPEND srcs "deprecated/dac_common_legacy.c"
|
||||
"deprecated/${target}/dac_legacy.c")
|
||||
endif()
|
||||
|
||||
# GPTimer legacy driver
|
||||
if(CONFIG_SOC_GPTIMER_SUPPORTED)
|
||||
list(APPEND srcs "deprecated/timer_legacy.c")
|
||||
endif()
|
||||
|
||||
# I2C related source files
|
||||
if(CONFIG_SOC_I2C_SUPPORTED)
|
||||
list(APPEND srcs "i2c/i2c.c")
|
||||
endif()
|
||||
|
||||
# I2S related source files
|
||||
if(CONFIG_SOC_I2S_SUPPORTED)
|
||||
list(APPEND srcs "deprecated/i2s_legacy.c")
|
||||
endif()
|
||||
|
||||
# MCPWM legacy driver
|
||||
if(CONFIG_SOC_MCPWM_SUPPORTED)
|
||||
list(APPEND srcs "deprecated/mcpwm_legacy.c")
|
||||
endif()
|
||||
|
||||
# PCNT legacy driver
|
||||
if(CONFIG_SOC_PCNT_SUPPORTED)
|
||||
list(APPEND srcs "deprecated/pcnt_legacy.c")
|
||||
endif()
|
||||
|
||||
# RMT legacy driver
|
||||
if(CONFIG_SOC_RMT_SUPPORTED)
|
||||
list(APPEND srcs "deprecated/rmt_legacy.c")
|
||||
@@ -36,6 +66,11 @@ if(CONFIG_SOC_SDM_SUPPORTED)
|
||||
list(APPEND srcs "deprecated/sigma_delta_legacy.c")
|
||||
endif()
|
||||
|
||||
# Temperature Sensor related source files
|
||||
if(CONFIG_SOC_TEMP_SENSOR_SUPPORTED)
|
||||
list(APPEND srcs "deprecated/rtc_temperature_legacy.c")
|
||||
endif()
|
||||
|
||||
# Touch Sensor related source files
|
||||
if(CONFIG_SOC_TOUCH_SENSOR_SUPPORTED)
|
||||
if(CONFIG_SOC_TOUCH_SENSOR_VERSION LESS 3)
|
||||
@@ -52,11 +87,18 @@ if(CONFIG_SOC_TWAI_SUPPORTED AND NOT CONFIG_SOC_TWAI_SUPPORT_FD)
|
||||
list(APPEND ldfragments "twai/linker.lf")
|
||||
endif()
|
||||
|
||||
# Other source files
|
||||
if(${target} STREQUAL "esp32")
|
||||
list(APPEND srcs "deprecated/adc_i2s_deprecated.c")
|
||||
endif()
|
||||
|
||||
if(BOOTLOADER_BUILD)
|
||||
# Bootloader shall NOT depend on the drivers
|
||||
idf_component_register()
|
||||
else()
|
||||
# (REQUIRES cannot hide soc headers, since many arguments in the driver headers are chip-dependent)
|
||||
# (Legacy drivers requires `esp_adc`, due to ADC HW resource mutex logics are there.
|
||||
# Can be removed together with legacy drivers)
|
||||
idf_component_register(SRCS "${srcs}"
|
||||
INCLUDE_DIRS ${includes}
|
||||
PRIV_REQUIRES efuse esp_timer esp_mm
|
||||
@@ -70,4 +112,9 @@ else()
|
||||
esp_driver_twai
|
||||
LDFRAGMENTS ${ldfragments}
|
||||
)
|
||||
if(CONFIG_SOC_ADC_SUPPORTED AND
|
||||
CONFIG_COMPILER_STATIC_ANALYZER AND CMAKE_C_COMPILER_ID STREQUAL "GNU") # TODO GCC-366
|
||||
set_source_files_properties(deprecated/adc_legacy.c
|
||||
PROPERTIES COMPILE_FLAGS "-Wno-analyzer-use-of-uninitialized-value")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
@@ -2,6 +2,89 @@ menu "Driver Configurations"
|
||||
|
||||
orsource "./twai/Kconfig.twai"
|
||||
|
||||
menu "Legacy ADC Driver Configuration"
|
||||
|
||||
config ADC_DISABLE_DAC
|
||||
depends on SOC_DAC_SUPPORTED
|
||||
bool "Disable DAC when ADC2 is used on GPIO 25 and 26"
|
||||
default y
|
||||
help
|
||||
If this is set, the ADC2 driver will disable the output of the DAC corresponding to the specified
|
||||
channel. This is the default value.
|
||||
|
||||
For testing, disable this option so that we can measure the output of DAC by internal ADC.
|
||||
|
||||
config ADC_SUPPRESS_DEPRECATE_WARN
|
||||
bool "Suppress legacy driver deprecated warning"
|
||||
default n
|
||||
help
|
||||
Whether to suppress the deprecation warnings when using legacy adc driver (driver/adc.h).
|
||||
If you want to continue using the legacy driver, and don't want to see related deprecation warnings,
|
||||
you can enable this option.
|
||||
|
||||
config ADC_SKIP_LEGACY_CONFLICT_CHECK
|
||||
bool "Skip legacy conflict check"
|
||||
default n
|
||||
help
|
||||
This configuration option allows the user to bypass the conflict check mechanism with legacy code.
|
||||
menu "Legacy ADC Calibration Configuration"
|
||||
|
||||
config ADC_CAL_EFUSE_TP_ENABLE
|
||||
depends on IDF_TARGET_ESP32
|
||||
bool "Use Two Point Values"
|
||||
default "y"
|
||||
help
|
||||
Some ESP32s have Two Point calibration values burned into eFuse BLOCK3.
|
||||
This option will allow the ADC calibration component to characterize the
|
||||
ADC-Voltage curve using Two Point values if they are available.
|
||||
|
||||
config ADC_CAL_EFUSE_VREF_ENABLE
|
||||
depends on IDF_TARGET_ESP32
|
||||
bool "Use eFuse Vref"
|
||||
default "y"
|
||||
help
|
||||
Some ESP32s have Vref burned into eFuse BLOCK0. This option will allow
|
||||
the ADC calibration component to characterize the ADC-Voltage curve using
|
||||
eFuse Vref if it is available.
|
||||
|
||||
config ADC_CAL_LUT_ENABLE
|
||||
depends on IDF_TARGET_ESP32
|
||||
bool "Use Lookup Tables"
|
||||
default "y"
|
||||
help
|
||||
This option will allow the ADC calibration component to use Lookup Tables
|
||||
to correct for non-linear behavior in 11db attenuation. Other attenuations
|
||||
do not exhibit non-linear behavior hence will not be affected by this option.
|
||||
|
||||
config ADC_CALI_SUPPRESS_DEPRECATE_WARN
|
||||
bool "Suppress legacy driver deprecated warning"
|
||||
default n
|
||||
help
|
||||
Whether to suppress the deprecation warnings when using legacy adc calibration
|
||||
driver (esp_adc_cal.h).
|
||||
If you want to continue using the legacy driver, and don't want to see related
|
||||
deprecation warnings, you can enable this option.
|
||||
|
||||
endmenu # Legacy ADC Calibration Configuration
|
||||
endmenu # Legacy ADC Driver Configuration
|
||||
|
||||
menu "Legacy DAC Driver Configurations"
|
||||
depends on SOC_DAC_SUPPORTED
|
||||
config DAC_SUPPRESS_DEPRECATE_WARN
|
||||
bool "Suppress legacy driver deprecated warning"
|
||||
default n
|
||||
help
|
||||
Whether to suppress the deprecation warnings when using legacy dac driver (driver/dac.h).
|
||||
If you want to continue using the legacy driver, and don't want to see related deprecation warnings,
|
||||
you can enable this option.
|
||||
|
||||
config DAC_SKIP_LEGACY_CONFLICT_CHECK
|
||||
bool "Skip legacy conflict check"
|
||||
default n
|
||||
help
|
||||
This configuration option allows the user to bypass the conflict check mechanism with legacy code.
|
||||
endmenu # Legacy DAC Driver Configurations
|
||||
|
||||
menu "Legacy MCPWM Driver Configurations"
|
||||
depends on SOC_MCPWM_SUPPORTED
|
||||
config MCPWM_SUPPRESS_DEPRECATE_WARN
|
||||
@@ -19,6 +102,23 @@ menu "Driver Configurations"
|
||||
This configuration option allows the user to bypass the conflict check mechanism with legacy code.
|
||||
endmenu # Legacy MCPWM Driver Configurations
|
||||
|
||||
menu "Legacy Timer Group Driver Configurations"
|
||||
depends on SOC_GPTIMER_SUPPORTED
|
||||
config GPTIMER_SUPPRESS_DEPRECATE_WARN
|
||||
bool "Suppress legacy driver deprecated warning"
|
||||
default n
|
||||
help
|
||||
Whether to suppress the deprecation warnings when using legacy timer group driver (driver/timer.h).
|
||||
If you want to continue using the legacy driver, and don't want to see related deprecation warnings,
|
||||
you can enable this option.
|
||||
|
||||
config GPTIMER_SKIP_LEGACY_CONFLICT_CHECK
|
||||
bool "Skip legacy conflict check"
|
||||
default n
|
||||
help
|
||||
This configuration option allows the user to bypass the conflict check mechanism with legacy code.
|
||||
endmenu # Legacy Timer Group Driver Configurations
|
||||
|
||||
menu "Legacy RMT Driver Configurations"
|
||||
depends on SOC_RMT_SUPPORTED
|
||||
config RMT_SUPPRESS_DEPRECATE_WARN
|
||||
@@ -36,6 +136,23 @@ menu "Driver Configurations"
|
||||
This configuration option allows the user to bypass the conflict check mechanism with legacy code.
|
||||
endmenu # Legacy RMT Driver Configurations
|
||||
|
||||
menu "Legacy I2S Driver Configurations"
|
||||
depends on SOC_I2S_SUPPORTED
|
||||
config I2S_SUPPRESS_DEPRECATE_WARN
|
||||
bool "Suppress legacy driver deprecated warning"
|
||||
default n
|
||||
help
|
||||
Whether to suppress the deprecation warnings when using legacy i2s driver (driver/i2s.h).
|
||||
If you want to continue using the legacy driver, and don't want to see related deprecation warnings,
|
||||
you can enable this option.
|
||||
|
||||
config I2S_SKIP_LEGACY_CONFLICT_CHECK
|
||||
bool "Skip legacy conflict check"
|
||||
default n
|
||||
help
|
||||
This configuration option allows the user to bypass the conflict check mechanism with legacy code.
|
||||
endmenu # Legacy I2S Driver Configurationss
|
||||
|
||||
menu "Legacy I2C Driver Configurations"
|
||||
depends on SOC_I2C_SUPPORTED
|
||||
config I2C_SKIP_LEGACY_CONFLICT_CHECK
|
||||
@@ -79,6 +196,23 @@ menu "Driver Configurations"
|
||||
This configuration option allows the user to bypass the conflict check mechanism with legacy code.
|
||||
endmenu # Legacy SDM Driver Configurationss
|
||||
|
||||
menu "Legacy Temperature Sensor Driver Configurations"
|
||||
depends on SOC_TEMP_SENSOR_SUPPORTED
|
||||
config TEMP_SENSOR_SUPPRESS_DEPRECATE_WARN
|
||||
bool "Suppress legacy driver deprecated warning"
|
||||
default n
|
||||
help
|
||||
whether to suppress the deprecation warnings when using legacy temperature sensor driver
|
||||
(driver/temp_sensor.h). If you want to continue using the legacy driver,
|
||||
and don't want to see related deprecation warnings, you can enable this option.
|
||||
|
||||
config TEMP_SENSOR_SKIP_LEGACY_CONFLICT_CHECK
|
||||
bool "Skip legacy conflict check"
|
||||
default n
|
||||
help
|
||||
This configuration option allows the user to bypass the conflict check mechanism with legacy code.
|
||||
endmenu # Legacy Temperature Sensor Driver Configurationss
|
||||
|
||||
menu "Legacy Touch Sensor Driver Configurations"
|
||||
depends on SOC_TOUCH_SENSOR_SUPPORTED
|
||||
config TOUCH_SUPPRESS_DEPRECATE_WARN
|
||||
|
||||
51
components/driver/deprecated/adc1_private.h
Normal file
51
components/driver/deprecated/adc1_private.h
Normal file
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "esp_err.h"
|
||||
|
||||
/**
|
||||
* @brief For I2S dma to claim the usage of ADC1.
|
||||
*
|
||||
* Other tasks will be forbidden to use ADC1 between ``adc1_dma_mode_acquire`` and ``adc1_i2s_release``.
|
||||
* The I2S module may have to wait for a short time for the current conversion (if exist) to finish.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK success
|
||||
* - ESP_ERR_TIMEOUT reserved for future use. Currently the function will wait until success.
|
||||
*/
|
||||
esp_err_t adc1_dma_mode_acquire(void);
|
||||
|
||||
/**
|
||||
* @brief For ADC1 to claim the usage of ADC1.
|
||||
*
|
||||
* Other tasks will be forbidden to use ADC1 between ``adc1_rtc_mode_acquire`` and ``adc1_i2s_release``.
|
||||
* The ADC1 may have to wait for some time for the I2S read operation to finish.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK success
|
||||
* - ESP_ERR_TIMEOUT reserved for future use. Currently the function will wait until success.
|
||||
*/
|
||||
esp_err_t adc1_rtc_mode_acquire(void);
|
||||
|
||||
/**
|
||||
* @brief to let other tasks use the ADC1 when I2S is not work.
|
||||
*
|
||||
* Other tasks will be forbidden to use ADC1 between ``adc1_adc/i2s_mode_acquire`` and ``adc1_i2s_release``.
|
||||
* Call this function to release the occupation of ADC1
|
||||
*
|
||||
* @return always return ESP_OK.
|
||||
*/
|
||||
esp_err_t adc1_lock_release(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
676
components/driver/deprecated/adc_dma_legacy.c
Normal file
676
components/driver/deprecated/adc_dma_legacy.c
Normal file
@@ -0,0 +1,676 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2016-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <esp_types.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
#include "sdkconfig.h"
|
||||
#include "soc/soc_caps.h"
|
||||
#include "esp_intr_alloc.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_pm.h"
|
||||
#include "esp_check.h"
|
||||
#include "sys/lock.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/semphr.h"
|
||||
#include "freertos/timers.h"
|
||||
#include "freertos/ringbuf.h"
|
||||
#include "esp_private/esp_clk_tree_common.h"
|
||||
#include "esp_private/periph_ctrl.h"
|
||||
#include "esp_private/adc_share_hw_ctrl.h"
|
||||
#include "esp_private/sar_periph_ctrl.h"
|
||||
#include "hal/adc_types.h"
|
||||
#include "hal/adc_hal.h"
|
||||
#include "hal/dma_types.h"
|
||||
#include "hal/adc_hal_common.h"
|
||||
#include "esp_private/regi2c_ctrl.h"
|
||||
|
||||
#include "driver/gpio.h"
|
||||
#include "driver/adc_types_legacy.h"
|
||||
|
||||
//For calibration
|
||||
#if CONFIG_IDF_TARGET_ESP32S2
|
||||
#include "esp_efuse_rtc_table.h"
|
||||
#elif SOC_ADC_CALIBRATION_V1_SUPPORTED
|
||||
#include "esp_efuse_rtc_calib.h"
|
||||
#endif
|
||||
//For DMA
|
||||
#if SOC_GDMA_SUPPORTED
|
||||
#include "esp_private/gdma.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||
#include "hal/spi_types.h"
|
||||
#include "esp_private/spi_common_internal.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32
|
||||
#include "driver/i2s_types.h"
|
||||
#include "soc/i2s_periph.h"
|
||||
#include "esp_private/i2s_platform.h"
|
||||
#endif
|
||||
|
||||
static const char *ADC_TAG = "ADC";
|
||||
|
||||
#define ADC_GET_IO_NUM(periph, channel) (adc_channel_io_map[periph][channel])
|
||||
|
||||
extern portMUX_TYPE rtc_spinlock; //TODO: Will be placed in the appropriate position after the rtc module is finished.
|
||||
#define ADC_ENTER_CRITICAL() portENTER_CRITICAL(&rtc_spinlock)
|
||||
#define ADC_EXIT_CRITICAL() portEXIT_CRITICAL(&rtc_spinlock)
|
||||
|
||||
#define INTERNAL_BUF_NUM 5
|
||||
|
||||
#if SOC_AHB_GDMA_SUPPORTED
|
||||
#define ADC_GDMA_HOST 0
|
||||
#define ADC_DMA_INTR_MASK GDMA_LL_EVENT_RX_SUC_EOF
|
||||
#define ADC_DMA_INTR_MASK GDMA_LL_EVENT_RX_SUC_EOF
|
||||
#define adc_dma_start(adc_dma, addr) gdma_start(s_adc_digi_ctx->rx_dma_channel, (intptr_t)addr)
|
||||
#define adc_dma_stop(adc_dma) gdma_stop(s_adc_digi_ctx->rx_dma_channel)
|
||||
#define adc_dma_reset(adc_dma) gdma_reset(s_adc_digi_ctx->rx_dma_channel)
|
||||
#define adc_dma_clear_intr(adc_dma)
|
||||
#define adc_dma_enable_intr(adc_dma)
|
||||
#define adc_dma_disable_intr(adc_dma)
|
||||
#define adc_dma_deinit(adc_dma) do { \
|
||||
gdma_disconnect(s_adc_digi_ctx->rx_dma_channel); \
|
||||
gdma_del_channel(s_adc_digi_ctx->rx_dma_channel); \
|
||||
} while (0)
|
||||
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||
#define ADC_DMA_SPI_HOST SPI3_HOST
|
||||
#define ADC_DMA_INTR_MASK SPI_LL_INTR_IN_SUC_EOF
|
||||
#define adc_dma_start(adc_dma, addr) spi_dma_ll_rx_start(s_adc_digi_ctx->adc_spi_dev, s_adc_digi_ctx->spi_dma_ctx->rx_dma_chan.chan_id, (lldesc_t *)addr)
|
||||
#define adc_dma_stop(adc_dma) spi_dma_ll_rx_stop(s_adc_digi_ctx->adc_spi_dev, s_adc_digi_ctx->spi_dma_ctx->rx_dma_chan.chan_id);
|
||||
#define adc_dma_reset(adc_dma) spi_dma_ll_rx_reset(s_adc_digi_ctx->adc_spi_dev, s_adc_digi_ctx->spi_dma_ctx->rx_dma_chan.chan_id);
|
||||
#define adc_dma_clear_intr(adc_dma) spi_ll_clear_intr(s_adc_digi_ctx->adc_spi_dev, ADC_DMA_INTR_MASK)
|
||||
#define adc_dma_enable_intr(adc_dma) spi_ll_enable_intr(s_adc_digi_ctx->adc_spi_dev, ADC_DMA_INTR_MASK);
|
||||
#define adc_dma_disable_intr(adc_dma) spi_ll_disable_intr(s_adc_digi_ctx->adc_spi_dev, ADC_DMA_INTR_MASK);
|
||||
#define adc_dma_deinit(adc_dma) do { \
|
||||
esp_intr_free(s_adc_digi_ctx->intr_hdl); \
|
||||
spicommon_dma_chan_free(s_adc_digi_ctx->spi_dma_ctx); \
|
||||
spicommon_periph_free(ADC_DMA_SPI_HOST); \
|
||||
} while (0)
|
||||
|
||||
#elif CONFIG_IDF_TARGET_ESP32
|
||||
#define ADC_DMA_I2S_HOST I2S_NUM_0
|
||||
#define ADC_DMA_INTR_MASK BIT(9)
|
||||
#define adc_dma_start(adc_dma, addr) do { \
|
||||
i2s_ll_enable_dma(s_adc_digi_ctx->adc_i2s_dev, true); \
|
||||
i2s_ll_rx_start_link(s_adc_digi_ctx->adc_i2s_dev, (uint32_t)addr); \
|
||||
} while (0)
|
||||
#define adc_dma_stop(adc_dma) i2s_ll_rx_stop_link(s_adc_digi_ctx->adc_i2s_dev);
|
||||
#define adc_dma_reset(adc_dma) i2s_ll_rx_reset_dma(s_adc_digi_ctx->adc_i2s_dev);
|
||||
#define adc_dma_clear_intr(adc_dma) i2s_ll_clear_intr_status(s_adc_digi_ctx->adc_i2s_dev, ADC_DMA_INTR_MASK);
|
||||
#define adc_dma_enable_intr(adc_dma) i2s_ll_enable_intr(s_adc_digi_ctx->adc_i2s_dev, ADC_DMA_INTR_MASK, true);
|
||||
#define adc_dma_disable_intr(adc_dma) i2s_ll_enable_intr(s_adc_digi_ctx->adc_i2s_dev, ADC_DMA_INTR_MASK, false);
|
||||
#define adc_dma_deinit(adc_dma) do { \
|
||||
esp_intr_free(s_adc_digi_ctx->intr_hdl); \
|
||||
i2s_platform_release_occupation(I2S_CTLR_HP, ADC_DMA_I2S_HOST); \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
/*---------------------------------------------------------------
|
||||
Digital Controller Context
|
||||
---------------------------------------------------------------*/
|
||||
typedef struct adc_digi_context_t {
|
||||
uint8_t *rx_dma_buf; //dma buffer
|
||||
adc_hal_dma_ctx_t hal; //hal context
|
||||
#if SOC_GDMA_SUPPORTED
|
||||
gdma_channel_handle_t rx_dma_channel; //dma rx channel handle
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||
spi_host_device_t spi_host; //ADC uses this SPI DMA
|
||||
spi_dma_ctx_t *spi_dma_ctx; //spi_dma context
|
||||
intr_handle_t intr_hdl; //Interrupt handler
|
||||
spi_dev_t *adc_spi_dev ;
|
||||
#elif CONFIG_IDF_TARGET_ESP32
|
||||
i2s_port_t i2s_host; //ADC uses this I2S DMA
|
||||
intr_handle_t intr_hdl; //Interrupt handler
|
||||
i2s_dev_t *adc_i2s_dev;
|
||||
#endif
|
||||
RingbufHandle_t ringbuf_hdl; //RX ringbuffer handler
|
||||
intptr_t rx_eof_desc_addr; //eof descriptor address of RX channel
|
||||
bool ringbuf_overflow_flag; //1: ringbuffer overflow
|
||||
bool driver_start_flag; //1: driver is started; 0: driver is stopped
|
||||
bool use_adc1; //1: ADC unit1 will be used; 0: ADC unit1 won't be used.
|
||||
bool use_adc2; //1: ADC unit2 will be used; 0: ADC unit2 won't be used. This determines whether to acquire sar_adc2_mutex lock or not.
|
||||
adc_atten_t adc1_atten; //Attenuation for ADC1. On this chip each ADC can only support one attenuation.
|
||||
adc_atten_t adc2_atten; //Attenuation for ADC2. On this chip each ADC can only support one attenuation.
|
||||
adc_hal_digi_ctrlr_cfg_t hal_digi_ctrlr_cfg; //Hal digital controller configuration
|
||||
esp_pm_lock_handle_t pm_lock; //For power management
|
||||
} adc_digi_context_t;
|
||||
|
||||
static adc_digi_context_t *s_adc_digi_ctx = NULL;
|
||||
#ifdef CONFIG_PM_ENABLE
|
||||
//Only for deprecated API
|
||||
extern esp_pm_lock_handle_t adc_digi_arbiter_lock;
|
||||
#endif //CONFIG_PM_ENABLE
|
||||
|
||||
/*---------------------------------------------------------------
|
||||
ADC Continuous Read Mode (via DMA)
|
||||
---------------------------------------------------------------*/
|
||||
//Function to address transaction
|
||||
static bool s_adc_dma_intr(adc_digi_context_t *adc_digi_ctx);
|
||||
|
||||
#if SOC_GDMA_SUPPORTED
|
||||
static bool adc_dma_in_suc_eof_callback(gdma_channel_handle_t dma_chan, gdma_event_data_t *event_data, void *user_data);
|
||||
#else
|
||||
static void adc_dma_intr_handler(void *arg);
|
||||
#endif
|
||||
|
||||
static int8_t adc_digi_get_io_num(adc_unit_t adc_unit, uint8_t adc_channel)
|
||||
{
|
||||
assert(adc_unit < SOC_ADC_PERIPH_NUM);
|
||||
uint8_t adc_n = (adc_unit == ADC_UNIT_1) ? 0 : 1;
|
||||
return adc_channel_io_map[adc_n][adc_channel];
|
||||
}
|
||||
|
||||
static esp_err_t adc_digi_gpio_init(adc_unit_t adc_unit, uint16_t channel_mask)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
uint64_t gpio_mask = 0;
|
||||
uint32_t n = 0;
|
||||
int8_t io = 0;
|
||||
|
||||
while (channel_mask) {
|
||||
if (channel_mask & 0x1) {
|
||||
io = adc_digi_get_io_num(adc_unit, n);
|
||||
if (io < 0) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
gpio_mask |= BIT64(io);
|
||||
}
|
||||
channel_mask = channel_mask >> 1;
|
||||
n++;
|
||||
}
|
||||
|
||||
gpio_config_t cfg = {
|
||||
.pin_bit_mask = gpio_mask,
|
||||
.mode = GPIO_MODE_DISABLE,
|
||||
};
|
||||
ret = gpio_config(&cfg);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t adc_digi_deinitialize(void)
|
||||
{
|
||||
if (!s_adc_digi_ctx) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
if (s_adc_digi_ctx->driver_start_flag != 0) {
|
||||
ESP_LOGE(ADC_TAG, "The driver is not stopped");
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
if (s_adc_digi_ctx->ringbuf_hdl) {
|
||||
vRingbufferDelete(s_adc_digi_ctx->ringbuf_hdl);
|
||||
s_adc_digi_ctx->ringbuf_hdl = NULL;
|
||||
}
|
||||
|
||||
#if CONFIG_PM_ENABLE
|
||||
if (s_adc_digi_ctx->pm_lock) {
|
||||
esp_pm_lock_delete(s_adc_digi_ctx->pm_lock);
|
||||
}
|
||||
#endif //CONFIG_PM_ENABLE
|
||||
|
||||
ANALOG_CLOCK_DISABLE();
|
||||
|
||||
free(s_adc_digi_ctx->rx_dma_buf);
|
||||
free(s_adc_digi_ctx->hal.rx_desc);
|
||||
free(s_adc_digi_ctx->hal_digi_ctrlr_cfg.adc_pattern);
|
||||
|
||||
adc_dma_deinit(s_adc_digi_ctx);
|
||||
free(s_adc_digi_ctx);
|
||||
s_adc_digi_ctx = NULL;
|
||||
|
||||
adc_apb_periph_free();
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t adc_digi_initialize(const adc_digi_init_config_t *init_config)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
ESP_RETURN_ON_FALSE((init_config->conv_num_each_intr % SOC_ADC_DIGI_DATA_BYTES_PER_CONV == 0), ESP_ERR_INVALID_ARG, ADC_TAG, "conv_frame_size should be in multiples of `SOC_ADC_DIGI_DATA_BYTES_PER_CONV`");
|
||||
|
||||
s_adc_digi_ctx = calloc(1, sizeof(adc_digi_context_t));
|
||||
if (s_adc_digi_ctx == NULL) {
|
||||
ret = ESP_ERR_NO_MEM;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
//ringbuffer
|
||||
s_adc_digi_ctx->ringbuf_hdl = xRingbufferCreate(init_config->max_store_buf_size, RINGBUF_TYPE_BYTEBUF);
|
||||
if (!s_adc_digi_ctx->ringbuf_hdl) {
|
||||
ret = ESP_ERR_NO_MEM;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
//malloc internal buffer used by DMA
|
||||
s_adc_digi_ctx->rx_dma_buf = heap_caps_calloc(1, init_config->conv_num_each_intr * INTERNAL_BUF_NUM, MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA);
|
||||
if (!s_adc_digi_ctx->rx_dma_buf) {
|
||||
ret = ESP_ERR_NO_MEM;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
//malloc dma descriptor
|
||||
uint32_t dma_desc_num_per_frame = (init_config->conv_num_each_intr + DMA_DESCRIPTOR_BUFFER_MAX_SIZE_4B_ALIGNED - 1) / DMA_DESCRIPTOR_BUFFER_MAX_SIZE_4B_ALIGNED;
|
||||
uint32_t dma_desc_max_num = dma_desc_num_per_frame * INTERNAL_BUF_NUM;
|
||||
s_adc_digi_ctx->hal.rx_desc = heap_caps_calloc(1, (sizeof(dma_descriptor_t)) * dma_desc_max_num, MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA);
|
||||
if (!s_adc_digi_ctx->hal.rx_desc) {
|
||||
ret = ESP_ERR_NO_MEM;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
//malloc pattern table
|
||||
s_adc_digi_ctx->hal_digi_ctrlr_cfg.adc_pattern = calloc(1, SOC_ADC_PATT_LEN_MAX * sizeof(adc_digi_pattern_config_t));
|
||||
if (!s_adc_digi_ctx->hal_digi_ctrlr_cfg.adc_pattern) {
|
||||
ret = ESP_ERR_NO_MEM;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
#if CONFIG_PM_ENABLE
|
||||
ret = esp_pm_lock_create(ESP_PM_APB_FREQ_MAX, 0, "adc_dma", &s_adc_digi_ctx->pm_lock);
|
||||
if (ret != ESP_OK) {
|
||||
goto cleanup;
|
||||
}
|
||||
#endif //CONFIG_PM_ENABLE
|
||||
|
||||
//init gpio pins
|
||||
if (init_config->adc1_chan_mask) {
|
||||
ret = adc_digi_gpio_init(ADC_UNIT_1, init_config->adc1_chan_mask);
|
||||
if (ret != ESP_OK) {
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
if (init_config->adc2_chan_mask) {
|
||||
ret = adc_digi_gpio_init(ADC_UNIT_2, init_config->adc2_chan_mask);
|
||||
if (ret != ESP_OK) {
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
#if SOC_GDMA_SUPPORTED
|
||||
//alloc rx gdma channel
|
||||
gdma_channel_alloc_config_t rx_alloc_config = {
|
||||
.direction = GDMA_CHANNEL_DIRECTION_RX,
|
||||
};
|
||||
ret = gdma_new_ahb_channel(&rx_alloc_config, &s_adc_digi_ctx->rx_dma_channel);
|
||||
if (ret != ESP_OK) {
|
||||
goto cleanup;
|
||||
}
|
||||
gdma_connect(s_adc_digi_ctx->rx_dma_channel, GDMA_MAKE_TRIGGER(GDMA_TRIG_PERIPH_ADC, 0));
|
||||
|
||||
gdma_strategy_config_t strategy_config = {
|
||||
.auto_update_desc = true,
|
||||
.owner_check = true
|
||||
};
|
||||
gdma_apply_strategy(s_adc_digi_ctx->rx_dma_channel, &strategy_config);
|
||||
|
||||
gdma_rx_event_callbacks_t cbs = {
|
||||
.on_recv_eof = adc_dma_in_suc_eof_callback
|
||||
};
|
||||
gdma_register_rx_event_callbacks(s_adc_digi_ctx->rx_dma_channel, &cbs, s_adc_digi_ctx);
|
||||
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||
//ADC utilises SPI3 DMA on ESP32S2
|
||||
bool spi_success = false;
|
||||
|
||||
spi_success = spicommon_periph_claim(ADC_DMA_SPI_HOST, "adc");
|
||||
ret = spicommon_dma_chan_alloc(ADC_DMA_SPI_HOST, SPI_DMA_CH_AUTO, &(s_adc_digi_ctx->spi_dma_ctx));
|
||||
if (ret != ESP_OK || spi_success != ESP_OK) {
|
||||
goto cleanup;
|
||||
}
|
||||
if (!spi_success || (s_adc_digi_ctx->spi_host != ADC_DMA_SPI_HOST)) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
ret = esp_intr_alloc(spicommon_irqdma_source_for_host(ADC_DMA_SPI_HOST), 0, adc_dma_intr_handler,
|
||||
(void *)s_adc_digi_ctx, &s_adc_digi_ctx->intr_hdl);
|
||||
if (ret != ESP_OK) {
|
||||
goto cleanup;
|
||||
}
|
||||
s_adc_digi_ctx->adc_spi_dev = SPI_LL_GET_HW(ADC_DMA_SPI_HOST);
|
||||
#elif CONFIG_IDF_TARGET_ESP32
|
||||
//ADC utilises I2S0 DMA on ESP32
|
||||
ret = i2s_platform_acquire_occupation(I2S_CTLR_HP, ADC_DMA_I2S_HOST, "adc");
|
||||
if (ret != ESP_OK) {
|
||||
ret = ESP_ERR_NOT_FOUND;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
s_adc_digi_ctx->i2s_host = I2S_NUM_0;
|
||||
|
||||
ret = esp_intr_alloc(i2s_periph_signal[ADC_DMA_I2S_HOST].irq, 0, adc_dma_intr_handler,
|
||||
(void *)s_adc_digi_ctx, &s_adc_digi_ctx->intr_hdl);
|
||||
if (ret != ESP_OK) {
|
||||
goto cleanup;
|
||||
}
|
||||
s_adc_digi_ctx->adc_i2s_dev = I2S_LL_GET_HW(ADC_DMA_I2S_HOST);
|
||||
#endif
|
||||
|
||||
adc_hal_dma_config_t config = {
|
||||
.eof_desc_num = INTERNAL_BUF_NUM,
|
||||
.eof_step = dma_desc_num_per_frame,
|
||||
.eof_num = init_config->conv_num_each_intr / SOC_ADC_DIGI_DATA_BYTES_PER_CONV
|
||||
};
|
||||
adc_hal_dma_ctx_config(&s_adc_digi_ctx->hal, &config);
|
||||
|
||||
adc_apb_periph_claim();
|
||||
|
||||
ANALOG_CLOCK_ENABLE();
|
||||
|
||||
#if SOC_ADC_CALIBRATION_V1_SUPPORTED
|
||||
adc_hal_calibration_init(ADC_UNIT_1);
|
||||
adc_hal_calibration_init(ADC_UNIT_2);
|
||||
#endif //#if SOC_ADC_CALIBRATION_V1_SUPPORTED
|
||||
|
||||
return ret;
|
||||
|
||||
cleanup:
|
||||
adc_digi_deinitialize();
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if SOC_GDMA_SUPPORTED
|
||||
static IRAM_ATTR bool adc_dma_in_suc_eof_callback(gdma_channel_handle_t dma_chan, gdma_event_data_t *event_data, void *user_data)
|
||||
{
|
||||
assert(event_data);
|
||||
s_adc_digi_ctx->rx_eof_desc_addr = event_data->rx_eof_desc_addr;
|
||||
return s_adc_dma_intr(user_data);
|
||||
}
|
||||
#else
|
||||
static IRAM_ATTR void adc_dma_intr_handler(void *arg)
|
||||
{
|
||||
adc_digi_context_t *ctx = (adc_digi_context_t *)arg;
|
||||
bool need_yield = false;
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32S2
|
||||
bool conversion_finish = spi_ll_get_intr(s_adc_digi_ctx->adc_spi_dev, ADC_DMA_INTR_MASK);
|
||||
if (conversion_finish) {
|
||||
spi_ll_clear_intr(s_adc_digi_ctx->adc_spi_dev, ADC_DMA_INTR_MASK);
|
||||
intptr_t desc_addr = spi_dma_ll_get_in_suc_eof_desc_addr(s_adc_digi_ctx->adc_spi_dev, s_adc_digi_ctx->spi_dma_ctx->rx_dma_chan.chan_id);
|
||||
ctx->rx_eof_desc_addr = desc_addr;
|
||||
need_yield = s_adc_dma_intr(ctx);
|
||||
}
|
||||
#elif CONFIG_IDF_TARGET_ESP32
|
||||
bool conversion_finish = i2s_ll_get_intr_status(s_adc_digi_ctx->adc_i2s_dev) & ADC_DMA_INTR_MASK;
|
||||
if (conversion_finish) {
|
||||
i2s_ll_clear_intr_status(s_adc_digi_ctx->adc_i2s_dev, ADC_DMA_INTR_MASK);
|
||||
uint32_t desc_addr;
|
||||
i2s_ll_rx_get_eof_des_addr(s_adc_digi_ctx->adc_i2s_dev, &desc_addr);
|
||||
ctx->rx_eof_desc_addr = (intptr_t)desc_addr;
|
||||
need_yield = s_adc_dma_intr(ctx);
|
||||
}
|
||||
#endif
|
||||
if (need_yield) {
|
||||
portYIELD_FROM_ISR();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static IRAM_ATTR bool s_adc_dma_intr(adc_digi_context_t *adc_digi_ctx)
|
||||
{
|
||||
BaseType_t taskAwoken = 0;
|
||||
BaseType_t ret;
|
||||
adc_hal_dma_desc_status_t status = false;
|
||||
uint8_t *finished_buffer = NULL;
|
||||
uint32_t finished_size = 0;
|
||||
|
||||
while (1) {
|
||||
status = adc_hal_get_reading_result(&adc_digi_ctx->hal, adc_digi_ctx->rx_eof_desc_addr, &finished_buffer, &finished_size);
|
||||
if (status != ADC_HAL_DMA_DESC_VALID) {
|
||||
break;
|
||||
}
|
||||
|
||||
ret = xRingbufferSendFromISR(adc_digi_ctx->ringbuf_hdl, finished_buffer, finished_size, &taskAwoken);
|
||||
if (ret == pdFALSE) {
|
||||
//ringbuffer overflow
|
||||
adc_digi_ctx->ringbuf_overflow_flag = 1;
|
||||
}
|
||||
}
|
||||
|
||||
return (taskAwoken == pdTRUE);
|
||||
}
|
||||
|
||||
esp_err_t adc_digi_start(void)
|
||||
{
|
||||
|
||||
if (s_adc_digi_ctx->driver_start_flag != 0) {
|
||||
ESP_LOGE(ADC_TAG, "The driver is already started");
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
//reset ADC digital part to reset ADC sampling EOF counter
|
||||
ADC_BUS_CLK_ATOMIC() {
|
||||
adc_ll_reset_register();
|
||||
}
|
||||
|
||||
sar_periph_ctrl_adc_continuous_power_acquire();
|
||||
//reset flags
|
||||
s_adc_digi_ctx->ringbuf_overflow_flag = 0;
|
||||
s_adc_digi_ctx->driver_start_flag = 1;
|
||||
if (s_adc_digi_ctx->use_adc1) {
|
||||
adc_lock_acquire(ADC_UNIT_1);
|
||||
}
|
||||
if (s_adc_digi_ctx->use_adc2) {
|
||||
adc_lock_acquire(ADC_UNIT_2);
|
||||
}
|
||||
|
||||
#if CONFIG_PM_ENABLE
|
||||
// Lock APB frequency while ADC driver is in use
|
||||
esp_pm_lock_acquire(s_adc_digi_ctx->pm_lock);
|
||||
#endif
|
||||
|
||||
#if SOC_ADC_CALIBRATION_V1_SUPPORTED
|
||||
if (s_adc_digi_ctx->use_adc1) {
|
||||
adc_set_hw_calibration_code(ADC_UNIT_1, s_adc_digi_ctx->adc1_atten);
|
||||
}
|
||||
if (s_adc_digi_ctx->use_adc2) {
|
||||
adc_set_hw_calibration_code(ADC_UNIT_2, s_adc_digi_ctx->adc2_atten);
|
||||
}
|
||||
#endif //#if SOC_ADC_CALIBRATION_V1_SUPPORTED
|
||||
|
||||
#if SOC_ADC_ARBITER_SUPPORTED
|
||||
adc_arbiter_t config = ADC_ARBITER_CONFIG_DEFAULT();
|
||||
adc_hal_arbiter_config(&config);
|
||||
#endif //#if SOC_ADC_ARBITER_SUPPORTED
|
||||
|
||||
adc_hal_set_controller(ADC_UNIT_1, ADC_HAL_CONTINUOUS_READ_MODE);
|
||||
adc_hal_set_controller(ADC_UNIT_2, ADC_HAL_CONTINUOUS_READ_MODE);
|
||||
|
||||
adc_hal_digi_init(&s_adc_digi_ctx->hal);
|
||||
#if !CONFIG_IDF_TARGET_ESP32
|
||||
esp_clk_tree_enable_src((soc_module_clk_t)(s_adc_digi_ctx->hal_digi_ctrlr_cfg.clk_src), true);
|
||||
#endif
|
||||
adc_hal_digi_controller_config(&s_adc_digi_ctx->hal, &s_adc_digi_ctx->hal_digi_ctrlr_cfg);
|
||||
|
||||
adc_dma_stop(s_adc_digi_ctx);
|
||||
adc_hal_digi_connect(false);
|
||||
|
||||
adc_dma_reset(s_adc_digi_ctx);
|
||||
adc_hal_digi_reset();
|
||||
adc_hal_digi_dma_link(&s_adc_digi_ctx->hal, s_adc_digi_ctx->rx_dma_buf);
|
||||
|
||||
adc_dma_start(s_adc_digi_ctx, s_adc_digi_ctx->hal.rx_desc);
|
||||
adc_hal_digi_connect(true);
|
||||
adc_hal_digi_enable(true);
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t adc_digi_stop(void)
|
||||
{
|
||||
if (s_adc_digi_ctx->driver_start_flag != 1) {
|
||||
ESP_LOGE(ADC_TAG, "The driver is already stopped");
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
s_adc_digi_ctx->driver_start_flag = 0;
|
||||
|
||||
adc_dma_stop(s_adc_digi_ctx);
|
||||
adc_hal_digi_enable(false);
|
||||
adc_hal_digi_connect(false);
|
||||
|
||||
adc_hal_digi_deinit();
|
||||
|
||||
#if CONFIG_PM_ENABLE
|
||||
if (s_adc_digi_ctx->pm_lock) {
|
||||
esp_pm_lock_release(s_adc_digi_ctx->pm_lock);
|
||||
}
|
||||
#endif //CONFIG_PM_ENABLE
|
||||
|
||||
if (s_adc_digi_ctx->use_adc2) {
|
||||
adc_lock_release(ADC_UNIT_2);
|
||||
}
|
||||
if (s_adc_digi_ctx->use_adc1) {
|
||||
adc_lock_release(ADC_UNIT_1);
|
||||
}
|
||||
sar_periph_ctrl_adc_continuous_power_release();
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t adc_digi_read_bytes(uint8_t *buf, uint32_t length_max, uint32_t *out_length, uint32_t timeout_ms)
|
||||
{
|
||||
TickType_t ticks_to_wait;
|
||||
esp_err_t ret = ESP_OK;
|
||||
uint8_t *data = NULL;
|
||||
size_t size = 0;
|
||||
|
||||
ticks_to_wait = timeout_ms / portTICK_PERIOD_MS;
|
||||
if (timeout_ms == ADC_MAX_DELAY) {
|
||||
ticks_to_wait = portMAX_DELAY;
|
||||
}
|
||||
|
||||
data = xRingbufferReceiveUpTo(s_adc_digi_ctx->ringbuf_hdl, &size, ticks_to_wait, length_max);
|
||||
if (!data) {
|
||||
ESP_LOGV(ADC_TAG, "No data, increase timeout or reduce conv_num_each_intr");
|
||||
ret = ESP_ERR_TIMEOUT;
|
||||
*out_length = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
memcpy(buf, data, size);
|
||||
vRingbufferReturnItem(s_adc_digi_ctx->ringbuf_hdl, data);
|
||||
assert((size % 4) == 0);
|
||||
*out_length = size;
|
||||
|
||||
if (s_adc_digi_ctx->ringbuf_overflow_flag) {
|
||||
ret = ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------
|
||||
Digital controller setting
|
||||
---------------------------------------------------------------*/
|
||||
esp_err_t adc_digi_controller_configure(const adc_digi_configuration_t *config)
|
||||
{
|
||||
if (!s_adc_digi_ctx) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
//Pattern related check
|
||||
ESP_RETURN_ON_FALSE(config->pattern_num <= SOC_ADC_PATT_LEN_MAX, ESP_ERR_INVALID_ARG, ADC_TAG, "Max pattern num is %d", SOC_ADC_PATT_LEN_MAX);
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
for (int i = 0; i < config->pattern_num; i++) {
|
||||
ESP_RETURN_ON_FALSE((config->adc_pattern[i].bit_width >= SOC_ADC_DIGI_MIN_BITWIDTH && config->adc_pattern->bit_width <= SOC_ADC_DIGI_MAX_BITWIDTH), ESP_ERR_INVALID_ARG, ADC_TAG, "ADC bitwidth not supported");
|
||||
ESP_RETURN_ON_FALSE(config->adc_pattern[i].unit == 0, ESP_ERR_INVALID_ARG, ADC_TAG, "Only support using ADC1 DMA mode");
|
||||
}
|
||||
#else
|
||||
for (int i = 0; i < config->pattern_num; i++) {
|
||||
ESP_RETURN_ON_FALSE((config->adc_pattern[i].bit_width == SOC_ADC_DIGI_MAX_BITWIDTH), ESP_ERR_INVALID_ARG, ADC_TAG, "ADC bitwidth not supported");
|
||||
}
|
||||
#endif
|
||||
ESP_RETURN_ON_FALSE(config->sample_freq_hz <= SOC_ADC_SAMPLE_FREQ_THRES_HIGH && config->sample_freq_hz >= SOC_ADC_SAMPLE_FREQ_THRES_LOW, ESP_ERR_INVALID_ARG, ADC_TAG, "ADC sampling frequency out of range");
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
ESP_RETURN_ON_FALSE(config->format == ADC_DIGI_OUTPUT_FORMAT_TYPE1, ESP_ERR_INVALID_ARG, ADC_TAG, "Please use type1");
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||
if (config->conv_mode == ADC_CONV_BOTH_UNIT || config->conv_mode == ADC_CONV_ALTER_UNIT) {
|
||||
ESP_RETURN_ON_FALSE(config->format == ADC_DIGI_OUTPUT_FORMAT_TYPE2, ESP_ERR_INVALID_ARG, ADC_TAG, "Please use type2");
|
||||
} else if (config->conv_mode == ADC_CONV_SINGLE_UNIT_1 || config->conv_mode == ADC_CONV_SINGLE_UNIT_2) {
|
||||
ESP_RETURN_ON_FALSE(config->format == ADC_DIGI_OUTPUT_FORMAT_TYPE1, ESP_ERR_INVALID_ARG, ADC_TAG, "Please use type1");
|
||||
}
|
||||
#else
|
||||
ESP_RETURN_ON_FALSE(config->format == ADC_DIGI_OUTPUT_FORMAT_TYPE2, ESP_ERR_INVALID_ARG, ADC_TAG, "Please use type2");
|
||||
#endif
|
||||
|
||||
s_adc_digi_ctx->hal_digi_ctrlr_cfg.adc_pattern_len = config->pattern_num;
|
||||
s_adc_digi_ctx->hal_digi_ctrlr_cfg.sample_freq_hz = config->sample_freq_hz;
|
||||
s_adc_digi_ctx->hal_digi_ctrlr_cfg.conv_mode = config->conv_mode;
|
||||
memcpy(s_adc_digi_ctx->hal_digi_ctrlr_cfg.adc_pattern, config->adc_pattern, config->pattern_num * sizeof(adc_digi_pattern_config_t));
|
||||
|
||||
const int atten_uninitialized = 999;
|
||||
s_adc_digi_ctx->adc1_atten = atten_uninitialized;
|
||||
s_adc_digi_ctx->adc2_atten = atten_uninitialized;
|
||||
s_adc_digi_ctx->use_adc1 = 0;
|
||||
s_adc_digi_ctx->use_adc2 = 0;
|
||||
for (int i = 0; i < config->pattern_num; i++) {
|
||||
const adc_digi_pattern_config_t *pat = &config->adc_pattern[i];
|
||||
if (pat->unit == ADC_UNIT_1) {
|
||||
s_adc_digi_ctx->use_adc1 = 1;
|
||||
|
||||
if (s_adc_digi_ctx->adc1_atten == atten_uninitialized) {
|
||||
s_adc_digi_ctx->adc1_atten = pat->atten;
|
||||
} else if (s_adc_digi_ctx->adc1_atten != pat->atten) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
} else if (pat->unit == ADC_UNIT_2) {
|
||||
//See whether ADC2 will be used or not. If yes, the ``sar_adc2_mutex`` should be acquired in the continuous read driver
|
||||
s_adc_digi_ctx->use_adc2 = 1;
|
||||
|
||||
if (s_adc_digi_ctx->adc2_atten == atten_uninitialized) {
|
||||
s_adc_digi_ctx->adc2_atten = pat->atten;
|
||||
} else if (s_adc_digi_ctx->adc2_atten != pat->atten) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
#if !CONFIG_ADC_SKIP_LEGACY_CONFLICT_CHECK
|
||||
/**
|
||||
* @brief This function will be called during start up, to check that adc_continuous driver is not running along with the legacy adc_continuous driver
|
||||
*/
|
||||
__attribute__((constructor))
|
||||
static void check_adc_continuous_driver_conflict(void)
|
||||
{
|
||||
// This function was declared as weak here. adc_continuous driver has one implementation.
|
||||
// So if adc_continuous driver is not linked in, then `adc_continuous_new_handle` should be NULL at runtime.
|
||||
extern __attribute__((weak)) esp_err_t adc_continuous_new_handle(const void *init_config, void **ret_handle);
|
||||
if ((void *)adc_continuous_new_handle != NULL) {
|
||||
ESP_EARLY_LOGE(ADC_TAG, "CONFLICT! driver_ng is not allowed to be used with the legacy driver");
|
||||
abort();
|
||||
}
|
||||
ESP_EARLY_LOGW(ADC_TAG, "legacy driver is deprecated, please migrate to `esp_adc/adc_continuous.h`");
|
||||
}
|
||||
#endif //CONFIG_ADC_SKIP_LEGACY_CONFLICT_CHECK
|
||||
|
||||
#if SOC_ADC_CALIBRATION_V1_SUPPORTED
|
||||
/*---------------------------------------------------------------
|
||||
ADC Hardware Calibration
|
||||
---------------------------------------------------------------*/
|
||||
static __attribute__((constructor)) void adc_hw_calibration(void)
|
||||
{
|
||||
//Calculate all ICode
|
||||
for (int i = 0; i < SOC_ADC_PERIPH_NUM; i++) {
|
||||
adc_hal_calibration_init(i);
|
||||
for (int j = 0; j < SOC_ADC_ATTEN_NUM; j++) {
|
||||
/**
|
||||
* This may get wrong when attenuations are NOT consecutive on some chips,
|
||||
* update this when bringing up the calibration on that chip
|
||||
*/
|
||||
adc_calc_hw_calibration_code(i, j);
|
||||
#if SOC_ADC_CALIB_CHAN_COMPENS_SUPPORTED
|
||||
/* Load the channel compensation from efuse */
|
||||
for (int k = 0; k < SOC_ADC_CHANNEL_NUM(i); k++) {
|
||||
adc_load_hw_calibration_chan_compens(i, k, j);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif //#if SOC_ADC_CALIBRATION_V1_SUPPORTED
|
||||
248
components/driver/deprecated/adc_i2s_deprecated.c
Normal file
248
components/driver/deprecated/adc_i2s_deprecated.c
Normal file
@@ -0,0 +1,248 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2016-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/*----------------------------------------------------------------------------------
|
||||
This file contains ESP32 and ESP32S2 Deprecated ADC APIs and functions
|
||||
-----------------------------------------------------------------------------------*/
|
||||
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_types.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_intr_alloc.h"
|
||||
#include "driver/rtc_io.h"
|
||||
#include "hal/adc_ll.h"
|
||||
#include "hal/adc_types.h"
|
||||
#ifdef CONFIG_PM_ENABLE
|
||||
#include "esp_pm.h"
|
||||
#endif
|
||||
#include "freertos/FreeRTOS.h"
|
||||
|
||||
#include "driver/adc_i2s_legacy.h"
|
||||
#include "driver/adc_types_legacy.h"
|
||||
|
||||
static __attribute__((unused)) const char *ADC_TAG = "ADC";
|
||||
|
||||
#define ADC_CHECK_RET(fun_ret) ({ \
|
||||
if (fun_ret != ESP_OK) { \
|
||||
ESP_LOGE(ADC_TAG,"%s:%d",__FUNCTION__,__LINE__); \
|
||||
return ESP_FAIL; \
|
||||
} \
|
||||
})
|
||||
|
||||
#define ADC_CHECK(a, str, ret_val) ({ \
|
||||
if (!(a)) { \
|
||||
ESP_LOGE(ADC_TAG,"%s(%d): %s", __FUNCTION__, __LINE__, str); \
|
||||
return (ret_val); \
|
||||
} \
|
||||
})
|
||||
|
||||
#define ADC_CHANNEL_CHECK(periph, channel) ADC_CHECK(channel < SOC_ADC_CHANNEL_NUM(periph), "ADC"#periph" channel error", ESP_ERR_INVALID_ARG)
|
||||
#define ADC_GET_IO_NUM(periph, channel) (adc_channel_io_map[periph][channel])
|
||||
|
||||
extern portMUX_TYPE rtc_spinlock; //TODO: Will be placed in the appropriate position after the rtc module is finished.
|
||||
#define ADC_ENTER_CRITICAL() portENTER_CRITICAL(&rtc_spinlock)
|
||||
#define ADC_EXIT_CRITICAL() portEXIT_CRITICAL(&rtc_spinlock)
|
||||
|
||||
#ifdef CONFIG_PM_ENABLE
|
||||
esp_pm_lock_handle_t adc_digi_arbiter_lock = NULL;
|
||||
#endif //CONFIG_PM_ENABLE
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
/*---------------------------------------------------------------
|
||||
ESP32 Deprecated ADC APIs and functions
|
||||
---------------------------------------------------------------*/
|
||||
#define DIG_ADC_OUTPUT_FORMAT_DEFUALT (ADC_DIGI_FORMAT_12BIT)
|
||||
#define DIG_ADC_ATTEN_DEFUALT (ADC_ATTEN_DB_12)
|
||||
#define DIG_ADC_BIT_WIDTH_DEFUALT (3) //3 for ADC_WIDTH_BIT_12
|
||||
|
||||
/**
|
||||
* @brief ADC digital controller (DMA mode) conversion rules setting.
|
||||
*/
|
||||
typedef struct {
|
||||
union {
|
||||
struct {
|
||||
uint8_t atten: 2; /*!< ADC sampling voltage attenuation configuration. Modification of attenuation affects the range of measurements.
|
||||
0: measurement range 0 - 800mV,
|
||||
1: measurement range 0 - 1100mV,
|
||||
2: measurement range 0 - 1350mV,
|
||||
3: measurement range 0 - 2600mV. */
|
||||
uint8_t bit_width: 2; /*!< ADC resolution.
|
||||
- 0: 9 bit;
|
||||
- 1: 10 bit;
|
||||
- 2: 11 bit;
|
||||
- 3: 12 bit. */
|
||||
int8_t channel: 4; /*!< ADC channel index. */
|
||||
};
|
||||
uint8_t val; /*!<Raw data value */
|
||||
};
|
||||
} adc_digi_pattern_table_t;
|
||||
|
||||
/**
|
||||
* @brief ADC digital controller (DMA mode) output data format option.
|
||||
*/
|
||||
typedef enum {
|
||||
ADC_DIGI_FORMAT_12BIT, /*!<ADC to DMA data format, [15:12]-channel, [11: 0]-12 bits ADC data (`adc_digi_output_data_t`). Note: For single convert mode. */
|
||||
ADC_DIGI_FORMAT_11BIT, /*!<ADC to DMA data format, [15]-adc unit, [14:11]-channel, [10: 0]-11 bits ADC data (`adc_digi_output_data_t`). Note: For multi or alter convert mode. */
|
||||
ADC_DIGI_FORMAT_MAX,
|
||||
} adc_digi_format_t;
|
||||
|
||||
/**
|
||||
* Explanation of the relationship between `conv_limit_num`, `dma_eof_num` and the number of DMA outputs:
|
||||
*
|
||||
* +---------------------+--------+--------+--------+
|
||||
* | conv_mode | single | both | alter |
|
||||
* +---------------------+--------+--------+--------+
|
||||
* | trigger meas times | 1 | 1 | 1 |
|
||||
* +---------------------+--------+--------+--------+
|
||||
* | conv_limit_num | +1 | +1 | +1 |
|
||||
* | dma_eof_num | +1 | +2 | +1 |
|
||||
* | dma output (byte) | +2 | +4 | +2 |
|
||||
* +---------------------+--------+--------+--------+
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t adc1_pattern_len; /*!<Pattern table length for digital controller. Range: 0 ~ 16 (0: Don't change the pattern table setting).
|
||||
The pattern table that defines the conversion rules for each SAR ADC. Each table has 16 items, in which channel selection,
|
||||
resolution and attenuation are stored. When the conversion is started, the controller reads conversion rules from the
|
||||
pattern table one by one. For each controller the scan sequence has at most 16 different rules before repeating itself. */
|
||||
uint32_t adc2_pattern_len; /*!<Refer to ``adc1_pattern_len`` */
|
||||
adc_digi_pattern_table_t *adc1_pattern; /*!<Pointer to pattern table for digital controller. The table size defined by `adc1_pattern_len`. */
|
||||
adc_digi_pattern_table_t *adc2_pattern; /*!<Refer to `adc1_pattern` */
|
||||
adc_digi_convert_mode_t conv_mode; /*!<ADC conversion mode for digital controller. See ``adc_digi_convert_mode_t``. */
|
||||
adc_digi_format_t format; /*!<ADC output data format for digital controller. See ``adc_digi_format_t``. */
|
||||
} adc_digi_config_t;
|
||||
|
||||
/**
|
||||
* Set adc output 16-bit-data format from digital controller.
|
||||
*
|
||||
* @param data_sel 1: [15] unit, [14:11] channel, [10:0] data, 11-bit-width at most. Only work under `ADC_LL_DIGI_CONV_BOTH_UNIT` or `ADC_LL_DIGI_CONV_ALTER_UNIT` mode.
|
||||
* 0: [15:12] channel, [11:0] data, 12-bit-width at most. Only work under `ADC_LL_DIGI_CONV_ONLY_ADC1` or `ADC_LL_DIGI_CONV_ONLY_ADC2` mode
|
||||
* @note see `adc_ll_digi_pattern_table_t` for more detail of data bit width
|
||||
*/
|
||||
static inline void adc_ll_digi_set_output_format(bool data_sel)
|
||||
{
|
||||
SYSCON.saradc_ctrl.data_sar_sel = data_sel;
|
||||
}
|
||||
|
||||
static inline void adc_ll_digi_prepare_pattern_table(adc_unit_t adc_n, uint32_t pattern_index, adc_digi_pattern_table_t pattern)
|
||||
{
|
||||
uint32_t tab;
|
||||
uint8_t index = pattern_index / 4;
|
||||
uint8_t offset = (pattern_index % 4) * 8;
|
||||
if (adc_n == ADC_UNIT_1) {
|
||||
tab = SYSCON.saradc_sar1_patt_tab[index]; // Read old register value
|
||||
tab &= (~(0xFF000000 >> offset)); // clear old data
|
||||
tab |= ((uint32_t)pattern.val << 24) >> offset; // Fill in the new data
|
||||
SYSCON.saradc_sar1_patt_tab[index] = tab; // Write back
|
||||
} else { // adc_n == ADC_UNIT_2
|
||||
tab = SYSCON.saradc_sar2_patt_tab[index]; // Read old register value
|
||||
tab &= (~(0xFF000000 >> offset)); // clear old data
|
||||
tab |= ((uint32_t)pattern.val << 24) >> offset; // Fill in the new data
|
||||
SYSCON.saradc_sar2_patt_tab[index] = tab; // Write back
|
||||
}
|
||||
}
|
||||
|
||||
static void adc_digi_controller_reg_set(const adc_digi_config_t *cfg)
|
||||
{
|
||||
/* On ESP32, only support ADC1 */
|
||||
switch (cfg->conv_mode) {
|
||||
case ADC_CONV_SINGLE_UNIT_1:
|
||||
adc_ll_digi_set_convert_mode(ADC_LL_DIGI_CONV_ONLY_ADC1);
|
||||
break;
|
||||
case ADC_CONV_SINGLE_UNIT_2:
|
||||
adc_ll_digi_set_convert_mode(ADC_LL_DIGI_CONV_ONLY_ADC2);
|
||||
break;
|
||||
case ADC_CONV_BOTH_UNIT:
|
||||
adc_ll_digi_set_convert_mode(ADC_LL_DIGI_CONV_BOTH_UNIT);
|
||||
break;
|
||||
case ADC_CONV_ALTER_UNIT:
|
||||
adc_ll_digi_set_convert_mode(ADC_LL_DIGI_CONV_ALTER_UNIT);
|
||||
break;
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
|
||||
if (cfg->conv_mode & ADC_CONV_SINGLE_UNIT_1) {
|
||||
adc_ll_set_controller(ADC_UNIT_1, ADC_LL_CTRL_DIG);
|
||||
if (cfg->adc1_pattern_len) {
|
||||
adc_ll_digi_clear_pattern_table(ADC_UNIT_1);
|
||||
adc_ll_digi_set_pattern_table_len(ADC_UNIT_1, cfg->adc1_pattern_len);
|
||||
for (uint32_t i = 0; i < cfg->adc1_pattern_len; i++) {
|
||||
adc_ll_digi_prepare_pattern_table(ADC_UNIT_1, i, cfg->adc1_pattern[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (cfg->conv_mode & ADC_CONV_SINGLE_UNIT_2) {
|
||||
adc_ll_set_controller(ADC_UNIT_2, ADC_LL_CTRL_DIG);
|
||||
if (cfg->adc2_pattern_len) {
|
||||
adc_ll_digi_clear_pattern_table(ADC_UNIT_2);
|
||||
adc_ll_digi_set_pattern_table_len(ADC_UNIT_2, cfg->adc2_pattern_len);
|
||||
for (uint32_t i = 0; i < cfg->adc2_pattern_len; i++) {
|
||||
adc_ll_digi_prepare_pattern_table(ADC_UNIT_2, i, cfg->adc2_pattern[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
adc_ll_digi_set_output_format(cfg->format);
|
||||
adc_ll_digi_convert_limit_enable(ADC_LL_DEFAULT_CONV_LIMIT_EN);
|
||||
adc_ll_digi_set_convert_limit_num(ADC_LL_DEFAULT_CONV_LIMIT_NUM);
|
||||
adc_ll_digi_set_data_source(ADC_I2S_DATA_SRC_ADC);
|
||||
}
|
||||
|
||||
esp_err_t adc_set_i2s_data_source(adc_i2s_source_t src)
|
||||
{
|
||||
ADC_CHECK((src == ADC_I2S_DATA_SRC_IO_SIG || src == ADC_I2S_DATA_SRC_ADC), "ADC i2s data source error", ESP_ERR_INVALID_ARG);
|
||||
ADC_ENTER_CRITICAL();
|
||||
adc_ll_digi_set_data_source(src);
|
||||
ADC_EXIT_CRITICAL();
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
extern esp_err_t adc_common_gpio_init(adc_unit_t adc_unit, adc_channel_t channel);
|
||||
esp_err_t adc_i2s_mode_init(adc_unit_t adc_unit, adc_channel_t channel)
|
||||
{
|
||||
if (adc_unit == ADC_UNIT_1) {
|
||||
ADC_CHANNEL_CHECK(ADC_UNIT_1, channel);
|
||||
} else if (adc_unit == ADC_UNIT_2) {
|
||||
//ADC2 does not support DMA mode
|
||||
ADC_CHECK(false, "ADC2 not support DMA for now.", ESP_ERR_INVALID_ARG);
|
||||
ADC_CHANNEL_CHECK(ADC_UNIT_2, channel);
|
||||
}
|
||||
|
||||
adc_digi_pattern_table_t adc1_pattern[1];
|
||||
adc_digi_pattern_table_t adc2_pattern[1];
|
||||
adc_digi_config_t dig_cfg = {
|
||||
.format = DIG_ADC_OUTPUT_FORMAT_DEFUALT,
|
||||
.conv_mode = ADC_CONV_SINGLE_UNIT_1,
|
||||
};
|
||||
|
||||
if (adc_unit == ADC_UNIT_1) {
|
||||
adc1_pattern[0].atten = DIG_ADC_ATTEN_DEFUALT;
|
||||
adc1_pattern[0].bit_width = DIG_ADC_BIT_WIDTH_DEFUALT;
|
||||
adc1_pattern[0].channel = channel;
|
||||
dig_cfg.adc1_pattern_len = 1;
|
||||
dig_cfg.adc1_pattern = adc1_pattern;
|
||||
} else if (adc_unit == ADC_UNIT_2) {
|
||||
adc2_pattern[0].atten = DIG_ADC_ATTEN_DEFUALT;
|
||||
adc2_pattern[0].bit_width = DIG_ADC_BIT_WIDTH_DEFUALT;
|
||||
adc2_pattern[0].channel = channel;
|
||||
dig_cfg.adc2_pattern_len = 1;
|
||||
dig_cfg.adc2_pattern = adc2_pattern;
|
||||
}
|
||||
adc_common_gpio_init(adc_unit, channel);
|
||||
ADC_ENTER_CRITICAL();
|
||||
adc_ll_digi_set_fsm_time(ADC_LL_FSM_RSTB_WAIT_DEFAULT, ADC_LL_FSM_START_WAIT_DEFAULT,
|
||||
ADC_LL_FSM_STANDBY_WAIT_DEFAULT);
|
||||
adc_ll_set_sample_cycle(ADC_LL_SAMPLE_CYCLE_DEFAULT);
|
||||
adc_ll_pwdet_set_cct(ADC_LL_PWDET_CCT_DEFAULT);
|
||||
adc_ll_digi_output_invert(ADC_UNIT_1, ADC_LL_DIGI_DATA_INVERT_DEFAULT(ADC_UNIT_1));
|
||||
adc_ll_digi_output_invert(ADC_UNIT_2, ADC_LL_DIGI_DATA_INVERT_DEFAULT(ADC_UNIT_2));
|
||||
adc_ll_digi_set_clk_div(ADC_LL_DIGI_SAR_CLK_DIV_DEFAULT);
|
||||
adc_digi_controller_reg_set(&dig_cfg);
|
||||
ADC_EXIT_CRITICAL();
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
#endif //#if CONFIG_IDF_TARGET_ESP32
|
||||
950
components/driver/deprecated/adc_legacy.c
Normal file
950
components/driver/deprecated/adc_legacy.c
Normal file
@@ -0,0 +1,950 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2019-2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <esp_types.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/semphr.h"
|
||||
#include "freertos/timers.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_check.h"
|
||||
#include "esp_pm.h"
|
||||
#include "soc/rtc.h"
|
||||
#include "soc/soc_caps.h"
|
||||
#include "esp_private/gpio.h"
|
||||
#include "sys/lock.h"
|
||||
#include "esp_private/adc_share_hw_ctrl.h"
|
||||
#include "esp_private/sar_periph_ctrl.h"
|
||||
#include "adc1_private.h"
|
||||
#include "hal/adc_types.h"
|
||||
#include "hal/adc_hal.h"
|
||||
#include "hal/adc_ll.h"
|
||||
#include "hal/adc_hal_common.h"
|
||||
#include "esp_private/esp_clk_tree_common.h"
|
||||
#include "esp_private/regi2c_ctrl.h"
|
||||
#include "esp_private/periph_ctrl.h"
|
||||
#include "driver/adc_types_legacy.h"
|
||||
#include "esp_clk_tree.h"
|
||||
|
||||
#if SOC_DAC_SUPPORTED
|
||||
#include "hal/dac_types.h"
|
||||
#include "hal/dac_ll.h"
|
||||
#endif
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32S3
|
||||
#include "esp_efuse_rtc_calib.h"
|
||||
#endif
|
||||
|
||||
static const char *ADC_TAG = "ADC";
|
||||
|
||||
#define ADC_GET_IO_NUM(periph, channel) (adc_channel_io_map[periph][channel])
|
||||
|
||||
//////////////////////// Locks ///////////////////////////////////////////
|
||||
extern portMUX_TYPE rtc_spinlock; //TODO: Will be placed in the appropriate position after the rtc module is finished.
|
||||
|
||||
#define RTC_ENTER_CRITICAL() portENTER_CRITICAL(&rtc_spinlock)
|
||||
#define RTC_EXIT_CRITICAL() portEXIT_CRITICAL(&rtc_spinlock)
|
||||
#define DIGI_ENTER_CRITICAL()
|
||||
#define DIGI_EXIT_CRITICAL()
|
||||
|
||||
#define ADC_POWER_ENTER() RTC_ENTER_CRITICAL()
|
||||
#define ADC_POWER_EXIT() RTC_EXIT_CRITICAL()
|
||||
|
||||
#define DIGI_CONTROLLER_ENTER() DIGI_ENTER_CRITICAL()
|
||||
#define DIGI_CONTROLLER_EXIT() DIGI_EXIT_CRITICAL()
|
||||
|
||||
#define SARADC1_ENTER() RTC_ENTER_CRITICAL()
|
||||
#define SARADC1_EXIT() RTC_EXIT_CRITICAL()
|
||||
|
||||
#define SARADC2_ENTER() RTC_ENTER_CRITICAL()
|
||||
#define SARADC2_EXIT() RTC_EXIT_CRITICAL()
|
||||
|
||||
//n stands for ADC unit: 1 for ADC1 and 2 for ADC2. Currently both unit touches the same registers
|
||||
#define VREF_ENTER(n) RTC_ENTER_CRITICAL()
|
||||
#define VREF_EXIT(n) RTC_EXIT_CRITICAL()
|
||||
|
||||
#define FSM_ENTER() RTC_ENTER_CRITICAL()
|
||||
#define FSM_EXIT() RTC_EXIT_CRITICAL()
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32P4
|
||||
//prevent ADC1 being used by I2S dma and other tasks at the same time.
|
||||
static _lock_t adc1_dma_lock;
|
||||
#define SARADC1_ACQUIRE() _lock_acquire( &adc1_dma_lock )
|
||||
#define SARADC1_RELEASE() _lock_release( &adc1_dma_lock )
|
||||
#endif
|
||||
|
||||
/*
|
||||
In ADC2, there're two locks used for different cases:
|
||||
1. lock shared with app and Wi-Fi:
|
||||
ESP32:
|
||||
When Wi-Fi using the ADC2, we assume it will never stop, so app checks the lock and returns immediately if failed.
|
||||
ESP32S2:
|
||||
The controller's control over the ADC is determined by the arbiter. There is no need to control by lock.
|
||||
|
||||
2. lock shared between tasks:
|
||||
when several tasks sharing the ADC2, we want to guarantee
|
||||
all the requests will be handled.
|
||||
Since conversions are short (about 31us), app returns the lock very soon,
|
||||
we use a spinlock to stand there waiting to do conversions one by one.
|
||||
|
||||
adc2_spinlock should be acquired first, then call `adc_lock_release(ADC_UNIT_2)` or rtc_spinlock.
|
||||
*/
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32S2
|
||||
#ifdef CONFIG_PM_ENABLE
|
||||
static esp_pm_lock_handle_t s_adc2_arbiter_lock;
|
||||
#endif //CONFIG_PM_ENABLE
|
||||
#endif // !CONFIG_IDF_TARGET_ESP32
|
||||
|
||||
static uint32_t clk_src_freq_hz;
|
||||
|
||||
static esp_err_t adc_hal_convert(adc_unit_t adc_n, int channel, uint32_t clk_src_freq_hz, int *out_raw);
|
||||
|
||||
/*---------------------------------------------------------------
|
||||
ADC Common
|
||||
---------------------------------------------------------------*/
|
||||
esp_err_t adc1_pad_get_io_num(adc1_channel_t channel, gpio_num_t *gpio_num)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(channel < SOC_ADC_CHANNEL_NUM(ADC_UNIT_1), ESP_ERR_INVALID_ARG, ADC_TAG, "invalid channel");
|
||||
|
||||
int io = ADC_GET_IO_NUM(ADC_UNIT_1, channel);
|
||||
if (io < 0) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
} else {
|
||||
*gpio_num = (gpio_num_t)io;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
#if (SOC_ADC_PERIPH_NUM >= 2)
|
||||
esp_err_t adc2_pad_get_io_num(adc2_channel_t channel, gpio_num_t *gpio_num)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(channel < SOC_ADC_CHANNEL_NUM(ADC_UNIT_2), ESP_ERR_INVALID_ARG, ADC_TAG, "invalid channel");
|
||||
|
||||
int io = ADC_GET_IO_NUM(ADC_UNIT_2, channel);
|
||||
if (io < 0) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
} else {
|
||||
*gpio_num = (gpio_num_t)io;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
//------------------------------------------------------------RTC Single Read----------------------------------------------//
|
||||
#if SOC_ADC_RTC_CTRL_SUPPORTED
|
||||
esp_err_t adc_set_clk_div(uint8_t clk_div)
|
||||
{
|
||||
DIGI_CONTROLLER_ENTER();
|
||||
adc_ll_digi_set_clk_div(clk_div);
|
||||
DIGI_CONTROLLER_EXIT();
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static void adc_rtc_chan_init(adc_unit_t adc_unit)
|
||||
{
|
||||
if (adc_unit == ADC_UNIT_1) {
|
||||
/* Workaround: Disable the synchronization operation function of ADC1 and DAC.
|
||||
If enabled(default), ADC RTC controller sampling will cause the DAC channel output voltage. */
|
||||
#if SOC_DAC_SUPPORTED
|
||||
dac_ll_rtc_sync_by_adc(false);
|
||||
#endif
|
||||
adc_oneshot_ll_output_invert(ADC_UNIT_1, ADC_LL_DATA_INVERT_DEFAULT(ADC_UNIT_1));
|
||||
adc_ll_set_sar_clk_div(ADC_UNIT_1, ADC_LL_SAR_CLK_DIV_DEFAULT(ADC_UNIT_1));
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32
|
||||
adc_ll_hall_disable(); //Disable other peripherals.
|
||||
adc_ll_amp_disable(); //Currently the LNA is not open, close it by default.
|
||||
#endif
|
||||
}
|
||||
if (adc_unit == ADC_UNIT_2) {
|
||||
adc_ll_pwdet_set_cct(ADC_LL_PWDET_CCT_DEFAULT);
|
||||
adc_oneshot_ll_output_invert(ADC_UNIT_2, ADC_LL_DATA_INVERT_DEFAULT(ADC_UNIT_2));
|
||||
adc_ll_set_sar_clk_div(ADC_UNIT_2, ADC_LL_SAR_CLK_DIV_DEFAULT(ADC_UNIT_2));
|
||||
}
|
||||
}
|
||||
|
||||
esp_err_t adc_common_gpio_init(adc_unit_t adc_unit, adc_channel_t channel)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(channel < SOC_ADC_CHANNEL_NUM(adc_unit), ESP_ERR_INVALID_ARG, ADC_TAG, "invalid channel");
|
||||
gpio_num_t gpio_num = 0;
|
||||
//If called with `ADC_UNIT_BOTH (ADC_UNIT_1 | ADC_UNIT_2)`, both if blocks will be run
|
||||
if (adc_unit == ADC_UNIT_1) {
|
||||
gpio_num = ADC_GET_IO_NUM(ADC_UNIT_1, channel);
|
||||
|
||||
} else if (adc_unit == ADC_UNIT_2) {
|
||||
gpio_num = ADC_GET_IO_NUM(ADC_UNIT_2, channel);
|
||||
} else {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
return gpio_config_as_analog(gpio_num);
|
||||
}
|
||||
|
||||
esp_err_t adc_set_data_inv(adc_unit_t adc_unit, bool inv_en)
|
||||
{
|
||||
if (adc_unit == ADC_UNIT_1) {
|
||||
SARADC1_ENTER();
|
||||
adc_oneshot_ll_output_invert(ADC_UNIT_1, inv_en);
|
||||
SARADC1_EXIT();
|
||||
}
|
||||
if (adc_unit == ADC_UNIT_2) {
|
||||
SARADC2_ENTER();
|
||||
adc_oneshot_ll_output_invert(ADC_UNIT_2, inv_en);
|
||||
SARADC2_EXIT();
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t adc_set_data_width(adc_unit_t adc_unit, adc_bits_width_t width_bit)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(width_bit < ADC_WIDTH_MAX, ESP_ERR_INVALID_ARG, ADC_TAG, "unsupported bit width");
|
||||
adc_bitwidth_t bitwidth = 0;
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
if ((uint32_t)width_bit == (uint32_t)ADC_BITWIDTH_DEFAULT) {
|
||||
bitwidth = SOC_ADC_RTC_MAX_BITWIDTH;
|
||||
} else {
|
||||
switch (width_bit) {
|
||||
case ADC_WIDTH_BIT_9:
|
||||
bitwidth = ADC_BITWIDTH_9;
|
||||
break;
|
||||
case ADC_WIDTH_BIT_10:
|
||||
bitwidth = ADC_BITWIDTH_10;
|
||||
break;
|
||||
case ADC_WIDTH_BIT_11:
|
||||
bitwidth = ADC_BITWIDTH_11;
|
||||
break;
|
||||
case ADC_WIDTH_BIT_12:
|
||||
bitwidth = ADC_BITWIDTH_12;
|
||||
break;
|
||||
default:
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
}
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||
bitwidth = ADC_BITWIDTH_13;
|
||||
#else //esp32s3
|
||||
bitwidth = ADC_BITWIDTH_12;
|
||||
#endif
|
||||
|
||||
if (adc_unit == ADC_UNIT_1) {
|
||||
SARADC1_ENTER();
|
||||
adc_oneshot_ll_set_output_bits(ADC_UNIT_1, bitwidth);
|
||||
SARADC1_EXIT();
|
||||
}
|
||||
if (adc_unit == ADC_UNIT_2) {
|
||||
SARADC2_ENTER();
|
||||
adc_oneshot_ll_set_output_bits(ADC_UNIT_2, bitwidth);
|
||||
SARADC2_EXIT();
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reset RTC controller FSM.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
#if !CONFIG_IDF_TARGET_ESP32
|
||||
esp_err_t adc_rtc_reset(void)
|
||||
{
|
||||
FSM_ENTER();
|
||||
adc_ll_rtc_reset();
|
||||
FSM_EXIT();
|
||||
return ESP_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*-------------------------------------------------------------------------------------
|
||||
* ADC1
|
||||
*------------------------------------------------------------------------------------*/
|
||||
esp_err_t adc1_config_channel_atten(adc1_channel_t channel, adc_atten_t atten)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(channel < SOC_ADC_CHANNEL_NUM(ADC_UNIT_1), ESP_ERR_INVALID_ARG, ADC_TAG, "invalid channel");
|
||||
ESP_RETURN_ON_FALSE(atten < SOC_ADC_ATTEN_NUM, ESP_ERR_INVALID_ARG, ADC_TAG, "ADC Atten Err");
|
||||
|
||||
#if SOC_ADC_DIG_CTRL_SUPPORTED && !SOC_ADC_RTC_CTRL_SUPPORTED
|
||||
if (!clk_src_freq_hz) {
|
||||
//should never fail
|
||||
esp_clk_tree_src_get_freq_hz(ADC_DIGI_CLK_SRC_DEFAULT, ESP_CLK_TREE_SRC_FREQ_PRECISION_CACHED, &clk_src_freq_hz);
|
||||
}
|
||||
#endif //#if SOC_ADC_DIG_CTRL_SUPPORTED && !SOC_ADC_RTC_CTRL_SUPPORTED
|
||||
|
||||
adc_common_gpio_init(ADC_UNIT_1, channel);
|
||||
SARADC1_ENTER();
|
||||
adc_rtc_chan_init(ADC_UNIT_1);
|
||||
adc_oneshot_ll_set_atten(ADC_UNIT_1, channel, atten);
|
||||
SARADC1_EXIT();
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t adc1_config_width(adc_bits_width_t width_bit)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(width_bit < ADC_WIDTH_MAX, ESP_ERR_INVALID_ARG, ADC_TAG, "unsupported bit width");
|
||||
adc_bitwidth_t bitwidth = 0;
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
if ((uint32_t)width_bit == (uint32_t)ADC_BITWIDTH_DEFAULT) {
|
||||
bitwidth = SOC_ADC_RTC_MAX_BITWIDTH;
|
||||
} else {
|
||||
switch (width_bit) {
|
||||
case ADC_WIDTH_BIT_9:
|
||||
bitwidth = ADC_BITWIDTH_9;
|
||||
break;
|
||||
case ADC_WIDTH_BIT_10:
|
||||
bitwidth = ADC_BITWIDTH_10;
|
||||
break;
|
||||
case ADC_WIDTH_BIT_11:
|
||||
bitwidth = ADC_BITWIDTH_11;
|
||||
break;
|
||||
case ADC_WIDTH_BIT_12:
|
||||
bitwidth = ADC_BITWIDTH_12;
|
||||
break;
|
||||
default:
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
}
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||
bitwidth = ADC_BITWIDTH_13;
|
||||
#else //esp32s3
|
||||
bitwidth = ADC_BITWIDTH_12;
|
||||
#endif
|
||||
|
||||
SARADC1_ENTER();
|
||||
adc_oneshot_ll_set_output_bits(ADC_UNIT_1, bitwidth);
|
||||
SARADC1_EXIT();
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t adc1_dma_mode_acquire(void)
|
||||
{
|
||||
/* Use locks to avoid digtal and RTC controller conflicts.
|
||||
for adc1, block until acquire the lock. */
|
||||
SARADC1_ACQUIRE();
|
||||
ESP_LOGD(ADC_TAG, "dma mode takes adc1 lock.");
|
||||
|
||||
sar_periph_ctrl_adc_continuous_power_acquire();
|
||||
|
||||
SARADC1_ENTER();
|
||||
/* switch SARADC into DIG channel */
|
||||
adc_ll_set_controller(ADC_UNIT_1, ADC_LL_CTRL_DIG);
|
||||
SARADC1_EXIT();
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t adc1_rtc_mode_acquire(void)
|
||||
{
|
||||
/* Use locks to avoid digtal and RTC controller conflicts.
|
||||
for adc1, block until acquire the lock. */
|
||||
SARADC1_ACQUIRE();
|
||||
sar_periph_ctrl_adc_oneshot_power_acquire();
|
||||
|
||||
SARADC1_ENTER();
|
||||
/* switch SARADC into RTC channel. */
|
||||
adc_ll_set_controller(ADC_UNIT_1, ADC_LL_CTRL_RTC);
|
||||
SARADC1_EXIT();
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t adc1_lock_release(void)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE((uint32_t *)adc1_dma_lock != NULL, ESP_ERR_INVALID_STATE, ADC_TAG, "adc1 lock release called before acquire");
|
||||
/* Use locks to avoid digtal and RTC controller conflicts. for adc1, block until acquire the lock. */
|
||||
|
||||
sar_periph_ctrl_adc_oneshot_power_release();
|
||||
SARADC1_RELEASE();
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
int adc1_get_raw(adc1_channel_t channel)
|
||||
{
|
||||
int adc_value;
|
||||
ESP_RETURN_ON_FALSE(channel < SOC_ADC_CHANNEL_NUM(ADC_UNIT_1), ESP_ERR_INVALID_ARG, ADC_TAG, "invalid channel");
|
||||
adc1_rtc_mode_acquire();
|
||||
|
||||
ANALOG_CLOCK_ENABLE();
|
||||
|
||||
#if SOC_ADC_CALIBRATION_V1_SUPPORTED
|
||||
adc_hal_calibration_init(ADC_UNIT_1);
|
||||
adc_atten_t atten = adc_ll_get_atten(ADC_UNIT_1, channel);
|
||||
adc_set_hw_calibration_code(ADC_UNIT_1, atten);
|
||||
#endif //SOC_ADC_CALIBRATION_V1_SUPPORTED
|
||||
|
||||
ANALOG_CLOCK_DISABLE();
|
||||
|
||||
SARADC1_ENTER();
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32
|
||||
adc_ll_hall_disable(); //Disable other peripherals.
|
||||
adc_ll_amp_disable(); //Currently the LNA is not open, close it by default.
|
||||
#endif
|
||||
adc_ll_set_controller(ADC_UNIT_1, ADC_LL_CTRL_RTC); //Set controller
|
||||
adc_oneshot_ll_set_channel(ADC_UNIT_1, channel);
|
||||
adc_hal_convert(ADC_UNIT_1, channel, clk_src_freq_hz, &adc_value); //Start conversion, For ADC1, the data always valid.
|
||||
#if !CONFIG_IDF_TARGET_ESP32
|
||||
adc_ll_rtc_reset(); //Reset FSM of rtc controller
|
||||
#endif
|
||||
SARADC1_EXIT();
|
||||
|
||||
adc1_lock_release();
|
||||
return adc_value;
|
||||
}
|
||||
|
||||
int adc1_get_voltage(adc1_channel_t channel) //Deprecated. Use adc1_get_raw() instead
|
||||
{
|
||||
return adc1_get_raw(channel);
|
||||
}
|
||||
|
||||
#if SOC_ULP_SUPPORTED
|
||||
void adc1_ulp_enable(void)
|
||||
{
|
||||
sar_periph_ctrl_adc_oneshot_power_acquire();
|
||||
|
||||
SARADC1_ENTER();
|
||||
adc_ll_set_controller(ADC_UNIT_1, ADC_LL_CTRL_ULP);
|
||||
/* since most users do not need LNA and HALL with uLP, we disable them here
|
||||
open them in the uLP if needed. */
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32
|
||||
/* disable other peripherals. */
|
||||
adc_ll_hall_disable();
|
||||
adc_ll_amp_disable();
|
||||
#endif
|
||||
SARADC1_EXIT();
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (SOC_ADC_PERIPH_NUM >= 2)
|
||||
/*---------------------------------------------------------------
|
||||
ADC2
|
||||
---------------------------------------------------------------*/
|
||||
esp_err_t adc2_config_channel_atten(adc2_channel_t channel, adc_atten_t atten)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(channel < SOC_ADC_CHANNEL_NUM(ADC_UNIT_2), ESP_ERR_INVALID_ARG, ADC_TAG, "invalid channel");
|
||||
ESP_RETURN_ON_FALSE(atten <= SOC_ADC_ATTEN_NUM, ESP_ERR_INVALID_ARG, ADC_TAG, "ADC2 Atten Err");
|
||||
#if SOC_ADC_DIG_CTRL_SUPPORTED && !SOC_ADC_RTC_CTRL_SUPPORTED
|
||||
if (!clk_src_freq_hz) {
|
||||
//should never fail
|
||||
esp_clk_tree_src_get_freq_hz(ADC_DIGI_CLK_SRC_DEFAULT, ESP_CLK_TREE_SRC_FREQ_PRECISION_CACHED, &clk_src_freq_hz);
|
||||
}
|
||||
#endif //#if SOC_ADC_DIG_CTRL_SUPPORTED && !SOC_ADC_RTC_CTRL_SUPPORTED
|
||||
|
||||
adc_common_gpio_init(ADC_UNIT_2, channel);
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
/** For ESP32S2 and S3, the right to use ADC2 is controlled by the arbiter, and there is no need to set a lock.*/
|
||||
if (adc_lock_try_acquire(ADC_UNIT_2) != ESP_OK) {
|
||||
//try the lock, return if failed (wifi using).
|
||||
return ESP_ERR_TIMEOUT;
|
||||
}
|
||||
#endif
|
||||
|
||||
//avoid collision with other tasks
|
||||
SARADC2_ENTER();
|
||||
adc_rtc_chan_init(ADC_UNIT_2);
|
||||
adc_oneshot_ll_set_atten(ADC_UNIT_2, channel, atten);
|
||||
SARADC2_EXIT();
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
adc_lock_release(ADC_UNIT_2);
|
||||
#endif
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static inline void adc2_init(void)
|
||||
{
|
||||
#if CONFIG_IDF_TARGET_ESP32S2
|
||||
#ifdef CONFIG_PM_ENABLE
|
||||
/* Lock APB clock. */
|
||||
if (s_adc2_arbiter_lock == NULL) {
|
||||
esp_pm_lock_create(ESP_PM_APB_FREQ_MAX, 0, "adc2", &s_adc2_arbiter_lock);
|
||||
}
|
||||
#endif //CONFIG_PM_ENABLE
|
||||
#endif //CONFIG_IDF_TARGET_ESP32S2
|
||||
}
|
||||
|
||||
static inline void adc2_dac_disable(adc2_channel_t channel)
|
||||
{
|
||||
#if SOC_DAC_SUPPORTED
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32
|
||||
if (channel == ADC2_CHANNEL_8) { // the same as DAC channel 0
|
||||
dac_ll_power_down(DAC_CHAN_0);
|
||||
} else if (channel == ADC2_CHANNEL_9) {
|
||||
dac_ll_power_down(DAC_CHAN_1);
|
||||
}
|
||||
#else
|
||||
if (channel == ADC2_CHANNEL_6) { // the same as DAC channel 0
|
||||
dac_ll_power_down(DAC_CHAN_0);
|
||||
} else if (channel == ADC2_CHANNEL_7) {
|
||||
dac_ll_power_down(DAC_CHAN_1);
|
||||
}
|
||||
#endif
|
||||
#endif // SOC_DAC_SUPPORTED
|
||||
}
|
||||
|
||||
/**
|
||||
* @note For ESP32S2:
|
||||
* The arbiter's working clock is APB_CLK. When the APB_CLK clock drops below 8 MHz, the arbiter must be in shield mode.
|
||||
* Or, the RTC controller will fail when get raw data.
|
||||
* This issue does not occur on digital controllers (DMA mode), and the hardware guarantees that there will be no errors.
|
||||
*/
|
||||
esp_err_t adc2_get_raw(adc2_channel_t channel, adc_bits_width_t width_bit, int *raw_out)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
int adc_value = 0;
|
||||
adc_bitwidth_t bitwidth = 0;
|
||||
|
||||
ESP_RETURN_ON_FALSE(raw_out != NULL, ESP_ERR_INVALID_ARG, ADC_TAG, "ADC out value err");
|
||||
ESP_RETURN_ON_FALSE(channel < ADC2_CHANNEL_MAX, ESP_ERR_INVALID_ARG, ADC_TAG, "ADC Channel Err");
|
||||
ESP_RETURN_ON_FALSE(width_bit < ADC_WIDTH_MAX, ESP_ERR_INVALID_ARG, ADC_TAG, "unsupported bit width");
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
if ((uint32_t)width_bit == (uint32_t)ADC_BITWIDTH_DEFAULT) {
|
||||
bitwidth = SOC_ADC_RTC_MAX_BITWIDTH;
|
||||
} else {
|
||||
switch (width_bit) {
|
||||
case ADC_WIDTH_BIT_9:
|
||||
bitwidth = ADC_BITWIDTH_9;
|
||||
break;
|
||||
case ADC_WIDTH_BIT_10:
|
||||
bitwidth = ADC_BITWIDTH_10;
|
||||
break;
|
||||
case ADC_WIDTH_BIT_11:
|
||||
bitwidth = ADC_BITWIDTH_11;
|
||||
break;
|
||||
case ADC_WIDTH_BIT_12:
|
||||
bitwidth = ADC_BITWIDTH_12;
|
||||
break;
|
||||
default:
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
}
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||
bitwidth = ADC_BITWIDTH_13;
|
||||
#else //esp32s3
|
||||
bitwidth = ADC_BITWIDTH_12;
|
||||
#endif
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
/** For ESP32S2 and S3, the right to use ADC2 is controlled by the arbiter, and there is no need to set a lock.*/
|
||||
if (adc_lock_try_acquire(ADC_UNIT_2) != ESP_OK) {
|
||||
//try the lock, return if failed (wifi using).
|
||||
return ESP_ERR_TIMEOUT;
|
||||
}
|
||||
#endif
|
||||
sar_periph_ctrl_adc_oneshot_power_acquire(); //in critical section with whole rtc module
|
||||
|
||||
#if SOC_ADC_CALIBRATION_V1_SUPPORTED
|
||||
adc_hal_calibration_init(ADC_UNIT_2);
|
||||
adc_atten_t atten = adc_ll_get_atten(ADC_UNIT_2, channel);
|
||||
adc_set_hw_calibration_code(ADC_UNIT_2, atten);
|
||||
#endif //SOC_ADC_CALIBRATION_V1_SUPPORTED
|
||||
|
||||
//avoid collision with other tasks
|
||||
adc2_init(); // in critical section with whole rtc module. because the PWDET use the same registers, place it here.
|
||||
SARADC2_ENTER();
|
||||
|
||||
#if SOC_ADC_ARBITER_SUPPORTED
|
||||
adc_arbiter_t config = ADC_ARBITER_CONFIG_DEFAULT();
|
||||
adc_hal_arbiter_config(&config);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ADC_DISABLE_DAC
|
||||
adc2_dac_disable(channel); //disable other peripherals
|
||||
#endif
|
||||
adc_oneshot_ll_set_output_bits(ADC_UNIT_2, bitwidth);
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32P4
|
||||
adc_ll_set_controller(ADC_UNIT_2, ADC_LL_CTRL_RTC);// set controller
|
||||
#else
|
||||
adc_ll_set_controller(ADC_UNIT_2, ADC_LL_CTRL_ARB);// set controller
|
||||
#endif
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32S2
|
||||
#ifdef CONFIG_PM_ENABLE
|
||||
if (s_adc2_arbiter_lock) {
|
||||
esp_pm_lock_acquire(s_adc2_arbiter_lock);
|
||||
}
|
||||
#endif //CONFIG_PM_ENABLE
|
||||
#endif //CONFIG_IDF_TARGET_ESP32
|
||||
|
||||
adc_oneshot_ll_set_channel(ADC_UNIT_2, channel);
|
||||
ret = adc_hal_convert(ADC_UNIT_2, channel, clk_src_freq_hz, &adc_value);
|
||||
if (ret != ESP_OK) {
|
||||
adc_value = -1;
|
||||
}
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32S2
|
||||
#ifdef CONFIG_PM_ENABLE
|
||||
/* Release APB clock. */
|
||||
if (s_adc2_arbiter_lock) {
|
||||
esp_pm_lock_release(s_adc2_arbiter_lock);
|
||||
}
|
||||
#endif //CONFIG_PM_ENABLE
|
||||
#endif //CONFIG_IDF_TARGET_ESP32
|
||||
SARADC2_EXIT();
|
||||
|
||||
sar_periph_ctrl_adc_oneshot_power_release();
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
adc_lock_release(ADC_UNIT_2);
|
||||
#endif
|
||||
|
||||
*raw_out = adc_value;
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t adc_vref_to_gpio(adc_unit_t adc_unit, gpio_num_t gpio)
|
||||
{
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32
|
||||
if (adc_unit == ADC_UNIT_1) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
#endif
|
||||
adc2_channel_t ch = ADC2_CHANNEL_MAX;
|
||||
/* Check if the GPIO supported. */
|
||||
for (int i = 0; i < ADC2_CHANNEL_MAX; i++) {
|
||||
if (gpio == ADC_GET_IO_NUM(ADC_UNIT_2, i)) {
|
||||
ch = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (ch == ADC2_CHANNEL_MAX) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
sar_periph_ctrl_adc_oneshot_power_acquire();
|
||||
if (adc_unit == ADC_UNIT_1) {
|
||||
VREF_ENTER(1);
|
||||
adc_ll_vref_output(ADC_UNIT_1, ch, true);
|
||||
VREF_EXIT(1);
|
||||
} else if (adc_unit == ADC_UNIT_2) {
|
||||
VREF_ENTER(2);
|
||||
adc_ll_vref_output(ADC_UNIT_2, ch, true);
|
||||
VREF_EXIT(2);
|
||||
}
|
||||
|
||||
//Configure RTC gpio, Only ADC2's channels IO are supported to output reference voltage.
|
||||
adc_common_gpio_init(ADC_UNIT_2, ch);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
#endif //SOC_ADC_RTC_CTRL_SUPPORTED
|
||||
#endif //#if (SOC_ADC_PERIPH_NUM >= 2)
|
||||
|
||||
#if SOC_ADC_DIG_CTRL_SUPPORTED && !SOC_ADC_RTC_CTRL_SUPPORTED
|
||||
/*---------------------------------------------------------------
|
||||
Legacy ADC Single Read Mode
|
||||
when RTC controller isn't supported
|
||||
---------------------------------------------------------------*/
|
||||
#include "esp_check.h"
|
||||
|
||||
portMUX_TYPE adc_reg_lock = portMUX_INITIALIZER_UNLOCKED;
|
||||
#define ADC_REG_LOCK_ENTER() portENTER_CRITICAL(&adc_reg_lock)
|
||||
#define ADC_REG_LOCK_EXIT() portEXIT_CRITICAL(&adc_reg_lock)
|
||||
|
||||
static adc_atten_t s_atten1_single[ADC1_CHANNEL_MAX]; //Array saving attenuate of each channel of ADC1, used by single read API
|
||||
#if (SOC_ADC_PERIPH_NUM >= 2)
|
||||
static adc_atten_t s_atten2_single[ADC2_CHANNEL_MAX]; //Array saving attenuate of each channel of ADC2, used by single read API
|
||||
#endif
|
||||
|
||||
static int8_t adc_digi_get_io_num(adc_unit_t adc_unit, uint8_t adc_channel)
|
||||
{
|
||||
assert(adc_unit < SOC_ADC_PERIPH_NUM);
|
||||
uint8_t adc_n = (adc_unit == ADC_UNIT_1) ? 0 : 1;
|
||||
return adc_channel_io_map[adc_n][adc_channel];
|
||||
}
|
||||
|
||||
static esp_err_t adc_digi_gpio_init(adc_unit_t adc_unit, uint16_t channel_mask)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
uint32_t n = 0;
|
||||
int8_t io = 0;
|
||||
|
||||
while (channel_mask) {
|
||||
if (channel_mask & 0x1) {
|
||||
io = adc_digi_get_io_num(adc_unit, n);
|
||||
if (io < 0) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
gpio_config_as_analog(io);
|
||||
}
|
||||
channel_mask = channel_mask >> 1;
|
||||
n++;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32C3
|
||||
esp_err_t adc_vref_to_gpio(adc_unit_t adc_unit, gpio_num_t gpio)
|
||||
{
|
||||
esp_err_t ret;
|
||||
uint32_t channel = ADC2_CHANNEL_MAX;
|
||||
if (adc_unit == ADC_UNIT_2) {
|
||||
for (int i = 0; i < ADC2_CHANNEL_MAX; i++) {
|
||||
if (gpio == ADC_GET_IO_NUM(ADC_UNIT_2, i)) {
|
||||
channel = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (channel == ADC2_CHANNEL_MAX) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
}
|
||||
|
||||
sar_periph_ctrl_adc_oneshot_power_acquire();
|
||||
if (adc_unit == ADC_UNIT_1) {
|
||||
RTC_ENTER_CRITICAL();
|
||||
adc_ll_vref_output(ADC_UNIT_1, channel, true);
|
||||
RTC_EXIT_CRITICAL();
|
||||
} else { //ADC_UNIT_2
|
||||
RTC_ENTER_CRITICAL();
|
||||
adc_ll_vref_output(ADC_UNIT_2, channel, true);
|
||||
RTC_EXIT_CRITICAL();
|
||||
}
|
||||
|
||||
ret = adc_digi_gpio_init(ADC_UNIT_2, BIT(channel));
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
esp_err_t adc1_config_width(adc_bits_width_t width_bit)
|
||||
{
|
||||
//On ESP32C3, the data width is always 12-bits.
|
||||
if (width_bit != ADC_WIDTH_BIT_12) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t adc1_config_channel_atten(adc1_channel_t channel, adc_atten_t atten)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(channel < SOC_ADC_CHANNEL_NUM(ADC_UNIT_1), ESP_ERR_INVALID_ARG, ADC_TAG, "ADC1 channel error");
|
||||
ESP_RETURN_ON_FALSE((atten < SOC_ADC_ATTEN_NUM), ESP_ERR_INVALID_ARG, ADC_TAG, "ADC Atten Err");
|
||||
#if SOC_ADC_DIG_CTRL_SUPPORTED && !SOC_ADC_RTC_CTRL_SUPPORTED
|
||||
if (!clk_src_freq_hz) {
|
||||
//should never fail
|
||||
esp_clk_tree_src_get_freq_hz(ADC_DIGI_CLK_SRC_DEFAULT, ESP_CLK_TREE_SRC_FREQ_PRECISION_CACHED, &clk_src_freq_hz);
|
||||
}
|
||||
#endif //#if SOC_ADC_DIG_CTRL_SUPPORTED && !SOC_ADC_RTC_CTRL_SUPPORTED
|
||||
|
||||
esp_err_t ret = ESP_OK;
|
||||
s_atten1_single[channel] = atten;
|
||||
ret = adc_digi_gpio_init(ADC_UNIT_1, BIT(channel));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int adc1_get_raw(adc1_channel_t channel)
|
||||
{
|
||||
int raw_out = 0;
|
||||
|
||||
if (adc_lock_try_acquire(ADC_UNIT_1) != ESP_OK) {
|
||||
return ESP_ERR_TIMEOUT;
|
||||
}
|
||||
|
||||
adc_apb_periph_claim();
|
||||
sar_periph_ctrl_adc_oneshot_power_acquire();
|
||||
esp_clk_tree_enable_src((soc_module_clk_t)ADC_DIGI_CLK_SRC_DEFAULT, true);
|
||||
adc_ll_digi_clk_sel(ADC_DIGI_CLK_SRC_DEFAULT);
|
||||
|
||||
adc_atten_t atten = s_atten1_single[channel];
|
||||
|
||||
ANALOG_CLOCK_ENABLE();
|
||||
|
||||
#if SOC_ADC_CALIBRATION_V1_SUPPORTED
|
||||
adc_hal_calibration_init(ADC_UNIT_1);
|
||||
adc_set_hw_calibration_code(ADC_UNIT_1, atten);
|
||||
#endif
|
||||
|
||||
ANALOG_CLOCK_DISABLE();
|
||||
|
||||
ADC_REG_LOCK_ENTER();
|
||||
adc_oneshot_ll_set_atten(ADC_UNIT_1, channel, atten);
|
||||
adc_hal_convert(ADC_UNIT_1, channel, clk_src_freq_hz, &raw_out);
|
||||
ADC_REG_LOCK_EXIT();
|
||||
|
||||
sar_periph_ctrl_adc_oneshot_power_release();
|
||||
adc_apb_periph_free();
|
||||
adc_lock_release(ADC_UNIT_1);
|
||||
|
||||
return raw_out;
|
||||
}
|
||||
|
||||
#if (SOC_ADC_PERIPH_NUM >= 2)
|
||||
esp_err_t adc2_config_channel_atten(adc2_channel_t channel, adc_atten_t atten)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(channel < SOC_ADC_CHANNEL_NUM(ADC_UNIT_2), ESP_ERR_INVALID_ARG, ADC_TAG, "ADC2 channel error");
|
||||
ESP_RETURN_ON_FALSE((atten <= ADC_ATTEN_DB_12), ESP_ERR_INVALID_ARG, ADC_TAG, "ADC2 Atten Err");
|
||||
|
||||
esp_err_t ret = ESP_OK;
|
||||
s_atten2_single[channel] = atten;
|
||||
ret = adc_digi_gpio_init(ADC_UNIT_2, BIT(channel));
|
||||
|
||||
#if SOC_ADC_CALIBRATION_V1_SUPPORTED
|
||||
adc_hal_calibration_init(ADC_UNIT_2);
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t adc2_get_raw(adc2_channel_t channel, adc_bits_width_t width_bit, int *raw_out)
|
||||
{
|
||||
//On ESP32C3, the data width is always 12-bits.
|
||||
if (width_bit != ADC_WIDTH_BIT_12) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
#if SOC_ADC_DIG_CTRL_SUPPORTED && !SOC_ADC_RTC_CTRL_SUPPORTED
|
||||
if (!clk_src_freq_hz) {
|
||||
//should never fail
|
||||
esp_clk_tree_src_get_freq_hz(ADC_DIGI_CLK_SRC_DEFAULT, ESP_CLK_TREE_SRC_FREQ_PRECISION_CACHED, &clk_src_freq_hz);
|
||||
}
|
||||
#endif //#if SOC_ADC_DIG_CTRL_SUPPORTED && !SOC_ADC_RTC_CTRL_SUPPORTED
|
||||
|
||||
esp_err_t ret = ESP_OK;
|
||||
|
||||
if (adc_lock_try_acquire(ADC_UNIT_2) != ESP_OK) {
|
||||
return ESP_ERR_TIMEOUT;
|
||||
}
|
||||
|
||||
adc_apb_periph_claim();
|
||||
sar_periph_ctrl_adc_oneshot_power_acquire();
|
||||
esp_clk_tree_enable_src((soc_module_clk_t)ADC_DIGI_CLK_SRC_DEFAULT, true);
|
||||
adc_ll_digi_clk_sel(ADC_DIGI_CLK_SRC_DEFAULT);
|
||||
|
||||
#if SOC_ADC_ARBITER_SUPPORTED
|
||||
adc_arbiter_t config = ADC_ARBITER_CONFIG_DEFAULT();
|
||||
adc_hal_arbiter_config(&config);
|
||||
#endif
|
||||
|
||||
adc_atten_t atten = s_atten2_single[channel];
|
||||
#if SOC_ADC_CALIBRATION_V1_SUPPORTED
|
||||
adc_set_hw_calibration_code(ADC_UNIT_2, atten);
|
||||
#endif
|
||||
|
||||
ADC_REG_LOCK_ENTER();
|
||||
adc_oneshot_ll_set_atten(ADC_UNIT_2, channel, atten);
|
||||
ret = adc_hal_convert(ADC_UNIT_2, channel, clk_src_freq_hz, raw_out);
|
||||
ADC_REG_LOCK_EXIT();
|
||||
|
||||
sar_periph_ctrl_adc_oneshot_power_release();
|
||||
adc_apb_periph_free();
|
||||
adc_lock_release(ADC_UNIT_2);
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif //#if (SOC_ADC_PERIPH_NUM >= 2)
|
||||
#endif //#if SOC_ADC_DIG_CTRL_SUPPORTED && !SOC_ADC_RTC_CTRL_SUPPORTED
|
||||
|
||||
static void adc_hal_onetime_start(adc_unit_t adc_n, uint32_t clk_src_freq_hz)
|
||||
{
|
||||
#if SOC_ADC_DIG_CTRL_SUPPORTED && !SOC_ADC_RTC_CTRL_SUPPORTED
|
||||
(void)adc_n;
|
||||
/**
|
||||
* There is a hardware limitation. If the APB clock frequency is high, the step of this reg signal: ``onetime_start`` may not be captured by the
|
||||
* ADC digital controller (when its clock frequency is too slow). A rough estimate for this step should be at least 3 ADC digital controller
|
||||
* clock cycle.
|
||||
*/
|
||||
uint32_t digi_clk = clk_src_freq_hz / (ADC_LL_CLKM_DIV_NUM_DEFAULT + ADC_LL_CLKM_DIV_A_DEFAULT / ADC_LL_CLKM_DIV_B_DEFAULT + 1);
|
||||
//Convert frequency to time (us). Since decimals are removed by this division operation. Add 1 here in case of the fact that delay is not enough.
|
||||
uint32_t delay = (1000 * 1000) / digi_clk + 1;
|
||||
//3 ADC digital controller clock cycle
|
||||
delay = delay * 3;
|
||||
//This coefficient (8) is got from test, and verified from DT. When digi_clk is not smaller than ``APB_CLK_FREQ/8``, no delay is needed.
|
||||
if (digi_clk >= APB_CLK_FREQ / 8) {
|
||||
delay = 0;
|
||||
}
|
||||
|
||||
adc_oneshot_ll_start(false);
|
||||
esp_rom_delay_us(delay);
|
||||
adc_oneshot_ll_start(true);
|
||||
|
||||
//No need to delay here. Because if the start signal is not seen, there won't be a done intr.
|
||||
#else
|
||||
(void)clk_src_freq_hz;
|
||||
adc_oneshot_ll_start(adc_n);
|
||||
#endif
|
||||
}
|
||||
|
||||
static esp_err_t adc_hal_convert(adc_unit_t adc_n, int channel, uint32_t clk_src_freq_hz, int *out_raw)
|
||||
{
|
||||
|
||||
uint32_t event = (adc_n == ADC_UNIT_1) ? ADC_LL_EVENT_ADC1_ONESHOT_DONE : ADC_LL_EVENT_ADC2_ONESHOT_DONE;
|
||||
adc_oneshot_ll_clear_event(event);
|
||||
adc_oneshot_ll_disable_all_unit();
|
||||
adc_oneshot_ll_enable(adc_n);
|
||||
adc_oneshot_ll_set_channel(adc_n, channel);
|
||||
|
||||
adc_hal_onetime_start(adc_n, clk_src_freq_hz);
|
||||
|
||||
while (adc_oneshot_ll_get_event(event) != true) {
|
||||
;
|
||||
}
|
||||
|
||||
*out_raw = adc_oneshot_ll_get_raw_result(adc_n);
|
||||
if (adc_oneshot_ll_raw_check_valid(adc_n, *out_raw) == false) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
//HW workaround: when enabling periph clock, this should be false
|
||||
adc_oneshot_ll_disable_all_unit();
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
#if !CONFIG_ADC_SKIP_LEGACY_CONFLICT_CHECK
|
||||
/**
|
||||
* @brief This function will be called during start up, to check that adc_oneshot driver is not running along with the legacy adc oneshot driver
|
||||
*/
|
||||
__attribute__((constructor))
|
||||
static void check_adc_oneshot_driver_conflict(void)
|
||||
{
|
||||
// This function was declared as weak here. adc_oneshot driver has one implementation.
|
||||
// So if adc_oneshot driver is not linked in, then `adc_oneshot_new_unit` should be NULL at runtime.
|
||||
extern __attribute__((weak)) esp_err_t adc_oneshot_new_unit(const void *init_config, void **ret_unit);
|
||||
if ((void *)adc_oneshot_new_unit != NULL) {
|
||||
ESP_EARLY_LOGE(ADC_TAG, "CONFLICT! driver_ng is not allowed to be used with the legacy driver");
|
||||
abort();
|
||||
}
|
||||
ESP_EARLY_LOGW(ADC_TAG, "legacy driver is deprecated, please migrate to `esp_adc/adc_oneshot.h`");
|
||||
}
|
||||
#endif //CONFIG_ADC_SKIP_LEGACY_CONFLICT_CHECK
|
||||
|
||||
#if SOC_ADC_CALIBRATION_V1_SUPPORTED
|
||||
/*---------------------------------------------------------------
|
||||
ADC Hardware Calibration
|
||||
---------------------------------------------------------------*/
|
||||
static __attribute__((constructor)) void adc_hw_calibration(void)
|
||||
{
|
||||
ANALOG_CLOCK_ENABLE();
|
||||
//Calculate all ICode
|
||||
for (int i = 0; i < SOC_ADC_PERIPH_NUM; i++) {
|
||||
adc_hal_calibration_init(i);
|
||||
for (int j = 0; j < SOC_ADC_ATTEN_NUM; j++) {
|
||||
/**
|
||||
* This may get wrong when attenuations are NOT consecutive on some chips,
|
||||
* update this when bringing up the calibration on that chip
|
||||
*/
|
||||
adc_calc_hw_calibration_code(i, j);
|
||||
#if SOC_ADC_CALIB_CHAN_COMPENS_SUPPORTED
|
||||
/* Load the channel compensation from efuse */
|
||||
for (int k = 0; k < SOC_ADC_CHANNEL_NUM(i); k++) {
|
||||
adc_load_hw_calibration_chan_compens(i, k, j);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
ANALOG_CLOCK_DISABLE();
|
||||
}
|
||||
#endif //#if SOC_ADC_CALIBRATION_V1_SUPPORTED
|
||||
144
components/driver/deprecated/dac_common_legacy.c
Normal file
144
components/driver/deprecated/dac_common_legacy.c
Normal file
@@ -0,0 +1,144 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2019-2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include "esp_check.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "esp_private/gpio.h"
|
||||
#include "driver/dac_types_legacy.h"
|
||||
#include "soc/dac_periph.h"
|
||||
#include "hal/gpio_types.h"
|
||||
#include "hal/dac_ll.h"
|
||||
#include "clk_ctrl_os.h"
|
||||
|
||||
extern portMUX_TYPE rtc_spinlock; //TODO: Will be placed in the appropriate position after the rtc module is finished.
|
||||
|
||||
static __attribute__((unused)) const char *TAG = "DAC";
|
||||
|
||||
/*---------------------------------------------------------------
|
||||
DAC
|
||||
---------------------------------------------------------------*/
|
||||
esp_err_t dac_pad_get_io_num(dac_channel_t channel, gpio_num_t *gpio_num)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(channel < SOC_DAC_CHAN_NUM, ESP_ERR_INVALID_ARG, TAG, "DAC channel error");
|
||||
|
||||
*gpio_num = (gpio_num_t)dac_periph_signal.dac_channel_io_num[channel];
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t dac_rtc_pad_init(dac_channel_t channel)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(channel < SOC_DAC_CHAN_NUM, ESP_ERR_INVALID_ARG, TAG, "DAC channel error");
|
||||
|
||||
gpio_num_t gpio_num = 0;
|
||||
dac_pad_get_io_num(channel, &gpio_num);
|
||||
gpio_config_as_analog(gpio_num);
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t dac_output_enable(dac_channel_t channel)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(channel < SOC_DAC_CHAN_NUM, ESP_ERR_INVALID_ARG, TAG, "DAC channel error");
|
||||
|
||||
dac_rtc_pad_init(channel);
|
||||
portENTER_CRITICAL(&rtc_spinlock);
|
||||
dac_ll_power_on(channel);
|
||||
dac_ll_rtc_sync_by_adc(false);
|
||||
portEXIT_CRITICAL(&rtc_spinlock);
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t dac_output_disable(dac_channel_t channel)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(channel < SOC_DAC_CHAN_NUM, ESP_ERR_INVALID_ARG, TAG, "DAC channel error");
|
||||
|
||||
portENTER_CRITICAL(&rtc_spinlock);
|
||||
dac_ll_power_down(channel);
|
||||
portEXIT_CRITICAL(&rtc_spinlock);
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t dac_output_voltage(dac_channel_t channel, uint8_t dac_value)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(channel < SOC_DAC_CHAN_NUM, ESP_ERR_INVALID_ARG, TAG, "DAC channel error");
|
||||
|
||||
portENTER_CRITICAL(&rtc_spinlock);
|
||||
dac_ll_update_output_value(channel, dac_value);
|
||||
portEXIT_CRITICAL(&rtc_spinlock);
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t dac_out_voltage(dac_channel_t channel, uint8_t dac_value)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(channel < SOC_DAC_CHAN_NUM, ESP_ERR_INVALID_ARG, TAG, "DAC channel error");
|
||||
|
||||
portENTER_CRITICAL(&rtc_spinlock);
|
||||
dac_ll_update_output_value(channel, dac_value);
|
||||
portEXIT_CRITICAL(&rtc_spinlock);
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t dac_cw_generator_enable(void)
|
||||
{
|
||||
portENTER_CRITICAL(&rtc_spinlock);
|
||||
periph_rtc_dig_clk8m_enable();
|
||||
dac_ll_cw_generator_enable();
|
||||
portEXIT_CRITICAL(&rtc_spinlock);
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t dac_cw_generator_disable(void)
|
||||
{
|
||||
portENTER_CRITICAL(&rtc_spinlock);
|
||||
dac_ll_cw_generator_disable();
|
||||
periph_rtc_dig_clk8m_disable();
|
||||
portEXIT_CRITICAL(&rtc_spinlock);
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t dac_cw_generator_config(dac_cw_config_t *cw)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(cw, ESP_ERR_INVALID_ARG, TAG, "invalid clock configuration");
|
||||
portENTER_CRITICAL(&rtc_spinlock);
|
||||
/* Enable the rtc8m clock temporary to get the correct frequency */
|
||||
periph_rtc_dig_clk8m_enable();
|
||||
uint32_t rtc_freq = periph_rtc_dig_clk8m_get_freq();
|
||||
periph_rtc_dig_clk8m_disable();
|
||||
dac_ll_cw_set_freq(cw->freq, rtc_freq);
|
||||
dac_ll_cw_set_atten(cw->en_ch, (dac_cosine_atten_t)cw->scale);
|
||||
dac_ll_cw_set_phase(cw->en_ch, (dac_cosine_phase_t)cw->phase);
|
||||
dac_ll_cw_set_dc_offset(cw->en_ch, cw->offset);
|
||||
dac_ll_cw_enable_channel(cw->en_ch, true);
|
||||
portEXIT_CRITICAL(&rtc_spinlock);
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
#if !CONFIG_DAC_SKIP_LEGACY_CONFLICT_CHECK
|
||||
/**
|
||||
* @brief This function will be called during start up, to check that this legacy DAC driver is not running along with the new driver
|
||||
*/
|
||||
__attribute__((constructor))
|
||||
static void check_dac_legacy_driver_conflict(void)
|
||||
{
|
||||
// This function was declared as weak here. The new DAC driver has one implementation.
|
||||
// So if the new DAC driver is not linked in, then `dac_priv_register_channel()` should be NULL at runtime.
|
||||
extern __attribute__((weak)) esp_err_t dac_priv_register_channel(dac_channel_t chan_id, const char *mode_name);
|
||||
if ((void *)dac_priv_register_channel != NULL) {
|
||||
ESP_EARLY_LOGE(TAG, "CONFLICT! The new DAC driver is not allowed to be used together with the legacy driver");
|
||||
abort();
|
||||
}
|
||||
ESP_EARLY_LOGW(TAG, "legacy driver is deprecated, please migrate to `driver/dac_oneshot.h`, `driver/dac_cosine.h` or `driver/dac_continuous.h` instead");
|
||||
}
|
||||
#endif //CONFIG_DAC_SKIP_LEGACY_CONFLICT_CHECK
|
||||
355
components/driver/deprecated/driver/adc.h
Normal file
355
components/driver/deprecated/driver/adc.h
Normal file
@@ -0,0 +1,355 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/*----------------------------------------------------------------------------------
|
||||
This file contains Deprecated ADC APIs
|
||||
-----------------------------------------------------------------------------------*/
|
||||
|
||||
#pragma once
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_err.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "driver/adc_types_legacy.h"
|
||||
#include "hal/adc_types.h"
|
||||
|
||||
#if !CONFIG_ADC_SUPPRESS_DEPRECATE_WARN
|
||||
#warning "legacy adc driver is deprecated, please migrate to use esp_adc/adc_oneshot.h and esp_adc/adc_continuous.h for oneshot mode and continuous mode drivers respectively"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*---------------------------------------------------------------
|
||||
Deprecated API
|
||||
---------------------------------------------------------------*/
|
||||
/*---------------------------------------------------------------
|
||||
ADC Single Read Setting
|
||||
---------------------------------------------------------------*/
|
||||
/**
|
||||
* @brief Get the GPIO number of a specific ADC1 channel.
|
||||
*
|
||||
* @param channel Channel to get the GPIO number
|
||||
* @param gpio_num output buffer to hold the GPIO number
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK if success
|
||||
* - ESP_ERR_INVALID_ARG if channel not valid
|
||||
*/
|
||||
esp_err_t adc1_pad_get_io_num(adc1_channel_t channel, gpio_num_t *gpio_num);
|
||||
|
||||
/**
|
||||
* @brief Set the attenuation of a particular channel on ADC1, and configure its associated GPIO pin mux.
|
||||
*
|
||||
* The default ADC voltage is for attenuation 0 dB and listed in the table below.
|
||||
* By setting higher attenuation it is possible to read higher voltages.
|
||||
*
|
||||
* Due to ADC characteristics, most accurate results are obtained within the "suggested range"
|
||||
* shown in the following table.
|
||||
*
|
||||
* +----------+-------------+-----------------+
|
||||
* | | attenuation | suggested range |
|
||||
* | SoC | (dB) | (mV) |
|
||||
* +==========+=============+=================+
|
||||
* | | 0 | 100 ~ 950 |
|
||||
* | +-------------+-----------------+
|
||||
* | | 2.5 | 100 ~ 1250 |
|
||||
* | ESP32 +-------------+-----------------+
|
||||
* | | 6 | 150 ~ 1750 |
|
||||
* | +-------------+-----------------+
|
||||
* | | 11 | 150 ~ 2450 |
|
||||
* +----------+-------------+-----------------+
|
||||
* | | 0 | 0 ~ 750 |
|
||||
* | +-------------+-----------------+
|
||||
* | | 2.5 | 0 ~ 1050 |
|
||||
* | ESP32-S2 +-------------+-----------------+
|
||||
* | | 6 | 0 ~ 1300 |
|
||||
* | +-------------+-----------------+
|
||||
* | | 11 | 0 ~ 2500 |
|
||||
* +----------+-------------+-----------------+
|
||||
*
|
||||
* For maximum accuracy, use the ADC calibration APIs and measure voltages within these recommended ranges.
|
||||
*
|
||||
* @note For any given channel, this function must be called before the first time ``adc1_get_raw()`` is called for that channel.
|
||||
*
|
||||
* @note This function can be called multiple times to configure multiple
|
||||
* ADC channels simultaneously. You may call ``adc1_get_raw()`` only after configuring a channel.
|
||||
*
|
||||
* @param channel ADC1 channel to configure
|
||||
* @param atten Attenuation level
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK success
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
*/
|
||||
esp_err_t adc1_config_channel_atten(adc1_channel_t channel, adc_atten_t atten);
|
||||
|
||||
/**
|
||||
* @brief Configure ADC1 capture width, meanwhile enable output invert for ADC1.
|
||||
* The configuration is for all channels of ADC1
|
||||
* @param width_bit Bit capture width for ADC1
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK success
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
*/
|
||||
esp_err_t adc1_config_width(adc_bits_width_t width_bit);
|
||||
|
||||
/**
|
||||
* @brief Take an ADC1 reading from a single channel.
|
||||
* @note ESP32:
|
||||
* When the power switch of SARADC1, SARADC2, HALL sensor and AMP sensor is turned on,
|
||||
* the input of GPIO36 and GPIO39 will be pulled down for about 80ns.
|
||||
* When enabling power for any of these peripherals, ignore input from GPIO36 and GPIO39.
|
||||
* Please refer to section 3.11 of 'ECO_and_Workarounds_for_Bugs_in_ESP32' for the description of this issue.
|
||||
* As a workaround, call sar_periph_ctrl_adc_oneshot_power_acquire() in the app. This will result in higher power consumption (by ~1mA),
|
||||
* but will remove the glitches on GPIO36 and GPIO39.
|
||||
*
|
||||
* @note Call ``adc1_config_width()`` before the first time this
|
||||
* function is called.
|
||||
*
|
||||
* @note For any given channel, adc1_config_channel_atten(channel)
|
||||
* must be called before the first time this function is called. Configuring
|
||||
* a new channel does not prevent a previously configured channel from being read.
|
||||
*
|
||||
* @param channel ADC1 channel to read
|
||||
*
|
||||
* @return
|
||||
* - -1: Parameter error
|
||||
* - Other: ADC1 channel reading.
|
||||
*/
|
||||
int adc1_get_raw(adc1_channel_t channel);
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
|
||||
//TODO IDF-3610, replace these with proper caps
|
||||
/**
|
||||
* @brief Set ADC data invert
|
||||
* @param adc_unit ADC unit index
|
||||
* @param inv_en whether enable data invert
|
||||
* @return
|
||||
* - ESP_OK success
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
*/
|
||||
esp_err_t adc_set_data_inv(adc_unit_t adc_unit, bool inv_en);
|
||||
|
||||
/**
|
||||
* @brief Set ADC source clock
|
||||
* @param clk_div ADC clock divider, ADC clock is divided from APB clock
|
||||
* @return
|
||||
* - ESP_OK success
|
||||
*/
|
||||
esp_err_t adc_set_clk_div(uint8_t clk_div);
|
||||
|
||||
/**
|
||||
* @brief Configure ADC capture width.
|
||||
*
|
||||
* @param adc_unit ADC unit index
|
||||
* @param width_bit Bit capture width for ADC unit.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK success
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
*/
|
||||
esp_err_t adc_set_data_width(adc_unit_t adc_unit, adc_bits_width_t width_bit);
|
||||
|
||||
/**
|
||||
* @brief Configure ADC1 to be usable by the ULP
|
||||
*
|
||||
* This function reconfigures ADC1 to be controlled by the ULP.
|
||||
* Effect of this function can be reverted using ``adc1_get_raw()`` function.
|
||||
*
|
||||
* Note that adc1_config_channel_atten, ``adc1_config_width()`` functions need
|
||||
* to be called to configure ADC1 channels, before ADC1 is used by the ULP.
|
||||
*/
|
||||
void adc1_ulp_enable(void);
|
||||
#endif //#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
|
||||
|
||||
#if (SOC_ADC_PERIPH_NUM >= 2)
|
||||
/**
|
||||
* @brief Get the GPIO number of a specific ADC2 channel.
|
||||
*
|
||||
* @param channel Channel to get the GPIO number
|
||||
*
|
||||
* @param gpio_num output buffer to hold the GPIO number
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK if success
|
||||
* - ESP_ERR_INVALID_ARG if channel not valid
|
||||
*/
|
||||
esp_err_t adc2_pad_get_io_num(adc2_channel_t channel, gpio_num_t *gpio_num);
|
||||
|
||||
/**
|
||||
* @brief Configure the ADC2 channel, including setting attenuation.
|
||||
*
|
||||
* The default ADC voltage is for attenuation 0 dB and listed in the table below.
|
||||
* By setting higher attenuation it is possible to read higher voltages.
|
||||
*
|
||||
* Due to ADC characteristics, most accurate results are obtained within the "suggested range"
|
||||
* shown in the following table.
|
||||
*
|
||||
* +----------+-------------+-----------------+
|
||||
* | | attenuation | suggested range |
|
||||
* | SoC | (dB) | (mV) |
|
||||
* +==========+=============+=================+
|
||||
* | | 0 | 100 ~ 950 |
|
||||
* | +-------------+-----------------+
|
||||
* | | 2.5 | 100 ~ 1250 |
|
||||
* | ESP32 +-------------+-----------------+
|
||||
* | | 6 | 150 ~ 1750 |
|
||||
* | +-------------+-----------------+
|
||||
* | | 11 | 150 ~ 2450 |
|
||||
* +----------+-------------+-----------------+
|
||||
* | | 0 | 0 ~ 750 |
|
||||
* | +-------------+-----------------+
|
||||
* | | 2.5 | 0 ~ 1050 |
|
||||
* | ESP32-S2 +-------------+-----------------+
|
||||
* | | 6 | 0 ~ 1300 |
|
||||
* | +-------------+-----------------+
|
||||
* | | 11 | 0 ~ 2500 |
|
||||
* +----------+-------------+-----------------+
|
||||
*
|
||||
* For maximum accuracy, use the ADC calibration APIs and measure voltages within these recommended ranges.
|
||||
*
|
||||
* @note This function also configures the input GPIO pin mux to
|
||||
* connect it to the ADC2 channel. It must be called before calling
|
||||
* ``adc2_get_raw()`` for this channel.
|
||||
*
|
||||
* @note For any given channel, this function must be called before the first time ``adc2_get_raw()`` is called for that channel.
|
||||
*
|
||||
* @param channel ADC2 channel to configure
|
||||
* @param atten Attenuation level
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK success
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
*/
|
||||
esp_err_t adc2_config_channel_atten(adc2_channel_t channel, adc_atten_t atten);
|
||||
|
||||
/**
|
||||
* @brief Take an ADC2 reading on a single channel
|
||||
*
|
||||
* @note ESP32:
|
||||
* When the power switch of SARADC1, SARADC2, HALL sensor and AMP sensor is turned on,
|
||||
* the input of GPIO36 and GPIO39 will be pulled down for about 80ns.
|
||||
* When enabling power for any of these peripherals, ignore input from GPIO36 and GPIO39.
|
||||
* Please refer to section 3.11 of 'ECO_and_Workarounds_for_Bugs_in_ESP32' for the description of this issue.
|
||||
* As a workaround, call sar_periph_ctrl_adc_oneshot_power_acquire() in the app. This will result in higher power consumption (by ~1mA),
|
||||
* but will remove the glitches on GPIO36 and GPIO39.
|
||||
*
|
||||
*
|
||||
* @note ESP32:
|
||||
* For a given channel, ``adc2_config_channel_atten()``
|
||||
* must be called before the first time this function is called. If Wi-Fi is started via ``esp_wifi_start()``, this
|
||||
* function will always fail with ``ESP_ERR_TIMEOUT``.
|
||||
*
|
||||
* @note ESP32-S2:
|
||||
* ADC2 support hardware arbiter. The arbiter is to improve the use efficiency of ADC2. After the control right is robbed by the high priority,
|
||||
* the low priority controller will read the invalid ADC2 data. Default priority: Wi-Fi > RTC > Digital;
|
||||
*
|
||||
* @param channel ADC2 channel to read
|
||||
* @param width_bit Bit capture width for ADC2
|
||||
* @param raw_out the variable to hold the output data.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK if success
|
||||
* - ESP_ERR_TIMEOUT ADC2 is being used by other controller and the request timed out.
|
||||
* - ESP_ERR_INVALID_STATE The controller status is invalid. Please try again.
|
||||
*/
|
||||
esp_err_t adc2_get_raw(adc2_channel_t channel, adc_bits_width_t width_bit, int *raw_out);
|
||||
|
||||
/**
|
||||
* @brief Output ADC1 or ADC2's reference voltage to ``adc2_channe_t``'s IO.
|
||||
*
|
||||
* This function routes the internal reference voltage of ADCn to one of
|
||||
* ADC2's channels. This reference voltage can then be manually measured
|
||||
* for calibration purposes.
|
||||
*
|
||||
* @note ESP32 only supports output of ADC2's internal reference voltage.
|
||||
* @param[in] adc_unit ADC unit index
|
||||
* @param[in] gpio GPIO number (Only ADC2's channels IO are supported)
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: v_ref successfully routed to selected GPIO
|
||||
* - ESP_ERR_INVALID_ARG: Unsupported GPIO
|
||||
*/
|
||||
esp_err_t adc_vref_to_gpio(adc_unit_t adc_unit, gpio_num_t gpio);
|
||||
#endif //#if (SOC_ADC_PERIPH_NUM >= 2)
|
||||
|
||||
/*---------------------------------------------------------------
|
||||
ADC DMA Read Setting
|
||||
---------------------------------------------------------------*/
|
||||
#if SOC_ADC_DMA_SUPPORTED
|
||||
/**
|
||||
* @brief Initialize the Digital ADC.
|
||||
*
|
||||
* @param init_config Pointer to Digital ADC initialization config. Refer to ``adc_digi_init_config_t``.
|
||||
*
|
||||
* @return
|
||||
* - 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_NO_MEM If out of memory
|
||||
* - ESP_OK On success
|
||||
*/
|
||||
esp_err_t adc_digi_initialize(const adc_digi_init_config_t *init_config);
|
||||
|
||||
/**
|
||||
* @brief Read bytes from Digital ADC through DMA.
|
||||
*
|
||||
* @param[out] buf Buffer to read from ADC.
|
||||
* @param[in] length_max Expected length of data read from the ADC.
|
||||
* @param[out] out_length Real length of data read from the ADC via this API.
|
||||
* @param[in] timeout_ms Time to wait for data via this API, in millisecond.
|
||||
*
|
||||
* @return
|
||||
* - ESP_ERR_INVALID_STATE Driver state is invalid. Usually it means the ADC sampling rate is faster than the task processing rate.
|
||||
* - ESP_ERR_TIMEOUT Operation timed out
|
||||
* - ESP_OK On success
|
||||
*/
|
||||
esp_err_t adc_digi_read_bytes(uint8_t *buf, uint32_t length_max, uint32_t *out_length, uint32_t timeout_ms);
|
||||
|
||||
/**
|
||||
* @brief Start the Digital ADC and DMA peripherals. After this, the hardware starts working.
|
||||
*
|
||||
* @return
|
||||
* - ESP_ERR_INVALID_STATE Driver state is invalid.
|
||||
* - ESP_OK On success
|
||||
*/
|
||||
esp_err_t adc_digi_start(void);
|
||||
|
||||
/**
|
||||
* @brief Stop the Digital ADC and DMA peripherals. After this, the hardware stops working.
|
||||
*
|
||||
* @return
|
||||
* - ESP_ERR_INVALID_STATE Driver state is invalid.
|
||||
* - ESP_OK On success
|
||||
*/
|
||||
esp_err_t adc_digi_stop(void);
|
||||
|
||||
/**
|
||||
* @brief Deinitialize the Digital ADC.
|
||||
*
|
||||
* @return
|
||||
* - ESP_ERR_INVALID_STATE Driver state is invalid.
|
||||
* - ESP_OK On success
|
||||
*/
|
||||
esp_err_t adc_digi_deinitialize(void);
|
||||
|
||||
/**
|
||||
* @brief Setting the digital controller.
|
||||
*
|
||||
* @param config Pointer to digital controller parameter. Refer to ``adc_digi_config_t``.
|
||||
*
|
||||
* @return
|
||||
* - ESP_ERR_INVALID_STATE Driver state is invalid.
|
||||
* - ESP_ERR_INVALID_ARG If the combination of arguments is invalid.
|
||||
* - ESP_OK On success
|
||||
*/
|
||||
esp_err_t adc_digi_controller_configure(const adc_digi_configuration_t *config);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
51
components/driver/deprecated/driver/adc_i2s_legacy.h
Normal file
51
components/driver/deprecated/driver/adc_i2s_legacy.h
Normal file
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_err.h"
|
||||
#include "hal/adc_types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32
|
||||
/**
|
||||
* @brief ESP32 ADC DMA source selection.
|
||||
*/
|
||||
typedef enum {
|
||||
ADC_I2S_DATA_SRC_IO_SIG = 0, /*!< I2S data from GPIO matrix signal */
|
||||
ADC_I2S_DATA_SRC_ADC = 1, /*!< I2S data from ADC */
|
||||
} adc_i2s_source_t;
|
||||
#endif
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
/*---------------------------------------------------------------
|
||||
ESP32 Deprecated API
|
||||
---------------------------------------------------------------*/
|
||||
/**
|
||||
* @brief Set I2S data source
|
||||
* @param src I2S DMA data source, I2S DMA can get data from digital signals or from ADC.
|
||||
* @return
|
||||
* - ESP_OK success
|
||||
*/
|
||||
esp_err_t adc_set_i2s_data_source(adc_i2s_source_t src);
|
||||
|
||||
/**
|
||||
* @brief Initialize I2S ADC mode
|
||||
* @param adc_unit ADC unit index
|
||||
* @param channel ADC channel index
|
||||
* @return
|
||||
* - ESP_OK success
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
*/
|
||||
esp_err_t adc_i2s_mode_init(adc_unit_t adc_unit, adc_channel_t channel);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
130
components/driver/deprecated/driver/adc_types_legacy.h
Normal file
130
components/driver/deprecated/driver/adc_types_legacy.h
Normal file
@@ -0,0 +1,130 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "hal/adc_types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief ADC resolution setting option.
|
||||
* @note Only used in single read mode
|
||||
*/
|
||||
typedef enum {
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
ADC_WIDTH_BIT_9 = 9, /*!< ADC capture width is 9Bit. */
|
||||
ADC_WIDTH_BIT_10 = 10, /*!< ADC capture width is 10Bit. */
|
||||
ADC_WIDTH_BIT_11 = 11, /*!< ADC capture width is 11Bit. */
|
||||
ADC_WIDTH_BIT_12 = 12, /*!< ADC capture width is 12Bit. */
|
||||
#elif SOC_ADC_RTC_MAX_BITWIDTH == 12
|
||||
ADC_WIDTH_BIT_12 = 12, /*!< ADC capture width is 12Bit. */
|
||||
#elif SOC_ADC_RTC_MAX_BITWIDTH == 13
|
||||
ADC_WIDTH_BIT_13 = 13, /*!< ADC capture width is 13Bit. */
|
||||
#endif
|
||||
ADC_WIDTH_MAX,
|
||||
} adc_bits_width_t;
|
||||
|
||||
/**
|
||||
* The default (max) bit width of the ADC of current version. You can also get the maximum bitwidth
|
||||
* by `SOC_ADC_RTC_MAX_BITWIDTH` defined in soc_caps.h.
|
||||
*/
|
||||
#define ADC_WIDTH_BIT_DEFAULT (ADC_WIDTH_MAX-1)
|
||||
|
||||
typedef enum {
|
||||
ADC1_CHANNEL_0 = 0,
|
||||
ADC1_CHANNEL_1,
|
||||
ADC1_CHANNEL_2,
|
||||
ADC1_CHANNEL_3,
|
||||
#if SOC_ADC_CHANNEL_NUM(0) > 4
|
||||
ADC1_CHANNEL_4,
|
||||
#endif
|
||||
#if SOC_ADC_CHANNEL_NUM(0) > 5
|
||||
ADC1_CHANNEL_5,
|
||||
#endif
|
||||
#if SOC_ADC_CHANNEL_NUM(0) > 6
|
||||
ADC1_CHANNEL_6,
|
||||
#endif
|
||||
#if SOC_ADC_CHANNEL_NUM(0) > 7
|
||||
ADC1_CHANNEL_7,
|
||||
#endif
|
||||
#if SOC_ADC_CHANNEL_NUM(0) > 8
|
||||
ADC1_CHANNEL_8,
|
||||
#endif
|
||||
#if SOC_ADC_CHANNEL_NUM(0) > 9
|
||||
ADC1_CHANNEL_9,
|
||||
#endif
|
||||
ADC1_CHANNEL_MAX = SOC_ADC_CHANNEL_NUM(0),
|
||||
} adc1_channel_t;
|
||||
|
||||
#if SOC_ADC_PERIPH_NUM > 1
|
||||
typedef enum {
|
||||
ADC2_CHANNEL_0 = 0,
|
||||
#if SOC_ADC_CHANNEL_NUM(1) > 1
|
||||
ADC2_CHANNEL_1,
|
||||
#endif
|
||||
#if SOC_ADC_CHANNEL_NUM(1) > 2
|
||||
ADC2_CHANNEL_2,
|
||||
#endif
|
||||
#if SOC_ADC_CHANNEL_NUM(1) > 3
|
||||
ADC2_CHANNEL_3,
|
||||
#endif
|
||||
#if SOC_ADC_CHANNEL_NUM(1) > 4
|
||||
ADC2_CHANNEL_4,
|
||||
#endif
|
||||
#if SOC_ADC_CHANNEL_NUM(1) > 5
|
||||
ADC2_CHANNEL_5,
|
||||
#endif
|
||||
#if SOC_ADC_CHANNEL_NUM(1) > 6
|
||||
ADC2_CHANNEL_6,
|
||||
#endif
|
||||
#if SOC_ADC_CHANNEL_NUM(1) > 7
|
||||
ADC2_CHANNEL_7,
|
||||
#endif
|
||||
#if SOC_ADC_CHANNEL_NUM(1) > 8
|
||||
ADC2_CHANNEL_8,
|
||||
#endif
|
||||
#if SOC_ADC_CHANNEL_NUM(1) > 9
|
||||
ADC2_CHANNEL_9,
|
||||
#endif
|
||||
ADC2_CHANNEL_MAX = SOC_ADC_CHANNEL_NUM(1),
|
||||
} adc2_channel_t;
|
||||
#endif
|
||||
|
||||
#if SOC_ADC_DMA_SUPPORTED
|
||||
/**
|
||||
* @brief Digital ADC DMA read max timeout value, it may make the ``adc_digi_read_bytes`` block forever if the OS supports
|
||||
*/
|
||||
#define ADC_MAX_DELAY UINT32_MAX
|
||||
|
||||
/**
|
||||
* @brief ADC DMA driver configuration
|
||||
*/
|
||||
typedef struct adc_digi_init_config_s {
|
||||
uint32_t max_store_buf_size; ///< Max length of the converted data that driver can store before they are processed.
|
||||
uint32_t conv_num_each_intr; ///< Bytes of data that can be converted in 1 interrupt. This should be in multiples of `SOC_ADC_DIGI_DATA_BYTES_PER_CONV`.
|
||||
uint32_t adc1_chan_mask; ///< Channel list of ADC1 to be initialized.
|
||||
uint32_t adc2_chan_mask; ///< Channel list of ADC2 to be initialized.
|
||||
} adc_digi_init_config_t;
|
||||
|
||||
/**
|
||||
* @brief ADC digital controller settings
|
||||
*/
|
||||
typedef struct {
|
||||
bool conv_limit_en; ///< Suggest leaving it empty, this parameter has been deprecated
|
||||
uint32_t conv_limit_num; ///< suggest leaving it empty, this parameter has been deprecated
|
||||
uint32_t pattern_num; ///< Number of ADC channels that will be used
|
||||
adc_digi_pattern_config_t *adc_pattern; ///< List of configs for each ADC channel that will be used
|
||||
uint32_t sample_freq_hz; /*!< Please refer to `soc/soc_caps.h` to know the ADC sampling frequency range*/
|
||||
adc_digi_convert_mode_t conv_mode; ///< ADC DMA conversion mode, see `adc_digi_convert_mode_t`.
|
||||
adc_digi_output_format_t format; ///< ADC DMA conversion output format, see `adc_digi_output_format_t`.
|
||||
} adc_digi_configuration_t;
|
||||
#endif // #if SOC_ADC_DMA_SUPPORTED
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
171
components/driver/deprecated/driver/dac.h
Normal file
171
components/driver/deprecated/driver/dac.h
Normal file
@@ -0,0 +1,171 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include "esp_err.h"
|
||||
#include "sdkconfig.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "driver/dac_types_legacy.h"
|
||||
|
||||
#if !CONFIG_DAC_SUPPRESS_DEPRECATE_WARN
|
||||
#warning "The legacy DAC driver is deprecated, please use `driver/dac_oneshot.h`, `driver/dac_cosine.h` or `driver/dac_continuous.h` instead"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Get the GPIO number of a specific DAC channel.
|
||||
*
|
||||
* @param channel Channel to get the gpio number
|
||||
* @param gpio_num output buffer to hold the gpio number
|
||||
* @return
|
||||
* - ESP_OK if success
|
||||
*/
|
||||
esp_err_t dac_pad_get_io_num(dac_channel_t channel, gpio_num_t *gpio_num);
|
||||
|
||||
/**
|
||||
* @brief Set DAC output voltage.
|
||||
* DAC output is 8-bit. Maximum (255) corresponds to VDD3P3_RTC.
|
||||
*
|
||||
* @note Need to configure DAC pad before calling this function.
|
||||
* DAC channel 0 is attached to GPIO25, DAC channel 1 is attached to GPIO26
|
||||
* @param channel DAC channel
|
||||
* @param dac_value DAC output value
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK success
|
||||
*/
|
||||
esp_err_t dac_output_voltage(dac_channel_t channel, uint8_t dac_value);
|
||||
|
||||
/**
|
||||
* @brief DAC pad output enable
|
||||
*
|
||||
* @param channel DAC channel
|
||||
* @note DAC channel 0 is attached to GPIO25, DAC channel 1 is attached to GPIO26
|
||||
* I2S left channel will be mapped to DAC channel 1
|
||||
* I2S right channel will be mapped to DAC channel 0
|
||||
*/
|
||||
esp_err_t dac_output_enable(dac_channel_t channel);
|
||||
|
||||
/**
|
||||
* @brief DAC pad output disable
|
||||
*
|
||||
* @param channel DAC channel
|
||||
* @note DAC channel 0 is attached to GPIO25, DAC channel 1 is attached to GPIO26
|
||||
* @return
|
||||
* - ESP_OK success
|
||||
*/
|
||||
esp_err_t dac_output_disable(dac_channel_t channel);
|
||||
|
||||
/**
|
||||
* @brief Enable cosine wave generator output.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK success
|
||||
*/
|
||||
esp_err_t dac_cw_generator_enable(void);
|
||||
|
||||
/**
|
||||
* @brief Disable cosine wave generator output.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK success
|
||||
*/
|
||||
esp_err_t dac_cw_generator_disable(void);
|
||||
|
||||
/**
|
||||
* @brief Config the cosine wave generator function in DAC module.
|
||||
*
|
||||
* @param cw Configuration.
|
||||
* @return
|
||||
* - ESP_OK success
|
||||
* - ESP_ERR_INVALID_ARG The parameter is NULL.
|
||||
*/
|
||||
esp_err_t dac_cw_generator_config(dac_cw_config_t *cw);
|
||||
|
||||
/*---------------------------------------------------------------
|
||||
Digital controller setting
|
||||
---------------------------------------------------------------*/
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
/**
|
||||
* @brief Enable DAC output data from I2S
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK success
|
||||
*/
|
||||
esp_err_t dac_i2s_enable(void);
|
||||
|
||||
/**
|
||||
* @brief Disable DAC output data from I2S
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK success
|
||||
*/
|
||||
esp_err_t dac_i2s_disable(void);
|
||||
#endif // CONFIG_IDF_TARGET_ESP32
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32S2
|
||||
/**
|
||||
* @brief DAC digital controller initialization.
|
||||
* @return
|
||||
* - ESP_OK success
|
||||
*/
|
||||
esp_err_t dac_digi_init(void);
|
||||
|
||||
/**
|
||||
* @brief DAC digital controller deinitialization.
|
||||
* @return
|
||||
* - ESP_OK success
|
||||
*/
|
||||
esp_err_t dac_digi_deinit(void);
|
||||
|
||||
/**
|
||||
* @brief Setting the DAC digital controller.
|
||||
*
|
||||
* @param cfg Pointer to digital controller parameter. See ``dac_digi_config_t``.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK success
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
*/
|
||||
esp_err_t dac_digi_controller_config(const dac_digi_config_t *cfg);
|
||||
|
||||
/**
|
||||
* @brief DAC digital controller start output voltage.
|
||||
* @return
|
||||
* - ESP_OK success
|
||||
*/
|
||||
esp_err_t dac_digi_start(void);
|
||||
|
||||
/**
|
||||
* @brief DAC digital controller stop output voltage.
|
||||
* @return
|
||||
* - ESP_OK success
|
||||
*/
|
||||
esp_err_t dac_digi_stop(void);
|
||||
|
||||
/**
|
||||
* @brief Reset DAC digital controller FIFO.
|
||||
* @return
|
||||
* - ESP_OK success
|
||||
*/
|
||||
esp_err_t dac_digi_fifo_reset(void);
|
||||
|
||||
/**
|
||||
* @brief Reset DAC digital controller.
|
||||
* @return
|
||||
* - ESP_OK success
|
||||
*/
|
||||
esp_err_t dac_digi_reset(void);
|
||||
#endif // CONFIG_IDF_TARGET_ESP32S2
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
79
components/driver/deprecated/driver/dac_types_legacy.h
Normal file
79
components/driver/deprecated/driver/dac_types_legacy.h
Normal file
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include "sdkconfig.h"
|
||||
#include "hal/dac_types.h"
|
||||
#if CONFIG_IDF_TARGET_ESP32S2
|
||||
#include "hal/adc_types.h"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief The multiple of the amplitude of the cosine wave generator. The max amplitude is VDD3P3_RTC.
|
||||
*/
|
||||
typedef enum {
|
||||
DAC_CW_SCALE_1 = 0x0, /*!< 1/1. Default. */
|
||||
DAC_CW_SCALE_2 = 0x1, /*!< 1/2. */
|
||||
DAC_CW_SCALE_4 = 0x2, /*!< 1/4. */
|
||||
DAC_CW_SCALE_8 = 0x3, /*!< 1/8. */
|
||||
} dac_cw_scale_t;
|
||||
|
||||
/**
|
||||
* @brief Set the phase of the cosine wave generator output.
|
||||
*/
|
||||
typedef enum {
|
||||
DAC_CW_PHASE_0 = 0x2, /*!< Phase shift +0° */
|
||||
DAC_CW_PHASE_180 = 0x3, /*!< Phase shift +180° */
|
||||
} dac_cw_phase_t;
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32S2
|
||||
/**
|
||||
* @brief DAC digital controller (DMA mode) work mode.
|
||||
*/
|
||||
typedef enum {
|
||||
DAC_CONV_NORMAL, /*!< The data in the DMA buffer is simultaneously output to the enable channel of the DAC. */
|
||||
DAC_CONV_ALTER, /*!< The data in the DMA buffer is alternately output to the enable channel of the DAC. */
|
||||
DAC_CONV_MAX
|
||||
} dac_digi_convert_mode_t;
|
||||
|
||||
/**
|
||||
* @brief DAC digital controller (DMA mode) configuration parameters.
|
||||
*/
|
||||
typedef struct {
|
||||
dac_digi_convert_mode_t mode; /*!<DAC digital controller (DMA mode) work mode. See ``dac_digi_convert_mode_t``. */
|
||||
uint32_t interval; /*!<The number of interval clock cycles for the DAC digital controller to output voltage.
|
||||
The unit is the divided clock. Range: 1 ~ 4095.
|
||||
Expression: `dac_output_freq` = `controller_clk` / interval. Refer to ``adc_digi_clk_t``.
|
||||
Note: The sampling rate of each channel is also related to the conversion mode (See ``dac_digi_convert_mode_t``) and pattern table settings. */
|
||||
adc_digi_clk_t dig_clk; /*!<DAC digital controller clock divider settings. Refer to ``adc_digi_clk_t``.
|
||||
Note: The clocks of the DAC digital controller use the ADC digital controller clock divider. */
|
||||
} dac_digi_config_t;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Config the cosine wave generator function in DAC module.
|
||||
*/
|
||||
typedef struct {
|
||||
dac_channel_t en_ch; /*!< Enable the cosine wave generator of DAC channel. */
|
||||
dac_cw_scale_t scale; /*!< Set the amplitude of the cosine wave generator output. */
|
||||
dac_cw_phase_t phase; /*!< Set the phase of the cosine wave generator output. */
|
||||
uint32_t freq; /*!< Set frequency of cosine wave generator output. Range: 130(130Hz) ~ 55000(100KHz). */
|
||||
int8_t offset; /*!< Set the voltage value of the DC component of the cosine wave generator output.
|
||||
Note: Unreasonable settings can cause waveform to be oversaturated. Range: -128 ~ 127. */
|
||||
} dac_cw_config_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
383
components/driver/deprecated/driver/i2s.h
Normal file
383
components/driver/deprecated/driver/i2s.h
Normal file
@@ -0,0 +1,383 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* This file is for the backward compatible to the deprecated I2S APIs,
|
||||
* The deprecated APIs will no longer supported in the future
|
||||
* Please refer to "driver/i2s_std.h", "driver/i2s_pdm.h" and ""driver/i2s_tdm.h"" for the latest I2S driver
|
||||
* Note that only one set of I2S APIs is allowed to be used at the same time
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "esp_types.h"
|
||||
#include "esp_err.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/semphr.h"
|
||||
#include "driver/i2s_types_legacy.h"
|
||||
|
||||
#if SOC_I2S_SUPPORTS_ADC
|
||||
#include "driver/adc.h"
|
||||
#endif
|
||||
|
||||
#if !CONFIG_I2S_SUPPRESS_DEPRECATE_WARN
|
||||
#warning "This set of I2S APIs has been deprecated, \
|
||||
please include 'driver/i2s_std.h', 'driver/i2s_pdm.h' or 'driver/i2s_tdm.h' instead. \
|
||||
if you want to keep using the old APIs and ignore this warning, \
|
||||
you can enable 'Suppress legacy driver deprecated warning' option under 'I2S Configuration' menu in Kconfig"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Set I2S pin number
|
||||
*
|
||||
* @note
|
||||
* The I2S peripheral output signals can be connected to multiple GPIO pads.
|
||||
* However, the I2S peripheral input signal can only be connected to one GPIO pad.
|
||||
*
|
||||
* @param i2s_num I2S port number
|
||||
*
|
||||
* @param pin I2S Pin structure, or NULL to set 2-channel 8-bit internal DAC pin configuration (GPIO25 & GPIO26)
|
||||
*
|
||||
* Inside the pin configuration structure, set I2S_PIN_NO_CHANGE for any pin where
|
||||
* the current configuration should not be changed.
|
||||
*
|
||||
* @note if *pin is set as NULL, this function will initialize both of the built-in DAC channels by default.
|
||||
* if you don't want this to happen and you want to initialize only one of the DAC channels, you can call i2s_set_dac_mode instead.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
* - ESP_FAIL IO error
|
||||
*/
|
||||
esp_err_t i2s_set_pin(i2s_port_t i2s_num, const i2s_pin_config_t *pin);
|
||||
|
||||
#if SOC_I2S_SUPPORTS_PDM_RX
|
||||
/**
|
||||
* @brief Set PDM mode down-sample rate
|
||||
* In PDM RX mode, there would be 2 rounds of downsample process in hardware.
|
||||
* In the first downsample process, the sampling number can be 16 or 8.
|
||||
* In the second downsample process, the sampling number is fixed as 8.
|
||||
* So the clock frequency in PDM RX mode would be (fpcm * 64) or (fpcm * 128) accordingly.
|
||||
* @param i2s_num I2S port number
|
||||
* @param downsample i2s RX down sample rate for PDM mode.
|
||||
*
|
||||
* @note After calling this function, it would call i2s_set_clk inside to update the clock frequency.
|
||||
* Please call this function after I2S driver has been initialized.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
* - ESP_ERR_NO_MEM Out of memory
|
||||
*/
|
||||
esp_err_t i2s_set_pdm_rx_down_sample(i2s_port_t i2s_num, i2s_pdm_dsr_t downsample);
|
||||
#endif
|
||||
|
||||
#if SOC_I2S_SUPPORTS_PDM_TX
|
||||
/**
|
||||
* @brief Set TX PDM mode up-sample rate
|
||||
* @note If you have set PDM mode while calling 'i2s_driver_install',
|
||||
* default PDM TX upsample parameters have already been set,
|
||||
* no need to call this function again if you don't have to change the default configuration
|
||||
*
|
||||
* @param i2s_num I2S port number
|
||||
* @param upsample_cfg Set I2S PDM up-sample rate configuration
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
* - ESP_ERR_NO_MEM Out of memory
|
||||
*/
|
||||
esp_err_t i2s_set_pdm_tx_up_sample(i2s_port_t i2s_num, const i2s_pdm_tx_upsample_cfg_t *upsample_cfg);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Install and start I2S driver.
|
||||
*
|
||||
* @param i2s_num I2S port number
|
||||
*
|
||||
* @param i2s_config I2S configurations - see i2s_config_t struct
|
||||
*
|
||||
* @param queue_size I2S event queue size/depth.
|
||||
*
|
||||
* @param i2s_queue I2S event queue handle, if set NULL, driver will not use an event queue.
|
||||
*
|
||||
* This function must be called before any I2S driver read/write operations.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
* - ESP_ERR_NO_MEM Out of memory
|
||||
* - ESP_ERR_INVALID_STATE Current I2S port is in use
|
||||
*/
|
||||
esp_err_t i2s_driver_install(i2s_port_t i2s_num, const i2s_config_t *i2s_config, int queue_size, void *i2s_queue);
|
||||
|
||||
/**
|
||||
* @brief Uninstall I2S driver.
|
||||
*
|
||||
* @param i2s_num I2S port number
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
* - ESP_ERR_INVALID_STATE I2S port has been uninstalled by others (e.g. LCD i80)
|
||||
*/
|
||||
esp_err_t i2s_driver_uninstall(i2s_port_t i2s_num);
|
||||
|
||||
/**
|
||||
* @brief Write data to I2S DMA transmit buffer.
|
||||
*
|
||||
* @param i2s_num I2S port number
|
||||
*
|
||||
* @param src Source address to write from
|
||||
*
|
||||
* @param size Size of data in bytes
|
||||
*
|
||||
* @param[out] bytes_written Number of bytes written, if timeout, the result will be less than the size passed in.
|
||||
*
|
||||
* @param ticks_to_wait TX buffer wait timeout in RTOS ticks. If this
|
||||
* many ticks pass without space becoming available in the DMA
|
||||
* transmit buffer, then the function will return (note that if the
|
||||
* data is written to the DMA buffer in pieces, the overall operation
|
||||
* may still take longer than this timeout.) Pass portMAX_DELAY for no
|
||||
* timeout.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
*/
|
||||
esp_err_t i2s_write(i2s_port_t i2s_num, const void *src, size_t size, size_t *bytes_written, TickType_t ticks_to_wait);
|
||||
|
||||
/**
|
||||
* @brief Write data to I2S DMA transmit buffer while expanding the number of bits per sample. For example, expanding 16-bit PCM to 32-bit PCM.
|
||||
*
|
||||
* @param i2s_num I2S port number
|
||||
*
|
||||
* @param src Source address to write from
|
||||
*
|
||||
* @param size Size of data in bytes
|
||||
*
|
||||
* @param src_bits Source audio bit
|
||||
*
|
||||
* @param aim_bits Bit wanted, no more than 32, and must be greater than src_bits
|
||||
*
|
||||
* @param[out] bytes_written Number of bytes written, if timeout, the result will be less than the size passed in.
|
||||
*
|
||||
* @param ticks_to_wait TX buffer wait timeout in RTOS ticks. If this
|
||||
* many ticks pass without space becoming available in the DMA
|
||||
* transmit buffer, then the function will return (note that if the
|
||||
* data is written to the DMA buffer in pieces, the overall operation
|
||||
* may still take longer than this timeout.) Pass portMAX_DELAY for no
|
||||
* timeout.
|
||||
*
|
||||
* Format of the data in source buffer is determined by the I2S
|
||||
* configuration (see i2s_config_t).
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
*/
|
||||
esp_err_t i2s_write_expand(i2s_port_t i2s_num, const void *src, size_t size, size_t src_bits, size_t aim_bits, size_t *bytes_written, TickType_t ticks_to_wait);
|
||||
|
||||
/**
|
||||
* @brief Read data from I2S DMA receive buffer
|
||||
*
|
||||
* @param i2s_num I2S port number
|
||||
*
|
||||
* @param dest Destination address to read into
|
||||
*
|
||||
* @param size Size of data in bytes
|
||||
*
|
||||
* @param[out] bytes_read Number of bytes read, if timeout, bytes read will be less than the size passed in.
|
||||
*
|
||||
* @param ticks_to_wait RX buffer wait timeout in RTOS ticks. If this many ticks pass without bytes becoming available in the DMA receive buffer, then the function will return (note that if data is read from the DMA buffer in pieces, the overall operation may still take longer than this timeout.) Pass portMAX_DELAY for no timeout.
|
||||
*
|
||||
* @note If the built-in ADC mode is enabled, we should call i2s_adc_enable and i2s_adc_disable around the whole reading process,
|
||||
* to prevent the data getting corrupted.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
*/
|
||||
esp_err_t i2s_read(i2s_port_t i2s_num, void *dest, size_t size, size_t *bytes_read, TickType_t ticks_to_wait);
|
||||
|
||||
/**
|
||||
* @brief Set sample rate used for I2S RX and TX.
|
||||
*
|
||||
* The bit clock rate is determined by the sample rate and i2s_config_t configuration parameters (number of channels, bits_per_sample).
|
||||
*
|
||||
* `bit_clock = rate * (number of channels) * bits_per_sample`
|
||||
*
|
||||
* @param i2s_num I2S port number
|
||||
*
|
||||
* @param rate I2S sample rate (ex: 8000, 44100...)
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
* - ESP_ERR_NO_MEM Out of memory
|
||||
*/
|
||||
esp_err_t i2s_set_sample_rates(i2s_port_t i2s_num, uint32_t rate);
|
||||
|
||||
/**
|
||||
* @brief Stop I2S driver
|
||||
*
|
||||
* There is no need to call i2s_stop() before calling i2s_driver_uninstall().
|
||||
*
|
||||
* Disables I2S TX/RX, until i2s_start() is called.
|
||||
*
|
||||
* @param i2s_num I2S port number
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
*/
|
||||
esp_err_t i2s_stop(i2s_port_t i2s_num);
|
||||
|
||||
/**
|
||||
* @brief Start I2S driver
|
||||
*
|
||||
* It is not necessary to call this function after i2s_driver_install() (it is started automatically), however it is necessary to call it after i2s_stop().
|
||||
*
|
||||
*
|
||||
* @param i2s_num I2S port number
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
*/
|
||||
esp_err_t i2s_start(i2s_port_t i2s_num);
|
||||
|
||||
/**
|
||||
* @brief Zero the contents of the TX DMA buffer.
|
||||
*
|
||||
* Pushes zero-byte samples into the TX DMA buffer, until it is full.
|
||||
*
|
||||
* @param i2s_num I2S port number
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
*/
|
||||
esp_err_t i2s_zero_dma_buffer(i2s_port_t i2s_num);
|
||||
|
||||
#if SOC_I2S_SUPPORTS_PCM
|
||||
/**
|
||||
* @brief Configure I2S a/u-law decompress or compress
|
||||
*
|
||||
* @note This function should be called after i2s driver installed
|
||||
* Only take effecttive when the i2s 'communication_format' is set to 'I2S_COMM_FORMAT_STAND_PCM_SHORT' or 'I2S_COMM_FORMAT_STAND_PCM_LONG'
|
||||
*
|
||||
* @param i2s_num I2S port number
|
||||
*
|
||||
* @param pcm_cfg including mode selection and a/u-law decompress or compress configuration parameter
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
*/
|
||||
esp_err_t i2s_pcm_config(i2s_port_t i2s_num, const i2s_pcm_cfg_t *pcm_cfg);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Set clock & bit width used for I2S RX and TX.
|
||||
*
|
||||
* Similar to i2s_set_sample_rates(), but also sets bit width.
|
||||
*
|
||||
* 1. stop i2s;
|
||||
* 2. calculate mclk, bck, bck_factor
|
||||
* 3. malloc dma buffer;
|
||||
* 4. start i2s
|
||||
*
|
||||
* @param i2s_num I2S port number
|
||||
*
|
||||
* @param rate I2S sample rate (ex: 8000, 44100...)
|
||||
*
|
||||
* @param bits_cfg I2S bits configuration
|
||||
* the low 16 bits is for data bits per sample in one channel (see 'i2s_bits_per_sample_t')
|
||||
* the high 16 bits is for total bits in one channel (see 'i2s_bits_per_chan_t')
|
||||
* high 16bits =0 means same as the bits per sample.
|
||||
*
|
||||
* @param ch I2S channel, (I2S_CHANNEL_MONO, I2S_CHANNEL_STEREO or specific channel in TDM mode)
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
* - ESP_ERR_NO_MEM Out of memory
|
||||
*/
|
||||
esp_err_t i2s_set_clk(i2s_port_t i2s_num, uint32_t rate, uint32_t bits_cfg, i2s_channel_t ch);
|
||||
|
||||
/**
|
||||
* @brief get clock set on particular port number.
|
||||
*
|
||||
* @param i2s_num I2S port number
|
||||
*
|
||||
* @return
|
||||
* - actual clock set by i2s driver
|
||||
*/
|
||||
float i2s_get_clk(i2s_port_t i2s_num);
|
||||
|
||||
#if SOC_I2S_SUPPORTS_ADC
|
||||
/**
|
||||
* @brief Set built-in ADC mode for I2S DMA, this function will initialize ADC pad,
|
||||
* and set ADC parameters.
|
||||
* @note In this mode, the ADC maximum sampling rate is 150KHz. Set the sampling rate through ``i2s_config_t``.
|
||||
* @param adc_unit SAR ADC unit index
|
||||
* @param adc_channel ADC channel index
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
*/
|
||||
esp_err_t i2s_set_adc_mode(adc_unit_t adc_unit, adc1_channel_t adc_channel);
|
||||
|
||||
/**
|
||||
* @brief Start to use I2S built-in ADC mode
|
||||
* @note This function would acquire the lock of ADC to prevent the data getting corrupted
|
||||
* during the I2S peripheral is being used to do fully continuous ADC sampling.
|
||||
*
|
||||
* @param i2s_num i2s port index
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
* - ESP_ERR_INVALID_STATE Driver state error
|
||||
*/
|
||||
esp_err_t i2s_adc_enable(i2s_port_t i2s_num);
|
||||
|
||||
/**
|
||||
* @brief Stop to use I2S built-in ADC mode
|
||||
* @param i2s_num i2s port index
|
||||
* @note This function would release the lock of ADC so that other tasks can use ADC.
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
* - ESP_ERR_INVALID_STATE Driver state error
|
||||
*/
|
||||
esp_err_t i2s_adc_disable(i2s_port_t i2s_num);
|
||||
#endif // SOC_I2S_SUPPORTS_ADC
|
||||
|
||||
#if SOC_I2S_SUPPORTS_DAC
|
||||
/**
|
||||
* @brief Set I2S dac mode, I2S built-in DAC is disabled by default
|
||||
*
|
||||
* @param dac_mode DAC mode configurations - see i2s_dac_mode_t
|
||||
*
|
||||
* @note Built-in DAC functions are only supported on I2S0 for current ESP32 chip.
|
||||
* If either of the built-in DAC channel are enabled, the other one can not
|
||||
* be used as RTC DAC function at the same time.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
*/
|
||||
esp_err_t i2s_set_dac_mode(i2s_dac_mode_t dac_mode);
|
||||
#endif //SOC_I2S_SUPPORTS_DAC
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
251
components/driver/deprecated/driver/i2s_types_legacy.h
Normal file
251
components/driver/deprecated/driver/i2s_types_legacy.h
Normal file
@@ -0,0 +1,251 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* This file is for the backward compatible to the deprecated I2S APIs,
|
||||
* The deprecated APIs will no longer supported in the future
|
||||
* Please refer to "hal/i2s_types.h" for the latest I2S driver types
|
||||
* Note that only one set of I2S APIs is allowed to be used at the same time
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "hal/i2s_types.h"
|
||||
#include "driver/i2s_types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
/******************** Deprecated Types **********************/
|
||||
#define I2S_PIN_NO_CHANGE (-1) /*!< Used in i2s_pin_config_t for pins which should not be changed */
|
||||
|
||||
/**
|
||||
* @brief I2S bit width per sample.
|
||||
*/
|
||||
typedef enum {
|
||||
I2S_BITS_PER_SAMPLE_8BIT = 8, /*!< data bit-width: 8 */
|
||||
I2S_BITS_PER_SAMPLE_16BIT = 16, /*!< data bit-width: 16 */
|
||||
I2S_BITS_PER_SAMPLE_24BIT = 24, /*!< data bit-width: 24 */
|
||||
I2S_BITS_PER_SAMPLE_32BIT = 32, /*!< data bit-width: 32 */
|
||||
} i2s_bits_per_sample_t;
|
||||
|
||||
/**
|
||||
* @brief I2S bit width per chan.
|
||||
*/
|
||||
typedef enum {
|
||||
I2S_BITS_PER_CHAN_DEFAULT = (0), /*!< channel bit-width equals to data bit-width */
|
||||
I2S_BITS_PER_CHAN_8BIT = (8), /*!< channel bit-width: 8 */
|
||||
I2S_BITS_PER_CHAN_16BIT = (16), /*!< channel bit-width: 16 */
|
||||
I2S_BITS_PER_CHAN_24BIT = (24), /*!< channel bit-width: 24 */
|
||||
I2S_BITS_PER_CHAN_32BIT = (32), /*!< channel bit-width: 32 */
|
||||
} i2s_bits_per_chan_t;
|
||||
|
||||
/**
|
||||
* @brief I2S channel.
|
||||
*/
|
||||
typedef enum {
|
||||
I2S_CHANNEL_MONO = 1, /*!< I2S channel (mono), one channel activated. In this mode, you only need to send one channel data but the fifo will copy same data for the other unactivated channels automatically, then both channels will transmit same data. */
|
||||
I2S_CHANNEL_STEREO = 2, /*!< I2S channel (stereo), two (or more) channels activated. In this mode, these channels will transmit different data. */
|
||||
#if SOC_I2S_SUPPORTS_TDM
|
||||
// Bit map of activated chan.
|
||||
// There are 16 channels in TDM mode.
|
||||
// For TX module, only the activated channel send the audio data, the unactivated channel send a constant(configurable) or will be skipped if 'skip_msk' is set.
|
||||
// For RX module, only receive the audio data in activated channels, the data in unactivated channels will be ignored.
|
||||
// the bit map of activated channel can not exceed the maximum enabled channel number (i.e. 0x10000 << total_chan_num).
|
||||
// e.g: active_chan_mask = (I2S_TDM_ACTIVE_CH0 | I2S_TDM_ACTIVE_CH3), here the active_chan_number is 2 and total_chan_num is not supposed to be smaller than 4.
|
||||
I2S_TDM_ACTIVE_CH0 = (0x1 << 16), /*!< I2S channel 0 activated */
|
||||
I2S_TDM_ACTIVE_CH1 = (0x1 << 17), /*!< I2S channel 1 activated */
|
||||
I2S_TDM_ACTIVE_CH2 = (0x1 << 18), /*!< I2S channel 2 activated */
|
||||
I2S_TDM_ACTIVE_CH3 = (0x1 << 19), /*!< I2S channel 3 activated */
|
||||
I2S_TDM_ACTIVE_CH4 = (0x1 << 20), /*!< I2S channel 4 activated */
|
||||
I2S_TDM_ACTIVE_CH5 = (0x1 << 21), /*!< I2S channel 5 activated */
|
||||
I2S_TDM_ACTIVE_CH6 = (0x1 << 22), /*!< I2S channel 6 activated */
|
||||
I2S_TDM_ACTIVE_CH7 = (0x1 << 23), /*!< I2S channel 7 activated */
|
||||
I2S_TDM_ACTIVE_CH8 = (0x1 << 24), /*!< I2S channel 8 activated */
|
||||
I2S_TDM_ACTIVE_CH9 = (0x1 << 25), /*!< I2S channel 9 activated */
|
||||
I2S_TDM_ACTIVE_CH10 = (0x1 << 26), /*!< I2S channel 10 activated */
|
||||
I2S_TDM_ACTIVE_CH11 = (0x1 << 27), /*!< I2S channel 11 activated */
|
||||
I2S_TDM_ACTIVE_CH12 = (0x1 << 28), /*!< I2S channel 12 activated */
|
||||
I2S_TDM_ACTIVE_CH13 = (0x1 << 29), /*!< I2S channel 13 activated */
|
||||
I2S_TDM_ACTIVE_CH14 = (0x1 << 30), /*!< I2S channel 14 activated */
|
||||
I2S_TDM_ACTIVE_CH15 = (0x1 << 31), /*!< I2S channel 15 activated */
|
||||
#endif
|
||||
} i2s_channel_t;
|
||||
|
||||
/**
|
||||
* @brief I2S communication standard format
|
||||
*/
|
||||
typedef enum {
|
||||
I2S_COMM_FORMAT_STAND_I2S = 0X01, /*!< I2S communication I2S Philips standard, data launch at second BCK*/
|
||||
I2S_COMM_FORMAT_STAND_MSB = 0X02, /*!< I2S communication MSB alignment standard, data launch at first BCK*/
|
||||
I2S_COMM_FORMAT_STAND_PCM_SHORT = 0x04, /*!< PCM Short standard, also known as DSP mode. The period of synchronization signal (WS) is 1 bck cycle.*/
|
||||
I2S_COMM_FORMAT_STAND_PCM_LONG = 0x0C, /*!< PCM Long standard. The period of synchronization signal (WS) is channel_bit*bck cycles.*/
|
||||
I2S_COMM_FORMAT_STAND_MAX, /*!< standard max*/
|
||||
|
||||
//old definition will be removed in the future.
|
||||
I2S_COMM_FORMAT_I2S __attribute__((deprecated)) = 0x01, /*!< I2S communication format I2S, correspond to `I2S_COMM_FORMAT_STAND_I2S`*/
|
||||
I2S_COMM_FORMAT_I2S_MSB __attribute__((deprecated)) = 0x01, /*!< I2S format MSB, (I2S_COMM_FORMAT_I2S |I2S_COMM_FORMAT_I2S_MSB) correspond to `I2S_COMM_FORMAT_STAND_I2S`*/
|
||||
I2S_COMM_FORMAT_I2S_LSB __attribute__((deprecated)) = 0x02, /*!< I2S format LSB, (I2S_COMM_FORMAT_I2S |I2S_COMM_FORMAT_I2S_LSB) correspond to `I2S_COMM_FORMAT_STAND_MSB`*/
|
||||
I2S_COMM_FORMAT_PCM __attribute__((deprecated)) = 0x04, /*!< I2S communication format PCM, correspond to `I2S_COMM_FORMAT_STAND_PCM_SHORT`*/
|
||||
I2S_COMM_FORMAT_PCM_SHORT __attribute__((deprecated)) = 0x04, /*!< PCM Short, (I2S_COMM_FORMAT_PCM | I2S_COMM_FORMAT_PCM_SHORT) correspond to `I2S_COMM_FORMAT_STAND_PCM_SHORT`*/
|
||||
I2S_COMM_FORMAT_PCM_LONG __attribute__((deprecated)) = 0x08, /*!< PCM Long, (I2S_COMM_FORMAT_PCM | I2S_COMM_FORMAT_PCM_LONG) correspond to `I2S_COMM_FORMAT_STAND_PCM_LONG`*/
|
||||
} i2s_comm_format_t;
|
||||
|
||||
/**
|
||||
* @brief I2S channel format type
|
||||
*/
|
||||
typedef enum {
|
||||
I2S_CHANNEL_FMT_RIGHT_LEFT, /*!< Separated left and right channel */
|
||||
I2S_CHANNEL_FMT_ALL_RIGHT, /*!< Load right channel data in both two channels */
|
||||
I2S_CHANNEL_FMT_ALL_LEFT, /*!< Load left channel data in both two channels */
|
||||
I2S_CHANNEL_FMT_ONLY_RIGHT, /*!< Only load data in right channel (mono mode) */
|
||||
I2S_CHANNEL_FMT_ONLY_LEFT, /*!< Only load data in left channel (mono mode) */
|
||||
#if SOC_I2S_SUPPORTS_TDM
|
||||
// Multiple channels are available with TDM feature
|
||||
I2S_CHANNEL_FMT_MULTIPLE, /*!< More than two channels are used */
|
||||
#endif
|
||||
} i2s_channel_fmt_t;
|
||||
|
||||
/**
|
||||
* @brief I2S Mode
|
||||
*/
|
||||
typedef enum {
|
||||
I2S_MODE_MASTER = (0x1 << 0), /*!< Master mode*/
|
||||
I2S_MODE_SLAVE = (0x1 << 1), /*!< Slave mode*/
|
||||
I2S_MODE_TX = (0x1 << 2), /*!< TX mode*/
|
||||
I2S_MODE_RX = (0x1 << 3), /*!< RX mode*/
|
||||
#if SOC_I2S_SUPPORTS_DAC
|
||||
//built-in DAC functions are only supported on I2S0 for ESP32 chip.
|
||||
I2S_MODE_DAC_BUILT_IN = (0x1 << 4), /*!< Output I2S data to built-in DAC, no matter the data format is 16bit or 32 bit, the DAC module will only take the 8bits from MSB*/
|
||||
#endif // SOC_I2S_SUPPORTS_DAC
|
||||
#if SOC_I2S_SUPPORTS_ADC
|
||||
I2S_MODE_ADC_BUILT_IN = (0x1 << 5), /*!< Input I2S data from built-in ADC, each data can be 12-bit width at most*/
|
||||
#endif // SOC_I2S_SUPPORTS_ADC
|
||||
// PDM functions are only supported on I2S0 (all chips).
|
||||
I2S_MODE_PDM = (0x1 << 6), /*!< I2S PDM mode*/
|
||||
} i2s_mode_t;
|
||||
|
||||
#if SOC_I2S_SUPPORTS_DAC
|
||||
/**
|
||||
* @brief I2S DAC mode for i2s_set_dac_mode.
|
||||
*
|
||||
* @note Built-in DAC functions are only supported on I2S0 for current ESP32 chip.
|
||||
*/
|
||||
typedef enum {
|
||||
I2S_DAC_CHANNEL_DISABLE = 0, /*!< Disable I2S built-in DAC signals*/
|
||||
I2S_DAC_CHANNEL_RIGHT_EN = 1, /*!< Enable I2S built-in DAC right channel, maps to DAC channel 0 on GPIO25*/
|
||||
I2S_DAC_CHANNEL_LEFT_EN = 2, /*!< Enable I2S built-in DAC left channel, maps to DAC channel 1 on GPIO26*/
|
||||
I2S_DAC_CHANNEL_BOTH_EN = 0x3, /*!< Enable both of the I2S built-in DAC channels.*/
|
||||
I2S_DAC_CHANNEL_MAX = 0x4, /*!< I2S built-in DAC mode max index*/
|
||||
} i2s_dac_mode_t;
|
||||
#endif //SOC_I2S_SUPPORTS_DAC
|
||||
|
||||
/**
|
||||
* @brief I2S event queue types
|
||||
*/
|
||||
typedef enum {
|
||||
I2S_EVENT_DMA_ERROR, /*!< I2S DMA has no next descriptor for sending or receiving */
|
||||
I2S_EVENT_TX_DONE, /*!< I2S DMA finished sending one DMA buffer */
|
||||
I2S_EVENT_RX_DONE, /*!< I2S DMA finished receiving one DMA buffer */
|
||||
I2S_EVENT_TX_Q_OVF, /*!< I2S DMA sending queue overflowed, the oldest data has been overwritten by the new data in the DMA buffer */
|
||||
I2S_EVENT_RX_Q_OVF, /*!< I2S DMA receive queue overflowed, the oldest data has been overwritten by the new data in the DMA buffer */
|
||||
} i2s_event_type_t;
|
||||
|
||||
/**
|
||||
* @brief Event structure used in I2S event queue
|
||||
*/
|
||||
typedef struct {
|
||||
i2s_event_type_t type; /*!< I2S event type */
|
||||
size_t size; /*!< I2S data size for I2S_DATA event*/
|
||||
} i2s_event_t;
|
||||
|
||||
/**
|
||||
* @brief I2S GPIO pins configuration
|
||||
*/
|
||||
typedef struct {
|
||||
int mck_io_num; /*!< MCK pin, output */
|
||||
int bck_io_num; /*!< BCK pin, input in slave role, output in master role */
|
||||
int ws_io_num; /*!< WS pin, input in slave role, output in master role */
|
||||
int data_out_num; /*!< DATA pin, output */
|
||||
int data_in_num; /*!< DATA pin, input */
|
||||
} i2s_pin_config_t;
|
||||
|
||||
#if SOC_I2S_SUPPORTS_PCM
|
||||
/**
|
||||
* @brief I2S PCM configuration
|
||||
*
|
||||
*/
|
||||
typedef struct {
|
||||
i2s_pcm_compress_t pcm_type; /*!< I2S PCM a/u-law decompress or compress type */
|
||||
} i2s_pcm_cfg_t;
|
||||
#endif
|
||||
|
||||
#if SOC_I2S_SUPPORTS_PDM_TX
|
||||
/**
|
||||
* @brief Default I2S PDM Up-Sampling Rate configuration
|
||||
*/
|
||||
#define I2S_PDM_DEFAULT_UPSAMPLE_CONFIG(rate) { \
|
||||
.sample_rate = rate, \
|
||||
.fp = 960, \
|
||||
.fs = (rate) / 100, \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief I2S PDM up-sample rate configuration
|
||||
* @note TX PDM can only be set to the following two up-sampling rate configurations:
|
||||
* 1: fp = 960, fs = sample_rate / 100, in this case, Fpdm = 128*48000
|
||||
* 2: fp = 960, fs = 480, in this case, Fpdm = 128*Fpcm = 128*sample_rate
|
||||
* If the pdm receiver do not care the pdm serial clock, it's recommended set Fpdm = 128*48000.
|
||||
* Otherwise, the second configuration should be applied.
|
||||
*/
|
||||
typedef struct {
|
||||
int sample_rate; /*!< I2S PDM sample rate */
|
||||
int fp; /*!< I2S PDM TX up-sampling parameter. Normally it should be set to 960 */
|
||||
int fs; /*!< I2S PDM TX up-sampling parameter. When it is set to 480, the pdm clock frequency Fpdm = 128 * sample_rate, when it is set to sample_rate / 100, Fpdm will be fixed to 128*48000 */
|
||||
} i2s_pdm_tx_upsample_cfg_t;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief I2S driver configuration parameters
|
||||
*
|
||||
*/
|
||||
typedef struct {
|
||||
|
||||
i2s_mode_t mode; /*!< I2S work mode */
|
||||
uint32_t sample_rate; /*!< I2S sample rate */
|
||||
i2s_bits_per_sample_t bits_per_sample; /*!< I2S sample bits in one channel */
|
||||
i2s_channel_fmt_t channel_format; /*!< I2S channel format.*/
|
||||
i2s_comm_format_t communication_format; /*!< I2S communication format */
|
||||
int intr_alloc_flags; /*!< Flags used to allocate the interrupt. One or multiple (ORred) ESP_INTR_FLAG_* values. See esp_intr_alloc.h for more info */
|
||||
union {
|
||||
int dma_desc_num; /*!< The total number of descriptors used by I2S DMA to receive/transmit data */
|
||||
int dma_buf_count __attribute__((deprecated)); /*!< This is an alias to 'dma_desc_num' for backward compatibility */
|
||||
};
|
||||
union {
|
||||
int dma_frame_num; /*!< Frame number for one-time sampling. Frame here means the total data from all the channels in a WS cycle */
|
||||
int dma_buf_len __attribute__((deprecated)); /*!< This is an alias to 'dma_frame_num' for backward compatibility */
|
||||
};
|
||||
bool use_apll; /*!< I2S using APLL as main I2S clock, enable it to get accurate clock */
|
||||
bool tx_desc_auto_clear; /*!< I2S auto clear tx descriptor if there is underflow condition (helps in avoiding noise in case of data unavailability) */
|
||||
int fixed_mclk; /*!< I2S using fixed MCLK output. If use_apll = true and fixed_mclk > 0, then the clock output for i2s is fixed and equal to the fixed_mclk value. If fixed_mclk set, mclk_multiple won't take effect */
|
||||
i2s_mclk_multiple_t mclk_multiple; /*!< The multiple of I2S master clock(MCLK) to sample rate */
|
||||
i2s_bits_per_chan_t bits_per_chan; /*!< I2S total bits in one channel, only take effect when larger than 'bits_per_sample', default '0' means equal to 'bits_per_sample' */
|
||||
|
||||
#if SOC_I2S_SUPPORTS_TDM
|
||||
i2s_channel_t chan_mask; /*!< I2S active channel bit mask, set value in `i2s_channel_t` to enable specific channel, the bit map of active channel can not exceed (0x1<<total_chan). */
|
||||
uint32_t total_chan; /*!< I2S Total number of channels. If it is smaller than the biggest active channel number, it will be set to this number automatically. */
|
||||
bool left_align; /*!< Set to enable left alignment */
|
||||
bool big_edin; /*!< Set to enable big endian */
|
||||
bool bit_order_msb; /*!< Set to enable msb order */
|
||||
bool skip_msk; /*!< Set to enable skip mask. If it is enabled, only the data of the enabled channels will be sent, otherwise all data stored in DMA TX buffer will be sent */
|
||||
#endif // SOC_I2S_SUPPORTS_TDM
|
||||
|
||||
} i2s_driver_config_t;
|
||||
|
||||
typedef i2s_driver_config_t i2s_config_t; // for backward compatible
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
366
components/driver/deprecated/driver/pcnt.h
Normal file
366
components/driver/deprecated/driver/pcnt.h
Normal file
@@ -0,0 +1,366 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_err.h"
|
||||
#include "driver/pcnt_types_legacy.h"
|
||||
|
||||
#if !CONFIG_PCNT_SUPPRESS_DEPRECATE_WARN
|
||||
#warning "legacy pcnt driver is deprecated, please migrate to use driver/pulse_cnt.h"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Configure Pulse Counter unit
|
||||
* @note
|
||||
* This function will disable three events: PCNT_EVT_L_LIM, PCNT_EVT_H_LIM, PCNT_EVT_ZERO.
|
||||
*
|
||||
* @param pcnt_config Pointer of Pulse Counter unit configure parameter
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_STATE pcnt driver already initialized
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
*/
|
||||
esp_err_t pcnt_unit_config(const pcnt_config_t *pcnt_config);
|
||||
|
||||
/**
|
||||
* @brief Get pulse counter value
|
||||
*
|
||||
* @param pcnt_unit Pulse Counter unit number
|
||||
* @param count Pointer to accept counter value
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_STATE pcnt driver has not been initialized
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
*/
|
||||
esp_err_t pcnt_get_counter_value(pcnt_unit_t pcnt_unit, int16_t *count);
|
||||
|
||||
/**
|
||||
* @brief Pause PCNT counter of PCNT unit
|
||||
*
|
||||
* @param pcnt_unit PCNT unit number
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_STATE pcnt driver has not been initialized
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
*/
|
||||
esp_err_t pcnt_counter_pause(pcnt_unit_t pcnt_unit);
|
||||
|
||||
/**
|
||||
* @brief Resume counting for PCNT counter
|
||||
*
|
||||
* @param pcnt_unit PCNT unit number, select from pcnt_unit_t
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_STATE pcnt driver has not been initialized
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
*/
|
||||
esp_err_t pcnt_counter_resume(pcnt_unit_t pcnt_unit);
|
||||
|
||||
/**
|
||||
* @brief Clear and reset PCNT counter value to zero
|
||||
*
|
||||
* @param pcnt_unit PCNT unit number, select from pcnt_unit_t
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_STATE pcnt driver has not been initialized
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
*/
|
||||
esp_err_t pcnt_counter_clear(pcnt_unit_t pcnt_unit);
|
||||
|
||||
/**
|
||||
* @brief Enable PCNT interrupt for PCNT unit
|
||||
* @note
|
||||
* Each Pulse counter unit has five watch point events that share the same interrupt.
|
||||
* Configure events with pcnt_event_enable() and pcnt_event_disable()
|
||||
*
|
||||
* @param pcnt_unit PCNT unit number
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_STATE pcnt driver has not been initialized
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
*/
|
||||
esp_err_t pcnt_intr_enable(pcnt_unit_t pcnt_unit);
|
||||
|
||||
/**
|
||||
* @brief Disable PCNT interrupt for PCNT unit
|
||||
*
|
||||
* @param pcnt_unit PCNT unit number
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_STATE pcnt driver has not been initialized
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
*/
|
||||
esp_err_t pcnt_intr_disable(pcnt_unit_t pcnt_unit);
|
||||
|
||||
/**
|
||||
* @brief Enable PCNT event of PCNT unit
|
||||
*
|
||||
* @param unit PCNT unit number
|
||||
* @param evt_type Watch point event type.
|
||||
* All enabled events share the same interrupt (one interrupt per pulse counter unit).
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_STATE pcnt driver has not been initialized
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
*/
|
||||
esp_err_t pcnt_event_enable(pcnt_unit_t unit, pcnt_evt_type_t evt_type);
|
||||
|
||||
/**
|
||||
* @brief Disable PCNT event of PCNT unit
|
||||
*
|
||||
* @param unit PCNT unit number
|
||||
* @param evt_type Watch point event type.
|
||||
* All enabled events share the same interrupt (one interrupt per pulse counter unit).
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_STATE pcnt driver has not been initialized
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
*/
|
||||
esp_err_t pcnt_event_disable(pcnt_unit_t unit, pcnt_evt_type_t evt_type);
|
||||
|
||||
/**
|
||||
* @brief Set PCNT event value of PCNT unit
|
||||
*
|
||||
* @param unit PCNT unit number
|
||||
* @param evt_type Watch point event type.
|
||||
* All enabled events share the same interrupt (one interrupt per pulse counter unit).
|
||||
*
|
||||
* @param value Counter value for PCNT event
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_STATE pcnt driver has not been initialized
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
*/
|
||||
esp_err_t pcnt_set_event_value(pcnt_unit_t unit, pcnt_evt_type_t evt_type, int16_t value);
|
||||
|
||||
/**
|
||||
* @brief Get PCNT event value of PCNT unit
|
||||
*
|
||||
* @param unit PCNT unit number
|
||||
* @param evt_type Watch point event type.
|
||||
* All enabled events share the same interrupt (one interrupt per pulse counter unit).
|
||||
* @param value Pointer to accept counter value for PCNT event
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_STATE pcnt driver has not been initialized
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
*/
|
||||
esp_err_t pcnt_get_event_value(pcnt_unit_t unit, pcnt_evt_type_t evt_type, int16_t *value);
|
||||
|
||||
/**
|
||||
* @brief Get PCNT event status of PCNT unit
|
||||
*
|
||||
* @param unit PCNT unit number
|
||||
* @param status Pointer to accept event status word
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_STATE pcnt driver has not been initialized
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
*/
|
||||
esp_err_t pcnt_get_event_status(pcnt_unit_t unit, uint32_t *status);
|
||||
|
||||
/**
|
||||
* @brief Unregister PCNT interrupt handler (registered by pcnt_isr_register), the handler is an ISR.
|
||||
* The handler will be attached to the same CPU core that this function is running on.
|
||||
* If the interrupt service is registered by pcnt_isr_service_install, please call pcnt_isr_service_uninstall instead
|
||||
*
|
||||
* @param handle handle to unregister the ISR service.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_NOT_FOUND Can not find the interrupt that matches the flags.
|
||||
* - ESP_ERR_INVALID_ARG Function pointer error.
|
||||
*/
|
||||
esp_err_t pcnt_isr_unregister(pcnt_isr_handle_t handle);
|
||||
|
||||
/**
|
||||
* @brief Register PCNT interrupt handler, the handler is an ISR.
|
||||
* The handler will be attached to the same CPU core that this function is running on.
|
||||
* Please do not use pcnt_isr_service_install if this function was called.
|
||||
*
|
||||
* @param fn Interrupt handler function.
|
||||
* @param arg Parameter for handler function
|
||||
* @param intr_alloc_flags Flags used to allocate the interrupt. One or multiple (ORred)
|
||||
* ESP_INTR_FLAG_* values. See esp_intr_alloc.h for more info.
|
||||
* @param handle Pointer to return handle. If non-NULL, a handle for the interrupt will
|
||||
* be returned here. Calling pcnt_isr_unregister to unregister this ISR service if needed,
|
||||
* but only if the handle is not NULL.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_NOT_FOUND Can not find the interrupt that matches the flags.
|
||||
* - ESP_ERR_INVALID_ARG Function pointer error.
|
||||
*/
|
||||
esp_err_t pcnt_isr_register(void (*fn)(void *), void *arg, int intr_alloc_flags, pcnt_isr_handle_t *handle);
|
||||
|
||||
/**
|
||||
* @brief Configure PCNT pulse signal input pin and control input pin
|
||||
*
|
||||
* @param unit PCNT unit number
|
||||
* @param channel PCNT channel number
|
||||
* @param pulse_io Pulse signal input GPIO
|
||||
* @param ctrl_io Control signal input GPIO
|
||||
*
|
||||
* @note Set the signal input to PCNT_PIN_NOT_USED if unused.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_STATE pcnt driver has not been initialized
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
*/
|
||||
esp_err_t pcnt_set_pin(pcnt_unit_t unit, pcnt_channel_t channel, int pulse_io, int ctrl_io);
|
||||
|
||||
/**
|
||||
* @brief Enable PCNT input filter
|
||||
*
|
||||
* @param unit PCNT unit number
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_STATE pcnt driver has not been initialized
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
*/
|
||||
esp_err_t pcnt_filter_enable(pcnt_unit_t unit);
|
||||
|
||||
/**
|
||||
* @brief Disable PCNT input filter
|
||||
*
|
||||
* @param unit PCNT unit number
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_STATE pcnt driver has not been initialized
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
*/
|
||||
esp_err_t pcnt_filter_disable(pcnt_unit_t unit);
|
||||
|
||||
/**
|
||||
* @brief Set PCNT filter value
|
||||
*
|
||||
* @param unit PCNT unit number
|
||||
* @param filter_val PCNT signal filter value, counter in APB_CLK cycles.
|
||||
* Any pulses lasting shorter than this will be ignored when the filter is enabled.
|
||||
* @note
|
||||
* filter_val is a 10-bit value, so the maximum filter_val should be limited to 1023.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_STATE pcnt driver has not been initialized
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
*/
|
||||
esp_err_t pcnt_set_filter_value(pcnt_unit_t unit, uint16_t filter_val);
|
||||
|
||||
/**
|
||||
* @brief Get PCNT filter value
|
||||
*
|
||||
* @param unit PCNT unit number
|
||||
* @param filter_val Pointer to accept PCNT filter value.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_STATE pcnt driver has not been initialized
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
*/
|
||||
esp_err_t pcnt_get_filter_value(pcnt_unit_t unit, uint16_t *filter_val);
|
||||
|
||||
/**
|
||||
* @brief Set PCNT counter mode
|
||||
*
|
||||
* @param unit PCNT unit number
|
||||
* @param channel PCNT channel number
|
||||
* @param pos_mode Counter mode when detecting positive edge
|
||||
* @param neg_mode Counter mode when detecting negative edge
|
||||
* @param hctrl_mode Counter mode when control signal is high level
|
||||
* @param lctrl_mode Counter mode when control signal is low level
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_STATE pcnt driver has not been initialized
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
*/
|
||||
esp_err_t pcnt_set_mode(pcnt_unit_t unit, pcnt_channel_t channel,
|
||||
pcnt_count_mode_t pos_mode, pcnt_count_mode_t neg_mode,
|
||||
pcnt_ctrl_mode_t hctrl_mode, pcnt_ctrl_mode_t lctrl_mode);
|
||||
|
||||
/**
|
||||
* @brief Add ISR handler for specified unit.
|
||||
*
|
||||
* Call this function after using pcnt_isr_service_install() to
|
||||
* install the PCNT driver's ISR handler service.
|
||||
*
|
||||
* The ISR handlers do not need to be declared with IRAM_ATTR,
|
||||
* unless you pass the ESP_INTR_FLAG_IRAM flag when allocating the
|
||||
* ISR in pcnt_isr_service_install().
|
||||
*
|
||||
* This ISR handler will be called from an ISR. So there is a stack
|
||||
* size limit (configurable as "ISR stack size" in menuconfig). This
|
||||
* limit is smaller compared to a global PCNT interrupt handler due
|
||||
* to the additional level of indirection.
|
||||
*
|
||||
* @param unit PCNT unit number
|
||||
* @param isr_handler Interrupt handler function.
|
||||
* @param args Parameter for handler function
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_STATE pcnt driver has not been initialized
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
*/
|
||||
esp_err_t pcnt_isr_handler_add(pcnt_unit_t unit, void(*isr_handler)(void *), void *args);
|
||||
|
||||
/**
|
||||
* @brief Install PCNT ISR service.
|
||||
* @note We can manage different interrupt service for each unit.
|
||||
* This function will use the default ISR handle service, Calling pcnt_isr_service_uninstall to
|
||||
* uninstall the default service if needed. Please do not use pcnt_isr_register if this function was called.
|
||||
*
|
||||
* @param intr_alloc_flags Flags used to allocate the interrupt. One or multiple (ORred)
|
||||
* ESP_INTR_FLAG_* values. See esp_intr_alloc.h for more info.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_STATE pcnt driver has not been initialized
|
||||
* - ESP_ERR_NO_MEM No memory to install this service
|
||||
* - ESP_ERR_INVALID_STATE ISR service already installed
|
||||
*/
|
||||
esp_err_t pcnt_isr_service_install(int intr_alloc_flags);
|
||||
|
||||
/**
|
||||
* @brief Uninstall PCNT ISR service, freeing related resources.
|
||||
*/
|
||||
void pcnt_isr_service_uninstall(void);
|
||||
|
||||
/**
|
||||
* @brief Delete ISR handler for specified unit.
|
||||
*
|
||||
* @param unit PCNT unit number
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_STATE pcnt driver has not been initialized
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
*/
|
||||
esp_err_t pcnt_isr_handler_remove(pcnt_unit_t unit);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
108
components/driver/deprecated/driver/pcnt_types_legacy.h
Normal file
108
components/driver/deprecated/driver/pcnt_types_legacy.h
Normal file
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "esp_intr_alloc.h"
|
||||
#include "soc/soc_caps.h"
|
||||
#include "hal/pcnt_types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define PCNT_PIN_NOT_USED (-1) /*!< When selected for a pin, this pin will not be used */
|
||||
|
||||
/**
|
||||
* @brief PCNT interrupt handle
|
||||
*/
|
||||
typedef intr_handle_t pcnt_isr_handle_t;
|
||||
|
||||
/**
|
||||
* @brief PCNT port number, the max port number is (PCNT_PORT_MAX - 1).
|
||||
*/
|
||||
typedef enum {
|
||||
PCNT_PORT_0, /*!< PCNT port 0 */
|
||||
PCNT_PORT_MAX, /*!< PCNT port max */
|
||||
} pcnt_port_t;
|
||||
|
||||
/**
|
||||
* @brief Selection of all available PCNT units
|
||||
*/
|
||||
typedef enum {
|
||||
PCNT_UNIT_0, /*!< PCNT unit 0 */
|
||||
PCNT_UNIT_1, /*!< PCNT unit 1 */
|
||||
PCNT_UNIT_2, /*!< PCNT unit 2 */
|
||||
PCNT_UNIT_3, /*!< PCNT unit 3 */
|
||||
#if SOC_PCNT_UNITS_PER_GROUP > 4
|
||||
PCNT_UNIT_4, /*!< PCNT unit 4 */
|
||||
PCNT_UNIT_5, /*!< PCNT unit 5 */
|
||||
PCNT_UNIT_6, /*!< PCNT unit 6 */
|
||||
PCNT_UNIT_7, /*!< PCNT unit 7 */
|
||||
#endif
|
||||
PCNT_UNIT_MAX,
|
||||
} pcnt_unit_t;
|
||||
|
||||
/**
|
||||
* @brief Selection of channels available for a single PCNT unit
|
||||
*/
|
||||
typedef enum {
|
||||
PCNT_CHANNEL_0, /*!< PCNT channel 0 */
|
||||
PCNT_CHANNEL_1, /*!< PCNT channel 1 */
|
||||
PCNT_CHANNEL_MAX,
|
||||
} pcnt_channel_t;
|
||||
|
||||
/**
|
||||
* @brief Selection of counter's events the may trigger an interrupt
|
||||
*/
|
||||
typedef enum {
|
||||
PCNT_EVT_THRES_1 = 1 << 2, /*!< PCNT watch point event: threshold1 value event */
|
||||
PCNT_EVT_THRES_0 = 1 << 3, /*!< PCNT watch point event: threshold0 value event */
|
||||
PCNT_EVT_L_LIM = 1 << 4, /*!< PCNT watch point event: Minimum counter value */
|
||||
PCNT_EVT_H_LIM = 1 << 5, /*!< PCNT watch point event: Maximum counter value */
|
||||
PCNT_EVT_ZERO = 1 << 6, /*!< PCNT watch point event: counter value zero event */
|
||||
PCNT_EVT_MAX
|
||||
} pcnt_evt_type_t;
|
||||
|
||||
/**
|
||||
* @brief Selection of available modes that determine the counter's action depending on the state of the control signal's input GPIO
|
||||
* @note Configuration covers two actions, one for high, and one for low level on the control input
|
||||
*/
|
||||
typedef pcnt_channel_level_action_t pcnt_ctrl_mode_t;
|
||||
#define PCNT_MODE_KEEP PCNT_CHANNEL_LEVEL_ACTION_KEEP /*!< Control mode: won't change counter mode*/
|
||||
#define PCNT_MODE_REVERSE PCNT_CHANNEL_LEVEL_ACTION_INVERSE /*!< Control mode: invert counter mode(increase -> decrease, decrease -> increase) */
|
||||
#define PCNT_MODE_DISABLE PCNT_CHANNEL_LEVEL_ACTION_HOLD /*!< Control mode: Inhibit counter(counter value will not change in this condition) */
|
||||
#define PCNT_MODE_MAX 3
|
||||
|
||||
/**
|
||||
* @brief Selection of available modes that determine the counter's action on the edge of the pulse signal's input GPIO
|
||||
* @note Configuration covers two actions, one for positive, and one for negative edge on the pulse input
|
||||
*/
|
||||
typedef pcnt_channel_edge_action_t pcnt_count_mode_t;
|
||||
#define PCNT_COUNT_DIS PCNT_CHANNEL_EDGE_ACTION_HOLD /*!< Counter mode: Inhibit counter(counter value will not change in this condition) */
|
||||
#define PCNT_COUNT_INC PCNT_CHANNEL_EDGE_ACTION_INCREASE /*!< Counter mode: Increase counter value */
|
||||
#define PCNT_COUNT_DEC PCNT_CHANNEL_EDGE_ACTION_DECREASE /*!< Counter mode: Decrease counter value */
|
||||
#define PCNT_COUNT_MAX 3
|
||||
|
||||
/**
|
||||
* @brief Pulse Counter configuration for a single channel
|
||||
*/
|
||||
typedef struct {
|
||||
int pulse_gpio_num; /*!< Pulse input GPIO number, if you want to use GPIO16, enter pulse_gpio_num = 16, a negative value will be ignored */
|
||||
int ctrl_gpio_num; /*!< Control signal input GPIO number, a negative value will be ignored */
|
||||
pcnt_ctrl_mode_t lctrl_mode; /*!< PCNT low control mode */
|
||||
pcnt_ctrl_mode_t hctrl_mode; /*!< PCNT high control mode */
|
||||
pcnt_count_mode_t pos_mode; /*!< PCNT positive edge count mode */
|
||||
pcnt_count_mode_t neg_mode; /*!< PCNT negative edge count mode */
|
||||
int16_t counter_h_lim; /*!< Maximum counter value */
|
||||
int16_t counter_l_lim; /*!< Minimum counter value */
|
||||
pcnt_unit_t unit; /*!< PCNT unit number */
|
||||
pcnt_channel_t channel; /*!< the PCNT channel */
|
||||
} pcnt_config_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
77
components/driver/deprecated/driver/temp_sensor.h
Normal file
77
components/driver/deprecated/driver/temp_sensor.h
Normal file
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2010-2021 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_err.h"
|
||||
#include "driver/temp_sensor_types_legacy.h"
|
||||
|
||||
#if !CONFIG_TEMP_SENSOR_SUPPRESS_DEPRECATE_WARN
|
||||
#warning "legacy temperature sensor driver is deprecated, please migrate to driver/temperature_sensor.h"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Set parameter of temperature sensor.
|
||||
* @param tsens
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t temp_sensor_set_config(temp_sensor_config_t tsens);
|
||||
|
||||
/**
|
||||
* @brief Get parameter of temperature sensor.
|
||||
* @param tsens
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t temp_sensor_get_config(temp_sensor_config_t *tsens);
|
||||
|
||||
/**
|
||||
* @brief Start temperature sensor measure.
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_STATE if temperature sensor is started already.
|
||||
*/
|
||||
esp_err_t temp_sensor_start(void);
|
||||
|
||||
/**
|
||||
* @brief Stop temperature sensor measure.
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_STATE if temperature sensor is stopped already.
|
||||
*/
|
||||
esp_err_t temp_sensor_stop(void);
|
||||
|
||||
/**
|
||||
* @brief Read temperature sensor raw data.
|
||||
* @param tsens_out Pointer to raw data, Range: 0 ~ 255
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_ARG `tsens_out` is NULL
|
||||
* - ESP_ERR_INVALID_STATE temperature sensor dont start
|
||||
*/
|
||||
esp_err_t temp_sensor_read_raw(uint32_t *tsens_out);
|
||||
|
||||
/**
|
||||
* @brief Read temperature sensor data that is converted to degrees Celsius.
|
||||
* @note Should not be called from interrupt.
|
||||
* @param celsius The measure output value.
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_ARG ARG is NULL.
|
||||
* - ESP_ERR_INVALID_STATE The ambient temperature is out of range.
|
||||
*/
|
||||
esp_err_t temp_sensor_read_celsius(float *celsius);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2010-2021 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include "esp_err.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
TSENS_DAC_L0 = 0, /*!< offset = -2, measure range: 50℃ ~ 125℃, error < 3℃. */
|
||||
TSENS_DAC_L1, /*!< offset = -1, measure range: 20℃ ~ 100℃, error < 2℃. */
|
||||
TSENS_DAC_L2, /*!< offset = 0, measure range:-10℃ ~ 80℃, error < 1℃. */
|
||||
TSENS_DAC_L3, /*!< offset = 1, measure range:-30℃ ~ 50℃, error < 2℃. */
|
||||
TSENS_DAC_L4, /*!< offset = 2, measure range:-40℃ ~ 20℃, error < 3℃. */
|
||||
TSENS_DAC_MAX,
|
||||
TSENS_DAC_DEFAULT = TSENS_DAC_L2,
|
||||
} temp_sensor_dac_offset_t;
|
||||
|
||||
/**
|
||||
* @brief Configuration for temperature sensor reading
|
||||
*/
|
||||
typedef struct {
|
||||
temp_sensor_dac_offset_t dac_offset; /*!< The temperature measurement range is configured with a built-in temperature offset DAC. */
|
||||
uint8_t clk_div; /*!< Default: 6 */
|
||||
} temp_sensor_config_t;
|
||||
|
||||
#define TSENS_CONFIG_DEFAULT() {.dac_offset = TSENS_DAC_L2, \
|
||||
.clk_div = 6}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
383
components/driver/deprecated/driver/timer.h
Normal file
383
components/driver/deprecated/driver/timer.h
Normal file
@@ -0,0 +1,383 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2010-2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_err.h"
|
||||
#include "driver/timer_types_legacy.h"
|
||||
|
||||
#if !CONFIG_GPTIMER_SUPPRESS_DEPRECATE_WARN
|
||||
#warning "legacy timer group driver is deprecated, please migrate to driver/gptimer.h"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Read the counter value of hardware timer.
|
||||
*
|
||||
* @param group_num Timer group, 0 for TIMERG0 or 1 for TIMERG1
|
||||
* @param timer_num Timer index, 0 for hw_timer[0] & 1 for hw_timer[1]
|
||||
* @param timer_val Pointer to accept timer counter value.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
*/
|
||||
esp_err_t timer_get_counter_value(timer_group_t group_num, timer_idx_t timer_num, uint64_t *timer_val);
|
||||
|
||||
/**
|
||||
* @brief Read the counter value of hardware timer, in unit of a given scale.
|
||||
*
|
||||
* @param group_num Timer group, 0 for TIMERG0 or 1 for TIMERG1
|
||||
* @param timer_num Timer index, 0 for hw_timer[0] & 1 for hw_timer[1]
|
||||
* @param time Pointer, type of double*, to accept timer counter value, in seconds.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
*/
|
||||
esp_err_t timer_get_counter_time_sec(timer_group_t group_num, timer_idx_t timer_num, double *time);
|
||||
|
||||
/**
|
||||
* @brief Set counter value to hardware timer.
|
||||
*
|
||||
* @param group_num Timer group, 0 for TIMERG0 or 1 for TIMERG1
|
||||
* @param timer_num Timer index, 0 for hw_timer[0] & 1 for hw_timer[1]
|
||||
* @param load_val Counter value to write to the hardware timer.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
*/
|
||||
esp_err_t timer_set_counter_value(timer_group_t group_num, timer_idx_t timer_num, uint64_t load_val);
|
||||
|
||||
/**
|
||||
* @brief Start the counter of hardware timer.
|
||||
*
|
||||
* @param group_num Timer group number, 0 for TIMERG0 or 1 for TIMERG1
|
||||
* @param timer_num Timer index, 0 for hw_timer[0] & 1 for hw_timer[1]
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
*/
|
||||
esp_err_t timer_start(timer_group_t group_num, timer_idx_t timer_num);
|
||||
|
||||
/**
|
||||
* @brief Pause the counter of hardware timer.
|
||||
*
|
||||
* @param group_num Timer group number, 0 for TIMERG0 or 1 for TIMERG1
|
||||
* @param timer_num Timer index, 0 for hw_timer[0] & 1 for hw_timer[1]
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
*/
|
||||
esp_err_t timer_pause(timer_group_t group_num, timer_idx_t timer_num);
|
||||
|
||||
/**
|
||||
* @brief Set counting mode for hardware timer.
|
||||
*
|
||||
* @param group_num Timer group number, 0 for TIMERG0 or 1 for TIMERG1
|
||||
* @param timer_num Timer index, 0 for hw_timer[0] & 1 for hw_timer[1]
|
||||
* @param counter_dir Counting direction of timer, count-up or count-down
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
*/
|
||||
esp_err_t timer_set_counter_mode(timer_group_t group_num, timer_idx_t timer_num, timer_count_dir_t counter_dir);
|
||||
|
||||
/**
|
||||
* @brief Enable or disable counter reload function when alarm event occurs.
|
||||
*
|
||||
* @param group_num Timer group number, 0 for TIMERG0 or 1 for TIMERG1
|
||||
* @param timer_num Timer index, 0 for hw_timer[0] & 1 for hw_timer[1]
|
||||
* @param reload Counter reload mode.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
*/
|
||||
esp_err_t timer_set_auto_reload(timer_group_t group_num, timer_idx_t timer_num, timer_autoreload_t reload);
|
||||
|
||||
/**
|
||||
* @brief Set hardware divider of the source clock to the timer group.
|
||||
* By default, the source clock is APB clock running at 80 MHz.
|
||||
* For more information, please check Chapter Reset and Clock in Chip Technical Reference Manual.
|
||||
* @param group_num Timer group number, 0 for TIMERG0 or 1 for TIMERG1
|
||||
* @param timer_num Timer index, 0 for hw_timer[0] & 1 for hw_timer[1]
|
||||
* @param divider Timer clock divider value. The divider's range is from from 2 to 65536.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
*/
|
||||
esp_err_t timer_set_divider(timer_group_t group_num, timer_idx_t timer_num, uint32_t divider);
|
||||
|
||||
/**
|
||||
* @brief Set timer alarm value.
|
||||
*
|
||||
* @param group_num Timer group, 0 for TIMERG0 or 1 for TIMERG1
|
||||
* @param timer_num Timer index, 0 for hw_timer[0] & 1 for hw_timer[1]
|
||||
* @param alarm_value A 64-bit value to set the alarm value.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
*/
|
||||
esp_err_t timer_set_alarm_value(timer_group_t group_num, timer_idx_t timer_num, uint64_t alarm_value);
|
||||
|
||||
/**
|
||||
* @brief Get timer alarm value.
|
||||
*
|
||||
* @param group_num Timer group, 0 for TIMERG0 or 1 for TIMERG1
|
||||
* @param timer_num Timer index, 0 for hw_timer[0] & 1 for hw_timer[1]
|
||||
* @param alarm_value Pointer of A 64-bit value to accept the alarm value.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
*/
|
||||
esp_err_t timer_get_alarm_value(timer_group_t group_num, timer_idx_t timer_num, uint64_t *alarm_value);
|
||||
|
||||
/**
|
||||
* @brief Enable or disable generation of timer alarm events.
|
||||
*
|
||||
* @param group_num Timer group, 0 for TIMERG0 or 1 for TIMERG1
|
||||
* @param timer_num Timer index, 0 for hw_timer[0] & 1 for hw_timer[1]
|
||||
* @param alarm_en To enable or disable timer alarm function.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
*/
|
||||
esp_err_t timer_set_alarm(timer_group_t group_num, timer_idx_t timer_num, timer_alarm_t alarm_en);
|
||||
|
||||
/**
|
||||
* @brief Add ISR handle callback for the corresponding timer.
|
||||
*
|
||||
* @param group_num Timer group number
|
||||
* @param timer_num Timer index of timer group
|
||||
* @param isr_handler Interrupt handler function, it is a callback function.
|
||||
* @param arg Parameter for handler function
|
||||
* @param intr_alloc_flags Flags used to allocate the interrupt. One or multiple (ORred)
|
||||
* ESP_INTR_FLAG_* values. See esp_intr_alloc.h for more info.
|
||||
*
|
||||
* @note This ISR handler will be called from an ISR.
|
||||
* This ISR handler do not need to handle interrupt status, and should be kept short.
|
||||
* If you want to realize some specific applications or write the whole ISR, you can
|
||||
* call timer_isr_register(...) to register ISR.
|
||||
*
|
||||
* The callback should return a bool value to determine whether need to do YIELD at
|
||||
* the end of the ISR.
|
||||
*
|
||||
* If the intr_alloc_flags value ESP_INTR_FLAG_IRAM is set,
|
||||
* the handler function must be declared with IRAM_ATTR attribute
|
||||
* and can only call functions in IRAM or ROM. It cannot call other timer APIs.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
*/
|
||||
esp_err_t timer_isr_callback_add(timer_group_t group_num, timer_idx_t timer_num, timer_isr_t isr_handler, void *arg, int intr_alloc_flags);
|
||||
|
||||
/**
|
||||
* @brief Remove ISR handle callback for the corresponding timer.
|
||||
*
|
||||
* @param group_num Timer group number
|
||||
* @param timer_num Timer index of timer group
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
*/
|
||||
esp_err_t timer_isr_callback_remove(timer_group_t group_num, timer_idx_t timer_num);
|
||||
|
||||
/**
|
||||
* @brief Register Timer interrupt handler, the handler is an ISR.
|
||||
* The handler will be attached to the same CPU core that this function is running on.
|
||||
*
|
||||
* @param group_num Timer group number
|
||||
* @param timer_num Timer index of timer group
|
||||
* @param fn Interrupt handler function.
|
||||
* @param arg Parameter for handler function
|
||||
* @param intr_alloc_flags Flags used to allocate the interrupt. One or multiple (ORred)
|
||||
* ESP_INTR_FLAG_* values. See esp_intr_alloc.h for more info.
|
||||
* @param handle Pointer to return handle. If non-NULL, a handle for the interrupt will
|
||||
* be returned here.
|
||||
*
|
||||
* @note If use this function to register ISR, you need to write the whole ISR.
|
||||
* In the interrupt handler, you need to call timer_spinlock_take(..) before
|
||||
* your handling, and call timer_spinlock_give(...) after your handling.
|
||||
*
|
||||
* If the intr_alloc_flags value ESP_INTR_FLAG_IRAM is set,
|
||||
* the handler function must be declared with IRAM_ATTR attribute
|
||||
* and can only call functions in IRAM or ROM. It cannot call other timer APIs.
|
||||
* Use direct register access to configure timers from inside the ISR in this case.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
*/
|
||||
esp_err_t timer_isr_register(timer_group_t group_num, timer_idx_t timer_num, void (*fn)(void *), void *arg, int intr_alloc_flags, timer_isr_handle_t *handle);
|
||||
|
||||
/** @brief Initializes and configure the timer.
|
||||
*
|
||||
* @param group_num Timer group number, 0 for TIMERG0 or 1 for TIMERG1
|
||||
* @param timer_num Timer index, 0 for hw_timer[0] & 1 for hw_timer[1]
|
||||
* @param config Pointer to timer initialization parameters.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
*/
|
||||
esp_err_t timer_init(timer_group_t group_num, timer_idx_t timer_num, const timer_config_t *config);
|
||||
|
||||
/** @brief Deinitializes the timer.
|
||||
*
|
||||
* @param group_num Timer group number, 0 for TIMERG0 or 1 for TIMERG1
|
||||
* @param timer_num Timer index, 0 for hw_timer[0] & 1 for hw_timer[1]
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
*/
|
||||
esp_err_t timer_deinit(timer_group_t group_num, timer_idx_t timer_num);
|
||||
|
||||
/** @brief Get timer configure value.
|
||||
*
|
||||
* @param group_num Timer group number, 0 for TIMERG0 or 1 for TIMERG1
|
||||
* @param timer_num Timer index, 0 for hw_timer[0] & 1 for hw_timer[1]
|
||||
* @param config Pointer of struct to accept timer parameters.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
*/
|
||||
esp_err_t timer_get_config(timer_group_t group_num, timer_idx_t timer_num, timer_config_t *config);
|
||||
|
||||
/** @brief Enable timer group interrupt, by enable mask
|
||||
*
|
||||
* @param group_num Timer group number, 0 for TIMERG0 or 1 for TIMERG1
|
||||
* @param intr_mask Timer interrupt enable mask.
|
||||
* - TIMER_INTR_T0: t0 interrupt
|
||||
* - TIMER_INTR_T1: t1 interrupt
|
||||
* - TIMER_INTR_WDT: watchdog interrupt
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
*/
|
||||
esp_err_t timer_group_intr_enable(timer_group_t group_num, timer_intr_t intr_mask);
|
||||
|
||||
/** @brief Disable timer group interrupt, by disable mask
|
||||
*
|
||||
* @param group_num Timer group number, 0 for TIMERG0 or 1 for TIMERG1
|
||||
* @param intr_mask Timer interrupt disable mask.
|
||||
* - TIMER_INTR_T0: t0 interrupt
|
||||
* - TIMER_INTR_T1: t1 interrupt
|
||||
* - TIMER_INTR_WDT: watchdog interrupt
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
*/
|
||||
esp_err_t timer_group_intr_disable(timer_group_t group_num, timer_intr_t intr_mask);
|
||||
|
||||
/** @brief Enable timer interrupt
|
||||
*
|
||||
* @param group_num Timer group number, 0 for TIMERG0 or 1 for TIMERG1
|
||||
* @param timer_num Timer index.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
*/
|
||||
esp_err_t timer_enable_intr(timer_group_t group_num, timer_idx_t timer_num);
|
||||
|
||||
/** @brief Disable timer interrupt
|
||||
*
|
||||
* @param group_num Timer group number, 0 for TIMERG0 or 1 for TIMERG1
|
||||
* @param timer_num Timer index.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
*/
|
||||
esp_err_t timer_disable_intr(timer_group_t group_num, timer_idx_t timer_num);
|
||||
|
||||
/** @brief Clear timer interrupt status, just used in ISR
|
||||
*
|
||||
* @param group_num Timer group number, 0 for TIMERG0 or 1 for TIMERG1
|
||||
* @param timer_num Timer index.
|
||||
*
|
||||
*/
|
||||
void timer_group_clr_intr_status_in_isr(timer_group_t group_num, timer_idx_t timer_num);
|
||||
|
||||
/** @brief Enable alarm interrupt, just used in ISR
|
||||
*
|
||||
* @param group_num Timer group number, 0 for TIMERG0 or 1 for TIMERG1
|
||||
* @param timer_num Timer index.
|
||||
*
|
||||
*/
|
||||
void timer_group_enable_alarm_in_isr(timer_group_t group_num, timer_idx_t timer_num);
|
||||
|
||||
/** @brief Get the current counter value, just used in ISR
|
||||
*
|
||||
* @param group_num Timer group number, 0 for TIMERG0 or 1 for TIMERG1
|
||||
* @param timer_num Timer index.
|
||||
*
|
||||
* @return
|
||||
* - Counter value
|
||||
*/
|
||||
uint64_t timer_group_get_counter_value_in_isr(timer_group_t group_num, timer_idx_t timer_num);
|
||||
|
||||
/** @brief Set the alarm threshold for the timer, just used in ISR
|
||||
*
|
||||
* @param group_num Timer group number, 0 for TIMERG0 or 1 for TIMERG1
|
||||
* @param timer_num Timer index.
|
||||
* @param alarm_val Alarm threshold.
|
||||
*
|
||||
*/
|
||||
void timer_group_set_alarm_value_in_isr(timer_group_t group_num, timer_idx_t timer_num, uint64_t alarm_val);
|
||||
|
||||
/** @brief Enable/disable a counter, just used in ISR
|
||||
*
|
||||
* @param group_num Timer group number, 0 for TIMERG0 or 1 for TIMERG1
|
||||
* @param timer_num Timer index.
|
||||
* @param counter_en Enable/disable.
|
||||
*
|
||||
*/
|
||||
void timer_group_set_counter_enable_in_isr(timer_group_t group_num, timer_idx_t timer_num, timer_start_t counter_en);
|
||||
|
||||
/** @brief Get interrupt status, just used in ISR
|
||||
*
|
||||
* @param group_num Timer group number, 0 for TIMERG0 or 1 for TIMERG1
|
||||
*
|
||||
* @return
|
||||
* - Interrupt status
|
||||
*/
|
||||
uint32_t timer_group_get_intr_status_in_isr(timer_group_t group_num);
|
||||
/** @brief Get auto reload enable status, just used in ISR
|
||||
*
|
||||
* @param group_num Timer group number, 0 for TIMERG0 or 1 for TIMERG1
|
||||
* @param timer_num Timer index
|
||||
*
|
||||
* @return
|
||||
* - True Auto reload enabled
|
||||
* - False Auto reload disabled
|
||||
*/
|
||||
bool timer_group_get_auto_reload_in_isr(timer_group_t group_num, timer_idx_t timer_num);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
144
components/driver/deprecated/driver/timer_types_legacy.h
Normal file
144
components/driver/deprecated/driver/timer_types_legacy.h
Normal file
@@ -0,0 +1,144 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2010-2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "soc/soc_caps.h"
|
||||
#include "soc/clk_tree_defs.h"
|
||||
#include "hal/timer_types.h"
|
||||
#include "esp_intr_alloc.h"
|
||||
#include "esp_attr.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Timer-Group ID
|
||||
*/
|
||||
typedef enum {
|
||||
TIMER_GROUP_0 = 0, /*!< Hw timer group 0 */
|
||||
#if SOC_TIMER_GROUPS > 1
|
||||
TIMER_GROUP_1 = 1, /*!< Hw timer group 1 */
|
||||
#endif
|
||||
TIMER_GROUP_MAX /*!< Maximum number of Hw timer groups */
|
||||
} timer_group_t;
|
||||
|
||||
/**
|
||||
* @brief Timer ID
|
||||
*/
|
||||
typedef enum {
|
||||
TIMER_0 = 0, /*!< Select timer0 of GROUPx*/
|
||||
#if SOC_TIMER_GROUP_TIMERS_PER_GROUP > 1
|
||||
TIMER_1 = 1, /*!< Select timer1 of GROUPx*/
|
||||
#endif
|
||||
TIMER_MAX,
|
||||
} timer_idx_t;
|
||||
|
||||
/**
|
||||
* @brief Interrupt types of the timer.
|
||||
*/
|
||||
typedef enum {
|
||||
TIMER_INTR_T0 = 1 << 0, /*!< interrupt of timer 0 */
|
||||
#if SOC_TIMER_GROUP_TIMERS_PER_GROUP > 1
|
||||
TIMER_INTR_T1 = 1 << 1, /*!< interrupt of timer 1 */
|
||||
TIMER_INTR_WDT = 1 << 2, /*!< interrupt of watchdog */
|
||||
#else
|
||||
TIMER_INTR_WDT = 1 << 1, /*!< interrupt of watchdog */
|
||||
#endif
|
||||
TIMER_INTR_NONE = 0
|
||||
} timer_intr_t;
|
||||
|
||||
/**
|
||||
* @brief Timer count direction
|
||||
*/
|
||||
typedef enum {
|
||||
TIMER_COUNT_DOWN = GPTIMER_COUNT_DOWN, /*!< Descending Count from cnt.high|cnt.low*/
|
||||
TIMER_COUNT_UP = GPTIMER_COUNT_UP, /*!< Ascending Count from Zero*/
|
||||
TIMER_COUNT_MAX /*!< Maximum number of timer count directions */
|
||||
} timer_count_dir_t;
|
||||
|
||||
/**
|
||||
* @brief Timer start/stop command
|
||||
*/
|
||||
typedef enum {
|
||||
TIMER_PAUSE, /*!< Pause timer counter*/
|
||||
TIMER_START, /*!< Start timer counter*/
|
||||
} timer_start_t;
|
||||
|
||||
/**
|
||||
* @brief Timer alarm command
|
||||
*/
|
||||
typedef enum {
|
||||
TIMER_ALARM_DIS = 0, /*!< Disable timer alarm*/
|
||||
TIMER_ALARM_EN = 1, /*!< Enable timer alarm*/
|
||||
TIMER_ALARM_MAX
|
||||
} timer_alarm_t;
|
||||
|
||||
/**
|
||||
* @brief Timer interrupt type
|
||||
*/
|
||||
typedef enum {
|
||||
TIMER_INTR_LEVEL = 0, /*!< Interrupt mode: level mode*/
|
||||
TIMER_INTR_MAX
|
||||
} timer_intr_mode_t;
|
||||
|
||||
/**
|
||||
* @brief Timer autoreload command
|
||||
*/
|
||||
typedef enum {
|
||||
TIMER_AUTORELOAD_DIS = 0, /*!< Disable auto-reload: hardware will not load counter value after an alarm event*/
|
||||
TIMER_AUTORELOAD_EN = 1, /*!< Enable auto-reload: hardware will load counter value after an alarm event*/
|
||||
TIMER_AUTORELOAD_MAX,
|
||||
} timer_autoreload_t;
|
||||
|
||||
#if SOC_GPTIMER_SUPPORTED
|
||||
/**
|
||||
* @brief Timer group clock source
|
||||
*/
|
||||
typedef soc_periph_tg_clk_src_legacy_t timer_src_clk_t;
|
||||
#else
|
||||
/**
|
||||
* @brief Default type
|
||||
*/
|
||||
typedef int timer_src_clk_t;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Interrupt handler callback function
|
||||
*
|
||||
* @return
|
||||
* - True Do task yield at the end of ISR
|
||||
* - False Not do task yield at the end of ISR
|
||||
*
|
||||
* @note If you called FreeRTOS functions in callback, you need to return true or false based on
|
||||
* the return value of argument `pxHigherPriorityTaskWoken`.
|
||||
* For example, `xQueueSendFromISR` is called in callback, if the return value `pxHigherPriorityTaskWoken`
|
||||
* of any FreeRTOS calls is pdTRUE, return true; otherwise return false.
|
||||
*/
|
||||
typedef bool (*timer_isr_t)(void *);
|
||||
|
||||
/**
|
||||
* @brief Interrupt handle, used in order to free the isr after use.
|
||||
*/
|
||||
typedef intr_handle_t timer_isr_handle_t;
|
||||
|
||||
/**
|
||||
* @brief Timer configurations
|
||||
*/
|
||||
typedef struct {
|
||||
timer_alarm_t alarm_en; /*!< Timer alarm enable */
|
||||
timer_start_t counter_en; /*!< Counter enable */
|
||||
timer_intr_mode_t intr_type; /*!< Interrupt mode */
|
||||
timer_count_dir_t counter_dir; /*!< Counter direction */
|
||||
timer_autoreload_t auto_reload; /*!< Timer auto-reload */
|
||||
timer_src_clk_t clk_src; /*!< Selects source clock. */
|
||||
uint32_t divider; /*!< Counter clock divider */
|
||||
} timer_config_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
35
components/driver/deprecated/esp32/dac_legacy.c
Normal file
35
components/driver/deprecated/esp32/dac_legacy.c
Normal file
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2019-2021 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "hal/dac_ll.h"
|
||||
#include "esp_err.h"
|
||||
|
||||
extern portMUX_TYPE rtc_spinlock; //TODO: Will be placed in the appropriate position after the rtc module is finished.
|
||||
#define DAC_ENTER_CRITICAL() portENTER_CRITICAL(&rtc_spinlock)
|
||||
#define DAC_EXIT_CRITICAL() portEXIT_CRITICAL(&rtc_spinlock)
|
||||
|
||||
/*---------------------------------------------------------------
|
||||
Digital controller setting
|
||||
---------------------------------------------------------------*/
|
||||
|
||||
esp_err_t dac_i2s_enable(void)
|
||||
{
|
||||
DAC_ENTER_CRITICAL();
|
||||
dac_ll_digi_enable_dma(true);
|
||||
DAC_EXIT_CRITICAL();
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t dac_i2s_disable(void)
|
||||
{
|
||||
DAC_ENTER_CRITICAL();
|
||||
dac_ll_digi_enable_dma(false);
|
||||
DAC_EXIT_CRITICAL();
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
135
components/driver/deprecated/esp32s2/dac_legacy.c
Normal file
135
components/driver/deprecated/esp32s2/dac_legacy.c
Normal file
@@ -0,0 +1,135 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2019-2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include "sdkconfig.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "driver/dac_types_legacy.h"
|
||||
#include "hal/adc_ll.h"
|
||||
#include "hal/dac_ll.h"
|
||||
#include "esp_check.h"
|
||||
#include "esp_pm.h"
|
||||
|
||||
static __attribute__((unused)) const char *TAG = "DAC";
|
||||
|
||||
extern portMUX_TYPE rtc_spinlock; //TODO: Will be placed in the appropriate position after the rtc module is finished.
|
||||
#define DAC_ENTER_CRITICAL() portENTER_CRITICAL(&rtc_spinlock)
|
||||
#define DAC_EXIT_CRITICAL() portEXIT_CRITICAL(&rtc_spinlock)
|
||||
|
||||
#ifdef CONFIG_PM_ENABLE
|
||||
static esp_pm_lock_handle_t s_dac_digi_lock = NULL;
|
||||
#endif //CONFIG_PM_ENABLE
|
||||
|
||||
/*---------------------------------------------------------------
|
||||
Digital controller setting
|
||||
---------------------------------------------------------------*/
|
||||
|
||||
esp_err_t dac_digi_init(void)
|
||||
{
|
||||
DAC_ENTER_CRITICAL();
|
||||
dac_ll_digi_clk_inv(true);
|
||||
DAC_EXIT_CRITICAL();
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t dac_digi_deinit(void)
|
||||
{
|
||||
#ifdef CONFIG_PM_ENABLE
|
||||
if (s_dac_digi_lock) {
|
||||
esp_pm_lock_delete(s_dac_digi_lock);
|
||||
s_dac_digi_lock = NULL;
|
||||
}
|
||||
#endif
|
||||
DAC_ENTER_CRITICAL();
|
||||
dac_ll_digi_trigger_output(false);
|
||||
dac_ll_digi_enable_dma(false);
|
||||
dac_ll_digi_fifo_reset();
|
||||
dac_ll_digi_reset();
|
||||
DAC_EXIT_CRITICAL();
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t dac_digi_controller_config(const dac_digi_config_t *cfg)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(cfg->mode <= DAC_CONV_ALTER, ESP_ERR_INVALID_ARG, TAG, "DAC mode error");
|
||||
ESP_RETURN_ON_FALSE(cfg->interval > 0 && cfg->interval < 4096, ESP_ERR_INVALID_ARG, TAG, "DAC interval error");
|
||||
ESP_RETURN_ON_FALSE(cfg->dig_clk.div_num < 256, ESP_ERR_INVALID_ARG, TAG, "DAC clk div_num error");
|
||||
ESP_RETURN_ON_FALSE(cfg->dig_clk.div_b > 0 && cfg->dig_clk.div_b < 64, ESP_ERR_INVALID_ARG, TAG, "DAC clk div_b error");
|
||||
ESP_RETURN_ON_FALSE(cfg->dig_clk.div_a < 64, ESP_ERR_INVALID_ARG, TAG, "DAC clk div_a error");
|
||||
#ifdef CONFIG_PM_ENABLE
|
||||
esp_err_t err;
|
||||
if (s_dac_digi_lock == NULL) {
|
||||
if (cfg->dig_clk.use_apll) {
|
||||
err = esp_pm_lock_create(ESP_PM_NO_LIGHT_SLEEP, 0, "dac_dma", &s_dac_digi_lock);
|
||||
} else {
|
||||
err = esp_pm_lock_create(ESP_PM_APB_FREQ_MAX, 0, "dac_dma", &s_dac_digi_lock);
|
||||
}
|
||||
if (err != ESP_OK) {
|
||||
s_dac_digi_lock = NULL;
|
||||
ESP_LOGE(TAG, "DAC-DMA pm lock error");
|
||||
return err;
|
||||
}
|
||||
}
|
||||
#endif //CONFIG_PM_ENABLE
|
||||
|
||||
DAC_ENTER_CRITICAL();
|
||||
dac_ll_digi_set_convert_mode(cfg->mode == DAC_CONV_ALTER);
|
||||
dac_ll_digi_set_trigger_interval(cfg->interval);
|
||||
adc_ll_digi_controller_clk_div(cfg->dig_clk.div_num, cfg->dig_clk.div_b, cfg->dig_clk.div_a);
|
||||
adc_ll_digi_clk_sel(cfg->dig_clk.use_apll ? ADC_DIGI_CLK_SRC_APLL : ADC_DIGI_CLK_SRC_DEFAULT);
|
||||
DAC_EXIT_CRITICAL();
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t dac_digi_start(void)
|
||||
{
|
||||
#ifdef CONFIG_PM_ENABLE
|
||||
ESP_RETURN_ON_FALSE(s_dac_digi_lock, ESP_FAIL, TAG, "Should start after call `dac_digi_controller_config`");
|
||||
esp_pm_lock_acquire(s_dac_digi_lock);
|
||||
#endif
|
||||
DAC_ENTER_CRITICAL();
|
||||
dac_ll_digi_enable_dma(true);
|
||||
dac_ll_digi_trigger_output(true);
|
||||
DAC_EXIT_CRITICAL();
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t dac_digi_stop(void)
|
||||
{
|
||||
#ifdef CONFIG_PM_ENABLE
|
||||
if (s_dac_digi_lock) {
|
||||
esp_pm_lock_release(s_dac_digi_lock);
|
||||
}
|
||||
#endif
|
||||
DAC_ENTER_CRITICAL();
|
||||
dac_ll_digi_trigger_output(false);
|
||||
dac_ll_digi_enable_dma(false);
|
||||
DAC_EXIT_CRITICAL();
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t dac_digi_fifo_reset(void)
|
||||
{
|
||||
DAC_ENTER_CRITICAL();
|
||||
dac_ll_digi_fifo_reset();
|
||||
DAC_EXIT_CRITICAL();
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t dac_digi_reset(void)
|
||||
{
|
||||
DAC_ENTER_CRITICAL();
|
||||
dac_ll_digi_reset();
|
||||
DAC_EXIT_CRITICAL();
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
2003
components/driver/deprecated/i2s_legacy.c
Normal file
2003
components/driver/deprecated/i2s_legacy.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -470,7 +470,7 @@ esp_err_t mcpwm_init(mcpwm_unit_t mcpwm_num, mcpwm_timer_t timer_num, const mcpw
|
||||
uint32_t group_pre_scale = clk_src_hz / group_resolution;
|
||||
uint32_t timer_pre_scale = group_resolution / timer_resolution;
|
||||
|
||||
ESP_ERROR_CHECK(esp_clk_tree_enable_src((soc_module_clk_t)MCPWM_CAPTURE_CLK_SRC_DEFAULT, true));
|
||||
esp_clk_tree_enable_src((soc_module_clk_t)MCPWM_CAPTURE_CLK_SRC_DEFAULT, true);
|
||||
MCPWM_CLOCK_SRC_ATOMIC() {
|
||||
mcpwm_ll_group_set_clock_source(mcpwm_num, (soc_module_clk_t)MCPWM_CAPTURE_CLK_SRC_DEFAULT);
|
||||
mcpwm_ll_group_set_clock_prescale(mcpwm_num, group_pre_scale);
|
||||
@@ -868,7 +868,7 @@ esp_err_t mcpwm_capture_enable_channel(mcpwm_unit_t mcpwm_num, mcpwm_capture_cha
|
||||
uint32_t group_resolution = mcpwm_group_get_resolution(mcpwm_num);
|
||||
uint32_t group_pre_scale = clk_src_hz / group_resolution;
|
||||
|
||||
ESP_ERROR_CHECK(esp_clk_tree_enable_src((soc_module_clk_t)MCPWM_CAPTURE_CLK_SRC_DEFAULT, true));
|
||||
esp_clk_tree_enable_src((soc_module_clk_t)MCPWM_CAPTURE_CLK_SRC_DEFAULT, true);
|
||||
MCPWM_CLOCK_SRC_ATOMIC() {
|
||||
mcpwm_ll_group_set_clock_source(mcpwm_num, (soc_module_clk_t)MCPWM_CAPTURE_CLK_SRC_DEFAULT);
|
||||
mcpwm_ll_group_set_clock_prescale(mcpwm_num, group_pre_scale);
|
||||
@@ -910,7 +910,6 @@ esp_err_t mcpwm_capture_disable_channel(mcpwm_unit_t mcpwm_num, mcpwm_capture_ch
|
||||
mcpwm_ll_capture_enable_channel(hal->dev, cap_channel, false);
|
||||
mcpwm_ll_intr_enable(hal->dev, MCPWM_LL_EVENT_CAPTURE(cap_channel), false);
|
||||
mcpwm_critical_exit(mcpwm_num);
|
||||
ESP_ERROR_CHECK(esp_clk_tree_enable_src((soc_module_clk_t)MCPWM_CAPTURE_CLK_SRC_DEFAULT, false));
|
||||
|
||||
mcpwm_mutex_lock(mcpwm_num);
|
||||
context[mcpwm_num].cap_isr_func[cap_channel].fn = NULL;
|
||||
|
||||
574
components/driver/deprecated/pcnt_legacy.c
Normal file
574
components/driver/deprecated/pcnt_legacy.c
Normal file
@@ -0,0 +1,574 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_check.h"
|
||||
#include "soc/soc_caps.h"
|
||||
#include "esp_private/periph_ctrl.h"
|
||||
#include "driver/pcnt_types_legacy.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "hal/pcnt_hal.h"
|
||||
#include "hal/pcnt_ll.h"
|
||||
#include "hal/gpio_hal.h"
|
||||
#include "soc/pcnt_periph.h"
|
||||
#include "esp_rom_gpio.h"
|
||||
#include "esp_private/gpio.h"
|
||||
|
||||
#define PCNT_CHANNEL_ERR_STR "PCNT CHANNEL ERROR"
|
||||
#define PCNT_UNIT_ERR_STR "PCNT UNIT ERROR"
|
||||
#define PCNT_GPIO_ERR_STR "PCNT GPIO NUM ERROR"
|
||||
#define PCNT_ADDRESS_ERR_STR "PCNT ADDRESS ERROR"
|
||||
#define PCNT_PARAM_ERR_STR "PCNT PARAM ERROR"
|
||||
#define PCNT_COUNT_MODE_ERR_STR "PCNT COUNTER MODE ERROR"
|
||||
#define PCNT_CTRL_MODE_ERR_STR "PCNT CTRL MODE ERROR"
|
||||
#define PCNT_EVT_TYPE_ERR_STR "PCNT value type error"
|
||||
#define PCNT_LIMT_VAL_ERR_STR "PCNT limit value error"
|
||||
#define PCNT_NUM_ERR_STR "PCNT num error"
|
||||
#define PCNT_DRIVER_ERR_STR "PCNT driver error"
|
||||
|
||||
#define PCNT_ENTER_CRITICAL(mux) portENTER_CRITICAL(mux)
|
||||
#define PCNT_EXIT_CRITICAL(mux) portEXIT_CRITICAL(mux)
|
||||
|
||||
#if !SOC_RCC_IS_INDEPENDENT
|
||||
#define PCNT_RCC_ATOMIC() PERIPH_RCC_ATOMIC()
|
||||
#else
|
||||
#define PCNT_RCC_ATOMIC()
|
||||
#endif
|
||||
|
||||
static const char *TAG = "pcnt(legacy)";
|
||||
|
||||
#define PCNT_CHECK(a, str, ret_val) ESP_RETURN_ON_FALSE(a, ret_val, TAG, "%s", str)
|
||||
|
||||
typedef struct {
|
||||
pcnt_hal_context_t hal; /*!< PCNT hal context*/
|
||||
} pcnt_obj_t;
|
||||
|
||||
static pcnt_obj_t *p_pcnt_obj[PCNT_PORT_MAX] = {0};
|
||||
|
||||
#define PCNT_OBJ_CHECK(pcnt_port) { \
|
||||
PCNT_CHECK((pcnt_port < PCNT_PORT_MAX), PCNT_NUM_ERR_STR, ESP_ERR_INVALID_ARG); \
|
||||
PCNT_CHECK((p_pcnt_obj[pcnt_port]), PCNT_DRIVER_ERR_STR, ESP_ERR_INVALID_STATE); \
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
void(*fn)(void *args); /*!< isr function */
|
||||
void *args; /*!< isr function args */
|
||||
} pcnt_isr_func_t;
|
||||
|
||||
static pcnt_isr_func_t *pcnt_isr_func = NULL;
|
||||
static pcnt_isr_handle_t pcnt_isr_service = NULL;
|
||||
static portMUX_TYPE pcnt_spinlock = portMUX_INITIALIZER_UNLOCKED;
|
||||
|
||||
esp_err_t pcnt_isr_register(void (*fun)(void *), void *arg, int intr_alloc_flags, pcnt_isr_handle_t *handle);
|
||||
esp_err_t pcnt_isr_unregister(pcnt_isr_handle_t handle);
|
||||
|
||||
static inline esp_err_t _pcnt_set_mode(pcnt_port_t pcnt_port, pcnt_unit_t unit, pcnt_channel_t channel, pcnt_count_mode_t pos_mode, pcnt_count_mode_t neg_mode, pcnt_ctrl_mode_t hctrl_mode, pcnt_ctrl_mode_t lctrl_mode)
|
||||
{
|
||||
PCNT_OBJ_CHECK(pcnt_port);
|
||||
PCNT_CHECK(unit < SOC_PCNT_UNITS_PER_GROUP, PCNT_UNIT_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
PCNT_CHECK(channel < PCNT_CHANNEL_MAX, PCNT_CHANNEL_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
PCNT_CHECK((pos_mode < PCNT_COUNT_MAX) && (neg_mode < PCNT_COUNT_MAX), PCNT_COUNT_MODE_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
PCNT_CHECK((hctrl_mode < PCNT_MODE_MAX) && (lctrl_mode < PCNT_MODE_MAX), PCNT_CTRL_MODE_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
|
||||
pcnt_ll_set_edge_action(p_pcnt_obj[pcnt_port]->hal.dev, unit, channel, pos_mode, neg_mode);
|
||||
pcnt_ll_set_level_action(p_pcnt_obj[pcnt_port]->hal.dev, unit, channel, hctrl_mode, lctrl_mode);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static inline esp_err_t _pcnt_set_pin(pcnt_port_t pcnt_port, pcnt_unit_t unit, pcnt_channel_t channel, int pulse_io, int ctrl_io)
|
||||
{
|
||||
PCNT_OBJ_CHECK(pcnt_port);
|
||||
PCNT_CHECK(unit < SOC_PCNT_UNITS_PER_GROUP, PCNT_UNIT_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
PCNT_CHECK(channel < PCNT_CHANNEL_MAX, PCNT_CHANNEL_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
PCNT_CHECK(GPIO_IS_VALID_GPIO(pulse_io) || pulse_io < 0, PCNT_GPIO_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
PCNT_CHECK(GPIO_IS_VALID_GPIO(ctrl_io) || ctrl_io < 0, PCNT_GPIO_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
|
||||
if (pulse_io >= 0) {
|
||||
gpio_func_sel(pulse_io, PIN_FUNC_GPIO);
|
||||
gpio_set_direction(pulse_io, GPIO_MODE_INPUT);
|
||||
gpio_set_pull_mode(pulse_io, GPIO_PULLUP_ONLY);
|
||||
esp_rom_gpio_connect_in_signal(pulse_io, pcnt_periph_signals.groups[pcnt_port].units[unit].channels[channel].pulse_sig, 0);
|
||||
}
|
||||
|
||||
if (ctrl_io >= 0) {
|
||||
gpio_func_sel(ctrl_io, PIN_FUNC_GPIO);
|
||||
gpio_set_direction(ctrl_io, GPIO_MODE_INPUT);
|
||||
gpio_set_pull_mode(ctrl_io, GPIO_PULLUP_ONLY);
|
||||
esp_rom_gpio_connect_in_signal(ctrl_io, pcnt_periph_signals.groups[pcnt_port].units[unit].channels[channel].control_sig, 0);
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static inline esp_err_t _pcnt_get_counter_value(pcnt_port_t pcnt_port, pcnt_unit_t pcnt_unit, int16_t *count)
|
||||
{
|
||||
PCNT_OBJ_CHECK(pcnt_port);
|
||||
PCNT_CHECK(pcnt_unit < SOC_PCNT_UNITS_PER_GROUP, PCNT_UNIT_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
PCNT_CHECK(count != NULL, PCNT_ADDRESS_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
*count = pcnt_ll_get_count(p_pcnt_obj[pcnt_port]->hal.dev, pcnt_unit);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static inline esp_err_t _pcnt_counter_pause(pcnt_port_t pcnt_port, pcnt_unit_t pcnt_unit)
|
||||
{
|
||||
PCNT_OBJ_CHECK(pcnt_port);
|
||||
PCNT_CHECK(pcnt_unit < SOC_PCNT_UNITS_PER_GROUP, PCNT_UNIT_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
PCNT_ENTER_CRITICAL(&pcnt_spinlock);
|
||||
pcnt_ll_stop_count(p_pcnt_obj[pcnt_port]->hal.dev, pcnt_unit);
|
||||
PCNT_EXIT_CRITICAL(&pcnt_spinlock);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static inline esp_err_t _pcnt_counter_resume(pcnt_port_t pcnt_port, pcnt_unit_t pcnt_unit)
|
||||
{
|
||||
PCNT_OBJ_CHECK(pcnt_port);
|
||||
PCNT_CHECK(pcnt_unit < SOC_PCNT_UNITS_PER_GROUP, PCNT_UNIT_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
PCNT_ENTER_CRITICAL(&pcnt_spinlock);
|
||||
pcnt_ll_start_count(p_pcnt_obj[pcnt_port]->hal.dev, pcnt_unit);
|
||||
PCNT_EXIT_CRITICAL(&pcnt_spinlock);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static inline esp_err_t _pcnt_counter_clear(pcnt_port_t pcnt_port, pcnt_unit_t pcnt_unit)
|
||||
{
|
||||
PCNT_OBJ_CHECK(pcnt_port);
|
||||
PCNT_CHECK(pcnt_unit < SOC_PCNT_UNITS_PER_GROUP, PCNT_UNIT_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
PCNT_ENTER_CRITICAL(&pcnt_spinlock);
|
||||
pcnt_ll_clear_count(p_pcnt_obj[pcnt_port]->hal.dev, pcnt_unit);
|
||||
PCNT_EXIT_CRITICAL(&pcnt_spinlock);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static inline esp_err_t _pcnt_intr_enable(pcnt_port_t pcnt_port, pcnt_unit_t pcnt_unit, bool enable)
|
||||
{
|
||||
PCNT_OBJ_CHECK(pcnt_port);
|
||||
PCNT_CHECK(pcnt_unit < SOC_PCNT_UNITS_PER_GROUP, PCNT_UNIT_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
PCNT_ENTER_CRITICAL(&pcnt_spinlock);
|
||||
pcnt_ll_enable_intr(p_pcnt_obj[pcnt_port]->hal.dev, 1 << pcnt_unit, enable);
|
||||
PCNT_EXIT_CRITICAL(&pcnt_spinlock);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static inline esp_err_t _pcnt_event_enable(pcnt_port_t pcnt_port, pcnt_unit_t unit, pcnt_evt_type_t evt_type, bool enable)
|
||||
{
|
||||
PCNT_OBJ_CHECK(pcnt_port);
|
||||
PCNT_CHECK(unit < SOC_PCNT_UNITS_PER_GROUP, PCNT_UNIT_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
PCNT_CHECK(evt_type < PCNT_EVT_MAX, PCNT_EVT_TYPE_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
switch (evt_type) {
|
||||
case PCNT_EVT_THRES_1:
|
||||
pcnt_ll_enable_thres_event(p_pcnt_obj[pcnt_port]->hal.dev, unit, 1, enable);
|
||||
break;
|
||||
case PCNT_EVT_THRES_0:
|
||||
pcnt_ll_enable_thres_event(p_pcnt_obj[pcnt_port]->hal.dev, unit, 0, enable);
|
||||
break;
|
||||
case PCNT_EVT_L_LIM:
|
||||
pcnt_ll_enable_low_limit_event(p_pcnt_obj[pcnt_port]->hal.dev, unit, enable);
|
||||
break;
|
||||
case PCNT_EVT_H_LIM:
|
||||
pcnt_ll_enable_high_limit_event(p_pcnt_obj[pcnt_port]->hal.dev, unit, enable);
|
||||
break;
|
||||
case PCNT_EVT_ZERO:
|
||||
pcnt_ll_enable_zero_cross_event(p_pcnt_obj[pcnt_port]->hal.dev, unit, enable);
|
||||
break;
|
||||
default:
|
||||
PCNT_CHECK(false, PCNT_EVT_TYPE_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
break;
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static inline esp_err_t _pcnt_set_event_value(pcnt_port_t pcnt_port, pcnt_unit_t unit, pcnt_evt_type_t evt_type, int16_t value)
|
||||
{
|
||||
PCNT_OBJ_CHECK(pcnt_port);
|
||||
PCNT_CHECK(unit < SOC_PCNT_UNITS_PER_GROUP, PCNT_UNIT_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
PCNT_CHECK(evt_type < PCNT_EVT_MAX, PCNT_EVT_TYPE_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
PCNT_CHECK(!(evt_type == PCNT_EVT_L_LIM && value > 0), PCNT_LIMT_VAL_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
PCNT_CHECK(!(evt_type == PCNT_EVT_H_LIM && value < 0), PCNT_LIMT_VAL_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
switch (evt_type) {
|
||||
case PCNT_EVT_THRES_1:
|
||||
pcnt_ll_set_thres_value(p_pcnt_obj[pcnt_port]->hal.dev, unit, 1, value);
|
||||
break;
|
||||
case PCNT_EVT_THRES_0:
|
||||
pcnt_ll_set_thres_value(p_pcnt_obj[pcnt_port]->hal.dev, unit, 0, value);
|
||||
break;
|
||||
case PCNT_EVT_L_LIM:
|
||||
pcnt_ll_set_low_limit_value(p_pcnt_obj[pcnt_port]->hal.dev, unit, value);
|
||||
break;
|
||||
case PCNT_EVT_H_LIM:
|
||||
pcnt_ll_set_high_limit_value(p_pcnt_obj[pcnt_port]->hal.dev, unit, value);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static inline esp_err_t _pcnt_get_event_value(pcnt_port_t pcnt_port, pcnt_unit_t unit, pcnt_evt_type_t evt_type, int16_t *value)
|
||||
{
|
||||
PCNT_OBJ_CHECK(pcnt_port);
|
||||
PCNT_CHECK(unit < SOC_PCNT_UNITS_PER_GROUP, PCNT_UNIT_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
PCNT_CHECK(evt_type < PCNT_EVT_MAX, PCNT_EVT_TYPE_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
PCNT_CHECK(value != NULL, PCNT_ADDRESS_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
switch (evt_type) {
|
||||
case PCNT_EVT_THRES_1:
|
||||
*value = pcnt_ll_get_thres_value(p_pcnt_obj[pcnt_port]->hal.dev, unit, 1);
|
||||
break;
|
||||
case PCNT_EVT_THRES_0:
|
||||
*value = pcnt_ll_get_thres_value(p_pcnt_obj[pcnt_port]->hal.dev, unit, 0);
|
||||
break;
|
||||
case PCNT_EVT_L_LIM:
|
||||
*value = pcnt_ll_get_low_limit_value(p_pcnt_obj[pcnt_port]->hal.dev, unit);
|
||||
break;
|
||||
case PCNT_EVT_H_LIM:
|
||||
*value = pcnt_ll_get_high_limit_value(p_pcnt_obj[pcnt_port]->hal.dev, unit);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static inline esp_err_t _pcnt_get_event_status(pcnt_port_t pcnt_port, pcnt_unit_t unit, uint32_t *status)
|
||||
{
|
||||
PCNT_OBJ_CHECK(pcnt_port);
|
||||
PCNT_CHECK(unit < SOC_PCNT_UNITS_PER_GROUP, PCNT_UNIT_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
PCNT_CHECK(status != NULL, PCNT_ADDRESS_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
|
||||
*status = pcnt_ll_get_unit_status(p_pcnt_obj[pcnt_port]->hal.dev, unit);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static inline esp_err_t _pcnt_set_filter_value(pcnt_port_t pcnt_port, pcnt_unit_t unit, uint16_t filter_val)
|
||||
{
|
||||
PCNT_OBJ_CHECK(pcnt_port);
|
||||
PCNT_CHECK(unit < SOC_PCNT_UNITS_PER_GROUP, PCNT_UNIT_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
PCNT_CHECK(filter_val < 1024, PCNT_PARAM_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
pcnt_ll_set_glitch_filter_thres(p_pcnt_obj[pcnt_port]->hal.dev, unit, filter_val);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static inline esp_err_t _pcnt_get_filter_value(pcnt_port_t pcnt_port, pcnt_unit_t unit, uint16_t *filter_val)
|
||||
{
|
||||
PCNT_OBJ_CHECK(pcnt_port);
|
||||
PCNT_CHECK(unit < SOC_PCNT_UNITS_PER_GROUP, PCNT_UNIT_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
PCNT_CHECK(filter_val != NULL, PCNT_ADDRESS_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
|
||||
*filter_val = (uint16_t)pcnt_ll_get_glitch_filter_thres(p_pcnt_obj[pcnt_port]->hal.dev, unit);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static inline esp_err_t _pcnt_filter_enable(pcnt_port_t pcnt_port, pcnt_unit_t unit, bool enable)
|
||||
{
|
||||
PCNT_OBJ_CHECK(pcnt_port);
|
||||
PCNT_CHECK(unit < SOC_PCNT_UNITS_PER_GROUP, PCNT_UNIT_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
pcnt_ll_enable_glitch_filter(p_pcnt_obj[pcnt_port]->hal.dev, unit, enable);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static inline esp_err_t _pcnt_isr_handler_add(pcnt_port_t pcnt_port, pcnt_unit_t unit, void(*isr_handler)(void *), void *args)
|
||||
{
|
||||
PCNT_OBJ_CHECK(pcnt_port);
|
||||
PCNT_CHECK(pcnt_isr_func != NULL, "ISR service is not installed, call pcnt_install_isr_service() first", ESP_ERR_INVALID_STATE);
|
||||
PCNT_CHECK(unit < SOC_PCNT_UNITS_PER_GROUP, "PCNT unit error", ESP_ERR_INVALID_ARG);
|
||||
PCNT_ENTER_CRITICAL(&pcnt_spinlock);
|
||||
_pcnt_intr_enable(PCNT_PORT_0, unit, false);
|
||||
|
||||
if (pcnt_isr_func) {
|
||||
pcnt_isr_func[unit].fn = isr_handler;
|
||||
pcnt_isr_func[unit].args = args;
|
||||
}
|
||||
|
||||
_pcnt_intr_enable(PCNT_PORT_0, unit, true);
|
||||
PCNT_EXIT_CRITICAL(&pcnt_spinlock);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static inline esp_err_t _pcnt_isr_handler_remove(pcnt_port_t pcnt_port, pcnt_unit_t unit)
|
||||
{
|
||||
PCNT_OBJ_CHECK(pcnt_port);
|
||||
PCNT_CHECK(pcnt_isr_func != NULL, "ISR service is not installed", ESP_ERR_INVALID_STATE);
|
||||
PCNT_CHECK(unit < SOC_PCNT_UNITS_PER_GROUP, "PCNT unit error", ESP_ERR_INVALID_ARG);
|
||||
PCNT_ENTER_CRITICAL(&pcnt_spinlock);
|
||||
_pcnt_intr_enable(PCNT_PORT_0, unit, false);
|
||||
|
||||
if (pcnt_isr_func) {
|
||||
pcnt_isr_func[unit].fn = NULL;
|
||||
pcnt_isr_func[unit].args = NULL;
|
||||
}
|
||||
|
||||
PCNT_EXIT_CRITICAL(&pcnt_spinlock);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
// pcnt interrupt service
|
||||
static void IRAM_ATTR pcnt_intr_service(void *arg)
|
||||
{
|
||||
uint32_t status = 0;
|
||||
pcnt_port_t pcnt_port = (pcnt_port_t)arg;
|
||||
status = pcnt_ll_get_intr_status(p_pcnt_obj[pcnt_port]->hal.dev);
|
||||
pcnt_ll_clear_intr_status(p_pcnt_obj[pcnt_port]->hal.dev, status);
|
||||
|
||||
while (status) {
|
||||
int unit = __builtin_ffs(status) - 1;
|
||||
status &= ~(1 << unit);
|
||||
|
||||
if (pcnt_isr_func[unit].fn != NULL) {
|
||||
(pcnt_isr_func[unit].fn)(pcnt_isr_func[unit].args);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline esp_err_t _pcnt_isr_service_install(pcnt_port_t pcnt_port, int intr_alloc_flags)
|
||||
{
|
||||
PCNT_OBJ_CHECK(pcnt_port);
|
||||
PCNT_CHECK(pcnt_isr_func == NULL, "ISR service already installed", ESP_ERR_INVALID_STATE);
|
||||
esp_err_t ret = ESP_FAIL;
|
||||
pcnt_isr_func = (pcnt_isr_func_t *) calloc(SOC_PCNT_UNITS_PER_GROUP, sizeof(pcnt_isr_func_t));
|
||||
|
||||
if (pcnt_isr_func == NULL) {
|
||||
ret = ESP_ERR_NO_MEM;
|
||||
} else {
|
||||
ret = pcnt_isr_register(pcnt_intr_service, (void *)pcnt_port, intr_alloc_flags, &pcnt_isr_service);
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE(TAG, "pcnt isr registration failed, maybe you need `pcnt_isr_unregister` to unregister your isr");
|
||||
free(pcnt_isr_func);
|
||||
pcnt_isr_func = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline esp_err_t _pcnt_isr_service_uninstall(pcnt_port_t pcnt_port)
|
||||
{
|
||||
PCNT_OBJ_CHECK(pcnt_port);
|
||||
PCNT_CHECK(pcnt_isr_func != NULL, "ISR Service not installed yet.", ESP_ERR_INVALID_STATE);
|
||||
esp_err_t ret = ESP_FAIL;
|
||||
ret = pcnt_isr_unregister(pcnt_isr_service);
|
||||
free(pcnt_isr_func);
|
||||
pcnt_isr_func = NULL;
|
||||
pcnt_isr_service = NULL;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline esp_err_t _pcnt_unit_config(pcnt_port_t pcnt_port, const pcnt_config_t *pcnt_config)
|
||||
{
|
||||
PCNT_OBJ_CHECK(pcnt_port);
|
||||
uint8_t unit = pcnt_config->unit;
|
||||
uint8_t channel = pcnt_config->channel;
|
||||
int input_io = pcnt_config->pulse_gpio_num;
|
||||
int ctrl_io = pcnt_config->ctrl_gpio_num;
|
||||
|
||||
PCNT_CHECK(unit < SOC_PCNT_UNITS_PER_GROUP, PCNT_UNIT_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
PCNT_CHECK(channel < PCNT_CHANNEL_MAX, PCNT_CHANNEL_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
PCNT_CHECK(input_io < 0 || (GPIO_IS_VALID_GPIO(input_io) && (input_io != ctrl_io)), "PCNT pulse input io error", ESP_ERR_INVALID_ARG);
|
||||
PCNT_CHECK(ctrl_io < 0 || GPIO_IS_VALID_GPIO(ctrl_io), "PCNT ctrl io error", ESP_ERR_INVALID_ARG);
|
||||
PCNT_CHECK((pcnt_config->pos_mode < PCNT_COUNT_MAX) && (pcnt_config->neg_mode < PCNT_COUNT_MAX), PCNT_COUNT_MODE_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
PCNT_CHECK((pcnt_config->hctrl_mode < PCNT_MODE_MAX) && (pcnt_config->lctrl_mode < PCNT_MODE_MAX), PCNT_CTRL_MODE_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
/*Enable hardware module*/
|
||||
static bool pcnt_enable = false;
|
||||
if (pcnt_enable == false) {
|
||||
PCNT_RCC_ATOMIC() {
|
||||
pcnt_ll_reset_register(pcnt_port);
|
||||
pcnt_ll_enable_bus_clock(pcnt_port, true);
|
||||
}
|
||||
pcnt_enable = true;
|
||||
}
|
||||
/*Set counter range*/
|
||||
_pcnt_set_event_value(pcnt_port, unit, PCNT_EVT_H_LIM, pcnt_config->counter_h_lim);
|
||||
_pcnt_set_event_value(pcnt_port, unit, PCNT_EVT_L_LIM, pcnt_config->counter_l_lim);
|
||||
/*Default value after reboot is positive, we disable these events like others*/
|
||||
_pcnt_event_enable(pcnt_port, unit, PCNT_EVT_H_LIM, false);
|
||||
_pcnt_event_enable(pcnt_port, unit, PCNT_EVT_L_LIM, false);
|
||||
_pcnt_event_enable(pcnt_port, unit, PCNT_EVT_ZERO, false);
|
||||
_pcnt_filter_enable(pcnt_port, unit, false);
|
||||
/*set pulse input and control mode*/
|
||||
_pcnt_set_mode(pcnt_port, unit, channel, pcnt_config->pos_mode, pcnt_config->neg_mode, pcnt_config->hctrl_mode, pcnt_config->lctrl_mode);
|
||||
/*Set pulse input and control pins*/
|
||||
_pcnt_set_pin(pcnt_port, unit, channel, input_io, ctrl_io);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t pcnt_deinit(pcnt_port_t pcnt_port)
|
||||
{
|
||||
PCNT_OBJ_CHECK(pcnt_port);
|
||||
|
||||
heap_caps_free(p_pcnt_obj[pcnt_port]);
|
||||
p_pcnt_obj[pcnt_port] = NULL;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t pcnt_init(pcnt_port_t pcnt_port)
|
||||
{
|
||||
PCNT_CHECK((pcnt_port < PCNT_PORT_MAX), PCNT_NUM_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
PCNT_CHECK((p_pcnt_obj[pcnt_port]) == NULL, "pcnt driver already initted", ESP_ERR_INVALID_STATE);
|
||||
|
||||
p_pcnt_obj[pcnt_port] = (pcnt_obj_t *)heap_caps_calloc(1, sizeof(pcnt_obj_t), MALLOC_CAP_DEFAULT);
|
||||
|
||||
if (p_pcnt_obj[pcnt_port] == NULL) {
|
||||
ESP_LOGE(TAG, "PCNT driver malloc error");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
pcnt_hal_init(&(p_pcnt_obj[pcnt_port]->hal), pcnt_port);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t pcnt_unit_config(const pcnt_config_t *pcnt_config)
|
||||
{
|
||||
esp_err_t ret;
|
||||
|
||||
if ((p_pcnt_obj[PCNT_PORT_0]) == NULL) {
|
||||
ret = pcnt_init(PCNT_PORT_0);
|
||||
if (ret != ESP_OK) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
return _pcnt_unit_config(PCNT_PORT_0, pcnt_config);
|
||||
}
|
||||
|
||||
esp_err_t pcnt_set_mode(pcnt_unit_t unit, pcnt_channel_t channel, pcnt_count_mode_t pos_mode, pcnt_count_mode_t neg_mode, pcnt_ctrl_mode_t hctrl_mode, pcnt_ctrl_mode_t lctrl_mode)
|
||||
{
|
||||
return _pcnt_set_mode(PCNT_PORT_0, unit, channel, pos_mode, neg_mode, hctrl_mode, lctrl_mode);
|
||||
}
|
||||
|
||||
esp_err_t pcnt_set_pin(pcnt_unit_t unit, pcnt_channel_t channel, int pulse_io, int ctrl_io)
|
||||
{
|
||||
return _pcnt_set_pin(PCNT_PORT_0, unit, channel, pulse_io, ctrl_io);
|
||||
}
|
||||
|
||||
esp_err_t pcnt_get_counter_value(pcnt_unit_t pcnt_unit, int16_t *count)
|
||||
{
|
||||
return _pcnt_get_counter_value(PCNT_PORT_0, pcnt_unit, count);
|
||||
}
|
||||
|
||||
esp_err_t pcnt_counter_pause(pcnt_unit_t pcnt_unit)
|
||||
{
|
||||
return _pcnt_counter_pause(PCNT_PORT_0, pcnt_unit);
|
||||
}
|
||||
|
||||
esp_err_t pcnt_counter_resume(pcnt_unit_t pcnt_unit)
|
||||
{
|
||||
return _pcnt_counter_resume(PCNT_PORT_0, pcnt_unit);
|
||||
}
|
||||
|
||||
esp_err_t pcnt_counter_clear(pcnt_unit_t pcnt_unit)
|
||||
{
|
||||
return _pcnt_counter_clear(PCNT_PORT_0, pcnt_unit);
|
||||
}
|
||||
|
||||
esp_err_t pcnt_intr_enable(pcnt_unit_t pcnt_unit)
|
||||
{
|
||||
return _pcnt_intr_enable(PCNT_PORT_0, pcnt_unit, true);
|
||||
}
|
||||
|
||||
esp_err_t pcnt_intr_disable(pcnt_unit_t pcnt_unit)
|
||||
{
|
||||
return _pcnt_intr_enable(PCNT_PORT_0, pcnt_unit, false);
|
||||
}
|
||||
|
||||
esp_err_t pcnt_event_enable(pcnt_unit_t unit, pcnt_evt_type_t evt_type)
|
||||
{
|
||||
return _pcnt_event_enable(PCNT_PORT_0, unit, evt_type, true);
|
||||
}
|
||||
|
||||
esp_err_t pcnt_event_disable(pcnt_unit_t unit, pcnt_evt_type_t evt_type)
|
||||
{
|
||||
return _pcnt_event_enable(PCNT_PORT_0, unit, evt_type, false);
|
||||
}
|
||||
|
||||
esp_err_t pcnt_set_event_value(pcnt_unit_t unit, pcnt_evt_type_t evt_type, int16_t value)
|
||||
{
|
||||
return _pcnt_set_event_value(PCNT_PORT_0, unit, evt_type, value);
|
||||
}
|
||||
|
||||
esp_err_t pcnt_get_event_value(pcnt_unit_t unit, pcnt_evt_type_t evt_type, int16_t *value)
|
||||
{
|
||||
return _pcnt_get_event_value(PCNT_PORT_0, unit, evt_type, value);
|
||||
}
|
||||
|
||||
esp_err_t pcnt_get_event_status(pcnt_unit_t unit, uint32_t *status)
|
||||
{
|
||||
return _pcnt_get_event_status(PCNT_PORT_0, unit, status);
|
||||
}
|
||||
|
||||
esp_err_t pcnt_set_filter_value(pcnt_unit_t unit, uint16_t filter_val)
|
||||
{
|
||||
return _pcnt_set_filter_value(PCNT_PORT_0, unit, filter_val);
|
||||
}
|
||||
|
||||
esp_err_t pcnt_get_filter_value(pcnt_unit_t unit, uint16_t *filter_val)
|
||||
{
|
||||
return _pcnt_get_filter_value(PCNT_PORT_0, unit, filter_val);
|
||||
}
|
||||
|
||||
esp_err_t pcnt_filter_enable(pcnt_unit_t unit)
|
||||
{
|
||||
return _pcnt_filter_enable(PCNT_PORT_0, unit, true);
|
||||
}
|
||||
|
||||
esp_err_t pcnt_filter_disable(pcnt_unit_t unit)
|
||||
{
|
||||
return _pcnt_filter_enable(PCNT_PORT_0, unit, false);
|
||||
}
|
||||
|
||||
esp_err_t pcnt_isr_unregister(pcnt_isr_handle_t handle)
|
||||
{
|
||||
esp_err_t ret = ESP_FAIL;
|
||||
PCNT_ENTER_CRITICAL(&pcnt_spinlock);
|
||||
ret = esp_intr_free(handle);
|
||||
PCNT_EXIT_CRITICAL(&pcnt_spinlock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t pcnt_isr_register(void (*fun)(void *), void *arg, int intr_alloc_flags, pcnt_isr_handle_t *handle)
|
||||
{
|
||||
esp_err_t ret = ESP_FAIL;
|
||||
PCNT_CHECK(fun != NULL, PCNT_ADDRESS_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
PCNT_ENTER_CRITICAL(&pcnt_spinlock);
|
||||
ret = esp_intr_alloc(pcnt_periph_signals.groups[0].irq, intr_alloc_flags, fun, arg, handle);
|
||||
PCNT_EXIT_CRITICAL(&pcnt_spinlock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t pcnt_isr_handler_add(pcnt_unit_t unit, void(*isr_handler)(void *), void *args)
|
||||
{
|
||||
return _pcnt_isr_handler_add(PCNT_PORT_0, unit, isr_handler, args);
|
||||
}
|
||||
|
||||
esp_err_t pcnt_isr_handler_remove(pcnt_unit_t unit)
|
||||
{
|
||||
return _pcnt_isr_handler_remove(PCNT_PORT_0, unit);
|
||||
}
|
||||
|
||||
esp_err_t pcnt_isr_service_install(int intr_alloc_flags)
|
||||
{
|
||||
return _pcnt_isr_service_install(PCNT_PORT_0, intr_alloc_flags);
|
||||
}
|
||||
|
||||
void pcnt_isr_service_uninstall(void)
|
||||
{
|
||||
_pcnt_isr_service_uninstall(PCNT_PORT_0);
|
||||
}
|
||||
|
||||
#if !CONFIG_PCNT_SKIP_LEGACY_CONFLICT_CHECK
|
||||
/**
|
||||
* @brief This function will be called during start up, to check that pulse_cnt driver is not running along with the legacy pcnt driver
|
||||
*/
|
||||
__attribute__((constructor))
|
||||
static void check_pcnt_driver_conflict(void)
|
||||
{
|
||||
// This function was declared as weak here. pulse_cnt driver has one implementation.
|
||||
// So if pulse_cnt driver is not linked in, then `pcnt_new_unit` should be NULL at runtime.
|
||||
extern __attribute__((weak)) esp_err_t pcnt_new_unit(const void *config, void **ret_unit);
|
||||
if ((void *)pcnt_new_unit != NULL) {
|
||||
ESP_EARLY_LOGE(TAG, "CONFLICT! driver_ng is not allowed to be used with the legacy driver");
|
||||
abort();
|
||||
}
|
||||
ESP_EARLY_LOGW(TAG, "legacy driver is deprecated, please migrate to `driver/pulse_cnt.h`");
|
||||
}
|
||||
#endif //CONFIG_PCNT_SKIP_LEGACY_CONFLICT_CHECK
|
||||
@@ -440,7 +440,7 @@ esp_err_t rmt_set_source_clk(rmt_channel_t channel, rmt_source_clk_t base_clk)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(channel < RMT_CHANNEL_MAX, ESP_ERR_INVALID_ARG, TAG, RMT_CHANNEL_ERROR_STR);
|
||||
RMT_ENTER_CRITICAL();
|
||||
ESP_ERROR_CHECK(esp_clk_tree_enable_src((soc_module_clk_t)base_clk, true));
|
||||
esp_clk_tree_enable_src((soc_module_clk_t)base_clk, true);
|
||||
// `rmt_clock_source_t` and `rmt_source_clk_t` are binary compatible, as the underlying enum entries come from the same `soc_module_clk_t`
|
||||
RMT_CLOCK_SRC_ATOMIC() {
|
||||
rmt_ll_set_group_clock_src(rmt_contex.hal.regs, channel, (rmt_clock_source_t)base_clk, 1, 0, 0);
|
||||
@@ -606,7 +606,7 @@ static esp_err_t rmt_internal_config(rmt_dev_t *dev, const rmt_config_t *rmt_par
|
||||
#endif
|
||||
}
|
||||
esp_clk_tree_src_get_freq_hz((soc_module_clk_t)clk_src, ESP_CLK_TREE_SRC_FREQ_PRECISION_CACHED, &rmt_source_clk_hz);
|
||||
ESP_ERROR_CHECK(esp_clk_tree_enable_src((soc_module_clk_t)clk_src, true));
|
||||
esp_clk_tree_enable_src((soc_module_clk_t)clk_src, true);
|
||||
RMT_CLOCK_SRC_ATOMIC() {
|
||||
rmt_ll_set_group_clock_src(dev, channel, clk_src, 1, 0, 0);
|
||||
rmt_ll_enable_group_clock(dev, true);
|
||||
|
||||
179
components/driver/deprecated/rtc_temperature_legacy.c
Normal file
179
components/driver/deprecated/rtc_temperature_legacy.c
Normal file
@@ -0,0 +1,179 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2016-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include <math.h>
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_types.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_check.h"
|
||||
#include "esp_compiler.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "esp_private/regi2c_ctrl.h"
|
||||
#include "soc/regi2c_saradc.h"
|
||||
#include "esp_efuse_rtc_calib.h"
|
||||
#include "hal/temperature_sensor_ll.h"
|
||||
#include "driver/temp_sensor_types_legacy.h"
|
||||
#include "esp_private/periph_ctrl.h"
|
||||
#include "esp_private/sar_periph_ctrl.h"
|
||||
|
||||
static const char *TAG = "tsens";
|
||||
|
||||
#define TSENS_ADC_FACTOR (0.4386)
|
||||
#define TSENS_DAC_FACTOR (27.88)
|
||||
#define TSENS_SYS_OFFSET (20.52)
|
||||
|
||||
typedef struct {
|
||||
int index;
|
||||
int offset;
|
||||
int reg_val;
|
||||
int range_min;
|
||||
int range_max;
|
||||
int error_max;
|
||||
} tsens_dac_offset_t;
|
||||
|
||||
static const tsens_dac_offset_t dac_offset[TSENS_DAC_MAX] = {
|
||||
/* DAC Offset reg_val min max error */
|
||||
{TSENS_DAC_L0, -2, 5, 50, 125, 3},
|
||||
{TSENS_DAC_L1, -1, 7, 20, 100, 2},
|
||||
{TSENS_DAC_L2, 0, 15, -10, 80, 1},
|
||||
{TSENS_DAC_L3, 1, 11, -30, 50, 2},
|
||||
{TSENS_DAC_L4, 2, 10, -40, 20, 3},
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
TSENS_HW_STATE_UNCONFIGURED,
|
||||
TSENS_HW_STATE_CONFIGURED,
|
||||
TSENS_HW_STATE_STARTED,
|
||||
} tsens_hw_state_t;
|
||||
|
||||
static tsens_hw_state_t tsens_hw_state = TSENS_HW_STATE_UNCONFIGURED;
|
||||
|
||||
static float s_deltaT = NAN; // Unused number
|
||||
static int s_tsens_range;
|
||||
|
||||
esp_err_t temp_sensor_set_config(temp_sensor_config_t tsens)
|
||||
{
|
||||
esp_err_t err = ESP_OK;
|
||||
if (tsens_hw_state == TSENS_HW_STATE_STARTED) {
|
||||
ESP_LOGE(TAG, "Do not configure the temp sensor when it's running!");
|
||||
err = ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
temperature_sensor_ll_set_clk_div(tsens.clk_div);
|
||||
temp_sensor_sync_tsens_idx(tsens.dac_offset);
|
||||
s_tsens_range = dac_offset[tsens.dac_offset].reg_val;
|
||||
ESP_LOGI(TAG, "Config range [%d°C ~ %d°C], error < %d°C",
|
||||
dac_offset[tsens.dac_offset].range_min,
|
||||
dac_offset[tsens.dac_offset].range_max,
|
||||
dac_offset[tsens.dac_offset].error_max);
|
||||
tsens_hw_state = TSENS_HW_STATE_CONFIGURED;
|
||||
return err;
|
||||
}
|
||||
|
||||
esp_err_t temp_sensor_get_config(temp_sensor_config_t *tsens)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(tsens != NULL, ESP_ERR_INVALID_ARG, TAG, "no tsens specified");
|
||||
tsens->dac_offset = temperature_sensor_ll_get_offset();
|
||||
for (int i = TSENS_DAC_L0; i < TSENS_DAC_MAX; i++) {
|
||||
if ((int)tsens->dac_offset == dac_offset[i].reg_val) {
|
||||
tsens->dac_offset = dac_offset[i].index;
|
||||
break;
|
||||
}
|
||||
}
|
||||
tsens->clk_div = temperature_sensor_ll_get_clk_div();
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t temp_sensor_start(void)
|
||||
{
|
||||
esp_err_t err = ESP_OK;
|
||||
if (tsens_hw_state != TSENS_HW_STATE_CONFIGURED) {
|
||||
ESP_LOGE(TAG, "Is already running or not be configured");
|
||||
err = ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
temperature_sensor_power_acquire();
|
||||
temperature_sensor_ll_set_range(s_tsens_range);
|
||||
temperature_sensor_ll_clk_sel(TEMPERATURE_SENSOR_CLK_SRC_DEFAULT);
|
||||
tsens_hw_state = TSENS_HW_STATE_STARTED;
|
||||
return err;
|
||||
}
|
||||
|
||||
esp_err_t temp_sensor_stop(void)
|
||||
{
|
||||
temperature_sensor_power_release();
|
||||
tsens_hw_state = TSENS_HW_STATE_CONFIGURED;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t temp_sensor_read_raw(uint32_t *tsens_out)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(tsens_out != NULL, ESP_ERR_INVALID_ARG, TAG, "no tsens_out specified");
|
||||
if (tsens_hw_state != TSENS_HW_STATE_STARTED) {
|
||||
ESP_LOGE(TAG, "Has not been started");
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
ESP_COMPILER_DIAGNOSTIC_PUSH_IGNORE("-Wanalyzer-use-of-uninitialized-value") // False-positive detection. TODO GCC-366
|
||||
*tsens_out = temperature_sensor_ll_get_raw_value();
|
||||
ESP_COMPILER_DIAGNOSTIC_POP("-Wanalyzer-use-of-uninitialized-value")
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t read_delta_t_from_efuse(void)
|
||||
{
|
||||
ESP_RETURN_ON_ERROR(esp_efuse_rtc_calib_get_tsens_val(&s_deltaT), TAG, "Calibration error");
|
||||
ESP_LOGD(TAG, "s_deltaT = %f", s_deltaT);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static float parse_temp_sensor_raw_value(uint32_t tsens_raw)
|
||||
{
|
||||
if (isnan(s_deltaT)) { //suggests that the value is not initialized
|
||||
read_delta_t_from_efuse();
|
||||
}
|
||||
float result = tsens_raw - s_deltaT / 10.0;
|
||||
return result;
|
||||
}
|
||||
|
||||
esp_err_t temp_sensor_read_celsius(float *celsius)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(celsius != NULL, ESP_ERR_INVALID_ARG, TAG, "celsius points to nothing");
|
||||
if (tsens_hw_state != TSENS_HW_STATE_STARTED) {
|
||||
ESP_LOGE(TAG, "Has not been started");
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
temp_sensor_config_t tsens;
|
||||
temp_sensor_get_config(&tsens);
|
||||
bool range_changed;
|
||||
uint16_t tsens_out = temp_sensor_get_raw_value(&range_changed);
|
||||
*celsius = parse_temp_sensor_raw_value(tsens_out);
|
||||
if (*celsius < TEMPERATURE_SENSOR_LL_MEASURE_MIN || *celsius > TEMPERATURE_SENSOR_LL_MEASURE_MAX) {
|
||||
ESP_LOGE(TAG, "Exceeding temperature measure range.");
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
if (range_changed) {
|
||||
temp_sensor_get_config(&tsens);
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
#if !CONFIG_TEMP_SENSOR_SKIP_LEGACY_CONFLICT_CHECK
|
||||
/**
|
||||
* @brief This function will be called during start up, to check that this legacy temp sensor driver is not running along with the new driver
|
||||
*/
|
||||
__attribute__((constructor))
|
||||
static void check_legacy_temp_sensor_driver_conflict(void)
|
||||
{
|
||||
// This function was declared as weak here. temperature_sensor driver has one implementation.
|
||||
// So if temperature_sensor driver is not linked in, then `temperature_sensor_install()` should be NULL at runtime.
|
||||
extern __attribute__((weak)) esp_err_t temperature_sensor_install(const void *tsens_config, void **ret_tsens);
|
||||
if ((void *)temperature_sensor_install != NULL) {
|
||||
ESP_EARLY_LOGE(TAG, "CONFLICT! driver_ng is not allowed to be used with the legacy driver");
|
||||
abort();
|
||||
}
|
||||
ESP_EARLY_LOGW(TAG, "legacy driver is deprecated, please migrate to `driver/temperature_sensor.h`");
|
||||
}
|
||||
#endif //CONFIG_TEMP_SENSOR_SKIP_LEGACY_CONFLICT_CHECK
|
||||
487
components/driver/deprecated/timer_legacy.c
Normal file
487
components/driver/deprecated/timer_legacy.c
Normal file
@@ -0,0 +1,487 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include "esp_log.h"
|
||||
#include "esp_err.h"
|
||||
#include "esp_check.h"
|
||||
#include "esp_intr_alloc.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "driver/timer_types_legacy.h"
|
||||
#include "hal/timer_hal.h"
|
||||
#include "hal/timer_ll.h"
|
||||
#include "hal/check.h"
|
||||
#include "soc/timer_periph.h"
|
||||
#include "soc/soc_caps.h"
|
||||
#include "esp_clk_tree.h"
|
||||
#include "soc/timer_group_reg.h"
|
||||
#include "esp_private/esp_clk_tree_common.h"
|
||||
#include "esp_private/periph_ctrl.h"
|
||||
|
||||
static const char *TIMER_TAG = "timer_group";
|
||||
|
||||
#define TIMER_GROUP_NUM_ERROR "TIMER GROUP NUM ERROR"
|
||||
#define TIMER_NUM_ERROR "HW TIMER NUM ERROR"
|
||||
#define TIMER_PARAM_ADDR_ERROR "HW TIMER PARAM ADDR ERROR"
|
||||
#define TIMER_NEVER_INIT_ERROR "HW TIMER NEVER INIT ERROR"
|
||||
#define TIMER_COUNT_DIR_ERROR "HW TIMER COUNTER DIR ERROR"
|
||||
#define TIMER_AUTORELOAD_ERROR "HW TIMER AUTORELOAD ERROR"
|
||||
#define TIMER_SCALE_ERROR "HW TIMER SCALE ERROR"
|
||||
#define TIMER_ALARM_ERROR "HW TIMER ALARM ERROR"
|
||||
#define DIVIDER_RANGE_ERROR "HW TIMER divider outside of [2, 65536] range error"
|
||||
|
||||
#define TIMER_ENTER_CRITICAL(mux) portENTER_CRITICAL_SAFE(mux);
|
||||
#define TIMER_EXIT_CRITICAL(mux) portEXIT_CRITICAL_SAFE(mux);
|
||||
|
||||
#if SOC_PERIPH_CLK_CTRL_SHARED
|
||||
#define GPTIMER_CLOCK_SRC_ATOMIC() PERIPH_RCC_ATOMIC()
|
||||
#else
|
||||
#define GPTIMER_CLOCK_SRC_ATOMIC()
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
timer_isr_t fn; /*!< isr function */
|
||||
void *args; /*!< isr function args */
|
||||
timer_isr_handle_t timer_isr_handle; /*!< interrupt handle */
|
||||
timer_group_t isr_timer_group; /*!< timer group of interrupt triggered */
|
||||
} timer_isr_func_t;
|
||||
|
||||
typedef struct {
|
||||
timer_hal_context_t hal;
|
||||
timer_isr_func_t timer_isr_fun;
|
||||
timer_src_clk_t clk_src;
|
||||
gptimer_count_direction_t direction;
|
||||
uint32_t divider;
|
||||
uint64_t alarm_value;
|
||||
bool alarm_en;
|
||||
bool auto_reload_en;
|
||||
bool counter_en;
|
||||
} timer_obj_t;
|
||||
|
||||
static timer_obj_t *p_timer_obj[TIMER_GROUP_MAX][TIMER_MAX] = {0};
|
||||
static portMUX_TYPE timer_spinlock[TIMER_GROUP_MAX] = { [0 ... TIMER_GROUP_MAX - 1] = portMUX_INITIALIZER_UNLOCKED, };
|
||||
|
||||
esp_err_t timer_get_counter_value(timer_group_t group_num, timer_idx_t timer_num, uint64_t *timer_val)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(group_num < TIMER_GROUP_MAX, ESP_ERR_INVALID_ARG, TIMER_TAG, TIMER_GROUP_NUM_ERROR);
|
||||
ESP_RETURN_ON_FALSE(timer_num < TIMER_MAX, ESP_ERR_INVALID_ARG, TIMER_TAG, TIMER_NUM_ERROR);
|
||||
ESP_RETURN_ON_FALSE(timer_val != NULL, ESP_ERR_INVALID_ARG, TIMER_TAG, TIMER_PARAM_ADDR_ERROR);
|
||||
ESP_RETURN_ON_FALSE(p_timer_obj[group_num][timer_num] != NULL, ESP_ERR_INVALID_ARG, TIMER_TAG, TIMER_NEVER_INIT_ERROR);
|
||||
TIMER_ENTER_CRITICAL(&timer_spinlock[group_num]);
|
||||
*timer_val = timer_hal_capture_and_get_counter_value(&p_timer_obj[group_num][timer_num]->hal);
|
||||
TIMER_EXIT_CRITICAL(&timer_spinlock[group_num]);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t timer_get_counter_time_sec(timer_group_t group_num, timer_idx_t timer_num, double *time)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(group_num < TIMER_GROUP_MAX, ESP_ERR_INVALID_ARG, TIMER_TAG, TIMER_GROUP_NUM_ERROR);
|
||||
ESP_RETURN_ON_FALSE(timer_num < TIMER_MAX, ESP_ERR_INVALID_ARG, TIMER_TAG, TIMER_NUM_ERROR);
|
||||
ESP_RETURN_ON_FALSE(time != NULL, ESP_ERR_INVALID_ARG, TIMER_TAG, TIMER_PARAM_ADDR_ERROR);
|
||||
ESP_RETURN_ON_FALSE(p_timer_obj[group_num][timer_num] != NULL, ESP_ERR_INVALID_ARG, TIMER_TAG, TIMER_NEVER_INIT_ERROR);
|
||||
uint64_t timer_val = timer_hal_capture_and_get_counter_value(&p_timer_obj[group_num][timer_num]->hal);
|
||||
uint32_t div = p_timer_obj[group_num][timer_num]->divider;
|
||||
// get clock source frequency
|
||||
uint32_t counter_src_hz = 0;
|
||||
ESP_RETURN_ON_ERROR(esp_clk_tree_src_get_freq_hz((soc_module_clk_t)p_timer_obj[group_num][timer_num]->clk_src,
|
||||
ESP_CLK_TREE_SRC_FREQ_PRECISION_CACHED, &counter_src_hz),
|
||||
TIMER_TAG, "get clock source frequency failed");
|
||||
*time = (double)timer_val * div / counter_src_hz;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t timer_set_counter_value(timer_group_t group_num, timer_idx_t timer_num, uint64_t load_val)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(group_num < TIMER_GROUP_MAX, ESP_ERR_INVALID_ARG, TIMER_TAG, TIMER_GROUP_NUM_ERROR);
|
||||
ESP_RETURN_ON_FALSE(timer_num < TIMER_MAX, ESP_ERR_INVALID_ARG, TIMER_TAG, TIMER_NUM_ERROR);
|
||||
ESP_RETURN_ON_FALSE(p_timer_obj[group_num][timer_num] != NULL, ESP_ERR_INVALID_ARG, TIMER_TAG, TIMER_NEVER_INIT_ERROR);
|
||||
TIMER_ENTER_CRITICAL(&timer_spinlock[group_num]);
|
||||
timer_hal_set_counter_value(&(p_timer_obj[group_num][timer_num]->hal), load_val);
|
||||
TIMER_EXIT_CRITICAL(&timer_spinlock[group_num]);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t timer_start(timer_group_t group_num, timer_idx_t timer_num)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(group_num < TIMER_GROUP_MAX, ESP_ERR_INVALID_ARG, TIMER_TAG, TIMER_GROUP_NUM_ERROR);
|
||||
ESP_RETURN_ON_FALSE(timer_num < TIMER_MAX, ESP_ERR_INVALID_ARG, TIMER_TAG, TIMER_NUM_ERROR);
|
||||
ESP_RETURN_ON_FALSE(p_timer_obj[group_num][timer_num] != NULL, ESP_ERR_INVALID_ARG, TIMER_TAG, TIMER_NEVER_INIT_ERROR);
|
||||
TIMER_ENTER_CRITICAL(&timer_spinlock[group_num]);
|
||||
timer_ll_enable_counter(p_timer_obj[group_num][timer_num]->hal.dev, timer_num, true);
|
||||
p_timer_obj[group_num][timer_num]->counter_en = true;
|
||||
TIMER_EXIT_CRITICAL(&timer_spinlock[group_num]);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t timer_pause(timer_group_t group_num, timer_idx_t timer_num)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(group_num < TIMER_GROUP_MAX, ESP_ERR_INVALID_ARG, TIMER_TAG, TIMER_GROUP_NUM_ERROR);
|
||||
ESP_RETURN_ON_FALSE(timer_num < TIMER_MAX, ESP_ERR_INVALID_ARG, TIMER_TAG, TIMER_NUM_ERROR);
|
||||
ESP_RETURN_ON_FALSE(p_timer_obj[group_num][timer_num] != NULL, ESP_ERR_INVALID_ARG, TIMER_TAG, TIMER_NEVER_INIT_ERROR);
|
||||
TIMER_ENTER_CRITICAL(&timer_spinlock[group_num]);
|
||||
timer_ll_enable_counter(p_timer_obj[group_num][timer_num]->hal.dev, timer_num, false);
|
||||
p_timer_obj[group_num][timer_num]->counter_en = false;
|
||||
TIMER_EXIT_CRITICAL(&timer_spinlock[group_num]);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t timer_set_counter_mode(timer_group_t group_num, timer_idx_t timer_num, timer_count_dir_t counter_dir)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(group_num < TIMER_GROUP_MAX, ESP_ERR_INVALID_ARG, TIMER_TAG, TIMER_GROUP_NUM_ERROR);
|
||||
ESP_RETURN_ON_FALSE(timer_num < TIMER_MAX, ESP_ERR_INVALID_ARG, TIMER_TAG, TIMER_NUM_ERROR);
|
||||
ESP_RETURN_ON_FALSE(counter_dir < TIMER_COUNT_MAX, ESP_ERR_INVALID_ARG, TIMER_TAG, TIMER_COUNT_DIR_ERROR);
|
||||
ESP_RETURN_ON_FALSE(p_timer_obj[group_num][timer_num] != NULL, ESP_ERR_INVALID_ARG, TIMER_TAG, TIMER_NEVER_INIT_ERROR);
|
||||
TIMER_ENTER_CRITICAL(&timer_spinlock[group_num]);
|
||||
timer_ll_set_count_direction(p_timer_obj[group_num][timer_num]->hal.dev, timer_num, counter_dir);
|
||||
TIMER_EXIT_CRITICAL(&timer_spinlock[group_num]);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t timer_set_auto_reload(timer_group_t group_num, timer_idx_t timer_num, timer_autoreload_t reload)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(group_num < TIMER_GROUP_MAX, ESP_ERR_INVALID_ARG, TIMER_TAG, TIMER_GROUP_NUM_ERROR);
|
||||
ESP_RETURN_ON_FALSE(timer_num < TIMER_MAX, ESP_ERR_INVALID_ARG, TIMER_TAG, TIMER_NUM_ERROR);
|
||||
ESP_RETURN_ON_FALSE(reload < TIMER_AUTORELOAD_MAX, ESP_ERR_INVALID_ARG, TIMER_TAG, TIMER_AUTORELOAD_ERROR);
|
||||
ESP_RETURN_ON_FALSE(p_timer_obj[group_num][timer_num] != NULL, ESP_ERR_INVALID_ARG, TIMER_TAG, TIMER_NEVER_INIT_ERROR);
|
||||
TIMER_ENTER_CRITICAL(&timer_spinlock[group_num]);
|
||||
timer_ll_enable_auto_reload(p_timer_obj[group_num][timer_num]->hal.dev, timer_num, reload);
|
||||
p_timer_obj[group_num][timer_num]->auto_reload_en = reload;
|
||||
TIMER_EXIT_CRITICAL(&timer_spinlock[group_num]);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t timer_set_divider(timer_group_t group_num, timer_idx_t timer_num, uint32_t divider)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(group_num < TIMER_GROUP_MAX, ESP_ERR_INVALID_ARG, TIMER_TAG, TIMER_GROUP_NUM_ERROR);
|
||||
ESP_RETURN_ON_FALSE(timer_num < TIMER_MAX, ESP_ERR_INVALID_ARG, TIMER_TAG, TIMER_NUM_ERROR);
|
||||
ESP_RETURN_ON_FALSE(divider > 1 && divider < 65537, ESP_ERR_INVALID_ARG, TIMER_TAG, DIVIDER_RANGE_ERROR);
|
||||
ESP_RETURN_ON_FALSE(p_timer_obj[group_num][timer_num] != NULL, ESP_ERR_INVALID_ARG, TIMER_TAG, TIMER_NEVER_INIT_ERROR);
|
||||
TIMER_ENTER_CRITICAL(&timer_spinlock[group_num]);
|
||||
timer_ll_set_clock_prescale(p_timer_obj[group_num][timer_num]->hal.dev, timer_num, divider);
|
||||
p_timer_obj[group_num][timer_num]->divider = divider;
|
||||
TIMER_EXIT_CRITICAL(&timer_spinlock[group_num]);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t timer_set_alarm_value(timer_group_t group_num, timer_idx_t timer_num, uint64_t alarm_value)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(group_num < TIMER_GROUP_MAX, ESP_ERR_INVALID_ARG, TIMER_TAG, TIMER_GROUP_NUM_ERROR);
|
||||
ESP_RETURN_ON_FALSE(timer_num < TIMER_MAX, ESP_ERR_INVALID_ARG, TIMER_TAG, TIMER_NUM_ERROR);
|
||||
ESP_RETURN_ON_FALSE(p_timer_obj[group_num][timer_num] != NULL, ESP_ERR_INVALID_ARG, TIMER_TAG, TIMER_NEVER_INIT_ERROR);
|
||||
TIMER_ENTER_CRITICAL(&timer_spinlock[group_num]);
|
||||
timer_ll_set_alarm_value(p_timer_obj[group_num][timer_num]->hal.dev, timer_num, alarm_value);
|
||||
p_timer_obj[group_num][timer_num]->alarm_value = alarm_value;
|
||||
TIMER_EXIT_CRITICAL(&timer_spinlock[group_num]);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t timer_get_alarm_value(timer_group_t group_num, timer_idx_t timer_num, uint64_t *alarm_value)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(group_num < TIMER_GROUP_MAX, ESP_ERR_INVALID_ARG, TIMER_TAG, TIMER_GROUP_NUM_ERROR);
|
||||
ESP_RETURN_ON_FALSE(timer_num < TIMER_MAX, ESP_ERR_INVALID_ARG, TIMER_TAG, TIMER_NUM_ERROR);
|
||||
ESP_RETURN_ON_FALSE(alarm_value != NULL, ESP_ERR_INVALID_ARG, TIMER_TAG, TIMER_PARAM_ADDR_ERROR);
|
||||
ESP_RETURN_ON_FALSE(p_timer_obj[group_num][timer_num] != NULL, ESP_ERR_INVALID_ARG, TIMER_TAG, TIMER_NEVER_INIT_ERROR);
|
||||
TIMER_ENTER_CRITICAL(&timer_spinlock[group_num]);
|
||||
*alarm_value = p_timer_obj[group_num][timer_num]->alarm_value;
|
||||
TIMER_EXIT_CRITICAL(&timer_spinlock[group_num]);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t timer_set_alarm(timer_group_t group_num, timer_idx_t timer_num, timer_alarm_t alarm_en)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(group_num < TIMER_GROUP_MAX, ESP_ERR_INVALID_ARG, TIMER_TAG, TIMER_GROUP_NUM_ERROR);
|
||||
ESP_RETURN_ON_FALSE(timer_num < TIMER_MAX, ESP_ERR_INVALID_ARG, TIMER_TAG, TIMER_NUM_ERROR);
|
||||
ESP_RETURN_ON_FALSE(alarm_en < TIMER_ALARM_MAX, ESP_ERR_INVALID_ARG, TIMER_TAG, TIMER_ALARM_ERROR);
|
||||
ESP_RETURN_ON_FALSE(p_timer_obj[group_num][timer_num] != NULL, ESP_ERR_INVALID_ARG, TIMER_TAG, TIMER_NEVER_INIT_ERROR);
|
||||
TIMER_ENTER_CRITICAL(&timer_spinlock[group_num]);
|
||||
timer_ll_enable_alarm(p_timer_obj[group_num][timer_num]->hal.dev, timer_num, alarm_en);
|
||||
TIMER_EXIT_CRITICAL(&timer_spinlock[group_num]);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static void IRAM_ATTR timer_isr_default(void *arg)
|
||||
{
|
||||
bool is_awoken = false;
|
||||
timer_obj_t *timer_obj = (timer_obj_t *)arg;
|
||||
if (timer_obj == NULL || timer_obj->timer_isr_fun.fn == NULL) {
|
||||
return;
|
||||
}
|
||||
uint32_t timer_id = timer_obj->hal.timer_id;
|
||||
timer_hal_context_t *hal = &timer_obj->hal;
|
||||
TIMER_ENTER_CRITICAL(&timer_spinlock[timer_obj->timer_isr_fun.isr_timer_group]);
|
||||
uint32_t intr_status = timer_ll_get_intr_status(hal->dev);
|
||||
uint64_t old_alarm_value = timer_obj->alarm_value;
|
||||
if (intr_status & TIMER_LL_EVENT_ALARM(timer_id)) {
|
||||
// Clear interrupt status
|
||||
timer_ll_clear_intr_status(hal->dev, TIMER_LL_EVENT_ALARM(timer_id));
|
||||
// call user registered callback
|
||||
is_awoken = timer_obj->timer_isr_fun.fn(timer_obj->timer_isr_fun.args);
|
||||
// re-enable alarm if required
|
||||
uint64_t new_alarm_value = timer_obj->alarm_value;
|
||||
bool reenable_alarm = (new_alarm_value != old_alarm_value) || timer_obj->auto_reload_en;
|
||||
timer_ll_enable_alarm(hal->dev, timer_id, reenable_alarm);
|
||||
}
|
||||
TIMER_EXIT_CRITICAL(&timer_spinlock[timer_obj->timer_isr_fun.isr_timer_group]);
|
||||
|
||||
if (is_awoken) {
|
||||
portYIELD_FROM_ISR();
|
||||
}
|
||||
}
|
||||
|
||||
esp_err_t timer_enable_intr(timer_group_t group_num, timer_idx_t timer_num)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(group_num < TIMER_GROUP_MAX, ESP_ERR_INVALID_ARG, TIMER_TAG, TIMER_GROUP_NUM_ERROR);
|
||||
ESP_RETURN_ON_FALSE(timer_num < TIMER_MAX, ESP_ERR_INVALID_ARG, TIMER_TAG, TIMER_NUM_ERROR);
|
||||
ESP_RETURN_ON_FALSE(p_timer_obj[group_num][timer_num] != NULL, ESP_ERR_INVALID_ARG, TIMER_TAG, TIMER_NEVER_INIT_ERROR);
|
||||
TIMER_ENTER_CRITICAL(&timer_spinlock[group_num]);
|
||||
timer_ll_enable_intr(p_timer_obj[group_num][timer_num]->hal.dev, TIMER_LL_EVENT_ALARM(timer_num), true);
|
||||
TIMER_EXIT_CRITICAL(&timer_spinlock[group_num]);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t timer_disable_intr(timer_group_t group_num, timer_idx_t timer_num)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(group_num < TIMER_GROUP_MAX, ESP_ERR_INVALID_ARG, TIMER_TAG, TIMER_GROUP_NUM_ERROR);
|
||||
ESP_RETURN_ON_FALSE(timer_num < TIMER_MAX, ESP_ERR_INVALID_ARG, TIMER_TAG, TIMER_NUM_ERROR);
|
||||
ESP_RETURN_ON_FALSE(p_timer_obj[group_num][timer_num] != NULL, ESP_ERR_INVALID_ARG, TIMER_TAG, TIMER_NEVER_INIT_ERROR);
|
||||
TIMER_ENTER_CRITICAL(&timer_spinlock[group_num]);
|
||||
timer_ll_enable_intr(p_timer_obj[group_num][timer_num]->hal.dev, TIMER_LL_EVENT_ALARM(timer_num), false);
|
||||
TIMER_EXIT_CRITICAL(&timer_spinlock[group_num]);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t timer_isr_register(timer_group_t group_num, timer_idx_t timer_num,
|
||||
void (*fn)(void *), void *arg, int intr_alloc_flags, timer_isr_handle_t *handle)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(group_num < TIMER_GROUP_MAX, ESP_ERR_INVALID_ARG, TIMER_TAG, TIMER_GROUP_NUM_ERROR);
|
||||
ESP_RETURN_ON_FALSE(timer_num < TIMER_MAX, ESP_ERR_INVALID_ARG, TIMER_TAG, TIMER_NUM_ERROR);
|
||||
ESP_RETURN_ON_FALSE(fn != NULL, ESP_ERR_INVALID_ARG, TIMER_TAG, TIMER_PARAM_ADDR_ERROR);
|
||||
ESP_RETURN_ON_FALSE(p_timer_obj[group_num][timer_num] != NULL, ESP_ERR_INVALID_ARG, TIMER_TAG, TIMER_NEVER_INIT_ERROR);
|
||||
timer_hal_context_t *hal = &p_timer_obj[group_num][timer_num]->hal;
|
||||
return esp_intr_alloc_intrstatus(timer_group_periph_signals.groups[group_num].timer_irq_id[timer_num],
|
||||
intr_alloc_flags,
|
||||
(uint32_t)timer_ll_get_intr_status_reg(hal->dev),
|
||||
TIMER_LL_EVENT_ALARM(timer_num), fn, arg, handle);
|
||||
}
|
||||
|
||||
esp_err_t timer_isr_callback_add(timer_group_t group_num, timer_idx_t timer_num, timer_isr_t isr_handler, void *args, int intr_alloc_flags)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(group_num < TIMER_GROUP_MAX, ESP_ERR_INVALID_ARG, TIMER_TAG, TIMER_GROUP_NUM_ERROR);
|
||||
ESP_RETURN_ON_FALSE(timer_num < TIMER_MAX, ESP_ERR_INVALID_ARG, TIMER_TAG, TIMER_NUM_ERROR);
|
||||
ESP_RETURN_ON_FALSE(p_timer_obj[group_num][timer_num] != NULL, ESP_ERR_INVALID_ARG, TIMER_TAG, TIMER_NEVER_INIT_ERROR);
|
||||
esp_err_t ret = ESP_OK;
|
||||
|
||||
timer_disable_intr(group_num, timer_num);
|
||||
p_timer_obj[group_num][timer_num]->timer_isr_fun.fn = isr_handler;
|
||||
p_timer_obj[group_num][timer_num]->timer_isr_fun.args = args;
|
||||
p_timer_obj[group_num][timer_num]->timer_isr_fun.isr_timer_group = group_num;
|
||||
ret = timer_isr_register(group_num, timer_num, timer_isr_default, (void *)p_timer_obj[group_num][timer_num],
|
||||
intr_alloc_flags, &(p_timer_obj[group_num][timer_num]->timer_isr_fun.timer_isr_handle));
|
||||
ESP_RETURN_ON_ERROR(ret, TIMER_TAG, "register interrupt service failed");
|
||||
timer_enable_intr(group_num, timer_num);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t timer_isr_callback_remove(timer_group_t group_num, timer_idx_t timer_num)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(group_num < TIMER_GROUP_MAX, ESP_ERR_INVALID_ARG, TIMER_TAG, TIMER_GROUP_NUM_ERROR);
|
||||
ESP_RETURN_ON_FALSE(timer_num < TIMER_MAX, ESP_ERR_INVALID_ARG, TIMER_TAG, TIMER_NUM_ERROR);
|
||||
ESP_RETURN_ON_FALSE(p_timer_obj[group_num][timer_num] != NULL, ESP_ERR_INVALID_ARG, TIMER_TAG, TIMER_NEVER_INIT_ERROR);
|
||||
|
||||
timer_disable_intr(group_num, timer_num);
|
||||
p_timer_obj[group_num][timer_num]->timer_isr_fun.fn = NULL;
|
||||
p_timer_obj[group_num][timer_num]->timer_isr_fun.args = NULL;
|
||||
esp_intr_free(p_timer_obj[group_num][timer_num]->timer_isr_fun.timer_isr_handle);
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t timer_init(timer_group_t group_num, timer_idx_t timer_num, const timer_config_t *config)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(group_num < TIMER_GROUP_MAX, ESP_ERR_INVALID_ARG, TIMER_TAG, TIMER_GROUP_NUM_ERROR);
|
||||
ESP_RETURN_ON_FALSE(timer_num < TIMER_MAX, ESP_ERR_INVALID_ARG, TIMER_TAG, TIMER_NUM_ERROR);
|
||||
ESP_RETURN_ON_FALSE(config != NULL, ESP_ERR_INVALID_ARG, TIMER_TAG, TIMER_PARAM_ADDR_ERROR);
|
||||
ESP_RETURN_ON_FALSE(config->divider > 1 && config->divider < 65537, ESP_ERR_INVALID_ARG, TIMER_TAG, DIVIDER_RANGE_ERROR);
|
||||
ESP_RETURN_ON_FALSE(config->intr_type < TIMER_INTR_MAX, ESP_ERR_INVALID_ARG, TIMER_TAG, "only support Level Interrupt");
|
||||
if (p_timer_obj[group_num][timer_num] == NULL) {
|
||||
p_timer_obj[group_num][timer_num] = (timer_obj_t *) heap_caps_calloc(1, sizeof(timer_obj_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
|
||||
ESP_RETURN_ON_FALSE(p_timer_obj[group_num][timer_num], ESP_ERR_NO_MEM, TIMER_TAG, "no mem for timer object");
|
||||
}
|
||||
timer_hal_context_t *hal = &p_timer_obj[group_num][timer_num]->hal;
|
||||
|
||||
PERIPH_RCC_ACQUIRE_ATOMIC(timer_group_periph_signals.groups[group_num].module, ref_count) {
|
||||
if (ref_count == 0) {
|
||||
timer_ll_enable_bus_clock(group_num, true);
|
||||
timer_ll_reset_register(group_num);
|
||||
}
|
||||
}
|
||||
|
||||
TIMER_ENTER_CRITICAL(&timer_spinlock[group_num]);
|
||||
timer_hal_init(hal, group_num, timer_num);
|
||||
timer_hal_set_counter_value(hal, 0);
|
||||
|
||||
timer_src_clk_t clk_src = TIMER_SRC_CLK_DEFAULT;
|
||||
if (config->clk_src) {
|
||||
clk_src = config->clk_src;
|
||||
}
|
||||
esp_clk_tree_enable_src((soc_module_clk_t)clk_src, true);
|
||||
GPTIMER_CLOCK_SRC_ATOMIC() {
|
||||
// although `clk_src` is of `timer_src_clk_t` type, but it's binary compatible with `gptimer_clock_source_t`,
|
||||
// as the underlying enum entries come from the same `soc_module_clk_t`
|
||||
timer_ll_set_clock_source(group_num, timer_num, (gptimer_clock_source_t)clk_src);
|
||||
timer_ll_enable_clock(group_num, timer_num, true);
|
||||
}
|
||||
timer_ll_set_clock_prescale(hal->dev, timer_num, config->divider);
|
||||
timer_ll_set_count_direction(p_timer_obj[group_num][timer_num]->hal.dev, timer_num, config->counter_dir);
|
||||
timer_ll_enable_intr(hal->dev, TIMER_LL_EVENT_ALARM(timer_num), false);
|
||||
timer_ll_clear_intr_status(hal->dev, TIMER_LL_EVENT_ALARM(timer_num));
|
||||
timer_ll_enable_alarm(hal->dev, timer_num, config->alarm_en);
|
||||
timer_ll_enable_auto_reload(hal->dev, timer_num, config->auto_reload);
|
||||
timer_ll_enable_counter(hal->dev, timer_num, config->counter_en);
|
||||
p_timer_obj[group_num][timer_num]->clk_src = clk_src;
|
||||
p_timer_obj[group_num][timer_num]->alarm_en = config->alarm_en;
|
||||
p_timer_obj[group_num][timer_num]->auto_reload_en = config->auto_reload;
|
||||
p_timer_obj[group_num][timer_num]->direction = config->counter_dir;
|
||||
p_timer_obj[group_num][timer_num]->counter_en = config->counter_en;
|
||||
p_timer_obj[group_num][timer_num]->divider = config->divider;
|
||||
TIMER_EXIT_CRITICAL(&timer_spinlock[group_num]);
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t timer_deinit(timer_group_t group_num, timer_idx_t timer_num)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(group_num < TIMER_GROUP_MAX, ESP_ERR_INVALID_ARG, TIMER_TAG, TIMER_GROUP_NUM_ERROR);
|
||||
ESP_RETURN_ON_FALSE(timer_num < TIMER_MAX, ESP_ERR_INVALID_ARG, TIMER_TAG, TIMER_NUM_ERROR);
|
||||
ESP_RETURN_ON_FALSE(p_timer_obj[group_num][timer_num] != NULL, ESP_ERR_INVALID_ARG, TIMER_TAG, TIMER_NEVER_INIT_ERROR);
|
||||
timer_hal_context_t *hal = &p_timer_obj[group_num][timer_num]->hal;
|
||||
|
||||
// disable the source clock
|
||||
GPTIMER_CLOCK_SRC_ATOMIC() {
|
||||
timer_ll_enable_clock(group_num, hal->timer_id, false);
|
||||
}
|
||||
TIMER_ENTER_CRITICAL(&timer_spinlock[group_num]);
|
||||
timer_ll_enable_intr(hal->dev, TIMER_LL_EVENT_ALARM(timer_num), false);
|
||||
timer_ll_clear_intr_status(hal->dev, TIMER_LL_EVENT_ALARM(timer_num));
|
||||
timer_hal_deinit(hal);
|
||||
TIMER_EXIT_CRITICAL(&timer_spinlock[group_num]);
|
||||
|
||||
PERIPH_RCC_RELEASE_ATOMIC(timer_group_periph_signals.groups[group_num].module, ref_count) {
|
||||
if (ref_count == 0) {
|
||||
timer_ll_enable_bus_clock(group_num, false);
|
||||
}
|
||||
}
|
||||
|
||||
free(p_timer_obj[group_num][timer_num]);
|
||||
p_timer_obj[group_num][timer_num] = NULL;
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t timer_get_config(timer_group_t group_num, timer_idx_t timer_num, timer_config_t *config)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(group_num < TIMER_GROUP_MAX, ESP_ERR_INVALID_ARG, TIMER_TAG, TIMER_GROUP_NUM_ERROR);
|
||||
ESP_RETURN_ON_FALSE(timer_num < TIMER_MAX, ESP_ERR_INVALID_ARG, TIMER_TAG, TIMER_NUM_ERROR);
|
||||
ESP_RETURN_ON_FALSE(config != NULL, ESP_ERR_INVALID_ARG, TIMER_TAG, TIMER_PARAM_ADDR_ERROR);
|
||||
ESP_RETURN_ON_FALSE(p_timer_obj[group_num][timer_num] != NULL, ESP_ERR_INVALID_ARG, TIMER_TAG, TIMER_NEVER_INIT_ERROR);
|
||||
|
||||
TIMER_ENTER_CRITICAL(&timer_spinlock[group_num]);
|
||||
config->alarm_en = p_timer_obj[group_num][timer_num]->alarm_en;
|
||||
config->auto_reload = p_timer_obj[group_num][timer_num]->auto_reload_en;
|
||||
config->counter_dir = p_timer_obj[group_num][timer_num]->direction;
|
||||
config->counter_en = p_timer_obj[group_num][timer_num]->counter_en;
|
||||
config->divider = p_timer_obj[group_num][timer_num]->divider;
|
||||
config->intr_type = TIMER_INTR_LEVEL;
|
||||
TIMER_EXIT_CRITICAL(&timer_spinlock[group_num]);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t timer_group_intr_enable(timer_group_t group_num, timer_intr_t en_mask)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(group_num < TIMER_GROUP_MAX, ESP_ERR_INVALID_ARG, TIMER_TAG, TIMER_GROUP_NUM_ERROR);
|
||||
ESP_RETURN_ON_FALSE(p_timer_obj[group_num] != NULL, ESP_ERR_INVALID_ARG, TIMER_TAG, TIMER_NEVER_INIT_ERROR);
|
||||
TIMER_ENTER_CRITICAL(&timer_spinlock[group_num]);
|
||||
timer_ll_enable_intr(p_timer_obj[group_num][0]->hal.dev, en_mask, true);
|
||||
TIMER_EXIT_CRITICAL(&timer_spinlock[group_num]);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t timer_group_intr_disable(timer_group_t group_num, timer_intr_t disable_mask)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(group_num < TIMER_GROUP_MAX, ESP_ERR_INVALID_ARG, TIMER_TAG, TIMER_GROUP_NUM_ERROR);
|
||||
ESP_RETURN_ON_FALSE(p_timer_obj[group_num] != NULL, ESP_ERR_INVALID_ARG, TIMER_TAG, TIMER_NEVER_INIT_ERROR);
|
||||
TIMER_ENTER_CRITICAL(&timer_spinlock[group_num]);
|
||||
timer_ll_enable_intr(p_timer_obj[group_num][0]->hal.dev, disable_mask, false);
|
||||
TIMER_EXIT_CRITICAL(&timer_spinlock[group_num]);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
uint32_t IRAM_ATTR timer_group_get_intr_status_in_isr(timer_group_t group_num)
|
||||
{
|
||||
uint32_t intr_status = 0;
|
||||
if (p_timer_obj[group_num][TIMER_0] != NULL) {
|
||||
intr_status = timer_ll_get_intr_status(TIMER_LL_GET_HW(group_num)) & TIMER_LL_EVENT_ALARM(0);
|
||||
}
|
||||
#if SOC_TIMER_GROUP_TIMERS_PER_GROUP > 1
|
||||
else if (p_timer_obj[group_num][TIMER_1] != NULL) {
|
||||
intr_status = timer_ll_get_intr_status(TIMER_LL_GET_HW(group_num)) & TIMER_LL_EVENT_ALARM(1);
|
||||
}
|
||||
#endif
|
||||
return intr_status;
|
||||
}
|
||||
|
||||
void IRAM_ATTR timer_group_clr_intr_status_in_isr(timer_group_t group_num, timer_idx_t timer_num)
|
||||
{
|
||||
timer_ll_clear_intr_status(p_timer_obj[group_num][timer_num]->hal.dev, TIMER_LL_EVENT_ALARM(timer_num));
|
||||
}
|
||||
|
||||
void IRAM_ATTR timer_group_enable_alarm_in_isr(timer_group_t group_num, timer_idx_t timer_num)
|
||||
{
|
||||
timer_ll_enable_alarm(p_timer_obj[group_num][timer_num]->hal.dev, timer_num, true);
|
||||
}
|
||||
|
||||
uint64_t IRAM_ATTR timer_group_get_counter_value_in_isr(timer_group_t group_num, timer_idx_t timer_num)
|
||||
{
|
||||
timer_ll_trigger_soft_capture(p_timer_obj[group_num][timer_num]->hal.dev, timer_num);
|
||||
uint64_t val = timer_ll_get_counter_value(p_timer_obj[group_num][timer_num]->hal.dev, timer_num);
|
||||
return val;
|
||||
}
|
||||
|
||||
void IRAM_ATTR timer_group_set_alarm_value_in_isr(timer_group_t group_num, timer_idx_t timer_num, uint64_t alarm_val)
|
||||
{
|
||||
timer_ll_set_alarm_value(p_timer_obj[group_num][timer_num]->hal.dev, timer_num, alarm_val);
|
||||
p_timer_obj[group_num][timer_num]->alarm_value = alarm_val;
|
||||
}
|
||||
|
||||
void IRAM_ATTR timer_group_set_counter_enable_in_isr(timer_group_t group_num, timer_idx_t timer_num, timer_start_t counter_en)
|
||||
{
|
||||
timer_ll_enable_counter(p_timer_obj[group_num][timer_num]->hal.dev, timer_num, counter_en);
|
||||
p_timer_obj[group_num][timer_num]->counter_en = counter_en;
|
||||
}
|
||||
|
||||
bool IRAM_ATTR timer_group_get_auto_reload_in_isr(timer_group_t group_num, timer_idx_t timer_num)
|
||||
{
|
||||
return p_timer_obj[group_num][timer_num]->auto_reload_en;
|
||||
}
|
||||
|
||||
#if !CONFIG_GPTIMER_SKIP_LEGACY_CONFLICT_CHECK
|
||||
/**
|
||||
* @brief This function will be called during start up, to check that this legacy timer group driver is not running along with the gptimer driver
|
||||
*/
|
||||
__attribute__((constructor))
|
||||
static void check_legacy_timer_driver_conflict(void)
|
||||
{
|
||||
// This function was declared as weak here. gptimer driver has one implementation.
|
||||
// So if gptimer driver is not linked in, then `gptimer_new_timer()` should be NULL at runtime.
|
||||
extern __attribute__((weak)) esp_err_t gptimer_new_timer(const void *config, void **ret_timer);
|
||||
if ((void *)gptimer_new_timer != NULL) {
|
||||
ESP_EARLY_LOGE(TIMER_TAG, "CONFLICT! driver_ng is not allowed to be used with the legacy driver");
|
||||
abort();
|
||||
}
|
||||
ESP_EARLY_LOGW(TIMER_TAG, "legacy driver is deprecated, please migrate to `driver/gptimer.h`");
|
||||
}
|
||||
#endif //CONFIG_GPTIMER_SKIP_LEGACY_CONFLICT_CHECK
|
||||
@@ -1,5 +1,33 @@
|
||||
# Documentation: .gitlab/ci/README.md#manifest-file-to-control-the-buildtest-apps
|
||||
|
||||
components/driver/test_apps/dac_test_apps/legacy_dac_driver:
|
||||
disable:
|
||||
- if: SOC_DAC_SUPPORTED != 1
|
||||
depends_components:
|
||||
- esp_adc
|
||||
|
||||
components/driver/test_apps/i2s_test_apps/legacy_i2s_adc_dac:
|
||||
disable:
|
||||
- if: SOC_I2S_SUPPORTS_ADC_DAC != 1
|
||||
|
||||
components/driver/test_apps/i2s_test_apps/legacy_i2s_driver:
|
||||
disable:
|
||||
- if: SOC_I2S_SUPPORTED != 1
|
||||
|
||||
components/driver/test_apps/legacy_adc_driver:
|
||||
disable:
|
||||
- if: SOC_ADC_SUPPORTED != 1
|
||||
disable_test:
|
||||
- if: IDF_TARGET == "esp32c61"
|
||||
temporary: true
|
||||
reason: lack of runners
|
||||
depends_components:
|
||||
- efuse
|
||||
- esp_driver_i2s
|
||||
- esp_driver_spi
|
||||
depends_filepatterns:
|
||||
- components/driver/deprecated/**/*adc*
|
||||
|
||||
components/driver/test_apps/legacy_i2c_driver:
|
||||
disable:
|
||||
- if: SOC_I2C_SUPPORTED != 1
|
||||
@@ -14,12 +42,22 @@ components/driver/test_apps/legacy_mcpwm_driver:
|
||||
depends_filepatterns:
|
||||
- components/driver/deprecated/**/*mcpwm*
|
||||
|
||||
components/driver/test_apps/legacy_pcnt_driver:
|
||||
disable:
|
||||
- if: SOC_PCNT_SUPPORTED != 1
|
||||
depends_filepatterns:
|
||||
- components/driver/deprecated/**/*pcnt*
|
||||
|
||||
components/driver/test_apps/legacy_rmt_driver:
|
||||
disable:
|
||||
- if: SOC_RMT_SUPPORTED != 1
|
||||
depends_filepatterns:
|
||||
- components/driver/deprecated/**/*rmt*
|
||||
|
||||
components/driver/test_apps/legacy_rtc_temp_driver:
|
||||
disable:
|
||||
- if: SOC_TEMP_SENSOR_SUPPORTED != 1
|
||||
|
||||
components/driver/test_apps/legacy_sigma_delta_driver:
|
||||
disable:
|
||||
- if: SOC_SDM_SUPPORTED != 1
|
||||
@@ -28,6 +66,12 @@ components/driver/test_apps/legacy_sigma_delta_driver:
|
||||
depends_components:
|
||||
- esp_driver_gpio
|
||||
|
||||
components/driver/test_apps/legacy_timer_driver:
|
||||
disable:
|
||||
- if: SOC_GPTIMER_SUPPORTED != 1
|
||||
depends_filepatterns:
|
||||
- components/driver/deprecated/**/*timer*
|
||||
|
||||
components/driver/test_apps/legacy_twai:
|
||||
disable:
|
||||
- if: SOC_TWAI_SUPPORTED != 1 or SOC_TWAI_SUPPORT_FD == 1
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
# This is the project CMakeLists.txt file for the test subproject
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
# "Trim" the build. Include the minimal set of components, main, and anything it depends on.
|
||||
set(COMPONENTS main)
|
||||
|
||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||
project(dac_legacy_test)
|
||||
|
||||
if(CONFIG_COMPILER_DUMP_RTL_FILES)
|
||||
add_custom_target(check_test_app_sections ALL
|
||||
COMMAND ${PYTHON} $ENV{IDF_PATH}/tools/ci/check_callgraph.py
|
||||
--rtl-dirs ${CMAKE_BINARY_DIR}/esp-idf/driver/,${CMAKE_BINARY_DIR}/esp-idf/hal/
|
||||
--elf-file ${CMAKE_BINARY_DIR}/dac_legacy_test.elf
|
||||
find-refs
|
||||
--from-sections=.iram0.text
|
||||
--to-sections=.flash.text,.flash.rodata
|
||||
--exit-code
|
||||
DEPENDS ${elf}
|
||||
)
|
||||
endif()
|
||||
@@ -0,0 +1,2 @@
|
||||
| Supported Targets | ESP32 | ESP32-S2 |
|
||||
| ----------------- | ----- | -------- |
|
||||
@@ -0,0 +1,8 @@
|
||||
set(srcs "test_app_main.c"
|
||||
"test_legacy_dac.c")
|
||||
|
||||
# In order for the cases defined by `TEST_CASE` to be linked into the final elf,
|
||||
# the component can be registered as WHOLE_ARCHIVE
|
||||
idf_component_register(SRCS ${srcs}
|
||||
PRIV_REQUIRES unity driver esp_event esp_adc
|
||||
WHOLE_ARCHIVE)
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "unity.h"
|
||||
#include "unity_test_runner.h"
|
||||
#include "esp_heap_caps.h"
|
||||
|
||||
// Some resources are lazy allocated in dac driver, the threshold is left for that case
|
||||
#define TEST_MEMORY_LEAK_THRESHOLD (-300)
|
||||
|
||||
static size_t before_free_8bit;
|
||||
static size_t before_free_32bit;
|
||||
|
||||
static void check_leak(size_t before_free, size_t after_free, const char *type)
|
||||
{
|
||||
ssize_t delta = after_free - before_free;
|
||||
printf("MALLOC_CAP_%s: Before %u bytes free, After %u bytes free (delta %d)\n", type, before_free, after_free, delta);
|
||||
TEST_ASSERT_MESSAGE(delta >= TEST_MEMORY_LEAK_THRESHOLD, "memory leak");
|
||||
}
|
||||
|
||||
void setUp(void)
|
||||
{
|
||||
before_free_8bit = heap_caps_get_free_size(MALLOC_CAP_8BIT);
|
||||
before_free_32bit = heap_caps_get_free_size(MALLOC_CAP_32BIT);
|
||||
}
|
||||
|
||||
void tearDown(void)
|
||||
{
|
||||
size_t after_free_8bit = heap_caps_get_free_size(MALLOC_CAP_8BIT);
|
||||
size_t after_free_32bit = heap_caps_get_free_size(MALLOC_CAP_32BIT);
|
||||
check_leak(before_free_8bit, after_free_8bit, "8BIT");
|
||||
check_leak(before_free_32bit, after_free_32bit, "32BIT");
|
||||
}
|
||||
|
||||
void app_main(void)
|
||||
{
|
||||
// ____ _ ____ _____ _
|
||||
// | _ \ / \ / ___| |_ _|__ ___| |_
|
||||
// | | | |/ _ \| | | |/ _ \/ __| __|
|
||||
// | |_| / ___ \ |___ | | __/\__ \ |_
|
||||
// |____/_/ \_\____| |_|\___||___/\__|
|
||||
|
||||
printf(" ____ _ ____ _____ _ \n");
|
||||
printf(" | _ \\ / \\ / ___| |_ _|__ ___| |_ \n");
|
||||
printf(" | | | |/ _ \\| | | |/ _ \\/ __| __|\n");
|
||||
printf(" | |_| / ___ \\ |___ | | __/\\__ \\ |_ \n");
|
||||
printf(" |____/_/ \\_\\____| |_|\\___||___/\\__| (legacy)\n");
|
||||
|
||||
unity_run_menu();
|
||||
}
|
||||
@@ -0,0 +1,183 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
/*
|
||||
Tests for the dac device driver
|
||||
*/
|
||||
#include <inttypes.h>
|
||||
#include "esp_system.h"
|
||||
|
||||
#include "unity.h"
|
||||
#include "unity_test_utils.h"
|
||||
#include "esp_system.h"
|
||||
#include "esp_event.h"
|
||||
#include "esp_log.h"
|
||||
#include "soc/soc_caps.h"
|
||||
#define CONFIG_ADC_SUPPRESS_DEPRECATE_WARN 1
|
||||
#include "driver/adc.h"
|
||||
|
||||
#include "driver/dac.h"
|
||||
#include "esp_adc_cal.h"
|
||||
|
||||
static const char *TAG = "test_dac";
|
||||
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32
|
||||
#define ADC_TEST_WIDTH ADC_WIDTH_BIT_12
|
||||
#elif defined CONFIG_IDF_TARGET_ESP32S2
|
||||
#define ADC_TEST_WIDTH ADC_WIDTH_BIT_13 //ESP32S2 only support 13 bit width
|
||||
#endif
|
||||
#define ADC_TEST_ATTEN ADC_ATTEN_DB_12
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
#define ADC_TEST_CHANNEL_NUM ADC2_CHANNEL_8 // GPIO25
|
||||
#define DAC_TEST_CHANNEL_NUM DAC_CHAN_0 // GPIO25
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||
#define ADC_TEST_CHANNEL_NUM ADC2_CHANNEL_6 // GPIO17
|
||||
#define DAC_TEST_CHANNEL_NUM DAC_CHAN_0 // GPIO17
|
||||
#endif
|
||||
|
||||
#define DAC_OUT_MAX (200)
|
||||
#define DAC_OUT_TIMES (10)
|
||||
#define DAC_OUT_STEP (DAC_OUT_MAX / DAC_OUT_TIMES)
|
||||
|
||||
#define DAC_TEST_TIMES (100)
|
||||
|
||||
TEST_CASE("DAC_output(RTC)_check_by_adc", "[dac_legacy]")
|
||||
{
|
||||
gpio_num_t adc_gpio_num, dac_gpio_num;
|
||||
|
||||
TEST_ESP_OK(adc2_pad_get_io_num(ADC_TEST_CHANNEL_NUM, &adc_gpio_num));
|
||||
TEST_ESP_OK(dac_pad_get_io_num(DAC_TEST_CHANNEL_NUM, &dac_gpio_num));
|
||||
|
||||
printf("Please connect ADC2 CH%d-GPIO%d <--> DAC CH%d-GPIO%d.\n", ADC_TEST_CHANNEL_NUM, adc_gpio_num,
|
||||
DAC_TEST_CHANNEL_NUM + 1, dac_gpio_num);
|
||||
|
||||
TEST_ESP_OK(dac_output_enable(DAC_TEST_CHANNEL_NUM));
|
||||
|
||||
//be sure to do the init before using adc2.
|
||||
printf("adc2_init...\n");
|
||||
TEST_ESP_OK(adc2_config_channel_atten(ADC_TEST_CHANNEL_NUM, ADC_TEST_ATTEN));
|
||||
|
||||
vTaskDelay(2 * portTICK_PERIOD_MS);
|
||||
|
||||
printf("start conversion.\n");
|
||||
int output_data = 0;
|
||||
int read_raw = 0, read_old = 0;
|
||||
for (int i = 0; i < DAC_OUT_TIMES; i++) {
|
||||
TEST_ESP_OK(dac_output_voltage(DAC_TEST_CHANNEL_NUM, output_data));
|
||||
output_data += DAC_OUT_STEP;
|
||||
vTaskDelay(2 * portTICK_PERIOD_MS);
|
||||
TEST_ESP_OK(adc2_get_raw(ADC_TEST_CHANNEL_NUM, ADC_TEST_WIDTH, &read_raw));
|
||||
ESP_LOGI(TAG, "DAC: %d - ADC: %d", output_data, read_raw);
|
||||
if (read_old != 0) {
|
||||
TEST_ASSERT_GREATER_THAN(read_old, read_raw);
|
||||
}
|
||||
read_old = read_raw;
|
||||
}
|
||||
TEST_ESP_OK(dac_output_disable(DAC_TEST_CHANNEL_NUM));
|
||||
}
|
||||
|
||||
TEST_CASE("DAC_cw_generator_output(RTC)_check_by_adc", "[dac_legacy]")
|
||||
{
|
||||
gpio_num_t adc_gpio_num, dac_gpio_num;
|
||||
|
||||
TEST_ESP_OK(adc2_pad_get_io_num(ADC_TEST_CHANNEL_NUM, &adc_gpio_num));
|
||||
TEST_ESP_OK(dac_pad_get_io_num(DAC_TEST_CHANNEL_NUM, &dac_gpio_num));
|
||||
|
||||
printf("Please connect ADC2 CH%d-GPIO%d <--> DAC CH%d-GPIO%d.\n", ADC_TEST_CHANNEL_NUM, adc_gpio_num,
|
||||
DAC_TEST_CHANNEL_NUM + 1, dac_gpio_num);
|
||||
|
||||
dac_cw_config_t cw = {
|
||||
.en_ch = DAC_TEST_CHANNEL_NUM,
|
||||
.scale = DAC_CW_SCALE_2,
|
||||
.phase = DAC_CW_PHASE_0,
|
||||
.freq = 1000,
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
.offset = 64,
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||
.offset = 16,
|
||||
#endif
|
||||
};
|
||||
TEST_ESP_OK(dac_cw_generator_config(&cw));
|
||||
TEST_ESP_OK(dac_cw_generator_enable());
|
||||
TEST_ESP_OK(dac_output_enable(DAC_TEST_CHANNEL_NUM));
|
||||
|
||||
//be sure to do the init before using adc2.
|
||||
printf("adc2_init...\n");
|
||||
TEST_ESP_OK(adc2_config_channel_atten(ADC_TEST_CHANNEL_NUM, ADC_TEST_ATTEN));
|
||||
|
||||
vTaskDelay(2 * portTICK_PERIOD_MS);
|
||||
|
||||
printf("start conversion.\n");
|
||||
int read_raw[3] = {0};
|
||||
for (int i = 0; i < DAC_TEST_TIMES; i++) {
|
||||
vTaskDelay(10 * portTICK_PERIOD_MS);
|
||||
TEST_ESP_OK(adc2_get_raw(ADC_TEST_CHANNEL_NUM, ADC_TEST_WIDTH, &read_raw[0]));
|
||||
ESP_LOGI(TAG, "ADC: %d", read_raw[0]);
|
||||
read_raw[2] = read_raw[1];
|
||||
read_raw[1] = read_raw[0];
|
||||
}
|
||||
|
||||
TEST_ESP_OK(dac_cw_generator_disable());
|
||||
TEST_ESP_OK(dac_output_disable(DAC_TEST_CHANNEL_NUM));
|
||||
}
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32S2
|
||||
static int helper_calc_dac_output(int mV)
|
||||
{
|
||||
return mV * 0.07722;
|
||||
}
|
||||
static bool subtest_adc_dac(int mV_ref, esp_adc_cal_characteristics_t * chars)
|
||||
{
|
||||
dac_output_voltage(DAC_TEST_CHANNEL_NUM, helper_calc_dac_output(mV_ref));
|
||||
vTaskDelay(pdMS_TO_TICKS(80));
|
||||
int raw;
|
||||
adc2_get_raw((adc2_channel_t)ADC_TEST_CHANNEL_NUM, ADC_WIDTH_BIT_13, &raw);
|
||||
uint32_t voltage = esp_adc_cal_raw_to_voltage(raw, chars);
|
||||
TEST_ASSERT_INT_WITHIN(200, mV_ref, voltage); // 200 mV error allowance, because both DAC and ADC have error
|
||||
return true;
|
||||
}
|
||||
|
||||
TEST_CASE("esp32s2_adc2-dac_with_adc2_calibration", "[dac_legacy]")
|
||||
{
|
||||
gpio_num_t adc_gpio_num, dac_gpio_num;
|
||||
if (esp_adc_cal_check_efuse(ESP_ADC_CAL_VAL_EFUSE_TP) != ESP_OK) {
|
||||
TEST_IGNORE_MESSAGE("Warning: This esp32s2 board does not support calibration. This test will be skipped.\n");
|
||||
}
|
||||
TEST_ESP_OK(adc2_pad_get_io_num(ADC_TEST_CHANNEL_NUM, &adc_gpio_num));
|
||||
TEST_ESP_OK(dac_pad_get_io_num(DAC_TEST_CHANNEL_NUM, &dac_gpio_num));
|
||||
printf("Please connect ADC2 CH%d-GPIO%d <--> DAC CH%d-GPIO%d.\n", ADC_TEST_CHANNEL_NUM, adc_gpio_num,
|
||||
DAC_TEST_CHANNEL_NUM + 1, dac_gpio_num);
|
||||
TEST_ESP_OK(dac_output_enable(DAC_TEST_CHANNEL_NUM));
|
||||
|
||||
esp_adc_cal_characteristics_t chars;
|
||||
|
||||
printf("Test 0dB atten...\n");
|
||||
adc2_config_channel_atten((adc2_channel_t)ADC_TEST_CHANNEL_NUM, ADC_ATTEN_DB_0);
|
||||
esp_adc_cal_characterize(ADC_UNIT_2, ADC_ATTEN_DB_0, ADC_WIDTH_BIT_13, 0, &chars);
|
||||
printf("a %"PRIu32", b %"PRIu32"\n", chars.coeff_a, chars.coeff_b);
|
||||
subtest_adc_dac(750, &chars);
|
||||
|
||||
printf("Test 2.5dB atten...\n");
|
||||
adc2_config_channel_atten((adc2_channel_t)ADC_TEST_CHANNEL_NUM, ADC_ATTEN_DB_2_5);
|
||||
esp_adc_cal_characterize(ADC_UNIT_2, ADC_ATTEN_DB_2_5, ADC_WIDTH_BIT_13, 0, &chars);
|
||||
printf("a %"PRIu32", b %"PRIu32"\n", chars.coeff_a, chars.coeff_b);
|
||||
subtest_adc_dac(1100, &chars);
|
||||
|
||||
printf("Test 6dB atten...\n");
|
||||
adc2_config_channel_atten((adc2_channel_t)ADC_TEST_CHANNEL_NUM, ADC_ATTEN_DB_6);
|
||||
esp_adc_cal_characterize(ADC_UNIT_2, ADC_ATTEN_DB_6, ADC_WIDTH_BIT_13, 0, &chars);
|
||||
printf("a %"PRIu32", b %"PRIu32"\n", chars.coeff_a, chars.coeff_b);
|
||||
subtest_adc_dac(800, &chars);
|
||||
subtest_adc_dac(1250, &chars);
|
||||
|
||||
printf("Test 11dB atten...\n");
|
||||
adc2_config_channel_atten((adc2_channel_t)ADC_TEST_CHANNEL_NUM, ADC_ATTEN_DB_12);
|
||||
esp_adc_cal_characterize(ADC_UNIT_2, ADC_ATTEN_DB_12, ADC_WIDTH_BIT_13, 0, &chars);
|
||||
printf("a %"PRIu32", b %"PRIu32"\n", chars.coeff_a, chars.coeff_b);
|
||||
subtest_adc_dac(1500, &chars);
|
||||
subtest_adc_dac(2500, &chars);
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,18 @@
|
||||
# SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD
|
||||
# SPDX-License-Identifier: CC0-1.0
|
||||
import pytest
|
||||
from pytest_embedded import Dut
|
||||
from pytest_embedded_idf.utils import idf_parametrize
|
||||
|
||||
|
||||
@pytest.mark.generic
|
||||
@pytest.mark.parametrize(
|
||||
'config',
|
||||
[
|
||||
'release',
|
||||
],
|
||||
indirect=True,
|
||||
)
|
||||
@idf_parametrize('target', ['esp32', 'esp32s2'], indirect=['target'])
|
||||
def test_legacy_dac(dut: Dut) -> None:
|
||||
dut.run_all_single_board_cases()
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user