forked from espressif/esp-idf
Compare commits
409 Commits
v5.4.3
...
remove-use
| Author | SHA1 | Date | |
|---|---|---|---|
| 4bbff34ac2 | |||
|
|
f420609c33 | ||
|
|
5910fc8270 | ||
|
|
691a0ee1fd | ||
|
|
66596b7f59 | ||
|
|
9c91d08c78 | ||
|
|
f3c95b632e | ||
|
|
978896a09d | ||
|
|
b65f8a98bd | ||
|
|
0045550de5 | ||
|
|
393b7410a6 | ||
|
|
03b6436745 | ||
|
|
6d3a82eecf | ||
|
|
b9253b4e66 | ||
|
|
e8800ac785 | ||
|
|
88c4086db9 | ||
|
|
42cbc7aada | ||
|
|
9382c9a400 | ||
|
|
4c9154bad1 | ||
|
|
16469297b4 | ||
|
|
5009857d7d | ||
|
|
401fa7b0f3 | ||
|
|
53d2d67226 | ||
|
|
a3922cd1a7 | ||
|
|
29b017b785 | ||
|
|
5aaa47834a | ||
|
|
c5ada2e82f | ||
|
|
9f47024e78 | ||
|
|
6e05a9e65b | ||
|
|
7c384facd7 | ||
|
|
092bbdbc9c | ||
|
|
c014ced2f8 | ||
|
|
872a3a2d71 | ||
|
|
e84b59cf92 | ||
|
|
a1ec278291 | ||
|
|
9dc4a27d9c | ||
|
|
d74bf059c8 | ||
|
|
3c8a32ff0d | ||
|
|
8255ba29a6 | ||
|
|
4b79cb964f | ||
|
|
4d75d2d487 | ||
|
|
59d20e80d3 | ||
|
|
890106fb23 | ||
|
|
7e9782b67e | ||
|
|
1a028bdfdc | ||
|
|
167cd4762b | ||
|
|
74c847210d | ||
|
|
6002db2fb9 | ||
|
|
c86a301736 | ||
|
|
ce85e113a9 | ||
|
|
c445ec134b | ||
|
|
1e11d42aa1 | ||
|
|
38b737511c | ||
|
|
7fcbdb9c2e | ||
|
|
83c9cffd2b | ||
|
|
ab75a94877 | ||
|
|
ace6a490bc | ||
|
|
7ff774905a | ||
|
|
705e2695ee | ||
|
|
0b1170af8f | ||
|
|
78a690517f | ||
|
|
074b74c701 | ||
|
|
d5f244c5f7 | ||
|
|
1de992adef | ||
|
|
6a9e7f61e8 | ||
|
|
bbcfb35d67 | ||
|
|
fe93c990e6 | ||
|
|
4b4a9a2174 | ||
|
|
d7bc953d66 | ||
|
|
ea31e155e8 | ||
|
|
32f60da330 | ||
|
|
4e9362a1cb | ||
|
|
7a305c0284 | ||
|
|
9ec62baa94 | ||
|
|
862f3bd7bf | ||
|
|
e613fcde6e | ||
|
|
d37e1cccb6 | ||
|
|
582c99041c | ||
|
|
5532fa8e26 | ||
|
|
0d99214012 | ||
|
|
1e7098fe97 | ||
|
|
1a25f6887d | ||
|
|
cbbb85fecd | ||
|
|
97b65d7350 | ||
|
|
b6be76f53b | ||
|
|
df52e1aa71 | ||
|
|
b4bd3d98bd | ||
|
|
908e62f5e4 | ||
|
|
ed8ec9de0b | ||
|
|
bff20b5397 | ||
|
|
f8ddcee8cd | ||
|
|
5bff669f2f | ||
|
|
727825663b | ||
|
|
cb41623b2e | ||
|
|
9e3b7e4558 | ||
|
|
cf44fc6a1f | ||
|
|
30b13b132d | ||
|
|
d8949fe50f | ||
|
|
5bae0b92ec | ||
|
|
7f54410256 | ||
|
|
ce72392e2f | ||
|
|
542a5d280c | ||
|
|
05beacad73 | ||
|
|
33149921aa | ||
|
|
dca5d193fc | ||
|
|
b0ffe15514 | ||
|
|
b4f366f56f | ||
|
|
32040c7f98 | ||
|
|
e8f0299557 | ||
|
|
de077c77b4 | ||
|
|
ccc2411191 | ||
|
|
bb9a2658a9 | ||
|
|
3318e0accd | ||
|
|
52f14f344d | ||
|
|
a4acbd2758 | ||
|
|
e8fda6f776 | ||
|
|
e6ef4d1791 | ||
|
|
16eef27492 | ||
|
|
d0e6e825d9 | ||
|
|
64bbb53b8f | ||
|
|
c9bf5d9698 | ||
|
|
c41cead036 | ||
|
|
f5f46ab74c | ||
|
|
98f1dd969a | ||
|
|
2b29de78bb | ||
|
|
3107f0abe7 | ||
|
|
1689c7e14f | ||
|
|
e7ab36ebbf | ||
|
|
afb4a02fe4 | ||
|
|
cf087cb8e5 | ||
|
|
2899c1e39f | ||
|
|
ba2bf2f512 | ||
|
|
3f46b378bb | ||
|
|
ea902d6ed7 | ||
|
|
dccbd16750 | ||
|
|
06508329c8 | ||
|
|
7bc8b998a7 | ||
|
|
08ef00d82d | ||
|
|
87e4f63c77 | ||
|
|
56db9a2841 | ||
|
|
4df585e1a8 | ||
|
|
3ec05583b2 | ||
|
|
2414b285c0 | ||
|
|
611e163024 | ||
|
|
7962d54c4c | ||
|
|
4e3e73f353 | ||
|
|
d74e99c08a | ||
|
|
110bfc1f45 | ||
|
|
f817b85fc3 | ||
|
|
d03ead4cf8 | ||
|
|
b3bae69c5c | ||
|
|
798d35b2e1 | ||
|
|
99f1455199 | ||
|
|
816a0da0fd | ||
|
|
8f777699ff | ||
|
|
8b191dd7a1 | ||
|
|
c7e2a9ea0d | ||
|
|
f269835865 | ||
|
|
9a41a61dd5 | ||
|
|
197128b162 | ||
|
|
2a5743c0c5 | ||
|
|
83306b79ef | ||
|
|
3e2b56d114 | ||
|
|
5a3f53a2b5 | ||
|
|
92cd70acc9 | ||
|
|
f84f883ab4 | ||
|
|
d137deed2a | ||
|
|
dcb4bf4600 | ||
|
|
fc81b6878e | ||
|
|
63e74e6b68 | ||
|
|
941d0e0779 | ||
|
|
f15c1b4c4f | ||
|
|
8576f40ced | ||
|
|
efd04b7709 | ||
|
|
d2c74a6b1e | ||
|
|
0bda2f8990 | ||
|
|
3730567940 | ||
|
|
6b54dfc636 | ||
|
|
7f07c9de44 | ||
|
|
1a30fd0c39 | ||
|
|
a86bb375f7 | ||
|
|
cfdefd3e03 | ||
|
|
c79eb0d5bf | ||
|
|
01cd5cf4fe | ||
|
|
f0ab551348 | ||
|
|
a50c095df1 | ||
|
|
ad476afb5c | ||
|
|
bb329c4e53 | ||
|
|
457f65195e | ||
|
|
cce9a80aee | ||
|
|
94536cb512 | ||
|
|
4fa6e03879 | ||
|
|
d2fe62f682 | ||
|
|
19ab0213d9 | ||
|
|
f41b43dc43 | ||
|
|
68e9bcbf1e | ||
|
|
97d150d69a | ||
|
|
ac630e4417 | ||
|
|
0ed4c19c5e | ||
|
|
712e6ad927 | ||
|
|
5e056de1e7 | ||
|
|
db579962b6 | ||
|
|
8aa56d805a | ||
|
|
d2b1202d5a | ||
|
|
269322191a | ||
|
|
8e4ff8bcba | ||
|
|
d1e7939940 | ||
|
|
9c5dde5536 | ||
|
|
ef437b7b0d | ||
|
|
6fdd380812 | ||
|
|
4a444c80ae | ||
|
|
dbc6be3138 | ||
|
|
97e669214c | ||
|
|
8bd4071f92 | ||
|
|
280b3d9e62 | ||
|
|
0a098f49d4 | ||
|
|
87f2080705 | ||
|
|
0eeb544bd2 | ||
|
|
4c6cda734d | ||
|
|
670d34e363 | ||
|
|
b7aecdbbaf | ||
|
|
df120ac962 | ||
|
|
e8c5992a57 | ||
|
|
1f49c9a845 | ||
|
|
068790baa9 | ||
|
|
9d4a897d47 | ||
|
|
c8b67235e6 | ||
|
|
402fecee17 | ||
|
|
50ac90b489 | ||
|
|
b2e0bd9200 | ||
|
|
765fe330ea | ||
|
|
afa46c06a8 | ||
|
|
72308ca089 | ||
|
|
26002e13fc | ||
|
|
405327d22a | ||
|
|
67169f8efd | ||
|
|
0c07ee6baf | ||
|
|
d46b23d44b | ||
|
|
6f86f70f0a | ||
|
|
3e4955345a | ||
|
|
f0701b265d | ||
|
|
7aaab5a3ff | ||
|
|
9677a4929f | ||
|
|
682a66d164 | ||
|
|
7e90a41bc9 | ||
|
|
0546805fc5 | ||
|
|
34ba72a431 | ||
|
|
e1a3ff1529 | ||
|
|
7786cbe2c8 | ||
|
|
ae51dcc227 | ||
|
|
47c8ca5556 | ||
|
|
5c3cb06d18 | ||
|
|
75aea08703 | ||
|
|
6bf2d91c4d | ||
|
|
9386b58e17 | ||
|
|
cfe6c45122 | ||
|
|
08f1c3681a | ||
|
|
676f5194d5 | ||
|
|
5cc9931dc7 | ||
|
|
70b652052e | ||
|
|
2d8053aabf | ||
|
|
403d44ae68 | ||
|
|
e6a97d2c56 | ||
|
|
1f47975472 | ||
|
|
93e77a4df6 | ||
|
|
c0f3ac4295 | ||
|
|
e1abef5e9b | ||
|
|
94d1a4f1c0 | ||
|
|
3cc9d42695 | ||
|
|
3357fe8b95 | ||
|
|
5504a596e2 | ||
|
|
6b3ae2822d | ||
|
|
ed21c54a64 | ||
|
|
c4bde5dfae | ||
|
|
375156918e | ||
|
|
a41c2d498e | ||
|
|
2cb35a2955 | ||
|
|
92ed77933b | ||
|
|
5976e391ea | ||
|
|
45ea08b955 | ||
|
|
f46b9ed5a6 | ||
|
|
02f6738d22 | ||
|
|
ce6085349f | ||
|
|
c2acddda7b | ||
|
|
37b600124f | ||
|
|
7397c159cb | ||
|
|
5b1891c2fa | ||
|
|
a71eb45ca1 | ||
|
|
5e8443a2f6 | ||
|
|
d1e5fd08ff | ||
|
|
569222488e | ||
|
|
63fdde6cd4 | ||
|
|
48ebf7c715 | ||
|
|
8fb28dcedc | ||
|
|
e27889a146 | ||
|
|
90abcdebf2 | ||
|
|
d1991b5b46 | ||
|
|
1a419e594b | ||
|
|
7bc9393301 | ||
|
|
feafc84ece | ||
|
|
729c55b790 | ||
|
|
a49454e352 | ||
|
|
e33bcaa6d3 | ||
|
|
a1df6b8185 | ||
|
|
775c65a6b7 | ||
|
|
a2f3585030 | ||
|
|
90e71bfa48 | ||
|
|
566721629f | ||
|
|
f6d154e761 | ||
|
|
24056620ef | ||
|
|
0e8a933488 | ||
|
|
50aeec2f97 | ||
|
|
8ac260a9d7 | ||
|
|
2c1bec2c70 | ||
|
|
ed31c19933 | ||
|
|
df2d09e3e0 | ||
|
|
116c3d6ddb | ||
|
|
8318adb448 | ||
|
|
203e5432a9 | ||
|
|
a4ef854a2d | ||
|
|
8c4f576f99 | ||
|
|
f9d6c4df20 | ||
|
|
7e5741953d | ||
|
|
77656e2046 | ||
|
|
8cd4091114 | ||
|
|
92b4c62d06 | ||
|
|
7d179ccd3e | ||
|
|
bb5a53c66c | ||
|
|
66f6364bb1 | ||
|
|
7a044c0f81 | ||
|
|
35ef6f5140 | ||
|
|
00dcf1a0c0 | ||
|
|
7cea2a78cc | ||
|
|
f7da0175b0 | ||
|
|
dee6ad56c9 | ||
|
|
f54ec30f6a | ||
|
|
92e4b80a65 | ||
|
|
b64e2ebfc9 | ||
|
|
460233ee3b | ||
|
|
034a35a66f | ||
|
|
1acc70f476 | ||
|
|
8f1fa6164a | ||
|
|
61a7ecd145 | ||
|
|
358e140705 | ||
|
|
dbad6a0ca5 | ||
|
|
dabd66e16f | ||
|
|
57eddeb36a | ||
|
|
908e1e670a | ||
|
|
3b36050e5e | ||
|
|
a2be2ffe5a | ||
|
|
d622011a2b | ||
|
|
dd8c545423 | ||
|
|
ddf6fea6a2 | ||
|
|
4685405a3f | ||
|
|
1805efb0b2 | ||
|
|
5ee42e0239 | ||
|
|
059de88f23 | ||
|
|
9b270c4c7d | ||
|
|
65deae1404 | ||
|
|
e2e4a36577 | ||
|
|
1de0358249 | ||
|
|
ecefb3c7e5 | ||
|
|
06da32f9f2 | ||
|
|
cb4442d948 | ||
|
|
ae4c4464b3 | ||
|
|
4464673ab9 | ||
|
|
29513cfe09 | ||
|
|
af75da0eee | ||
|
|
d74b584427 | ||
|
|
a98ff3aea6 | ||
|
|
653ce935f9 | ||
|
|
81f43866cd | ||
|
|
4b767d03fe | ||
|
|
c007ec5f17 | ||
|
|
1ccb534dc7 | ||
|
|
6856aec19e | ||
|
|
1cd9dd5001 | ||
|
|
10e6101061 | ||
|
|
e4c92855ee | ||
|
|
cceadc4ce8 | ||
|
|
8f7672e117 | ||
|
|
949fc7f2c9 | ||
|
|
e8f01afef7 | ||
|
|
1fcf006ec6 | ||
|
|
c466082ea6 | ||
|
|
cd21bdeb15 | ||
|
|
31b665c628 | ||
|
|
c0e1ecd310 | ||
|
|
901812c589 | ||
|
|
fc5b392c30 | ||
|
|
1d89e14433 | ||
|
|
21b38e8b97 | ||
|
|
d092c1ba55 | ||
|
|
33d3c60b26 | ||
|
|
52496491f8 | ||
|
|
d998d76627 | ||
|
|
7df8467be5 | ||
|
|
7fdfa6c227 | ||
|
|
4a22f982f3 | ||
|
|
000270a4f6 | ||
|
|
d837cae2b0 | ||
|
|
3881d4031d | ||
|
|
675653af89 | ||
|
|
cd8eb11ee7 | ||
|
|
0abdd20240 | ||
|
|
7bfee98996 | ||
|
|
bdf0821f97 | ||
|
|
ff25e646fb | ||
|
|
f3087c8fb0 |
2
.github/workflows/docker.yml
vendored
2
.github/workflows/docker.yml
vendored
@@ -21,7 +21,7 @@ jobs:
|
||||
# Disable the job in forks
|
||||
if: ${{ github.repository_owner == 'espressif' }}
|
||||
|
||||
runs-on: ubuntu-24.04-X64-large
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
# Depending on the branch/tag, set CLONE_BRANCH_OR_TAG variable (used in the Dockerfile
|
||||
# as a build arg) and TAG_NAME (used when tagging the image).
|
||||
|
||||
11
.github/workflows/release_zips.yml
vendored
11
.github/workflows/release_zips.yml
vendored
@@ -8,11 +8,10 @@ on:
|
||||
jobs:
|
||||
release_zips:
|
||||
name: Create release zip file
|
||||
runs-on: ubuntu-24.04
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- name: Create a recursive clone source zip
|
||||
uses: espressif/release-zips-action@v1
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
release_project_name: ESP-IDF
|
||||
git_extra_args: --shallow-since="1 year ago"
|
||||
uses: espressif/github-actions/release_zips@master
|
||||
env:
|
||||
RELEASE_PROJECT_NAME: ESP-IDF
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
@@ -2,5 +2,248 @@
|
||||
#
|
||||
# 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/all-maintainers
|
||||
* @esp-idf-codeowners/other
|
||||
|
||||
/.* @esp-idf-codeowners/tools
|
||||
/.codespellrc @esp-idf-codeowners/ci
|
||||
/.github/workflows/ @esp-idf-codeowners/ci
|
||||
/.gitlab-ci.yml @esp-idf-codeowners/ci
|
||||
/.gitlab/ci/ @esp-idf-codeowners/ci
|
||||
/.pre-commit-config.yaml @esp-idf-codeowners/ci
|
||||
/.readthedocs.yml @esp-idf-codeowners/docs
|
||||
/.vale.ini @esp-idf-codeowners/docs
|
||||
/CMakeLists.txt @esp-idf-codeowners/build-config
|
||||
/COMPATIBILITY*.md @esp-idf-codeowners/peripherals
|
||||
/CONTRIBUTING.md @esp-idf-codeowners/docs
|
||||
/Kconfig @esp-idf-codeowners/build-config
|
||||
/README*.md @esp-idf-codeowners/docs
|
||||
/ROADMAP*.md @esp-idf-codeowners/docs
|
||||
/SUPPORT_POLICY*.md @esp-idf-codeowners/docs
|
||||
/add_path.sh @esp-idf-codeowners/tools
|
||||
/conftest.py @esp-idf-codeowners/ci
|
||||
/export.* @esp-idf-codeowners/tools
|
||||
/install.* @esp-idf-codeowners/tools
|
||||
/pytest.ini @esp-idf-codeowners/ci
|
||||
/sdkconfig.rename @esp-idf-codeowners/build-config
|
||||
/sonar-project.properties @esp-idf-codeowners/ci
|
||||
|
||||
# sort-order-reset
|
||||
|
||||
/components/app_trace/ @esp-idf-codeowners/debugging
|
||||
/components/app_update/ @esp-idf-codeowners/system @esp-idf-codeowners/app-utilities
|
||||
/components/bootloader*/ @esp-idf-codeowners/system @esp-idf-codeowners/security
|
||||
/components/bootloader_support/bootloader_flash/ @esp-idf-codeowners/peripherals
|
||||
/components/bt/ @esp-idf-codeowners/bluetooth
|
||||
/components/cmock/ @esp-idf-codeowners/system
|
||||
/components/console/ @esp-idf-codeowners/system @esp-idf-codeowners/app-utilities/console
|
||||
/components/cxx/ @esp-idf-codeowners/system
|
||||
/components/driver/ @esp-idf-codeowners/peripherals
|
||||
/components/efuse/ @esp-idf-codeowners/system
|
||||
/components/esp_adc/ @esp-idf-codeowners/peripherals
|
||||
/components/esp_app_format/ @esp-idf-codeowners/system @esp-idf-codeowners/app-utilities
|
||||
/components/esp_bootloader_format/ @esp-idf-codeowners/system @esp-idf-codeowners/app-utilities
|
||||
/components/esp_coex/ @esp-idf-codeowners/wifi @esp-idf-codeowners/bluetooth @esp-idf-codeowners/ieee802154
|
||||
/components/esp_common/ @esp-idf-codeowners/system
|
||||
/components/esp_driver_*/ @esp-idf-codeowners/peripherals
|
||||
/components/esp_driver_sdmmc/ @esp-idf-codeowners/peripherals @esp-idf-codeowners/storage
|
||||
/components/esp_eth/ @esp-idf-codeowners/network
|
||||
/components/esp_event/ @esp-idf-codeowners/system
|
||||
/components/esp_gdbstub/ @esp-idf-codeowners/debugging
|
||||
/components/esp_hid/ @esp-idf-codeowners/bluetooth
|
||||
/components/esp_http_client/ @esp-idf-codeowners/app-utilities
|
||||
/components/esp_http_server/ @esp-idf-codeowners/app-utilities
|
||||
/components/esp_https_ota/ @esp-idf-codeowners/app-utilities
|
||||
/components/esp_https_server/ @esp-idf-codeowners/app-utilities
|
||||
/components/esp_hw_support/ @esp-idf-codeowners/system @esp-idf-codeowners/peripherals
|
||||
/components/esp_hw_support/lowpower/ @esp-idf-codeowners/power-management
|
||||
/components/esp_lcd/ @esp-idf-codeowners/peripherals
|
||||
/components/esp_local_ctrl/ @esp-idf-codeowners/app-utilities
|
||||
/components/esp_mm/ @esp-idf-codeowners/peripherals
|
||||
/components/esp_netif/ @esp-idf-codeowners/network
|
||||
/components/esp_netif_stack/ @esp-idf-codeowners/network
|
||||
/components/esp_partition/ @esp-idf-codeowners/storage
|
||||
/components/esp_phy/ @esp-idf-codeowners/bluetooth @esp-idf-codeowners/wifi @esp-idf-codeowners/ieee802154
|
||||
/components/esp_pm/ @esp-idf-codeowners/power-management @esp-idf-codeowners/bluetooth @esp-idf-codeowners/wifi @esp-idf-codeowners/system
|
||||
/components/esp_psram/ @esp-idf-codeowners/peripherals @esp-idf-codeowners/system
|
||||
/components/esp_ringbuf/ @esp-idf-codeowners/system
|
||||
/components/esp_rom/ @esp-idf-codeowners/system @esp-idf-codeowners/bluetooth @esp-idf-codeowners/wifi
|
||||
/components/esp_security/ @esp-idf-codeowners/security
|
||||
/components/esp_system/ @esp-idf-codeowners/system
|
||||
/components/esp_timer/ @esp-idf-codeowners/system
|
||||
/components/esp-tls/ @esp-idf-codeowners/app-utilities
|
||||
/components/esp_vfs_*/ @esp-idf-codeowners/storage
|
||||
/components/esp_vfs_console/ @esp-idf-codeowners/storage @esp-idf-codeowners/system
|
||||
/components/esp_wifi/ @esp-idf-codeowners/wifi
|
||||
/components/espcoredump/ @esp-idf-codeowners/debugging
|
||||
/components/esptool_py/ @esp-idf-codeowners/tools
|
||||
/components/fatfs/ @esp-idf-codeowners/storage
|
||||
/components/freertos/ @esp-idf-codeowners/system
|
||||
/components/hal/ @esp-idf-codeowners/peripherals
|
||||
/components/hal/test_apps/crypto/ @esp-idf-codeowners/peripherals @esp-idf-codeowners/security
|
||||
/components/heap/ @esp-idf-codeowners/system
|
||||
/components/http_parser/ @esp-idf-codeowners/app-utilities
|
||||
/components/idf_test/ @esp-idf-codeowners/ci
|
||||
/components/ieee802154/ @esp-idf-codeowners/ieee802154
|
||||
/components/json/ @esp-idf-codeowners/app-utilities
|
||||
/components/linux/ @esp-idf-codeowners/system
|
||||
/components/log/ @esp-idf-codeowners/system
|
||||
/components/lwip/ @esp-idf-codeowners/lwip
|
||||
/components/mbedtls/ @esp-idf-codeowners/app-utilities/mbedtls @esp-idf-codeowners/security
|
||||
/components/mqtt/ @esp-idf-codeowners/network
|
||||
/components/newlib/ @esp-idf-codeowners/system @esp-idf-codeowners/toolchain
|
||||
/components/nvs_flash/ @esp-idf-codeowners/storage
|
||||
/components/nvs_sec_provider/ @esp-idf-codeowners/storage @esp-idf-codeowners/security
|
||||
/components/openthread/ @esp-idf-codeowners/ieee802154
|
||||
/components/partition_table/ @esp-idf-codeowners/system
|
||||
/components/perfmon/ @esp-idf-codeowners/debugging
|
||||
/components/protobuf-c/ @esp-idf-codeowners/app-utilities
|
||||
/components/protocomm/ @esp-idf-codeowners/app-utilities/provisioning
|
||||
/components/pthread/ @esp-idf-codeowners/system
|
||||
/components/riscv/ @esp-idf-codeowners/system
|
||||
/components/rt/ @esp-idf-codeowners/system
|
||||
/components/sdmmc/ @esp-idf-codeowners/storage
|
||||
/components/soc/ @esp-idf-codeowners/peripherals @esp-idf-codeowners/system
|
||||
/components/spi_flash/ @esp-idf-codeowners/peripherals
|
||||
/components/spiffs/ @esp-idf-codeowners/storage
|
||||
/components/tcp_transport/ @esp-idf-codeowners/network
|
||||
/components/touch_element/ @esp-idf-codeowners/peripherals
|
||||
/components/ulp/ @esp-idf-codeowners/system
|
||||
/components/unity/ @esp-idf-codeowners/ci
|
||||
/components/usb/ @esp-idf-codeowners/peripherals/usb
|
||||
/components/vfs/ @esp-idf-codeowners/storage
|
||||
/components/wear_levelling/ @esp-idf-codeowners/storage
|
||||
/components/wifi_provisioning/ @esp-idf-codeowners/app-utilities/provisioning
|
||||
/components/wpa_supplicant/ @esp-idf-codeowners/wifi @esp-idf-codeowners/app-utilities/mbedtls
|
||||
/components/xtensa/ @esp-idf-codeowners/system
|
||||
|
||||
/docs/ @esp-idf-codeowners/docs
|
||||
/docs/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/mesh/ @esp-idf-codeowners/wifi
|
||||
/examples/network/ @esp-idf-codeowners/network @esp-idf-codeowners/wifi
|
||||
/examples/openthread/ @esp-idf-codeowners/ieee802154
|
||||
/examples/peripherals/ @esp-idf-codeowners/peripherals
|
||||
/examples/peripherals/usb/ @esp-idf-codeowners/peripherals @esp-idf-codeowners/peripherals/usb
|
||||
/examples/phy/ @esp-idf-codeowners/bluetooth @esp-idf-codeowners/wifi @esp-idf-codeowners/ieee802154
|
||||
/examples/protocols/ @esp-idf-codeowners/network @esp-idf-codeowners/app-utilities
|
||||
/examples/provisioning/ @esp-idf-codeowners/app-utilities/provisioning
|
||||
/examples/security/ @esp-idf-codeowners/security
|
||||
/examples/storage/ @esp-idf-codeowners/storage
|
||||
/examples/system/ @esp-idf-codeowners/system
|
||||
/examples/system/ota/ @esp-idf-codeowners/app-utilities
|
||||
/examples/wifi/ @esp-idf-codeowners/wifi
|
||||
/examples/zigbee/ @esp-idf-codeowners/ieee802154
|
||||
|
||||
/tools/ @esp-idf-codeowners/tools
|
||||
/tools/ble/ @esp-idf-codeowners/app-utilities
|
||||
/tools/catch/ @esp-idf-codeowners/ci
|
||||
/tools/ci/ @esp-idf-codeowners/ci
|
||||
/tools/cmake/ @esp-idf-codeowners/build-config
|
||||
/tools/cmake/toolchain-*.cmake @esp-idf-codeowners/toolchain
|
||||
/tools/esp_app_trace/ @esp-idf-codeowners/debugging
|
||||
/tools/esp_prov/ @esp-idf-codeowners/app-utilities
|
||||
/tools/gdb_panic_server.py @esp-idf-codeowners/debugging
|
||||
/tools/kconfig*/ @esp-idf-codeowners/build-config
|
||||
/tools/ldgen/ @esp-idf-codeowners/build-config
|
||||
/tools/mass_mfg/ @esp-idf-codeowners/app-utilities
|
||||
/tools/mocks/ @esp-idf-codeowners/system
|
||||
|
||||
/tools/test_apps/ @esp-idf-codeowners/ci
|
||||
/tools/test_apps/README.md @esp-idf-codeowners/docs @esp-idf-codeowners/ci
|
||||
|
||||
## Note: owners here should be the same as the owners for the same example subdir, above
|
||||
/tools/test_apps/build_system/ @esp-idf-codeowners/build-config
|
||||
/tools/test_apps/configs/ @esp-idf-codeowners/system
|
||||
/tools/test_apps/linux_compatible/ @esp-idf-codeowners/system
|
||||
/tools/test_apps/peripherals/ @esp-idf-codeowners/peripherals
|
||||
/tools/test_apps/phy/ @esp-idf-codeowners/bluetooth @esp-idf-codeowners/wifi @esp-idf-codeowners/ieee802154
|
||||
/tools/test_apps/protocols/ @esp-idf-codeowners/network @esp-idf-codeowners/app-utilities
|
||||
/tools/test_apps/security/ @esp-idf-codeowners/security
|
||||
/tools/test_apps/storage/ @esp-idf-codeowners/storage
|
||||
/tools/test_apps/system/ @esp-idf-codeowners/system
|
||||
|
||||
/tools/test_apps/**/*.py @esp-idf-codeowners/ci @esp-idf-codeowners/tools
|
||||
|
||||
/tools/test_build_system/ @esp-idf-codeowners/tools @esp-idf-codeowners/build-config
|
||||
|
||||
/tools/tools.json @esp-idf-codeowners/tools @esp-idf-codeowners/toolchain @esp-idf-codeowners/debugging
|
||||
|
||||
/tools/unit-test-app/ @esp-idf-codeowners/system @esp-idf-codeowners/tools
|
||||
|
||||
# sort-order-reset
|
||||
|
||||
/components/**/test_apps/**/*.py @esp-idf-codeowners/ci @esp-idf-codeowners/tools
|
||||
|
||||
# ignore lists
|
||||
/tools/ci/check_copyright_config.yaml @esp-idf-codeowners/all-maintainers
|
||||
/tools/ci/check_copyright_ignore.txt @esp-idf-codeowners/all-maintainers
|
||||
/tools/ci/mypy_ignore_list.txt @esp-idf-codeowners/tools
|
||||
|
||||
@@ -234,10 +234,10 @@ pytest_build_system_macos:
|
||||
- macos_shell
|
||||
parallel: 3
|
||||
variables:
|
||||
PYENV_VERSION: "3.8"
|
||||
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.
|
||||
build_docker:
|
||||
extends:
|
||||
- .before_script:minimal
|
||||
|
||||
@@ -6,9 +6,9 @@ stages:
|
||||
- pre_check
|
||||
- build
|
||||
- assign_test
|
||||
- build_doc
|
||||
- target_test
|
||||
- host_test
|
||||
- build_doc
|
||||
- test_deploy
|
||||
- deploy
|
||||
- post_deploy
|
||||
@@ -40,7 +40,7 @@ variables:
|
||||
GIT_FETCH_EXTRA_FLAGS: "--no-recurse-submodules --prune --prune-tags"
|
||||
# we're using .cache folder for caches
|
||||
GIT_CLEAN_FLAGS: -ffdx -e .cache/
|
||||
LATEST_GIT_TAG: v5.4.3
|
||||
LATEST_GIT_TAG: v5.5-dev
|
||||
|
||||
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-v5.4:2"
|
||||
ESP_IDF_DOC_ENV_IMAGE: "${CI_DOCKER_REGISTRY}/esp-idf-doc-env-v5.4:2-1"
|
||||
TARGET_TEST_ENV_IMAGE: "${CI_DOCKER_REGISTRY}/target-test-env-v5.4:2"
|
||||
ESP_ENV_IMAGE: "${CI_DOCKER_REGISTRY}/esp-env-v5.5:2"
|
||||
ESP_IDF_DOC_ENV_IMAGE: "${CI_DOCKER_REGISTRY}/esp-idf-doc-env-v5.5:2-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.v5.4.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.
|
||||
@@ -88,7 +88,7 @@ variables:
|
||||
CI_CLANG_DISTRO_URL: ""
|
||||
|
||||
# Set this variable to specify the file name for the known failure cases.
|
||||
KNOWN_FAILURE_CASES_FILE_NAME: "5.4.txt"
|
||||
KNOWN_FAILURE_CASES_FILE_NAME: "master.txt"
|
||||
|
||||
IDF_CI_BUILD: 1
|
||||
|
||||
@@ -191,21 +191,13 @@ variables:
|
||||
fi
|
||||
|
||||
# Custom OpenOCD
|
||||
if [[ "$CI_JOB_STAGE" == "target_test" ]]; then
|
||||
machine="$(uname -m)"
|
||||
if [[ "$machine" == "armv7l" ]] ; then
|
||||
OOCD_DISTRO_URL="$OOCD_DISTRO_URL_ARMHF"
|
||||
elif [[ "$machine" == "aarch64" ]] ; then
|
||||
OOCD_DISTRO_URL="$OOCD_DISTRO_URL_ARM64"
|
||||
fi
|
||||
if [[ ! -z "$OOCD_DISTRO_URL" ]]; then
|
||||
echo "Using custom OpenOCD from ${OOCD_DISTRO_URL}"
|
||||
wget $OOCD_DISTRO_URL
|
||||
ARCH_NAME=$(basename $OOCD_DISTRO_URL)
|
||||
tar -x -f $ARCH_NAME
|
||||
export OPENOCD_SCRIPTS=$PWD/openocd-esp32/share/openocd/scripts
|
||||
export PATH=$PWD/openocd-esp32/bin:$PATH
|
||||
fi
|
||||
if [[ ! -z "$OOCD_DISTRO_URL" && "$CI_JOB_STAGE" == "target_test" ]]; then
|
||||
echo "Using custom OpenOCD from ${OOCD_DISTRO_URL}"
|
||||
wget $OOCD_DISTRO_URL
|
||||
ARCH_NAME=$(basename $OOCD_DISTRO_URL)
|
||||
tar -x -f $ARCH_NAME
|
||||
export OPENOCD_SCRIPTS=$PWD/openocd-esp32/share/openocd/scripts
|
||||
export PATH=$PWD/openocd-esp32/bin:$PATH
|
||||
fi
|
||||
|
||||
if [[ -n "$CI_PYTHON_TOOL_REPO" ]]; then
|
||||
@@ -327,26 +319,32 @@ variables:
|
||||
- *git_init
|
||||
- *git_fetch_from_mirror_url_if_exists
|
||||
- |
|
||||
# Store the diff output in a temporary file
|
||||
TEMP_FILE=$(mktemp)
|
||||
# merged results pipelines, by default
|
||||
if [[ -n $CI_MERGE_REQUEST_SOURCE_BRANCH_SHA ]]; then
|
||||
git fetch origin $CI_MERGE_REQUEST_DIFF_BASE_SHA --depth=1 ${GIT_FETCH_EXTRA_FLAGS}
|
||||
git fetch origin $CI_MERGE_REQUEST_SOURCE_BRANCH_SHA --depth=1 ${GIT_FETCH_EXTRA_FLAGS}
|
||||
export GIT_DIFF_OUTPUT=$(git diff --name-only $CI_MERGE_REQUEST_DIFF_BASE_SHA $CI_MERGE_REQUEST_SOURCE_BRANCH_SHA)
|
||||
git diff --name-only $CI_MERGE_REQUEST_DIFF_BASE_SHA $CI_MERGE_REQUEST_SOURCE_BRANCH_SHA > "$TEMP_FILE"
|
||||
GIT_DIFF_OUTPUT=$(cat "$TEMP_FILE")
|
||||
git fetch origin $CI_COMMIT_SHA --depth=1 ${GIT_FETCH_EXTRA_FLAGS}
|
||||
# merge request pipelines, when the mr got conflicts
|
||||
elif [[ -n $CI_MERGE_REQUEST_DIFF_BASE_SHA ]]; then
|
||||
git fetch origin $CI_MERGE_REQUEST_DIFF_BASE_SHA --depth=1 ${GIT_FETCH_EXTRA_FLAGS}
|
||||
git fetch origin $CI_COMMIT_SHA --depth=1 ${GIT_FETCH_EXTRA_FLAGS}
|
||||
export GIT_DIFF_OUTPUT=$(git diff --name-only $CI_MERGE_REQUEST_DIFF_BASE_SHA $CI_COMMIT_SHA)
|
||||
git diff --name-only $CI_MERGE_REQUEST_DIFF_BASE_SHA $CI_COMMIT_SHA > "$TEMP_FILE"
|
||||
GIT_DIFF_OUTPUT=$(cat "$TEMP_FILE")
|
||||
# other pipelines, like the protected branches pipelines
|
||||
elif [[ "$CI_COMMIT_BEFORE_SHA" != "0000000000000000000000000000000000000000" ]]; then
|
||||
git fetch origin $CI_COMMIT_BEFORE_SHA --depth=1 ${GIT_FETCH_EXTRA_FLAGS}
|
||||
git fetch origin $CI_COMMIT_SHA --depth=1 ${GIT_FETCH_EXTRA_FLAGS}
|
||||
export GIT_DIFF_OUTPUT=$(git diff --name-only $CI_COMMIT_BEFORE_SHA $CI_COMMIT_SHA)
|
||||
git diff --name-only $CI_COMMIT_BEFORE_SHA $CI_COMMIT_SHA > "$TEMP_FILE"
|
||||
GIT_DIFF_OUTPUT=$(cat "$TEMP_FILE")
|
||||
else
|
||||
# pipeline source could be web, scheduler, etc.
|
||||
git fetch origin $CI_COMMIT_SHA --depth=2 ${GIT_FETCH_EXTRA_FLAGS}
|
||||
export GIT_DIFF_OUTPUT=$(git diff --name-only $CI_COMMIT_SHA~1 $CI_COMMIT_SHA)
|
||||
git diff --name-only $CI_COMMIT_SHA~1 $CI_COMMIT_SHA > "$TEMP_FILE"
|
||||
GIT_DIFF_OUTPUT=$(cat "$TEMP_FILE")
|
||||
fi
|
||||
- *git_checkout_ci_commit_sha
|
||||
- *common-before_scripts
|
||||
|
||||
@@ -7,12 +7,11 @@
|
||||
#
|
||||
# This file should ONLY be used during bringup. Should be reset to empty after the bringup process
|
||||
extra_default_build_targets:
|
||||
|
||||
|
||||
bypass_check_test_targets:
|
||||
- esp32c5
|
||||
- esp32c61
|
||||
|
||||
bypass_check_test_targets:
|
||||
|
||||
#
|
||||
# These lines would
|
||||
# - enable the README.md check for esp32c6. Don't forget to add the build jobs in .gitlab/ci/build.yml
|
||||
|
||||
@@ -19,7 +19,6 @@ check_submodule_sync:
|
||||
dependencies: []
|
||||
script:
|
||||
- git submodule deinit --force .
|
||||
- rm -rf .git/modules # remove all the cached metadata
|
||||
# setting the default remote URL to the public one, to resolve relative location URLs
|
||||
- git config remote.origin.url ${PUBLIC_IDF_URL}
|
||||
# check if all submodules are correctly synced to public repository
|
||||
|
||||
@@ -37,16 +37,25 @@
|
||||
.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"'
|
||||
|
||||
.doc-rules:build:docs-full:
|
||||
rules:
|
||||
- <<: *if-qa-test-tag
|
||||
when: never
|
||||
- <<: *if-protected
|
||||
- <<: *if-schedule
|
||||
- <<: *if-label-build_docs
|
||||
- <<: *if-label-docs_full
|
||||
- <<: *if-dev-push
|
||||
changes: *patterns-docs-full
|
||||
|
||||
.doc-rules:build:docs-full-prod:
|
||||
rules:
|
||||
- <<: *if-qa-test-tag
|
||||
when: never
|
||||
- <<: *if-protected-no_label
|
||||
|
||||
.doc-rules:build:docs-partial:
|
||||
rules:
|
||||
- <<: *if-qa-test-tag
|
||||
@@ -83,14 +92,13 @@ check_docs_lang_sync:
|
||||
stage: build_doc
|
||||
tags:
|
||||
- build_docs
|
||||
needs:
|
||||
- job: fast_template_app
|
||||
artifacts: false
|
||||
optional: true
|
||||
script:
|
||||
- if [ -n "${BREATHE_ALT_INSTALL_URL}" ]; then pip uninstall -y breathe && pip install -U ${BREATHE_ALT_INSTALL_URL}; fi
|
||||
- cd docs
|
||||
- build-docs -t $DOCTGT -bs $DOC_BUILDERS -l $DOCLANG build
|
||||
artifacts:
|
||||
expire_in: 4 days
|
||||
when: always
|
||||
parallel:
|
||||
matrix:
|
||||
- DOCLANG: ["en", "zh_CN"]
|
||||
@@ -111,12 +119,26 @@ build_docs_html_full:
|
||||
extends:
|
||||
- .build_docs_template
|
||||
- .doc-rules:build:docs-full
|
||||
needs:
|
||||
- job: fast_template_app
|
||||
artifacts: false
|
||||
optional: true
|
||||
artifacts:
|
||||
paths:
|
||||
- docs/_build/*/*/*.txt
|
||||
- docs/_build/*/*/html/*
|
||||
variables:
|
||||
DOC_BUILDERS: "html"
|
||||
|
||||
build_docs_html_full_prod:
|
||||
extends:
|
||||
- .build_docs_template
|
||||
- .doc-rules:build:docs-full-prod
|
||||
dependencies: [] # Stop build_docs jobs from downloading all previous job's artifacts
|
||||
artifacts:
|
||||
when: always
|
||||
paths:
|
||||
- docs/_build/*/*/*.txt
|
||||
- docs/_build/*/*/html/*
|
||||
expire_in: 4 days
|
||||
variables:
|
||||
DOC_BUILDERS: "html"
|
||||
|
||||
@@ -124,12 +146,14 @@ build_docs_html_partial:
|
||||
extends:
|
||||
- .build_docs_template
|
||||
- .doc-rules:build:docs-partial
|
||||
needs:
|
||||
- job: fast_template_app
|
||||
artifacts: false
|
||||
optional: true
|
||||
artifacts:
|
||||
when: always
|
||||
paths:
|
||||
- docs/_build/*/*/*.txt
|
||||
- docs/_build/*/*/html/*
|
||||
expire_in: 4 days
|
||||
variables:
|
||||
DOC_BUILDERS: "html"
|
||||
parallel:
|
||||
@@ -139,21 +163,43 @@ build_docs_html_partial:
|
||||
- DOCLANG: "zh_CN"
|
||||
DOCTGT: "esp32p4"
|
||||
|
||||
build_docs_pdf:
|
||||
extends:
|
||||
- .build_docs_template
|
||||
- .doc-rules:build:docs-full
|
||||
needs:
|
||||
- job: fast_template_app
|
||||
artifacts: false
|
||||
optional: true
|
||||
allow_failure: true # TODO IDFCI-2216
|
||||
artifacts:
|
||||
paths:
|
||||
- docs/_build/*/*/latex/*
|
||||
variables:
|
||||
DOC_BUILDERS: "latex"
|
||||
|
||||
build_docs_pdf_prod:
|
||||
extends:
|
||||
- .build_docs_template
|
||||
- .doc-rules:build:docs-full-prod
|
||||
dependencies: [] # Stop build_docs jobs from downloading all previous job's artifacts
|
||||
allow_failure: true # TODO IDFCI-2216
|
||||
artifacts:
|
||||
paths:
|
||||
- docs/_build/*/*/latex/*
|
||||
variables:
|
||||
DOC_BUILDERS: "latex"
|
||||
|
||||
.deploy_docs_template:
|
||||
image: $ESP_IDF_DOC_ENV_IMAGE
|
||||
variables:
|
||||
DOCS_BUILD_DIR: "${IDF_PATH}/docs/_build/"
|
||||
PYTHONUNBUFFERED: 1
|
||||
# ensure all tags are fetched, need to know the latest/stable tag for the docs
|
||||
GIT_STRATEGY: clone
|
||||
GIT_DEPTH: 0
|
||||
stage: test_deploy
|
||||
tags:
|
||||
- deploy
|
||||
- shiny
|
||||
script:
|
||||
# ensure all tags are fetched, need to know the latest/stable tag for the docs
|
||||
- git fetch --tags --prune
|
||||
- add_doc_server_ssh_keys $DOCS_DEPLOY_PRIVATEKEY $DOCS_DEPLOY_SERVER $DOCS_DEPLOY_SERVER_USER
|
||||
- export GIT_VER=$(git describe --always ${PIPELINE_COMMIT_SHA} --)
|
||||
- deploy-docs
|
||||
@@ -172,6 +218,8 @@ deploy_docs_preview:
|
||||
optional: true
|
||||
- job: build_docs_html_full
|
||||
optional: true
|
||||
- job: build_docs_pdf
|
||||
optional: true
|
||||
variables:
|
||||
TYPE: "preview"
|
||||
# older branches use DOCS_DEPLOY_KEY, DOCS_SERVER, DOCS_SERVER_USER, DOCS_PATH for preview server so we keep these names for 'preview'
|
||||
@@ -186,12 +234,12 @@ 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:
|
||||
- <<: *if-protected-no_label
|
||||
- .doc-rules:build:docs-full-prod
|
||||
stage: post_deploy
|
||||
dependencies: # set dependencies to null to avoid missing artifacts issue
|
||||
needs: # ensure runs after push_to_github succeeded
|
||||
- build_docs_html_full
|
||||
- build_docs_html_full_prod
|
||||
- build_docs_pdf_prod
|
||||
- job: push_to_github
|
||||
artifacts: false
|
||||
variables:
|
||||
@@ -206,19 +254,16 @@ deploy_docs_production:
|
||||
check_doc_links:
|
||||
extends:
|
||||
- .build_docs_template
|
||||
rules:
|
||||
- <<: *if-protected-no_label
|
||||
- .doc-rules:build:docs-full-prod
|
||||
stage: post_deploy
|
||||
needs:
|
||||
- job: deploy_docs_production
|
||||
artifacts: false
|
||||
tags: ["build", "amd64", "internet"]
|
||||
artifacts:
|
||||
when: always
|
||||
paths:
|
||||
- docs/_build/*/*/*.txt
|
||||
- docs/_build/*/*/linkcheck/*.txt
|
||||
expire_in: 1 week
|
||||
allow_failure: true
|
||||
script:
|
||||
- cd docs
|
||||
|
||||
@@ -111,8 +111,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
|
||||
@@ -234,7 +233,6 @@ test_mqtt_on_host:
|
||||
|
||||
test_transport_on_host:
|
||||
extends: .host_test_template
|
||||
allow_failure: true # IDFCI-2781 [v5.5, v5.4] test_transport_on_host fails on ubuntu 24.04
|
||||
script:
|
||||
- cd ${IDF_PATH}/components/tcp_transport/host_test
|
||||
- idf.py build
|
||||
@@ -349,6 +347,7 @@ test_pytest_macos:
|
||||
reports:
|
||||
junit: XUNIT_RESULT.xml
|
||||
variables:
|
||||
PYENV_VERSION: "3.9"
|
||||
PYTEST_IGNORE_COLLECT_IMPORT_ERROR: "1"
|
||||
script:
|
||||
- run_cmd python tools/ci/ci_build_apps.py components examples tools/test_apps -v
|
||||
@@ -400,17 +399,6 @@ test_nvs_gen_check:
|
||||
- cd ${IDF_PATH}/components/nvs_flash/nvs_partition_tool
|
||||
- pytest --noconftest test_nvs_gen_check.py --junitxml=XUNIT_RESULT.xml
|
||||
|
||||
test_esp_rom:
|
||||
extends: .host_test_template
|
||||
artifacts:
|
||||
paths:
|
||||
- XUNIT_RESULT.xml
|
||||
reports:
|
||||
junit: XUNIT_RESULT.xml
|
||||
script:
|
||||
- cd ${IDF_PATH}/components/esp_rom/
|
||||
- pytest --noconftest test_esp_rom.py --junitxml=XUNIT_RESULT.xml
|
||||
|
||||
make_sure_soc_caps_compatible_in_idf_build_apps:
|
||||
extends:
|
||||
- .host_test_template
|
||||
|
||||
@@ -165,8 +165,6 @@ pipeline_variables:
|
||||
if [ -n "$CI_PYTHON_CONSTRAINT_BRANCH" ]; then
|
||||
echo "BUILD_AND_TEST_ALL_APPS=1" >> pipeline.env
|
||||
fi
|
||||
- echo "OOCD_DISTRO_URL_ARMHF=$OOCD_DISTRO_URL_ARMHF" >> pipeline.env
|
||||
- echo "OOCD_DISTRO_URL_ARM64=$OOCD_DISTRO_URL_ARM64" >> pipeline.env
|
||||
- python tools/ci/ci_process_description.py
|
||||
- cat pipeline.env
|
||||
- python tools/ci/artifacts_handler.py upload --type modified_files_and_components_report
|
||||
|
||||
@@ -31,8 +31,7 @@ test_cli_installer_win:
|
||||
IDF_PATH: "$CI_PROJECT_DIR"
|
||||
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
|
||||
|
||||
6
.gitmodules
vendored
6
.gitmodules
vendored
@@ -49,13 +49,13 @@
|
||||
[submodule "components/json/cJSON"]
|
||||
path = components/json/cJSON
|
||||
url = ../../DaveGamble/cJSON.git
|
||||
sbom-version = 1.7.19
|
||||
sbom-version = 1.7.18
|
||||
sbom-cpe = cpe:2.3:a:cjson_project:cjson:{}:*:*:*:*:*:*:*
|
||||
sbom-cpe = cpe:2.3:a:davegamble:cjson:{}:*:*:*:*:*:*:*
|
||||
sbom-supplier = Person: Dave Gamble
|
||||
sbom-url = https://github.com/DaveGamble/cJSON
|
||||
sbom-description = Ultralightweight JSON parser in ANSI C
|
||||
sbom-hash = c859b25da02955fef659d658b8f324b5cde87be3
|
||||
sbom-hash = acc76239bee01d8e9c858ae2cab296704e52d916
|
||||
sbom-cve-exclude-list = CVE-2024-31755 Resolved in v1.7.18
|
||||
|
||||
[submodule "components/mbedtls/mbedtls"]
|
||||
path = components/mbedtls/mbedtls
|
||||
|
||||
@@ -23,8 +23,7 @@ repos:
|
||||
.*.pb-c.h|
|
||||
.*.pb-c.c|
|
||||
.*.yuv|
|
||||
.*.rgb|
|
||||
docs/sphinx-known-warnings\.txt
|
||||
.*.rgb
|
||||
)$
|
||||
- id: end-of-file-fixer
|
||||
exclude: *whitespace_excludes
|
||||
@@ -57,7 +56,6 @@ repos:
|
||||
rev: v2.3.0
|
||||
hooks:
|
||||
- id: codespell
|
||||
exclude: ^docs/sphinx-known-warnings\.txt$
|
||||
- repo: local
|
||||
hooks:
|
||||
- id: check-executables
|
||||
@@ -72,6 +70,11 @@ repos:
|
||||
language: python
|
||||
pass_filenames: false
|
||||
always_run: true
|
||||
- id: check-deprecated-kconfigs-options
|
||||
name: Check if any Kconfig Options Deprecated
|
||||
entry: tools/ci/check_deprecated_kconfigs.py
|
||||
language: python
|
||||
files: 'sdkconfig\.ci$|sdkconfig\.rename$|sdkconfig.*$'
|
||||
- id: cmake-lint
|
||||
name: Check CMake Files Format
|
||||
entry: cmakelint --linelength=120 --spaces=4 --filter=-whitespace/indent
|
||||
@@ -151,7 +154,7 @@ repos:
|
||||
require_serial: true
|
||||
additional_dependencies:
|
||||
- PyYAML == 5.3.1
|
||||
- idf-build-apps~=2.5
|
||||
- idf-build-apps~=2.0
|
||||
- id: sort-yaml-files
|
||||
name: sort yaml files
|
||||
entry: tools/ci/sort_yaml.py
|
||||
@@ -238,7 +241,6 @@ repos:
|
||||
name: Lint rST files in docs folder using Sphinx Lint
|
||||
files: ^(docs/en|docs/zh_CN)/.*\.(rst|inc)$
|
||||
- repo: https://github.com/espressif/esp-idf-kconfig.git
|
||||
rev: v2.5.0
|
||||
rev: v2.3.0
|
||||
hooks:
|
||||
- id: check-kconfig-files
|
||||
- id: check-deprecated-kconfig-options
|
||||
|
||||
10
Kconfig
10
Kconfig
@@ -136,6 +136,14 @@ mainmenu "Espressif IoT Development Framework Configuration"
|
||||
select FREERTOS_UNICORE
|
||||
select IDF_TARGET_ARCH_RISCV
|
||||
|
||||
config IDF_TARGET_ESP32H21
|
||||
bool
|
||||
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_LINUX
|
||||
bool
|
||||
default "y" if IDF_TARGET="linux"
|
||||
@@ -152,6 +160,7 @@ mainmenu "Espressif IoT Development Framework Configuration"
|
||||
default 0x0012 if IDF_TARGET_ESP32P4
|
||||
default 0x0017 if IDF_TARGET_ESP32C5
|
||||
default 0x0014 if IDF_TARGET_ESP32C61
|
||||
default 0x0019 if IDF_TARGET_ESP32H21
|
||||
default 0xFFFF
|
||||
|
||||
|
||||
@@ -678,4 +687,5 @@ mainmenu "Espressif IoT Development Framework Configuration"
|
||||
- CONFIG_BOOTLOADER_CACHE_32BIT_ADDR_QUAD_FLASH
|
||||
- CONFIG_ESP_WIFI_EAP_TLS1_3
|
||||
- CONFIG_ESP_WIFI_ENABLE_ROAMING_APP
|
||||
- CONFIG_USB_HOST_EXT_PORT_SUPPORT_LS
|
||||
- CONFIG_USB_HOST_EXT_PORT_RESET_ATTEMPTS
|
||||
|
||||
@@ -121,16 +121,3 @@ if(CONFIG_APPTRACE_GCOV_ENABLE)
|
||||
else()
|
||||
target_link_libraries(${COMPONENT_LIB} INTERFACE $<TARGET_FILE:${app_trace}> c)
|
||||
endif()
|
||||
|
||||
# This function adds a dependency on the given component if the component is included into the build.
|
||||
function(maybe_add_component component_name)
|
||||
idf_build_get_property(components BUILD_COMPONENTS)
|
||||
if(${component_name} IN_LIST components)
|
||||
idf_component_get_property(lib_name ${component_name} COMPONENT_LIB)
|
||||
target_link_libraries(${COMPONENT_LIB} PUBLIC ${lib_name})
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
if(CONFIG_APPTRACE_DEST_UART0 OR CONFIG_APPTRACE_DEST_UART1 OR CONFIG_APPTRACE_DEST_UART2)
|
||||
maybe_add_component(driver)
|
||||
endif()
|
||||
|
||||
@@ -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 OR MIT
|
||||
*/
|
||||
@@ -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;
|
||||
@@ -148,18 +148,6 @@ static esp_err_t esp_apptrace_membufs_swap_waitus(esp_apptrace_membufs_proto_dat
|
||||
if (res != ESP_OK) {
|
||||
break;
|
||||
}
|
||||
#if CONFIG_IDF_TARGET_ESP32S3
|
||||
/*
|
||||
* ESP32S3 has a serious data corruption issue with the transferred data to host.
|
||||
* This delay helps reduce the failure rate by temporarily reducing heavy memory writes
|
||||
* from RTOS-level tracing and giving OpenOCD more time to read trace memory before
|
||||
* the current thread continues execution. While this doesn't completely prevent
|
||||
* memory access from other threads/cores/ISRs, it has shown to significantly improve
|
||||
* reliability when combined with CRC checks in OpenOCD. In practice, this reduces the
|
||||
* number of retries needed to read an entire block without corruption.
|
||||
*/
|
||||
esp_rom_delay_us(100);
|
||||
#endif
|
||||
}
|
||||
return res;
|
||||
}
|
||||
@@ -351,7 +339,7 @@ uint8_t *esp_apptrace_membufs_up_buffer_get(esp_apptrace_membufs_proto_data_t *p
|
||||
esp_err_t esp_apptrace_membufs_up_buffer_put(esp_apptrace_membufs_proto_data_t *proto, uint8_t *ptr, esp_apptrace_tmo_t *tmo)
|
||||
{
|
||||
esp_apptrace_membufs_pkt_end(ptr);
|
||||
// TODO: mark block as busy in order not to reuse it for other tracing calls until it is completely written
|
||||
// TODO: mark block as busy in order not to re-use it for other tracing calls until it is completely written
|
||||
// TODO: avoid potential situation when all memory is consumed by low prio tasks which can not complete writing due to
|
||||
// higher prio tasks and the latter can not allocate buffers at all
|
||||
// this is abnormal situation can be detected on host which will receive only uncompleted buffers
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2017-2021 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2017-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -218,6 +218,13 @@ static esp_err_t esp_apptrace_uart_init(esp_apptrace_uart_data_t *hw_data)
|
||||
hw_data->message_buff_overflow = false;
|
||||
hw_data->circular_buff_overflow = false;
|
||||
|
||||
assert((hw_data->port_num <= SOC_UART_NUM) && "Not possible to configure UART. Please check selected UART port");
|
||||
|
||||
int source_clk = UART_SCLK_DEFAULT;
|
||||
#if SOC_UART_LP_NUM > 0
|
||||
if (hw_data->port_num >= SOC_UART_HP_NUM)
|
||||
source_clk = LP_UART_SCLK_DEFAULT;
|
||||
#endif
|
||||
|
||||
const uart_config_t uart_config = {
|
||||
.baud_rate = CONFIG_APPTRACE_UART_BAUDRATE,
|
||||
@@ -225,7 +232,7 @@ static esp_err_t esp_apptrace_uart_init(esp_apptrace_uart_data_t *hw_data)
|
||||
.parity = UART_PARITY_DISABLE,
|
||||
.stop_bits = UART_STOP_BITS_1,
|
||||
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
|
||||
.source_clk = UART_SCLK_DEFAULT,
|
||||
.source_clk = source_clk,
|
||||
};
|
||||
ESP_LOGI(TAG, "UART baud rate: %i", CONFIG_APPTRACE_UART_BAUDRATE);
|
||||
// We won't use a buffer for sending data.
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 OR MIT
|
||||
*/
|
||||
@@ -12,7 +12,7 @@
|
||||
// ======================
|
||||
|
||||
// Xtensa has useful feature: TRAX debug module. It allows recording program execution flow at run-time without disturbing CPU.
|
||||
// Execution flow data are written to configurable Trace RAM block. Besides accessing Trace RAM itself TRAX module also allows to read/write
|
||||
// Exectution flow data are written to configurable Trace RAM block. Besides accessing Trace RAM itself TRAX module also allows to read/write
|
||||
// trace memory via its registers by means of JTAG, APB or ERI transactions.
|
||||
// ESP32 has two Xtensa cores with separate TRAX modules on them and provides two special memory regions to be used as trace memory.
|
||||
// Chip allows muxing access to those trace memory blocks in such a way that while one block is accessed by CPUs another one can be accessed by host
|
||||
@@ -47,7 +47,7 @@
|
||||
// 2. TRAX Registers layout
|
||||
// ========================
|
||||
|
||||
// This module uses two TRAX HW registers and one Performance Monitor register to communicate with host SW (OpenOCD).
|
||||
// This module uses two TRAX HW registers to communicate with host SW (OpenOCD).
|
||||
// - Control register uses TRAX_DELAYCNT as storage. Only lower 24 bits of TRAX_DELAYCNT are writable. Control register has the following bitfields:
|
||||
// | 31..XXXXXX..24 | 23 .(host_connect). 23| 22..(block_id)..15 | 14..(block_len)..0 |
|
||||
// 14..0 bits - actual length of user data in trace memory block. Target updates it every time it fills memory block and exposes it to host.
|
||||
@@ -55,15 +55,9 @@
|
||||
// 21..15 bits - trace memory block transfer ID. Block counter. It can overflow. Updated by target, host should not modify it. Actually can be 2 bits;
|
||||
// 22 bit - 'host data present' flag. If set to one there is data from host, otherwise - no host data;
|
||||
// 23 bit - 'host connected' flag. If zero then host is not connected and tracing module works in post-mortem mode, otherwise in streaming mode;
|
||||
// - Status register uses TRAX_TRIGGERPC as storage. If this register is not zero then current CPU is changing TRAX registers and
|
||||
// this register holds address of the instruction which application will execute when it finishes with those registers modifications.
|
||||
// See 'Targets Connection' section for details.
|
||||
// - CRC16 register uses ERI_PERFMON_PM1 as storage. This register is used to store CRC16 checksum of the exposed trace memory block.
|
||||
// The register has the following format:
|
||||
// | 31..16 (CRC indicator) | 15..0 (CRC16 value) |
|
||||
// CRC indicator (0xA55A) is used to distinguish valid CRC values from other data that might be in the register.
|
||||
// CRC16 is calculated over the entire exposed block and is updated every time a block is exposed to the host.
|
||||
// This allows the host to verify data integrity of the received trace data.
|
||||
// - Status register uses TRAX_TRIGGERPC as storage. If this register is not zero then current CPU is changing TRAX registers and
|
||||
// this register holds address of the instruction which application will execute when it finishes with those registers modifications.
|
||||
// See 'Targets Connection' setion for details.
|
||||
|
||||
// 3. Modes of operation
|
||||
// =====================
|
||||
@@ -133,7 +127,7 @@
|
||||
|
||||
// Access to internal module's data is synchronized with custom mutex. Mutex is a wrapper for portMUX_TYPE and uses almost the same sync mechanism as in
|
||||
// vPortCPUAcquireMutex/vPortCPUReleaseMutex. The mechanism uses S32C1I Xtensa instruction to implement exclusive access to module's data from tasks and
|
||||
// ISRs running on both cores. Also custom mutex allows specifying timeout for locking operation. Locking routine checks underlying mutex in cycle until
|
||||
// ISRs running on both cores. Also custom mutex allows specifying timeout for locking operation. Locking routine checks underlaying mutex in cycle until
|
||||
// it gets its ownership or timeout expires. The differences of application tracing module's mutex implementation from vPortCPUAcquireMutex/vPortCPUReleaseMutex are:
|
||||
// - Support for timeouts.
|
||||
// - Local IRQs for CPU which owns the mutex are disabled till the call to unlocking routine. This is made to avoid possible task's prio inversion.
|
||||
@@ -148,9 +142,9 @@
|
||||
|
||||
// Timeout mechanism is based on xthal_get_ccount() routine and supports timeout values in microseconds.
|
||||
// There are two situations when task/ISR can be delayed by tracing API call. Timeout mechanism takes into account both conditions:
|
||||
// - Trace data are locked by another task/ISR. When waiting on trace data lock.
|
||||
// - Trace data are locked by another task/ISR. When wating on trace data lock.
|
||||
// - Current TRAX memory input block is full when working in streaming mode (host is connected). When waiting for host to complete previous block reading.
|
||||
// When waiting for any of above conditions xthal_get_ccount() is called periodically to calculate time elapsed from trace API routine entry. When elapsed
|
||||
// When wating for any of above conditions xthal_get_ccount() is called periodically to calculate time elapsed from trace API routine entry. When elapsed
|
||||
// time exceeds specified timeout value operation is canceled and ESP_ERR_TIMEOUT code is returned.
|
||||
#include "sdkconfig.h"
|
||||
#include "soc/soc.h"
|
||||
@@ -165,15 +159,11 @@
|
||||
#include "esp_log.h"
|
||||
#include "esp_app_trace_membufs_proto.h"
|
||||
#include "esp_app_trace_port.h"
|
||||
#include "esp_rom_crc.h"
|
||||
|
||||
// TRAX is disabled, so we use its registers for our own purposes
|
||||
// | 31..XXXXXX..24 | 23 .(host_connect). 23 | 22 .(host_data). 22| 21..(block_id)..15 | 14..(block_len)..0 |
|
||||
#define ESP_APPTRACE_TRAX_CTRL_REG ERI_TRAX_DELAYCNT
|
||||
#define ESP_APPTRACE_TRAX_STAT_REG ERI_TRAX_TRIGGERPC
|
||||
#define ESP_APPTRACE_TRAX_CRC16_REG ERI_PERFMON_PM1
|
||||
|
||||
#define ESP_APPTRACE_CRC_INDICATOR (0xA55AU << 16)
|
||||
|
||||
#define ESP_APPTRACE_TRAX_BLOCK_LEN_MSK 0x7FFFUL
|
||||
#define ESP_APPTRACE_TRAX_BLOCK_LEN(_l_) ((_l_) & ESP_APPTRACE_TRAX_BLOCK_LEN_MSK)
|
||||
@@ -208,7 +198,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);
|
||||
|
||||
@@ -508,8 +498,7 @@ static esp_err_t esp_apptrace_trax_buffer_swap_start(uint32_t curr_block_id)
|
||||
uint32_t acked_block = ESP_APPTRACE_TRAX_BLOCK_ID_GET(ctrl_reg);
|
||||
uint32_t host_to_read = ESP_APPTRACE_TRAX_BLOCK_LEN_GET(ctrl_reg);
|
||||
if (host_to_read != 0 || acked_block != (curr_block_id & ESP_APPTRACE_TRAX_BLOCK_ID_MSK)) {
|
||||
ESP_APPTRACE_LOGD("HC[%d]: Can not switch %" PRIx32 " %" PRIu32 " %" PRIx32 " %" PRIx32 "/%" PRIx32,
|
||||
esp_cpu_get_core_id(), ctrl_reg, host_to_read, acked_block,
|
||||
ESP_APPTRACE_LOGD("HC[%d]: Can not switch %" PRIx32 " %" PRIu32 " %" PRIx32 " %" PRIx32 "/%" PRIx32, esp_cpu_get_core_id(), ctrl_reg, host_to_read, acked_block,
|
||||
curr_block_id & ESP_APPTRACE_TRAX_BLOCK_ID_MSK, curr_block_id);
|
||||
res = ESP_ERR_NO_MEM;
|
||||
goto _on_err;
|
||||
@@ -525,22 +514,14 @@ 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)
|
||||
static esp_err_t esp_apptrace_trax_buffer_swap(uint32_t new_block_id)
|
||||
{
|
||||
/* Before switching to the new block, calculate CRC16 of the current 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);
|
||||
}
|
||||
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;
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
* The Embedded Experts *
|
||||
**********************************************************************
|
||||
* *
|
||||
* (c) 1995 - 2024 SEGGER Microcontroller GmbH *
|
||||
* (c) 1995 - 2021 SEGGER Microcontroller GmbH *
|
||||
* *
|
||||
* www.segger.com Support: support@segger.com *
|
||||
* *
|
||||
@@ -49,7 +49,7 @@
|
||||
* *
|
||||
**********************************************************************
|
||||
* *
|
||||
* SystemView version: 3.56 *
|
||||
* SystemView version: 3.42 *
|
||||
* *
|
||||
**********************************************************************
|
||||
----------------------------------------------------------------------
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
* The Embedded Experts *
|
||||
**********************************************************************
|
||||
* *
|
||||
* (c) 1995 - 2024 SEGGER Microcontroller GmbH *
|
||||
* (c) 1995 - 2021 SEGGER Microcontroller GmbH *
|
||||
* *
|
||||
* www.segger.com Support: support@segger.com *
|
||||
* *
|
||||
@@ -47,7 +47,7 @@
|
||||
* *
|
||||
**********************************************************************
|
||||
* *
|
||||
* SystemView version: 3.56 *
|
||||
* SystemView version: 3.42 *
|
||||
* *
|
||||
**********************************************************************
|
||||
---------------------------END-OF-HEADER------------------------------
|
||||
@@ -100,10 +100,6 @@ Revision: $Rev: 25842 $
|
||||
#define _CORE_HAS_RTT_ASM_SUPPORT 1
|
||||
#define _CORE_NEEDS_DMB 1
|
||||
#define RTT__DMB() __asm volatile ("dmb\n" : : :);
|
||||
#elif (defined(__ARM_ARCH_8_1M_MAIN__)) // Cortex-M85
|
||||
#define _CORE_HAS_RTT_ASM_SUPPORT 1
|
||||
#define _CORE_NEEDS_DMB 1
|
||||
#define RTT__DMB() __asm volatile ("dmb\n" : : :);
|
||||
#else
|
||||
#define _CORE_HAS_RTT_ASM_SUPPORT 0
|
||||
#endif
|
||||
@@ -134,10 +130,6 @@ Revision: $Rev: 25842 $
|
||||
#define _CORE_HAS_RTT_ASM_SUPPORT 1
|
||||
#define _CORE_NEEDS_DMB 1
|
||||
#define RTT__DMB() __asm volatile ("dmb\n" : : :);
|
||||
#elif (defined __ARM_ARCH_8_1M_MAIN__) // Cortex-M85
|
||||
#define _CORE_HAS_RTT_ASM_SUPPORT 1
|
||||
#define _CORE_NEEDS_DMB 1
|
||||
#define RTT__DMB() __asm volatile ("dmb\n" : : :);
|
||||
#elif ((defined __ARM_ARCH_7A__) || (defined __ARM_ARCH_7R__)) // Cortex-A/R 32-bit ARMv7-A/R
|
||||
#define _CORE_NEEDS_DMB 1
|
||||
#define RTT__DMB() __asm volatile ("dmb\n" : : :);
|
||||
@@ -164,10 +156,6 @@ Revision: $Rev: 25842 $
|
||||
#define _CORE_HAS_RTT_ASM_SUPPORT 1
|
||||
#define _CORE_NEEDS_DMB 1
|
||||
#define RTT__DMB() __asm volatile ("dmb\n" : : :);
|
||||
#elif (defined __ARM_ARCH_8_1M_MAIN__) // Cortex-M85
|
||||
#define _CORE_HAS_RTT_ASM_SUPPORT 1
|
||||
#define _CORE_NEEDS_DMB 1
|
||||
#define RTT__DMB() __asm volatile ("dmb\n" : : :);
|
||||
#elif ((defined __ARM_ARCH_7A__) || (defined __ARM_ARCH_7R__)) // Cortex-A/R 32-bit ARMv7-A/R
|
||||
#define _CORE_NEEDS_DMB 1
|
||||
#define RTT__DMB() __asm volatile ("dmb\n" : : :);
|
||||
@@ -283,7 +271,6 @@ Revision: $Rev: 25842 $
|
||||
#ifndef SEGGER_RTT_ASM // defined when SEGGER_RTT.h is included from assembly file
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
@@ -425,7 +412,7 @@ unsigned SEGGER_RTT_ReadUpBufferNoLock (unsigned BufferIndex, void* pDa
|
||||
unsigned SEGGER_RTT_WriteDownBuffer (unsigned BufferIndex, const void* pBuffer, unsigned NumBytes);
|
||||
unsigned SEGGER_RTT_WriteDownBufferNoLock (unsigned BufferIndex, const void* pBuffer, unsigned NumBytes);
|
||||
|
||||
#define SEGGER_RTT_HASDATA_UP(n) (((SEGGER_RTT_BUFFER_UP*)((uintptr_t)&_SEGGER_RTT.aUp[n] + SEGGER_RTT_UNCACHED_OFF))->WrOff - ((SEGGER_RTT_BUFFER_UP*)((uintptr_t)&_SEGGER_RTT.aUp[n] + SEGGER_RTT_UNCACHED_OFF))->RdOff) // Access uncached to make sure we see changes made by the J-Link side and all of our changes go into HW directly
|
||||
#define SEGGER_RTT_HASDATA_UP(n) (((SEGGER_RTT_BUFFER_UP*)((char*)&_SEGGER_RTT.aUp[n] + SEGGER_RTT_UNCACHED_OFF))->WrOff - ((SEGGER_RTT_BUFFER_UP*)((char*)&_SEGGER_RTT.aUp[n] + SEGGER_RTT_UNCACHED_OFF))->RdOff) // Access uncached to make sure we see changes made by the J-Link side and all of our changes go into HW directly
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
|
||||
@@ -3,14 +3,14 @@
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-1-Clause
|
||||
*
|
||||
* SPDX-FileContributor: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileContributor: 2023 Espressif Systems (Shanghai) CO LTD
|
||||
*/
|
||||
/*********************************************************************
|
||||
* SEGGER Microcontroller GmbH *
|
||||
* The Embedded Experts *
|
||||
**********************************************************************
|
||||
* *
|
||||
* (c) 1995 - 2024 SEGGER Microcontroller GmbH *
|
||||
* (c) 1995 - 2021 SEGGER Microcontroller GmbH *
|
||||
* *
|
||||
* www.segger.com Support: support@segger.com *
|
||||
* *
|
||||
@@ -49,14 +49,14 @@
|
||||
* *
|
||||
**********************************************************************
|
||||
* *
|
||||
* SystemView version: 3.56 *
|
||||
* SystemView version: 3.42 *
|
||||
* *
|
||||
**********************************************************************
|
||||
-------------------------- END-OF-HEADER -----------------------------
|
||||
|
||||
File : SEGGER_SYSVIEW.c
|
||||
Purpose : System visualization API implementation.
|
||||
Revision: $Rev: 29105 $
|
||||
Revision: $Rev: 28341 $
|
||||
|
||||
Additional information:
|
||||
Packet format:
|
||||
@@ -66,10 +66,10 @@ Additional information:
|
||||
|
||||
Packets with IDs 24..31 are standard packets with extendible
|
||||
structure and contain a length field.
|
||||
<ID><Length><Data><TimeStampDelta>
|
||||
<ID><Lenght><Data><TimeStampDelta>
|
||||
|
||||
Packet ID 31 is used for SystemView extended events.
|
||||
<ID><Length><ID_EX><Data><TimeStampDelta>
|
||||
<ID><Lenght><ID_EX><Data><TimeStampDelta>
|
||||
|
||||
Packets with IDs >= 32 always contain a length field.
|
||||
<ID><Length><Data><TimeStampDelta>
|
||||
@@ -150,7 +150,6 @@ Additional information:
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <assert.h>
|
||||
#include "SEGGER_SYSVIEW_Int.h"
|
||||
#include "SEGGER_RTT.h"
|
||||
|
||||
@@ -189,7 +188,7 @@ Additional information:
|
||||
// Timestamps may be less than full 32-bits, in which case we need to zero
|
||||
// the unused bits to properly handle overflows.
|
||||
// Note that this is a quite common scenario, as a 32-bit time such as
|
||||
// SysTick might be scaled down to reduce bandwidth
|
||||
// SysTick might be scaled down to reduce bandwith
|
||||
// or a 16-bit hardware time might be used.
|
||||
#if SEGGER_SYSVIEW_TIMESTAMP_BITS < 32 // Eliminate unused bits in case hardware timestamps are less than 32 bits
|
||||
#define MAKE_DELTA_32BIT(Delta) Delta <<= 32 - SEGGER_SYSVIEW_TIMESTAMP_BITS; \
|
||||
@@ -389,6 +388,8 @@ static U8 _NumModules;
|
||||
pDest = pSysviewPointer; \
|
||||
};
|
||||
|
||||
|
||||
|
||||
#if (SEGGER_SYSVIEW_USE_STATIC_BUFFER == 1)
|
||||
static U8 _aPacket[SEGGER_SYSVIEW_MAX_PACKET_SIZE];
|
||||
|
||||
@@ -431,9 +432,6 @@ static U8 _aPacket[SEGGER_SYSVIEW_MAX_PACKET_SIZE];
|
||||
static U8* _EncodeData(U8* pPayload, const char* pSrc, unsigned int NumBytes) {
|
||||
unsigned int n;
|
||||
const U8* p;
|
||||
|
||||
// Espressif doesn't support larger packages yet. Encode data length must be less than 255.
|
||||
assert(NumBytes < 255);
|
||||
//
|
||||
n = 0;
|
||||
p = (const U8*)pSrc;
|
||||
@@ -444,8 +442,8 @@ static U8* _EncodeData(U8* pPayload, const char* pSrc, unsigned int NumBytes) {
|
||||
*pPayload++ = (U8)NumBytes;
|
||||
} else {
|
||||
*pPayload++ = 255;
|
||||
*pPayload++ = ((NumBytes >> 8) & 255);
|
||||
*pPayload++ = (NumBytes & 255);
|
||||
*pPayload++ = ((NumBytes >> 8) & 255);
|
||||
}
|
||||
while (n < NumBytes) {
|
||||
*pPayload++ = *p++;
|
||||
@@ -454,38 +452,6 @@ static U8* _EncodeData(U8* pPayload, const char* pSrc, unsigned int NumBytes) {
|
||||
return pPayload;
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* _EncodeFloat()
|
||||
*
|
||||
* Function description
|
||||
* Encode a float value in variable-length format.
|
||||
*
|
||||
* Parameters
|
||||
* pPayload - Pointer to where value will be encoded.
|
||||
* Value - Value to be encoded.
|
||||
*
|
||||
* Return value
|
||||
* Pointer to the byte following the value, i.e. the first free
|
||||
* byte in the payload and the next position to store payload
|
||||
* content.
|
||||
*/
|
||||
static U8* _EncodeFloat(U8* pPayload, float Value) {
|
||||
float Val = Value;
|
||||
U8* pSysviewPointer;
|
||||
U32* SysViewData;
|
||||
pSysviewPointer = pPayload;
|
||||
SysViewData = (U32*)&Val;
|
||||
while((*SysViewData) > 0x7F) {
|
||||
*pSysviewPointer++ = (U8)((*SysViewData) | 0x80);
|
||||
(*SysViewData) >>= 7;
|
||||
};
|
||||
*pSysviewPointer++ = (U8)(*SysViewData);
|
||||
pPayload = pSysviewPointer;
|
||||
|
||||
return pPayload;
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* _EncodeStr()
|
||||
@@ -509,42 +475,38 @@ static U8* _EncodeFloat(U8* pPayload, float Value) {
|
||||
* No more than 1 + Limit bytes will be encoded to the payload.
|
||||
*/
|
||||
static U8 *_EncodeStr(U8 *pPayload, const char *pText, unsigned int Limit) {
|
||||
U8* pLen;
|
||||
const char* sStart;
|
||||
|
||||
if (pText == NULL) {
|
||||
*pPayload++ = (U8)0;
|
||||
} else {
|
||||
sStart = pText; // Remember start of string.
|
||||
//
|
||||
// Save space to store count byte(s).
|
||||
//
|
||||
pLen = pPayload++;
|
||||
#if (SEGGER_SYSVIEW_MAX_STRING_LEN >= 255) // Length always encodes in 3 bytes
|
||||
pPayload += 2;
|
||||
#endif
|
||||
//
|
||||
// Limit string to maximum length and copy into payload buffer.
|
||||
//
|
||||
if (Limit > SEGGER_SYSVIEW_MAX_STRING_LEN) {
|
||||
Limit = SEGGER_SYSVIEW_MAX_STRING_LEN;
|
||||
unsigned int n;
|
||||
unsigned int Len;
|
||||
//
|
||||
// Compute string len
|
||||
//
|
||||
Len = 0;
|
||||
if (pText != NULL) {
|
||||
while(*(pText + Len) != 0) {
|
||||
Len++;
|
||||
}
|
||||
while ((Limit-- > 0) && (*pText != '\0')) {
|
||||
*pPayload++ = *pText++;
|
||||
if (Len > Limit) {
|
||||
Len = Limit;
|
||||
}
|
||||
//
|
||||
// Save string length to buffer.
|
||||
//
|
||||
#if (SEGGER_SYSVIEW_MAX_STRING_LEN >= 255) // Length always encodes in 3 bytes
|
||||
Limit = (unsigned int)(pText - sStart);
|
||||
*pLen++ = (U8)255;
|
||||
*pLen++ = (U8)((Limit >> 8) & 255);
|
||||
*pLen++ = (U8)(Limit & 255);
|
||||
#else // Length always encodes in 1 byte
|
||||
*pLen = (U8)(pText - sStart);
|
||||
#endif
|
||||
}
|
||||
//
|
||||
// Write Len
|
||||
//
|
||||
if (Len < 255) {
|
||||
*pPayload++ = (U8)Len;
|
||||
} else {
|
||||
*pPayload++ = 255;
|
||||
*pPayload++ = (Len & 255);
|
||||
*pPayload++ = ((Len >> 8) & 255);
|
||||
}
|
||||
//
|
||||
// copy string
|
||||
//
|
||||
n = 0;
|
||||
while (n < Len) {
|
||||
*pPayload++ = *pText++;
|
||||
n++;
|
||||
}
|
||||
return pPayload;
|
||||
}
|
||||
|
||||
@@ -731,6 +693,7 @@ static void _SendSyncInfo(void) {
|
||||
for (n = 0; n < _NumModules; n++) {
|
||||
SEGGER_SYSVIEW_SendModule(n);
|
||||
}
|
||||
SEGGER_SYSVIEW_SendModuleDescription();
|
||||
}
|
||||
}
|
||||
#endif // (SEGGER_SYSVIEW_POST_MORTEM_MODE == 1)
|
||||
@@ -1255,7 +1218,6 @@ static void _VPrintTarget(const char* sFormat, U32 Options, va_list* pParamList)
|
||||
unsigned int FormatFlags;
|
||||
unsigned int FieldWidth;
|
||||
U8* pPayloadStart;
|
||||
const char* s;
|
||||
#if SEGGER_SYSVIEW_USE_STATIC_BUFFER == 0
|
||||
RECORD_START(SEGGER_SYSVIEW_INFO_SIZE + SEGGER_SYSVIEW_MAX_STRING_LEN + 1 + 2 * SEGGER_SYSVIEW_QUANTA_U32);
|
||||
SEGGER_SYSVIEW_LOCK();
|
||||
@@ -1360,20 +1322,6 @@ static void _VPrintTarget(const char* sFormat, U32 Options, va_list* pParamList)
|
||||
v = va_arg(*pParamList, int);
|
||||
_PrintUnsigned(&BufferDesc, (unsigned int)v, 16u, NumDigits, FieldWidth, FormatFlags);
|
||||
break;
|
||||
case 's':
|
||||
s = va_arg(*pParamList, const char*);
|
||||
if (s == NULL) {
|
||||
s = "(null)";
|
||||
}
|
||||
do {
|
||||
c = *s;
|
||||
s++;
|
||||
if (c == '\0') {
|
||||
break;
|
||||
}
|
||||
_StoreChar(&BufferDesc, c);
|
||||
} while (BufferDesc.Cnt < SEGGER_SYSVIEW_MAX_STRING_LEN);
|
||||
break;
|
||||
case 'p':
|
||||
v = va_arg(*pParamList, int);
|
||||
_PrintUnsigned(&BufferDesc, (unsigned int)v, 16u, 8u, 8u, 0u);
|
||||
@@ -2006,61 +1954,11 @@ void SEGGER_SYSVIEW_SendTaskInfo(const SEGGER_SYSVIEW_TASKINFO *pInfo) {
|
||||
ENCODE_U32(pPayload, SHRINK_ID(pInfo->TaskID));
|
||||
ENCODE_U32(pPayload, pInfo->StackBase);
|
||||
ENCODE_U32(pPayload, pInfo->StackSize);
|
||||
ENCODE_U32(pPayload, pInfo->StackUsage);
|
||||
ENCODE_U32(pPayload, 0); // Stack End, future use
|
||||
_SendPacket(pPayloadStart, pPayload, SYSVIEW_EVTID_STACK_INFO);
|
||||
RECORD_END();
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* SEGGER_SYSVIEW_SendStackInfo()
|
||||
*
|
||||
* Function description
|
||||
* Send a Stack Info Packet, containing TaskId for identification,
|
||||
* stack base, stack size and stack usage.
|
||||
*
|
||||
*
|
||||
* Parameters
|
||||
* pInfo - Pointer to stack information to send.
|
||||
*/
|
||||
void SEGGER_SYSVIEW_SendStackInfo(const SEGGER_SYSVIEW_STACKINFO *pInfo) {
|
||||
U8* pPayload;
|
||||
U8* pPayloadStart;
|
||||
RECORD_START(SEGGER_SYSVIEW_INFO_SIZE + 4 * SEGGER_SYSVIEW_QUANTA_U32);
|
||||
//
|
||||
pPayload = pPayloadStart;
|
||||
ENCODE_U32(pPayload, SHRINK_ID(pInfo->TaskID));
|
||||
ENCODE_U32(pPayload, pInfo->StackBase);
|
||||
ENCODE_U32(pPayload, pInfo->StackSize);
|
||||
ENCODE_U32(pPayload, pInfo->StackUsage);
|
||||
|
||||
RECORD_END();
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* SEGGER_SYSVIEW_SampleData()
|
||||
*
|
||||
* Function description
|
||||
* Send a Data Sample Packet, containing the data Id and the value.
|
||||
*
|
||||
*
|
||||
* Parameters
|
||||
* pInfo - Pointer to data sample struct to send.
|
||||
*/
|
||||
void SEGGER_SYSVIEW_SampleData(const SEGGER_SYSVIEW_DATA_SAMPLE *pInfo) {
|
||||
U8* pPayload;
|
||||
U8* pPayloadStart;
|
||||
RECORD_START(SEGGER_SYSVIEW_INFO_SIZE + 2 * SEGGER_SYSVIEW_QUANTA_U32);
|
||||
//
|
||||
pPayload = pPayloadStart;
|
||||
ENCODE_U32(pPayload, pInfo->ID);
|
||||
pPayload = _EncodeFloat(pPayload, *(pInfo->pFloat_Value));
|
||||
_SendPacket(pPayloadStart, pPayload, SYSVIEW_EVTID_DATA_SAMPLE);
|
||||
|
||||
RECORD_END();
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* SEGGER_SYSVIEW_SendTaskList()
|
||||
@@ -2550,63 +2448,6 @@ void SEGGER_SYSVIEW_NameResource(U32 ResourceId, const char* sName) {
|
||||
RECORD_END();
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* SEGGER_SYSVIEW_RegisterData()
|
||||
*
|
||||
* Function description
|
||||
* Register data to sample the values via SystemView.
|
||||
*
|
||||
* Register functions are usually set in the system description
|
||||
* callback, to ensure it is only sent when the SystemView Application
|
||||
* is connected.
|
||||
*
|
||||
* Parameters
|
||||
* pInfo - Struct containing all possible properties that can be sent via this registration event.
|
||||
*/
|
||||
void SEGGER_SYSVIEW_RegisterData(SEGGER_SYSVIEW_DATA_REGISTER* pInfo) {
|
||||
U8* pPayload;
|
||||
U8* pPayloadStart;
|
||||
RECORD_START(SEGGER_SYSVIEW_INFO_SIZE + 8 * SEGGER_SYSVIEW_QUANTA_U32 + 1 + SEGGER_SYSVIEW_MAX_STRING_LEN);
|
||||
//
|
||||
pPayload = pPayloadStart;
|
||||
ENCODE_U32(pPayload, SYSVIEW_EVTID_EX_REGISTER_DATA);
|
||||
ENCODE_U32(pPayload, pInfo->ID);
|
||||
pPayload = _EncodeStr(pPayload, pInfo->sName, SEGGER_SYSVIEW_MAX_STRING_LEN);
|
||||
|
||||
if (pInfo->sName != 0) {
|
||||
ENCODE_U32(pPayload, pInfo->DataType);
|
||||
ENCODE_U32(pPayload, pInfo->Offset);
|
||||
ENCODE_U32(pPayload, pInfo->RangeMin);
|
||||
ENCODE_U32(pPayload, pInfo->RangeMax);
|
||||
pPayload = _EncodeFloat(pPayload, pInfo->ScalingFactor);
|
||||
pPayload = _EncodeStr(pPayload, pInfo->sUnit, SEGGER_SYSVIEW_MAX_STRING_LEN);
|
||||
} else if (pInfo->ScalingFactor != 0) {
|
||||
ENCODE_U32(pPayload, pInfo->DataType);
|
||||
ENCODE_U32(pPayload, pInfo->Offset);
|
||||
ENCODE_U32(pPayload, pInfo->RangeMin);
|
||||
ENCODE_U32(pPayload, pInfo->RangeMax);
|
||||
pPayload = _EncodeFloat(pPayload, pInfo->ScalingFactor);
|
||||
} else if (pInfo->RangeMax != 0) {
|
||||
ENCODE_U32(pPayload, pInfo->DataType);
|
||||
ENCODE_U32(pPayload, pInfo->Offset);
|
||||
ENCODE_U32(pPayload, pInfo->RangeMin);
|
||||
ENCODE_U32(pPayload, pInfo->RangeMax);
|
||||
} else if (pInfo->RangeMin != 0) {
|
||||
ENCODE_U32(pPayload, pInfo->DataType);
|
||||
ENCODE_U32(pPayload, pInfo->Offset);
|
||||
ENCODE_U32(pPayload, pInfo->RangeMin);
|
||||
} else if (pInfo->Offset != 0) {
|
||||
ENCODE_U32(pPayload, pInfo->DataType);
|
||||
ENCODE_U32(pPayload, pInfo->Offset);
|
||||
} else if (pInfo->DataType != 0) {
|
||||
ENCODE_U32(pPayload, pInfo->DataType);
|
||||
}
|
||||
|
||||
_SendPacket(pPayloadStart, pPayload, SYSVIEW_EVTID_EX);
|
||||
RECORD_END();
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* SEGGER_SYSVIEW_HeapDefine()
|
||||
@@ -2979,6 +2820,9 @@ void SEGGER_SYSVIEW_RegisterModule(SEGGER_SYSVIEW_MODULE* pModule) {
|
||||
_NumModules++;
|
||||
}
|
||||
SEGGER_SYSVIEW_SendModule(0);
|
||||
if (pModule->pfSendModuleDesc) {
|
||||
pModule->pfSendModuleDesc();
|
||||
}
|
||||
SEGGER_SYSVIEW_UNLOCK();
|
||||
}
|
||||
|
||||
@@ -3062,9 +2906,6 @@ void SEGGER_SYSVIEW_SendModule(U8 ModuleId) {
|
||||
_SendPacket(pPayloadStart, pPayload, SYSVIEW_EVTID_MODULEDESC);
|
||||
RECORD_END();
|
||||
}
|
||||
if (pModule && pModule->pfSendModuleDesc) {
|
||||
pModule->pfSendModuleDesc();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3145,39 +2986,6 @@ void SEGGER_SYSVIEW_PrintfHostEx(const char* s, U32 Options, ...) {
|
||||
#endif
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* SEGGER_SYSVIEW_VPrintfHostEx()
|
||||
*
|
||||
* Function description
|
||||
* Print a string which is formatted on the host by the SystemView Application
|
||||
* with Additional information.
|
||||
*
|
||||
* Parameters
|
||||
* s - String to be formatted.
|
||||
* Options - Options for the string. i.e. Log level.
|
||||
* pParamList - Pointer to the list of arguments for the format string
|
||||
*
|
||||
* Additional information
|
||||
* All format arguments are treated as 32-bit scalar values.
|
||||
*/
|
||||
void SEGGER_SYSVIEW_VPrintfHostEx(const char* s, U32 Options, va_list *pParamList) {
|
||||
#if SEGGER_SYSVIEW_PRINTF_IMPLICIT_FORMAT
|
||||
int r;
|
||||
va_list ParamListCopy;
|
||||
va_copy(ParamListCopy, *pParamList);
|
||||
|
||||
r = _VPrintHost(s, Options, pParamList);
|
||||
|
||||
if (r == -1) {
|
||||
_VPrintTarget(s, Options, &ParamListCopy);
|
||||
}
|
||||
va_end(ParamListCopy);
|
||||
#else
|
||||
_VPrintHost(s, Options, pParamList);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* SEGGER_SYSVIEW_PrintfHost()
|
||||
@@ -3212,37 +3020,6 @@ void SEGGER_SYSVIEW_PrintfHost(const char* s, ...) {
|
||||
#endif
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* SEGGER_SYSVIEW_VPrintfHost()
|
||||
*
|
||||
* Function description
|
||||
* Print a string which is formatted on the host by the SystemView Application.
|
||||
*
|
||||
* Parameters
|
||||
* s - String to be formatted.
|
||||
* pParamList - Pointer to the list of arguments for the format string
|
||||
*
|
||||
* Additional information
|
||||
* All format arguments are treated as 32-bit scalar values.
|
||||
*/
|
||||
void SEGGER_SYSVIEW_VPrintfHost(const char* s, va_list *pParamList) {
|
||||
#if SEGGER_SYSVIEW_PRINTF_IMPLICIT_FORMAT
|
||||
int r;
|
||||
va_list ParamListCopy;
|
||||
va_copy(ParamListCopy, *pParamList);
|
||||
|
||||
r = _VPrintHost(s, SEGGER_SYSVIEW_LOG, pParamList);
|
||||
|
||||
if (r == -1) {
|
||||
_VPrintTarget(s, SEGGER_SYSVIEW_LOG, &ParamListCopy);
|
||||
}
|
||||
va_end(ParamListCopy);
|
||||
#else
|
||||
_VPrintHost(s, SEGGER_SYSVIEW_LOG, pParamList);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* SEGGER_SYSVIEW_WarnfHost()
|
||||
@@ -3278,38 +3055,6 @@ void SEGGER_SYSVIEW_WarnfHost(const char* s, ...) {
|
||||
#endif
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* SEGGER_SYSVIEW_VWarnfHost()
|
||||
*
|
||||
* Function description
|
||||
* Print a warning string which is formatted on the host by
|
||||
* the SystemView Application.
|
||||
*
|
||||
* Parameters
|
||||
* s - String to be formatted.
|
||||
* pParamList - Pointer to the list of arguments for the format string
|
||||
*
|
||||
* Additional information
|
||||
* All format arguments are treated as 32-bit scalar values.
|
||||
*/
|
||||
void SEGGER_SYSVIEW_VWarnfHost(const char* s, va_list *pParamList) {
|
||||
#if SEGGER_SYSVIEW_PRINTF_IMPLICIT_FORMAT
|
||||
int r;
|
||||
va_list ParamListCopy;
|
||||
va_copy(ParamListCopy, *pParamList);
|
||||
|
||||
r = _VPrintHost(s, SEGGER_SYSVIEW_WARNING, pParamList);
|
||||
|
||||
if (r == -1) {
|
||||
_VPrintTarget(s, SEGGER_SYSVIEW_WARNING, &ParamListCopy);
|
||||
}
|
||||
va_end(ParamListCopy);
|
||||
#else
|
||||
_VPrintHost(s, SEGGER_SYSVIEW_WARNING, pParamList);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* SEGGER_SYSVIEW_ErrorfHost()
|
||||
@@ -3345,38 +3090,6 @@ void SEGGER_SYSVIEW_ErrorfHost(const char* s, ...) {
|
||||
#endif
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* SEGGER_SYSVIEW_VErrorfHost()
|
||||
*
|
||||
* Function description
|
||||
* Print a warning string which is formatted on the host by
|
||||
* the SystemView Application.
|
||||
*
|
||||
* Parameters
|
||||
* s - String to be formatted.
|
||||
* pParamList - Pointer to the list of arguments for the format string
|
||||
*
|
||||
* Additional information
|
||||
* All format arguments are treated as 32-bit scalar values.
|
||||
*/
|
||||
void SEGGER_SYSVIEW_VErrorfHost(const char* s, va_list *pParamList) {
|
||||
#if SEGGER_SYSVIEW_PRINTF_IMPLICIT_FORMAT
|
||||
int r;
|
||||
va_list ParamListCopy;
|
||||
va_copy(ParamListCopy, *pParamList);
|
||||
|
||||
r = _VPrintHost(s, SEGGER_SYSVIEW_ERROR, pParamList);
|
||||
|
||||
if (r == -1) {
|
||||
_VPrintTarget(s, SEGGER_SYSVIEW_ERROR, &ParamListCopy);
|
||||
}
|
||||
va_end(ParamListCopy);
|
||||
#else
|
||||
_VPrintHost(s, SEGGER_SYSVIEW_ERROR, pParamList);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* SEGGER_SYSVIEW_PrintfTargetEx()
|
||||
@@ -3397,23 +3110,6 @@ void SEGGER_SYSVIEW_PrintfTargetEx(const char* s, U32 Options, ...) {
|
||||
va_end(ParamList);
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* SEGGER_SYSVIEW_VPrintfTargetEx()
|
||||
*
|
||||
* Function description
|
||||
* Print a string which is formatted on the target before sent to
|
||||
* the host with Additional information.
|
||||
*
|
||||
* Parameters
|
||||
* s - String to be formatted.
|
||||
* Options - Options for the string. i.e. Log level.
|
||||
* pParamList - Pointer to the list of arguments for the format string
|
||||
*/
|
||||
void SEGGER_SYSVIEW_VPrintfTargetEx(const char* s, U32 Options, va_list *pParamList) {
|
||||
_VPrintTarget(s, Options, pParamList);
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* SEGGER_SYSVIEW_PrintfTarget()
|
||||
@@ -3433,22 +3129,6 @@ void SEGGER_SYSVIEW_PrintfTarget(const char* s, ...) {
|
||||
va_end(ParamList);
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* SEGGER_SYSVIEW_VPrintfTarget()
|
||||
*
|
||||
* Function description
|
||||
* Print a string which is formatted on the target before sent to
|
||||
* the host.
|
||||
*
|
||||
* Parameters
|
||||
* s - String to be formatted.
|
||||
* pParamList - Pointer to the list of arguments for the format string
|
||||
*/
|
||||
void SEGGER_SYSVIEW_VPrintfTarget(const char* s, va_list* pParamList) {
|
||||
_VPrintTarget(s, SEGGER_SYSVIEW_LOG, pParamList);
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* SEGGER_SYSVIEW_WarnfTarget()
|
||||
@@ -3468,22 +3148,6 @@ void SEGGER_SYSVIEW_WarnfTarget(const char* s, ...) {
|
||||
va_end(ParamList);
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* SEGGER_SYSVIEW_VWarnfTarget()
|
||||
*
|
||||
* Function description
|
||||
* Print a warning string which is formatted on the target before
|
||||
* sent to the host.
|
||||
*
|
||||
* Parameters
|
||||
* s - String to be formatted.
|
||||
* pParamList - Pointer to the list of arguments for the format string
|
||||
*/
|
||||
void SEGGER_SYSVIEW_VWarnfTarget(const char* s, va_list* pParamList) {
|
||||
_VPrintTarget(s, SEGGER_SYSVIEW_WARNING, pParamList);
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* SEGGER_SYSVIEW_ErrorfTarget()
|
||||
@@ -3502,22 +3166,6 @@ void SEGGER_SYSVIEW_ErrorfTarget(const char* s, ...) {
|
||||
_VPrintTarget(s, SEGGER_SYSVIEW_ERROR, &ParamList);
|
||||
va_end(ParamList);
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* SEGGER_SYSVIEW_VErrorfTarget()
|
||||
*
|
||||
* Function description
|
||||
* Print an error string which is formatted on the target before
|
||||
* sent to the host.
|
||||
*
|
||||
* Parameters
|
||||
* s - String to be formatted.
|
||||
* pParamList - Pointer to the list of arguments for the format string
|
||||
*/
|
||||
void SEGGER_SYSVIEW_VErrorfTarget(const char* s, va_list* pParamList) {
|
||||
_VPrintTarget(s, SEGGER_SYSVIEW_ERROR, pParamList);
|
||||
}
|
||||
#endif // SEGGER_SYSVIEW_EXCLUDE_PRINTF
|
||||
|
||||
/*********************************************************************
|
||||
|
||||
@@ -3,14 +3,14 @@
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-1-Clause
|
||||
*
|
||||
* SPDX-FileContributor: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileContributor: 2023 Espressif Systems (Shanghai) CO LTD
|
||||
*/
|
||||
/*********************************************************************
|
||||
* SEGGER Microcontroller GmbH *
|
||||
* The Embedded Experts *
|
||||
**********************************************************************
|
||||
* *
|
||||
* (c) 1995 - 2024 SEGGER Microcontroller GmbH *
|
||||
* (c) 1995 - 2021 SEGGER Microcontroller GmbH *
|
||||
* *
|
||||
* www.segger.com Support: support@segger.com *
|
||||
* *
|
||||
@@ -49,13 +49,13 @@
|
||||
* *
|
||||
**********************************************************************
|
||||
* *
|
||||
* SystemView version: 3.56 *
|
||||
* SystemView version: 3.42 *
|
||||
* *
|
||||
**********************************************************************
|
||||
-------------------------- END-OF-HEADER -----------------------------
|
||||
File : SEGGER_SYSVIEW.h
|
||||
Purpose : System visualization API.
|
||||
Revision: $Rev: 28768 $
|
||||
Revision: $Rev: 28237 $
|
||||
*/
|
||||
|
||||
#ifndef SEGGER_SYSVIEW_H
|
||||
@@ -123,7 +123,7 @@ extern "C" {
|
||||
#define SYSVIEW_EVTID_TIMER_EXIT 20
|
||||
#define SYSVIEW_EVTID_STACK_INFO 21
|
||||
#define SYSVIEW_EVTID_MODULEDESC 22
|
||||
#define SYSVIEW_EVTID_DATA_SAMPLE 23
|
||||
|
||||
#define SYSVIEW_EVTID_INIT 24
|
||||
#define SYSVIEW_EVTID_NAME_RESOURCE 25
|
||||
#define SYSVIEW_EVTID_PRINT_FORMATTED 26
|
||||
@@ -135,13 +135,12 @@ extern "C" {
|
||||
//
|
||||
// SystemView extended events. Sent with ID 31.
|
||||
//
|
||||
#define SYSVIEW_EVTID_EX_MARK 0
|
||||
#define SYSVIEW_EVTID_EX_NAME_MARKER 1
|
||||
#define SYSVIEW_EVTID_EX_HEAP_DEFINE 2
|
||||
#define SYSVIEW_EVTID_EX_HEAP_ALLOC 3
|
||||
#define SYSVIEW_EVTID_EX_HEAP_ALLOC_EX 4
|
||||
#define SYSVIEW_EVTID_EX_HEAP_FREE 5
|
||||
#define SYSVIEW_EVTID_EX_REGISTER_DATA 6
|
||||
#define SYSVIEW_EVTID_EX_MARK 0
|
||||
#define SYSVIEW_EVTID_EX_NAME_MARKER 1
|
||||
#define SYSVIEW_EVTID_EX_HEAP_DEFINE 2
|
||||
#define SYSVIEW_EVTID_EX_HEAP_ALLOC 3
|
||||
#define SYSVIEW_EVTID_EX_HEAP_ALLOC_EX 4
|
||||
#define SYSVIEW_EVTID_EX_HEAP_FREE 5
|
||||
//
|
||||
// Event masks to disable/enable events
|
||||
//
|
||||
@@ -168,7 +167,7 @@ extern "C" {
|
||||
#define SYSVIEW_EVTMASK_TIMER_EXIT (1 << SYSVIEW_EVTID_TIMER_EXIT)
|
||||
#define SYSVIEW_EVTMASK_STACK_INFO (1 << SYSVIEW_EVTID_STACK_INFO)
|
||||
#define SYSVIEW_EVTMASK_MODULEDESC (1 << SYSVIEW_EVTID_MODULEDESC)
|
||||
#define SYSVIEW_EVTMASK_DATA_SAMPLE (1 << SYSVIEW_EVTID_DATA_SAMPLE)
|
||||
|
||||
#define SYSVIEW_EVTMASK_INIT (1 << SYSVIEW_EVTID_INIT)
|
||||
#define SYSVIEW_EVTMASK_NAME_RESOURCE (1 << SYSVIEW_EVTID_NAME_RESOURCE)
|
||||
#define SYSVIEW_EVTMASK_PRINT_FORMATTED (1 << SYSVIEW_EVTID_PRINT_FORMATTED)
|
||||
@@ -203,42 +202,8 @@ typedef struct {
|
||||
U32 Prio;
|
||||
U32 StackBase;
|
||||
U32 StackSize;
|
||||
U32 StackUsage;
|
||||
} SEGGER_SYSVIEW_TASKINFO;
|
||||
|
||||
typedef struct {
|
||||
U32 TaskID;
|
||||
U32 StackBase;
|
||||
U32 StackSize;
|
||||
U32 StackUsage;
|
||||
} SEGGER_SYSVIEW_STACKINFO;
|
||||
|
||||
typedef struct {
|
||||
U32 ID;
|
||||
union {
|
||||
U32* pU32_Value;
|
||||
I32* pI32_Value;
|
||||
float* pFloat_Value;
|
||||
};
|
||||
} SEGGER_SYSVIEW_DATA_SAMPLE;
|
||||
|
||||
typedef enum {
|
||||
SEGGER_SYSVIEW_TYPE_U32 = 0,
|
||||
SEGGER_SYSVIEW_TYPE_I32 = 1,
|
||||
SEGGER_SYSVIEW_TYPE_FLOAT = 2
|
||||
} SEGGER_SYSVIEW_DATA_TYPE;
|
||||
|
||||
typedef struct {
|
||||
U32 ID;
|
||||
SEGGER_SYSVIEW_DATA_TYPE DataType;
|
||||
I32 Offset;
|
||||
I32 RangeMin;
|
||||
I32 RangeMax;
|
||||
float ScalingFactor;
|
||||
const char* sName;
|
||||
const char* sUnit;
|
||||
} SEGGER_SYSVIEW_DATA_REGISTER;
|
||||
|
||||
typedef struct SEGGER_SYSVIEW_MODULE_STRUCT SEGGER_SYSVIEW_MODULE;
|
||||
|
||||
struct SEGGER_SYSVIEW_MODULE_STRUCT {
|
||||
@@ -282,8 +247,8 @@ EXTERN unsigned int SEGGER_SYSVIEW_InterruptId;
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
U64 (*pfGetTime) (void);
|
||||
void (*pfSendTaskList) (void);
|
||||
U64 (*pfGetTime) (void);
|
||||
void (*pfSendTaskList) (void);
|
||||
} SEGGER_SYSVIEW_OS_API;
|
||||
|
||||
/*********************************************************************
|
||||
@@ -297,13 +262,9 @@ void SEGGER_SYSVIEW_Stop (void);
|
||||
void SEGGER_SYSVIEW_GetSysDesc (void);
|
||||
void SEGGER_SYSVIEW_SendTaskList (void);
|
||||
void SEGGER_SYSVIEW_SendTaskInfo (const SEGGER_SYSVIEW_TASKINFO* pInfo);
|
||||
void SEGGER_SYSVIEW_SendStackInfo (const SEGGER_SYSVIEW_STACKINFO* pInfo);
|
||||
void SEGGER_SYSVIEW_SendSysDesc (const char* sSysDesc);
|
||||
int SEGGER_SYSVIEW_IsStarted (void);
|
||||
int SEGGER_SYSVIEW_GetChannelID (void);
|
||||
|
||||
void SEGGER_SYSVIEW_SampleData (const SEGGER_SYSVIEW_DATA_SAMPLE *pInfo);
|
||||
|
||||
// Checks whether tracing has been started
|
||||
U8 SEGGER_SYSVIEW_Started(void);
|
||||
|
||||
@@ -350,7 +311,6 @@ void SEGGER_SYSVIEW_HeapAllocEx (void* pHeap, void* pUserData,
|
||||
void SEGGER_SYSVIEW_HeapFree (void* pHeap, void* pUserData);
|
||||
|
||||
void SEGGER_SYSVIEW_NameResource (U32 ResourceId, const char* sName);
|
||||
void SEGGER_SYSVIEW_RegisterData ( SEGGER_SYSVIEW_DATA_REGISTER* pInfo);
|
||||
|
||||
int SEGGER_SYSVIEW_SendPacket (U8* pPacket, U8* pPayloadEnd, unsigned int EventId);
|
||||
|
||||
@@ -381,21 +341,13 @@ void SEGGER_SYSVIEW_SendNumModules (void);
|
||||
*/
|
||||
#ifndef SEGGER_SYSVIEW_EXCLUDE_PRINTF // Define in project to avoid warnings about variable parameter list
|
||||
void SEGGER_SYSVIEW_PrintfHostEx (const char* s, U32 Options, ...);
|
||||
void SEGGER_SYSVIEW_VPrintfHostEx (const char* s, U32 Options, va_list* pParamList);
|
||||
void SEGGER_SYSVIEW_PrintfTargetEx (const char* s, U32 Options, ...);
|
||||
void SEGGER_SYSVIEW_VPrintfTargetEx (const char* s, U32 Options, va_list* pParamList);
|
||||
void SEGGER_SYSVIEW_PrintfHost (const char* s, ...);
|
||||
void SEGGER_SYSVIEW_VPrintfHost (const char* s, va_list* pParamList);
|
||||
void SEGGER_SYSVIEW_PrintfTarget (const char* s, ...);
|
||||
void SEGGER_SYSVIEW_VPrintfTarget (const char* s, va_list* pParamList);
|
||||
void SEGGER_SYSVIEW_WarnfHost (const char* s, ...);
|
||||
void SEGGER_SYSVIEW_VWarnfHost (const char* s, va_list* pParamList);
|
||||
void SEGGER_SYSVIEW_WarnfTarget (const char* s, ...);
|
||||
void SEGGER_SYSVIEW_VWarnfTarget (const char* s, va_list* pParamList);
|
||||
void SEGGER_SYSVIEW_ErrorfHost (const char* s, ...);
|
||||
void SEGGER_SYSVIEW_VErrorfHost (const char* s, va_list* pParamList);
|
||||
void SEGGER_SYSVIEW_ErrorfTarget (const char* s, ...);
|
||||
void SEGGER_SYSVIEW_VErrorfTarget (const char* s, va_list* pParamList);
|
||||
#endif
|
||||
|
||||
void SEGGER_SYSVIEW_Print (const char* s);
|
||||
|
||||
@@ -3,14 +3,14 @@
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-1-Clause
|
||||
*
|
||||
* SPDX-FileContributor: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileContributor: 2023 Espressif Systems (Shanghai) CO LTD
|
||||
*/
|
||||
/*********************************************************************
|
||||
* SEGGER Microcontroller GmbH *
|
||||
* The Embedded Experts *
|
||||
**********************************************************************
|
||||
* *
|
||||
* (c) 1995 - 2024 SEGGER Microcontroller GmbH *
|
||||
* (c) 1995 - 2021 SEGGER Microcontroller GmbH *
|
||||
* *
|
||||
* www.segger.com Support: support@segger.com *
|
||||
* *
|
||||
@@ -49,7 +49,7 @@
|
||||
* *
|
||||
**********************************************************************
|
||||
* *
|
||||
* SystemView version: 3.56 *
|
||||
* SystemView version: 3.42 *
|
||||
* *
|
||||
**********************************************************************
|
||||
-------------------------- END-OF-HEADER -----------------------------
|
||||
@@ -72,8 +72,6 @@ Revision: $Rev: 26230 $
|
||||
#include "SEGGER_SYSVIEW_Conf.h"
|
||||
#include "SEGGER_RTT_Conf.h"
|
||||
|
||||
#include "esp_assert.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
@@ -372,14 +370,12 @@ extern "C" {
|
||||
#define SEGGER_SYSVIEW_MAX_STRING_LEN 128
|
||||
#endif
|
||||
|
||||
ESP_STATIC_ASSERT(SEGGER_SYSVIEW_MAX_STRING_LEN < 255, "SEGGER Sysview string length must be less than 255.");
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Define: SEGGER_SYSVIEW_SUPPORT_LONG_ID
|
||||
*
|
||||
* Description
|
||||
* It set, support encoding Evend Ids longer than 14 bit.
|
||||
* It set, support enconding Evend Ids longer than 14 bit.
|
||||
* Default
|
||||
* 1
|
||||
*/
|
||||
@@ -392,7 +388,7 @@ ESP_STATIC_ASSERT(SEGGER_SYSVIEW_MAX_STRING_LEN < 255, "SEGGER Sysview string le
|
||||
* Define: SEGGER_SYSVIEW_SUPPORT_LONG_DATA
|
||||
*
|
||||
* Description
|
||||
* It set, support encoding event data longer than 14 bit.
|
||||
* It set, support enconding event data longer than 14 bit.
|
||||
* Default
|
||||
* 0
|
||||
*/
|
||||
@@ -521,7 +517,7 @@ ESP_STATIC_ASSERT(SEGGER_SYSVIEW_MAX_STRING_LEN < 255, "SEGGER Sysview string le
|
||||
* Define: SEGGER_SYSVIEW_SYNC_PERIOD_SHIFT
|
||||
*
|
||||
* Description
|
||||
* Configure how frequently synchronization is sent in post-mortem
|
||||
* Configure how frequently syncronization is sent in post-mortem
|
||||
* mode.
|
||||
* Default
|
||||
* 8: (1 << 8) = Every 256 Events.
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
* The Embedded Experts *
|
||||
**********************************************************************
|
||||
* *
|
||||
* (c) 1995 - 2024 SEGGER Microcontroller GmbH *
|
||||
* (c) 1995 - 2021 SEGGER Microcontroller GmbH *
|
||||
* *
|
||||
* www.segger.com Support: support@segger.com *
|
||||
* *
|
||||
@@ -47,7 +47,7 @@
|
||||
* *
|
||||
**********************************************************************
|
||||
* *
|
||||
* SystemView version: 3.56 *
|
||||
* SystemView version: 3.42 *
|
||||
* *
|
||||
**********************************************************************
|
||||
-------------------------- END-OF-HEADER -----------------------------
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: 'SystemView'
|
||||
version: '3.56'
|
||||
version: '3.42'
|
||||
cpe: cpe:2.3:a:segger:systemview:{}:*:*:*:*:*:*:*
|
||||
supplier: 'Organization: Espressif Systems (Shanghai) CO LTD'
|
||||
originator: 'Organization: SEGGER Microcontroller GmbH'
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-1-Clause
|
||||
*
|
||||
* SPDX-FileContributor: 2017-2025 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileContributor: 2017-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*/
|
||||
/*********************************************************************
|
||||
* SEGGER Microcontroller GmbH *
|
||||
@@ -65,7 +65,6 @@ Revision: $Rev: 7745 $
|
||||
#include "esp_app_trace.h"
|
||||
#include "esp_app_trace_util.h"
|
||||
#include "esp_intr_alloc.h"
|
||||
#include "esp_clk_tree.h"
|
||||
#include "esp_cpu.h"
|
||||
#include "soc/soc.h"
|
||||
#include "soc/interrupts.h"
|
||||
@@ -85,7 +84,11 @@ extern const SEGGER_SYSVIEW_OS_API SYSVIEW_X_OS_TraceAPI;
|
||||
// The target device name
|
||||
#define SYSVIEW_DEVICE_NAME CONFIG_IDF_TARGET
|
||||
// The target core name
|
||||
#define SYSVIEW_CORE_NAME "core0" // In dual core, this will be renamed by OpenOCD as core1
|
||||
#if CONFIG_IDF_TARGET_ARCH_XTENSA
|
||||
#define SYSVIEW_CORE_NAME "xtensa"
|
||||
#elif CONFIG_IDF_TARGET_ARCH_RISCV
|
||||
#define SYSVIEW_CORE_NAME "riscv"
|
||||
#endif
|
||||
|
||||
// Determine which timer to use as timestamp source
|
||||
#if CONFIG_APPTRACE_SV_TS_SOURCE_CCOUNT
|
||||
@@ -102,6 +105,9 @@ extern const SEGGER_SYSVIEW_OS_API SYSVIEW_X_OS_TraceAPI;
|
||||
// Timer group timer divisor
|
||||
#define SYSVIEW_TIMER_DIV 2
|
||||
|
||||
// Frequency of the timestamp, using APB as GPTimer source clock
|
||||
#define SYSVIEW_TIMESTAMP_FREQ (esp_clk_apb_freq() / SYSVIEW_TIMER_DIV)
|
||||
|
||||
// GPTimer handle
|
||||
gptimer_handle_t s_sv_gptimer;
|
||||
|
||||
@@ -171,38 +177,30 @@ static void _cbSendSystemDesc(void) {
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
static int SEGGER_SYSVIEW_TS_Init(void)
|
||||
static void SEGGER_SYSVIEW_TS_Init(void)
|
||||
{
|
||||
/* We only need to initialize something if we use Timer Group.
|
||||
* esp_timer and ccount can be used as is.
|
||||
*/
|
||||
#if TS_USE_TIMERGROUP
|
||||
// get clock source frequency
|
||||
uint32_t counter_src_hz = 0;
|
||||
ESP_ERROR_CHECK(esp_clk_tree_src_get_freq_hz(
|
||||
(soc_module_clk_t)GPTIMER_CLK_SRC_DEFAULT,
|
||||
ESP_CLK_TREE_SRC_FREQ_PRECISION_CACHED, &counter_src_hz));
|
||||
gptimer_config_t config = {
|
||||
.clk_src = GPTIMER_CLK_SRC_DEFAULT,
|
||||
.direction = GPTIMER_COUNT_UP,
|
||||
.resolution_hz = counter_src_hz / SYSVIEW_TIMER_DIV,
|
||||
.resolution_hz = SYSVIEW_TIMESTAMP_FREQ,
|
||||
};
|
||||
// pick any free GPTimer instance
|
||||
ESP_ERROR_CHECK(gptimer_new_timer(&config, &s_sv_gptimer));
|
||||
/* Start counting */
|
||||
gptimer_enable(s_sv_gptimer);
|
||||
gptimer_start(s_sv_gptimer);
|
||||
return config.resolution_hz;
|
||||
#else
|
||||
return SYSVIEW_TIMESTAMP_FREQ;
|
||||
#endif // TS_USE_TIMERGROUP
|
||||
}
|
||||
|
||||
void SEGGER_SYSVIEW_Conf(void) {
|
||||
U32 disable_evts = 0;
|
||||
|
||||
int timestamp_freq = SEGGER_SYSVIEW_TS_Init();
|
||||
SEGGER_SYSVIEW_Init(timestamp_freq, SYSVIEW_CPU_FREQ,
|
||||
SEGGER_SYSVIEW_TS_Init();
|
||||
SEGGER_SYSVIEW_Init(SYSVIEW_TIMESTAMP_FREQ, SYSVIEW_CPU_FREQ,
|
||||
&SYSVIEW_X_OS_TraceAPI, _cbSendSystemDesc);
|
||||
SEGGER_SYSVIEW_SetRAMBase(SYSVIEW_RAM_BASE);
|
||||
|
||||
|
||||
@@ -108,7 +108,7 @@ static void _cbSendTaskList(void) {
|
||||
* Called from SystemView when asked by the host, returns the
|
||||
* current system time in micro seconds.
|
||||
*/
|
||||
__attribute__((unused)) static U64 _cbGetTime(void) {
|
||||
static U64 _cbGetTime(void) {
|
||||
U64 Time;
|
||||
|
||||
Time = xTaskGetTickCountFromISR();
|
||||
@@ -260,10 +260,7 @@ void SYSVIEW_SendTaskInfo(U32 TaskID, const char* sName, unsigned Prio, U32 Stac
|
||||
*/
|
||||
// Callbacks provided to SYSTEMVIEW by FreeRTOS
|
||||
const SEGGER_SYSVIEW_OS_API SYSVIEW_X_OS_TraceAPI = {
|
||||
/* Callback _cbGetTime locks xKernelLock inside xTaskGetTickCountFromISR, this can cause deadlock on multi-core.
|
||||
To prevent deadlock, always lock xKernelLock before s_sys_view_lock. Omitting the callback here results in sending
|
||||
SYSVIEW_EVTID_SYSTIME_CYCLES events instead of SYSVIEW_EVTID_SYSTIME_US */
|
||||
NULL,
|
||||
_cbGetTime,
|
||||
_cbSendTaskList,
|
||||
};
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ const static char *TAG = "sysview_heap_trace";
|
||||
#endif
|
||||
|
||||
static SEGGER_SYSVIEW_MODULE s_esp_sysview_heap_module = {
|
||||
.sModule = "M=ESP32 SystemView Heap Tracing Module",
|
||||
.sModule = "ESP32 SystemView Heap Tracing Module",
|
||||
.NumEvents = 2,
|
||||
};
|
||||
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
@@ -31,17 +31,22 @@
|
||||
#include "esp_attr.h"
|
||||
#include "esp_bootloader_desc.h"
|
||||
#include "esp_flash.h"
|
||||
#include "esp_flash_internal.h"
|
||||
|
||||
#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 */
|
||||
typedef struct ota_ops_entry_ {
|
||||
uint32_t handle;
|
||||
const esp_partition_t *part;
|
||||
struct {
|
||||
const esp_partition_t *staging; /*!< New image will be downloaded in this staging partition. */
|
||||
const esp_partition_t *final; /*!< Final destination partition which is intended to be updated. Its type/subtype shall be used for verification. */
|
||||
bool finalize_with_copy; /*!< Flag to copy the image from staging partition to the final partition at the end of OTA update */
|
||||
} partition;
|
||||
bool need_erase;
|
||||
uint32_t wrote_size;
|
||||
uint8_t partial_bytes;
|
||||
bool ota_resumption;
|
||||
WORD_ALIGNED_ATTR uint8_t partial_data[16];
|
||||
LIST_ENTRY(ota_ops_entry_) entries;
|
||||
} ota_ops_entry_t;
|
||||
@@ -53,6 +58,8 @@ static uint32_t s_ota_ops_last_handle = 0;
|
||||
|
||||
const static char *TAG = "esp_ota_ops";
|
||||
|
||||
static ota_ops_entry_t *get_ota_ops_entry(esp_ota_handle_t handle);
|
||||
|
||||
/* Return true if this is an OTA app partition */
|
||||
static bool is_ota_partition(const esp_partition_t *p)
|
||||
{
|
||||
@@ -112,114 +119,101 @@ static esp_ota_img_states_t set_new_state_otadata(void)
|
||||
#endif
|
||||
}
|
||||
|
||||
static ota_ops_entry_t* esp_ota_init_entry(const esp_partition_t *partition)
|
||||
esp_err_t esp_ota_begin(const esp_partition_t *partition, size_t image_size, esp_ota_handle_t *out_handle)
|
||||
{
|
||||
ota_ops_entry_t *new_entry = (ota_ops_entry_t *) calloc(1, sizeof(ota_ops_entry_t));
|
||||
ota_ops_entry_t *new_entry;
|
||||
if ((partition == NULL) || (out_handle == NULL)) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
partition = esp_partition_verify(partition);
|
||||
if (partition == NULL) {
|
||||
return ESP_ERR_NOT_FOUND;
|
||||
}
|
||||
|
||||
if (partition->type == ESP_PARTITION_TYPE_APP) {
|
||||
// The staging partition cannot be of type Factory, but the final partition can be.
|
||||
if (!is_ota_partition(partition)) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
const esp_partition_t* running_partition = esp_ota_get_running_partition();
|
||||
if (partition == running_partition) {
|
||||
return ESP_ERR_OTA_PARTITION_CONFLICT;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE
|
||||
esp_ota_img_states_t ota_state_running_part;
|
||||
if (esp_ota_get_state_partition(running_partition, &ota_state_running_part) == ESP_OK) {
|
||||
if (ota_state_running_part == ESP_OTA_IMG_PENDING_VERIFY) {
|
||||
ESP_LOGE(TAG, "Running app has not confirmed state (ESP_OTA_IMG_PENDING_VERIFY)");
|
||||
return ESP_ERR_OTA_ROLLBACK_INVALID_STATE;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
new_entry = (ota_ops_entry_t *) calloc(1, sizeof(ota_ops_entry_t));
|
||||
if (new_entry == NULL) {
|
||||
return NULL;
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
|
||||
LIST_INSERT_HEAD(&s_ota_ops_entries_head, new_entry, entries);
|
||||
|
||||
new_entry->part = partition;
|
||||
new_entry->partition.staging = partition;
|
||||
new_entry->partition.final = partition;
|
||||
new_entry->partition.finalize_with_copy = false;
|
||||
new_entry->handle = ++s_ota_ops_last_handle;
|
||||
|
||||
return new_entry;
|
||||
}
|
||||
|
||||
|
||||
esp_err_t esp_ota_begin(const esp_partition_t *partition, size_t image_size, esp_ota_handle_t *out_handle)
|
||||
{
|
||||
ota_ops_entry_t *new_entry;
|
||||
esp_err_t ret = ESP_OK;
|
||||
|
||||
if ((partition == NULL) || (out_handle == NULL)) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
partition = esp_partition_verify(partition);
|
||||
if (partition == NULL) {
|
||||
return ESP_ERR_NOT_FOUND;
|
||||
}
|
||||
|
||||
if (!is_ota_partition(partition)) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
const esp_partition_t* running_partition = esp_ota_get_running_partition();
|
||||
if (partition == running_partition) {
|
||||
return ESP_ERR_OTA_PARTITION_CONFLICT;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE
|
||||
esp_ota_img_states_t ota_state_running_part;
|
||||
if (esp_ota_get_state_partition(running_partition, &ota_state_running_part) == ESP_OK) {
|
||||
if (ota_state_running_part == ESP_OTA_IMG_PENDING_VERIFY) {
|
||||
ESP_LOGE(TAG, "Running app has not confirmed state (ESP_OTA_IMG_PENDING_VERIFY)");
|
||||
return ESP_ERR_OTA_ROLLBACK_INVALID_STATE;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
new_entry = esp_ota_init_entry(partition);
|
||||
if (new_entry == NULL) {
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
new_entry->need_erase = (image_size == OTA_WITH_SEQUENTIAL_WRITES);
|
||||
*out_handle = new_entry->handle;
|
||||
|
||||
if (image_size != OTA_WITH_SEQUENTIAL_WRITES) {
|
||||
// If input image size is 0 or OTA_SIZE_UNKNOWN, erase entire partition
|
||||
if ((image_size == 0) || (image_size == OTA_SIZE_UNKNOWN)) {
|
||||
ret = esp_partition_erase_range(partition, 0, partition->size);
|
||||
} else {
|
||||
const int aligned_erase_size = (image_size + partition->erase_size - 1) & ~(partition->erase_size - 1);
|
||||
ret = esp_partition_erase_range(partition, 0, aligned_erase_size);
|
||||
}
|
||||
if (ret != ESP_OK) {
|
||||
return ret;
|
||||
}
|
||||
if (partition->type == ESP_PARTITION_TYPE_BOOTLOADER) {
|
||||
esp_image_bootloader_offset_set(partition->address);
|
||||
}
|
||||
if (partition->type == ESP_PARTITION_TYPE_BOOTLOADER || partition->type == ESP_PARTITION_TYPE_PARTITION_TABLE) {
|
||||
esp_flash_set_dangerous_write_protection(esp_flash_default_chip, false);
|
||||
}
|
||||
|
||||
if (image_size != OTA_WITH_SEQUENTIAL_WRITES) {
|
||||
// If input image size is 0 or OTA_SIZE_UNKNOWN, erase entire partition
|
||||
size_t erase_size;
|
||||
if ((image_size == 0) || (image_size == OTA_SIZE_UNKNOWN)) {
|
||||
erase_size = partition->size;
|
||||
} else {
|
||||
erase_size = ALIGN_UP(image_size, partition->erase_size);
|
||||
}
|
||||
return esp_partition_erase_range(partition, 0, erase_size);
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ota_resume(const esp_partition_t *partition, const size_t erase_size, const size_t image_offset, esp_ota_handle_t *out_handle)
|
||||
esp_err_t esp_ota_set_final_partition(esp_ota_handle_t handle, const esp_partition_t *final, bool finalize_with_copy)
|
||||
{
|
||||
ota_ops_entry_t *new_entry;
|
||||
|
||||
if ((partition == NULL) || (out_handle == NULL)) {
|
||||
ota_ops_entry_t *it = get_ota_ops_entry(handle);
|
||||
if (final == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
if (image_offset > partition->size) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
partition = esp_partition_verify(partition);
|
||||
if (partition == NULL) {
|
||||
if (it == NULL) {
|
||||
return ESP_ERR_NOT_FOUND;
|
||||
}
|
||||
|
||||
// The staging partition cannot be of type Factory, but the final partition can be.
|
||||
if (!is_ota_partition(partition)) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
if (it->wrote_size != 0) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
const esp_partition_t* running_partition = esp_ota_get_running_partition();
|
||||
if (partition == running_partition) {
|
||||
return ESP_ERR_OTA_PARTITION_CONFLICT;
|
||||
if (it->partition.staging != final) {
|
||||
const esp_partition_t* final_partition = esp_partition_verify(final);
|
||||
if (final_partition == NULL) {
|
||||
return ESP_ERR_NOT_FOUND;
|
||||
}
|
||||
ESP_LOGI(TAG,"Staging partition - <%s>. Final partition - <%s>.", it->partition.staging->label, final_partition->label);
|
||||
it->partition.final = final_partition;
|
||||
it->partition.finalize_with_copy = finalize_with_copy;
|
||||
if (final_partition->type == ESP_PARTITION_TYPE_BOOTLOADER) {
|
||||
esp_image_bootloader_offset_set(it->partition.staging->address);
|
||||
}
|
||||
if (final_partition->type == ESP_PARTITION_TYPE_BOOTLOADER || final_partition->type == ESP_PARTITION_TYPE_PARTITION_TABLE) {
|
||||
esp_flash_set_dangerous_write_protection(esp_flash_default_chip, false);
|
||||
}
|
||||
}
|
||||
|
||||
new_entry = esp_ota_init_entry(partition);
|
||||
if (new_entry == NULL) {
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
|
||||
new_entry->ota_resumption = true;
|
||||
new_entry->wrote_size = image_offset;
|
||||
new_entry->need_erase = (erase_size == OTA_WITH_SEQUENTIAL_WRITES);
|
||||
*out_handle = new_entry->handle;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
@@ -244,23 +238,33 @@ esp_err_t esp_ota_write(esp_ota_handle_t handle, const void *data, size_t size)
|
||||
if (it->handle == handle) {
|
||||
if (it->need_erase) {
|
||||
// must erase the partition before writing to it
|
||||
uint32_t first_sector = it->wrote_size / it->part->erase_size; // first affected sector
|
||||
uint32_t last_sector = (it->wrote_size + size - 1) / it->part->erase_size; // last affected sector
|
||||
uint32_t first_sector = it->wrote_size / it->partition.staging->erase_size; // first affected sector
|
||||
uint32_t last_sector = (it->wrote_size + size - 1) / it->partition.staging->erase_size; // last affected sector
|
||||
|
||||
ret = ESP_OK;
|
||||
if ((it->wrote_size % it->part->erase_size) == 0) {
|
||||
ret = esp_partition_erase_range(it->part, it->wrote_size, ((last_sector - first_sector) + 1) * it->part->erase_size);
|
||||
if ((it->wrote_size % it->partition.staging->erase_size) == 0) {
|
||||
ret = esp_partition_erase_range(it->partition.staging, it->wrote_size, ((last_sector - first_sector) + 1) * it->partition.staging->erase_size);
|
||||
} else if (first_sector != last_sector) {
|
||||
ret = esp_partition_erase_range(it->part, (first_sector + 1) * it->part->erase_size, (last_sector - first_sector) * it->part->erase_size);
|
||||
ret = esp_partition_erase_range(it->partition.staging, (first_sector + 1) * it->partition.staging->erase_size, (last_sector - first_sector) * it->partition.staging->erase_size);
|
||||
}
|
||||
if (ret != ESP_OK) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
if (it->wrote_size == 0 && it->partial_bytes == 0 && size > 0 && data_bytes[0] != ESP_IMAGE_HEADER_MAGIC) {
|
||||
ESP_LOGE(TAG, "OTA image has invalid magic byte (expected 0xE9, saw 0x%02x)", data_bytes[0]);
|
||||
return ESP_ERR_OTA_VALIDATE_FAILED;
|
||||
if (it->wrote_size == 0 && it->partial_bytes == 0 && size > 0) {
|
||||
if (it->partition.final->type == ESP_PARTITION_TYPE_APP || it->partition.final->type == ESP_PARTITION_TYPE_BOOTLOADER) {
|
||||
if (data_bytes[0] != ESP_IMAGE_HEADER_MAGIC) {
|
||||
ESP_LOGE(TAG, "OTA image has invalid magic byte (expected 0xE9, saw 0x%02x)", data_bytes[0]);
|
||||
return ESP_ERR_OTA_VALIDATE_FAILED;
|
||||
}
|
||||
|
||||
} else if (it->partition.final->type == ESP_PARTITION_TYPE_PARTITION_TABLE) {
|
||||
if (*(uint16_t*)data_bytes != (uint16_t)ESP_PARTITION_MAGIC) {
|
||||
ESP_LOGE(TAG, "Partition table image has invalid magic word (expected 0x50AA, saw 0x%04x)", *(uint16_t*)data_bytes);
|
||||
return ESP_ERR_OTA_VALIDATE_FAILED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (esp_flash_encryption_enabled()) {
|
||||
@@ -276,7 +280,7 @@ esp_err_t esp_ota_write(esp_ota_handle_t handle, const void *data, size_t size)
|
||||
return ESP_OK; /* nothing to write yet, just filling buffer */
|
||||
}
|
||||
/* write 16 byte to partition */
|
||||
ret = esp_partition_write(it->part, it->wrote_size, it->partial_data, 16);
|
||||
ret = esp_partition_write(it->partition.staging, it->wrote_size, it->partial_data, 16);
|
||||
if (ret != ESP_OK) {
|
||||
return ret;
|
||||
}
|
||||
@@ -295,7 +299,7 @@ esp_err_t esp_ota_write(esp_ota_handle_t handle, const void *data, size_t size)
|
||||
}
|
||||
}
|
||||
|
||||
ret = esp_partition_write(it->part, it->wrote_size, data_bytes, size);
|
||||
ret = esp_partition_write(it->partition.staging, it->wrote_size, data_bytes, size);
|
||||
if(ret == ESP_OK){
|
||||
it->wrote_size += size;
|
||||
}
|
||||
@@ -332,7 +336,7 @@ esp_err_t esp_ota_write_with_offset(esp_ota_handle_t handle, const void *data, s
|
||||
ESP_LOGE(TAG, "Size should be 16byte aligned for flash encryption case");
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
ret = esp_partition_write(it->part, offset, data_bytes, size);
|
||||
ret = esp_partition_write(it->partition.staging, offset, data_bytes, size);
|
||||
if (ret == ESP_OK) {
|
||||
it->wrote_size += size;
|
||||
}
|
||||
@@ -368,6 +372,34 @@ esp_err_t esp_ota_abort(esp_ota_handle_t handle)
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t ota_verify_partition(ota_ops_entry_t *ota_ops)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
if (ota_ops->partition.final->type == ESP_PARTITION_TYPE_APP || ota_ops->partition.final->type == ESP_PARTITION_TYPE_BOOTLOADER) {
|
||||
esp_image_metadata_t data;
|
||||
const esp_partition_pos_t part_pos = {
|
||||
.offset = ota_ops->partition.staging->address,
|
||||
.size = ota_ops->partition.staging->size,
|
||||
};
|
||||
if (esp_image_verify(ESP_IMAGE_VERIFY, &part_pos, &data) != ESP_OK) {
|
||||
return ESP_ERR_OTA_VALIDATE_FAILED;
|
||||
}
|
||||
} else if (ota_ops->partition.final->type == ESP_PARTITION_TYPE_PARTITION_TABLE) {
|
||||
const esp_partition_info_t *partition_table = NULL;
|
||||
esp_partition_mmap_handle_t partition_table_map;
|
||||
ret = esp_partition_mmap(ota_ops->partition.staging, 0, ESP_PARTITION_TABLE_MAX_LEN, ESP_PARTITION_MMAP_DATA, (const void**)&partition_table, &partition_table_map);
|
||||
if (ret == ESP_OK) {
|
||||
int num_partitions;
|
||||
if (esp_partition_table_verify(partition_table, true, &num_partitions) != ESP_OK) {
|
||||
esp_partition_munmap(partition_table_map);
|
||||
return ESP_ERR_OTA_VALIDATE_FAILED;
|
||||
}
|
||||
esp_partition_munmap(partition_table_map);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t esp_ota_end(esp_ota_handle_t handle)
|
||||
{
|
||||
ota_ops_entry_t *it = get_ota_ops_entry(handle);
|
||||
@@ -387,7 +419,7 @@ esp_err_t esp_ota_end(esp_ota_handle_t handle)
|
||||
|
||||
if (it->partial_bytes > 0) {
|
||||
/* Write out last 16 bytes, if necessary */
|
||||
ret = esp_partition_write(it->part, it->wrote_size, it->partial_data, 16);
|
||||
ret = esp_partition_write(it->partition.staging, it->wrote_size, it->partial_data, 16);
|
||||
if (ret != ESP_OK) {
|
||||
ret = ESP_ERR_INVALID_STATE;
|
||||
goto cleanup;
|
||||
@@ -396,18 +428,21 @@ esp_err_t esp_ota_end(esp_ota_handle_t handle)
|
||||
it->partial_bytes = 0;
|
||||
}
|
||||
|
||||
esp_image_metadata_t data;
|
||||
const esp_partition_pos_t part_pos = {
|
||||
.offset = it->part->address,
|
||||
.size = it->part->size,
|
||||
};
|
||||
|
||||
if (esp_image_verify(ESP_IMAGE_VERIFY, &part_pos, &data) != ESP_OK) {
|
||||
ret = ESP_ERR_OTA_VALIDATE_FAILED;
|
||||
goto cleanup;
|
||||
ret = ota_verify_partition(it);
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE(TAG, "New image failed verification");
|
||||
} else {
|
||||
if (it->partition.finalize_with_copy) {
|
||||
ESP_LOGI(TAG, "Copy from <%s> staging partition to <%s>...", it->partition.staging->label, it->partition.final->label);
|
||||
ret = esp_partition_copy(it->partition.final, 0, it->partition.staging, 0, it->partition.final->size);
|
||||
}
|
||||
}
|
||||
|
||||
cleanup:
|
||||
if (it->partition.final->type == ESP_PARTITION_TYPE_BOOTLOADER) {
|
||||
// In esp_ota_begin, bootloader offset was updated, here we return it to default.
|
||||
esp_image_bootloader_offset_set(ESP_PRIMARY_BOOTLOADER_OFFSET);
|
||||
}
|
||||
LIST_REMOVE(it, entries);
|
||||
free(it);
|
||||
return ret;
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
@@ -82,7 +82,11 @@ int esp_ota_get_app_elf_sha256(char* dst, size_t size) __attribute__((deprecated
|
||||
* it will lead to the ESP_ERR_OTA_ROLLBACK_INVALID_STATE error. Confirm the running app before to run download a new app,
|
||||
* use esp_ota_mark_app_valid_cancel_rollback() function for it (this should be done as early as possible when you first download a new application).
|
||||
*
|
||||
* @param partition Pointer to info for partition which will receive the OTA update. Required.
|
||||
* Note: Rollback is applicable only for app type partitions.
|
||||
*
|
||||
* @param partition Pointer to info for partition which will receive the OTA update. Required.
|
||||
* This is considered as the staging partition (where OTA is downloaded), be default this also considered as the final partition which supposed to be updated.
|
||||
* The final partition can be overwritten using esp_ota_set_final_partition() after calling esp_ota_begin() to relocate contents to the final destination partition.
|
||||
* @param image_size Size of new OTA app image. Partition will be erased in order to receive this size of image. If 0 or OTA_SIZE_UNKNOWN, the entire partition is erased.
|
||||
* @param out_handle On success, returns a handle which should be used for subsequent esp_ota_write() and esp_ota_end() calls.
|
||||
|
||||
@@ -100,30 +104,29 @@ int esp_ota_get_app_elf_sha256(char* dst, size_t size) __attribute__((deprecated
|
||||
esp_err_t esp_ota_begin(const esp_partition_t* partition, size_t image_size, esp_ota_handle_t* out_handle);
|
||||
|
||||
/**
|
||||
* @brief Resume an interrupted OTA update by continuing to write to the specified partition.
|
||||
* @brief Set the final destination partition for OTA update
|
||||
*
|
||||
* This function is used when an OTA update was previously started and needs to be resumed after an interruption.
|
||||
* It continues the OTA process from the specified offset within the partition.
|
||||
* This function configures the specified final partition as the destination for the OTA update.
|
||||
* It also allows setting a flag to indicate if the image should be copied from the staging
|
||||
* partition to the final partition after the OTA update completes. Otherwise, copying will need
|
||||
* to be handled by custom code using esp_partition_copy().
|
||||
*
|
||||
* Unlike esp_ota_begin(), this function does not erase the partition which receives the OTA update, but rather expects that part of the image
|
||||
* has already been written correctly, and it resumes writing from the given offset.
|
||||
* @note This can be called after esp_ota_begin() and before the OTA update has started (before esp_ota_write()).
|
||||
*
|
||||
* @param partition Pointer to info for the partition which is receiving the OTA update. Required.
|
||||
* @param erase_size Specifies how much flash memory to erase before resuming OTA, depending on whether a sequential write or a bulk erase is being used.
|
||||
* @param image_offset Offset from where to resume the OTA process. Should be set to the number of bytes already written.
|
||||
* @param out_handle On success, returns a handle that should be used for subsequent esp_ota_write() and esp_ota_end() calls.
|
||||
* @param handle OTA update handle obtained from esp_ota_begin().
|
||||
* @param final Pointer to the final destination partition where the new image will be verified and potentially finalized.
|
||||
* This partition must not be NULL.
|
||||
* @param finalize_with_copy Boolean flag indicating if the downloaded image should be copied
|
||||
* from the staging partition to the final partition upon completion.
|
||||
* Set to False if you intend to perform the final copy process manually later.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: OTA operation resumed successfully.
|
||||
* - ESP_ERR_INVALID_ARG: partition, out_handle were NULL or image_offset arguments is negative, or partition doesn't point to an OTA app partition.
|
||||
* - ESP_ERR_NO_MEM: Cannot allocate memory for OTA operation.
|
||||
* - ESP_ERR_OTA_PARTITION_CONFLICT: Partition holds the currently running firmware, cannot update in place.
|
||||
* - ESP_ERR_NOT_FOUND: Partition argument not found in partition table.
|
||||
* - ESP_ERR_OTA_SELECT_INFO_INVALID: The OTA data partition contains invalid data.
|
||||
* - ESP_ERR_INVALID_SIZE: Partition doesn't fit in configured flash size.
|
||||
* - ESP_ERR_FLASH_OP_TIMEOUT or ESP_ERR_FLASH_OP_FAIL: Flash write failed.
|
||||
* - ESP_OK: final destination partition set successfully.
|
||||
* - ESP_ERR_INVALID_STATE: Once the OTA update has started, changing the final destination partition is prohibited.
|
||||
* - ESP_ERR_INVALID_ARG: Invalid arguments were passed (e.g., final partition is NULL).
|
||||
* - ESP_ERR_NOT_FOUND: OTA handle not found or final partition verification failed.
|
||||
*/
|
||||
esp_err_t esp_ota_resume(const esp_partition_t *partition, const size_t erase_size, const size_t image_offset, esp_ota_handle_t *out_handle);
|
||||
esp_err_t esp_ota_set_final_partition(esp_ota_handle_t handle, const esp_partition_t *final, bool finalize_with_copy);
|
||||
|
||||
/**
|
||||
* @brief Write OTA update data to partition
|
||||
@@ -139,9 +142,8 @@ esp_err_t esp_ota_resume(const esp_partition_t *partition, const size_t erase_si
|
||||
* @return
|
||||
* - ESP_OK: Data was written to flash successfully, or size = 0
|
||||
* - ESP_ERR_INVALID_ARG: handle is invalid.
|
||||
* - ESP_ERR_OTA_VALIDATE_FAILED: First byte of image contains invalid app image magic byte.
|
||||
* - ESP_ERR_OTA_VALIDATE_FAILED: First byte of image contains invalid image magic byte.
|
||||
* - ESP_ERR_FLASH_OP_TIMEOUT or ESP_ERR_FLASH_OP_FAIL: Flash write failed.
|
||||
* - ESP_ERR_OTA_SELECT_INFO_INVALID: OTA data partition has invalid contents
|
||||
* - ESP_ERR_INVALID_SIZE: if write would go out of bounds of the partition
|
||||
* - or one of error codes from lower-level flash driver.
|
||||
*/
|
||||
@@ -164,9 +166,7 @@ esp_err_t esp_ota_write(esp_ota_handle_t handle, const void* data, size_t size);
|
||||
* @return
|
||||
* - ESP_OK: Data was written to flash successfully.
|
||||
* - ESP_ERR_INVALID_ARG: handle is invalid.
|
||||
* - ESP_ERR_OTA_VALIDATE_FAILED: First byte of image contains invalid app image magic byte.
|
||||
* - ESP_ERR_FLASH_OP_TIMEOUT or ESP_ERR_FLASH_OP_FAIL: Flash write failed.
|
||||
* - ESP_ERR_OTA_SELECT_INFO_INVALID: OTA data partition has invalid contents
|
||||
*/
|
||||
esp_err_t esp_ota_write_with_offset(esp_ota_handle_t handle, const void *data, size_t size, uint32_t offset);
|
||||
|
||||
@@ -176,6 +176,11 @@ esp_err_t esp_ota_write_with_offset(esp_ota_handle_t handle, const void *data, s
|
||||
* @param handle Handle obtained from esp_ota_begin().
|
||||
*
|
||||
* @note After calling esp_ota_end(), the handle is no longer valid and any memory associated with it is freed (regardless of result).
|
||||
* @note If either the final or staging partitions were for the bootloader, then at the end of this function,
|
||||
* the bootloader is reset to its default offset: esp_image_bootloader_offset_set(ESP_PRIMARY_BOOTLOADER_OFFSET)
|
||||
*
|
||||
* If the finalize_with_copy option is set, the staging partition will be copied to the final partition at the end of this function.
|
||||
* Otherwise, copying will need to be handled by custom code using esp_partition_copy().
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: Newly written OTA app image is valid.
|
||||
@@ -284,7 +289,7 @@ esp_err_t esp_ota_get_partition_description(const esp_partition_t *partition, es
|
||||
* @brief Returns the description structure of the bootloader.
|
||||
*
|
||||
* @param[in] bootloader_partition Pointer to bootloader partition.
|
||||
* If NULL, then the current bootloader is used (the default location).
|
||||
* If NULL, then the PRIMARY bootloader is used (the default location).
|
||||
* offset = CONFIG_BOOTLOADER_OFFSET_IN_FLASH,
|
||||
* size = CONFIG_PARTITION_TABLE_OFFSET - CONFIG_BOOTLOADER_OFFSET_IN_FLASH,
|
||||
* @param[out] desc Structure of info about bootloader.
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
components/app_update/test_apps:
|
||||
enable:
|
||||
- if: CONFIG_NAME == "defaults" and IDF_TARGET != "linux"
|
||||
- if: CONFIG_NAME == "defaults" and IDF_TARGET in ["esp32", "esp32c2", "esp32c3", "esp32c5", "esp32c6", "esp32c61", "esp32h2", "esp32p4", "esp32s2", "esp32s3"]
|
||||
- if: CONFIG_NAME == "xip_psram" and IDF_TARGET in ["esp32s2", "esp32s3", "esp32p4"]
|
||||
# S2 doesn't have ROM for flash
|
||||
- if: CONFIG_NAME == "xip_psram_with_rom_impl" and IDF_TARGET in ["esp32s3", "esp32p4"]
|
||||
|
||||
@@ -0,0 +1,256 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include "esp_ota_ops.h"
|
||||
#include "esp_partition.h"
|
||||
#include "esp_flash_partitions.h"
|
||||
#include "esp_flash_internal.h"
|
||||
#include "spi_flash_mmap.h"
|
||||
#include "esp_image_format.h"
|
||||
#include "esp_system.h"
|
||||
#include "esp_log.h"
|
||||
#include "unity.h"
|
||||
#include "nvs_flash.h"
|
||||
#include "sdkconfig.h"
|
||||
|
||||
static const char *TAG = "test";
|
||||
|
||||
static uint8_t buffer[SPI_FLASH_SEC_SIZE];
|
||||
|
||||
// Find the unused offset after the last partition, checking that it is of the required size
|
||||
static uint32_t find_unused_space(size_t required_size)
|
||||
{
|
||||
esp_partition_iterator_t it = esp_partition_find(ESP_PARTITION_TYPE_ANY, ESP_PARTITION_SUBTYPE_ANY, NULL);
|
||||
TEST_ASSERT_NOT_NULL(it);
|
||||
const esp_partition_t* latest_partition = esp_partition_get(it);
|
||||
for (; it != NULL; it = esp_partition_next(it)) {
|
||||
const esp_partition_t *p = esp_partition_get(it);
|
||||
if (p->address > latest_partition->address) {
|
||||
latest_partition = p;
|
||||
}
|
||||
}
|
||||
esp_partition_iterator_release(it);
|
||||
TEST_ASSERT_NOT_NULL(latest_partition);
|
||||
|
||||
#if CONFIG_IDF_TARGET_LINUX
|
||||
uint32_t flash_chip_size;
|
||||
esp_flash_get_size(NULL, &flash_chip_size);
|
||||
#else
|
||||
uint32_t flash_chip_size = esp_flash_default_chip->size;
|
||||
#endif // CONFIG_IDF_TARGET_LINUX
|
||||
uint32_t unused_offset = latest_partition->address + latest_partition->size;
|
||||
TEST_ASSERT_GREATER_OR_EQUAL_UINT32(required_size, flash_chip_size - unused_offset);
|
||||
return unused_offset;
|
||||
}
|
||||
|
||||
static void check_after_reboot(void)
|
||||
{
|
||||
ESP_LOGI(TAG, "App runs");
|
||||
}
|
||||
|
||||
static void download_new_image_from_partition(esp_ota_handle_t update_handle, const esp_partition_t *copy_from_part)
|
||||
{
|
||||
uint32_t offset = 0;
|
||||
ESP_LOGI(TAG, "Downloading image...");
|
||||
do {
|
||||
TEST_ESP_OK(esp_partition_read(copy_from_part, offset, buffer, sizeof(buffer)));
|
||||
TEST_ESP_OK(esp_ota_write(update_handle, buffer, sizeof(buffer)));
|
||||
offset += sizeof(buffer);
|
||||
} while (offset < copy_from_part->size);
|
||||
}
|
||||
|
||||
static void start_bootloader_ota_update_via_ota_bootloader_part(void)
|
||||
{
|
||||
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 *ota_bootloader;
|
||||
const uint32_t ota_bootloader_offset = find_unused_space(ESP_BOOTLOADER_SIZE);
|
||||
TEST_ESP_OK(esp_partition_register_external(NULL, ota_bootloader_offset, ESP_BOOTLOADER_SIZE, "OtaBTLDR", ESP_PARTITION_TYPE_BOOTLOADER, ESP_PARTITION_SUBTYPE_BOOTLOADER_OTA, &ota_bootloader));
|
||||
|
||||
esp_ota_handle_t update_handle;
|
||||
TEST_ESP_OK(esp_ota_begin(ota_bootloader, OTA_WITH_SEQUENTIAL_WRITES, &update_handle));
|
||||
TEST_ESP_OK(esp_ota_set_final_partition(update_handle, primary_bootloader, true));
|
||||
download_new_image_from_partition(update_handle, primary_bootloader);
|
||||
TEST_ESP_OK(esp_ota_end(update_handle));
|
||||
|
||||
TEST_ESP_OK(esp_partition_deregister_external(primary_bootloader));
|
||||
TEST_ESP_OK(esp_partition_deregister_external(ota_bootloader));
|
||||
esp_restart();
|
||||
}
|
||||
|
||||
TEST_CASE_MULTIPLE_STAGES("OTA update of bootloader via temp partition", "[bootloader_ota][reset=SW_CPU_RESET]", start_bootloader_ota_update_via_ota_bootloader_part, check_after_reboot);
|
||||
|
||||
static void start_bootloader_ota_update_via_primary_bootloader_part(void)
|
||||
{
|
||||
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));
|
||||
|
||||
esp_ota_handle_t update_handle;
|
||||
TEST_ESP_OK(esp_ota_begin(primary_bootloader, OTA_WITH_SEQUENTIAL_WRITES, &update_handle));
|
||||
download_new_image_from_partition(update_handle, primary_bootloader);
|
||||
TEST_ESP_OK(esp_ota_end(update_handle));
|
||||
|
||||
TEST_ESP_OK(esp_partition_deregister_external(primary_bootloader));
|
||||
esp_restart();
|
||||
}
|
||||
|
||||
TEST_CASE_MULTIPLE_STAGES("OTA update of bootloader via primary partition", "[bootloader_ota][reset=SW_CPU_RESET]", start_bootloader_ota_update_via_primary_bootloader_part, check_after_reboot);
|
||||
|
||||
static void start_partition_table_ota_update_via_ota_part_table(void)
|
||||
{
|
||||
const esp_partition_t *primary_partition_table;
|
||||
const esp_partition_t *ota_partition_table;
|
||||
TEST_ESP_OK(esp_partition_register_external(NULL, ESP_PRIMARY_PARTITION_TABLE_OFFSET, ESP_PARTITION_TABLE_SIZE, "PrimaryPrtTable", ESP_PARTITION_TYPE_PARTITION_TABLE, ESP_PARTITION_SUBTYPE_PARTITION_TABLE_PRIMARY, &primary_partition_table));
|
||||
|
||||
uint32_t ota_partition_table_offset = find_unused_space(ESP_PARTITION_TABLE_SIZE);
|
||||
TEST_ESP_OK(esp_partition_register_external(NULL, ota_partition_table_offset, ESP_PARTITION_TABLE_SIZE, "OtaPrtTable", ESP_PARTITION_TYPE_PARTITION_TABLE, ESP_PARTITION_SUBTYPE_PARTITION_TABLE_OTA, &ota_partition_table));
|
||||
|
||||
esp_ota_handle_t update_handle;
|
||||
TEST_ESP_OK(esp_ota_begin(ota_partition_table, OTA_WITH_SEQUENTIAL_WRITES, &update_handle));
|
||||
TEST_ESP_OK(esp_ota_set_final_partition(update_handle, primary_partition_table, true));
|
||||
download_new_image_from_partition(update_handle, primary_partition_table);
|
||||
TEST_ESP_OK(esp_ota_end(update_handle));
|
||||
|
||||
TEST_ESP_OK(esp_partition_deregister_external(primary_partition_table));
|
||||
TEST_ESP_OK(esp_partition_deregister_external(ota_partition_table));
|
||||
esp_restart();
|
||||
}
|
||||
|
||||
TEST_CASE_MULTIPLE_STAGES("OTA update of partition_table via temp partition", "[partition_table_ota][reset=SW_CPU_RESET]", start_partition_table_ota_update_via_ota_part_table, check_after_reboot);
|
||||
|
||||
static void start_partition_table_ota_update_via_primary_part_table(void)
|
||||
{
|
||||
const esp_partition_t *primary_partition_table;
|
||||
TEST_ESP_OK(esp_partition_register_external(NULL, ESP_PRIMARY_PARTITION_TABLE_OFFSET, ESP_PARTITION_TABLE_SIZE, "PrimaryPrtTable", ESP_PARTITION_TYPE_PARTITION_TABLE, ESP_PARTITION_SUBTYPE_PARTITION_TABLE_PRIMARY, &primary_partition_table));
|
||||
|
||||
esp_ota_handle_t update_handle;
|
||||
TEST_ESP_OK(esp_ota_begin(primary_partition_table, OTA_WITH_SEQUENTIAL_WRITES, &update_handle));
|
||||
download_new_image_from_partition(update_handle, primary_partition_table);
|
||||
TEST_ESP_OK(esp_ota_end(update_handle));
|
||||
|
||||
TEST_ESP_OK(esp_partition_deregister_external(primary_partition_table));
|
||||
esp_restart();
|
||||
}
|
||||
|
||||
TEST_CASE_MULTIPLE_STAGES("OTA update of partition_table via primary partition", "[partition_table_ota][reset=SW_CPU_RESET]", start_partition_table_ota_update_via_primary_part_table, check_after_reboot);
|
||||
|
||||
TEST_CASE("OTA update of NVS partition", "[nvs_ota]")
|
||||
{
|
||||
// intilaize "nvs" partition and define a var (magic_value).
|
||||
TEST_ESP_OK(nvs_flash_erase());
|
||||
TEST_ESP_OK(nvs_flash_init());
|
||||
nvs_handle_t my_handle;
|
||||
TEST_ESP_OK(nvs_open("namespace", NVS_READWRITE, &my_handle));
|
||||
uint32_t magic_value = 0x0729FEED;
|
||||
TEST_ESP_OK(nvs_set_u32(my_handle, "magic_value", magic_value));
|
||||
TEST_ESP_OK(nvs_commit(my_handle));
|
||||
magic_value = 0;
|
||||
TEST_ESP_OK(nvs_get_u32(my_handle, "magic_value", &magic_value));
|
||||
TEST_ASSERT_EQUAL_HEX(0x0729FEED, magic_value);
|
||||
nvs_close(my_handle);
|
||||
TEST_ESP_OK(nvs_flash_deinit());
|
||||
|
||||
// register a new "nvs2" partition
|
||||
const esp_partition_t *nvs_part = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_NVS, "nvs");
|
||||
const esp_partition_t *nvs2_part;
|
||||
TEST_ESP_OK(esp_partition_register_external(NULL, find_unused_space(nvs_part->size), nvs_part->size, "nvs2", ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_NVS, &nvs2_part));
|
||||
ESP_LOGI(TAG, "Use %s partition (0x%08" PRIx32 ") to load a new image", nvs2_part->label, nvs2_part->address);
|
||||
TEST_ESP_OK(nvs_flash_erase_partition("nvs2"));
|
||||
|
||||
// OTA update of the new "nvs2" partition, taking "nvs" partition as source.
|
||||
esp_ota_handle_t update_handle;
|
||||
TEST_ESP_OK(esp_ota_begin(nvs2_part, OTA_WITH_SEQUENTIAL_WRITES, &update_handle));
|
||||
download_new_image_from_partition(update_handle, nvs_part);
|
||||
TEST_ESP_OK(esp_ota_end(update_handle));
|
||||
|
||||
// init "nvs2" partition and check if the magic_value == 0x0729FEED
|
||||
TEST_ESP_OK(nvs_flash_init_partition("nvs2"));
|
||||
nvs_handle_t my_handle2;
|
||||
TEST_ESP_OK(nvs_open_from_partition("nvs2", "namespace", NVS_READWRITE, &my_handle2));
|
||||
magic_value = 0;
|
||||
TEST_ESP_OK(nvs_get_u32(my_handle2, "magic_value", &magic_value));
|
||||
TEST_ASSERT_EQUAL_HEX(0x0729FEED, magic_value);
|
||||
nvs_close(my_handle2);
|
||||
TEST_ESP_OK(nvs_flash_deinit_partition("nvs2"));
|
||||
|
||||
// deregister "nvs2"
|
||||
TEST_ESP_OK(esp_partition_deregister_external(nvs2_part));
|
||||
|
||||
TEST_ESP_OK(nvs_flash_erase());
|
||||
}
|
||||
|
||||
static void start_bootloader_ota_update_via_app_part(void)
|
||||
{
|
||||
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 *free_app_ota_partition = esp_ota_get_next_update_partition(NULL);
|
||||
esp_ota_handle_t update_handle;
|
||||
TEST_ESP_OK(esp_ota_begin(free_app_ota_partition, OTA_WITH_SEQUENTIAL_WRITES, &update_handle));
|
||||
TEST_ESP_OK(esp_ota_set_final_partition(update_handle, primary_bootloader, true));
|
||||
download_new_image_from_partition(update_handle, primary_bootloader);
|
||||
TEST_ESP_OK(esp_ota_end(update_handle));
|
||||
|
||||
TEST_ESP_OK(esp_partition_deregister_external(primary_bootloader));
|
||||
esp_restart();
|
||||
}
|
||||
|
||||
TEST_CASE_MULTIPLE_STAGES("OTA update of bootloader via a free ota partition", "[bootloader_ota][reset=SW_CPU_RESET]", start_bootloader_ota_update_via_app_part, check_after_reboot);
|
||||
|
||||
static void start_partition_table_ota_update_via_app_part(void)
|
||||
{
|
||||
const esp_partition_t *primary_partition_table;
|
||||
TEST_ESP_OK(esp_partition_register_external(NULL, ESP_PRIMARY_PARTITION_TABLE_OFFSET, ESP_PARTITION_TABLE_SIZE, "PrimaryPrtTable", ESP_PARTITION_TYPE_PARTITION_TABLE, ESP_PARTITION_SUBTYPE_PARTITION_TABLE_PRIMARY, &primary_partition_table));
|
||||
|
||||
const esp_partition_t *free_app_ota_partition = esp_ota_get_next_update_partition(NULL);
|
||||
esp_ota_handle_t update_handle;
|
||||
TEST_ESP_OK(esp_ota_begin(free_app_ota_partition, OTA_WITH_SEQUENTIAL_WRITES, &update_handle));
|
||||
TEST_ESP_OK(esp_ota_set_final_partition(update_handle, primary_partition_table, true));
|
||||
download_new_image_from_partition(update_handle, primary_partition_table);
|
||||
TEST_ESP_OK(esp_ota_end(update_handle));
|
||||
|
||||
TEST_ESP_OK(esp_partition_deregister_external(primary_partition_table));
|
||||
esp_restart();
|
||||
}
|
||||
|
||||
TEST_CASE_MULTIPLE_STAGES("OTA update of partition_table via a free ota partition", "[partition_table_ota][reset=SW_CPU_RESET]", start_partition_table_ota_update_via_app_part, check_after_reboot);
|
||||
|
||||
TEST_CASE("OTA update of NVS partition via a free ota partition", "[nvs_ota]")
|
||||
{
|
||||
// intilaize "nvs" partition and define a var (magic_value).
|
||||
const esp_partition_t *nvs_part = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_NVS, "nvs");
|
||||
TEST_ESP_OK(nvs_flash_erase());
|
||||
TEST_ESP_OK(nvs_flash_init());
|
||||
nvs_handle_t my_handle;
|
||||
TEST_ESP_OK(nvs_open("namespace", NVS_READWRITE, &my_handle));
|
||||
uint32_t magic_value = 0x0729FEED;
|
||||
TEST_ESP_OK(nvs_set_u32(my_handle, "magic_value", magic_value));
|
||||
TEST_ESP_OK(nvs_commit(my_handle));
|
||||
magic_value = 0;
|
||||
TEST_ESP_OK(nvs_get_u32(my_handle, "magic_value", &magic_value));
|
||||
TEST_ASSERT_EQUAL_HEX(0x0729FEED, magic_value);
|
||||
nvs_close(my_handle);
|
||||
TEST_ESP_OK(nvs_flash_deinit());
|
||||
|
||||
// 1. OTA update nvs partition into free_app_ota_partition
|
||||
// 2. copy free_app_ota_partition into the original nvs partition (which was erased before coping)
|
||||
const esp_partition_t *free_app_ota_partition = esp_ota_get_next_update_partition(NULL);
|
||||
esp_ota_handle_t update_handle;
|
||||
TEST_ESP_OK(esp_ota_begin(free_app_ota_partition, OTA_WITH_SEQUENTIAL_WRITES, &update_handle));
|
||||
TEST_ESP_OK(esp_ota_set_final_partition(update_handle, nvs_part, true));
|
||||
download_new_image_from_partition(update_handle, nvs_part);
|
||||
TEST_ESP_OK(esp_ota_end(update_handle));
|
||||
|
||||
// Check if the magic_value == 0x0729FEED
|
||||
TEST_ESP_OK(nvs_flash_init());
|
||||
TEST_ESP_OK(nvs_open("namespace", NVS_READONLY, &my_handle));
|
||||
magic_value = 0;
|
||||
TEST_ESP_OK(nvs_get_u32(my_handle, "magic_value", &magic_value));
|
||||
TEST_ASSERT_EQUAL_HEX(0x0729FEED, magic_value);
|
||||
nvs_close(my_handle);
|
||||
TEST_ESP_OK(nvs_flash_deinit());
|
||||
TEST_ESP_OK(nvs_flash_erase());
|
||||
}
|
||||
@@ -43,7 +43,12 @@ static const char *TAG = "ota_test";
|
||||
static void set_boot_count_in_nvs(uint8_t boot_count)
|
||||
{
|
||||
nvs_handle_t boot_count_handle;
|
||||
TEST_ESP_OK(nvs_open(BOOT_COUNT_NAMESPACE, NVS_READWRITE, &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);
|
||||
|
||||
68
components/bootloader/Kconfig.app_rollback
Normal file
68
components/bootloader/Kconfig.app_rollback
Normal file
@@ -0,0 +1,68 @@
|
||||
menu "Application Rollback"
|
||||
|
||||
config BOOTLOADER_APP_ROLLBACK_ENABLE
|
||||
bool "Enable app rollback support"
|
||||
default n
|
||||
help
|
||||
After updating the app, the bootloader runs a new app with the "ESP_OTA_IMG_PENDING_VERIFY" state set.
|
||||
This state prevents the re-run of this app. After the first boot of the new app in the user code, the
|
||||
function should be called to confirm the operability of the app or vice versa about its non-operability.
|
||||
If the app is working, then it is marked as valid. Otherwise, it is marked as not valid and rolls back to
|
||||
the previous working app. A reboot is performed, and the app is booted before the software update.
|
||||
Note: If during the first boot a new app the power goes out or the WDT works, then roll back will happen.
|
||||
Rollback is possible only between the apps with the same security versions.
|
||||
|
||||
config BOOTLOADER_APP_ANTI_ROLLBACK
|
||||
bool "Enable app anti-rollback support"
|
||||
depends on BOOTLOADER_APP_ROLLBACK_ENABLE
|
||||
default n
|
||||
help
|
||||
This option prevents rollback to previous firmware/application image with lower security version.
|
||||
|
||||
config BOOTLOADER_APP_SECURE_VERSION
|
||||
int "eFuse secure version of app"
|
||||
depends on BOOTLOADER_APP_ANTI_ROLLBACK
|
||||
default 0
|
||||
help
|
||||
The secure version is the sequence number stored in the header of each firmware.
|
||||
The security version is set in the bootloader, version is recorded in the eFuse field
|
||||
as the number of set ones. The allocated number of bits in the efuse field
|
||||
for storing the security version is limited (see BOOTLOADER_APP_SEC_VER_SIZE_EFUSE_FIELD option).
|
||||
|
||||
Bootloader: When bootloader selects an app to boot, an app is selected that has
|
||||
a security version greater or equal that recorded in eFuse field.
|
||||
The app is booted with a higher (or equal) secure version.
|
||||
|
||||
The security version is worth increasing if in previous versions there is
|
||||
a significant vulnerability and their use is not acceptable.
|
||||
|
||||
Your partition table should has a scheme with ota_0 + ota_1 (without factory).
|
||||
|
||||
config BOOTLOADER_APP_SEC_VER_SIZE_EFUSE_FIELD
|
||||
int "Size of the efuse secure version field"
|
||||
depends on BOOTLOADER_APP_ANTI_ROLLBACK
|
||||
range 1 32 if IDF_TARGET_ESP32
|
||||
default 32 if IDF_TARGET_ESP32
|
||||
range 1 4 if IDF_TARGET_ESP32C2
|
||||
default 4 if IDF_TARGET_ESP32C2
|
||||
range 1 16
|
||||
default 16
|
||||
help
|
||||
The size of the efuse secure version field.
|
||||
Its length is limited to 32 bits for ESP32 and 16 bits for ESP32-S2.
|
||||
This determines how many times the security version can be increased.
|
||||
|
||||
config BOOTLOADER_EFUSE_SECURE_VERSION_EMULATE
|
||||
bool "Emulate operations with efuse secure version(only test)"
|
||||
default n
|
||||
depends on BOOTLOADER_APP_ANTI_ROLLBACK
|
||||
select EFUSE_VIRTUAL
|
||||
select EFUSE_VIRTUAL_KEEP_IN_FLASH
|
||||
help
|
||||
This option allows to emulate read/write operations with all eFuses and efuse secure version.
|
||||
It allows to test anti-rollback implementation without permanent write eFuse bits.
|
||||
There should be an entry in partition table with following details: `emul_efuse, data, efuse, , 0x2000`.
|
||||
|
||||
This option enables: EFUSE_VIRTUAL and EFUSE_VIRTUAL_KEEP_IN_FLASH.
|
||||
|
||||
endmenu
|
||||
25
components/bootloader/Kconfig.bootloader_rollback
Normal file
25
components/bootloader/Kconfig.bootloader_rollback
Normal file
@@ -0,0 +1,25 @@
|
||||
menu "Bootloader Rollback"
|
||||
|
||||
config BOOTLOADER_ANTI_ROLLBACK_ENABLE
|
||||
bool "Enable bootloader rollback support"
|
||||
depends on SOC_RECOVERY_BOOTLOADER_SUPPORTED
|
||||
default n
|
||||
help
|
||||
This option prevents rollback to previous bootloader image with lower security version.
|
||||
|
||||
config BOOTLOADER_SECURE_VERSION
|
||||
int "Secure version of bootloader"
|
||||
depends on BOOTLOADER_ANTI_ROLLBACK_ENABLE
|
||||
default 0
|
||||
range 0 4
|
||||
help
|
||||
The secure version is the sequence number stored in the header of each bootloader.
|
||||
|
||||
The ROM Bootloader which runs the 2nd stage bootloader (PRIMARY or RECOVERY) checks that
|
||||
the security version is greater or equal that recorded in the eFuse field.
|
||||
Bootloaders that have a secure version in the image < secure version in efuse will not boot.
|
||||
|
||||
The security version is worth increasing if in previous versions there is
|
||||
a significant vulnerability and their use is not acceptable.
|
||||
|
||||
endmenu
|
||||
@@ -1,6 +1,8 @@
|
||||
menu "Bootloader config"
|
||||
|
||||
orsource "../esp_bootloader_format/Kconfig.bootloader"
|
||||
orsource "Kconfig.app_rollback"
|
||||
orsource "Kconfig.bootloader_rollback"
|
||||
|
||||
config BOOTLOADER_OFFSET_IN_FLASH
|
||||
hex
|
||||
@@ -312,71 +314,6 @@ menu "Bootloader config"
|
||||
- these options can increase the execution time.
|
||||
Note: RTC_WDT will reset while encryption operations will be performed.
|
||||
|
||||
config BOOTLOADER_APP_ROLLBACK_ENABLE
|
||||
bool "Enable app rollback support"
|
||||
default n
|
||||
help
|
||||
After updating the app, the bootloader runs a new app with the "ESP_OTA_IMG_PENDING_VERIFY" state set.
|
||||
This state prevents the re-run of this app. After the first boot of the new app in the user code, the
|
||||
function should be called to confirm the operability of the app or vice versa about its non-operability.
|
||||
If the app is working, then it is marked as valid. Otherwise, it is marked as not valid and rolls back to
|
||||
the previous working app. A reboot is performed, and the app is booted before the software update.
|
||||
Note: If during the first boot a new app the power goes out or the WDT works, then roll back will happen.
|
||||
Rollback is possible only between the apps with the same security versions.
|
||||
|
||||
config BOOTLOADER_APP_ANTI_ROLLBACK
|
||||
bool "Enable app anti-rollback support"
|
||||
depends on BOOTLOADER_APP_ROLLBACK_ENABLE
|
||||
default n
|
||||
help
|
||||
This option prevents rollback to previous firmware/application image with lower security version.
|
||||
|
||||
config BOOTLOADER_APP_SECURE_VERSION
|
||||
int "eFuse secure version of app"
|
||||
depends on BOOTLOADER_APP_ANTI_ROLLBACK
|
||||
default 0
|
||||
help
|
||||
The secure version is the sequence number stored in the header of each firmware.
|
||||
The security version is set in the bootloader, version is recorded in the eFuse field
|
||||
as the number of set ones. The allocated number of bits in the efuse field
|
||||
for storing the security version is limited (see BOOTLOADER_APP_SEC_VER_SIZE_EFUSE_FIELD option).
|
||||
|
||||
Bootloader: When bootloader selects an app to boot, an app is selected that has
|
||||
a security version greater or equal that recorded in eFuse field.
|
||||
The app is booted with a higher (or equal) secure version.
|
||||
|
||||
The security version is worth increasing if in previous versions there is
|
||||
a significant vulnerability and their use is not acceptable.
|
||||
|
||||
Your partition table should has a scheme with ota_0 + ota_1 (without factory).
|
||||
|
||||
config BOOTLOADER_APP_SEC_VER_SIZE_EFUSE_FIELD
|
||||
int "Size of the efuse secure version field"
|
||||
depends on BOOTLOADER_APP_ANTI_ROLLBACK
|
||||
range 1 32 if IDF_TARGET_ESP32
|
||||
default 32 if IDF_TARGET_ESP32
|
||||
range 1 4 if IDF_TARGET_ESP32C2
|
||||
default 4 if IDF_TARGET_ESP32C2
|
||||
range 1 16
|
||||
default 16
|
||||
help
|
||||
The size of the efuse secure version field.
|
||||
Its length is limited to 32 bits for ESP32 and 16 bits for ESP32-S2.
|
||||
This determines how many times the security version can be increased.
|
||||
|
||||
config BOOTLOADER_EFUSE_SECURE_VERSION_EMULATE
|
||||
bool "Emulate operations with efuse secure version(only test)"
|
||||
default n
|
||||
depends on BOOTLOADER_APP_ANTI_ROLLBACK
|
||||
select EFUSE_VIRTUAL
|
||||
select EFUSE_VIRTUAL_KEEP_IN_FLASH
|
||||
help
|
||||
This option allows to emulate read/write operations with all eFuses and efuse secure version.
|
||||
It allows to test anti-rollback implementation without permanent write eFuse bits.
|
||||
There should be an entry in partition table with following details: `emul_efuse, data, efuse, , 0x2000`.
|
||||
|
||||
This option enables: EFUSE_VIRTUAL and EFUSE_VIRTUAL_KEEP_IN_FLASH.
|
||||
|
||||
config BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP
|
||||
bool "Skip image validation when exiting deep sleep"
|
||||
# note: dependencies for this config item are different to other "skip image validation"
|
||||
@@ -1107,7 +1044,7 @@ menu "Security features"
|
||||
endmenu # Potentially Insecure
|
||||
|
||||
config SECURE_FLASH_ENCRYPT_ONLY_IMAGE_LEN_IN_APP_PART
|
||||
bool "Encrypt contents upto app image length in app partition"
|
||||
bool "Encrypt only the app image that is present in the partition of type app"
|
||||
depends on SECURE_FLASH_ENC_ENABLED && !SECURE_FLASH_REQUIRE_ALREADY_ENABLED
|
||||
default y
|
||||
help
|
||||
@@ -1134,45 +1071,6 @@ menu "Security features"
|
||||
|
||||
If not set, the app does not care if the flash encryption eFuse bit is set or not.
|
||||
|
||||
config SECURE_FLASH_PSEUDO_ROUND_FUNC
|
||||
bool "Permanently enable XTS-AES's pseudo rounds function"
|
||||
default y if SECURE_FLASH_ENCRYPTION_MODE_RELEASE
|
||||
default n
|
||||
depends on SECURE_FLASH_ENC_ENABLED && SOC_FLASH_ENCRYPTION_XTS_AES_SUPPORT_PSEUDO_ROUND
|
||||
help
|
||||
If set (default), the bootloader will permanently enable the XTS-AES peripheral's pseudo rounds function.
|
||||
Note: Enabling this config would burn an efuse.
|
||||
|
||||
choice SECURE_FLASH_PSEUDO_ROUND_FUNC_STRENGTH
|
||||
prompt "Strength of the pseudo rounds function"
|
||||
depends on SECURE_FLASH_PSEUDO_ROUND_FUNC
|
||||
default SECURE_FLASH_PSEUDO_ROUND_FUNC_STRENGTH_LOW
|
||||
help
|
||||
The strength of the pseudo rounds functions can be configured to low, medium and high,
|
||||
each denoting the values that would be stored in the efuses field.
|
||||
By default the value to set to low.
|
||||
You can configure the strength of the pseudo rounds functions according to your use cases,
|
||||
for example, increasing the strength would provide higher security but would slow down the
|
||||
flash encryption/decryption operations.
|
||||
For more info regarding the performance impact, please checkout the pseudo round function section of the
|
||||
security guide documentation.
|
||||
|
||||
config SECURE_FLASH_PSEUDO_ROUND_FUNC_STRENGTH_LOW
|
||||
bool "Low"
|
||||
|
||||
config SECURE_FLASH_PSEUDO_ROUND_FUNC_STRENGTH_MEDIUM
|
||||
bool "Medium"
|
||||
|
||||
config SECURE_FLASH_PSEUDO_ROUND_FUNC_STRENGTH_HIGH
|
||||
bool "High"
|
||||
endchoice
|
||||
|
||||
config SECURE_FLASH_PSEUDO_ROUND_FUNC_STRENGTH
|
||||
int
|
||||
default 1 if SECURE_FLASH_PSEUDO_ROUND_FUNC_STRENGTH_LOW
|
||||
default 2 if SECURE_FLASH_PSEUDO_ROUND_FUNC_STRENGTH_MEDIUM
|
||||
default 3 if SECURE_FLASH_PSEUDO_ROUND_FUNC_STRENGTH_HIGH
|
||||
|
||||
config SECURE_ROM_DL_MODE_ENABLED
|
||||
bool
|
||||
default y if SOC_SUPPORTS_SECURE_DL_MODE && !SECURE_FLASH_ENCRYPTION_MODE_DEVELOPMENT
|
||||
@@ -1224,7 +1122,7 @@ menu "Security features"
|
||||
It is also possible to enable secure download mode at runtime by calling
|
||||
esp_efuse_enable_rom_secure_download_mode()
|
||||
|
||||
Note: Secure Download mode is not available for ESP32.
|
||||
Note: Secure Download mode is not available for ESP32 (includes revisions till ECO3).
|
||||
|
||||
config SECURE_INSECURE_ALLOW_DL_MODE
|
||||
bool "UART ROM download mode (Enabled (not recommended))"
|
||||
|
||||
@@ -116,8 +116,13 @@ idf_build_get_property(sdkconfig SDKCONFIG)
|
||||
idf_build_get_property(python PYTHON)
|
||||
idf_build_get_property(extra_cmake_args EXTRA_CMAKE_ARGS)
|
||||
|
||||
# We cannot pass lists are a parameter to the external project without modifying the ';' separator
|
||||
# BOOTLOADER_EXTRA_COMPONENT_DIRS may have been set by the `main` component, do not overwrite it
|
||||
idf_build_get_property(bootloader_extra_component_dirs BOOTLOADER_EXTRA_COMPONENT_DIRS)
|
||||
list(APPEND bootloader_extra_component_dirs "${CMAKE_CURRENT_LIST_DIR}")
|
||||
|
||||
# We cannot pass lists as a parameter to the external project without modifying the ';' separator
|
||||
string(REPLACE ";" "|" BOOTLOADER_IGNORE_EXTRA_COMPONENT "${BOOTLOADER_IGNORE_EXTRA_COMPONENT}")
|
||||
string(REPLACE ";" "|" bootloader_extra_component_dirs "${bootloader_extra_component_dirs}")
|
||||
|
||||
externalproject_add(bootloader
|
||||
SOURCE_DIR "${CMAKE_CURRENT_LIST_DIR}/subproject"
|
||||
@@ -127,7 +132,7 @@ externalproject_add(bootloader
|
||||
LIST_SEPARATOR |
|
||||
CMAKE_ARGS -DSDKCONFIG=${sdkconfig} -DIDF_PATH=${idf_path} -DIDF_TARGET=${idf_target}
|
||||
-DPYTHON_DEPS_CHECKED=1 -DPYTHON=${python}
|
||||
-DEXTRA_COMPONENT_DIRS=${CMAKE_CURRENT_LIST_DIR}
|
||||
-DEXTRA_COMPONENT_DIRS=${bootloader_extra_component_dirs}
|
||||
-DPROJECT_SOURCE_DIR=${PROJECT_SOURCE_DIR}
|
||||
-DIGNORE_EXTRA_COMPONENT=${BOOTLOADER_IGNORE_EXTRA_COMPONENT}
|
||||
${sign_key_arg} ${ver_key_arg}
|
||||
|
||||
@@ -34,8 +34,8 @@ set(COMPONENTS
|
||||
esp_system
|
||||
newlib)
|
||||
|
||||
# Make EXTRA_COMPONENT_DIRS variable to point to the bootloader_components directory
|
||||
# of the project being compiled
|
||||
# EXTRA_COMPONENT_DIRS can be populated with directories containing one or several components.
|
||||
# Make sure this variable contains `bootloader_components` directory of the project being compiled.
|
||||
set(PROJECT_EXTRA_COMPONENTS "${PROJECT_SOURCE_DIR}/bootloader_components")
|
||||
if(EXISTS ${PROJECT_EXTRA_COMPONENTS})
|
||||
list(APPEND EXTRA_COMPONENT_DIRS "${PROJECT_EXTRA_COMPONENTS}")
|
||||
|
||||
@@ -36,10 +36,6 @@ if(CONFIG_APP_BUILD_TYPE_APP_2NDBOOT)
|
||||
)
|
||||
endif()
|
||||
|
||||
if(CONFIG_ESP_ROM_REV0_HAS_NO_ECDSA_INTERFACE)
|
||||
list(APPEND srcs "src/${IDF_TARGET}/bootloader_ecdsa.c")
|
||||
endif()
|
||||
|
||||
if(BOOTLOADER_BUILD OR CONFIG_APP_BUILD_TYPE_RAM)
|
||||
set(include_dirs "include" "bootloader_flash/include"
|
||||
"private_include")
|
||||
@@ -54,6 +50,10 @@ if(BOOTLOADER_BUILD OR CONFIG_APP_BUILD_TYPE_RAM)
|
||||
"src/${IDF_TARGET}/bootloader_${IDF_TARGET}.c"
|
||||
)
|
||||
list(APPEND priv_requires hal)
|
||||
if(CONFIG_ESP_ROM_REV0_HAS_NO_ECDSA_INTERFACE)
|
||||
list(APPEND srcs
|
||||
"src/${IDF_TARGET}/bootloader_ecdsa.c")
|
||||
endif()
|
||||
else()
|
||||
list(APPEND srcs
|
||||
"src/idf/bootloader_sha.c")
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2010-2025 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2010-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -28,21 +28,7 @@ extern "C" {
|
||||
*/
|
||||
__attribute__((always_inline))
|
||||
inline static bool esp_dram_match_iram(void) {
|
||||
return ((SOC_DRAM_LOW == SOC_IRAM_LOW) && (SOC_DRAM_HIGH == SOC_IRAM_HIGH));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check if the RTC IRAM and RTC DRAM are separate or using the same memory space
|
||||
*
|
||||
* @return true if the RTC DRAM and RTC IRAM are sharing the same memory space, false otherwise
|
||||
*/
|
||||
__attribute__((always_inline))
|
||||
inline static bool esp_rtc_dram_match_rtc_iram(void) {
|
||||
#if SOC_RTC_FAST_MEM_SUPPORTED
|
||||
return ((SOC_RTC_IRAM_LOW == SOC_RTC_DRAM_LOW) && (SOC_RTC_IRAM_HIGH == SOC_RTC_DRAM_HIGH));
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
return (SOC_DRAM_LOW == SOC_IRAM_LOW && SOC_DRAM_HIGH == SOC_IRAM_HIGH);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -96,7 +82,6 @@ __attribute__((always_inline))
|
||||
inline static bool esp_ptr_in_diram_iram(const void *p) {
|
||||
// TODO: IDF-5980 esp32c6 D/I RAM share the same address
|
||||
#if SOC_DIRAM_IRAM_LOW == SOC_DIRAM_DRAM_LOW
|
||||
(void)p;
|
||||
return false;
|
||||
#else
|
||||
return ((intptr_t)p >= SOC_DIRAM_IRAM_LOW && (intptr_t)p < SOC_DIRAM_IRAM_HIGH);
|
||||
@@ -115,7 +100,6 @@ inline static bool esp_ptr_in_rtc_iram_fast(const void *p) {
|
||||
#if SOC_RTC_FAST_MEM_SUPPORTED
|
||||
return ((intptr_t)p >= SOC_RTC_IRAM_LOW && (intptr_t)p < SOC_RTC_IRAM_HIGH);
|
||||
#else
|
||||
(void)p;
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
@@ -132,7 +116,6 @@ inline static bool esp_ptr_in_rtc_dram_fast(const void *p) {
|
||||
#if SOC_RTC_FAST_MEM_SUPPORTED
|
||||
return ((intptr_t)p >= SOC_RTC_DRAM_LOW && (intptr_t)p < SOC_RTC_DRAM_HIGH);
|
||||
#else
|
||||
(void)p;
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
@@ -168,21 +151,6 @@ inline static void * esp_ptr_diram_dram_to_iram(const void *p) {
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Convert a RTC DRAM pointer to equivalent word address in RTC IRAM
|
||||
|
||||
- Address must be word aligned
|
||||
- Address must pass esp_ptr_in_rtc_dram_fast() test, or result will be invalid pointer
|
||||
*/
|
||||
__attribute__((always_inline))
|
||||
inline static void * esp_ptr_rtc_dram_to_iram(const void *p) {
|
||||
intptr_t ptr = (intptr_t)p;
|
||||
#if SOC_RTC_FAST_MEM_SUPPORTED && (SOC_RTC_IRAM_LOW != SOC_RTC_DRAM_LOW)
|
||||
return (void *) ( SOC_RTC_IRAM_LOW + (ptr - SOC_RTC_DRAM_LOW) );
|
||||
#else
|
||||
return (void *) ptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Convert a D/IRAM IRAM pointer to equivalent word address in DRAM
|
||||
|
||||
- Address must be word aligned
|
||||
|
||||
@@ -215,10 +215,6 @@ bool esp_flash_encryption_cfg_verify_release_mode(void);
|
||||
* It burns:
|
||||
* - "disable encrypt in dl mode"
|
||||
* - set FLASH_CRYPT_CNT efuse to max
|
||||
*
|
||||
* In case of the targets that support the XTS-AES peripheral's pseudo rounds function,
|
||||
* this API would configure the pseudo rounds level efuse bit to level low if the efuse bit
|
||||
* is not set already.
|
||||
*/
|
||||
void esp_flash_encryption_set_release_mode(void);
|
||||
|
||||
|
||||
@@ -32,6 +32,7 @@ extern "C" {
|
||||
#define PART_TYPE_BOOTLOADER 0x02
|
||||
#define PART_SUBTYPE_BOOTLOADER_PRIMARY 0x00
|
||||
#define PART_SUBTYPE_BOOTLOADER_OTA 0x01
|
||||
#define PART_SUBTYPE_BOOTLOADER_RECOVERY 0x02
|
||||
|
||||
#define PART_TYPE_PARTITION_TABLE 0x03
|
||||
#define PART_SUBTYPE_PARTITION_TABLE_PRIMARY 0x00
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -87,12 +87,12 @@ ESP_STATIC_ASSERT(sizeof(rtc_retain_mem_t) <= ESP_BOOTLOADER_RESERVE_RTC, "Reser
|
||||
#endif // CONFIG_BOOTLOADER_RESERVE_RTC_MEM
|
||||
|
||||
/**
|
||||
* @brief Verify an app image.
|
||||
* @brief Verify an app/bootloader image.
|
||||
*
|
||||
* If encryption is enabled, data will be transparently decrypted.
|
||||
*
|
||||
* @param mode Mode of operation (verify, silent verify, or load).
|
||||
* @param part Partition to load the app from.
|
||||
* @param part Partition to load the app/bootloader from.
|
||||
* @param[inout] data Pointer to the image metadata structure which is be filled in by this function.
|
||||
* 'start_addr' member should be set (to the start address of the image.)
|
||||
* Other fields will all be initialised by this function.
|
||||
@@ -114,11 +114,11 @@ ESP_STATIC_ASSERT(sizeof(rtc_retain_mem_t) <= ESP_BOOTLOADER_RESERVE_RTC, "Reser
|
||||
esp_err_t esp_image_verify(esp_image_load_mode_t mode, const esp_partition_pos_t *part, esp_image_metadata_t *data);
|
||||
|
||||
/**
|
||||
* @brief Get metadata of app
|
||||
* @brief Get metadata of app/bootloader
|
||||
*
|
||||
* If encryption is enabled, data will be transparently decrypted.
|
||||
*
|
||||
* @param part Partition to load the app from.
|
||||
* @param part Partition to load the app/bootloader from.
|
||||
* @param[out] metadata Pointer to the image metadata structure which is be filled in by this function.
|
||||
* Fields will all be initialised by this function.
|
||||
*
|
||||
@@ -172,7 +172,7 @@ esp_err_t bootloader_load_image(const esp_partition_pos_t *part, esp_image_metad
|
||||
esp_err_t bootloader_load_image_no_verify(const esp_partition_pos_t *part, esp_image_metadata_t *data);
|
||||
|
||||
/**
|
||||
* @brief Verify the bootloader image.
|
||||
* @brief Verify the PRIMARY bootloader image.
|
||||
*
|
||||
* @param[out] If result is ESP_OK and this pointer is non-NULL, it
|
||||
* will be set to the length of the bootloader image.
|
||||
@@ -182,7 +182,7 @@ esp_err_t bootloader_load_image_no_verify(const esp_partition_pos_t *part, esp_i
|
||||
esp_err_t esp_image_verify_bootloader(uint32_t *length);
|
||||
|
||||
/**
|
||||
* @brief Verify the bootloader image.
|
||||
* @brief Verify the PRIMARY bootloader image.
|
||||
*
|
||||
* @param[out] Metadata for the image. Only valid if result is ESP_OK.
|
||||
*
|
||||
@@ -198,6 +198,25 @@ esp_err_t esp_image_verify_bootloader_data(esp_image_metadata_t *data);
|
||||
*/
|
||||
int esp_image_get_flash_size(esp_image_flash_size_t app_flash_size);
|
||||
|
||||
/**
|
||||
* @brief Get the ota bootloader offset
|
||||
*
|
||||
* The esp_image_verify functions use the offset to distinguish between application and bootloader verifications.
|
||||
* The application must set the OTA bootloader offset before running any verification functions for the OTA bootloader partition.
|
||||
*
|
||||
* @return ota Bootloader offset. UINT32_MAX - not set.
|
||||
*/
|
||||
uint32_t esp_image_bootloader_offset_get(void);
|
||||
|
||||
/**
|
||||
* @brief Set the ota bootloader offset
|
||||
*
|
||||
* The esp_image_verify functions use the offset to distinguish between application and bootloader verifications.
|
||||
* The application must set the OTA bootloader offset before running any verification functions for the OTA bootloader partition.
|
||||
*
|
||||
* @param offset ota Bootloader offset
|
||||
*/
|
||||
void esp_image_bootloader_offset_set(const uint32_t offset);
|
||||
|
||||
typedef struct {
|
||||
uint32_t drom_addr;
|
||||
|
||||
@@ -236,23 +236,6 @@ typedef struct {
|
||||
uint8_t signature[64];
|
||||
} esp_secure_boot_sig_block_t;
|
||||
|
||||
/** @brief Get the size of the secure boot signature block
|
||||
*
|
||||
* This is the size of the signature block appended to a signed image.
|
||||
*
|
||||
* @return Size of the secure boot signature block in bytes
|
||||
*/
|
||||
static inline uint32_t esp_secure_boot_sig_block_size(void)
|
||||
{
|
||||
#if CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME || CONFIG_SECURE_SIGNED_APPS_ECDSA_V2_SCHEME
|
||||
return sizeof(ets_secure_boot_signature_t);
|
||||
#elif defined(CONFIG_SECURE_SIGNED_APPS_ECDSA_SCHEME)
|
||||
return sizeof(esp_secure_boot_sig_block_t);
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
/** @brief Verify the ECDSA secure boot signature block for Secure Boot V1.
|
||||
*
|
||||
* Calculates Deterministic ECDSA w/ SHA256 based on the SHA256 hash of the image. ECDSA signature
|
||||
|
||||
@@ -64,7 +64,7 @@ __attribute__((weak)) void bootloader_clock_configure(void)
|
||||
// RTC_FAST clock source will be switched to RC_FAST at application startup
|
||||
clk_cfg.fast_clk_src = rtc_clk_fast_src_get();
|
||||
if (clk_cfg.fast_clk_src == SOC_RTC_FAST_CLK_SRC_INVALID) {
|
||||
clk_cfg.fast_clk_src = SOC_RTC_FAST_CLK_SRC_XTAL_DIV;
|
||||
clk_cfg.fast_clk_src = SOC_RTC_FAST_CLK_SRC_DEFAULT;
|
||||
}
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32C6
|
||||
|
||||
@@ -140,13 +140,13 @@ bool bootloader_common_erase_part_type_data(const char *list_erase, bool ota_dat
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t bootloader_common_get_sha256_of_partition (uint32_t address, uint32_t size, int type, uint8_t *out_sha_256)
|
||||
esp_err_t bootloader_common_get_sha256_of_partition(uint32_t address, uint32_t size, int type, uint8_t *out_sha_256)
|
||||
{
|
||||
if (out_sha_256 == NULL || size == 0) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
if (type == PART_TYPE_APP) {
|
||||
if (type == PART_TYPE_APP || type == PART_TYPE_BOOTLOADER) {
|
||||
const esp_partition_pos_t partition_pos = {
|
||||
.offset = address,
|
||||
.size = size,
|
||||
|
||||
@@ -28,7 +28,6 @@
|
||||
|
||||
#define ESP_PARTITION_HASH_LEN 32 /* SHA-256 digest length */
|
||||
#define IS_FIELD_SET(rev_full) (((rev_full) != 65535) && ((rev_full) != 0))
|
||||
#define ALIGN_UP(num, align) (((num) + ((align) - 1)) & ~((align) - 1))
|
||||
|
||||
static const char* TAG = "boot_comm";
|
||||
|
||||
@@ -243,10 +242,7 @@ rtc_retain_mem_t* bootloader_common_get_rtc_retain_mem(void)
|
||||
#if ESP_ROM_HAS_LP_ROM
|
||||
#define RTC_RETAIN_MEM_ADDR (SOC_RTC_DRAM_LOW)
|
||||
#else
|
||||
/* Since the structure containing the retain_mem_t is aligned on 8 by the linker, make sure we align this
|
||||
* structure size here too */
|
||||
#define RETAIN_MEM_SIZE ALIGN_UP(sizeof(rtc_retain_mem_t), 8)
|
||||
#define RTC_RETAIN_MEM_ADDR (SOC_RTC_DRAM_HIGH - RETAIN_MEM_SIZE)
|
||||
#define RTC_RETAIN_MEM_ADDR (SOC_RTC_DRAM_HIGH - sizeof(rtc_retain_mem_t))
|
||||
#endif //ESP_ROM_HAS_LP_ROM
|
||||
static rtc_retain_mem_t *const s_bootloader_retain_mem = (rtc_retain_mem_t *)RTC_RETAIN_MEM_ADDR;
|
||||
return s_bootloader_retain_mem;
|
||||
|
||||
@@ -74,12 +74,6 @@ void bootloader_console_init(void)
|
||||
// Enable the peripheral
|
||||
uart_ll_enable_bus_clock(uart_num, true);
|
||||
uart_ll_reset_register(uart_num);
|
||||
// Set clock source
|
||||
#if SOC_UART_SUPPORT_XTAL_CLK
|
||||
uart_ll_set_sclk(UART_LL_GET_HW(uart_num), (soc_module_clk_t)UART_SCLK_XTAL);
|
||||
#else
|
||||
uart_ll_set_sclk(UART_LL_GET_HW(uart_num), (soc_module_clk_t)UART_SCLK_APB);
|
||||
#endif
|
||||
// Reset TX and RX FIFOs
|
||||
uart_ll_txfifo_rst(UART_LL_GET_HW(uart_num));
|
||||
uart_ll_rxfifo_rst(UART_LL_GET_HW(uart_num));
|
||||
|
||||
@@ -46,6 +46,9 @@ void bootloader_random_enable(void)
|
||||
SET_PERI_REG_MASK(PMU_RF_PWC_REG, PMU_PERIF_I2C_RSTB);
|
||||
SET_PERI_REG_MASK(PMU_RF_PWC_REG, PMU_XPD_PERIF_I2C);
|
||||
|
||||
// enable analog i2c master clock for RNG runtime
|
||||
ANALOG_CLOCK_ENABLE();
|
||||
|
||||
// Config ADC circuit (Analog part) with I2C (HOST ID 0X69) and choose internal voltage as sampling source
|
||||
REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SARADC_DTEST_RTC_ADDR, 0);
|
||||
REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SARADC_ENT_PERIF_ADDR, 1);
|
||||
@@ -94,6 +97,9 @@ void bootloader_random_disable(void)
|
||||
REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SARADC1_EN_TOUT_ADDR, 0);
|
||||
REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SARADC2_EN_TOUT_ADDR, 0);
|
||||
|
||||
// disable analog i2c master clock
|
||||
ANALOG_CLOCK_DISABLE();
|
||||
|
||||
// disable ADC_CTRL_CLK (SAR ADC function clock)
|
||||
REG_WRITE(PCR_SARADC_CLKM_CONF_REG, 0x00404000);
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -40,6 +40,9 @@ void bootloader_random_enable(void)
|
||||
SET_PERI_REG_MASK(PMU_RF_PWC_REG, PMU_PERIF_I2C_RSTB);
|
||||
SET_PERI_REG_MASK(PMU_RF_PWC_REG, PMU_XPD_PERIF_I2C);
|
||||
|
||||
// enable analog i2c master clock for RNG runtime
|
||||
ANALOG_CLOCK_ENABLE();
|
||||
|
||||
// Config ADC circuit (Analog part) with I2C(HOST ID 0x69) and chose internal voltage as sampling source
|
||||
REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SARADC_DTEST_RTC_ADDR , 2);
|
||||
REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SARADC_ENT_RTC_ADDR , 1);
|
||||
@@ -88,6 +91,9 @@ void bootloader_random_disable(void)
|
||||
REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SARADC1_ENCAL_REF_ADDR, 0);
|
||||
REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SARADC2_ENCAL_REF_ADDR, 0);
|
||||
|
||||
// disable analog i2c master clock
|
||||
ANALOG_CLOCK_DISABLE();
|
||||
|
||||
// disable ADC_CTRL_CLK (SAR ADC function clock)
|
||||
REG_WRITE(PCR_SARADC_CLKM_CONF_REG, 0x00404000);
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -45,6 +45,9 @@ void bootloader_random_enable(void)
|
||||
SET_PERI_REG_MASK(PMU_RF_PWC_REG, PMU_PERIF_I2C_RSTB);
|
||||
SET_PERI_REG_MASK(PMU_RF_PWC_REG, PMU_XPD_PERIF_I2C);
|
||||
|
||||
// enable analog i2c master clock for RNG runtime
|
||||
ANALOG_CLOCK_ENABLE();
|
||||
|
||||
// Config ADC circuit (Analog part) with I2C(HOST ID 0x69) and chose internal voltage as sampling source
|
||||
REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SARADC_DTEST_RTC_ADDR , 0);
|
||||
REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SARADC_ENT_RTC_ADDR , 1);
|
||||
@@ -93,6 +96,9 @@ void bootloader_random_disable(void)
|
||||
REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SARADC1_ENCAL_REF_ADDR, 0);
|
||||
REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SARADC2_ENCAL_REF_ADDR, 0);
|
||||
|
||||
// disable analog i2c master clock
|
||||
ANALOG_CLOCK_DISABLE();
|
||||
|
||||
// disable ADC_CTRL_CLK (SAR ADC function clock)
|
||||
REG_WRITE(PCR_SARADC_CLKM_CONF_REG, 0x00404000);
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -35,6 +35,9 @@ void bootloader_random_enable(void)
|
||||
// some ADC sensor registers are in power group PERIF_I2C and need to be enabled via PMU
|
||||
SET_PERI_REG_MASK(PMU_RF_PWC_REG, PMU_XPD_PERIF_I2C);
|
||||
|
||||
// enable analog i2c master clock for RNG runtime
|
||||
ANALOG_CLOCK_ENABLE();
|
||||
|
||||
REGI2C_WRITE_MASK(I2C_SAR_ADC, I2C_SARADC_DTEST, 0);
|
||||
REGI2C_WRITE_MASK(I2C_SAR_ADC, I2C_SARADC_ENT_SAR, 1);
|
||||
REGI2C_WRITE_MASK(I2C_SAR_ADC, I2C_SARADC_EN_TOUT_SAR1_BUS, 1);
|
||||
@@ -80,6 +83,9 @@ void bootloader_random_disable(void)
|
||||
REGI2C_WRITE_MASK(I2C_SAR_ADC, I2C_SARADC_ENT_SAR, 0);
|
||||
REGI2C_WRITE_MASK(I2C_SAR_ADC, I2C_SARADC_EN_TOUT_SAR1_BUS, 0);
|
||||
|
||||
// disable analog i2c master clock
|
||||
ANALOG_CLOCK_DISABLE();
|
||||
|
||||
// disable ADC_CTRL_CLK (SAR ADC function clock)
|
||||
REG_WRITE(PCR_SARADC_CLKM_CONF_REG, 0x00404000);
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -12,7 +12,6 @@
|
||||
#include "soc/lp_adc_reg.h"
|
||||
#include "esp_private/regi2c_ctrl.h"
|
||||
#include "esp_rom_regi2c.h"
|
||||
#include "soc/lpperi_reg.h"
|
||||
|
||||
// TODO IDF-6497: once ADC API is supported, use the API instead of defining functions and constants here
|
||||
|
||||
@@ -31,8 +30,8 @@ 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);
|
||||
REGI2C_WRITE_MASK(I2C_SAR_ADC, I2C_SAR_ADC_SAR1_INIT_CODE_MSB, msb);
|
||||
REGI2C_WRITE_MASK(I2C_SAR_ADC, I2C_SAR_ADC_SAR1_INIT_CODE_LSB, lsb);
|
||||
}
|
||||
|
||||
//total 4 tables
|
||||
@@ -51,7 +50,6 @@ void bootloader_random_enable(void)
|
||||
pattern_table sar1_table[4] = {};
|
||||
uint32_t pattern_len = 0;
|
||||
|
||||
SET_PERI_REG_MASK(LPPERI_CLK_EN_REG, LPPERI_CK_EN_LP_ADC);
|
||||
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);
|
||||
|
||||
@@ -64,6 +62,9 @@ void bootloader_random_enable(void)
|
||||
|
||||
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();
|
||||
|
||||
adc1_fix_initcode_set(I2C_SAR_ADC_INIT_CODE_VAL);
|
||||
|
||||
// cfg pattern table
|
||||
@@ -96,8 +97,10 @@ void bootloader_random_enable(void)
|
||||
|
||||
void bootloader_random_disable(void)
|
||||
{
|
||||
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);
|
||||
// disable analog i2c master clock
|
||||
ANALOG_CLOCK_DISABLE();
|
||||
|
||||
// No-op for now TODO IDF-6497
|
||||
// ADC should be set to defaults here, once ADC API is implemented
|
||||
// OR just keep this empty and let application continue to use RNG initialized by the bootloader
|
||||
}
|
||||
|
||||
@@ -208,6 +208,9 @@ bool bootloader_utility_load_partition_table(bootloader_state_t *bs)
|
||||
case PART_SUBTYPE_BOOTLOADER_OTA:
|
||||
partition_usage = "ota bootloader";
|
||||
break;
|
||||
case PART_SUBTYPE_BOOTLOADER_RECOVERY:
|
||||
partition_usage = "recovery bootloader";
|
||||
break;
|
||||
}
|
||||
break; /* PART_TYPE_BOOTLOADER */
|
||||
case PART_TYPE_PARTITION_TABLE: /* Partition table partition */
|
||||
|
||||
@@ -85,7 +85,7 @@ static void bootloader_super_wdt_auto_feed(void)
|
||||
|
||||
static inline void bootloader_hardware_init(void)
|
||||
{
|
||||
regi2c_ctrl_ll_master_enable_clock(true);
|
||||
_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();
|
||||
}
|
||||
|
||||
@@ -96,7 +96,7 @@ static inline void bootloader_hardware_init(void)
|
||||
esp_rom_spiflash_fix_dummylen(1, 1);
|
||||
#endif
|
||||
|
||||
regi2c_ctrl_ll_master_enable_clock(true);
|
||||
_regi2c_ctrl_ll_master_enable_clock(true); // keep ana i2c mst clock always enabled in bootloader
|
||||
regi2c_ctrl_ll_master_configure_clock();
|
||||
}
|
||||
|
||||
|
||||
@@ -86,7 +86,7 @@ static void bootloader_super_wdt_auto_feed(void)
|
||||
|
||||
static inline void bootloader_hardware_init(void)
|
||||
{
|
||||
regi2c_ctrl_ll_master_enable_clock(true);
|
||||
_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();
|
||||
}
|
||||
|
||||
@@ -11,9 +11,9 @@
|
||||
#include "hal/regi2c_ctrl.h"
|
||||
#include "soc/regi2c_saradc.h"
|
||||
|
||||
//Not supported but common bootloader calls the function. Do nothing
|
||||
void bootloader_ana_clock_glitch_reset_config(bool enable)
|
||||
{
|
||||
// TODO: IDF-9274
|
||||
(void)enable;
|
||||
}
|
||||
|
||||
|
||||
@@ -90,10 +90,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);
|
||||
_regi2c_ctrl_ll_master_enable_clock(true); // keep ana i2c mst clock always enabled in bootloader
|
||||
regi2c_ctrl_ll_master_configure_clock();
|
||||
REGI2C_WRITE_MASK(I2C_BIAS, I2C_BIAS_DREG_0P8, 8); // fix low temp issue, need to increase this internal voltage
|
||||
|
||||
}
|
||||
|
||||
static inline void bootloader_ana_reset_config(void)
|
||||
|
||||
@@ -1,18 +1,15 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <strings.h>
|
||||
#include "esp_flash_encrypt.h"
|
||||
#include "esp_secure_boot.h"
|
||||
#include "esp_efuse.h"
|
||||
#include "esp_efuse_table.h"
|
||||
#include "esp_log.h"
|
||||
#include "hal/spi_flash_encrypted_ll.h"
|
||||
#include "soc/soc_caps.h"
|
||||
#include "sdkconfig.h"
|
||||
|
||||
static __attribute__((unused)) const char *TAG = "flash_encrypt";
|
||||
@@ -36,14 +33,6 @@ esp_err_t esp_flash_encryption_enable_secure_features(void)
|
||||
|
||||
esp_efuse_write_field_bit(ESP_EFUSE_DIS_DIRECT_BOOT);
|
||||
|
||||
#if CONFIG_SECURE_FLASH_PSEUDO_ROUND_FUNC
|
||||
if (spi_flash_encrypt_ll_is_pseudo_rounds_function_supported()) {
|
||||
ESP_LOGI(TAG, "Enable XTS-AES pseudo rounds function...");
|
||||
uint8_t xts_pseudo_level = CONFIG_SECURE_FLASH_PSEUDO_ROUND_FUNC_STRENGTH;
|
||||
esp_efuse_write_field_blob(ESP_EFUSE_XTS_DPA_PSEUDO_LEVEL, &xts_pseudo_level, ESP_EFUSE_XTS_DPA_PSEUDO_LEVEL[0]->bit_count);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_SECURE_BOOT_V2_ENABLED) && !defined(CONFIG_SECURE_BOOT_V2_ALLOW_EFUSE_RD_DIS)
|
||||
// This bit is set when enabling Secure Boot V2, but we can't enable it until this later point in the first boot
|
||||
// otherwise the Flash Encryption key cannot be read protected
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <strings.h>
|
||||
#include "hal/ecdsa_ll.h"
|
||||
#include "esp_flash_encrypt.h"
|
||||
#include "esp_secure_boot.h"
|
||||
#include "esp_efuse.h"
|
||||
@@ -37,12 +36,6 @@ esp_err_t esp_secure_boot_enable_secure_features(void)
|
||||
ESP_LOGW(TAG, "UART ROM Download mode kept enabled - SECURITY COMPROMISED");
|
||||
#endif
|
||||
|
||||
#ifdef SOC_ECDSA_P192_CURVE_DEFAULT_DISABLED
|
||||
if (ecdsa_ll_is_configurable_curve_supported()) {
|
||||
esp_efuse_write_field_bit(ESP_EFUSE_WR_DIS_ECDSA_CURVE_MODE);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_SECURE_BOOT_ALLOW_JTAG
|
||||
ESP_LOGI(TAG, "Disable hardware & software JTAG...");
|
||||
esp_efuse_write_field_bit(ESP_EFUSE_DIS_PAD_JTAG);
|
||||
|
||||
@@ -95,8 +95,7 @@ static void bootloader_super_wdt_auto_feed(void)
|
||||
|
||||
static inline void bootloader_hardware_init(void)
|
||||
{
|
||||
int __DECLARE_RCC_RC_ATOMIC_ENV __attribute__ ((unused)); // To avoid build errors/warnings about __DECLARE_RCC_RC_ATOMIC_ENV
|
||||
regi2c_ctrl_ll_master_enable_clock(true);
|
||||
_regi2c_ctrl_ll_master_enable_clock(true); // keep ana i2c mst clock always enabled in bootloader
|
||||
regi2c_ctrl_ll_master_configure_clock();
|
||||
|
||||
unsigned chip_version = efuse_hal_chip_revision();
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
@@ -48,12 +48,7 @@ static const char *TAG = "esp_image";
|
||||
|
||||
#define HASH_LEN ESP_IMAGE_HASH_LEN
|
||||
|
||||
#if SOC_SPI_MEM_SUPPORT_CACHE_32BIT_ADDR_MAP
|
||||
#define ESP_IMAGE_MAX_FLASH_ADDR_SIZE UINT32_MAX
|
||||
#else
|
||||
#define ESP_IMAGE_MAX_FLASH_ADDR_SIZE 0x1000000
|
||||
#endif
|
||||
|
||||
#define SIXTEEN_MB 0x1000000
|
||||
#define ESP_ROM_CHECKSUM_INITIAL 0xEF
|
||||
|
||||
/* Headroom to ensure between stack SP (at time of checking) and data loaded from flash */
|
||||
@@ -108,6 +103,24 @@ static esp_err_t process_checksum(bootloader_sha256_handle_t sha_handle, uint32_
|
||||
static esp_err_t __attribute__((unused)) verify_secure_boot_signature(bootloader_sha256_handle_t sha_handle, esp_image_metadata_t *data, uint8_t *image_digest, uint8_t *verified_digest);
|
||||
static esp_err_t __attribute__((unused)) verify_simple_hash(bootloader_sha256_handle_t sha_handle, esp_image_metadata_t *data);
|
||||
|
||||
static uint32_t s_bootloader_partition_offset = ESP_PRIMARY_BOOTLOADER_OFFSET;
|
||||
|
||||
uint32_t esp_image_bootloader_offset_get(void)
|
||||
{
|
||||
return s_bootloader_partition_offset;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
static bool is_bootloader(uint32_t offset)
|
||||
{
|
||||
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)
|
||||
{
|
||||
#ifdef BOOTLOADER_BUILD
|
||||
@@ -141,10 +154,10 @@ static esp_err_t image_load(esp_image_load_mode_t mode, const esp_partition_pos_
|
||||
// For secure boot V1 on ESP32, we don't calculate SHA or verify signature on bootloaders.
|
||||
// (For non-secure boot, we don't verify any SHA-256 hash appended to the bootloader because
|
||||
// esptool.py may have rewritten the header - rely on esptool.py having verified the bootloader at flashing time, instead.)
|
||||
verify_sha = (part->offset != ESP_BOOTLOADER_OFFSET) && do_verify;
|
||||
verify_sha = !is_bootloader(part->offset) && do_verify;
|
||||
#endif
|
||||
|
||||
if (part->size > ESP_IMAGE_MAX_FLASH_ADDR_SIZE) {
|
||||
if (part->size > SIXTEEN_MB) {
|
||||
err = ESP_ERR_INVALID_ARG;
|
||||
FAIL_LOAD("partition size 0x%"PRIx32" invalid, larger than 16MB", part->size);
|
||||
}
|
||||
@@ -205,7 +218,7 @@ static esp_err_t image_load(esp_image_load_mode_t mode, const esp_partition_pos_
|
||||
#if CONFIG_SECURE_BOOT_V2_ENABLED
|
||||
ESP_FAULT_ASSERT(!esp_secure_boot_enabled() || memcmp(image_digest, verified_digest, HASH_LEN) == 0);
|
||||
#else // Secure Boot V1 on ESP32, only verify signatures for apps not bootloaders
|
||||
ESP_FAULT_ASSERT(data->start_addr == ESP_BOOTLOADER_OFFSET || memcmp(image_digest, verified_digest, HASH_LEN) == 0);
|
||||
ESP_FAULT_ASSERT(is_bootloader(data->start_addr) || memcmp(image_digest, verified_digest, HASH_LEN) == 0);
|
||||
#endif
|
||||
|
||||
#endif // SECURE_BOOT_CHECK_SIGNATURE
|
||||
@@ -303,7 +316,7 @@ esp_err_t esp_image_verify(esp_image_load_mode_t mode, const esp_partition_pos_t
|
||||
esp_err_t esp_image_get_metadata(const esp_partition_pos_t *part, esp_image_metadata_t *metadata)
|
||||
{
|
||||
esp_err_t err;
|
||||
if (metadata == NULL || part == NULL || part->size > ESP_IMAGE_MAX_FLASH_ADDR_SIZE) {
|
||||
if (metadata == NULL || part == NULL || part->size > SIXTEEN_MB) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
@@ -338,7 +351,8 @@ static esp_err_t verify_image_header(uint32_t src_addr, const esp_image_header_t
|
||||
// Checking the chip revision header *will* print a bunch of other info
|
||||
// regardless of silent setting as this may be important, but don't bother checking it
|
||||
// if it looks like the app partition is erased or otherwise garbage
|
||||
CHECK_ERR(bootloader_common_check_chip_validity(image, ESP_IMAGE_APPLICATION));
|
||||
esp_image_type image_type = is_bootloader(src_addr) ? ESP_IMAGE_BOOTLOADER : ESP_IMAGE_APPLICATION;
|
||||
CHECK_ERR(bootloader_common_check_chip_validity(image, image_type));
|
||||
|
||||
if (image->segment_count > ESP_IMAGE_MAX_SEGMENTS) {
|
||||
FAIL_LOAD("image at 0x%"PRIx32" segment count %d exceeds max %d", src_addr, image->segment_count, ESP_IMAGE_MAX_SEGMENTS);
|
||||
@@ -701,7 +715,7 @@ static esp_err_t process_segment_data(int segment, intptr_t load_addr, uint32_t
|
||||
// Case II: Bootloader verifying bootloader
|
||||
// The esp_app_desc_t structure is located in DROM and is always in segment #0.
|
||||
// Anti-rollback check and efuse block version check should handle only Case I from above.
|
||||
if (segment == 0 && metadata->start_addr != ESP_BOOTLOADER_OFFSET) {
|
||||
if (segment == 0 && !is_bootloader(metadata->start_addr)) {
|
||||
/* ESP32 doesn't have more memory and more efuse bits for block major version. */
|
||||
#if !CONFIG_IDF_TARGET_ESP32
|
||||
const esp_app_desc_t *app_desc = (const esp_app_desc_t *)src;
|
||||
@@ -757,7 +771,7 @@ static esp_err_t process_segment_data(int segment, intptr_t load_addr, uint32_t
|
||||
static esp_err_t verify_segment_header(int index, const esp_image_segment_header_t *segment, uint32_t segment_data_offs, esp_image_metadata_t *metadata, bool silent)
|
||||
{
|
||||
if ((segment->data_len & 3) != 0
|
||||
|| segment->data_len >= ESP_IMAGE_MAX_FLASH_ADDR_SIZE) {
|
||||
|| segment->data_len >= SIXTEEN_MB) {
|
||||
if (!silent) {
|
||||
ESP_LOGE(TAG, "invalid segment length 0x%"PRIx32, segment->data_len);
|
||||
}
|
||||
@@ -768,28 +782,21 @@ static esp_err_t verify_segment_header(int index, const esp_image_segment_header
|
||||
bool map_segment = should_map(load_addr);
|
||||
|
||||
#if SOC_MMU_PAGE_SIZE_CONFIGURABLE
|
||||
esp_err_t err = ESP_FAIL;
|
||||
|
||||
/* ESP APP descriptor is present in the DROM segment #0 */
|
||||
if (index == 0 && metadata->start_addr != ESP_BOOTLOADER_OFFSET) {
|
||||
uint32_t mmu_page_size = 0, magic_word = 0;
|
||||
const uint32_t mmu_page_size_offset = segment_data_offs + offsetof(esp_app_desc_t, mmu_page_size);
|
||||
CHECK_ERR(bootloader_flash_read(segment_data_offs, &magic_word, sizeof(uint32_t), true));
|
||||
CHECK_ERR(bootloader_flash_read(mmu_page_size_offset, &mmu_page_size, sizeof(uint32_t), true));
|
||||
// Extract only the lowest byte from mmu_page_size (as per image format)
|
||||
mmu_page_size &= 0xFF;
|
||||
|
||||
if (magic_word != ESP_APP_DESC_MAGIC_WORD) {
|
||||
if (index == 0 && !is_bootloader(metadata->start_addr)) {
|
||||
const esp_app_desc_t *app_desc = (const esp_app_desc_t *)bootloader_mmap(segment_data_offs, sizeof(esp_app_desc_t));
|
||||
if (!app_desc || app_desc->magic_word != ESP_APP_DESC_MAGIC_WORD) {
|
||||
ESP_LOGE(TAG, "Failed to fetch app description header!");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
// Convert from log base 2 number to actual size while handling legacy image case (value 0)
|
||||
metadata->mmu_page_size = (mmu_page_size > 0) ? (1UL << mmu_page_size) : SPI_FLASH_MMU_PAGE_SIZE;
|
||||
metadata->mmu_page_size = (app_desc->mmu_page_size > 0) ? (1UL << app_desc->mmu_page_size) : SPI_FLASH_MMU_PAGE_SIZE;
|
||||
if (metadata->mmu_page_size != SPI_FLASH_MMU_PAGE_SIZE) {
|
||||
ESP_LOGI(TAG, "MMU page size mismatch, configured: 0x%x, found: 0x%"PRIx32, SPI_FLASH_MMU_PAGE_SIZE, metadata->mmu_page_size);
|
||||
}
|
||||
} else if (index == 0 && metadata->start_addr == ESP_BOOTLOADER_OFFSET) {
|
||||
bootloader_munmap(app_desc);
|
||||
} else if (index == 0 && is_bootloader(metadata->start_addr)) {
|
||||
// Bootloader always uses the default MMU page size
|
||||
metadata->mmu_page_size = SPI_FLASH_MMU_PAGE_SIZE;
|
||||
}
|
||||
@@ -815,10 +822,6 @@ static esp_err_t verify_segment_header(int index, const esp_image_segment_header
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
#if SOC_MMU_PAGE_SIZE_CONFIGURABLE
|
||||
err:
|
||||
return err;
|
||||
#endif
|
||||
}
|
||||
|
||||
static bool should_map(uint32_t load_addr)
|
||||
@@ -890,8 +893,8 @@ esp_err_t esp_image_verify_bootloader_data(esp_image_metadata_t *data)
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
const esp_partition_pos_t bootloader_part = {
|
||||
.offset = ESP_BOOTLOADER_OFFSET,
|
||||
.size = ESP_PARTITION_TABLE_OFFSET - ESP_BOOTLOADER_OFFSET,
|
||||
.offset = ESP_PRIMARY_BOOTLOADER_OFFSET,
|
||||
.size = ESP_BOOTLOADER_SIZE,
|
||||
};
|
||||
return esp_image_verify(ESP_IMAGE_VERIFY,
|
||||
&bootloader_part,
|
||||
@@ -914,7 +917,7 @@ static esp_err_t process_appended_hash_and_sig(esp_image_metadata_t *data, uint3
|
||||
#if CONFIG_SECURE_BOOT || CONFIG_SECURE_SIGNED_APPS_NO_SECURE_BOOT
|
||||
|
||||
// Case I: Bootloader part
|
||||
if (part_offset == ESP_BOOTLOADER_OFFSET) {
|
||||
if (is_bootloader(part_offset)) {
|
||||
// For bootloader with secure boot v1, signature stays in an independent flash
|
||||
// sector (offset 0x0) and does not get appended to the image.
|
||||
#if CONFIG_SECURE_BOOT_V2_ENABLED
|
||||
@@ -1048,7 +1051,7 @@ static esp_err_t verify_secure_boot_signature(bootloader_sha256_handle_t sha_han
|
||||
#if CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME || CONFIG_SECURE_SIGNED_APPS_ECDSA_V2_SCHEME
|
||||
data->image_len = end - data->start_addr + sizeof(ets_secure_boot_signature_t);
|
||||
#elif defined(CONFIG_SECURE_SIGNED_APPS_ECDSA_SCHEME)
|
||||
if (data->start_addr != ESP_BOOTLOADER_OFFSET) {
|
||||
if (!is_bootloader(data->start_addr)) {
|
||||
data->image_len = end - data->start_addr + sizeof(esp_secure_boot_sig_block_t);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
@@ -12,9 +12,6 @@
|
||||
#include "esp_flash_encrypt.h"
|
||||
#include "esp_secure_boot.h"
|
||||
#include "hal/efuse_hal.h"
|
||||
#include "hal/spi_flash_encrypted_ll.h"
|
||||
#include "hal/spi_flash_encrypt_hal.h"
|
||||
#include "soc/soc_caps.h"
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
#define CRYPT_CNT ESP_EFUSE_FLASH_CRYPT_CNT
|
||||
@@ -210,18 +207,6 @@ void esp_flash_encryption_set_release_mode(void)
|
||||
#endif // CONFIG_SOC_FLASH_ENCRYPTION_XTS_AES_128_DERIVED
|
||||
#endif // !CONFIG_IDF_TARGET_ESP32
|
||||
|
||||
#ifdef SOC_FLASH_ENCRYPTION_XTS_AES_SUPPORT_PSEUDO_ROUND
|
||||
if (spi_flash_encrypt_ll_is_pseudo_rounds_function_supported()) {
|
||||
uint8_t xts_pseudo_level = 0;
|
||||
esp_efuse_read_field_blob(ESP_EFUSE_XTS_DPA_PSEUDO_LEVEL, &xts_pseudo_level, ESP_EFUSE_XTS_DPA_PSEUDO_LEVEL[0]->bit_count);
|
||||
|
||||
if (xts_pseudo_level == ESP_XTS_AES_PSEUDO_ROUNDS_DISABLE) {
|
||||
xts_pseudo_level = ESP_XTS_AES_PSEUDO_ROUNDS_LOW;
|
||||
esp_efuse_write_field_blob(ESP_EFUSE_XTS_DPA_PSEUDO_LEVEL, &xts_pseudo_level, ESP_EFUSE_XTS_DPA_PSEUDO_LEVEL[0]->bit_count);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32
|
||||
esp_efuse_write_field_bit(ESP_EFUSE_WR_DIS_DIS_CACHE);
|
||||
#else
|
||||
@@ -483,17 +468,6 @@ bool esp_flash_encryption_cfg_verify_release_mode(void)
|
||||
}
|
||||
result &= secure;
|
||||
|
||||
#if SOC_FLASH_ENCRYPTION_XTS_AES_SUPPORT_PSEUDO_ROUND
|
||||
if (spi_flash_encrypt_ll_is_pseudo_rounds_function_supported()) {
|
||||
uint8_t xts_pseudo_level = 0;
|
||||
esp_efuse_read_field_blob(ESP_EFUSE_XTS_DPA_PSEUDO_LEVEL, &xts_pseudo_level, ESP_EFUSE_XTS_DPA_PSEUDO_LEVEL[0]->bit_count);
|
||||
if (!xts_pseudo_level) {
|
||||
result &= false;
|
||||
ESP_LOGW(TAG, "Not enabled XTS-AES pseudo rounds function (set XTS_DPA_PSEUDO_LEVEL->1 or more)");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return result;
|
||||
}
|
||||
#endif // not CONFIG_IDF_TARGET_ESP32
|
||||
|
||||
@@ -43,7 +43,7 @@ static const char *TAG = "flash_encrypt";
|
||||
|
||||
/* Static functions for stages of flash encryption */
|
||||
static esp_err_t encrypt_bootloader(void);
|
||||
static esp_err_t encrypt_and_load_partition_table(esp_partition_info_t *partition_table, int *num_partitions);
|
||||
static esp_err_t encrypt_and_load_partition_table(uint32_t offset, esp_partition_info_t *partition_table, int *num_partitions);
|
||||
static esp_err_t encrypt_partition(int index, const esp_partition_info_t *partition);
|
||||
static size_t get_flash_encrypt_cnt_value(void);
|
||||
|
||||
@@ -262,12 +262,12 @@ esp_err_t esp_flash_encrypt_contents(void)
|
||||
esp_flash_encryption_enable_key_mgr();
|
||||
#endif
|
||||
|
||||
err = encrypt_bootloader();
|
||||
err = encrypt_bootloader(); // PART_SUBTYPE_BOOTLOADER_PRIMARY
|
||||
if (err != ESP_OK) {
|
||||
return err;
|
||||
}
|
||||
|
||||
err = encrypt_and_load_partition_table(partition_table, &num_partitions);
|
||||
err = encrypt_and_load_partition_table(ESP_PRIMARY_PARTITION_TABLE_OFFSET, partition_table, &num_partitions); // PART_SUBTYPE_PARTITION_TABLE_PRIMARY
|
||||
if (err != ESP_OK) {
|
||||
return err;
|
||||
}
|
||||
@@ -277,6 +277,14 @@ esp_err_t esp_flash_encrypt_contents(void)
|
||||
|
||||
/* Go through each partition and encrypt if necessary */
|
||||
for (int i = 0; i < num_partitions; i++) {
|
||||
if ((partition_table[i].type == PART_TYPE_BOOTLOADER && partition_table[i].subtype == PART_SUBTYPE_BOOTLOADER_PRIMARY)
|
||||
|| (partition_table[i].type == PART_TYPE_PARTITION_TABLE && partition_table[i].subtype == PART_SUBTYPE_PARTITION_TABLE_PRIMARY)) {
|
||||
/* Skip encryption of PRIMARY partitions for bootloader and partition table.
|
||||
* PRIMARY partitions have already been encrypted above.
|
||||
* We allow to encrypt partitions that are not PRIMARY.
|
||||
*/
|
||||
continue;
|
||||
}
|
||||
err = encrypt_partition(i, &partition_table[i]);
|
||||
if (err != ESP_OK) {
|
||||
return err;
|
||||
@@ -337,13 +345,13 @@ static esp_err_t encrypt_bootloader(void)
|
||||
|
||||
#if CONFIG_SECURE_BOOT_V2_ENABLED
|
||||
/* The image length obtained from esp_image_verify_bootloader includes the sector boundary padding and the signature block lengths */
|
||||
if (ESP_BOOTLOADER_OFFSET + image_length > ESP_PARTITION_TABLE_OFFSET) {
|
||||
ESP_LOGE(TAG, "Bootloader is too large to fit Secure Boot V2 signature sector and partition table (configured offset 0x%x)", ESP_PARTITION_TABLE_OFFSET);
|
||||
if (image_length > ESP_BOOTLOADER_SIZE) {
|
||||
ESP_LOGE(TAG, "Bootloader is too large to fit Secure Boot V2 signature sector and partition table (configured offset 0x%x)", ESP_PRIMARY_PARTITION_TABLE_OFFSET);
|
||||
return ESP_ERR_INVALID_SIZE;
|
||||
}
|
||||
#endif // CONFIG_SECURE_BOOT_V2_ENABLED
|
||||
|
||||
err = esp_flash_encrypt_region(ESP_BOOTLOADER_OFFSET, image_length);
|
||||
err = esp_flash_encrypt_region(ESP_PRIMARY_BOOTLOADER_OFFSET, image_length);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to encrypt bootloader in place: 0x%x", err);
|
||||
return err;
|
||||
@@ -368,33 +376,37 @@ static esp_err_t encrypt_bootloader(void)
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t encrypt_and_load_partition_table(esp_partition_info_t *partition_table, int *num_partitions)
|
||||
static esp_err_t read_and_verify_partition_table(uint32_t offset, esp_partition_info_t *partition_table, int *num_partitions)
|
||||
{
|
||||
esp_err_t err;
|
||||
/* Check for plaintext partition table */
|
||||
err = bootloader_flash_read(ESP_PARTITION_TABLE_OFFSET, partition_table, ESP_PARTITION_TABLE_MAX_LEN, false);
|
||||
err = bootloader_flash_read(offset, partition_table, ESP_PARTITION_TABLE_MAX_LEN, false);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to read partition table data");
|
||||
ESP_LOGE(TAG, "Failed to read partition table data at 0x%" PRIx32, offset);
|
||||
return err;
|
||||
}
|
||||
if (esp_partition_table_verify(partition_table, false, num_partitions) == ESP_OK) {
|
||||
ESP_LOGD(TAG, "partition table is plaintext. Encrypting...");
|
||||
esp_err_t err = esp_flash_encrypt_region(ESP_PARTITION_TABLE_OFFSET,
|
||||
FLASH_SECTOR_SIZE);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to encrypt partition table in place. %x", err);
|
||||
return err;
|
||||
}
|
||||
} else {
|
||||
ESP_LOGE(TAG, "Failed to read partition table data - not plaintext?");
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
err = esp_partition_table_verify(partition_table, false, num_partitions);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to read partition table data - not plaintext or empty?");
|
||||
}
|
||||
|
||||
/* Valid partition table loaded */
|
||||
ESP_LOGI(TAG, "partition table encrypted and loaded successfully");
|
||||
return ESP_OK;
|
||||
return err;
|
||||
}
|
||||
|
||||
static esp_err_t encrypt_and_load_partition_table(uint32_t offset, esp_partition_info_t *partition_table, int *num_partitions)
|
||||
{
|
||||
esp_err_t err = read_and_verify_partition_table(offset, partition_table, num_partitions);
|
||||
if (err != ESP_OK) {
|
||||
return err;
|
||||
}
|
||||
ESP_LOGD(TAG, "partition table is plaintext. Encrypting...");
|
||||
err = esp_flash_encrypt_region(offset, FLASH_SECTOR_SIZE);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to encrypt partition table in place. %x", err);
|
||||
return err;
|
||||
}
|
||||
ESP_LOGI(TAG, "partition table encrypted and loaded successfully");
|
||||
return err;
|
||||
}
|
||||
|
||||
static esp_err_t encrypt_partition(int index, const esp_partition_info_t *partition)
|
||||
{
|
||||
@@ -402,23 +414,26 @@ static esp_err_t encrypt_partition(int index, const esp_partition_info_t *partit
|
||||
bool should_encrypt = (partition->flags & PART_FLAG_ENCRYPTED);
|
||||
uint32_t size = partition->pos.size;
|
||||
|
||||
if (partition->type == PART_TYPE_APP) {
|
||||
/* check if the partition holds a valid unencrypted app */
|
||||
if (partition->type == PART_TYPE_APP || partition->type == PART_TYPE_BOOTLOADER) {
|
||||
/* check if the partition holds a valid unencrypted app/bootloader */
|
||||
esp_image_metadata_t image_data = {};
|
||||
err = esp_image_verify(ESP_IMAGE_VERIFY,
|
||||
&partition->pos,
|
||||
&image_data);
|
||||
if (partition->type == PART_TYPE_BOOTLOADER) {
|
||||
esp_image_bootloader_offset_set(partition->pos.offset);
|
||||
}
|
||||
err = esp_image_verify(ESP_IMAGE_VERIFY, &partition->pos, &image_data);
|
||||
should_encrypt = (err == ESP_OK);
|
||||
#ifdef CONFIG_SECURE_FLASH_ENCRYPT_ONLY_IMAGE_LEN_IN_APP_PART
|
||||
if (should_encrypt) {
|
||||
if (partition->type == PART_TYPE_APP && should_encrypt) {
|
||||
// Encrypt only the app image instead of encrypting the whole partition
|
||||
size = image_data.image_len;
|
||||
#if CONFIG_SECURE_SIGNED_ON_UPDATE_NO_SECURE_BOOT
|
||||
// If secure update without secure boot, also encrypt the signature block
|
||||
size += esp_secure_boot_sig_block_size();
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
} else if (partition->type == PART_TYPE_PARTITION_TABLE) {
|
||||
/* check if the partition holds a valid unencrypted partition table */
|
||||
esp_partition_info_t partition_table[ESP_PARTITION_TABLE_MAX_ENTRIES];
|
||||
int num_partitions;
|
||||
err = read_and_verify_partition_table(partition->pos.offset, partition_table, &num_partitions);
|
||||
should_encrypt = (err == ESP_OK && num_partitions != 0);
|
||||
} else if ((partition->type == PART_TYPE_DATA && partition->subtype == PART_SUBTYPE_DATA_OTA)
|
||||
|| (partition->type == PART_TYPE_DATA && partition->subtype == PART_SUBTYPE_DATA_NVS_KEYS)) {
|
||||
/* check if we have ota data partition and the partition should be encrypted unconditionally */
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -52,10 +52,11 @@ esp_err_t esp_partition_table_verify(const esp_partition_info_t *partition_table
|
||||
}
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
//MD5 checksum matches and we continue with the next interation in
|
||||
//MD5 checksum matches and we continue with the next iteration in
|
||||
//order to detect the end of the partition table
|
||||
md5_found = 1;
|
||||
} else if (part->magic == 0xFFFF
|
||||
} else if (num_parts != 0 // the first record cannot be empty, otherwise the whole table is empty
|
||||
&& part->magic == 0xFFFF
|
||||
&& part->type == PART_TYPE_END
|
||||
&& part->subtype == PART_SUBTYPE_END) {
|
||||
ESP_LOGD(TAG, "partition table verified, %d entries", num_parts);
|
||||
|
||||
@@ -12,10 +12,6 @@
|
||||
#include "esp_secure_boot.h"
|
||||
#include "hal/efuse_hal.h"
|
||||
|
||||
#ifdef SOC_ECDSA_SUPPORTED
|
||||
#include "hal/ecdsa_ll.h"
|
||||
#endif
|
||||
|
||||
#ifndef BOOTLOADER_BUILD
|
||||
static __attribute__((unused)) const char *TAG = "secure_boot";
|
||||
|
||||
@@ -344,23 +340,6 @@ bool esp_secure_boot_cfg_verify_release_mode(void)
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef SOC_ECDSA_P192_CURVE_DEFAULT_DISABLED
|
||||
if (ecdsa_ll_is_configurable_curve_supported()) {
|
||||
secure = esp_efuse_read_field_bit(ESP_EFUSE_WR_DIS_ECDSA_CURVE_MODE);
|
||||
if (!secure) {
|
||||
uint8_t current_curve;
|
||||
esp_err_t err = esp_efuse_read_field_blob(ESP_EFUSE_ECDSA_CURVE_MODE, ¤t_curve, ESP_EFUSE_ECDSA_CURVE_MODE[0]->bit_count);
|
||||
if (err == ESP_OK) {
|
||||
if (current_curve != ESP_EFUSE_ECDSA_CURVE_MODE_ALLOW_ONLY_P256_BIT_LOCKED) {
|
||||
// If not P256 mode
|
||||
result &= secure;
|
||||
ESP_LOGW(TAG, "Not write disabled ECDSA curve mode (set WR_DIS_ECDSA_CURVE_MODE->1)");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SECURE_BOOT_ENABLE_AGGRESSIVE_KEY_REVOKE
|
||||
secure = esp_efuse_read_field_bit(ESP_EFUSE_SECURE_BOOT_AGGRESSIVE_REVOKE);
|
||||
result &= secure;
|
||||
|
||||
@@ -154,12 +154,13 @@ esp_err_t esp_secure_boot_verify_sbv2_signature_block(const ets_secure_boot_sign
|
||||
ets_secure_boot_key_digests_t trusted_key_digests = {0};
|
||||
bool valid_sig_blk = false;
|
||||
for (unsigned i = 0; i < SECURE_BOOT_NUM_BLOCKS; i++) {
|
||||
trusted_key_digests.key_digests[i] = &trusted.key_digests[i];
|
||||
if (sig_block->block[i].version != ESP_SECURE_BOOT_SCHEME) {
|
||||
ESP_LOGD(TAG, "%s signing scheme selected but signature block %d generated for %s scheme", esp_secure_boot_get_scheme_name(ESP_SECURE_BOOT_SCHEME), i, esp_secure_boot_get_scheme_name(sig_block->block[i].version));
|
||||
continue;
|
||||
} else {
|
||||
valid_sig_blk = true;
|
||||
}
|
||||
trusted_key_digests.key_digests[i] = &trusted.key_digests[i];
|
||||
}
|
||||
if (valid_sig_blk != true) {
|
||||
ESP_LOGE(TAG, "No signature block generated for valid scheme");
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-P4 | ESP32-S2 | ESP32-S3 |
|
||||
| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- | -------- |
|
||||
| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-P4 | ESP32-S2 | ESP32-S3 |
|
||||
| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | -------- |
|
||||
|
||||
@@ -24,7 +24,6 @@ set(common_include_dirs
|
||||
common/btc/profile/esp/blufi/include
|
||||
common/btc/profile/esp/include
|
||||
common/hci_log/include
|
||||
common/ble_log/include
|
||||
)
|
||||
|
||||
set(ble_mesh_include_dirs
|
||||
@@ -86,13 +85,11 @@ if(CONFIG_BT_ENABLED)
|
||||
elseif(CONFIG_IDF_TARGET_ESP32S3)
|
||||
list(APPEND ldscripts "linker_rw_bt_controller.lf")
|
||||
elseif(CONFIG_IDF_TARGET_ESP32C2)
|
||||
list(APPEND srcs "controller/esp32c2/ble.c")
|
||||
if(CONFIG_BT_CTRL_RUN_IN_FLASH_ONLY)
|
||||
list(APPEND srcs "controller/esp32c2/dummy.c")
|
||||
endif()
|
||||
set(ldscripts "linker_esp32c2.lf")
|
||||
else()
|
||||
list(APPEND srcs "controller/${target_name}/ble.c")
|
||||
list(APPEND ldscripts "linker_esp_ble_controller.lf")
|
||||
endif()
|
||||
|
||||
@@ -133,46 +130,8 @@ if(CONFIG_BT_ENABLED)
|
||||
"common/osi/osi.c"
|
||||
"common/osi/semaphore.c"
|
||||
"porting/mem/bt_osi_mem.c"
|
||||
"common/ble_log/ble_log_spi_out.c"
|
||||
"common/ble_log/ble_log_uhci_out.c"
|
||||
)
|
||||
|
||||
# BLE Log Module
|
||||
if(CONFIG_BLE_LOG_ENABLED)
|
||||
# Core source files
|
||||
list(APPEND srcs
|
||||
common/ble_log/src/ble_log.c
|
||||
common/ble_log/src/ble_log_lbm.c
|
||||
common/ble_log/src/ble_log_rt.c
|
||||
common/ble_log/src/ble_log_util.c
|
||||
)
|
||||
|
||||
# Includes
|
||||
list(APPEND include_dirs
|
||||
common/ble_log/include
|
||||
)
|
||||
|
||||
# Private includes
|
||||
list(APPEND priv_include_dirs
|
||||
common/ble_log/src/internal_include
|
||||
common/ble_log/src/internal_include/prph
|
||||
)
|
||||
|
||||
# Timestamp synchronization extension
|
||||
if(CONFIG_BLE_LOG_TS_ENABLED)
|
||||
list(APPEND srcs common/ble_log/src/ble_log_ts.c)
|
||||
endif()
|
||||
|
||||
# Peripheral interface implementation
|
||||
if(CONFIG_BLE_LOG_PRPH_DUMMY)
|
||||
list(APPEND srcs common/ble_log/src/prph/ble_log_prph_dummy.c)
|
||||
elseif(CONFIG_BLE_LOG_PRPH_SPI_MASTER_DMA)
|
||||
list(APPEND srcs common/ble_log/src/prph/ble_log_prph_spi_master_dma.c)
|
||||
elseif(CONFIG_BLE_LOG_PRPH_UART_DMA)
|
||||
list(APPEND srcs common/ble_log/src/prph/ble_log_prph_uart_dma.c)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Host Bluedroid
|
||||
if(CONFIG_BT_BLUEDROID_ENABLED)
|
||||
|
||||
@@ -488,19 +447,6 @@ if(CONFIG_BT_ENABLED)
|
||||
list(APPEND srcs "esp_ble_mesh/core/bluedroid_host/adapter.c")
|
||||
endif()
|
||||
|
||||
if(CONFIG_BT_BLE_FEAT_ISO_EN)
|
||||
list(APPEND srcs "host/bluedroid/stack/btm/btm_ble_iso.c"
|
||||
"host/bluedroid/btc/profile/std/iso/btc_iso_ble.c"
|
||||
"host/bluedroid/api/esp_ble_iso_api.c"
|
||||
"host/bluedroid/hci/ble_hci_iso.c")
|
||||
endif()
|
||||
|
||||
if(CONFIG_BT_BLE_FEAT_CTE_EN)
|
||||
list(APPEND srcs "host/bluedroid/stack/btm/btm_ble_cte.c"
|
||||
"host/bluedroid/btc/profile/std/cte/btc_ble_cte.c"
|
||||
"host/bluedroid/api/esp_ble_cte_api.c")
|
||||
endif()
|
||||
|
||||
endif()
|
||||
|
||||
if(CONFIG_BLE_MESH)
|
||||
@@ -678,25 +624,23 @@ if(CONFIG_BT_ENABLED)
|
||||
|
||||
if(NOT (CONFIG_BT_LE_CRYPTO_STACK_MBEDTLS OR CONFIG_BT_NIMBLE_CRYPTO_STACK_MBEDTLS))
|
||||
list(APPEND include_dirs
|
||||
common/tinycrypt/include
|
||||
common/tinycrypt/port
|
||||
porting/ext/tinycrypt/include
|
||||
)
|
||||
list(APPEND srcs "common/tinycrypt/src/utils.c"
|
||||
"common/tinycrypt/src/sha256.c"
|
||||
"common/tinycrypt/src/ecc.c"
|
||||
"common/tinycrypt/src/ctr_prng.c"
|
||||
"common/tinycrypt/src/ctr_mode.c"
|
||||
"common/tinycrypt/src/aes_decrypt.c"
|
||||
"common/tinycrypt/src/aes_encrypt.c"
|
||||
"common/tinycrypt/src/ccm_mode.c"
|
||||
"common/tinycrypt/src/ecc_dsa.c"
|
||||
"common/tinycrypt/src/cmac_mode.c"
|
||||
"common/tinycrypt/src/ecc_dh.c"
|
||||
"common/tinycrypt/src/hmac_prng.c"
|
||||
"common/tinycrypt/src/ecc_platform_specific.c"
|
||||
"common/tinycrypt/src/hmac.c"
|
||||
"common/tinycrypt/src/cbc_mode.c"
|
||||
"common/tinycrypt/port/esp_tinycrypt_port.c")
|
||||
list(APPEND srcs "porting/ext/tinycrypt/src/utils.c"
|
||||
"porting/ext/tinycrypt/src/sha256.c"
|
||||
"porting/ext/tinycrypt/src/ecc.c"
|
||||
"porting/ext/tinycrypt/src/ctr_prng.c"
|
||||
"porting/ext/tinycrypt/src/ctr_mode.c"
|
||||
"porting/ext/tinycrypt/src/aes_decrypt.c"
|
||||
"porting/ext/tinycrypt/src/aes_encrypt.c"
|
||||
"porting/ext/tinycrypt/src/ccm_mode.c"
|
||||
"porting/ext/tinycrypt/src/ecc_dsa.c"
|
||||
"porting/ext/tinycrypt/src/cmac_mode.c"
|
||||
"porting/ext/tinycrypt/src/ecc_dh.c"
|
||||
"porting/ext/tinycrypt/src/hmac_prng.c"
|
||||
"porting/ext/tinycrypt/src/ecc_platform_specific.c"
|
||||
"porting/ext/tinycrypt/src/hmac.c"
|
||||
"porting/ext/tinycrypt/src/cbc_mode.c")
|
||||
endif()
|
||||
|
||||
if(CONFIG_BT_NIMBLE_ENABLED)
|
||||
@@ -793,16 +737,8 @@ if(CONFIG_BT_ENABLED)
|
||||
"host/nimble/nimble/nimble/host/store/config/src/ble_store_nvs.c"
|
||||
"host/nimble/nimble/nimble/host/src/ble_gattc_cache.c"
|
||||
"host/nimble/nimble/nimble/host/src/ble_gattc_cache_conn.c"
|
||||
"host/nimble/nimble/nimble/host/src/ble_eatt.c"
|
||||
)
|
||||
|
||||
if(CONFIG_BT_NIMBLE_ISO)
|
||||
list(APPEND srcs
|
||||
"host/nimble/nimble/nimble/host/src/ble_hs_iso_hci.c"
|
||||
"host/nimble/nimble/nimble/host/src/ble_hs_iso.c"
|
||||
)
|
||||
endif()
|
||||
|
||||
if(CONFIG_BT_CONTROLLER_DISABLED AND CONFIG_BT_NIMBLE_TRANSPORT_UART)
|
||||
list(APPEND srcs
|
||||
"host/nimble/nimble/nimble/transport/uart_ll/src/hci_uart.c"
|
||||
@@ -915,27 +851,11 @@ if(CONFIG_BT_ENABLED)
|
||||
|
||||
endif()
|
||||
|
||||
|
||||
set(bt_priv_requires
|
||||
nvs_flash
|
||||
soc
|
||||
esp_pm
|
||||
esp_phy
|
||||
esp_coex
|
||||
mbedtls
|
||||
esp_driver_uart
|
||||
vfs
|
||||
esp_ringbuf
|
||||
esp_driver_spi
|
||||
esp_driver_gpio
|
||||
esp_gdbstub
|
||||
)
|
||||
|
||||
idf_component_register(SRCS "${srcs}"
|
||||
INCLUDE_DIRS "${include_dirs}"
|
||||
PRIV_INCLUDE_DIRS "${priv_include_dirs}"
|
||||
REQUIRES esp_timer esp_wifi
|
||||
PRIV_REQUIRES "${bt_priv_requires}"
|
||||
PRIV_REQUIRES nvs_flash soc esp_pm esp_phy esp_coex mbedtls esp_driver_uart vfs esp_ringbuf
|
||||
LDFRAGMENTS "${ldscripts}")
|
||||
|
||||
if(CONFIG_BT_ENABLED)
|
||||
@@ -962,38 +882,19 @@ if(CONFIG_BT_ENABLED)
|
||||
target_link_libraries(${COMPONENT_LIB} PUBLIC btdm_app)
|
||||
endif()
|
||||
elseif(CONFIG_BT_CONTROLLER_ENABLED)
|
||||
if(CONFIG_BT_LE_CONTROLLER_LOG_WRAP_PANIC_HANDLER_ENABLE)
|
||||
target_link_libraries(${COMPONENT_LIB} INTERFACE "-Wl,--wrap=esp_panic_handler")
|
||||
endif()
|
||||
if(DEFINED CONFIG_BLE_LOG_PRPH_UART_DMA_PORT)
|
||||
if(CONFIG_BLE_LOG_PRPH_UART_DMA_PORT EQUAL 0)
|
||||
target_link_libraries(${COMPONENT_LIB} INTERFACE "-Wl,--wrap=uart_tx_chars")
|
||||
target_link_libraries(${COMPONENT_LIB} INTERFACE "-Wl,--wrap=uart_write_bytes")
|
||||
target_link_libraries(${COMPONENT_LIB} INTERFACE "-Wl,--wrap=uart_write_bytes_with_break")
|
||||
endif()
|
||||
endif()
|
||||
if(CONFIG_BT_BLE_LOG_UHCI_OUT_ENABLED)
|
||||
target_link_libraries(${COMPONENT_LIB} INTERFACE "-Wl,--wrap=uart_tx_chars")
|
||||
target_link_libraries(${COMPONENT_LIB} INTERFACE "-Wl,--wrap=uart_write_bytes")
|
||||
target_link_libraries(${COMPONENT_LIB} INTERFACE "-Wl,--wrap=uart_write_bytes_with_break")
|
||||
endif()
|
||||
if(CONFIG_IDF_TARGET_ESP32C6)
|
||||
add_prebuilt_library(libble_app
|
||||
"${CMAKE_CURRENT_LIST_DIR}/controller/lib_esp32c6/esp32c6-bt-lib/esp32c6/libble_app.a"
|
||||
REQUIRES esp_phy)
|
||||
"${CMAKE_CURRENT_LIST_DIR}/controller/lib_esp32c6/esp32c6-bt-lib/esp32c6/libble_app.a")
|
||||
elseif(CONFIG_IDF_TARGET_ESP32C61)
|
||||
add_prebuilt_library(libble_app
|
||||
"${CMAKE_CURRENT_LIST_DIR}/controller/lib_esp32c6/esp32c6-bt-lib/esp32c61/libble_app.a"
|
||||
REQUIRES esp_phy)
|
||||
"${CMAKE_CURRENT_LIST_DIR}/controller/lib_esp32c6/esp32c6-bt-lib/esp32c61/libble_app.a")
|
||||
else()
|
||||
if(CONFIG_BT_CTRL_RUN_IN_FLASH_ONLY AND CONFIG_IDF_TARGET_ESP32C2)
|
||||
if(CONFIG_BT_CTRL_RUN_IN_FLASH_ONLY)
|
||||
add_prebuilt_library(libble_app
|
||||
"controller/lib_${target_name}/${target_name}-bt-lib/libble_app_flash.a"
|
||||
REQUIRES esp_phy)
|
||||
"controller/lib_${target_name}/${target_name}-bt-lib/libble_app_flash.a")
|
||||
else()
|
||||
add_prebuilt_library(libble_app
|
||||
"controller/lib_${target_name}/${target_name}-bt-lib/libble_app.a"
|
||||
REQUIRES esp_phy)
|
||||
"controller/lib_${target_name}/${target_name}-bt-lib/libble_app.a")
|
||||
endif()
|
||||
endif()
|
||||
target_link_libraries(${COMPONENT_LIB} PRIVATE libble_app)
|
||||
|
||||
@@ -81,6 +81,8 @@ menu "Bluetooth"
|
||||
So this option will disable the PMP (ESP_SYSTEM_PMP_IDRAM_SPLIT)
|
||||
|
||||
menu "Common Options"
|
||||
visible if (BT_BLUEDROID_ENABLED || BT_NIMBLE_ENABLED)
|
||||
|
||||
source "$IDF_PATH/components/bt/common/Kconfig.in"
|
||||
endmenu
|
||||
|
||||
|
||||
@@ -1,257 +1,6 @@
|
||||
config BT_ALARM_MAX_NUM
|
||||
int "Maximum number of Bluetooth alarms"
|
||||
default 50
|
||||
depends on (BT_BLUEDROID_ENABLED || BT_NIMBLE_ENABLED)
|
||||
help
|
||||
This option decides the maximum number of alarms which
|
||||
could be used by Bluetooth host.
|
||||
|
||||
menu "BLE Log"
|
||||
source "$IDF_PATH/components/bt/common/ble_log/Kconfig.in"
|
||||
endmenu
|
||||
|
||||
config BT_BLE_LOG_SPI_OUT_ENABLED
|
||||
bool "Output ble logs to SPI bus (Experimental)"
|
||||
default n
|
||||
help
|
||||
Output ble logs to SPI bus
|
||||
|
||||
config BT_BLE_LOG_SPI_OUT_UL_TASK_BUF_SIZE
|
||||
int "SPI transaction buffer size for upper layer task logs"
|
||||
depends on BT_BLE_LOG_SPI_OUT_ENABLED
|
||||
default 512
|
||||
help
|
||||
SPI transaction buffer size for upper layer task logs.
|
||||
There will be 2 SPI DMA buffers with the same size.
|
||||
|
||||
config BT_BLE_LOG_SPI_OUT_HCI_ENABLED
|
||||
bool "Enable HCI log output to SPI"
|
||||
depends on BT_BLE_LOG_SPI_OUT_ENABLED
|
||||
default n
|
||||
help
|
||||
Enable logging of HCI packets to the SPI bus when BLE SPI log output is enabled.
|
||||
|
||||
config BT_BLE_LOG_SPI_OUT_HCI_BUF_SIZE
|
||||
int "SPI transaction buffer size for HCI logs"
|
||||
depends on BT_BLE_LOG_SPI_OUT_HCI_ENABLED
|
||||
default 1024
|
||||
help
|
||||
SPI transaction buffer size for HCI logs.
|
||||
There will be 2 SPI DMA buffers with the same size.
|
||||
|
||||
config BT_BLE_LOG_SPI_OUT_HCI_TASK_CNT
|
||||
int "HCI task count"
|
||||
depends on BT_BLE_LOG_SPI_OUT_HCI_ENABLED
|
||||
default 1
|
||||
help
|
||||
HCI task count
|
||||
|
||||
config BT_BLE_LOG_SPI_OUT_HOST_ENABLED
|
||||
bool "Enable Host log output to SPI"
|
||||
depends on BT_BLE_LOG_SPI_OUT_ENABLED
|
||||
default n
|
||||
help
|
||||
This configuration applies to the logs of both Bluedroid Host and NimBLE Host.
|
||||
When BLE SPI log output is enabled, this option allows host logs to be transmitted via SPI.
|
||||
|
||||
config BT_BLE_LOG_SPI_OUT_HOST_BUF_SIZE
|
||||
int "SPI transaction buffer size for host logs"
|
||||
depends on BT_BLE_LOG_SPI_OUT_HOST_ENABLED
|
||||
default 1024
|
||||
help
|
||||
SPI transaction buffer size for host logs.
|
||||
There will be 2 SPI DMA buffers with the same size.
|
||||
|
||||
config BT_BLE_LOG_SPI_OUT_HOST_TASK_CNT
|
||||
int "Host task count"
|
||||
depends on BT_BLE_LOG_SPI_OUT_HOST_ENABLED
|
||||
default 2
|
||||
help
|
||||
Host task count.
|
||||
|
||||
config BT_BLE_LOG_SPI_OUT_LL_ENABLED
|
||||
bool "Enable Controller log output to SPI"
|
||||
depends on BT_BLE_LOG_SPI_OUT_ENABLED
|
||||
depends on BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED
|
||||
default n
|
||||
help
|
||||
Enable controller log output to SPI bus.
|
||||
|
||||
config BT_BLE_LOG_SPI_OUT_LL_TASK_BUF_SIZE
|
||||
int "SPI transaction buffer size for lower layer task logs"
|
||||
depends on BT_BLE_LOG_SPI_OUT_LL_ENABLED
|
||||
default 1024
|
||||
help
|
||||
SPI transaction buffer size for lower layer task logs.
|
||||
There will be 2 SPI DMA buffers with the same size.
|
||||
|
||||
config BT_BLE_LOG_SPI_OUT_LL_ISR_BUF_SIZE
|
||||
int "SPI transaction buffer size for lower layer ISR logs"
|
||||
depends on BT_BLE_LOG_SPI_OUT_LL_ENABLED
|
||||
default 512
|
||||
help
|
||||
SPI transaction buffer size for lower layer ISR logs.
|
||||
There will be 2 SPI DMA buffers with the same size.
|
||||
|
||||
config BT_BLE_LOG_SPI_OUT_LL_HCI_BUF_SIZE
|
||||
int "SPI transaction buffer size for lower layer HCI logs"
|
||||
depends on BT_BLE_LOG_SPI_OUT_LL_ENABLED
|
||||
default 512
|
||||
help
|
||||
SPI transaction buffer size for upper layer HCI logs.
|
||||
There will be 2 SPI DMA buffers with the same size
|
||||
|
||||
config BT_BLE_LOG_SPI_OUT_MOSI_IO_NUM
|
||||
int "GPIO number of SPI MOSI"
|
||||
depends on BT_BLE_LOG_SPI_OUT_ENABLED
|
||||
default 0
|
||||
help
|
||||
GPIO number of SPI MOSI
|
||||
|
||||
config BT_BLE_LOG_SPI_OUT_SCLK_IO_NUM
|
||||
int "GPIO number of SPI SCLK"
|
||||
depends on BT_BLE_LOG_SPI_OUT_ENABLED
|
||||
default 1
|
||||
help
|
||||
GPIO number of SPI SCLK
|
||||
|
||||
config BT_BLE_LOG_SPI_OUT_CS_IO_NUM
|
||||
int "GPIO number of SPI CS"
|
||||
depends on BT_BLE_LOG_SPI_OUT_ENABLED
|
||||
default 2
|
||||
help
|
||||
GPIO number of SPI CS
|
||||
|
||||
config BT_BLE_LOG_SPI_OUT_TS_SYNC_ENABLED
|
||||
bool "Enable ble log & logic analyzer log time sync"
|
||||
depends on BT_BLE_LOG_SPI_OUT_ENABLED
|
||||
default y
|
||||
help
|
||||
Enable ble log & logic analyzer log time sync
|
||||
|
||||
config BT_BLE_LOG_SPI_OUT_SYNC_IO_NUM
|
||||
int "GPIO number of SYNC IO"
|
||||
depends on BT_BLE_LOG_SPI_OUT_TS_SYNC_ENABLED
|
||||
default 3
|
||||
help
|
||||
GPIO number of SYNC IO
|
||||
|
||||
config BT_BLE_LOG_SPI_OUT_FLUSH_TIMER_ENABLED
|
||||
bool "Enable periodic buffer flush out"
|
||||
depends on BT_BLE_LOG_SPI_OUT_ENABLED
|
||||
default n
|
||||
help
|
||||
Enable periodic buffer flush out
|
||||
Not recommended when SPI receiver is unavailable
|
||||
|
||||
config BT_BLE_LOG_SPI_OUT_FLUSH_TIMEOUT
|
||||
int "Buffer flush out period in unit of ms"
|
||||
depends on BT_BLE_LOG_SPI_OUT_FLUSH_TIMER_ENABLED
|
||||
default 1000
|
||||
help
|
||||
Buffer flush out period in unit of ms
|
||||
|
||||
config BT_BLE_LOG_SPI_OUT_LE_AUDIO_ENABLED
|
||||
bool "Enable LE Audio log output to SPI"
|
||||
depends on BT_BLE_LOG_SPI_OUT_ENABLED
|
||||
default n
|
||||
help
|
||||
Enable LE Audio log output to SPI
|
||||
|
||||
config BT_BLE_LOG_SPI_OUT_LE_AUDIO_BUF_SIZE
|
||||
int "SPI transaction buffer size for LE Audio logs"
|
||||
depends on BT_BLE_LOG_SPI_OUT_LE_AUDIO_ENABLED
|
||||
default 1024
|
||||
help
|
||||
SPI transaction buffer size for LE Audio logs.
|
||||
There will be 2 SPI DMA buffers with the same size.
|
||||
|
||||
config BT_BLE_LOG_SPI_OUT_LE_AUDIO_TASK_CNT
|
||||
int "LE audio task count"
|
||||
depends on BT_BLE_LOG_SPI_OUT_LE_AUDIO_ENABLED
|
||||
default 1
|
||||
help
|
||||
LE audio task count
|
||||
|
||||
config BT_BLE_LOG_SPI_OUT_MESH_ENABLED
|
||||
bool "Enable BLE mesh log output to SPI"
|
||||
depends on BT_BLE_LOG_SPI_OUT_ENABLED
|
||||
default n
|
||||
help
|
||||
Enable BLE mesh log output to SPI
|
||||
|
||||
config BT_BLE_LOG_SPI_OUT_MESH_BUF_SIZE
|
||||
int "SPI transaction buffer size for BLE mesh logs"
|
||||
depends on BT_BLE_LOG_SPI_OUT_MESH_ENABLED
|
||||
default 1024
|
||||
help
|
||||
SPI transaction buffer size for BLE mesh logs.
|
||||
There will be 2 SPI DMA buffers with the same size.
|
||||
|
||||
config BT_BLE_LOG_SPI_OUT_MESH_TASK_CNT
|
||||
int "Mesh task count"
|
||||
depends on BT_BLE_LOG_SPI_OUT_MESH_ENABLED
|
||||
default 3
|
||||
help
|
||||
Mesh task count
|
||||
|
||||
config BT_BLE_LOG_UHCI_OUT_ENABLED
|
||||
bool "Output ble logs via UHCI (UART DMA) driver (Experimental)"
|
||||
default n
|
||||
help
|
||||
Output ble logs via UHCI (UART DMA) driver
|
||||
On enable, BT_BLE_LOG_UHCI_OUT_UART_PORT would be reinited with
|
||||
BT_BLE_LOG_UHCI_OUT_UART_BAUD_RATE as new baud rate and
|
||||
BT_BLE_LOG_UHCI_OUT_UART_IO_NUM_TX as new UART Tx IO
|
||||
|
||||
config BT_BLE_LOG_UHCI_OUT_UART_PORT
|
||||
int "UART port connected to UHCI controller"
|
||||
depends on BT_BLE_LOG_UHCI_OUT_ENABLED
|
||||
default 0
|
||||
help
|
||||
UART port connected to UHCI controller
|
||||
If UART port 0 is selected, UART VFS Driver, UART ROM Driver
|
||||
and UART Driver output would be redirected to BLE Log UHCI Out
|
||||
to solve UART Tx FIFO multi-task access issue
|
||||
|
||||
config BT_BLE_LOG_UHCI_OUT_LL_TASK_BUF_SIZE
|
||||
int "UHCI transaction buffer size for lower layer task logs"
|
||||
depends on BT_BLE_LOG_UHCI_OUT_ENABLED
|
||||
default 1024
|
||||
help
|
||||
UHCI transaction buffer size for lower layer task logs
|
||||
|
||||
config BT_BLE_LOG_UHCI_OUT_LL_ISR_BUF_SIZE
|
||||
int "UHCI transaction buffer size for lower layer ISR logs"
|
||||
depends on BT_BLE_LOG_UHCI_OUT_ENABLED
|
||||
default 1024
|
||||
help
|
||||
UHCI transaction buffer size for lower layer ISR logs
|
||||
|
||||
config BT_BLE_LOG_UHCI_OUT_LL_HCI_BUF_SIZE
|
||||
int "UHCI transaction buffer size for lower layer HCI logs"
|
||||
depends on BT_BLE_LOG_UHCI_OUT_ENABLED
|
||||
default 1024
|
||||
help
|
||||
UHCI transaction buffer size for lower layer HCI logs
|
||||
|
||||
config BT_BLE_LOG_UHCI_OUT_UART_NEED_INIT
|
||||
bool "Enable to init UART port"
|
||||
depends on BT_BLE_LOG_UHCI_OUT_ENABLED
|
||||
default y
|
||||
help
|
||||
Enable to init UART port
|
||||
|
||||
config BT_BLE_LOG_UHCI_OUT_UART_BAUD_RATE
|
||||
int "Baud rate for BT_BLE_LOG_UHCI_OUT_UART_PORT"
|
||||
depends on BT_BLE_LOG_UHCI_OUT_UART_NEED_INIT
|
||||
default 3000000
|
||||
help
|
||||
Baud rate for BT_BLE_LOG_UHCI_OUT_UART_PORT
|
||||
|
||||
config BT_BLE_LOG_UHCI_OUT_UART_IO_NUM_TX
|
||||
int "IO number for UART TX port"
|
||||
depends on BT_BLE_LOG_UHCI_OUT_UART_NEED_INIT
|
||||
default 0
|
||||
help
|
||||
IO number for UART TX port
|
||||
|
||||
@@ -1,169 +0,0 @@
|
||||
config BLE_LOG_ENABLED
|
||||
bool "Enable BLE Log Module (Experimental)"
|
||||
default n
|
||||
help
|
||||
Enable BLE Log Module
|
||||
|
||||
if BLE_LOG_ENABLED
|
||||
config BLE_LOG_LBM_TRANS_SIZE
|
||||
int "Buffer size for each peripheral transport"
|
||||
default 512
|
||||
help
|
||||
There're 2 log buffer managers (LBMs) with compare-and-swap
|
||||
(CAS) protection, 1 LBM with FreeRTOS mutex protection, 1 LBM
|
||||
without protection for critical section. Each LBM is managing
|
||||
2 ping-pong buffers, which means there will be 4 * 2 *
|
||||
BLE_LOG_LBM_TRANS_SIZE bytes buffer allocated
|
||||
|
||||
config BLE_LOG_LBM_ATOMIC_LOCK_TASK_CNT
|
||||
int "Count of log buffer managers with atomic lock protection for task context"
|
||||
default 2
|
||||
help
|
||||
BLE Log module will search for an LBM with atomic lock protection first; if
|
||||
all LBMs with atomic lock protection are unavailable, BLE Log module will
|
||||
try to use the LBM with spin lock protection. So the more LBMs with atomic
|
||||
lock protection are created, the better the logging performance will be.
|
||||
|
||||
config BLE_LOG_LBM_ATOMIC_LOCK_ISR_CNT
|
||||
int "Count of log buffer managers with atomic lock protection for ISR context"
|
||||
default 1
|
||||
help
|
||||
BLE Log module will search for an LBM with atomic lock protection first; if
|
||||
all LBMs with atomic lock protection are unavailable, BLE Log module will
|
||||
try to use the LBM with spin lock protection. So the more LBMs with atomic
|
||||
lock protection are created, the more ISRs can nest.
|
||||
|
||||
config BLE_LOG_IS_ESP_CONTROLLER
|
||||
bool "Current BLE Controller is ESP BLE Controller"
|
||||
depends on BT_CONTROLLER_ENABLED
|
||||
depends on SOC_ESP_NIMBLE_CONTROLLER
|
||||
default y
|
||||
select BT_LE_CONTROLLER_LOG_ENABLED
|
||||
select BT_LE_CONTROLLER_LOG_MODE_BLE_LOG_V2
|
||||
select BLE_LOG_LL_ENABLED
|
||||
help
|
||||
Current BLE Controller is ESP BLE Controller
|
||||
|
||||
config BLE_LOG_IS_ESP_LEGACY_CONTROLLER
|
||||
bool "Current BLE Controller is ESP BLE Legacy Controller"
|
||||
depends on BT_CONTROLLER_ENABLED
|
||||
depends on !SOC_ESP_NIMBLE_CONTROLLER
|
||||
depends on BT_CTRL_RUN_IN_FLASH_ONLY
|
||||
default y
|
||||
select BT_CTRL_LE_LOG_EN
|
||||
select BLE_LOG_LL_ENABLED
|
||||
help
|
||||
Current BLE Controller is ESP BLE Legacy Controller
|
||||
|
||||
config BLE_LOG_LL_ENABLED
|
||||
bool "Enable BLE Log for Link Layer"
|
||||
depends on BT_CONTROLLER_ENABLED
|
||||
default n
|
||||
help
|
||||
Enable BLE Log for Link Layer
|
||||
|
||||
config BLE_LOG_LBM_LL_TRANS_SIZE
|
||||
int "Buffer size for each peripheral transport of Link Layer LBM"
|
||||
depends on BLE_LOG_LL_ENABLED
|
||||
default 1024
|
||||
help
|
||||
There're 2 Link Layer dedicated log buffer managers (LBMs) with
|
||||
compare-and-swap (CAS) protection. Each LBM is managing 2 ping-
|
||||
pong buffers, which means there will be additional 2 * 2 *
|
||||
BLE_LOG_LBM_LL_TRANS_SIZE bytes buffer allocated
|
||||
|
||||
config BLE_LOG_PAYLOAD_CHECKSUM_ENABLED
|
||||
bool "Enable payload checksum for BLE Log data integrity check"
|
||||
default y
|
||||
help
|
||||
Checksum is the default method for BLE Log data integrity check,
|
||||
but for targets with slow CPU speed, it may cause significant system
|
||||
performance decrease; a compromise could be made to balance the
|
||||
realtime performance and log data integrity, which is calculating the
|
||||
checksum of frame head and payload all together by default, or only
|
||||
calculate the checksum of frame head to minimize performance decrease
|
||||
|
||||
config BLE_LOG_ENH_STAT_ENABLED
|
||||
bool "Enable enhanced statistics for BLE Log"
|
||||
default n
|
||||
help
|
||||
Enable enhanced statistics for written/lost frame/bytes count, which may
|
||||
cost additional ~100kB memory
|
||||
|
||||
config BLE_LOG_TS_ENABLED
|
||||
bool "Enable BLE Log Timestamp Synchronization (TS)"
|
||||
default n
|
||||
help
|
||||
Enable BLE Log TS with external logging module
|
||||
|
||||
config BLE_LOG_SYNC_IO_NUM
|
||||
int "GPIO number for Timestamp Synchronization (TS) toggle output"
|
||||
depends on BLE_LOG_TS_ENABLED
|
||||
default 0
|
||||
help
|
||||
GPIO number for TS toggle output
|
||||
|
||||
choice BLE_LOG_PRPH_CHOICE
|
||||
prompt "BLE Log peripheral choice"
|
||||
default BLE_LOG_PRPH_DUMMY
|
||||
help
|
||||
Choose BLE Log peripheral
|
||||
|
||||
config BLE_LOG_PRPH_DUMMY
|
||||
bool "Dummy transport"
|
||||
help
|
||||
Dummy transport (dump only)
|
||||
|
||||
config BLE_LOG_PRPH_SPI_MASTER_DMA
|
||||
bool "Utilize SPI master DMA driver as transport"
|
||||
depends on SOC_GPSPI_SUPPORTED
|
||||
help
|
||||
Utilize SPI master DMA driver as transport
|
||||
|
||||
config BLE_LOG_PRPH_UART_DMA
|
||||
bool "Utilize UART DMA driver as transport"
|
||||
depends on SOC_UHCI_SUPPORTED
|
||||
help
|
||||
Utilize UART DMA driver as transport
|
||||
endchoice
|
||||
|
||||
if BLE_LOG_PRPH_SPI_MASTER_DMA
|
||||
config BLE_LOG_PRPH_SPI_MASTER_DMA_MOSI_IO_NUM
|
||||
int "GPIO number of MOSI port for SPI master DMA transport"
|
||||
default 0
|
||||
help
|
||||
GPIO number of MOSI port for SPI master DMA transport
|
||||
|
||||
config BLE_LOG_PRPH_SPI_MASTER_DMA_SCLK_IO_NUM
|
||||
int "GPIO number of SCLK port for SPI master DMA transport"
|
||||
default 0
|
||||
help
|
||||
GPIO number of SCLK port for SPI master DMA transport
|
||||
|
||||
config BLE_LOG_PRPH_SPI_MASTER_DMA_CS_IO_NUM
|
||||
int "GPIO number of CS port for SPI master DMA transport"
|
||||
default 0
|
||||
help
|
||||
GPIO number of CS port for SPI master DMA transport
|
||||
endif
|
||||
|
||||
if BLE_LOG_PRPH_UART_DMA
|
||||
config BLE_LOG_PRPH_UART_DMA_PORT
|
||||
int "UART port number for UART DMA transport"
|
||||
default 0
|
||||
help
|
||||
UART port number for UART DMA
|
||||
|
||||
config BLE_LOG_PRPH_UART_DMA_BAUD_RATE
|
||||
int "Baud rate of UART port for UART DMA transport"
|
||||
default 921600
|
||||
help
|
||||
Determine the baud rate of UART port
|
||||
|
||||
config BLE_LOG_PRPH_UART_DMA_TX_IO_NUM
|
||||
int "GPIO number for UART TX"
|
||||
default 0
|
||||
help
|
||||
GPIO number for UART TX
|
||||
endif
|
||||
endif
|
||||
@@ -1,450 +0,0 @@
|
||||
# BLE Log Module
|
||||
|
||||
A high-performance, modular Bluetooth logging system that provides real-time log capture and transmission capabilities for the ESP-IDF Bluetooth stack.
|
||||
|
||||
## Table of Contents
|
||||
|
||||
- [Overview](#overview)
|
||||
- [Architecture Design](#architecture-design)
|
||||
- [Features](#features)
|
||||
- [Quick Start](#quick-start)
|
||||
- [Configuration Options](#configuration-options)
|
||||
- [API Reference](#api-reference)
|
||||
- [Usage Examples](#usage-examples)
|
||||
- [Performance & Memory Optimization](#performance--memory-optimization)
|
||||
- [Troubleshooting](#troubleshooting)
|
||||
- [Important Notes](#important-notes)
|
||||
|
||||
## Overview
|
||||
|
||||
The BLE Log module is an efficient logging system specifically designed for the ESP-IDF Bluetooth stack, supporting real-time log capture, multi-source log collection, and various transmission methods. This module has been refactored with a modular design, featuring high-concurrency processing capabilities and low-latency characteristics.
|
||||
|
||||
### Main Components
|
||||
|
||||
- **BLE Log Core** (`ble_log.c`): Module core responsible for initialization and coordination of sub-modules
|
||||
- **Runtime Manager** (`ble_log_rt.c`): Runtime task management for log transmission scheduling
|
||||
- **Log Buffer Manager** (`ble_log_lbm.c`): Log buffer management supporting multiple locking mechanisms
|
||||
- **Peripheral Interface** (`ble_log_prph_*.c`): Peripheral interface abstraction layer supporting various transmission methods
|
||||
- **Timestamp Sync** (`ble_log_ts.c`): Timestamp synchronization module
|
||||
- **Utility** (`ble_log_util.c`): Common utility functions
|
||||
|
||||
## Features
|
||||
|
||||
### Core Functionality
|
||||
|
||||
- **Multi-source Log Collection**: Supports multiple log sources including Link Layer, Host, HCI, etc.
|
||||
- **High Concurrency Processing**: Uses atomic and spin lock mechanisms for multi-task concurrent writing
|
||||
- **Real-time Transmission**: Asynchronous transmission mechanism based on FreeRTOS tasks
|
||||
- **Data Integrity**: Configurable checksum mechanism ensures data integrity
|
||||
- **Memory Optimization**: Ping-pong buffer design minimizes memory usage
|
||||
|
||||
### Advanced Features
|
||||
|
||||
- **Timestamp Synchronization**: Supports timestamp synchronization with external devices (optional)
|
||||
- **Enhanced Statistics**: Detailed logging statistics including loss rate analysis (optional)
|
||||
- **Link Layer Integration**: Deep integration with ESP-IDF Bluetooth Link Layer
|
||||
- **Multiple Transmission Methods**: Supports SPI DMA, UART DMA, and Dummy transmission
|
||||
|
||||
### Performance Features
|
||||
|
||||
- **IRAM Optimization**: Critical path code runs in IRAM ensuring low latency
|
||||
- **Lock-free Design**: Most operations use atomic operations reducing lock contention
|
||||
- **Buffer Reuse**: Intelligent buffer management reduces memory allocation overhead
|
||||
|
||||
## Quick Start
|
||||
|
||||
### 1. Enable Module
|
||||
|
||||
Enable the BLE Log module in `menuconfig`:
|
||||
|
||||
```
|
||||
Component config → Bluetooth → Enable BLE Log Module (Experimental)
|
||||
```
|
||||
|
||||
### 2. Basic Configuration
|
||||
|
||||
```c
|
||||
#include "ble_log.h"
|
||||
|
||||
void app_main() {
|
||||
// Initialize BLE Log module
|
||||
if (!ble_log_init()) {
|
||||
ESP_LOGE(TAG, "Failed to initialize BLE Log");
|
||||
return;
|
||||
}
|
||||
|
||||
// Write log data
|
||||
uint8_t data[] = {0x01, 0x02, 0x03, 0x04};
|
||||
ble_log_write_hex(BLE_LOG_SRC_CUSTOM, data, sizeof(data));
|
||||
|
||||
// Force flush buffers
|
||||
ble_log_flush();
|
||||
|
||||
// Cleanup resources
|
||||
ble_log_deinit();
|
||||
}
|
||||
```
|
||||
|
||||
### 3. Link Layer Integration
|
||||
|
||||
When `CONFIG_BLE_LOG_LL_ENABLED` is enabled, Link Layer logs are automatically integrated:
|
||||
|
||||
```c
|
||||
// Link Layer logs will automatically call this function
|
||||
void ble_log_write_hex_ll(uint32_t len, const uint8_t *addr,
|
||||
uint32_t len_append, const uint8_t *addr_append,
|
||||
uint32_t flag);
|
||||
```
|
||||
|
||||
## Configuration Options
|
||||
|
||||
### Basic Configuration
|
||||
|
||||
| Configuration | Default | Description |
|
||||
|---------------|---------|-------------|
|
||||
| `CONFIG_BLE_LOG_ENABLED` | n | Enable BLE Log module |
|
||||
| `CONFIG_BLE_LOG_LBM_TRANS_SIZE` | 512 | Size of each transport buffer |
|
||||
| `CONFIG_BLE_LOG_LBM_ATOMIC_LOCK_TASK_CNT` | 2 | Number of atomic lock LBMs for task context |
|
||||
| `CONFIG_BLE_LOG_LBM_ATOMIC_LOCK_ISR_CNT` | 1 | Number of atomic lock LBMs for ISR context |
|
||||
|
||||
### Link Layer Configuration
|
||||
|
||||
| Configuration | Default | Description |
|
||||
|---------------|---------|-------------|
|
||||
| `CONFIG_BLE_LOG_LL_ENABLED` | y | Enable Link Layer logging |
|
||||
| `CONFIG_BLE_LOG_LBM_LL_TRANS_SIZE` | 1024 | Link Layer transport buffer size |
|
||||
|
||||
### Advanced Features
|
||||
|
||||
| Configuration | Default | Description |
|
||||
|---------------|---------|-------------|
|
||||
| `CONFIG_BLE_LOG_PAYLOAD_CHECKSUM_ENABLED` | y | Enable payload checksum |
|
||||
| `CONFIG_BLE_LOG_ENH_STAT_ENABLED` | n | Enable enhanced statistics |
|
||||
| `CONFIG_BLE_LOG_TS_ENABLED` | n | Enable timestamp synchronization |
|
||||
|
||||
### Transport Method Configuration
|
||||
|
||||
| Transport | Configuration | Description |
|
||||
|-----------|---------------|-------------|
|
||||
| Dummy | `CONFIG_BLE_LOG_PRPH_DUMMY` | Debug dummy transport |
|
||||
| SPI Master DMA | `CONFIG_BLE_LOG_PRPH_SPI_MASTER_DMA` | SPI DMA transport |
|
||||
| UART DMA | `CONFIG_BLE_LOG_PRPH_UART_DMA` | UART DMA transport |
|
||||
|
||||
## API Reference
|
||||
|
||||
### Core API
|
||||
|
||||
#### `bool ble_log_init(void)`
|
||||
|
||||
Initialize the BLE Log module.
|
||||
|
||||
**Return Value**:
|
||||
- `true`: Initialization successful
|
||||
- `false`: Initialization failed
|
||||
|
||||
**Note**: Must be called before using any other APIs.
|
||||
|
||||
#### `void ble_log_deinit(void)`
|
||||
|
||||
Cleanup the BLE Log module and release all resources.
|
||||
|
||||
**Note**:
|
||||
- All pending logs will be lost after calling this function
|
||||
- Peripheral interface will be cleaned up first to avoid DMA transmission issues during memory release
|
||||
|
||||
#### `bool ble_log_write_hex(ble_log_src_t src_code, const uint8_t *addr, size_t len)`
|
||||
|
||||
Write hexadecimal log data.
|
||||
|
||||
**Parameters**:
|
||||
- `src_code`: Log source code
|
||||
- `addr`: Data pointer
|
||||
- `len`: Data length
|
||||
|
||||
**Return Value**:
|
||||
- `true`: Write successful
|
||||
- `false`: Write failed (module not initialized or insufficient buffer)
|
||||
|
||||
#### `void ble_log_flush(void)`
|
||||
|
||||
Force flush all buffers and send pending logs immediately.
|
||||
|
||||
**Note**: This operation is blocking and will pause module operation until all buffers are cleared.
|
||||
|
||||
#### `void ble_log_dump_to_console(void)`
|
||||
|
||||
Output all buffer contents to console in hexadecimal format for debugging.
|
||||
|
||||
### Log Source Types
|
||||
|
||||
```c
|
||||
typedef enum {
|
||||
BLE_LOG_SRC_INTERNAL = 0, // Internal system logs
|
||||
BLE_LOG_SRC_CUSTOM, // User-defined logs
|
||||
BLE_LOG_SRC_LL_TASK, // Link Layer task logs
|
||||
BLE_LOG_SRC_LL_HCI, // Link Layer HCI logs
|
||||
BLE_LOG_SRC_LL_ISR, // Link Layer interrupt logs
|
||||
BLE_LOG_SRC_HOST, // Host layer logs
|
||||
BLE_LOG_SRC_HCI, // HCI layer logs
|
||||
BLE_LOG_SRC_ENCODE, // Encoding layer logs
|
||||
BLE_LOG_SRC_MAX,
|
||||
} ble_log_src_t;
|
||||
```
|
||||
|
||||
### Link Layer API (Conditional Compilation)
|
||||
|
||||
#### `void ble_log_write_hex_ll(uint32_t len, const uint8_t *addr, uint32_t len_append, const uint8_t *addr_append, uint32_t flag)`
|
||||
|
||||
Link Layer dedicated log writing interface.
|
||||
|
||||
**Parameters**:
|
||||
- `len`: Main data length
|
||||
- `addr`: Main data pointer
|
||||
- `len_append`: Append data length
|
||||
- `addr_append`: Append data pointer
|
||||
- `flag`: Log flag bits
|
||||
|
||||
**Flag Definitions**:
|
||||
```c
|
||||
enum {
|
||||
BLE_LOG_LL_FLAG_CONTINUE = 0,
|
||||
BLE_LOG_LL_FLAG_END,
|
||||
BLE_LOG_LL_FLAG_TASK,
|
||||
BLE_LOG_LL_FLAG_ISR,
|
||||
BLE_LOG_LL_FLAG_HCI,
|
||||
BLE_LOG_LL_FLAG_RAW,
|
||||
BLE_LOG_LL_FLAG_HCI_UPSTREAM,
|
||||
};
|
||||
```
|
||||
|
||||
### Timestamp Synchronization API (Conditional Compilation)
|
||||
|
||||
#### `bool ble_log_sync_enable(bool enable)`
|
||||
|
||||
Enable or disable timestamp synchronization functionality.
|
||||
|
||||
**Parameters**:
|
||||
- `enable`: true to enable, false to disable
|
||||
|
||||
**Return Value**:
|
||||
- `true`: Operation successful
|
||||
- `false`: Operation failed (module not initialized)
|
||||
|
||||
## Usage Examples
|
||||
|
||||
### Example 1: Basic Logging
|
||||
|
||||
```c
|
||||
#include "ble_log.h"
|
||||
|
||||
void example_basic_logging() {
|
||||
// Initialize
|
||||
if (!ble_log_init()) {
|
||||
printf("BLE Log init failed\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// Log some example data
|
||||
uint8_t hci_cmd[] = {0x01, 0x03, 0x0C, 0x00}; // HCI Reset Command
|
||||
ble_log_write_hex(BLE_LOG_SRC_HCI, hci_cmd, sizeof(hci_cmd));
|
||||
|
||||
uint8_t host_data[] = {0x02, 0x00, 0x20, 0x0B, 0x00, 0x07, 0x00, 0x04, 0x00, 0x10, 0x01, 0x00, 0xFF, 0xFF, 0x00, 0x28};
|
||||
ble_log_write_hex(BLE_LOG_SRC_HOST, host_data, sizeof(host_data));
|
||||
|
||||
// Force send
|
||||
ble_log_flush();
|
||||
|
||||
// Cleanup
|
||||
ble_log_deinit();
|
||||
}
|
||||
```
|
||||
|
||||
### Example 2: ISR Context Logging
|
||||
|
||||
```c
|
||||
void IRAM_ATTR some_isr_handler() {
|
||||
uint8_t isr_data[] = {0xDE, 0xAD, 0xBE, 0xEF};
|
||||
|
||||
// Safe to write logs in ISR context
|
||||
ble_log_write_hex(BLE_LOG_SRC_LL_ISR, isr_data, sizeof(isr_data));
|
||||
}
|
||||
```
|
||||
|
||||
### Example 3: Logging with Timestamp Synchronization
|
||||
|
||||
```c
|
||||
void example_with_timestamp_sync() {
|
||||
if (!ble_log_init()) {
|
||||
return;
|
||||
}
|
||||
|
||||
#if CONFIG_BLE_LOG_TS_ENABLED
|
||||
// Enable timestamp synchronization
|
||||
ble_log_sync_enable(true);
|
||||
#endif
|
||||
|
||||
// Log data...
|
||||
uint8_t data[] = {0x01, 0x02, 0x03};
|
||||
ble_log_write_hex(BLE_LOG_SRC_CUSTOM, data, sizeof(data));
|
||||
|
||||
// Timestamp information will be automatically included in logs
|
||||
|
||||
ble_log_deinit();
|
||||
}
|
||||
```
|
||||
|
||||
### Example 4: Performance Testing
|
||||
|
||||
```c
|
||||
void example_performance_test() {
|
||||
if (!ble_log_init()) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t test_data[100];
|
||||
for (int i = 0; i < 100; i++) {
|
||||
test_data[i] = i;
|
||||
}
|
||||
|
||||
uint32_t start_time = esp_timer_get_time();
|
||||
|
||||
// Send 1000 logs
|
||||
for (int i = 0; i < 1000; i++) {
|
||||
ble_log_write_hex(BLE_LOG_SRC_CUSTOM, test_data, sizeof(test_data));
|
||||
}
|
||||
|
||||
ble_log_flush();
|
||||
uint32_t end_time = esp_timer_get_time();
|
||||
|
||||
printf("Time to write 1000 logs: %lu us\n", end_time - start_time);
|
||||
|
||||
ble_log_deinit();
|
||||
}
|
||||
```
|
||||
|
||||
## Performance & Memory Optimization
|
||||
|
||||
### Memory Usage Estimation
|
||||
|
||||
Memory usage under default configuration:
|
||||
|
||||
```
|
||||
Total Buffers = (Atomic Task LBMs + Atomic ISR LBMs + Spin LBMs) × 2 × Transport Buffer Size
|
||||
Default Config = (2 + 1 + 2) × 2 × 512 = 5120 bytes
|
||||
|
||||
Additional when Link Layer enabled:
|
||||
LL Buffers = 2 × 2 × 1024 = 4096 bytes
|
||||
|
||||
Additional when Enhanced Statistics enabled:
|
||||
Statistics Data = Log Source Count × sizeof(ble_log_stat_mgr_t) = 8 × 40 = 320 bytes
|
||||
```
|
||||
|
||||
### Performance Optimization Recommendations
|
||||
|
||||
1. **Adjust LBM Count**: Adjust atomic lock LBM count based on concurrency requirements
|
||||
2. **Buffer Size**: Adjust transport buffer size based on log volume
|
||||
3. **Transport Method**: Choose optimal transport method based on hardware (SPI DMA typically has best performance)
|
||||
4. **Checksum**: Consider disabling payload checksum when performance requirements are extremely high
|
||||
|
||||
### Real-time Considerations
|
||||
|
||||
- Critical code paths are marked with `BLE_LOG_IRAM_ATTR` and run in IRAM
|
||||
- Atomic operations avoid lock contention
|
||||
- Ping-pong buffers ensure continuous writing
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Common Issues
|
||||
|
||||
#### 1. Initialization Failure
|
||||
|
||||
**Symptoms**: `ble_log_init()` returns `false`
|
||||
|
||||
**Possible Causes**:
|
||||
- Insufficient memory
|
||||
- Peripheral configuration error
|
||||
- Duplicate initialization
|
||||
|
||||
**Solutions**:
|
||||
```c
|
||||
// Check available memory
|
||||
printf("Free heap: %d bytes\n", esp_get_free_heap_size());
|
||||
|
||||
// Ensure initialization only happens once
|
||||
static bool initialized = false;
|
||||
if (!initialized) {
|
||||
initialized = ble_log_init();
|
||||
}
|
||||
```
|
||||
|
||||
#### 2. Log Loss
|
||||
|
||||
**Symptoms**: Some logs don't appear in output
|
||||
|
||||
**Possible Causes**:
|
||||
- Buffer overflow
|
||||
- Transmission speed can't keep up with write speed
|
||||
- Module not properly initialized
|
||||
|
||||
**Solutions**:
|
||||
```c
|
||||
// Enable enhanced statistics to check loss rate
|
||||
#if CONFIG_BLE_LOG_ENH_STAT_ENABLED
|
||||
// Statistics will be automatically included in logs
|
||||
#endif
|
||||
|
||||
// Adjust buffer size
|
||||
// CONFIG_BLE_LOG_LBM_TRANS_SIZE=1024
|
||||
|
||||
// Increase atomic lock LBM count
|
||||
// CONFIG_BLE_LOG_LBM_ATOMIC_LOCK_TASK_CNT=4
|
||||
```
|
||||
|
||||
#### 3. Performance Issues
|
||||
|
||||
**Symptoms**: System response becomes slow
|
||||
|
||||
**Possible Causes**:
|
||||
- Checksum calculation overhead
|
||||
- Transmission bottleneck
|
||||
- Lock contention
|
||||
|
||||
**Solutions**:
|
||||
```c
|
||||
// Disable payload checksum
|
||||
// CONFIG_BLE_LOG_PAYLOAD_CHECKSUM_ENABLED=n
|
||||
|
||||
// Use faster transmission method
|
||||
// CONFIG_BLE_LOG_PRPH_SPI_MASTER_DMA=y
|
||||
|
||||
// Adjust task priority
|
||||
#define BLE_LOG_TASK_PRIO configMAX_PRIORITIES-3
|
||||
```
|
||||
|
||||
### Debugging Techniques
|
||||
|
||||
#### 1. Use Dummy Transport for Debugging
|
||||
|
||||
```c
|
||||
// Select Dummy transport in menuconfig
|
||||
// Then use dump function to view buffer contents
|
||||
ble_log_dump_to_console();
|
||||
```
|
||||
|
||||
#### 2. Enable Enhanced Statistics
|
||||
|
||||
```c
|
||||
// Enable in menuconfig
|
||||
// CONFIG_BLE_LOG_ENH_STAT_ENABLED=y
|
||||
// Statistics will be automatically output to logs
|
||||
```
|
||||
|
||||
#### 3. Monitor Memory Usage
|
||||
|
||||
```c
|
||||
void monitor_memory() {
|
||||
printf("Free heap before init: %d\n", esp_get_free_heap_size());
|
||||
ble_log_init();
|
||||
printf("Free heap after init: %d\n", esp_get_free_heap_size());
|
||||
}
|
||||
```
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,780 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include "ble_log/ble_log_uhci_out.h"
|
||||
|
||||
|
||||
#if CONFIG_BT_BLE_LOG_UHCI_OUT_ENABLED
|
||||
|
||||
// Private includes
|
||||
#include "esp_bt.h"
|
||||
|
||||
// sdkconfig defines
|
||||
#define UHCI_OUT_LL_TASK_BUF_SIZE CONFIG_BT_BLE_LOG_UHCI_OUT_LL_TASK_BUF_SIZE
|
||||
#define UHCI_OUT_LL_ISR_BUF_SIZE CONFIG_BT_BLE_LOG_UHCI_OUT_LL_ISR_BUF_SIZE
|
||||
#define UHCI_OUT_LL_HCI_BUF_SIZE CONFIG_BT_BLE_LOG_UHCI_OUT_LL_HCI_BUF_SIZE
|
||||
#define UHCI_OUT_UART_PORT CONFIG_BT_BLE_LOG_UHCI_OUT_UART_PORT
|
||||
#define UHCI_OUT_UART_NEED_INIT CONFIG_BT_BLE_LOG_UHCI_OUT_UART_NEED_INIT
|
||||
|
||||
#if UHCI_OUT_UART_NEED_INIT
|
||||
#define UHCI_OUT_UART_BAUD_RATE CONFIG_BT_BLE_LOG_UHCI_OUT_UART_BAUD_RATE
|
||||
#define UHCI_OUT_UART_IO_NUM_TX CONFIG_BT_BLE_LOG_UHCI_OUT_UART_IO_NUM_TX
|
||||
#endif // UHCI_OUT_UART_NEED_INIT
|
||||
|
||||
// Private defines
|
||||
#define UHCI_OUT_MAX_TRANSFER_SIZE (10240)
|
||||
#define UHCI_OUT_MALLOC(size) heap_caps_malloc(size, MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT)
|
||||
#define UHCI_OUT_FLUSH_TIMEOUT_MS (100)
|
||||
#define UHCI_OUT_FLUSH_TIMEOUT_US (UHCI_OUT_FLUSH_TIMEOUT_MS * 1000)
|
||||
#define UHCI_OUT_USER_BUF_SIZE (512)
|
||||
#define UHCI_OUT_UART_PORT0 (0)
|
||||
#define UHCI_OUT_UART_PORT1 (1)
|
||||
#define UHCI_OUT_UART_DRIVER_RX_BUF_SIZE (32)
|
||||
|
||||
// Queue size defines
|
||||
#define UHCI_OUT_PING_PONG_BUF_CNT (2)
|
||||
#define UHCI_OUT_USER_QUEUE_SIZE (UHCI_OUT_PING_PONG_BUF_CNT)
|
||||
#define UHCI_OUT_LL_QUEUE_SIZE (3 * UHCI_OUT_PING_PONG_BUF_CNT)
|
||||
#define UHCI_OUT_QUEUE_SIZE (UHCI_OUT_USER_QUEUE_SIZE + UHCI_OUT_LL_QUEUE_SIZE)
|
||||
|
||||
// Private typedefs
|
||||
typedef struct {
|
||||
// This flag is for multithreading, must be a word, do not modify
|
||||
volatile uint32_t flag;
|
||||
uint16_t buf_size;
|
||||
uint16_t length;
|
||||
uint8_t buffer[0];
|
||||
} uhci_out_trans_cb_t;
|
||||
|
||||
typedef struct {
|
||||
uhci_out_trans_cb_t *trans_cb[2];
|
||||
uint8_t trans_cb_idx;
|
||||
uint8_t type;
|
||||
uint16_t lost_frame_cnt;
|
||||
uint32_t lost_bytes_cnt;
|
||||
uint32_t frame_sn;
|
||||
} uhci_out_log_cb_t;
|
||||
|
||||
typedef struct {
|
||||
uint16_t length;
|
||||
uint8_t source;
|
||||
uint8_t type;
|
||||
uint16_t frame_sn;
|
||||
} __attribute__((packed)) frame_head_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t type;
|
||||
uint16_t lost_frame_cnt;
|
||||
uint32_t lost_bytes_cnt;
|
||||
} __attribute__((packed)) loss_payload_t;
|
||||
|
||||
// Private enums
|
||||
enum {
|
||||
TRANS_CB_FLAG_AVAILABLE = 0,
|
||||
TRANS_CB_FLAG_NEED_QUEUE,
|
||||
TRANS_CB_FLAG_IN_QUEUE,
|
||||
};
|
||||
|
||||
enum {
|
||||
LOG_CB_TYPE_USER = 0,
|
||||
LOG_CB_TYPE_LL,
|
||||
};
|
||||
|
||||
enum {
|
||||
LOG_CB_LL_SUBTYPE_TASK = 0,
|
||||
LOG_CB_LL_SUBTYPE_ISR,
|
||||
LOG_CB_LL_SUBTYPE_HCI
|
||||
};
|
||||
|
||||
enum {
|
||||
LL_LOG_FLAG_CONTINUE = 0,
|
||||
LL_LOG_FLAG_END,
|
||||
LL_LOG_FLAG_TASK,
|
||||
LL_LOG_FLAG_ISR,
|
||||
LL_LOG_FLAG_HCI,
|
||||
LL_LOG_FLAG_RAW,
|
||||
LL_LOG_FLAG_SYNC
|
||||
};
|
||||
|
||||
enum {
|
||||
LL_EV_FLAG_ISR_APPEND = 0,
|
||||
LL_EV_FLAG_FLUSH_LOG,
|
||||
};
|
||||
|
||||
// Private variables
|
||||
static bool uhci_out_inited = false;
|
||||
static uhci_controller_handle_t uhci_handle = NULL;
|
||||
|
||||
static bool user_log_inited = false;
|
||||
static SemaphoreHandle_t user_log_mutex = NULL;
|
||||
static uhci_out_log_cb_t *user_log_cb = NULL;
|
||||
static uint32_t user_last_write_ts = 0;
|
||||
|
||||
static bool ll_log_inited = false;
|
||||
static uhci_out_log_cb_t *ll_task_log_cb = NULL;
|
||||
static uhci_out_log_cb_t *ll_isr_log_cb = NULL;
|
||||
static uhci_out_log_cb_t *ll_hci_log_cb = NULL;
|
||||
static uint32_t ll_ev_flags = 0;
|
||||
static uint32_t ll_last_write_ts = 0;
|
||||
|
||||
static esp_timer_handle_t flush_timer = NULL;
|
||||
|
||||
// Private function declarations
|
||||
extern void esp_panic_handler_feed_wdts(void);
|
||||
|
||||
static int uhci_out_init_trans(uhci_out_trans_cb_t **trans_cb, uint16_t buf_size);
|
||||
static void uhci_out_deinit_trans(uhci_out_trans_cb_t **trans_cb);
|
||||
static bool uhci_out_tx_done_cb(uhci_controller_handle_t uhci_ctrl,
|
||||
const uhci_tx_done_event_data_t *edata, void *user_ctx);
|
||||
static inline void uhci_out_append_trans(uhci_out_trans_cb_t *trans_cb);
|
||||
|
||||
static int uhci_out_log_cb_init(uhci_out_log_cb_t **log_cb, uint16_t buf_size, uint8_t type, uint8_t idx);
|
||||
static void uhci_out_log_cb_deinit(uhci_out_log_cb_t **log_cb);
|
||||
static inline bool uhci_out_log_cb_check_trans(uhci_out_log_cb_t *log_cb, uint16_t len, bool *need_append);
|
||||
static inline void uhci_out_log_cb_append_trans(uhci_out_log_cb_t *log_cb);
|
||||
static inline void uhci_out_log_cb_flush_trans(uhci_out_log_cb_t *log_cb);
|
||||
static bool uhci_out_log_cb_write(uhci_out_log_cb_t *log_cb, const uint8_t *addr, uint16_t len,
|
||||
const uint8_t *addr_append, uint16_t len_append, uint8_t source);
|
||||
static void uhci_out_log_cb_write_loss(uhci_out_log_cb_t *log_cb);
|
||||
static void uhci_out_log_cb_dump(uhci_out_log_cb_t *log_cb);
|
||||
|
||||
static void esp_timer_cb_log_flush(void);
|
||||
static void uhci_out_user_write_str(const uint8_t *src, uint16_t len);
|
||||
|
||||
#if UHCI_OUT_UART_PORT == UHCI_OUT_UART_PORT0
|
||||
static void uhci_out_user_write_char(char c);
|
||||
#endif // UHCI_OUT_UART_PORT == UHCI_OUT_UART_PORT0
|
||||
|
||||
static int uhci_out_user_log_init(void);
|
||||
static void uhci_out_user_log_deinit(void);
|
||||
|
||||
static int uhci_out_ll_log_init(void);
|
||||
static void uhci_out_ll_log_deinit(void);
|
||||
static void uhci_out_ll_log_flush(void);
|
||||
|
||||
#if defined(CONFIG_IDF_TARGET_ESP32H2) || defined(CONFIG_IDF_TARGET_ESP32C6) || defined(CONFIG_IDF_TARGET_ESP32C5) ||\
|
||||
defined(CONFIG_IDF_TARGET_ESP32C61) || defined(CONFIG_IDF_TARGET_ESP32H21)
|
||||
extern void r_ble_log_simple_put_ev(void);
|
||||
#define UHCI_OUT_LL_PUT_EV r_ble_log_simple_put_ev()
|
||||
#elif defined(CONFIG_IDF_TARGET_ESP32C2)
|
||||
extern void ble_log_simple_put_ev(void);
|
||||
#define UHCI_OUT_LL_PUT_EV ble_log_simple_put_ev()
|
||||
#else
|
||||
#define UHCI_OUT_LL_PUT_EV
|
||||
#endif
|
||||
|
||||
// Private macros
|
||||
#define UHCI_OUT_FRAME_HEAD_LEN (sizeof(frame_head_t))
|
||||
#define UHCI_OUT_FRAME_TAIL_LEN (sizeof(uint32_t))
|
||||
#define UHCI_OUT_FRAME_OVERHEAD (UHCI_OUT_FRAME_HEAD_LEN + UHCI_OUT_FRAME_TAIL_LEN)
|
||||
#define UHCI_OUT_GET_FRAME_SN(VAR) __atomic_fetch_add(VAR, 1, __ATOMIC_RELAXED)
|
||||
|
||||
// Private functions
|
||||
static int uhci_out_init_trans(uhci_out_trans_cb_t **trans_cb, uint16_t buf_size)
|
||||
{
|
||||
// Memory allocations
|
||||
size_t cb_size = sizeof(uhci_out_trans_cb_t) + buf_size;
|
||||
*trans_cb = (uhci_out_trans_cb_t *)UHCI_OUT_MALLOC(cb_size);
|
||||
if (!(*trans_cb)) {
|
||||
return -1;
|
||||
}
|
||||
memset(*trans_cb, 0, sizeof(uhci_out_trans_cb_t));
|
||||
|
||||
// Initialization
|
||||
(*trans_cb)->buf_size = buf_size;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void uhci_out_deinit_trans(uhci_out_trans_cb_t **trans_cb)
|
||||
{
|
||||
if (!(*trans_cb)) {
|
||||
return;
|
||||
}
|
||||
|
||||
free(*trans_cb);
|
||||
*trans_cb = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
IRAM_ATTR static bool uhci_out_tx_done_cb(uhci_controller_handle_t uhci_ctrl,
|
||||
const uhci_tx_done_event_data_t *edata, void *user_ctx)
|
||||
{
|
||||
uhci_out_trans_cb_t *trans_cb = (uhci_out_trans_cb_t *)((uint8_t *)edata->buffer - sizeof(uhci_out_trans_cb_t));
|
||||
trans_cb->length = 0;
|
||||
trans_cb->flag = TRANS_CB_FLAG_AVAILABLE;
|
||||
return true;
|
||||
}
|
||||
|
||||
IRAM_ATTR static inline void uhci_out_append_trans(uhci_out_trans_cb_t *trans_cb)
|
||||
{
|
||||
if ((trans_cb->flag != TRANS_CB_FLAG_NEED_QUEUE) || !trans_cb->length) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Note: If task yield after transmission but before flag set
|
||||
// flag might be reset in tx done ISR before flag set, leading to buffer access failure
|
||||
trans_cb->flag = TRANS_CB_FLAG_IN_QUEUE;
|
||||
if (uhci_transmit(uhci_handle, trans_cb->buffer, trans_cb->length) != ESP_OK) {
|
||||
goto recycle;
|
||||
}
|
||||
return;
|
||||
|
||||
recycle:
|
||||
trans_cb->length = 0;
|
||||
trans_cb->flag = TRANS_CB_FLAG_AVAILABLE;
|
||||
return;
|
||||
}
|
||||
|
||||
static int uhci_out_log_cb_init(uhci_out_log_cb_t **log_cb, uint16_t buf_size, uint8_t type, uint8_t idx)
|
||||
{
|
||||
// Initialize log control block
|
||||
*log_cb = (uhci_out_log_cb_t *)UHCI_OUT_MALLOC(sizeof(uhci_out_log_cb_t));
|
||||
if (!(*log_cb)) {
|
||||
return -1;
|
||||
}
|
||||
memset(*log_cb, 0, sizeof(uhci_out_log_cb_t));
|
||||
|
||||
// Initialize transactions
|
||||
int ret = 0;
|
||||
for (uint8_t i = 0; i < 2; i++) {
|
||||
ret |= uhci_out_init_trans(&((*log_cb)->trans_cb[i]), buf_size);
|
||||
}
|
||||
if (ret != 0) {
|
||||
uhci_out_log_cb_deinit(log_cb);
|
||||
return -1;
|
||||
}
|
||||
|
||||
(*log_cb)->type = (type << 4) | (idx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void uhci_out_log_cb_deinit(uhci_out_log_cb_t **log_cb)
|
||||
{
|
||||
if (!(*log_cb)) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (uint8_t i = 0; i < 2; i++) {
|
||||
if ((*log_cb)->trans_cb[i]) {
|
||||
uhci_out_deinit_trans(&((*log_cb)->trans_cb[i]));
|
||||
}
|
||||
}
|
||||
free(*log_cb);
|
||||
*log_cb = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
IRAM_ATTR static inline bool uhci_out_log_cb_check_trans(uhci_out_log_cb_t *log_cb, uint16_t len, bool *need_append)
|
||||
{
|
||||
uhci_out_trans_cb_t *trans_cb;
|
||||
*need_append = false;
|
||||
for (uint8_t i = 0; i < 2; i++) {
|
||||
trans_cb = log_cb->trans_cb[log_cb->trans_cb_idx];
|
||||
if (len > trans_cb->buf_size) {
|
||||
goto failed;
|
||||
}
|
||||
if (trans_cb->flag == TRANS_CB_FLAG_AVAILABLE) {
|
||||
if ((trans_cb->buf_size - trans_cb->length) >= len) {
|
||||
return true;
|
||||
} else {
|
||||
trans_cb->flag = TRANS_CB_FLAG_NEED_QUEUE;
|
||||
*need_append = true;
|
||||
}
|
||||
}
|
||||
log_cb->trans_cb_idx = !(log_cb->trans_cb_idx);
|
||||
}
|
||||
failed:
|
||||
log_cb->lost_bytes_cnt += len;
|
||||
log_cb->lost_frame_cnt++;
|
||||
return false;
|
||||
}
|
||||
|
||||
// CRITICAL: Shall not be called from ISR!
|
||||
IRAM_ATTR static inline void uhci_out_log_cb_append_trans(uhci_out_log_cb_t *log_cb)
|
||||
{
|
||||
uhci_out_trans_cb_t *trans_cb;
|
||||
uint8_t idx = !log_cb->trans_cb_idx;
|
||||
for (uint8_t i = 0; i < 2; i++) {
|
||||
trans_cb = log_cb->trans_cb[idx];
|
||||
if (trans_cb->flag == TRANS_CB_FLAG_NEED_QUEUE) {
|
||||
uhci_out_append_trans(trans_cb);
|
||||
}
|
||||
idx = !idx;
|
||||
}
|
||||
}
|
||||
|
||||
IRAM_ATTR static inline void uhci_out_log_cb_flush_trans(uhci_out_log_cb_t *log_cb)
|
||||
{
|
||||
uhci_out_trans_cb_t *trans_cb;
|
||||
for (uint8_t i = 0; i < 2; i++) {
|
||||
trans_cb = log_cb->trans_cb[i];
|
||||
if (trans_cb->length && (trans_cb->flag == TRANS_CB_FLAG_AVAILABLE)) {
|
||||
trans_cb->flag = TRANS_CB_FLAG_NEED_QUEUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Return value: Need append
|
||||
IRAM_ATTR static bool uhci_out_log_cb_write(uhci_out_log_cb_t *log_cb, const uint8_t *addr, uint16_t len,
|
||||
const uint8_t *addr_append, uint16_t len_append, uint8_t source)
|
||||
{
|
||||
uhci_out_trans_cb_t *trans_cb = log_cb->trans_cb[log_cb->trans_cb_idx];
|
||||
|
||||
uint8_t *buf = trans_cb->buffer + trans_cb->length;
|
||||
uint16_t total_length = len + len_append;
|
||||
frame_head_t head = {
|
||||
.length = total_length,
|
||||
.source = source,
|
||||
.type = log_cb->type,
|
||||
.frame_sn = UHCI_OUT_GET_FRAME_SN(&(log_cb->frame_sn)) & 0xFFFF,
|
||||
};
|
||||
|
||||
memcpy(buf, (const uint8_t *)&head, UHCI_OUT_FRAME_HEAD_LEN);
|
||||
memcpy(buf + UHCI_OUT_FRAME_HEAD_LEN, addr, len);
|
||||
if (len_append && addr_append) {
|
||||
memcpy(buf + UHCI_OUT_FRAME_HEAD_LEN + len, addr_append, len_append);
|
||||
}
|
||||
|
||||
uint32_t checksum = 0;
|
||||
for (int i = 0; i < UHCI_OUT_FRAME_HEAD_LEN + total_length; i++) {
|
||||
checksum += buf[i];
|
||||
}
|
||||
memcpy(buf + UHCI_OUT_FRAME_HEAD_LEN + total_length, &checksum, UHCI_OUT_FRAME_TAIL_LEN);
|
||||
|
||||
trans_cb->length += total_length + UHCI_OUT_FRAME_OVERHEAD;
|
||||
if ((trans_cb->buf_size - trans_cb->length) <= UHCI_OUT_FRAME_OVERHEAD) {
|
||||
trans_cb->flag = TRANS_CB_FLAG_NEED_QUEUE;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
IRAM_ATTR static void uhci_out_log_cb_write_loss(uhci_out_log_cb_t *log_cb)
|
||||
{
|
||||
if (!log_cb->lost_bytes_cnt || !log_cb->lost_frame_cnt) {
|
||||
return;
|
||||
}
|
||||
bool need_append;
|
||||
uint16_t frame_len = sizeof(loss_payload_t) + UHCI_OUT_FRAME_OVERHEAD;
|
||||
if (uhci_out_log_cb_check_trans(log_cb, frame_len, &need_append)) {
|
||||
loss_payload_t payload = {
|
||||
.type = log_cb->type,
|
||||
.lost_frame_cnt = log_cb->lost_frame_cnt,
|
||||
.lost_bytes_cnt = log_cb->lost_bytes_cnt,
|
||||
};
|
||||
uhci_out_log_cb_write(log_cb, (const uint8_t *)&payload, sizeof(loss_payload_t),
|
||||
NULL, 0, BLE_LOG_UHCI_OUT_SOURCE_LOSS);
|
||||
|
||||
log_cb->lost_frame_cnt = 0;
|
||||
log_cb->lost_bytes_cnt = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void uhci_out_log_cb_dump(uhci_out_log_cb_t *log_cb)
|
||||
{
|
||||
uhci_out_trans_cb_t *trans_cb;
|
||||
uint8_t *buf;
|
||||
for (uint8_t i = 0; i < 2; i++) {
|
||||
// Dump the last transaction before dumping the current transaction
|
||||
log_cb->trans_cb_idx = !(log_cb->trans_cb_idx);
|
||||
trans_cb = log_cb->trans_cb[log_cb->trans_cb_idx];
|
||||
buf = (uint8_t *)trans_cb->buffer;
|
||||
for (uint16_t j = 0; j < trans_cb->buf_size; j++) {
|
||||
esp_rom_printf("%02x ", buf[j]);
|
||||
|
||||
// Feed watchdogs periodically to avoid wdts timeout
|
||||
if ((j % 100) == 0) {
|
||||
esp_panic_handler_feed_wdts();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void esp_timer_cb_log_flush(void)
|
||||
{
|
||||
uint32_t os_ts = pdTICKS_TO_MS(xTaskGetTickCount());
|
||||
|
||||
if ((os_ts - user_last_write_ts) > UHCI_OUT_FLUSH_TIMEOUT_MS) {
|
||||
xSemaphoreTake(user_log_mutex, portMAX_DELAY);
|
||||
uhci_out_log_cb_flush_trans(user_log_cb);
|
||||
uhci_out_log_cb_append_trans(user_log_cb);
|
||||
xSemaphoreGive(user_log_mutex);
|
||||
}
|
||||
|
||||
if ((esp_bt_controller_get_status() >= ESP_BT_CONTROLLER_STATUS_INITED) &&
|
||||
((os_ts - ll_last_write_ts) > UHCI_OUT_FLUSH_TIMEOUT_MS)) {
|
||||
ll_ev_flags |= BIT(LL_EV_FLAG_FLUSH_LOG);
|
||||
UHCI_OUT_LL_PUT_EV;
|
||||
}
|
||||
|
||||
esp_timer_start_once(flush_timer, UHCI_OUT_FLUSH_TIMEOUT_US);
|
||||
}
|
||||
|
||||
static void uhci_out_user_write_str(const uint8_t *src, uint16_t len)
|
||||
{
|
||||
if (!user_log_inited || !src || !len) {
|
||||
return;
|
||||
}
|
||||
|
||||
xSemaphoreTake(user_log_mutex, portMAX_DELAY);
|
||||
|
||||
bool need_append;
|
||||
if (uhci_out_log_cb_check_trans(user_log_cb, len, &need_append)) {
|
||||
uhci_out_trans_cb_t *trans_cb = user_log_cb->trans_cb[user_log_cb->trans_cb_idx];
|
||||
uint8_t *buf = trans_cb->buffer + trans_cb->length;
|
||||
|
||||
memcpy(buf, (const uint8_t *)src, len);
|
||||
trans_cb->length += len;
|
||||
}
|
||||
|
||||
if (need_append) {
|
||||
uhci_out_log_cb_append_trans(user_log_cb);
|
||||
}
|
||||
|
||||
user_last_write_ts = pdTICKS_TO_MS(xTaskGetTickCount());
|
||||
|
||||
xSemaphoreGive(user_log_mutex);
|
||||
}
|
||||
|
||||
#if UHCI_OUT_UART_PORT == UHCI_OUT_UART_PORT0
|
||||
static void uhci_out_user_write_char(char c)
|
||||
{
|
||||
uhci_out_user_write_str((const uint8_t *)&c, 1);
|
||||
}
|
||||
#endif // UHCI_OUT_UART_PORT == UHCI_OUT_UART_PORT0
|
||||
|
||||
static int uhci_out_user_log_init(void)
|
||||
{
|
||||
if (user_log_inited) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Initialize mutex
|
||||
user_log_mutex = xSemaphoreCreateMutex();
|
||||
if (!user_log_mutex) {
|
||||
goto failed;
|
||||
}
|
||||
|
||||
// Initialize log control block
|
||||
if (uhci_out_log_cb_init(&user_log_cb, UHCI_OUT_USER_BUF_SIZE, LOG_CB_TYPE_USER, 0) != 0) {
|
||||
goto failed;
|
||||
}
|
||||
|
||||
// Initialization done
|
||||
user_log_inited = true;
|
||||
return 0;
|
||||
|
||||
failed:
|
||||
uhci_out_user_log_deinit();
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void uhci_out_user_log_deinit(void)
|
||||
{
|
||||
user_log_inited = false;
|
||||
|
||||
if (!user_log_mutex) {
|
||||
return;
|
||||
}
|
||||
xSemaphoreTake(user_log_mutex, portMAX_DELAY);
|
||||
|
||||
uhci_out_log_cb_deinit(&user_log_cb);
|
||||
|
||||
xSemaphoreGive(user_log_mutex);
|
||||
vSemaphoreDelete(user_log_mutex);
|
||||
user_log_mutex = NULL;
|
||||
}
|
||||
|
||||
static int uhci_out_ll_log_init(void)
|
||||
{
|
||||
if (ll_log_inited) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (uhci_out_log_cb_init(&ll_task_log_cb, UHCI_OUT_LL_TASK_BUF_SIZE,
|
||||
LOG_CB_TYPE_LL, LOG_CB_LL_SUBTYPE_TASK) != 0) {
|
||||
goto failed;
|
||||
}
|
||||
if (uhci_out_log_cb_init(&ll_isr_log_cb, UHCI_OUT_LL_ISR_BUF_SIZE,
|
||||
LOG_CB_TYPE_LL, LOG_CB_LL_SUBTYPE_ISR) != 0) {
|
||||
goto failed;
|
||||
}
|
||||
if (uhci_out_log_cb_init(&ll_hci_log_cb, UHCI_OUT_LL_HCI_BUF_SIZE,
|
||||
LOG_CB_TYPE_LL, LOG_CB_LL_SUBTYPE_HCI) != 0) {
|
||||
goto failed;
|
||||
}
|
||||
|
||||
ll_log_inited = true;
|
||||
return 0;
|
||||
|
||||
failed:
|
||||
uhci_out_ll_log_deinit();
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void uhci_out_ll_log_deinit(void)
|
||||
{
|
||||
ll_log_inited = false;
|
||||
|
||||
uhci_out_log_cb_deinit(&ll_hci_log_cb);
|
||||
uhci_out_log_cb_deinit(&ll_isr_log_cb);
|
||||
uhci_out_log_cb_deinit(&ll_task_log_cb);
|
||||
}
|
||||
|
||||
static void uhci_out_ll_log_flush(void)
|
||||
{
|
||||
if (!ll_log_inited) {
|
||||
return;
|
||||
}
|
||||
|
||||
uhci_out_log_cb_write_loss(ll_task_log_cb);
|
||||
uhci_out_log_cb_write_loss(ll_hci_log_cb);
|
||||
|
||||
uhci_out_log_cb_flush_trans(ll_task_log_cb);
|
||||
uhci_out_log_cb_flush_trans(ll_hci_log_cb);
|
||||
|
||||
portMUX_TYPE spinlock = portMUX_INITIALIZER_UNLOCKED;
|
||||
portENTER_CRITICAL_SAFE(&spinlock);
|
||||
uhci_out_log_cb_write_loss(ll_isr_log_cb);
|
||||
uhci_out_log_cb_flush_trans(ll_isr_log_cb);
|
||||
portEXIT_CRITICAL_SAFE(&spinlock);
|
||||
|
||||
uhci_out_log_cb_append_trans(ll_task_log_cb);
|
||||
uhci_out_log_cb_append_trans(ll_hci_log_cb);
|
||||
uhci_out_log_cb_append_trans(ll_isr_log_cb);
|
||||
}
|
||||
|
||||
// Public functions
|
||||
int ble_log_uhci_out_init(void)
|
||||
{
|
||||
// Avoid double init
|
||||
if (uhci_out_inited) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if UHCI_OUT_UART_NEED_INIT
|
||||
uart_config_t uart_config = {
|
||||
.baud_rate = UHCI_OUT_UART_BAUD_RATE,
|
||||
.data_bits = UART_DATA_8_BITS,
|
||||
.parity = UART_PARITY_DISABLE,
|
||||
.stop_bits = UART_STOP_BITS_1,
|
||||
.flow_ctrl = UART_HW_FLOWCTRL_CTS_RTS,
|
||||
.rx_flow_ctrl_thresh = 122,
|
||||
};
|
||||
// Configure UART parameters
|
||||
uart_param_config(UHCI_OUT_UART_PORT, &uart_config);
|
||||
uart_set_pin(UHCI_OUT_UART_PORT, UHCI_OUT_UART_IO_NUM_TX, -1, -1, -1);
|
||||
#endif // UHCI_OUT_UART_NEED_INIT
|
||||
|
||||
uhci_controller_config_t uhci_config = {
|
||||
.uart_port = UHCI_OUT_UART_PORT,
|
||||
.tx_trans_queue_depth = UHCI_OUT_QUEUE_SIZE,
|
||||
.max_receive_internal_mem = 1024,
|
||||
.max_transmit_size = UHCI_OUT_MAX_TRANSFER_SIZE,
|
||||
.dma_burst_size = 32,
|
||||
.rx_eof_flags.idle_eof = 1,
|
||||
};
|
||||
if (uhci_new_controller(&uhci_config, &uhci_handle) != ESP_OK) {
|
||||
goto failed;
|
||||
}
|
||||
|
||||
uhci_event_callbacks_t uhci_cbs = {
|
||||
.on_tx_trans_done = uhci_out_tx_done_cb,
|
||||
};
|
||||
uhci_register_event_callbacks(uhci_handle, &uhci_cbs, NULL);
|
||||
|
||||
if (uhci_out_user_log_init() != 0) {
|
||||
goto failed;
|
||||
}
|
||||
|
||||
if (uhci_out_ll_log_init() != 0) {
|
||||
goto failed;
|
||||
}
|
||||
|
||||
esp_timer_create_args_t timer_args = {
|
||||
.callback = (esp_timer_cb_t)esp_timer_cb_log_flush,
|
||||
.dispatch_method = ESP_TIMER_TASK
|
||||
};
|
||||
if (esp_timer_create(&timer_args, &flush_timer) != ESP_OK) {
|
||||
goto failed;
|
||||
}
|
||||
|
||||
#if UHCI_OUT_UART_PORT == UHCI_OUT_UART_PORT0
|
||||
// Install UART Driver if not installed
|
||||
if (!uart_is_driver_installed(UHCI_OUT_UART_PORT0)) {
|
||||
uart_driver_install(UHCI_OUT_UART_PORT0, UHCI_OUT_UART_DRIVER_RX_BUF_SIZE, 0, 0, NULL, 0);
|
||||
}
|
||||
|
||||
// Redirect UART VFS Driver to UART Driver
|
||||
uart_vfs_dev_use_driver(UHCI_OUT_UART_PORT0);
|
||||
|
||||
// Redirect esp_rom_printf to BLE Log UHCI Out
|
||||
esp_rom_install_channel_putc(1, uhci_out_user_write_char);
|
||||
esp_rom_install_channel_putc(2, NULL);
|
||||
#endif // UHCI_OUT_UART_PORT == UHCI_OUT_UART_PORT0
|
||||
|
||||
uhci_out_inited = true;
|
||||
esp_timer_start_once(flush_timer, UHCI_OUT_FLUSH_TIMEOUT_US);
|
||||
return 0;
|
||||
|
||||
failed:
|
||||
ble_log_uhci_out_deinit();
|
||||
return -1;
|
||||
}
|
||||
|
||||
void ble_log_uhci_out_deinit(void)
|
||||
{
|
||||
uhci_out_inited = false;
|
||||
|
||||
if (flush_timer) {
|
||||
esp_timer_stop(flush_timer);
|
||||
esp_timer_delete(flush_timer);
|
||||
flush_timer = NULL;
|
||||
}
|
||||
|
||||
if (uhci_handle) {
|
||||
uhci_wait_all_tx_transaction_done(uhci_handle, portMAX_DELAY);
|
||||
uhci_del_controller(uhci_handle);
|
||||
uhci_handle = NULL;
|
||||
}
|
||||
|
||||
uhci_out_ll_log_deinit();
|
||||
uhci_out_user_log_deinit();
|
||||
}
|
||||
|
||||
IRAM_ATTR void ble_log_uhci_out_ll_write(uint32_t len, const uint8_t *addr, uint32_t len_append,
|
||||
const uint8_t *addr_append, uint32_t flag)
|
||||
{
|
||||
// Raw logs will come in case of assert, shall be printed to console directly
|
||||
if (flag & BIT(LL_LOG_FLAG_RAW)) {
|
||||
if (len && addr) {
|
||||
for (uint32_t i = 0; i < len; i++) { esp_rom_printf("%02x ", addr[i]); }
|
||||
}
|
||||
if (len_append && addr_append) {
|
||||
for (uint32_t i = 0; i < len_append; i++) { esp_rom_printf("%02x ", addr_append[i]); }
|
||||
}
|
||||
if (flag & BIT(LL_LOG_FLAG_END)) { esp_rom_printf("\n"); }
|
||||
}
|
||||
|
||||
if (!ll_log_inited) {
|
||||
return;
|
||||
}
|
||||
|
||||
bool in_isr = false;
|
||||
uint8_t source;
|
||||
uhci_out_log_cb_t *log_cb;
|
||||
if (flag & BIT(LL_LOG_FLAG_ISR)) {
|
||||
log_cb = ll_isr_log_cb;
|
||||
source = BLE_LOG_UHCI_OUT_SOURCE_ESP_ISR;
|
||||
in_isr = true;
|
||||
} else if (flag & BIT(LL_LOG_FLAG_HCI)) {
|
||||
log_cb = ll_hci_log_cb;
|
||||
source = BLE_LOG_UHCI_OUT_SOURCE_LL_HCI;
|
||||
} else {
|
||||
log_cb = ll_task_log_cb;
|
||||
source = BLE_LOG_UHCI_OUT_SOURCE_ESP;
|
||||
}
|
||||
|
||||
bool need_append;
|
||||
uint16_t frame_len = len + len_append + UHCI_OUT_FRAME_OVERHEAD;
|
||||
if (uhci_out_log_cb_check_trans(log_cb, frame_len, &need_append)) {
|
||||
need_append |= uhci_out_log_cb_write(log_cb, addr, len, addr_append,
|
||||
len_append, source);
|
||||
}
|
||||
|
||||
ll_last_write_ts = in_isr?\
|
||||
pdTICKS_TO_MS(xTaskGetTickCountFromISR()):\
|
||||
pdTICKS_TO_MS(xTaskGetTickCount());
|
||||
|
||||
if (need_append) {
|
||||
if (in_isr) {
|
||||
ll_ev_flags |= BIT(LL_EV_FLAG_ISR_APPEND);
|
||||
UHCI_OUT_LL_PUT_EV;
|
||||
} else {
|
||||
uhci_out_log_cb_append_trans(log_cb);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
IRAM_ATTR void ble_log_uhci_out_ll_log_ev_proc(void)
|
||||
{
|
||||
if (!ll_log_inited) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (ll_ev_flags & BIT(LL_EV_FLAG_ISR_APPEND)) {
|
||||
uhci_out_log_cb_append_trans(ll_isr_log_cb);
|
||||
ll_ev_flags &= ~BIT(LL_EV_FLAG_ISR_APPEND);
|
||||
}
|
||||
|
||||
if (ll_ev_flags & BIT(LL_EV_FLAG_FLUSH_LOG)) {
|
||||
uhci_out_ll_log_flush();
|
||||
ll_ev_flags &= ~BIT(LL_EV_FLAG_FLUSH_LOG);
|
||||
}
|
||||
|
||||
ll_ev_flags = 0;
|
||||
}
|
||||
|
||||
// Redirect UART Driver to BLE Log UHCI Out
|
||||
int __real_uart_tx_chars(uart_port_t uart_num, const char *buffer, uint32_t len);
|
||||
int __wrap_uart_tx_chars(uart_port_t uart_num, const char *buffer, uint32_t len)
|
||||
{
|
||||
#if UHCI_OUT_UART_PORT == UHCI_OUT_UART_PORT0
|
||||
uhci_out_user_write_str((const uint8_t *)buffer, len);
|
||||
return 0;
|
||||
#else
|
||||
return __real_uart_tx_chars(uart_num, buffer, len);
|
||||
#endif // UHCI_OUT_UART_PORT == UHCI_OUT_UART_PORT0
|
||||
}
|
||||
|
||||
int __real_uart_write_bytes(uart_port_t uart_num, const void *src, size_t size);
|
||||
int __wrap_uart_write_bytes(uart_port_t uart_num, const void *src, size_t size)
|
||||
{
|
||||
#if UHCI_OUT_UART_PORT == UHCI_OUT_UART_PORT0
|
||||
uhci_out_user_write_str((const uint8_t *)src, size);
|
||||
return 0;
|
||||
#else
|
||||
return __real_uart_write_bytes(uart_num, src, size);
|
||||
#endif // UHCI_OUT_UART_PORT == UHCI_OUT_UART_PORT0
|
||||
}
|
||||
|
||||
int __real_uart_write_bytes_with_break(uart_port_t uart_num, const void *src, size_t size, int brk_len);
|
||||
int __wrap_uart_write_bytes_with_break(uart_port_t uart_num, const void *src, size_t size, int brk_len)
|
||||
{
|
||||
#if UHCI_OUT_UART_PORT == UHCI_OUT_UART_PORT0
|
||||
return __wrap_uart_write_bytes(uart_num, src, size);
|
||||
#else
|
||||
return __real_uart_write_bytes_with_break(uart_num, src, size, brk_len);
|
||||
#endif // UHCI_OUT_UART_PORT == UHCI_OUT_UART_PORT0
|
||||
}
|
||||
|
||||
void ble_log_uhci_out_dump_all(void)
|
||||
{
|
||||
if (!uhci_out_inited) {
|
||||
return;
|
||||
}
|
||||
|
||||
#if UHCI_OUT_UART_PORT == UHCI_OUT_UART_PORT0
|
||||
esp_rom_output_tx_wait_idle(UHCI_OUT_UART_PORT0);
|
||||
esp_rom_install_uart_printf();
|
||||
#endif // UHCI_OUT_UART_PORT == UHCI_OUT_UART_PORT0
|
||||
|
||||
portMUX_TYPE spinlock = portMUX_INITIALIZER_UNLOCKED;
|
||||
portENTER_CRITICAL_SAFE(&spinlock);
|
||||
|
||||
if (ll_log_inited) {
|
||||
esp_rom_printf("[DUMP_START:\n");
|
||||
uhci_out_log_cb_dump(ll_isr_log_cb);
|
||||
uhci_out_log_cb_dump(ll_task_log_cb);
|
||||
uhci_out_log_cb_dump(ll_hci_log_cb);
|
||||
esp_rom_printf("\n:DUMP_END]\n\n");
|
||||
}
|
||||
portEXIT_CRITICAL_SAFE(&spinlock);
|
||||
|
||||
#if UHCI_OUT_UART_PORT == UHCI_OUT_UART_PORT0
|
||||
esp_rom_install_channel_putc(1, uhci_out_user_write_char);
|
||||
#endif // UHCI_OUT_UART_PORT == UHCI_OUT_UART_PORT0
|
||||
}
|
||||
#endif // CONFIG_BT_BLE_LOG_UHCI_OUT_ENABLED
|
||||
@@ -1,56 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#ifndef __BLE_LOG_H__
|
||||
#define __BLE_LOG_H__
|
||||
|
||||
/* ------- */
|
||||
/* BLE Log */
|
||||
/* ------- */
|
||||
|
||||
/* INCLUDE */
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
/* TYPEDEF */
|
||||
/* CRITICAL:
|
||||
* The number of BLE Log source code will directly determine the number of statistic manager
|
||||
* memory requirements, keep it as less as possible; it's recommended to use subcode for more
|
||||
* log data structure decoding */
|
||||
typedef enum {
|
||||
/* Internal */
|
||||
BLE_LOG_SRC_INTERNAL = 0,
|
||||
|
||||
/* Custom */
|
||||
BLE_LOG_SRC_CUSTOM,
|
||||
|
||||
/* BLE Stack */
|
||||
BLE_LOG_SRC_LL_TASK,
|
||||
BLE_LOG_SRC_LL_HCI,
|
||||
BLE_LOG_SRC_LL_ISR,
|
||||
BLE_LOG_SRC_HOST,
|
||||
BLE_LOG_SRC_HCI,
|
||||
BLE_LOG_SRC_ENCODE,
|
||||
|
||||
BLE_LOG_SRC_MAX,
|
||||
} ble_log_src_t;
|
||||
|
||||
/* INTERFACE */
|
||||
bool ble_log_init(void);
|
||||
void ble_log_deinit(void);
|
||||
bool ble_log_enable(bool enable);
|
||||
void ble_log_flush(void);
|
||||
bool ble_log_write_hex(ble_log_src_t src_code, const uint8_t *addr, size_t len);
|
||||
void ble_log_dump_to_console(void);
|
||||
#if CONFIG_BLE_LOG_LL_ENABLED
|
||||
void ble_log_write_hex_ll(uint32_t len, const uint8_t *addr,
|
||||
uint32_t len_append, const uint8_t *addr_append, uint32_t flag);
|
||||
#endif /* CONFIG_BLE_LOG_LL_ENABLED */
|
||||
#if CONFIG_BLE_LOG_TS_ENABLED
|
||||
bool ble_log_sync_enable(bool enable);
|
||||
#endif /* CONFIG_BLE_LOG_TS_ENABLED */
|
||||
|
||||
#endif /* __BLE_LOG_H__ */
|
||||
@@ -1,65 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#ifndef __BT_SPI_OUT_H__
|
||||
#define __BT_SPI_OUT_H__
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include "driver/spi_master.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "esp_timer.h"
|
||||
#include "freertos/semphr.h"
|
||||
#include "esp_heap_caps.h"
|
||||
#include "esp_task.h"
|
||||
|
||||
// Public enums
|
||||
enum {
|
||||
BLE_LOG_SPI_OUT_SOURCE_ESP = 0,
|
||||
BLE_LOG_SPI_OUT_SOURCE_ESP_LEGACY,
|
||||
BLE_LOG_SPI_OUT_SOURCE_BLUEDROID,
|
||||
BLE_LOG_SPI_OUT_SOURCE_NIMBLE,
|
||||
BLE_LOG_SPI_OUT_SOURCE_HCI_UPSTREAM,
|
||||
BLE_LOG_SPI_OUT_SOURCE_HCI_DOWNSTREAM,
|
||||
BLE_LOG_SPI_OUT_SOURCE_ESP_ISR,
|
||||
BLE_LOG_SPI_OUT_SOURCE_ESP_LEGACY_ISR,
|
||||
BLE_LOG_SPI_OUT_SOURCE_LL_HCI,
|
||||
BLE_LOG_SPI_OUT_SOURCE_LE_AUDIO,
|
||||
BLE_LOG_SPI_OUT_SOURCE_MESH,
|
||||
BLE_LOG_SPI_OUT_SOURCE_USER = 0x10,
|
||||
BLE_LOG_SPI_OUT_SOURCE_SSC = 0xFD,
|
||||
BLE_LOG_SPI_OUT_SOURCE_SYNC,
|
||||
BLE_LOG_SPI_OUT_SOURCE_LOSS,
|
||||
};
|
||||
|
||||
#define BLE_LOG_SPI_OUT_LEVEL_NONE 0
|
||||
#define BLE_LOG_SPI_OUT_LEVEL_ERROR 1
|
||||
#define BLE_LOG_SPI_OUT_LEVEL_WARN 2
|
||||
#define BLE_LOG_SPI_OUT_LEVEL_INFO 3
|
||||
#define BLE_LOG_SPI_OUT_LEVEL_DEBUG 4
|
||||
#define BLE_LOG_SPI_OUT_LEVEL_VERBOSE 5
|
||||
#define BLE_LOG_SPI_OUT_STR(x) #x
|
||||
#define BLE_LOG_SPI_OUT_XSTR(x) BLE_LOG_SPI_OUT_STR(x)
|
||||
#define BLE_LOG_SPI_OUT_BUILD_PREFIX(LEVEL, TAG) "[" BLE_LOG_SPI_OUT_XSTR(LEVEL) "][" TAG "]"
|
||||
|
||||
// Public functions
|
||||
int ble_log_spi_out_init(void);
|
||||
void ble_log_spi_out_deinit(void);
|
||||
void ble_log_spi_out_timer_control(bool enable);
|
||||
int ble_log_spi_out_write(uint8_t source, const uint8_t *addr, uint16_t len);
|
||||
void ble_log_spi_out_ll_write(uint32_t len, const uint8_t *addr, uint32_t len_append,\
|
||||
const uint8_t *addr_append, uint32_t flag);
|
||||
void ble_log_spi_out_ll_log_ev_proc(void);
|
||||
void ble_log_spi_out_ts_sync_start(void);
|
||||
void ble_log_spi_out_ts_sync_stop(void);
|
||||
void ble_log_spi_out_dump_all(void);
|
||||
void ble_log_spi_out_enable(bool enable);
|
||||
void ble_log_spi_out_flush(void);
|
||||
void ble_log_spi_out_le_audio_write(const uint8_t *addr, uint16_t len);
|
||||
int ble_log_spi_out_host_write(uint8_t source, const char *prefix, const char *format, ...);
|
||||
int ble_log_spi_out_hci_write(uint8_t source, const uint8_t *addr, uint16_t len);
|
||||
int ble_log_spi_out_mesh_write(const char *prefix, const char *format, ...);
|
||||
|
||||
#endif // __BT_SPI_OUT_H__
|
||||
@@ -1,36 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#ifndef __BT_SPI_OUT_H__
|
||||
#define __BT_SPI_OUT_H__
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include "driver/uhci.h"
|
||||
#include "driver/uart.h"
|
||||
#include "driver/uart_vfs.h"
|
||||
#include "esp_rom_uart.h"
|
||||
#include "esp_rom_sys.h"
|
||||
#include "esp_timer.h"
|
||||
#include "freertos/semphr.h"
|
||||
|
||||
// Public enums
|
||||
enum {
|
||||
BLE_LOG_UHCI_OUT_SOURCE_ESP = 0,
|
||||
BLE_LOG_UHCI_OUT_SOURCE_ESP_ISR = 6,
|
||||
BLE_LOG_UHCI_OUT_SOURCE_LL_HCI = 8,
|
||||
BLE_LOG_UHCI_OUT_SOURCE_USER = 0x10,
|
||||
BLE_LOG_UHCI_OUT_SOURCE_LOSS = 0xFF,
|
||||
};
|
||||
|
||||
// Public functions
|
||||
int ble_log_uhci_out_init(void);
|
||||
void ble_log_uhci_out_deinit(void);
|
||||
void ble_log_uhci_out_ll_write(uint32_t len, const uint8_t *addr, uint32_t len_append,
|
||||
const uint8_t *addr_append, uint32_t flag);
|
||||
void ble_log_uhci_out_ll_log_ev_proc(void);
|
||||
void ble_log_uhci_out_dump_all(void);
|
||||
|
||||
#endif // __BT_SPI_OUT_H__
|
||||
@@ -1,94 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
/* ------- */
|
||||
/* BLE Log */
|
||||
/* ------- */
|
||||
|
||||
/* INCLUDE */
|
||||
#include "ble_log.h"
|
||||
#include "ble_log_rt.h"
|
||||
#include "ble_log_lbm.h"
|
||||
#include "ble_log_prph.h"
|
||||
#include "ble_log_util.h"
|
||||
#if CONFIG_BLE_LOG_TS_ENABLED
|
||||
#include "ble_log_ts.h"
|
||||
#endif /* CONFIG_BLE_LOG_TS_ENABLED */
|
||||
|
||||
/* VARIABLE */
|
||||
BLE_LOG_STATIC bool ble_log_inited = false;
|
||||
|
||||
/* INTERFACE */
|
||||
bool ble_log_init(void)
|
||||
{
|
||||
/* Avoid double init */
|
||||
if (ble_log_inited) {
|
||||
return true;
|
||||
}
|
||||
|
||||
#if CONFIG_BLE_LOG_TS_ENABLED
|
||||
/* Initialize BLE Log TS */
|
||||
if (!ble_log_ts_init()) {
|
||||
goto exit;
|
||||
}
|
||||
#endif /* CONFIG_BLE_LOG_TS_ENABLED */
|
||||
|
||||
/* Initialize BLE Log Runtime */
|
||||
if (!ble_log_rt_init()) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* Initialize BLE Log LBM */
|
||||
if (!ble_log_lbm_init()) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* Initialize BLE Log peripheral interface */
|
||||
if (!ble_log_prph_init(BLE_LOG_LBM_CNT)) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* Initialization done */
|
||||
ble_log_inited = true;
|
||||
ble_log_enable(true);
|
||||
|
||||
/* Write initialization done log */
|
||||
ble_log_info_t ble_log_info = {
|
||||
.int_src_code = BLE_LOG_INT_SRC_INIT_DONE,
|
||||
.version = BLE_LOG_VERSION,
|
||||
};
|
||||
ble_log_write_hex(BLE_LOG_SRC_INTERNAL, (const uint8_t *)&ble_log_info, sizeof(ble_log_info_t));
|
||||
return true;
|
||||
|
||||
exit:
|
||||
ble_log_deinit();
|
||||
return false;
|
||||
}
|
||||
|
||||
void ble_log_deinit(void)
|
||||
{
|
||||
ble_log_enable(false);
|
||||
ble_log_inited = false;
|
||||
|
||||
/* CRITICAL:
|
||||
* BLE Log peripheral interface must be deinitialized at first,
|
||||
* because there's a risky scenario that may cause severe peripheral
|
||||
* driver fault - if a log buffer is sent to peripheral driver, and
|
||||
* ble_log_deinit is called; in this case, if LBM is deinitialized
|
||||
* before peripheral interface, the log buffer may be freed before
|
||||
* peripheral driver completing tx, and the result would be faulty */
|
||||
ble_log_prph_deinit();
|
||||
|
||||
/* Deinitialize BLE Log LBM */
|
||||
ble_log_lbm_deinit();
|
||||
|
||||
/* Deinitialize BLE Log Runtime */
|
||||
ble_log_rt_deinit();
|
||||
|
||||
#if CONFIG_BLE_LOG_TS_ENABLED
|
||||
/* Deinitialize BLE Log TS */
|
||||
ble_log_ts_deinit();
|
||||
#endif /* CONFIG_BLE_LOG_TS_ENABLED */
|
||||
}
|
||||
@@ -1,543 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
/* ------------------------------- */
|
||||
/* BLE Log - Log Buffer Management */
|
||||
/* ------------------------------- */
|
||||
|
||||
/* INCLUDE */
|
||||
#include "ble_log.h"
|
||||
#include "ble_log_lbm.h"
|
||||
#include "ble_log_rt.h"
|
||||
|
||||
/* VARIABLE */
|
||||
BLE_LOG_STATIC volatile uint32_t lbm_ref_count = 0;
|
||||
BLE_LOG_STATIC bool lbm_inited = false;
|
||||
BLE_LOG_STATIC bool lbm_enabled = false;
|
||||
BLE_LOG_STATIC ble_log_lbm_ctx_t *lbm_ctx = NULL;
|
||||
BLE_LOG_STATIC ble_log_stat_mgr_t *stat_mgr_ctx[BLE_LOG_SRC_MAX] = {0};
|
||||
|
||||
/* PRIVATE FUNCTION DECLARATION */
|
||||
BLE_LOG_STATIC ble_log_lbm_t *ble_log_lbm_acquire(void);
|
||||
BLE_LOG_STATIC void ble_log_lbm_release(ble_log_lbm_t *lbm);
|
||||
BLE_LOG_STATIC
|
||||
void ble_log_lbm_write_trans(ble_log_prph_trans_t **trans, ble_log_src_t src_code,
|
||||
const uint8_t *addr, uint16_t len,
|
||||
const uint8_t *addr_append, uint16_t len_append);
|
||||
#if CONFIG_BLE_LOG_ENH_STAT_ENABLED
|
||||
BLE_LOG_STATIC void ble_log_stat_mgr_update(ble_log_src_t src_code, uint32_t len, bool lost);
|
||||
#endif /* CONFIG_BLE_LOG_ENH_STAT_ENABLED */
|
||||
|
||||
/* ------------------------- */
|
||||
/* PRIVATE INTERFACE */
|
||||
/* ------------------------- */
|
||||
BLE_LOG_IRAM_ATTR BLE_LOG_STATIC
|
||||
ble_log_lbm_t *ble_log_lbm_acquire(void)
|
||||
{
|
||||
ble_log_lbm_t *lbm = NULL;
|
||||
ble_log_lbm_t *atomic_pool;
|
||||
ble_log_lbm_t *spin_lbm;
|
||||
int atomic_pool_size;
|
||||
|
||||
if (BLE_LOG_IN_ISR()) {
|
||||
atomic_pool = lbm_ctx->atomic_pool_isr;
|
||||
spin_lbm = &(lbm_ctx->spin_isr);
|
||||
atomic_pool_size = BLE_LOG_LBM_ATOMIC_ISR_CNT;
|
||||
} else {
|
||||
atomic_pool = lbm_ctx->atomic_pool_task;
|
||||
spin_lbm = &(lbm_ctx->spin_task);
|
||||
atomic_pool_size = BLE_LOG_LBM_ATOMIC_TASK_CNT;
|
||||
}
|
||||
|
||||
/* Try to acquire atomic LBM first */
|
||||
for (int i = 0; i < atomic_pool_size; i++) {
|
||||
lbm = &atomic_pool[i];
|
||||
if (ble_log_cas_acquire(&(lbm->atomic_lock))) {
|
||||
return lbm;
|
||||
}
|
||||
}
|
||||
|
||||
/* Fallback to spinlock LBM */
|
||||
lbm = spin_lbm;
|
||||
BLE_LOG_ACQUIRE_SPIN_LOCK(&(lbm->spin_lock));
|
||||
return lbm;
|
||||
}
|
||||
|
||||
BLE_LOG_IRAM_ATTR BLE_LOG_STATIC
|
||||
void ble_log_lbm_release(ble_log_lbm_t *lbm)
|
||||
{
|
||||
switch (lbm->lock_type) {
|
||||
case BLE_LOG_LBM_LOCK_ATOMIC:
|
||||
ble_log_cas_release(&(lbm->atomic_lock));
|
||||
break;
|
||||
case BLE_LOG_LBM_LOCK_SPIN:
|
||||
BLE_LOG_RELEASE_SPIN_LOCK(&lbm->spin_lock);
|
||||
break;
|
||||
case BLE_LOG_LBM_LOCK_NONE:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
BLE_LOG_IRAM_ATTR BLE_LOG_STATIC
|
||||
void ble_log_lbm_write_trans(ble_log_prph_trans_t **trans, ble_log_src_t src_code,
|
||||
const uint8_t *addr, uint16_t len,
|
||||
const uint8_t *addr_append, uint16_t len_append)
|
||||
{
|
||||
/* Preparation before writing */
|
||||
uint8_t *buf = (*trans)->buf + (*trans)->pos;
|
||||
uint16_t payload_len = len + len_append;
|
||||
ble_log_stat_mgr_t *stat_mgr = stat_mgr_ctx[src_code];
|
||||
uint32_t frame_sn = BLE_LOG_GET_FRAME_SN(&(stat_mgr->frame_sn));
|
||||
ble_log_frame_head_t frame_head = {
|
||||
.length = payload_len,
|
||||
.frame_meta = BLE_LOG_MAKE_FRAME_META(src_code, frame_sn),
|
||||
};
|
||||
|
||||
/* Memory operation */
|
||||
BLE_LOG_MEMCPY(buf, &frame_head, BLE_LOG_FRAME_HEAD_LEN);
|
||||
if (len) {
|
||||
BLE_LOG_MEMCPY(buf + BLE_LOG_FRAME_HEAD_LEN, addr, len);
|
||||
}
|
||||
if (len_append) {
|
||||
BLE_LOG_MEMCPY(buf + BLE_LOG_FRAME_HEAD_LEN + len, addr_append, len_append);
|
||||
}
|
||||
|
||||
/* Data integrity check */
|
||||
#if CONFIG_BLE_LOG_PAYLOAD_CHECKSUM_ENABLED
|
||||
uint32_t checksum = ble_log_fast_checksum((const uint8_t *)buf, BLE_LOG_FRAME_HEAD_LEN + payload_len);
|
||||
#else /* !CONFIG_BLE_LOG_PAYLOAD_CHECKSUM_ENABLED */
|
||||
/* Note:
|
||||
* Minimum data integrity check is still required for log parsing reliability,
|
||||
* which can be achieved by validating the checksum of frame head only */
|
||||
uint32_t checksum = ble_log_fast_checksum((const uint8_t *)buf, BLE_LOG_FRAME_HEAD_LEN);
|
||||
#endif /* CONFIG_BLE_LOG_PAYLOAD_CHECKSUM_ENABLED */
|
||||
BLE_LOG_MEMCPY(buf + BLE_LOG_FRAME_HEAD_LEN + payload_len, &checksum, BLE_LOG_FRAME_TAIL_LEN);
|
||||
|
||||
/* Update peripheral transport */
|
||||
(*trans)->pos += payload_len + BLE_LOG_FRAME_OVERHEAD;
|
||||
|
||||
#if CONFIG_BLE_LOG_ENH_STAT_ENABLED
|
||||
ble_log_stat_mgr_update(src_code, payload_len, false);
|
||||
#endif /* CONFIG_BLE_LOG_ENH_STAT_ENABLED */
|
||||
|
||||
/* Queue trans if full */
|
||||
if (BLE_LOG_TRANS_FREE_SPACE((*trans)) <= BLE_LOG_FRAME_OVERHEAD) {
|
||||
ble_log_rt_queue_trans(trans);
|
||||
}
|
||||
}
|
||||
|
||||
#if CONFIG_BLE_LOG_ENH_STAT_ENABLED
|
||||
BLE_LOG_IRAM_ATTR BLE_LOG_STATIC
|
||||
void ble_log_stat_mgr_update(ble_log_src_t src_code, uint32_t len, bool lost)
|
||||
{
|
||||
/* Get statistic manager by source code */
|
||||
ble_log_stat_mgr_t *stat_mgr = stat_mgr_ctx[src_code];
|
||||
|
||||
/* Update statistics */
|
||||
uint32_t bytes_cnt = len + BLE_LOG_FRAME_OVERHEAD;
|
||||
if (lost) {
|
||||
stat_mgr->enh_stat.lost_frame_cnt++;
|
||||
stat_mgr->enh_stat.lost_bytes_cnt += bytes_cnt;
|
||||
} else {
|
||||
stat_mgr->enh_stat.written_frame_cnt++;
|
||||
stat_mgr->enh_stat.written_bytes_cnt += bytes_cnt;
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_BLE_LOG_ENH_STAT_ENABLED */
|
||||
|
||||
/* -------------------------- */
|
||||
/* INTERNAL INTERFACE */
|
||||
/* -------------------------- */
|
||||
bool ble_log_lbm_init(void)
|
||||
{
|
||||
/* Avoid double init */
|
||||
if (lbm_inited) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Initialize LBM context */
|
||||
lbm_ctx = (ble_log_lbm_ctx_t *)BLE_LOG_MALLOC(sizeof(ble_log_lbm_ctx_t));
|
||||
if (!lbm_ctx) {
|
||||
goto exit;
|
||||
}
|
||||
BLE_LOG_MEMSET(lbm_ctx, 0, sizeof(ble_log_lbm_ctx_t));
|
||||
|
||||
/* Initialize peripheral transport for common LBMs */
|
||||
ble_log_lbm_t *lbm;
|
||||
for (int i = 0; i < BLE_LOG_LBM_COMMON_CNT; i++) {
|
||||
lbm = &(lbm_ctx->lbm_common_pool[i]);
|
||||
for (int j = 0; j < BLE_LOG_TRANS_PING_PONG_BUF_CNT; j++) {
|
||||
if (!ble_log_prph_trans_init(&(lbm->trans[j]),
|
||||
CONFIG_BLE_LOG_LBM_TRANS_SIZE)) {
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Initialize lock types for atomic pool */
|
||||
for (int i = 0; i < BLE_LOG_LBM_ATOMIC_CNT; i++) {
|
||||
lbm_ctx->atomic_pool[i].lock_type = BLE_LOG_LBM_LOCK_ATOMIC;
|
||||
}
|
||||
|
||||
/* Initialize lock types for spin pool */
|
||||
for (int i = 0; i < BLE_LOG_LBM_SPIN_MAX; i++) {
|
||||
lbm_ctx->spin_pool[i].lock_type = BLE_LOG_LBM_LOCK_SPIN;
|
||||
}
|
||||
|
||||
#if CONFIG_BLE_LOG_LL_ENABLED
|
||||
for (int i = 0; i < BLE_LOG_LBM_LL_MAX; i++) {
|
||||
lbm = &(lbm_ctx->lbm_ll_pool[i]);
|
||||
for (int j = 0; j < BLE_LOG_TRANS_PING_PONG_BUF_CNT; j++) {
|
||||
if (!ble_log_prph_trans_init(&(lbm->trans[j]),
|
||||
CONFIG_BLE_LOG_LBM_LL_TRANS_SIZE)) {
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Initialize lock types for LL pool */
|
||||
for (int i = 0; i < BLE_LOG_LBM_LL_MAX; i++) {
|
||||
lbm_ctx->lbm_ll_pool[i].lock_type = BLE_LOG_LBM_LOCK_NONE;
|
||||
}
|
||||
#endif /* CONFIG_BLE_LOG_LL_ENABLED */
|
||||
|
||||
/* Initialize statistic manager context */
|
||||
for (int i = 0; i < BLE_LOG_SRC_MAX; i++) {
|
||||
stat_mgr_ctx[i] = (ble_log_stat_mgr_t *)BLE_LOG_MALLOC(sizeof(ble_log_stat_mgr_t));
|
||||
if (!stat_mgr_ctx[i]) {
|
||||
goto exit;
|
||||
}
|
||||
BLE_LOG_MEMSET(stat_mgr_ctx[i], 0, sizeof(ble_log_stat_mgr_t));
|
||||
|
||||
#if CONFIG_BLE_LOG_ENH_STAT_ENABLED
|
||||
stat_mgr_ctx[i]->enh_stat.int_src_code = BLE_LOG_INT_SRC_ENH_STAT;
|
||||
stat_mgr_ctx[i]->enh_stat.src_code = i;
|
||||
#endif /* CONFIG_BLE_LOG_ENH_STAT_ENABLED */
|
||||
}
|
||||
|
||||
/* Initialization done */
|
||||
lbm_ref_count = 0;
|
||||
lbm_inited = true;
|
||||
lbm_enabled = false;
|
||||
return true;
|
||||
|
||||
exit:
|
||||
ble_log_lbm_deinit();
|
||||
return false;
|
||||
}
|
||||
|
||||
void ble_log_lbm_deinit(void)
|
||||
{
|
||||
/* Set inited flag to false to prevent new references */
|
||||
lbm_inited = false;
|
||||
lbm_enabled = false;
|
||||
|
||||
/* Disable module and wait for all references to be released */
|
||||
uint32_t time_waited = 0;
|
||||
while (lbm_ref_count > 0) {
|
||||
vTaskDelay(pdMS_TO_TICKS(1));
|
||||
BLE_LOG_ASSERT(time_waited++ < 1000);
|
||||
}
|
||||
|
||||
/* Release statistic manager context */
|
||||
for (int i = 0; i < BLE_LOG_SRC_MAX; i++) {
|
||||
if (stat_mgr_ctx[i]) {
|
||||
BLE_LOG_FREE(stat_mgr_ctx[i]);
|
||||
stat_mgr_ctx[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Release LBM */
|
||||
if (lbm_ctx) {
|
||||
/* Release peripheral transport for common pools */
|
||||
ble_log_lbm_t *lbm;
|
||||
for (int i = 0; i < BLE_LOG_LBM_CNT; i++) {
|
||||
lbm = &(lbm_ctx->lbm_pool[i]);
|
||||
for (int j = 0; j < BLE_LOG_TRANS_PING_PONG_BUF_CNT; j++) {
|
||||
ble_log_prph_trans_deinit(&(lbm->trans[j]));
|
||||
}
|
||||
}
|
||||
|
||||
/* Release LBM context */
|
||||
BLE_LOG_FREE(lbm_ctx);
|
||||
lbm_ctx = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Note:
|
||||
* The function below should be private, but when UART redirection is required,
|
||||
* it would be a waste to implement get transport function again, thus
|
||||
* make it available internally */
|
||||
BLE_LOG_IRAM_ATTR
|
||||
ble_log_prph_trans_t **ble_log_lbm_get_trans(ble_log_lbm_t *lbm, size_t log_len)
|
||||
{
|
||||
/* Check if available buffer can contain incoming log */
|
||||
ble_log_prph_trans_t **trans;
|
||||
for (int i = 0; i < BLE_LOG_TRANS_PING_PONG_BUF_CNT; i++) {
|
||||
trans = &(lbm->trans[lbm->trans_idx]);
|
||||
if (!(*trans)->prph_owned) {
|
||||
/* Return if there's enough free space in current transport */
|
||||
if (BLE_LOG_TRANS_FREE_SPACE((*trans)) >= (log_len + BLE_LOG_FRAME_OVERHEAD)) {
|
||||
return trans;
|
||||
}
|
||||
|
||||
/* Queue transport if there's insufficient free space */
|
||||
if ((*trans)->pos) {
|
||||
ble_log_rt_queue_trans(trans);
|
||||
}
|
||||
}
|
||||
|
||||
/* Current transport unavailable, switch to the other */
|
||||
lbm->trans_idx = !lbm->trans_idx;
|
||||
}
|
||||
|
||||
/* Both ping-pong buffers are unavailable */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#if CONFIG_BLE_LOG_ENH_STAT_ENABLED
|
||||
void ble_log_write_enh_stat(void)
|
||||
{
|
||||
BLE_LOG_REF_COUNT_ACQUIRE(&lbm_ref_count);
|
||||
if (!lbm_enabled) {
|
||||
goto deref;
|
||||
}
|
||||
|
||||
for (int i = 0; i < BLE_LOG_SRC_MAX; i++) {
|
||||
ble_log_enh_stat_t *enh_stat = &(stat_mgr_ctx[i]->enh_stat);
|
||||
ble_log_write_hex(BLE_LOG_SRC_INTERNAL, (const uint8_t *)enh_stat, sizeof(ble_log_enh_stat_t));
|
||||
}
|
||||
|
||||
deref:
|
||||
BLE_LOG_REF_COUNT_RELEASE(&lbm_ref_count);
|
||||
}
|
||||
#endif /* CONFIG_BLE_LOG_ENH_STAT_ENABLED */
|
||||
|
||||
/* ------------------------ */
|
||||
/* PUBLIC INTERFACE */
|
||||
/* ------------------------ */
|
||||
bool ble_log_enable(bool enable)
|
||||
{
|
||||
if (!lbm_inited) {
|
||||
return false;
|
||||
}
|
||||
lbm_enabled = enable;
|
||||
return true;
|
||||
}
|
||||
|
||||
void ble_log_flush(void)
|
||||
{
|
||||
BLE_LOG_REF_COUNT_ACQUIRE(&lbm_ref_count);
|
||||
if (!lbm_inited) {
|
||||
goto deref;
|
||||
}
|
||||
|
||||
#if CONFIG_BLE_LOG_ENH_STAT_ENABLED
|
||||
/* Write enhanced statistics before module disable */
|
||||
ble_log_write_enh_stat();
|
||||
#endif /* CONFIG_BLE_LOG_ENH_STAT_ENABLED */
|
||||
|
||||
/* Write BLE Log flush log */
|
||||
ble_log_info_t ble_log_info = {
|
||||
.int_src_code = BLE_LOG_INT_SRC_FLUSH,
|
||||
.version = BLE_LOG_VERSION,
|
||||
};
|
||||
ble_log_write_hex(BLE_LOG_SRC_INTERNAL, (const uint8_t *)&ble_log_info, sizeof(ble_log_info_t));
|
||||
|
||||
/* Disable module and wait for all other references to release */
|
||||
bool lbm_enabled_copy = lbm_enabled;
|
||||
lbm_enabled = false;
|
||||
uint32_t time_waited = 0;
|
||||
while (lbm_ref_count > 1) {
|
||||
vTaskDelay(pdMS_TO_TICKS(1));
|
||||
BLE_LOG_ASSERT(time_waited++ < 1000);
|
||||
}
|
||||
|
||||
/* Queue transports with logs */
|
||||
ble_log_lbm_t *lbm;
|
||||
ble_log_prph_trans_t **trans;
|
||||
|
||||
/* Flush pools */
|
||||
for (int i = 0; i < BLE_LOG_LBM_CNT; i++) {
|
||||
lbm = &(lbm_ctx->lbm_pool[i]);
|
||||
int trans_idx = lbm->trans_idx;
|
||||
for (int j = 0; j < BLE_LOG_TRANS_PING_PONG_BUF_CNT; j++) {
|
||||
trans = &(lbm->trans[trans_idx]);
|
||||
if (!(*trans)->prph_owned && (*trans)->pos) {
|
||||
ble_log_rt_queue_trans(trans);
|
||||
}
|
||||
trans_idx = !trans_idx;
|
||||
}
|
||||
}
|
||||
|
||||
/* Wait for transportation to finish */
|
||||
time_waited = 0;
|
||||
bool in_progress;
|
||||
do {
|
||||
in_progress = false;
|
||||
for (int i = 0; i < BLE_LOG_LBM_CNT; i++) {
|
||||
lbm = &(lbm_ctx->lbm_pool[i]);
|
||||
for (int j = 0; j < BLE_LOG_TRANS_PING_PONG_BUF_CNT; j++) {
|
||||
trans = &(lbm->trans[j]);
|
||||
in_progress |= (*trans)->prph_owned;
|
||||
}
|
||||
}
|
||||
if (in_progress) {
|
||||
vTaskDelay(pdMS_TO_TICKS(1));
|
||||
BLE_LOG_ASSERT(time_waited++ < 1000);
|
||||
}
|
||||
} while (in_progress);
|
||||
|
||||
/* Reset statistics manager after all operations complete */
|
||||
for (int i = 0; i < BLE_LOG_SRC_MAX; i++) {
|
||||
BLE_LOG_MEMSET(stat_mgr_ctx[i], 0, sizeof(ble_log_stat_mgr_t));
|
||||
#if CONFIG_BLE_LOG_ENH_STAT_ENABLED
|
||||
/* Reinitialize enhanced statistics fields */
|
||||
stat_mgr_ctx[i]->enh_stat.int_src_code = BLE_LOG_INT_SRC_ENH_STAT;
|
||||
stat_mgr_ctx[i]->enh_stat.src_code = i;
|
||||
#endif /* CONFIG_BLE_LOG_ENH_STAT_ENABLED */
|
||||
}
|
||||
|
||||
/* Resume enable status */
|
||||
lbm_enabled = lbm_enabled_copy;
|
||||
|
||||
deref:
|
||||
BLE_LOG_REF_COUNT_RELEASE(&lbm_ref_count);
|
||||
}
|
||||
|
||||
bool ble_log_write_hex(ble_log_src_t src_code, const uint8_t *addr, size_t len)
|
||||
{
|
||||
BLE_LOG_REF_COUNT_ACQUIRE(&lbm_ref_count);
|
||||
size_t payload_len = len + sizeof(uint32_t);
|
||||
if (!lbm_enabled) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* Get transport */
|
||||
ble_log_lbm_t *lbm = ble_log_lbm_acquire();
|
||||
ble_log_prph_trans_t **trans = ble_log_lbm_get_trans(lbm, payload_len);
|
||||
if (!trans) {
|
||||
ble_log_lbm_release(lbm);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* Write transport */
|
||||
uint32_t os_ts = pdTICKS_TO_MS(BLE_LOG_IN_ISR()?
|
||||
xTaskGetTickCountFromISR():
|
||||
xTaskGetTickCount());
|
||||
ble_log_lbm_write_trans(trans, src_code, (const uint8_t *)&os_ts,
|
||||
sizeof(uint32_t), addr, len);
|
||||
|
||||
/* Release */
|
||||
ble_log_lbm_release(lbm);
|
||||
BLE_LOG_REF_COUNT_RELEASE(&lbm_ref_count);
|
||||
return true;
|
||||
|
||||
exit:
|
||||
#if CONFIG_BLE_LOG_ENH_STAT_ENABLED
|
||||
if (lbm_inited) {
|
||||
ble_log_stat_mgr_update(src_code, payload_len, true);
|
||||
}
|
||||
#endif /* CONFIG_BLE_LOG_ENH_STAT_ENABLED */
|
||||
BLE_LOG_REF_COUNT_RELEASE(&lbm_ref_count);
|
||||
return false;
|
||||
}
|
||||
|
||||
#if CONFIG_BLE_LOG_LL_ENABLED
|
||||
BLE_LOG_IRAM_ATTR
|
||||
void ble_log_write_hex_ll(uint32_t len, const uint8_t *addr,
|
||||
uint32_t len_append, const uint8_t *addr_append, uint32_t flag)
|
||||
{
|
||||
BLE_LOG_REF_COUNT_ACQUIRE(&lbm_ref_count);
|
||||
size_t payload_len = len + len_append;
|
||||
|
||||
/* Source code shall be determined before LBM enable status check */
|
||||
ble_log_src_t src_code;
|
||||
bool use_ll_task = false;
|
||||
if (flag & BIT(BLE_LOG_LL_FLAG_ISR)) {
|
||||
src_code = BLE_LOG_SRC_LL_ISR;
|
||||
} else if (flag & BIT(BLE_LOG_LL_FLAG_HCI)) {
|
||||
src_code = BLE_LOG_SRC_LL_HCI;
|
||||
} else if (flag & BIT(BLE_LOG_LL_FLAG_HCI_UPSTREAM)) {
|
||||
src_code = BLE_LOG_SRC_HCI;
|
||||
} else {
|
||||
src_code = BLE_LOG_SRC_LL_TASK;
|
||||
use_ll_task = true;
|
||||
}
|
||||
|
||||
if (!lbm_enabled) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* Determine LBM by flag */
|
||||
ble_log_lbm_t *lbm;
|
||||
if (BLE_LOG_IN_ISR()) {
|
||||
/* Reuse common LBM acquire logic */
|
||||
lbm = ble_log_lbm_acquire();
|
||||
} else {
|
||||
lbm = (use_ll_task)? &(lbm_ctx->lbm_ll_task): &(lbm_ctx->lbm_ll_hci);
|
||||
}
|
||||
|
||||
/* Get transport */
|
||||
ble_log_prph_trans_t **trans = ble_log_lbm_get_trans(lbm, payload_len);
|
||||
if (!trans) {
|
||||
ble_log_lbm_release(lbm);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* Write transport */
|
||||
ble_log_lbm_write_trans(trans, src_code, addr, len, addr_append, len_append);
|
||||
|
||||
ble_log_lbm_release(lbm);
|
||||
BLE_LOG_REF_COUNT_RELEASE(&lbm_ref_count);
|
||||
return;
|
||||
|
||||
exit:
|
||||
#if CONFIG_BLE_LOG_ENH_STAT_ENABLED
|
||||
if (lbm_inited) {
|
||||
ble_log_stat_mgr_update(src_code, payload_len, true);
|
||||
}
|
||||
#endif /* CONFIG_BLE_LOG_ENH_STAT_ENABLED */
|
||||
BLE_LOG_REF_COUNT_RELEASE(&lbm_ref_count);
|
||||
return;
|
||||
}
|
||||
#endif /* CONFIG_BLE_LOG_LL_ENABLED */
|
||||
|
||||
void ble_log_dump_to_console(void)
|
||||
{
|
||||
BLE_LOG_REF_COUNT_ACQUIRE(&lbm_ref_count);
|
||||
if (!lbm_inited) {
|
||||
goto deref;
|
||||
}
|
||||
|
||||
int trans_idx;
|
||||
ble_log_lbm_t *lbm;
|
||||
ble_log_prph_trans_t *trans;
|
||||
BLE_LOG_ENTER_CRITICAL();
|
||||
BLE_LOG_CONSOLE("[BLE_LOG_DUMP_START:\n");
|
||||
for (int i = 0; i < BLE_LOG_LBM_CNT; i++) {
|
||||
lbm = &(lbm_ctx->lbm_pool[i]);
|
||||
trans_idx = lbm->trans_idx;
|
||||
for (int j = 0; j < BLE_LOG_TRANS_PING_PONG_BUF_CNT; j++) {
|
||||
trans = lbm->trans[trans_idx];
|
||||
BLE_LOG_FEED_WDT();
|
||||
|
||||
for (int k = 0; k < trans->size; k++) {
|
||||
BLE_LOG_CONSOLE("%02x ", trans->buf[k]);
|
||||
if (!(k & 0xFF)) {
|
||||
BLE_LOG_FEED_WDT();
|
||||
}
|
||||
}
|
||||
trans_idx = !trans_idx;
|
||||
}
|
||||
}
|
||||
BLE_LOG_CONSOLE("\n:BLE_LOG_DUMP_END]\n\n");
|
||||
BLE_LOG_EXIT_CRITICAL();
|
||||
|
||||
deref:
|
||||
BLE_LOG_REF_COUNT_RELEASE(&lbm_ref_count);
|
||||
return;
|
||||
}
|
||||
@@ -1,144 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/* ----------------- */
|
||||
/* BLE Log - Runtime */
|
||||
/* ----------------- */
|
||||
|
||||
/* INCLUDE */
|
||||
#include "ble_log.h"
|
||||
#include "ble_log_rt.h"
|
||||
#include "ble_log_lbm.h"
|
||||
|
||||
/* VARIABLE */
|
||||
BLE_LOG_STATIC bool rt_inited = false;
|
||||
BLE_LOG_STATIC TaskHandle_t rt_task_handle = NULL;
|
||||
BLE_LOG_STATIC QueueHandle_t rt_queue_handle = NULL;
|
||||
#if CONFIG_BLE_LOG_TS_ENABLED
|
||||
BLE_LOG_STATIC bool rt_ts_enabled = false;
|
||||
#endif /* CONFIG_BLE_LOG_TS_ENABLED */
|
||||
|
||||
/* PRIVATE FUNCTION */
|
||||
BLE_LOG_IRAM_ATTR BLE_LOG_STATIC void ble_log_rt_task(void *pvParameters)
|
||||
{
|
||||
(void)pvParameters;
|
||||
ble_log_prph_trans_t *trans = NULL;
|
||||
uint32_t curr_os_ts = 0;
|
||||
uint32_t last_hook_os_ts = 0;
|
||||
#ifndef UNIT_TEST
|
||||
while (1)
|
||||
#endif /* !UNIT_TEST */
|
||||
{
|
||||
/* CRITICAL:
|
||||
* Blocking queue receive is mandatory for light sleep support */
|
||||
if (xQueueReceive(rt_queue_handle, &trans, portMAX_DELAY) == pdTRUE) {
|
||||
ble_log_prph_send_trans(trans);
|
||||
}
|
||||
|
||||
/* Task hook */
|
||||
curr_os_ts = pdTICKS_TO_MS(xTaskGetTickCount());
|
||||
if ((curr_os_ts - last_hook_os_ts) < BLE_LOG_TASK_HOOK_TIMEOUT_MS) {
|
||||
#ifndef UNIT_TEST
|
||||
continue;
|
||||
#else /* UNIT_TEST */
|
||||
return;
|
||||
#endif /* !UNIT_TEST */
|
||||
}
|
||||
last_hook_os_ts = curr_os_ts;
|
||||
|
||||
/* Write BLE Log info log */
|
||||
ble_log_info_t ble_log_info = {
|
||||
.int_src_code = BLE_LOG_INT_SRC_INFO,
|
||||
.version = BLE_LOG_VERSION,
|
||||
};
|
||||
ble_log_write_hex(BLE_LOG_SRC_INTERNAL, (const uint8_t *)&ble_log_info, sizeof(ble_log_info_t));
|
||||
|
||||
#if CONFIG_BLE_LOG_TS_ENABLED
|
||||
if (rt_ts_enabled) {
|
||||
ble_log_ts_info_t *ts_info = NULL;
|
||||
ble_log_ts_info_update(&ts_info);
|
||||
ble_log_write_hex(BLE_LOG_SRC_INTERNAL, (const uint8_t *)ts_info, sizeof(ble_log_ts_info_t));
|
||||
}
|
||||
#endif /* CONFIG_BLE_LOG_TS_ENABLED */
|
||||
|
||||
#if CONFIG_BLE_LOG_ENH_STAT_ENABLED
|
||||
ble_log_write_enh_stat();
|
||||
#endif /* CONFIG_BLE_LOG_ENH_STAT_ENABLED */
|
||||
}
|
||||
}
|
||||
|
||||
/* INTERFACE */
|
||||
bool ble_log_rt_init(void)
|
||||
{
|
||||
if (rt_inited) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/* CRITICAL:
|
||||
* Queue must be initialized before creating task */
|
||||
rt_queue_handle = xQueueCreate(BLE_LOG_LBM_CNT, sizeof(ble_log_prph_trans_t *));
|
||||
if (!rt_queue_handle) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* Initialize task */
|
||||
if (xTaskCreate(ble_log_rt_task, "ble_log", BLE_LOG_TASK_STACK_SIZE, NULL,
|
||||
BLE_LOG_TASK_PRIO, &rt_task_handle) != pdTRUE) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
rt_inited = true;
|
||||
#if CONFIG_BLE_LOG_TS_ENABLED
|
||||
rt_ts_enabled = false;
|
||||
#endif /* CONFIG_BLE_LOG_TS_ENABLED */
|
||||
return true;
|
||||
|
||||
exit:
|
||||
ble_log_rt_deinit();
|
||||
return false;
|
||||
}
|
||||
|
||||
void ble_log_rt_deinit(void)
|
||||
{
|
||||
rt_inited = false;
|
||||
#if CONFIG_BLE_LOG_TS_ENABLED
|
||||
rt_ts_enabled = false;
|
||||
#endif /* CONFIG_BLE_LOG_TS_ENABLED */
|
||||
|
||||
/* CRITICAL:
|
||||
* Task must be deinitialized before deinitializing queue */
|
||||
if (rt_task_handle) {
|
||||
vTaskDelete(rt_task_handle);
|
||||
rt_task_handle = NULL;
|
||||
}
|
||||
|
||||
/* Release task queue */
|
||||
if (rt_queue_handle) {
|
||||
vQueueDelete(rt_queue_handle);
|
||||
rt_queue_handle = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
BLE_LOG_IRAM_ATTR void ble_log_rt_queue_trans(ble_log_prph_trans_t **trans)
|
||||
{
|
||||
(*trans)->prph_owned = true;
|
||||
if (BLE_LOG_IN_ISR()) {
|
||||
xQueueSendFromISR(rt_queue_handle, trans, NULL);
|
||||
} else {
|
||||
xQueueSend(rt_queue_handle, trans, portMAX_DELAY);
|
||||
}
|
||||
}
|
||||
|
||||
#if CONFIG_BLE_LOG_TS_ENABLED
|
||||
bool ble_log_sync_enable(bool enable)
|
||||
{
|
||||
if (!rt_inited) {
|
||||
return false;
|
||||
}
|
||||
rt_ts_enabled = enable;
|
||||
return true;
|
||||
}
|
||||
#endif /* CONFIG_BLE_LOG_TS_ENABLED */
|
||||
@@ -1,75 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
/* ----------------------------------- */
|
||||
/* BLE Log - Timestamp Synchronization */
|
||||
/* ----------------------------------- */
|
||||
|
||||
/* INCLUDE */
|
||||
#include "ble_log_ts.h"
|
||||
|
||||
/* VARIABLE */
|
||||
BLE_LOG_STATIC bool ts_inited = false;
|
||||
BLE_LOG_STATIC ble_log_ts_info_t *ts_info = NULL;
|
||||
|
||||
/* INTERFACE */
|
||||
bool ble_log_ts_init(void)
|
||||
{
|
||||
if (ts_inited) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Initialize toggle IO */
|
||||
gpio_config_t sync_io_conf = {
|
||||
.intr_type = GPIO_INTR_DISABLE,
|
||||
.mode = GPIO_MODE_OUTPUT,
|
||||
.pin_bit_mask = BIT(CONFIG_BLE_LOG_SYNC_IO_NUM),
|
||||
};
|
||||
if (gpio_config(&sync_io_conf) != ESP_OK) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* Initialize sync data */
|
||||
ts_info = (ble_log_ts_info_t *)BLE_LOG_MALLOC(sizeof(ble_log_ts_info_t));
|
||||
if (!ts_info) {
|
||||
goto exit;
|
||||
}
|
||||
BLE_LOG_MEMSET(ts_info, 0, sizeof(ble_log_ts_info_t));
|
||||
ts_info->int_src_code = BLE_LOG_INT_SRC_TS;
|
||||
|
||||
ts_inited = true;
|
||||
return true;
|
||||
|
||||
exit:
|
||||
ble_log_ts_deinit();
|
||||
return false;
|
||||
}
|
||||
|
||||
void ble_log_ts_deinit(void)
|
||||
{
|
||||
ts_inited = false;
|
||||
|
||||
/* Release sync data */
|
||||
if (ts_info) {
|
||||
BLE_LOG_FREE(ts_info);
|
||||
ts_info = NULL;
|
||||
}
|
||||
|
||||
/* Release toggle IO */
|
||||
gpio_reset_pin(CONFIG_BLE_LOG_SYNC_IO_NUM);
|
||||
}
|
||||
|
||||
void ble_log_ts_info_update(ble_log_ts_info_t **info)
|
||||
{
|
||||
BLE_LOG_ENTER_CRITICAL();
|
||||
ts_info->io_level = !ts_info->io_level;
|
||||
gpio_set_level(CONFIG_BLE_LOG_SYNC_IO_NUM, ts_info->io_level);
|
||||
ts_info->lc_ts = BLE_LOG_GET_LC_TS;
|
||||
ts_info->esp_ts = esp_timer_get_time();
|
||||
ts_info->os_ts = pdTICKS_TO_MS(xTaskGetTickCountFromISR());
|
||||
BLE_LOG_EXIT_CRITICAL();
|
||||
|
||||
*info = ts_info;
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/* ----------------- */
|
||||
/* BLE Log - Utility */
|
||||
/* ----------------- */
|
||||
|
||||
/* INCLUDE */
|
||||
#include "ble_log_util.h"
|
||||
|
||||
/* VARIABLE */
|
||||
#ifndef UNIT_TEST
|
||||
portMUX_TYPE ble_log_spin_lock = portMUX_INITIALIZER_UNLOCKED;
|
||||
#endif /* !UNIT_TEST */
|
||||
|
||||
/* INTERNAL INTERFACE */
|
||||
BLE_LOG_IRAM_ATTR uint32_t ble_log_fast_checksum(const uint8_t *data, size_t len)
|
||||
{
|
||||
uint32_t sum = 0;
|
||||
size_t i = 0;
|
||||
|
||||
/* Step 1: Sum up until 4-byte aligned */
|
||||
while (((uintptr_t)(data + i) & 0x3) && (i < len)) {
|
||||
sum += data[i++];
|
||||
}
|
||||
|
||||
/* Step 2: Sum up 4-byte aligned blocks */
|
||||
const uint32_t *p32 = (const uint32_t *)(data + i);
|
||||
size_t blocks = (len - i) / 4;
|
||||
for (size_t b = 0; b < blocks; b++) {
|
||||
uint32_t v = p32[b];
|
||||
sum += (v & 0xFF)
|
||||
+ ((v >> 8) & 0xFF)
|
||||
+ ((v >> 16) & 0xFF)
|
||||
+ ((v >> 24) & 0xFF);
|
||||
}
|
||||
i += blocks * 4;
|
||||
|
||||
/* Step 3: Sum up remaining bytes */
|
||||
while (i < len) {
|
||||
sum += data[i++];
|
||||
}
|
||||
|
||||
return sum;
|
||||
}
|
||||
@@ -1,176 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#ifndef __BLE_LOG_LBM_H__
|
||||
#define __BLE_LOG_LBM_H__
|
||||
|
||||
/* --------------------------------------- */
|
||||
/* BLE Log - Log Buffer Management */
|
||||
/* --------------------------------------- */
|
||||
|
||||
/* ---------------- */
|
||||
/* Includes */
|
||||
/* ---------------- */
|
||||
#include "ble_log_prph.h"
|
||||
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/semphr.h"
|
||||
|
||||
/* ------------------------- */
|
||||
/* Log Frame Defines */
|
||||
/* ------------------------- */
|
||||
typedef struct {
|
||||
uint16_t length;
|
||||
uint32_t frame_meta;
|
||||
} __attribute__((packed)) ble_log_frame_head_t;
|
||||
|
||||
#define BLE_LOG_FRAME_HEAD_LEN (sizeof(ble_log_frame_head_t))
|
||||
#define BLE_LOG_FRAME_TAIL_LEN (sizeof(uint32_t))
|
||||
#define BLE_LOG_FRAME_OVERHEAD (BLE_LOG_FRAME_HEAD_LEN + BLE_LOG_FRAME_TAIL_LEN)
|
||||
#define BLE_LOG_MAKE_FRAME_META(src_code, sn) ((src_code & 0xFF) | (sn << 8))
|
||||
|
||||
/* ---------------------------------- */
|
||||
/* Log Buffer Manager Defines */
|
||||
/* ---------------------------------- */
|
||||
typedef enum {
|
||||
BLE_LOG_LBM_LOCK_NONE,
|
||||
BLE_LOG_LBM_LOCK_SPIN,
|
||||
BLE_LOG_LBM_LOCK_ATOMIC,
|
||||
BLE_LOG_LBM_LOCK_MUTEX,
|
||||
} ble_log_lbm_lock_t;
|
||||
|
||||
typedef struct {
|
||||
int trans_idx;
|
||||
ble_log_prph_trans_t *trans[BLE_LOG_TRANS_PING_PONG_BUF_CNT];
|
||||
ble_log_lbm_lock_t lock_type;
|
||||
union {
|
||||
/* BLE_LOG_LBM_LOCK_NONE */
|
||||
void *none;
|
||||
/* BLE_LOG_LBM_LOCK_SPIN */
|
||||
portMUX_TYPE spin_lock;
|
||||
/* BLE_LOG_LBM_LOCK_ATOMIC */
|
||||
volatile bool atomic_lock;
|
||||
/* BLE_LOG_LBM_LOCK_MUTEX */
|
||||
SemaphoreHandle_t mutex;
|
||||
};
|
||||
} ble_log_lbm_t;
|
||||
|
||||
/* --------------------------------------- */
|
||||
/* Log Buffer Manager Pool Defines */
|
||||
/* --------------------------------------- */
|
||||
enum {
|
||||
#if CONFIG_BLE_LOG_LL_ENABLED
|
||||
BLE_LOG_LBM_LL_TASK,
|
||||
BLE_LOG_LBM_LL_HCI,
|
||||
#endif /* CONFIG_BLE_LOG_LL_ENABLED */
|
||||
BLE_LOG_LBM_LL_MAX,
|
||||
};
|
||||
|
||||
enum {
|
||||
BLE_LOG_LBM_SPIN_TASK = 0,
|
||||
BLE_LOG_LBM_SPIN_ISR,
|
||||
BLE_LOG_LBM_SPIN_MAX,
|
||||
};
|
||||
|
||||
#define BLE_LOG_LBM_ATOMIC_TASK_CNT CONFIG_BLE_LOG_LBM_ATOMIC_LOCK_TASK_CNT
|
||||
#define BLE_LOG_LBM_ATOMIC_ISR_CNT CONFIG_BLE_LOG_LBM_ATOMIC_LOCK_ISR_CNT
|
||||
#define BLE_LOG_LBM_ATOMIC_CNT (BLE_LOG_LBM_ATOMIC_TASK_CNT +\
|
||||
BLE_LOG_LBM_ATOMIC_ISR_CNT)
|
||||
#define BLE_LOG_LBM_COMMON_CNT (BLE_LOG_LBM_ATOMIC_CNT + BLE_LOG_LBM_SPIN_MAX)
|
||||
#define BLE_LOG_LBM_CNT (BLE_LOG_LBM_COMMON_CNT + BLE_LOG_LBM_LL_MAX)
|
||||
#define BLE_LOG_TRANS_CNT (BLE_LOG_LBM_CNT * BLE_LOG_TRANS_PING_PONG_BUF_CNT)
|
||||
|
||||
/* ------------------------------------------ */
|
||||
/* Log Buffer Manager Context Defines */
|
||||
/* ------------------------------------------ */
|
||||
typedef struct {
|
||||
union {
|
||||
ble_log_lbm_t lbm_pool[BLE_LOG_LBM_CNT];
|
||||
struct {
|
||||
union {
|
||||
ble_log_lbm_t lbm_common_pool[BLE_LOG_LBM_COMMON_CNT];
|
||||
struct {
|
||||
union {
|
||||
ble_log_lbm_t spin_pool[BLE_LOG_LBM_SPIN_MAX];
|
||||
struct {
|
||||
ble_log_lbm_t spin_task;
|
||||
ble_log_lbm_t spin_isr;
|
||||
};
|
||||
};
|
||||
union {
|
||||
ble_log_lbm_t atomic_pool[BLE_LOG_LBM_ATOMIC_CNT];
|
||||
struct {
|
||||
ble_log_lbm_t atomic_pool_task[BLE_LOG_LBM_ATOMIC_TASK_CNT];
|
||||
ble_log_lbm_t atomic_pool_isr[BLE_LOG_LBM_ATOMIC_ISR_CNT];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
union {
|
||||
ble_log_lbm_t lbm_ll_pool[BLE_LOG_LBM_LL_MAX];
|
||||
#if CONFIG_BLE_LOG_LL_ENABLED
|
||||
struct {
|
||||
ble_log_lbm_t lbm_ll_task;
|
||||
ble_log_lbm_t lbm_ll_hci;
|
||||
};
|
||||
#endif /* CONFIG_BLE_LOG_LL_ENABLED */
|
||||
};
|
||||
};
|
||||
};
|
||||
} ble_log_lbm_ctx_t;
|
||||
|
||||
/* ---------------------------------------- */
|
||||
/* Enhanced Statistics Data Defines */
|
||||
/* ---------------------------------------- */
|
||||
#if CONFIG_BLE_LOG_ENH_STAT_ENABLED
|
||||
typedef struct {
|
||||
uint8_t int_src_code;
|
||||
uint8_t src_code;
|
||||
uint32_t written_frame_cnt;
|
||||
uint32_t lost_frame_cnt;
|
||||
uint32_t written_bytes_cnt;
|
||||
uint32_t lost_bytes_cnt;
|
||||
} __attribute__((packed)) ble_log_enh_stat_t;
|
||||
#endif /* CONFIG_BLE_LOG_ENH_STAT_ENABLED */
|
||||
|
||||
/* -------------------------------------- */
|
||||
/* Log Statistics Manager Context */
|
||||
/* -------------------------------------- */
|
||||
typedef struct {
|
||||
uint32_t frame_sn;
|
||||
#if CONFIG_BLE_LOG_ENH_STAT_ENABLED
|
||||
ble_log_enh_stat_t enh_stat;
|
||||
#endif /* CONFIG_BLE_LOG_ENH_STAT_ENABLED */
|
||||
} ble_log_stat_mgr_t;
|
||||
|
||||
#define BLE_LOG_GET_FRAME_SN(VAR) __atomic_fetch_add(VAR, 1, __ATOMIC_RELAXED)
|
||||
|
||||
/* -------------------------- */
|
||||
/* Link Layer Defines */
|
||||
/* -------------------------- */
|
||||
#if CONFIG_BLE_LOG_LL_ENABLED
|
||||
enum {
|
||||
BLE_LOG_LL_FLAG_CONTINUE = 0,
|
||||
BLE_LOG_LL_FLAG_END,
|
||||
BLE_LOG_LL_FLAG_TASK,
|
||||
BLE_LOG_LL_FLAG_ISR,
|
||||
BLE_LOG_LL_FLAG_HCI,
|
||||
BLE_LOG_LL_FLAG_RAW,
|
||||
BLE_LOG_LL_FLAG_HCI_UPSTREAM,
|
||||
};
|
||||
#endif /* CONFIG_BLE_LOG_LL_ENABLED */
|
||||
|
||||
/* --------------------------- */
|
||||
/* Internal Interfaces */
|
||||
/* --------------------------- */
|
||||
bool ble_log_lbm_init(void);
|
||||
void ble_log_lbm_deinit(void);
|
||||
ble_log_prph_trans_t **ble_log_lbm_get_trans(ble_log_lbm_t *lbm, size_t log_len);
|
||||
void ble_log_lbm_enable(bool enable);
|
||||
#if CONFIG_BLE_LOG_ENH_STAT_ENABLED
|
||||
void ble_log_write_enh_stat(void);
|
||||
#endif /* CONFIG_BLE_LOG_ENH_STAT_ENABLED */
|
||||
|
||||
#endif /* __BLE_LOG_LBM_H__ */
|
||||
@@ -1,37 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#ifndef __BLE_LOG_PRPH_H__
|
||||
#define __BLE_LOG_PRPH_H__
|
||||
|
||||
/* ------------------------------ */
|
||||
/* BLE Log - Peripheral Interface */
|
||||
/* ------------------------------ */
|
||||
|
||||
/* INCLUDE */
|
||||
#include "ble_log_util.h"
|
||||
|
||||
/* TYPEDEF */
|
||||
typedef struct {
|
||||
volatile bool prph_owned;
|
||||
uint8_t *buf;
|
||||
uint16_t size;
|
||||
uint16_t pos;
|
||||
|
||||
/* Peripheral implementation specific context */
|
||||
void *ctx;
|
||||
} ble_log_prph_trans_t;
|
||||
|
||||
#define BLE_LOG_TRANS_FREE_SPACE(trans) (trans->size - trans->pos)
|
||||
#define BLE_LOG_TRANS_PING_PONG_BUF_CNT (2)
|
||||
|
||||
/* INTERFACE */
|
||||
bool ble_log_prph_init(size_t trans_cnt);
|
||||
void ble_log_prph_deinit(void);
|
||||
bool ble_log_prph_trans_init(ble_log_prph_trans_t **trans, size_t trans_size);
|
||||
void ble_log_prph_trans_deinit(ble_log_prph_trans_t **trans);
|
||||
void ble_log_prph_send_trans(ble_log_prph_trans_t *trans);
|
||||
|
||||
#endif /* __BLE_LOG_PRPH_H__ */
|
||||
@@ -1,32 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#ifndef __BLE_LOG_RT_H__
|
||||
#define __BLE_LOG_RT_H__
|
||||
|
||||
/* ----------------- */
|
||||
/* BLE Log - Runtime */
|
||||
/* ----------------- */
|
||||
|
||||
/* INCLUDE */
|
||||
#include "ble_log_prph.h"
|
||||
#include "ble_log_ts.h"
|
||||
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/queue.h"
|
||||
#include "esp_task.h"
|
||||
|
||||
/* MACRO */
|
||||
#define BLE_LOG_TASK_PRIO (ESP_TASK_PRIO_MAX - 1)
|
||||
#define BLE_LOG_TASK_STACK_SIZE (1024)
|
||||
#define BLE_LOG_TASK_HOOK_TIMEOUT_MS (1000)
|
||||
|
||||
/* INTERFACE */
|
||||
bool ble_log_rt_init();
|
||||
void ble_log_rt_deinit(void);
|
||||
void ble_log_rt_queue_trans(ble_log_prph_trans_t **trans);
|
||||
|
||||
#endif /* __BLE_LOG_RT_H__ */
|
||||
@@ -1,57 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#ifndef __BLE_LOG_TS_H__
|
||||
#define __BLE_LOG_TS_H__
|
||||
|
||||
/* ----------------------------------- */
|
||||
/* BLE Log - Timestamp Synchronization */
|
||||
/* ----------------------------------- */
|
||||
|
||||
/* INCLUDE */
|
||||
#include "ble_log_util.h"
|
||||
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "esp_timer.h"
|
||||
#include "driver/gpio.h"
|
||||
|
||||
/* MACRO */
|
||||
#if CONFIG_BLE_LOG_LL_ENABLED
|
||||
/* ESP BLE Controller Gen 2 */
|
||||
#if defined(CONFIG_IDF_TARGET_ESP32H2) || defined(CONFIG_IDF_TARGET_ESP32C6) || defined(CONFIG_IDF_TARGET_ESP32C5) ||\
|
||||
defined(CONFIG_IDF_TARGET_ESP32C61) || defined(CONFIG_IDF_TARGET_ESP32H21) || defined(CONFIG_IDF_TARGET_ESP32H4)
|
||||
extern uint32_t r_ble_lll_timer_current_tick_get(void);
|
||||
#define BLE_LOG_GET_LC_TS r_ble_lll_timer_current_tick_get()
|
||||
/* ESP BLE Controller Gen 1 */
|
||||
#elif defined(CONFIG_IDF_TARGET_ESP32C2)
|
||||
extern uint32_t r_os_cputime_get32(void);
|
||||
#define BLE_LOG_GET_LC_TS r_os_cputime_get32()
|
||||
/* Legacy BLE Controller (Wait for support) */
|
||||
// #elif defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32S3)
|
||||
// extern uint32_t lld_read_clock_us(void);
|
||||
// #define BLE_LOG_GET_LC_TS lld_read_clock_us()
|
||||
#else /* Other targets */
|
||||
#define BLE_LOG_GET_LC_TS 0
|
||||
#endif /* BLE targets */
|
||||
#else /* !CONFIG_BLE_LOG_LL_ENABLED */
|
||||
#define BLE_LOG_GET_LC_TS 0
|
||||
#endif /* CONFIG_BLE_LOG_LL_ENABLED */
|
||||
|
||||
/* TYPEDEF */
|
||||
typedef struct {
|
||||
uint8_t int_src_code;
|
||||
uint8_t io_level;
|
||||
uint32_t lc_ts;
|
||||
uint32_t esp_ts;
|
||||
uint32_t os_ts;
|
||||
} __attribute__((packed)) ble_log_ts_info_t;
|
||||
|
||||
/* INTERFACE */
|
||||
bool ble_log_ts_init(void);
|
||||
void ble_log_ts_deinit(void);
|
||||
void ble_log_ts_info_update(ble_log_ts_info_t **ts_info);
|
||||
|
||||
#endif /* __BLE_LOG_TS_H__ */
|
||||
@@ -1,153 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#ifndef __BLE_LOG_UTIL_H__
|
||||
#define __BLE_LOG_UTIL_H__
|
||||
|
||||
/* ----------------- */
|
||||
/* BLE Log - Utility */
|
||||
/* ----------------- */
|
||||
|
||||
/* INCLUDE */
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "esp_bit_defs.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
|
||||
#ifndef UNIT_TEST
|
||||
#include "esp_heap_caps.h"
|
||||
#include "esp_rom_uart.h"
|
||||
#endif /* !UNIT_TEST */
|
||||
|
||||
/* MACRO */
|
||||
/* Unit test */
|
||||
#ifndef UNIT_TEST
|
||||
|
||||
/* Reference counting macros */
|
||||
#define BLE_LOG_REF_COUNT_ACQUIRE(VAR) __atomic_fetch_add(VAR, 1, __ATOMIC_ACQUIRE)
|
||||
#define BLE_LOG_REF_COUNT_RELEASE(VAR) __atomic_fetch_sub(VAR, 1, __ATOMIC_RELEASE)
|
||||
|
||||
/* Specifier */
|
||||
#define BLE_LOG_STATIC static
|
||||
#define BLE_LOG_INLINE inline
|
||||
|
||||
/* Section */
|
||||
#define BLE_LOG_IRAM_ATTR IRAM_ATTR
|
||||
|
||||
/* Memory operation */
|
||||
#define BLE_LOG_MEM_CAP (MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT | MALLOC_CAP_DMA)
|
||||
#define BLE_LOG_MALLOC(size) heap_caps_malloc(size, BLE_LOG_MEM_CAP)
|
||||
#define BLE_LOG_FREE(ptr) heap_caps_free(ptr)
|
||||
#define BLE_LOG_MEMCPY(dst, src, len) memcpy(dst, src, len)
|
||||
#define BLE_LOG_MEMSET(ptr, value, len) memset(ptr, value, len)
|
||||
|
||||
/* Critical section wrapper */
|
||||
extern portMUX_TYPE ble_log_spin_lock;
|
||||
#define BLE_LOG_ENTER_CRITICAL() portENTER_CRITICAL_SAFE(&ble_log_spin_lock);
|
||||
#define BLE_LOG_EXIT_CRITICAL() portEXIT_CRITICAL_SAFE(&ble_log_spin_lock);
|
||||
|
||||
#define BLE_LOG_ACQUIRE_SPIN_LOCK(spin_lock) portENTER_CRITICAL_SAFE(spin_lock)
|
||||
#define BLE_LOG_RELEASE_SPIN_LOCK(spin_lock) portEXIT_CRITICAL_SAFE(spin_lock)
|
||||
|
||||
#define BLE_LOG_IN_ISR() xPortInIsrContext()
|
||||
#define BLE_LOG_CONSOLE esp_rom_printf
|
||||
#define BLE_LOG_ASSERT(expr) assert(expr)
|
||||
|
||||
extern void esp_panic_handler_feed_wdts(void);
|
||||
#define BLE_LOG_FEED_WDT() esp_panic_handler_feed_wdts()
|
||||
|
||||
/* INLINE */
|
||||
BLE_LOG_IRAM_ATTR static inline
|
||||
bool ble_log_cas_acquire(volatile bool *cas_lock)
|
||||
{
|
||||
bool expected = false;
|
||||
return __atomic_compare_exchange_n(
|
||||
cas_lock, &expected, true, false, __ATOMIC_ACQUIRE, __ATOMIC_RELAXED
|
||||
);
|
||||
}
|
||||
|
||||
BLE_LOG_IRAM_ATTR static inline
|
||||
void ble_log_cas_release(volatile bool *cas_lock)
|
||||
{
|
||||
__atomic_store_n(cas_lock, false, __ATOMIC_RELEASE);
|
||||
}
|
||||
|
||||
#else /* UNIT_TEST */
|
||||
|
||||
/* Reference counting macros */
|
||||
#define BLE_LOG_REF_COUNT_ACQUIRE(VAR) (*VAR)++
|
||||
#define BLE_LOG_REF_COUNT_RELEASE(VAR) (*VAR)--
|
||||
|
||||
/* Specifier*/
|
||||
#define BLE_LOG_STATIC
|
||||
#define BLE_LOG_INLINE
|
||||
|
||||
/* Section */
|
||||
#define BLE_LOG_IRAM_ATTR
|
||||
|
||||
/* Memory operation */
|
||||
void *mocked_malloc(size_t size);
|
||||
void mocked_free(void *ptr);
|
||||
void mocked_memcpy(void *dst, const void *src, size_t len);
|
||||
void mocked_memset(void *ptr, int value, size_t len);
|
||||
#define BLE_LOG_MALLOC(size) mocked_malloc(size)
|
||||
#define BLE_LOG_FREE(ptr) mocked_free(ptr)
|
||||
#define BLE_LOG_MEMCPY(dst, src, len) mocked_memcpy(dst, src, len)
|
||||
#define BLE_LOG_MEMSET(ptr, value, len) mocked_memset(ptr, value, len)
|
||||
|
||||
/* Critical section wrapper */
|
||||
void mocked_enter_critical(void);
|
||||
void mocked_exit_critical(void);
|
||||
#define BLE_LOG_ENTER_CRITICAL() mocked_enter_critical()
|
||||
#define BLE_LOG_EXIT_CRITICAL() mocked_exit_critical()
|
||||
|
||||
/* FreeRTOS API wrapper */
|
||||
bool mocked_in_isr(void);
|
||||
#define BLE_LOG_IN_ISR() mocked_in_isr()
|
||||
|
||||
/* Spin lock wrapper */
|
||||
void mocked_acquire_spin_lock(void *spin_lock);
|
||||
void mocked_release_spin_lock(void *spin_lock);
|
||||
#define BLE_LOG_ACQUIRE_SPIN_LOCK(spin_lock) mocked_acquire_spin_lock(spin_lock)
|
||||
#define BLE_LOG_RELEASE_SPIN_LOCK(spin_lock) mocked_release_spin_lock(spin_lock)
|
||||
|
||||
/* Printf wrapper */
|
||||
void mocked_printf(const char *fmt, ...);
|
||||
#define BLE_LOG_CONSOLE mocked_printf
|
||||
|
||||
/* Assert wrapper */
|
||||
void mocked_assert(bool expr);
|
||||
#define BLE_LOG_ASSERT(expr) mocked_assert(expr)
|
||||
|
||||
#define BLE_LOG_FEED_WDT()
|
||||
|
||||
bool ble_log_cas_acquire(volatile bool *cas_lock);
|
||||
void ble_log_cas_release(volatile bool *cas_lock);
|
||||
#endif /* UNIT_TEST */
|
||||
|
||||
#define BLE_LOG_VERSION (2)
|
||||
|
||||
/* TYPEDEF */
|
||||
typedef enum {
|
||||
BLE_LOG_INT_SRC_INIT_DONE,
|
||||
BLE_LOG_INT_SRC_TS,
|
||||
BLE_LOG_INT_SRC_ENH_STAT,
|
||||
BLE_LOG_INT_SRC_INFO,
|
||||
BLE_LOG_INT_SRC_FLUSH,
|
||||
BLE_LOG_INT_SRC_MAX,
|
||||
} ble_log_int_src_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t int_src_code;
|
||||
uint8_t version;
|
||||
} __attribute__((packed)) ble_log_info_t;
|
||||
|
||||
/* INTERFACE */
|
||||
uint32_t ble_log_fast_checksum(const uint8_t *data, size_t len);
|
||||
|
||||
#endif /* __BLE_LOG_UTIL_H__ */
|
||||
@@ -1,21 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#ifndef __BLE_LOG_PRPH_DUMMY_H__
|
||||
#define __BLE_LOG_PRPH_DUMMY_H__
|
||||
|
||||
/* ----------------------------------------------- */
|
||||
/* BLE Log - Peripheral-specific Transport - Dummy */
|
||||
/* ----------------------------------------------- */
|
||||
|
||||
/* INCLUDE */
|
||||
#include "ble_log_prph.h"
|
||||
|
||||
/* TYPEDEF */
|
||||
typedef struct {
|
||||
uint8_t *trans_buf;
|
||||
} ble_log_prph_trans_ctx_t;
|
||||
|
||||
#endif /* __BLE_LOG_PRPH_DUMMY_H__ */
|
||||
@@ -1,22 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#ifndef __BLE_LOG_PRPH_SPI_MASTER_DMA_H__
|
||||
#define __BLE_LOG_PRPH_SPI_MASTER_DMA_H__
|
||||
|
||||
/* ----------------------------------------------- */
|
||||
/* BLE Log - Peripheral Interface - SPI Master DMA */
|
||||
/* ----------------------------------------------- */
|
||||
|
||||
/* INCLUDE */
|
||||
#include "ble_log_prph.h"
|
||||
|
||||
#include <string.h>
|
||||
#include "driver/spi_master.h"
|
||||
|
||||
/* TYPEDEF */
|
||||
typedef spi_transaction_t ble_log_prph_trans_ctx_t;
|
||||
|
||||
#endif /* __BLE_LOG_PRPH_SPI_MASTER_DMA_H__ */
|
||||
@@ -1,32 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#ifndef __BLE_LOG_PRPH_UART_DMA_H__
|
||||
#define __BLE_LOG_PRPH_UART_DMA_H__
|
||||
|
||||
/* ----------------------------------------- */
|
||||
/* BLE Log - Peripheral Interface - UART DMA */
|
||||
/* ----------------------------------------- */
|
||||
|
||||
/* INCLUDE */
|
||||
#include "ble_log_prph.h"
|
||||
|
||||
#include "driver/uart.h"
|
||||
#include "driver/uhci.h"
|
||||
|
||||
/* MACRO */
|
||||
#if CONFIG_BLE_LOG_PRPH_UART_DMA_PORT == UART_NUM_0
|
||||
#define BLE_LOG_PRPH_UART_DMA_REDIR (1)
|
||||
#else
|
||||
#define BLE_LOG_PRPH_UART_DMA_REDIR (0)
|
||||
#endif /* CONFIG_BLE_LOG_PRPH_UART_DMA_PORT == UART_NUM_0 */
|
||||
|
||||
/* TYPEDEF */
|
||||
typedef struct {
|
||||
ble_log_prph_trans_t *trans;
|
||||
uint8_t trans_buf[0];
|
||||
} ble_log_prph_trans_ctx_t;
|
||||
|
||||
#endif /* __BLE_LOG_PRPH_UART_DMA_H__ */
|
||||
@@ -1,86 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
/* ----------------------------------------------- */
|
||||
/* BLE Log - Peripheral-specific Transport - Dummy */
|
||||
/* ----------------------------------------------- */
|
||||
|
||||
/* INCLUDE */
|
||||
#include "ble_log_prph_dummy.h"
|
||||
|
||||
/* INTERFACE */
|
||||
bool ble_log_prph_init(size_t trans_cnt)
|
||||
{
|
||||
(void)trans_cnt;
|
||||
return true;
|
||||
}
|
||||
|
||||
void ble_log_prph_deinit(void)
|
||||
{
|
||||
}
|
||||
|
||||
bool ble_log_prph_trans_init(ble_log_prph_trans_t **trans, size_t trans_size)
|
||||
{
|
||||
/* Validate inputs */
|
||||
if (!trans || !trans_size) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Initialize peripheral transport data */
|
||||
*trans = (ble_log_prph_trans_t *)BLE_LOG_MALLOC(sizeof(ble_log_prph_trans_t));
|
||||
if (!(*trans)) {
|
||||
goto exit;
|
||||
}
|
||||
BLE_LOG_MEMSET(*trans, 0, sizeof(ble_log_prph_trans_t));
|
||||
(*trans)->size = trans_size;
|
||||
|
||||
/* Initialize peripheral-specific transport context */
|
||||
ble_log_prph_trans_ctx_t *dummy_trans_ctx = (ble_log_prph_trans_ctx_t *)BLE_LOG_MALLOC(sizeof(ble_log_prph_trans_ctx_t));
|
||||
if (!dummy_trans_ctx) {
|
||||
goto exit;
|
||||
}
|
||||
BLE_LOG_MEMSET(dummy_trans_ctx, 0, sizeof(ble_log_prph_trans_ctx_t));
|
||||
(*trans)->ctx = (void *)dummy_trans_ctx;
|
||||
|
||||
/* Initialize log buffer */
|
||||
(*trans)->buf = (uint8_t *)BLE_LOG_MALLOC(trans_size);
|
||||
if (!(*trans)->buf) {
|
||||
goto exit;
|
||||
}
|
||||
BLE_LOG_MEMSET((*trans)->buf, 0, trans_size);
|
||||
dummy_trans_ctx->trans_buf = (*trans)->buf;
|
||||
return true;
|
||||
|
||||
exit:
|
||||
ble_log_prph_trans_deinit(trans);
|
||||
return false;
|
||||
}
|
||||
|
||||
void ble_log_prph_trans_deinit(ble_log_prph_trans_t **trans)
|
||||
{
|
||||
/* Validate inputs */
|
||||
if (!trans || !(*trans)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Release log buffer */
|
||||
if ((*trans)->buf) {
|
||||
BLE_LOG_FREE((*trans)->buf);
|
||||
}
|
||||
|
||||
/* Release peripheral-specific transport context */
|
||||
if ((*trans)->ctx) {
|
||||
BLE_LOG_FREE((*trans)->ctx);
|
||||
}
|
||||
|
||||
/* Release peripheral transport data */
|
||||
BLE_LOG_FREE(*trans);
|
||||
*trans = NULL;
|
||||
}
|
||||
|
||||
void ble_log_prph_send_trans(ble_log_prph_trans_t *trans)
|
||||
{
|
||||
(void)trans;
|
||||
}
|
||||
@@ -1,184 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
/* ----------------------------------------------- */
|
||||
/* BLE Log - Peripheral Interface - SPI Master DMA */
|
||||
/* ----------------------------------------------- */
|
||||
|
||||
/* INCLUDE */
|
||||
#include "ble_log_prph_spi_master_dma.h"
|
||||
|
||||
#include "esp_timer.h"
|
||||
|
||||
/* MACRO */
|
||||
#define BLE_LOG_SPI_BUS SPI2_HOST
|
||||
#define BLE_LOG_SPI_MAX_TRANSFER_SIZE (10240)
|
||||
#define BLE_LOG_SPI_TRANS_ITVL_MIN_US (30)
|
||||
|
||||
/* VARIABLE */
|
||||
BLE_LOG_STATIC bool prph_inited = false;
|
||||
BLE_LOG_STATIC spi_device_handle_t dev_handle = NULL;
|
||||
BLE_LOG_STATIC uint32_t last_tx_done_ts = 0;
|
||||
|
||||
/* PRIVATE FUNCTION DECLARATION */
|
||||
BLE_LOG_STATIC void spi_master_dma_tx_done_cb(spi_transaction_t *spi_trans);
|
||||
BLE_LOG_STATIC void spi_master_dma_pre_tx_cb(spi_transaction_t *spi_trans);
|
||||
|
||||
/* PRIVATE FUNCTION */
|
||||
BLE_LOG_IRAM_ATTR BLE_LOG_STATIC void spi_master_dma_tx_done_cb(spi_transaction_t *spi_trans)
|
||||
{
|
||||
/* SPI slave performance issue workaround */
|
||||
last_tx_done_ts = esp_timer_get_time();
|
||||
|
||||
/* Recycle transport */
|
||||
ble_log_prph_trans_t *trans = (ble_log_prph_trans_t *)(spi_trans->user);
|
||||
trans->pos = 0;
|
||||
trans->prph_owned = false;
|
||||
}
|
||||
|
||||
BLE_LOG_IRAM_ATTR BLE_LOG_STATIC void spi_master_dma_pre_tx_cb(spi_transaction_t *spi_trans)
|
||||
{
|
||||
/* SPI slave performance issue workaround */
|
||||
while ((esp_timer_get_time() - last_tx_done_ts) < BLE_LOG_SPI_TRANS_ITVL_MIN_US) {}
|
||||
}
|
||||
|
||||
/* INTERFACE */
|
||||
bool ble_log_prph_init(size_t trans_cnt)
|
||||
{
|
||||
/* Avoid double init */
|
||||
if (prph_inited) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/* SPI master initialization */
|
||||
spi_bus_config_t bus_config = {
|
||||
.miso_io_num = -1,
|
||||
.mosi_io_num = CONFIG_BLE_LOG_PRPH_SPI_MASTER_DMA_MOSI_IO_NUM,
|
||||
.sclk_io_num = CONFIG_BLE_LOG_PRPH_SPI_MASTER_DMA_SCLK_IO_NUM,
|
||||
.quadwp_io_num = -1,
|
||||
.quadhd_io_num = -1,
|
||||
.max_transfer_sz = BLE_LOG_SPI_MAX_TRANSFER_SIZE,
|
||||
#if CONFIG_SPI_MASTER_ISR_IN_IRAM
|
||||
.intr_flags = ESP_INTR_FLAG_IRAM
|
||||
#endif // CONFIG_SPI_MASTER_ISR_IN_IRAM
|
||||
};
|
||||
if (spi_bus_initialize(BLE_LOG_SPI_BUS, &bus_config, SPI_DMA_CH_AUTO) != ESP_OK) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
spi_device_interface_config_t dev_config = {
|
||||
.clock_speed_hz = SPI_MASTER_FREQ_20M,
|
||||
.mode = 0,
|
||||
.spics_io_num = CONFIG_BLE_LOG_PRPH_SPI_MASTER_DMA_CS_IO_NUM,
|
||||
.queue_size = trans_cnt,
|
||||
.post_cb = spi_master_dma_tx_done_cb,
|
||||
.pre_cb = spi_master_dma_pre_tx_cb,
|
||||
.flags = SPI_DEVICE_NO_RETURN_RESULT
|
||||
};
|
||||
if (spi_bus_add_device(BLE_LOG_SPI_BUS, &dev_config, &dev_handle) != ESP_OK) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* Initialization done */
|
||||
prph_inited = true;
|
||||
return true;
|
||||
|
||||
exit:
|
||||
ble_log_prph_deinit();
|
||||
return false;
|
||||
}
|
||||
|
||||
void ble_log_prph_deinit(void)
|
||||
{
|
||||
prph_inited = false;
|
||||
if (dev_handle) {
|
||||
/* Drain all queued transactions */
|
||||
if (spi_device_acquire_bus(dev_handle, portMAX_DELAY) == ESP_OK) {
|
||||
spi_device_release_bus(dev_handle);
|
||||
spi_bus_remove_device(dev_handle);
|
||||
dev_handle = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Note: We don't care if the bus has been inited or not */
|
||||
spi_bus_free(BLE_LOG_SPI_BUS);
|
||||
}
|
||||
|
||||
bool ble_log_prph_trans_init(ble_log_prph_trans_t **trans, size_t trans_size)
|
||||
{
|
||||
/* Validate inputs */
|
||||
if (!trans || !trans_size) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Initialize peripheral transport data */
|
||||
*trans = (ble_log_prph_trans_t *)BLE_LOG_MALLOC(sizeof(ble_log_prph_trans_t));
|
||||
if (!(*trans)) {
|
||||
goto exit;
|
||||
}
|
||||
BLE_LOG_MEMSET(*trans, 0, sizeof(ble_log_prph_trans_t));
|
||||
(*trans)->size = trans_size;
|
||||
|
||||
/* Initialize peripheral-specific transport context */
|
||||
ble_log_prph_trans_ctx_t *spi_trans_ctx = (ble_log_prph_trans_ctx_t *)BLE_LOG_MALLOC(sizeof(ble_log_prph_trans_ctx_t));
|
||||
if (!spi_trans_ctx) {
|
||||
goto exit;
|
||||
}
|
||||
BLE_LOG_MEMSET(spi_trans_ctx, 0, sizeof(ble_log_prph_trans_ctx_t));
|
||||
spi_trans_ctx->user = (void *)(*trans);
|
||||
(*trans)->ctx = (void *)spi_trans_ctx;
|
||||
|
||||
/* Initialize log buffer */
|
||||
(*trans)->buf = (uint8_t *)BLE_LOG_MALLOC(trans_size);
|
||||
if (!(*trans)->buf) {
|
||||
goto exit;
|
||||
}
|
||||
BLE_LOG_MEMSET((*trans)->buf, 0, trans_size);
|
||||
spi_trans_ctx->tx_buffer = (const void *)(*trans)->buf;
|
||||
return true;
|
||||
|
||||
exit:
|
||||
ble_log_prph_trans_deinit(trans);
|
||||
return false;
|
||||
}
|
||||
|
||||
void ble_log_prph_trans_deinit(ble_log_prph_trans_t **trans)
|
||||
{
|
||||
/* Validate inputs */
|
||||
if (!trans || !(*trans)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Release log buffer */
|
||||
if ((*trans)->buf) {
|
||||
BLE_LOG_FREE((*trans)->buf);
|
||||
}
|
||||
|
||||
/* Release peripheral-specific transport context */
|
||||
if ((*trans)->ctx) {
|
||||
BLE_LOG_FREE((*trans)->ctx);
|
||||
}
|
||||
|
||||
/* Release peripheral transport data */
|
||||
BLE_LOG_FREE(*trans);
|
||||
*trans = NULL;
|
||||
}
|
||||
|
||||
/* CRITICAL:
|
||||
* This function is designed to be called by BLE Log Runtime only,
|
||||
* function call from any other submodules is not allowed */
|
||||
BLE_LOG_IRAM_ATTR void ble_log_prph_send_trans(ble_log_prph_trans_t *trans)
|
||||
{
|
||||
spi_transaction_t *spi_trans = (spi_transaction_t *)trans->ctx;
|
||||
|
||||
/* CRITICAL:
|
||||
* Bytes to bits length conversion is required for tx, and rxlength must be
|
||||
* cleared regardless of whether it is used for rx as per SPI master driver */
|
||||
spi_trans->length = (trans->pos << 3);
|
||||
spi_trans->rxlength = 0;
|
||||
if (spi_device_queue_trans(dev_handle, spi_trans, 0) != ESP_OK) {
|
||||
trans->prph_owned = false;
|
||||
}
|
||||
}
|
||||
@@ -1,329 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/* ----------------------------------------- */
|
||||
/* BLE Log - Peripheral Interface - UART DMA */
|
||||
/* ----------------------------------------- */
|
||||
|
||||
/* INCLUDE */
|
||||
#include "ble_log_prph_uart_dma.h"
|
||||
|
||||
#if BLE_LOG_PRPH_UART_DMA_REDIR
|
||||
#include "ble_log.h"
|
||||
#include "ble_log_rt.h"
|
||||
#include "ble_log_lbm.h"
|
||||
|
||||
#include "esp_timer.h"
|
||||
#include "driver/uart.h"
|
||||
#include "driver/uart_vfs.h"
|
||||
#endif /* BLE_LOG_PRPH_UART_DMA_REDIR */
|
||||
|
||||
/* MACRO */
|
||||
#define BLE_LOG_UART_MAX_TRANSFER_SIZE (10240)
|
||||
#define BLE_LOG_UART_RX_BUF_SIZE (256)
|
||||
#define BLE_LOG_UART_DMA_BURST_SIZE (32)
|
||||
#if BLE_LOG_PRPH_UART_DMA_REDIR
|
||||
#define BLE_LOG_UART_REDIR_BUF_SIZE (512)
|
||||
#define BLE_LOG_UART_REDIR_FLUSH_TIMEOUT (100)
|
||||
#endif /* BLE_LOG_PRPH_UART_DMA_REDIR */
|
||||
|
||||
/* VARIABLE */
|
||||
BLE_LOG_STATIC bool prph_inited = false;
|
||||
BLE_LOG_STATIC uhci_controller_handle_t dev_handle = NULL;
|
||||
#if BLE_LOG_PRPH_UART_DMA_REDIR
|
||||
BLE_LOG_STATIC bool uart_driver_inited = false;
|
||||
BLE_LOG_STATIC ble_log_lbm_t *redir_lbm = NULL;
|
||||
BLE_LOG_STATIC uint32_t redir_last_write_ts = 0;
|
||||
BLE_LOG_STATIC esp_timer_handle_t redir_flush_timer = NULL;
|
||||
#endif /* BLE_LOG_PRPH_UART_DMA_REDIR */
|
||||
|
||||
/* PRIVATE FUNCTION DECLARATION */
|
||||
BLE_LOG_STATIC bool uart_dma_tx_done_cb(
|
||||
uhci_controller_handle_t uhci_ctrl, const uhci_tx_done_event_data_t *edata, void *user_ctx);
|
||||
|
||||
/* PRIVATE FUNCTION */
|
||||
BLE_LOG_IRAM_ATTR BLE_LOG_STATIC bool uart_dma_tx_done_cb(
|
||||
uhci_controller_handle_t uhci_ctrl, const uhci_tx_done_event_data_t *edata, void *user_ctx)
|
||||
{
|
||||
/* Unused arguments */
|
||||
(void)uhci_ctrl;
|
||||
(void)user_ctx;
|
||||
|
||||
/* Recycle transport */
|
||||
ble_log_prph_trans_ctx_t *uart_trans_ctx = (ble_log_prph_trans_ctx_t *)(
|
||||
(uint8_t *)edata->buffer - sizeof(ble_log_prph_trans_ctx_t)
|
||||
);
|
||||
ble_log_prph_trans_t *trans = uart_trans_ctx->trans;
|
||||
trans->pos = 0;
|
||||
trans->prph_owned = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
#if BLE_LOG_PRPH_UART_DMA_REDIR
|
||||
BLE_LOG_IRAM_ATTR BLE_LOG_STATIC void esp_timer_cb_flush_log(void)
|
||||
{
|
||||
uint32_t os_ts = pdTICKS_TO_MS(xTaskGetTickCount());
|
||||
if ((os_ts - redir_last_write_ts) > BLE_LOG_UART_REDIR_FLUSH_TIMEOUT) {
|
||||
xSemaphoreTake(redir_lbm->mutex, portMAX_DELAY);
|
||||
int trans_idx = redir_lbm->trans_idx;
|
||||
for (int i = 0; i < BLE_LOG_TRANS_PING_PONG_BUF_CNT; i++) {
|
||||
ble_log_prph_trans_t **trans = &(redir_lbm->trans[trans_idx]);
|
||||
if (!(*trans)->prph_owned && (*trans)->pos) {
|
||||
ble_log_rt_queue_trans(trans);
|
||||
}
|
||||
trans_idx = !trans_idx;
|
||||
}
|
||||
xSemaphoreGive(redir_lbm->mutex);
|
||||
}
|
||||
}
|
||||
#endif /* BLE_LOG_PRPH_UART_DMA_REDIR */
|
||||
|
||||
/* INTERFACE */
|
||||
bool ble_log_prph_init(size_t trans_cnt)
|
||||
{
|
||||
/* Avoid double init */
|
||||
if (prph_inited) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Initialize UART */
|
||||
uart_config_t uart_config = {
|
||||
.baud_rate = CONFIG_BLE_LOG_PRPH_UART_DMA_BAUD_RATE,
|
||||
.data_bits = UART_DATA_8_BITS,
|
||||
.parity = UART_PARITY_DISABLE,
|
||||
.stop_bits = UART_STOP_BITS_1,
|
||||
};
|
||||
if ((uart_param_config(CONFIG_BLE_LOG_PRPH_UART_DMA_PORT, &uart_config) != ESP_OK) ||
|
||||
(uart_set_pin(CONFIG_BLE_LOG_PRPH_UART_DMA_PORT,
|
||||
CONFIG_BLE_LOG_PRPH_UART_DMA_TX_IO_NUM, -1, -1, -1) != ESP_OK)) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* Initialize UHCI */
|
||||
uhci_controller_config_t uhci_config = {
|
||||
.uart_port = CONFIG_BLE_LOG_PRPH_UART_DMA_PORT,
|
||||
.tx_trans_queue_depth = trans_cnt,
|
||||
.max_receive_internal_mem = BLE_LOG_UART_RX_BUF_SIZE,
|
||||
.max_transmit_size = BLE_LOG_UART_MAX_TRANSFER_SIZE,
|
||||
.dma_burst_size = BLE_LOG_UART_DMA_BURST_SIZE,
|
||||
.rx_eof_flags.idle_eof = 1,
|
||||
};
|
||||
uhci_event_callbacks_t uhci_cbs = {
|
||||
.on_tx_trans_done = uart_dma_tx_done_cb,
|
||||
};
|
||||
if ((uhci_new_controller(&uhci_config, &dev_handle) != ESP_OK) ||
|
||||
(uhci_register_event_callbacks(dev_handle, &uhci_cbs, NULL) != ESP_OK)) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* Redirection is required when utilizing UART port 0 */
|
||||
#if BLE_LOG_PRPH_UART_DMA_REDIR
|
||||
/* Initialize a dedicated LBM for redirection */
|
||||
redir_lbm = (ble_log_lbm_t *)BLE_LOG_MALLOC(sizeof(ble_log_lbm_t));
|
||||
if (!redir_lbm) {
|
||||
goto exit;
|
||||
}
|
||||
BLE_LOG_MEMSET(redir_lbm, 0, sizeof(ble_log_lbm_t));
|
||||
|
||||
/* Transport initialization */
|
||||
for (int i = 0; i < BLE_LOG_TRANS_PING_PONG_BUF_CNT; i++) {
|
||||
if (!ble_log_prph_trans_init(&(redir_lbm->trans[i]),
|
||||
BLE_LOG_UART_REDIR_BUF_SIZE)) {
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
|
||||
/* Mutex initilaization */
|
||||
redir_lbm->mutex = xSemaphoreCreateMutex();
|
||||
if (!redir_lbm->mutex) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* Initialize UART driver for redirection */
|
||||
if (!uart_is_driver_installed(UART_NUM_0)) {
|
||||
uart_driver_install(UART_NUM_0, BLE_LOG_UART_RX_BUF_SIZE, 0, 0, NULL, 0);
|
||||
uart_driver_inited = true;
|
||||
}
|
||||
uart_vfs_dev_use_driver(UART_NUM_0);
|
||||
|
||||
/* Initialize periodic flush timer */
|
||||
esp_timer_create_args_t timer_args = {
|
||||
.callback = (esp_timer_cb_t)esp_timer_cb_flush_log,
|
||||
.dispatch_method = ESP_TIMER_TASK,
|
||||
};
|
||||
if (esp_timer_create(&timer_args, &redir_flush_timer) != ESP_OK) {
|
||||
goto exit;
|
||||
}
|
||||
#endif /* BLE_LOG_PRPH_UART_DMA_REDIR */
|
||||
|
||||
prph_inited = true;
|
||||
#if BLE_LOG_PRPH_UART_DMA_REDIR
|
||||
esp_timer_start_periodic(redir_flush_timer, BLE_LOG_UART_REDIR_FLUSH_TIMEOUT);
|
||||
#endif /* BLE_LOG_PRPH_UART_DMA_REDIR */
|
||||
|
||||
return true;
|
||||
|
||||
exit:
|
||||
ble_log_prph_deinit();
|
||||
return false;
|
||||
}
|
||||
|
||||
void ble_log_prph_deinit(void)
|
||||
{
|
||||
prph_inited = false;
|
||||
|
||||
#if BLE_LOG_PRPH_UART_DMA_REDIR
|
||||
/* Release flush timer */
|
||||
if (redir_flush_timer) {
|
||||
esp_timer_stop(redir_flush_timer);
|
||||
esp_timer_delete(redir_flush_timer);
|
||||
redir_flush_timer = NULL;
|
||||
}
|
||||
|
||||
/* Delete UART driver if it's installed by current module */
|
||||
if (uart_driver_inited) {
|
||||
uart_driver_delete(UART_NUM_0);
|
||||
}
|
||||
|
||||
/* Release redirection LBM */
|
||||
if (redir_lbm) {
|
||||
/* Release mutex */
|
||||
if (redir_lbm->mutex) {
|
||||
xSemaphoreTake(redir_lbm->mutex, portMAX_DELAY);
|
||||
xSemaphoreGive(redir_lbm->mutex);
|
||||
vSemaphoreDelete(redir_lbm->mutex);
|
||||
}
|
||||
|
||||
/* Release transport */
|
||||
for (int i = 0; i < BLE_LOG_TRANS_PING_PONG_BUF_CNT; i++) {
|
||||
ble_log_prph_trans_deinit(&(redir_lbm->trans[i]));
|
||||
}
|
||||
|
||||
/* Release LBM */
|
||||
BLE_LOG_FREE(redir_lbm);
|
||||
redir_lbm = NULL;
|
||||
}
|
||||
#endif /* BLE_LOG_PRPH_UART_DMA_REDIR */
|
||||
|
||||
if (dev_handle) {
|
||||
uhci_wait_all_tx_transaction_done(dev_handle, portMAX_DELAY);
|
||||
uhci_del_controller(dev_handle);
|
||||
dev_handle = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
bool ble_log_prph_trans_init(ble_log_prph_trans_t **trans, size_t trans_size)
|
||||
{
|
||||
/* Validate inputs */
|
||||
if (!trans || !trans_size) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Initialize peripheral transport data */
|
||||
*trans = (ble_log_prph_trans_t *)BLE_LOG_MALLOC(sizeof(ble_log_prph_trans_t));
|
||||
if (!(*trans)) {
|
||||
goto exit;
|
||||
}
|
||||
BLE_LOG_MEMSET(*trans, 0, sizeof(ble_log_prph_trans_t));
|
||||
(*trans)->size = trans_size;
|
||||
|
||||
/* Initialize peripheral-specific transport context */
|
||||
size_t trans_ctx_size = sizeof(ble_log_prph_trans_ctx_t) + trans_size;
|
||||
ble_log_prph_trans_ctx_t *uart_trans_ctx = (ble_log_prph_trans_ctx_t *)BLE_LOG_MALLOC(trans_ctx_size);
|
||||
if (!uart_trans_ctx) {
|
||||
goto exit;
|
||||
}
|
||||
BLE_LOG_MEMSET(uart_trans_ctx, 0, trans_ctx_size);
|
||||
|
||||
/* Log buffer linking */
|
||||
(*trans)->ctx = (void *)uart_trans_ctx;
|
||||
(*trans)->buf = (uint8_t *)uart_trans_ctx->trans_buf;
|
||||
uart_trans_ctx->trans = *trans;
|
||||
return true;
|
||||
|
||||
exit:
|
||||
ble_log_prph_trans_deinit(trans);
|
||||
return false;
|
||||
}
|
||||
|
||||
void ble_log_prph_trans_deinit(ble_log_prph_trans_t **trans)
|
||||
{
|
||||
/* Validate inputs */
|
||||
if (!trans || !(*trans)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Release peripheral-specific transport context */
|
||||
if ((*trans)->ctx) {
|
||||
BLE_LOG_FREE((*trans)->ctx);
|
||||
}
|
||||
|
||||
/* Release peripheral transport data */
|
||||
BLE_LOG_FREE(*trans);
|
||||
*trans = NULL;
|
||||
}
|
||||
|
||||
/* CRITICAL:
|
||||
* This function is designed to be called by BLE Log Runtime only,
|
||||
* function call from any other submodules is not allowed */
|
||||
BLE_LOG_IRAM_ATTR void ble_log_prph_send_trans(ble_log_prph_trans_t *trans)
|
||||
{
|
||||
if (uhci_transmit(dev_handle, trans->buf, trans->pos) != ESP_OK) {
|
||||
trans->prph_owned = false;
|
||||
}
|
||||
}
|
||||
|
||||
/* Redirection is required when utilizing UART port 0 */
|
||||
#if BLE_LOG_PRPH_UART_DMA_REDIR
|
||||
BLE_LOG_IRAM_ATTR BLE_LOG_STATIC
|
||||
void ble_log_redir_uart_tx_chars(const char *src, size_t len)
|
||||
{
|
||||
xSemaphoreTake(redir_lbm->mutex, portMAX_DELAY);
|
||||
ble_log_prph_trans_t **trans = ble_log_lbm_get_trans(redir_lbm, len);
|
||||
if (trans) {
|
||||
uint8_t *buf = (*trans)->buf + (*trans)->pos;
|
||||
BLE_LOG_MEMCPY(buf, src, len);
|
||||
(*trans)->pos += len;
|
||||
redir_last_write_ts = pdTICKS_TO_MS(xTaskGetTickCount());
|
||||
|
||||
if (BLE_LOG_TRANS_FREE_SPACE((*trans)) <= BLE_LOG_FRAME_OVERHEAD) {
|
||||
ble_log_rt_queue_trans(trans);
|
||||
}
|
||||
}
|
||||
xSemaphoreGive(redir_lbm->mutex);
|
||||
}
|
||||
|
||||
int __real_uart_tx_chars(uart_port_t uart_num, const char *buffer, uint32_t len);
|
||||
int __wrap_uart_tx_chars(uart_port_t uart_num, const char *buffer, uint32_t len)
|
||||
{
|
||||
if (!prph_inited || (uart_num != UART_NUM_0)) {
|
||||
return __real_uart_tx_chars(uart_num, buffer, len);
|
||||
}
|
||||
ble_log_redir_uart_tx_chars(buffer, len);
|
||||
return len;
|
||||
}
|
||||
|
||||
int __real_uart_write_bytes(uart_port_t uart_num, const void *src, size_t size);
|
||||
int __wrap_uart_write_bytes(uart_port_t uart_num, const void *src, size_t size)
|
||||
{
|
||||
if (!prph_inited || (uart_num != UART_NUM_0)) {
|
||||
return __real_uart_write_bytes(uart_num, src, size);
|
||||
}
|
||||
ble_log_redir_uart_tx_chars(src, size);
|
||||
return size;
|
||||
}
|
||||
|
||||
int __real_uart_write_bytes_with_break(uart_port_t uart_num, const void *src, size_t size, int brk_len);
|
||||
int __wrap_uart_write_bytes_with_break(uart_port_t uart_num, const void *src, size_t size, int brk_len)
|
||||
{
|
||||
if (!prph_inited || (uart_num != UART_NUM_0)) {
|
||||
return __real_uart_write_bytes_with_break(uart_num, src, size, brk_len);
|
||||
} else {
|
||||
(void)brk_len;
|
||||
return __wrap_uart_write_bytes(uart_num, src, size);
|
||||
}
|
||||
}
|
||||
#endif /* BLE_LOG_PRPH_UART_DMA_REDIR */
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -16,12 +16,6 @@ void **btc_profile_cb_tab;
|
||||
|
||||
void esp_profile_cb_reset(void)
|
||||
{
|
||||
#if BTC_DYNAMIC_MEMORY == TRUE
|
||||
if (btc_profile_cb_tab == NULL) {
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
int i;
|
||||
|
||||
for (i = 0; i < BTC_PID_NUM; i++) {
|
||||
@@ -31,12 +25,6 @@ void esp_profile_cb_reset(void)
|
||||
|
||||
int btc_profile_cb_set(btc_pid_t profile_id, void *cb)
|
||||
{
|
||||
#if BTC_DYNAMIC_MEMORY == TRUE
|
||||
if (btc_profile_cb_tab == NULL) {
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (profile_id < 0 || profile_id >= BTC_PID_NUM) {
|
||||
return -1;
|
||||
}
|
||||
@@ -48,12 +36,6 @@ int btc_profile_cb_set(btc_pid_t profile_id, void *cb)
|
||||
|
||||
void *btc_profile_cb_get(btc_pid_t profile_id)
|
||||
{
|
||||
#if BTC_DYNAMIC_MEMORY == TRUE
|
||||
if (btc_profile_cb_tab == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (profile_id < 0 || profile_id >= BTC_PID_NUM) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
@@ -24,8 +24,6 @@
|
||||
#include "btc_gattc.h"
|
||||
#include "btc_gatt_common.h"
|
||||
#include "btc_gap_ble.h"
|
||||
#include "btc_iso_ble.h"
|
||||
#include "btc_ble_cte.h"
|
||||
#include "btc/btc_dm.h"
|
||||
#include "bta/bta_gatt_api.h"
|
||||
#if CLASSIC_BT_INCLUDED
|
||||
@@ -212,7 +210,7 @@ static const btc_func_t profile_tab[BTC_PID_NUM] = {
|
||||
[BTC_PID_RPR_CLIENT] = {btc_ble_mesh_rpr_client_call_handler, btc_ble_mesh_rpr_client_cb_handler },
|
||||
#endif /* CONFIG_BLE_MESH_RPR_CLI */
|
||||
#if CONFIG_BLE_MESH_RPR_SRV
|
||||
[BTC_PID_RPR_SERVER] = {btc_ble_mesh_rpr_server_call_handler, btc_ble_mesh_rpr_server_cb_handler },
|
||||
[BTC_PID_RPR_SERVER] = {NULL, btc_ble_mesh_rpr_server_cb_handler },
|
||||
#endif /* CONFIG_BLE_MESH_RPR_SRV */
|
||||
#if CONFIG_BLE_MESH_SAR_CLI
|
||||
[BTC_PID_SAR_CLIENT] = {btc_ble_mesh_sar_client_call_handler, btc_ble_mesh_sar_client_cb_handler },
|
||||
@@ -256,16 +254,10 @@ static const btc_func_t profile_tab[BTC_PID_NUM] = {
|
||||
#if CONFIG_BLE_MESH_MBT_SRV
|
||||
[BTC_PID_MBT_SERVER] = {btc_ble_mesh_mbt_server_call_handler, btc_ble_mesh_mbt_server_cb_handler },
|
||||
#endif /* CONFIG_BLE_MESH_MBT_SRV */
|
||||
#if CONFIG_BLE_MESH_BLE_COEX_SUPPORT
|
||||
#if CONFIG_BLE_MESH_BLE_COEX_SUPPORT || CONFIG_BLE_MESH_USE_BLE_50
|
||||
[BTC_PID_BLE_MESH_BLE_COEX] = {btc_ble_mesh_ble_call_handler, btc_ble_mesh_ble_cb_handler },
|
||||
#endif /* CONFIG_BLE_MESH_BLE_COEX_SUPPORT */
|
||||
#endif /* CONFIG_BLE_MESH_BLE_COEX_SUPPORT || CONFIG_BLE_MESH_USE_BLE_50 */
|
||||
#endif /* #if CONFIG_BLE_MESH */
|
||||
#if (BLE_FEAT_ISO_EN == TRUE)
|
||||
[BTC_PID_ISO_BLE] = {btc_iso_ble_call_handler, btc_iso_ble_cb_handler },
|
||||
#endif // #if (BLE_FEAT_ISO_EN == TRUE)
|
||||
#if (BLE_FEAT_CTE_EN == TRUE)
|
||||
[BTC_PID_BLE_CTE] = {btc_ble_cte_call_handler, btc_ble_cte_cb_handler },
|
||||
#endif // #if (BLE_FEAT_CTE_EN == TRUE)
|
||||
};
|
||||
|
||||
/*****************************************************************************
|
||||
@@ -391,7 +383,6 @@ static void btc_deinit_mem(void) {
|
||||
}
|
||||
|
||||
#if (BLE_42_FEATURE_SUPPORT == TRUE)
|
||||
#if (BLE_42_ADV_EN == TRUE)
|
||||
if (gl_bta_adv_data_ptr) {
|
||||
osi_free(gl_bta_adv_data_ptr);
|
||||
gl_bta_adv_data_ptr = NULL;
|
||||
@@ -401,7 +392,6 @@ static void btc_deinit_mem(void) {
|
||||
osi_free(gl_bta_scan_rsp_data_ptr);
|
||||
gl_bta_scan_rsp_data_ptr = NULL;
|
||||
}
|
||||
#endif // #if (BLE_42_ADV_EN == TRUE)
|
||||
#endif // BLE_42_FEATURE_SUPPORT
|
||||
|
||||
#if GATTS_INCLUDED == TRUE && GATT_DYNAMIC_MEMORY == TRUE
|
||||
@@ -456,7 +446,6 @@ static bt_status_t btc_init_mem(void) {
|
||||
|
||||
#if BTC_DYNAMIC_MEMORY == TRUE
|
||||
#if (BLE_42_FEATURE_SUPPORT == TRUE)
|
||||
#if (BLE_42_ADV_EN == TRUE)
|
||||
if ((gl_bta_adv_data_ptr = (tBTA_BLE_ADV_DATA *)osi_malloc(sizeof(tBTA_BLE_ADV_DATA))) == NULL) {
|
||||
goto error_exit;
|
||||
}
|
||||
@@ -466,7 +455,6 @@ static bt_status_t btc_init_mem(void) {
|
||||
goto error_exit;
|
||||
}
|
||||
memset((void *)gl_bta_scan_rsp_data_ptr, 0, sizeof(tBTA_BLE_ADV_DATA));
|
||||
#endif // #if (BLE_42_ADV_EN == TRUE)
|
||||
#endif // (BLE_42_FEATURE_SUPPORT == TRUE)
|
||||
#endif // BTC_DYNAMIC_MEMORY == TRUE
|
||||
|
||||
@@ -484,10 +472,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
|
||||
@@ -530,30 +518,21 @@ bt_status_t btc_init(void)
|
||||
return BT_STATUS_NOMEM;
|
||||
}
|
||||
#endif
|
||||
#if BTC_GAP_BT_INCLUDED
|
||||
btc_gap_bt_init();
|
||||
#endif
|
||||
|
||||
#if (BLE_INCLUDED == TRUE)
|
||||
btc_gap_callback_init();
|
||||
#if (BLE_FEAT_ISO_EN == TRUE)
|
||||
btc_iso_callback_init();
|
||||
#endif // #if (BLE_FEAT_ISO_EN == TRUE)
|
||||
#if (BLE_FEAT_CTE_EN == TRUE)
|
||||
btc_cte_callback_init();
|
||||
#endif // #if (BLE_FEAT_CTE_EN == TRUE)
|
||||
btc_gap_ble_init();
|
||||
#endif ///BLE_INCLUDED == TRUE
|
||||
|
||||
#if SCAN_QUEUE_CONGEST_CHECK
|
||||
btc_adv_list_init();
|
||||
#endif
|
||||
/* TODO: initial the profile_tab */
|
||||
return BT_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
void btc_deinit(void)
|
||||
{
|
||||
#if BTC_GAP_BT_INCLUDED
|
||||
btc_gap_bt_deinit();
|
||||
#endif
|
||||
#if BTC_DYNAMIC_MEMORY
|
||||
btc_deinit_mem();
|
||||
#endif
|
||||
@@ -563,6 +542,18 @@ void btc_deinit(void)
|
||||
#if (BLE_INCLUDED == TRUE)
|
||||
btc_gap_ble_deinit();
|
||||
#endif ///BLE_INCLUDED == TRUE
|
||||
#if SCAN_QUEUE_CONGEST_CHECK
|
||||
btc_adv_list_deinit();
|
||||
#endif
|
||||
}
|
||||
|
||||
bool btc_check_queue_is_congest(void)
|
||||
{
|
||||
if (osi_thread_queue_wait_size(btc_thread, 0) >= BT_QUEUE_CONGEST_SIZE) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int get_btc_work_queue_size(void)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user