forked from espressif/esp-idf
Compare commits
381 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8c750b088c | ||
|
|
25c7c11970 | ||
|
|
280a2f9307 | ||
|
|
94c643ba87 | ||
|
|
b43b2001a2 | ||
|
|
ddfb59657c | ||
|
|
e67274f0ff | ||
|
|
7bed0d3937 | ||
|
|
b8f555c16b | ||
|
|
f6826dda7e | ||
|
|
11bbb25dc4 | ||
|
|
8755edfb3a | ||
|
|
8f6e0f4cc3 | ||
|
|
9f19124bd8 | ||
|
|
e8052de6b4 | ||
|
|
c66052e5dd | ||
|
|
12191f266f | ||
|
|
b7887b052e | ||
|
|
a441cad4b7 | ||
|
|
d5ff5d3f46 | ||
|
|
4451649760 | ||
|
|
66ddf66e64 | ||
|
|
7a329d5e91 | ||
|
|
ebaece4dff | ||
|
|
97888e2152 | ||
|
|
8588446859 | ||
|
|
cf8dad0746 | ||
|
|
577d650d83 | ||
|
|
c844ba4f7f | ||
|
|
65d4e3f06f | ||
|
|
adb3f2a580 | ||
|
|
d2299ef3c6 | ||
|
|
aae5e12d77 | ||
|
|
d468522078 | ||
|
|
a6f092516a | ||
|
|
3fcb964577 | ||
|
|
f3579cee33 | ||
|
|
a714eb84b5 | ||
|
|
7c79d6e663 | ||
|
|
fbc18b2c1d | ||
|
|
cbe9388f45 | ||
|
|
1d9e0ac834 | ||
|
|
b37d4b338c | ||
|
|
5986566708 | ||
|
|
20ec15edff | ||
|
|
60e884b438 | ||
|
|
589c2516c8 | ||
|
|
5210e576d5 | ||
|
|
e7a76ff71e | ||
|
|
8694f893ea | ||
|
|
5c6701aad0 | ||
|
|
4d06a6ec9d | ||
|
|
6cb9214520 | ||
|
|
b62e55db0b | ||
|
|
8ac432ec0a | ||
|
|
6fd5f51432 | ||
|
|
0eb2407a26 | ||
|
|
85c77bdb82 | ||
|
|
391c39414e | ||
|
|
df19d0421f | ||
|
|
5558a08c07 | ||
|
|
8aa235a9a5 | ||
|
|
9c61e31be4 | ||
|
|
f0d7baae5e | ||
|
|
9189406b05 | ||
|
|
30c24b2f31 | ||
|
|
23bc0a51fb | ||
|
|
16985bfd3c | ||
|
|
e454c9be2d | ||
|
|
4fd109860b | ||
|
|
88f234f1ef | ||
|
|
e44e7ce2f9 | ||
|
|
06268a4efc | ||
|
|
4684d3dffc | ||
|
|
d8f3e05201 | ||
|
|
0104bcde1a | ||
|
|
aac26c847e | ||
|
|
4a21060839 | ||
|
|
9671a5d3b0 | ||
|
|
2f3351f1a9 | ||
|
|
39ebd0b143 | ||
|
|
cfe6cbaaa0 | ||
|
|
c7990e649e | ||
|
|
adc3a80381 | ||
|
|
e0f7f4e539 | ||
|
|
42a3c9b024 | ||
|
|
a468bbcadd | ||
|
|
d0d04bd986 | ||
|
|
7b1cbb89e0 | ||
|
|
e17993b175 | ||
|
|
36749445f4 | ||
|
|
a644e9073e | ||
|
|
191a24cb6d | ||
|
|
24e323685a | ||
|
|
7bbaba909f | ||
|
|
f7046307a5 | ||
|
|
cd7c97e6eb | ||
|
|
624175fc01 | ||
|
|
8cf17632c2 | ||
|
|
9a74093e98 | ||
|
|
fa889bf5b6 | ||
|
|
c4747aae02 | ||
|
|
0ea73a9273 | ||
|
|
80d191e797 | ||
|
|
ba0da6f2a6 | ||
|
|
c943797004 | ||
|
|
1a40b106b4 | ||
|
|
10a210d08a | ||
|
|
56a4c70c31 | ||
|
|
5a04cfded1 | ||
|
|
3fe9252c3f | ||
|
|
c837712306 | ||
|
|
80abd1c7e4 | ||
|
|
3da3f6f2e2 | ||
|
|
8d7aefa890 | ||
|
|
ef71aad834 | ||
|
|
73058bfca0 | ||
|
|
d5323cfaaa | ||
|
|
6e82c7a061 | ||
|
|
6cf1a6f297 | ||
|
|
95b7c023da | ||
|
|
f4669e3377 | ||
|
|
7e28275ac1 | ||
|
|
da534bf462 | ||
|
|
59434db045 | ||
|
|
2e7a9174fc | ||
|
|
fc77b58ced | ||
|
|
770052e859 | ||
|
|
71f83ca625 | ||
|
|
156ead0cd5 | ||
|
|
5555ef7425 | ||
|
|
4b93bde59b | ||
|
|
04f5e591c0 | ||
|
|
2d5d7b819f | ||
|
|
908ff6e5df | ||
|
|
0dd5b0b979 | ||
|
|
e536aa670b | ||
|
|
1df4f13b2e | ||
|
|
bb72c42611 | ||
|
|
d8fa0886b0 | ||
|
|
08d78dcd7e | ||
|
|
849c74b2b9 | ||
|
|
e32bd2502d | ||
|
|
666f3db1a3 | ||
|
|
79da851a4c | ||
|
|
3f8da22ae0 | ||
|
|
f523943972 | ||
|
|
fc71a8643e | ||
|
|
0e585a2994 | ||
|
|
f5be149eb2 | ||
|
|
ccef14fad2 | ||
|
|
bb8338b17a | ||
|
|
53534bc5ce | ||
|
|
ace361e7e1 | ||
|
|
ec2f1c0023 | ||
|
|
5584880376 | ||
|
|
ebdafe8e0c | ||
|
|
addc2101dc | ||
|
|
6078213bcd | ||
|
|
4869e83855 | ||
|
|
37f017585d | ||
|
|
8f57d672d2 | ||
|
|
881c5a9795 | ||
|
|
2e760d374e | ||
|
|
e22c523b55 | ||
|
|
7c2734dc02 | ||
|
|
9e7325a3d6 | ||
|
|
29ba5469ef | ||
|
|
20d66da972 | ||
|
|
4c3d086c13 | ||
|
|
d0e0c188fb | ||
|
|
19b0d6c13c | ||
|
|
e9e995bd0a | ||
|
|
7914e75525 | ||
|
|
90b3d29223 | ||
|
|
30d77f494e | ||
|
|
7557ec0951 | ||
|
|
e29823cfe0 | ||
|
|
f0a4d73ea1 | ||
|
|
22aeb00462 | ||
|
|
fd3178eb6b | ||
|
|
7cf59adc0c | ||
|
|
96b43c9797 | ||
|
|
168808248d | ||
|
|
fc72303490 | ||
|
|
6b74032d2e | ||
|
|
39c6c703b1 | ||
|
|
ce09a8c037 | ||
|
|
370ac37623 | ||
|
|
98cd765953 | ||
|
|
73747da716 | ||
|
|
18b6997e32 | ||
|
|
693a5393b2 | ||
|
|
23892d857a | ||
|
|
087727a693 | ||
|
|
49b5cc9e50 | ||
|
|
33c71ea033 | ||
|
|
5961670d06 | ||
|
|
07ae83249a | ||
|
|
fa75a4dd67 | ||
|
|
b002e50857 | ||
|
|
f19263a97c | ||
|
|
7f8290e911 | ||
|
|
0170c56e04 | ||
|
|
7b66ed489f | ||
|
|
35876be5e6 | ||
|
|
e2b524c609 | ||
|
|
30859ceaff | ||
|
|
99e5203d89 | ||
|
|
c48b74805f | ||
|
|
a2cd564044 | ||
|
|
ad5d36257b | ||
|
|
52e3d9bb5f | ||
|
|
d881dda91c | ||
|
|
ecb5fc3075 | ||
|
|
cd1601f408 | ||
|
|
4d83f1b8af | ||
|
|
0fe8891e3a | ||
|
|
b1a379d574 | ||
|
|
84973428b2 | ||
|
|
41a17b71ad | ||
|
|
253ca4267a | ||
|
|
60ab2598c5 | ||
|
|
b9c586ebd1 | ||
|
|
3d09da9251 | ||
|
|
fddf34d7b0 | ||
|
|
2e761da92a | ||
|
|
b045635cea | ||
|
|
3b596bb602 | ||
|
|
45fed1d225 | ||
|
|
d7216d221b | ||
|
|
80c5fd1836 | ||
|
|
b3843ea09a | ||
|
|
6687749fae | ||
|
|
2b0c548593 | ||
|
|
59496b4927 | ||
|
|
b977a13796 | ||
|
|
0a3cc83a86 | ||
|
|
d5d713cff2 | ||
|
|
80c92bae34 | ||
|
|
0904640409 | ||
|
|
b0f107b69a | ||
|
|
1c81d11ec3 | ||
|
|
059a675e5c | ||
|
|
4c7a13b570 | ||
|
|
5be9ac3d93 | ||
|
|
e100fc790c | ||
|
|
a73197e886 | ||
|
|
9e0c4d226a | ||
|
|
68dd2c9a3c | ||
|
|
3d3b7caf95 | ||
|
|
0e59feac9d | ||
|
|
c0f77d8993 | ||
|
|
3092578b4a | ||
|
|
fafc25b8b9 | ||
|
|
e7c8f555e7 | ||
|
|
5f71d958c3 | ||
|
|
e26be2be8f | ||
|
|
e8475d7796 | ||
|
|
31149354a9 | ||
|
|
833df30063 | ||
|
|
1cc377a373 | ||
|
|
a74197c552 | ||
|
|
d482206483 | ||
|
|
27496e47f0 | ||
|
|
eca7c7296c | ||
|
|
039cc1ac80 | ||
|
|
ee3baa4ca7 | ||
|
|
ba70c7f3d1 | ||
|
|
c5b725fc50 | ||
|
|
10a690fe10 | ||
|
|
758da73338 | ||
|
|
27b85137c7 | ||
|
|
06ee44ef46 | ||
|
|
f4add076a8 | ||
|
|
5e6ecd81b5 | ||
|
|
45fb5fb793 | ||
|
|
63f72f659d | ||
|
|
7910ea8571 | ||
|
|
7f46f6152e | ||
|
|
5da8865f9b | ||
|
|
c771e4508e | ||
|
|
375d675cdc | ||
|
|
2252a4166a | ||
|
|
1f4fbd060c | ||
|
|
f97fd7490f | ||
|
|
dbfb663b66 | ||
|
|
429183de1e | ||
|
|
1ba8abd8b7 | ||
|
|
5b1588e0db | ||
|
|
3ded40b276 | ||
|
|
a6db9d402f | ||
|
|
693dfe6b0e | ||
|
|
d738d889d8 | ||
|
|
ce340fcce7 | ||
|
|
b1218adfae | ||
|
|
aff86ba14b | ||
|
|
c85c74f54b | ||
|
|
0778748506 | ||
|
|
8a54378b95 | ||
|
|
43ff2531ab | ||
|
|
a3edce572a | ||
|
|
4aa47aacc3 | ||
|
|
379f4de500 | ||
|
|
048d03e94d | ||
|
|
29520e982c | ||
|
|
527e2f38b8 | ||
|
|
9cf4ddf797 | ||
|
|
3052ad53e7 | ||
|
|
1adbeceb27 | ||
|
|
d1c131f649 | ||
|
|
7b52c11661 | ||
|
|
5bb83afac7 | ||
|
|
669e677ba3 | ||
|
|
1909105acf | ||
|
|
afcb8199b0 | ||
|
|
0a17f79cc7 | ||
|
|
de17b6ff94 | ||
|
|
046479c23f | ||
|
|
79d2bedbf9 | ||
|
|
6514df1ba9 | ||
|
|
692f7df5aa | ||
|
|
f6cb4422db | ||
|
|
60adcc5980 | ||
|
|
a544a33131 | ||
|
|
4f56bba225 | ||
|
|
5273ba9731 | ||
|
|
eb0cf524c0 | ||
|
|
6ba1a3a427 | ||
|
|
f9597a06f4 | ||
|
|
f056662cd5 | ||
|
|
e1aee3ff2b | ||
|
|
2e02c26b81 | ||
|
|
f5748f3d9b | ||
|
|
8a138cbd22 | ||
|
|
c18e53b672 | ||
|
|
28ac0243bb | ||
|
|
c61f36de13 | ||
|
|
6fdcf9efc1 | ||
|
|
a652a8473e | ||
|
|
6f82f332fd | ||
|
|
b095331a51 | ||
|
|
084dfefd6f | ||
|
|
04d83433c3 | ||
|
|
dd1a331f4f | ||
|
|
0f7b621d47 | ||
|
|
72ae023a42 | ||
|
|
84e62daedc | ||
|
|
0d5d31b343 | ||
|
|
05617e458b | ||
|
|
f8284e1733 | ||
|
|
b9e03c3cf4 | ||
|
|
4498eea285 | ||
|
|
af9e528409 | ||
|
|
d35923141d | ||
|
|
81f5d899f6 | ||
|
|
2eac57a1da | ||
|
|
2fd71413f0 | ||
|
|
b8badb85d1 | ||
|
|
f8cdf02b55 | ||
|
|
ac12d560a2 | ||
|
|
18cd0fa030 | ||
|
|
269f1d110d | ||
|
|
f03b0fe0c5 | ||
|
|
a0fc3e68a8 | ||
|
|
0993f1e67b | ||
|
|
45831351fa | ||
|
|
37e28522c2 | ||
|
|
8ea6b3170b | ||
|
|
2de265b3e7 | ||
|
|
953fe222ec | ||
|
|
70f19793f8 | ||
|
|
0b2f639c62 | ||
|
|
a3cb7f4404 | ||
|
|
b264d7f89b | ||
|
|
14c29c467e | ||
|
|
3b7f4e2341 | ||
|
|
3a6e5dba88 | ||
|
|
27e1a30acc | ||
|
|
c0d91e33d0 | ||
|
|
a4d0ab04c5 |
@@ -1,4 +1,4 @@
|
||||
[codespell]
|
||||
skip = build,*.yuv,components/fatfs/src/*,alice.txt,*.rgb,components/wpa_supplicant/*,components/esp_wifi/*,*.pem,*/COPYING*,docs/sphinx-known-warnings.txt
|
||||
skip = build,*.yuv,components/fatfs/src/*,alice.txt,*.rgb,components/wpa_supplicant/*,components/esp_wifi/*,*.pem,components/newlib/COPYING.*
|
||||
ignore-words-list = ser,dout,rsource,fram,inout,shs,ans,aci,unstall,unstalling,hart,wheight,wel,ot,fane,assertIn,registr,oen,parms
|
||||
write-changes = true
|
||||
|
||||
2
.github/ISSUE_TEMPLATE/02_runtime_bug.yml
vendored
2
.github/ISSUE_TEMPLATE/02_runtime_bug.yml
vendored
@@ -26,7 +26,7 @@ body:
|
||||
id: chip_revision
|
||||
attributes:
|
||||
label: Espressif SoC revision.
|
||||
description: On which Espressif SoC revision does your application run on? Run `esptool chip-id` (or `esptool.py chip_id` for ESP-IDF v5.5 and older) to find it.
|
||||
description: On which Espressif SoC revision does your application run on? Run `esptool chip_id` to find it.
|
||||
placeholder: ex. ESP32-C3 (QFN32) (revision v0.3)
|
||||
validations:
|
||||
required: true
|
||||
|
||||
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).
|
||||
|
||||
3
.github/workflows/issue_comment.yml
vendored
3
.github/workflows/issue_comment.yml
vendored
@@ -14,11 +14,10 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Sync issue comments to JIRA
|
||||
uses: espressif/sync-jira-actions@v1
|
||||
uses: espressif/github-actions/sync_issues_to_jira@master
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
JIRA_PASS: ${{ secrets.JIRA_PASS }}
|
||||
JIRA_PROJECT: IDFGH
|
||||
JIRA_URL: ${{ secrets.JIRA_URL }}
|
||||
JIRA_USER: ${{ secrets.JIRA_USER }}
|
||||
WEBHOOK_URL: ${{ secrets.JIRA_ISSUE_COMMENT_WEBHOOK_URL }}
|
||||
|
||||
3
.github/workflows/new_issues.yml
vendored
3
.github/workflows/new_issues.yml
vendored
@@ -14,11 +14,10 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Sync GitHub issues to Jira project
|
||||
uses: espressif/sync-jira-actions@v1
|
||||
uses: espressif/github-actions/sync_issues_to_jira@master
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
JIRA_PASS: ${{ secrets.JIRA_PASS }}
|
||||
JIRA_PROJECT: IDFGH
|
||||
JIRA_URL: ${{ secrets.JIRA_URL }}
|
||||
JIRA_USER: ${{ secrets.JIRA_USER }}
|
||||
WEBHOOK_URL: ${{ secrets.JIRA_ISSUE_COMMENT_WEBHOOK_URL }}
|
||||
|
||||
2
.github/workflows/pre_commit_check.yml
vendored
2
.github/workflows/pre_commit_check.yml
vendored
@@ -23,7 +23,7 @@ jobs:
|
||||
- name: Set up Python environment
|
||||
uses: actions/setup-python@master
|
||||
with:
|
||||
python-version: "3.10"
|
||||
python-version: v3.8
|
||||
- name: Install python packages
|
||||
run: |
|
||||
pip install pre-commit
|
||||
|
||||
5
.gitignore
vendored
5
.gitignore
vendored
@@ -37,7 +37,6 @@ components/**/build/
|
||||
components/**/build_*_*/
|
||||
components/**/sdkconfig
|
||||
components/**/sdkconfig.old
|
||||
components/**/test_apps/wifi_nvs_config/nvs_data_suffix.csv
|
||||
|
||||
# Example project files
|
||||
examples/**/build/
|
||||
@@ -66,6 +65,8 @@ build_summary_*.xml
|
||||
coverage.info
|
||||
coverage_report/
|
||||
|
||||
test_multi_heap_host
|
||||
|
||||
# VS Code Settings
|
||||
.vscode/
|
||||
|
||||
@@ -98,7 +99,7 @@ managed_components
|
||||
pytest-embedded/
|
||||
# legacy one
|
||||
pytest_embedded_log/
|
||||
app_info_*.txt
|
||||
list_job*.txt
|
||||
size_info*.txt
|
||||
XUNIT_RESULT*.xml
|
||||
.manifest_sha
|
||||
|
||||
@@ -3,30 +3,33 @@ workflow:
|
||||
# Disable those non-protected push triggered pipelines
|
||||
- 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"'
|
||||
when: never
|
||||
# merged result pipelines
|
||||
- if: $CI_MERGE_REQUEST_SOURCE_BRANCH_SHA
|
||||
# when running merged result pipelines, CI_COMMIT_SHA represents the temp commit it created.
|
||||
# Please use PIPELINE_COMMIT_SHA at all places that require a commit sha of the original commit.
|
||||
- if: $CI_OPEN_MERGE_REQUESTS != null
|
||||
variables:
|
||||
PIPELINE_COMMIT_SHA: $CI_MERGE_REQUEST_SOURCE_BRANCH_SHA
|
||||
# else
|
||||
- if: $CI_MERGE_REQUEST_SOURCE_BRANCH_SHA == null || $CI_MERGE_REQUEST_SOURCE_BRANCH_SHA == ""
|
||||
IS_MR_PIPELINE: 1
|
||||
- if: $CI_OPEN_MERGE_REQUESTS == null
|
||||
variables:
|
||||
PIPELINE_COMMIT_SHA: $CI_COMMIT_SHA
|
||||
IS_MR_PIPELINE: 0
|
||||
- when: always
|
||||
|
||||
# Place the default settings in `.gitlab/ci/common.yml` instead
|
||||
|
||||
include:
|
||||
- ".gitlab/ci/danger.yml"
|
||||
- ".gitlab/ci/common.yml"
|
||||
- ".gitlab/ci/rules.yml"
|
||||
- ".gitlab/ci/upload_cache.yml"
|
||||
- ".gitlab/ci/docs.yml"
|
||||
- ".gitlab/ci/static-code-analysis.yml"
|
||||
- ".gitlab/ci/pre_commit.yml"
|
||||
- ".gitlab/ci/pre_check.yml"
|
||||
- ".gitlab/ci/build.yml"
|
||||
- ".gitlab/ci/integration_test.yml"
|
||||
- ".gitlab/ci/host-test.yml"
|
||||
- ".gitlab/ci/deploy.yml"
|
||||
- ".gitlab/ci/post_deploy.yml"
|
||||
- ".gitlab/ci/test-win.yml"
|
||||
- '.gitlab/ci/danger.yml'
|
||||
- '.gitlab/ci/common.yml'
|
||||
- '.gitlab/ci/rules.yml'
|
||||
- '.gitlab/ci/upload_cache.yml'
|
||||
- '.gitlab/ci/docs.yml'
|
||||
- '.gitlab/ci/static-code-analysis.yml'
|
||||
- '.gitlab/ci/pre_commit.yml'
|
||||
- '.gitlab/ci/pre_check.yml'
|
||||
- '.gitlab/ci/build.yml'
|
||||
- '.gitlab/ci/integration_test.yml'
|
||||
- '.gitlab/ci/host-test.yml'
|
||||
- '.gitlab/ci/deploy.yml'
|
||||
- '.gitlab/ci/post_deploy.yml'
|
||||
- '.gitlab/ci/retry_failed_jobs.yml'
|
||||
- '.gitlab/ci/test-win.yml'
|
||||
|
||||
@@ -2,252 +2,5 @@
|
||||
#
|
||||
# https://docs.gitlab.com/ee/user/project/code_owners.html#the-syntax-of-code-owners-files
|
||||
#
|
||||
# If more than one rule matches a given file, the latest rule is used.
|
||||
# The file should be generally kept sorted, except when it is necessary
|
||||
# to use a different order due to the fact above. In that case, use
|
||||
# '# sort-order-reset' comment line to reset the sort order.
|
||||
#
|
||||
# Recipes for a few common cases:
|
||||
#
|
||||
# 1. Specific directory with all its contents:
|
||||
#
|
||||
# /components/app_trace/
|
||||
#
|
||||
# Note the trailing slash!
|
||||
#
|
||||
# 2. File with certain extension in any subdirectory of a certain directory:
|
||||
#
|
||||
# /examples/**/*.py
|
||||
#
|
||||
# This includes an *.py files in /examples/ directory as well.
|
||||
#
|
||||
# 3. Contents of a directory with a certain name, anywhere in the tree:
|
||||
#
|
||||
# test_*_host/
|
||||
#
|
||||
# Will match everything under components/efuse/test_efuse_host/,
|
||||
# components/heap/test_multi_heap_host/, components/lwip/test_afl_host/, etc.
|
||||
#
|
||||
# 4. Same as above, except limited to a specific place in the tree:
|
||||
#
|
||||
# /components/esp32*/
|
||||
#
|
||||
# Matches everything under /components/esp32, /components/esp32s2, etc.
|
||||
# Doesn't match /tools/some-test/components/esp32s5.
|
||||
#
|
||||
# 5. Specific file:
|
||||
#
|
||||
# /tools/tools.json
|
||||
#
|
||||
# 6. File with a certain name anywhere in the tree
|
||||
#
|
||||
# .gitignore
|
||||
#
|
||||
|
||||
* @esp-idf-codeowners/other
|
||||
|
||||
/.* @esp-idf-codeowners/tools
|
||||
/.codespellrc @esp-idf-codeowners/ci
|
||||
/.github/workflows/ @esp-idf-codeowners/ci
|
||||
/.gitlab-ci.yml @esp-idf-codeowners/ci
|
||||
/.gitlab/ci/ @esp-idf-codeowners/ci
|
||||
/.idf_build_apps.toml @esp-idf-codeowners/ci
|
||||
/.idf_ci.toml @esp-idf-codeowners/ci
|
||||
/.pre-commit-config.yaml @esp-idf-codeowners/ci
|
||||
/.vale.ini @esp-idf-codeowners/docs
|
||||
/CMakeLists.txt @esp-idf-codeowners/build-config
|
||||
/COMPATIBILITY*.md @esp-idf-codeowners/peripherals
|
||||
/CONTRIBUTING.md @esp-idf-codeowners/docs
|
||||
/Kconfig @esp-idf-codeowners/build-config
|
||||
/README*.md @esp-idf-codeowners/docs
|
||||
/ROADMAP*.md @esp-idf-codeowners/docs
|
||||
/SUPPORT_POLICY*.md @esp-idf-codeowners/docs
|
||||
/add_path.sh @esp-idf-codeowners/tools
|
||||
/conftest.py @esp-idf-codeowners/ci
|
||||
/export.* @esp-idf-codeowners/tools
|
||||
/install.* @esp-idf-codeowners/tools
|
||||
/pytest.ini @esp-idf-codeowners/ci
|
||||
/ruff.toml @esp-idf-codeowners/tools
|
||||
/sdkconfig.rename @esp-idf-codeowners/build-config
|
||||
/sonar-project.properties @esp-idf-codeowners/ci
|
||||
|
||||
# sort-order-reset
|
||||
|
||||
/components/app_trace/ @esp-idf-codeowners/debugging
|
||||
/components/app_update/ @esp-idf-codeowners/system @esp-idf-codeowners/app-utilities
|
||||
/components/bootloader*/ @esp-idf-codeowners/system @esp-idf-codeowners/security
|
||||
/components/bootloader_support/bootloader_flash/ @esp-idf-codeowners/peripherals
|
||||
/components/bt/ @esp-idf-codeowners/bluetooth
|
||||
/components/cmock/ @esp-idf-codeowners/system
|
||||
/components/console/ @esp-idf-codeowners/system @esp-idf-codeowners/app-utilities/console
|
||||
/components/cxx/ @esp-idf-codeowners/system
|
||||
/components/driver/ @esp-idf-codeowners/peripherals
|
||||
/components/efuse/ @esp-idf-codeowners/system
|
||||
/components/esp_adc/ @esp-idf-codeowners/peripherals
|
||||
/components/esp_app_format/ @esp-idf-codeowners/system @esp-idf-codeowners/app-utilities
|
||||
/components/esp_blockdev/ @esp-idf-codeowners/storage
|
||||
/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_hal_*/ @esp-idf-codeowners/peripherals
|
||||
/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_hw_support/usb_phy/ @esp-idf-codeowners/peripherals/usb
|
||||
/components/esp_lcd/ @esp-idf-codeowners/peripherals
|
||||
/components/esp_libc/ @esp-idf-codeowners/system @esp-idf-codeowners/toolchain
|
||||
/components/esp_local_ctrl/ @esp-idf-codeowners/app-utilities
|
||||
/components/esp_mm/ @esp-idf-codeowners/peripherals
|
||||
/components/esp_netif/ @esp-idf-codeowners/network
|
||||
/components/esp_netif_stack/ @esp-idf-codeowners/network
|
||||
/components/esp_partition/ @esp-idf-codeowners/storage
|
||||
/components/esp_phy/ @esp-idf-codeowners/bluetooth @esp-idf-codeowners/wifi @esp-idf-codeowners/ieee802154
|
||||
/components/esp_pm/ @esp-idf-codeowners/power-management @esp-idf-codeowners/bluetooth @esp-idf-codeowners/wifi @esp-idf-codeowners/system
|
||||
/components/esp_psram/ @esp-idf-codeowners/peripherals
|
||||
/components/esp_psram/system_layer/ @esp-idf-codeowners/peripherals @esp-idf-codeowners/system
|
||||
/components/esp_ringbuf/ @esp-idf-codeowners/system
|
||||
/components/esp_rom/ @esp-idf-codeowners/system @esp-idf-codeowners/bluetooth @esp-idf-codeowners/wifi
|
||||
/components/esp_security/ @esp-idf-codeowners/security
|
||||
/components/esp_stdio/ @esp-idf-codeowners/storage @esp-idf-codeowners/system
|
||||
/components/esp_system/ @esp-idf-codeowners/system
|
||||
/components/esp_tee/ @esp-idf-codeowners/security
|
||||
/components/esp_timer/ @esp-idf-codeowners/system
|
||||
/components/esp-tls/ @esp-idf-codeowners/app-utilities
|
||||
/components/esp_trace/ @esp-idf-codeowners/debugging
|
||||
/components/esp_usb_cdc_rom_console/ @esp-idf-codeowners/system @esp-idf-codeowners/peripherals/usb
|
||||
/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/hal/test_apps/tee/ @esp-idf-codeowners/peripherals @esp-idf-codeowners/security
|
||||
/components/heap/ @esp-idf-codeowners/system
|
||||
/components/http_parser/ @esp-idf-codeowners/app-utilities
|
||||
/components/idf_test/ @esp-idf-codeowners/peripherals @esp-idf-codeowners/system
|
||||
/components/ieee802154/ @esp-idf-codeowners/ieee802154
|
||||
/components/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/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/ulp/ @esp-idf-codeowners/system
|
||||
/components/unity/ @esp-idf-codeowners/peripherals @esp-idf-codeowners/system
|
||||
/components/vfs/ @esp-idf-codeowners/storage
|
||||
/components/wear_levelling/ @esp-idf-codeowners/storage
|
||||
/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/**/api-guides/kconfig/ @esp-idf-codeowners/tools
|
||||
/docs/en/api-guides/core_dump.rst @esp-idf-codeowners/debugging
|
||||
/docs/**/api-guides/wifi* @esp-idf-codeowners/wifi
|
||||
/docs/**/api-guides/esp-wifi-mesh.rst @esp-idf-codeowners/wifi
|
||||
/docs/en/api-guides/jtag-debugging/ @esp-idf-codeowners/debugging
|
||||
/docs/**/api-reference/bluetooth/ @esp-idf-codeowners/bluetooth
|
||||
/docs/**/api-reference/network/ @esp-idf-codeowners/network @esp-idf-codeowners/wifi
|
||||
/docs/**/api-reference/peripherals/ @esp-idf-codeowners/peripherals
|
||||
/docs/**/api-reference/peripherals/usb* @esp-idf-codeowners/peripherals @esp-idf-codeowners/peripherals/usb
|
||||
/docs/**/api-reference/peripherals/usb*/ @esp-idf-codeowners/peripherals @esp-idf-codeowners/peripherals/usb
|
||||
/docs/**/api-reference/protocols/ @esp-idf-codeowners/network @esp-idf-codeowners/app-utilities
|
||||
/docs/**/api-reference/provisioning/ @esp-idf-codeowners/app-utilities/provisioning
|
||||
/docs/**/api-reference/storage/ @esp-idf-codeowners/storage
|
||||
/docs/**/api-reference/system/ @esp-idf-codeowners/system
|
||||
/docs/**/security/ @esp-idf-codeowners/security
|
||||
/docs/**/migration-guides/ @esp-idf-codeowners/docs @esp-idf-codeowners/all-maintainers
|
||||
/docs/**/contribute/install-pre-commit-hook.rst @esp-idf-codeowners/ci @esp-idf-codeowners/tools
|
||||
|
||||
/examples/README.md @esp-idf-codeowners/docs @esp-idf-codeowners/ci
|
||||
/examples/**/*.py @esp-idf-codeowners/ci @esp-idf-codeowners/tools
|
||||
/examples/bluetooth/ @esp-idf-codeowners/bluetooth
|
||||
/examples/build_system/ @esp-idf-codeowners/build-config
|
||||
/examples/common_components/ @esp-idf-codeowners/system @esp-idf-codeowners/wifi @esp-idf-codeowners/lwip @esp-idf-codeowners/network
|
||||
/examples/custom_bootloader/ @esp-idf-codeowners/system
|
||||
/examples/cxx/ @esp-idf-codeowners/system
|
||||
/examples/ethernet/ @esp-idf-codeowners/network
|
||||
/examples/get-started/ @esp-idf-codeowners/system
|
||||
/examples/ieee802154/ @esp-idf-codeowners/ieee802154
|
||||
/examples/lowpower/ @esp-idf-codeowners/power-management @esp-idf-codeowners/system
|
||||
/examples/mesh/ @esp-idf-codeowners/wifi
|
||||
/examples/network/ @esp-idf-codeowners/network @esp-idf-codeowners/wifi
|
||||
/examples/openthread/ @esp-idf-codeowners/ieee802154
|
||||
/examples/peripherals/ @esp-idf-codeowners/peripherals
|
||||
/examples/peripherals/usb/ @esp-idf-codeowners/peripherals @esp-idf-codeowners/peripherals/usb
|
||||
/examples/phy/ @esp-idf-codeowners/bluetooth @esp-idf-codeowners/wifi @esp-idf-codeowners/ieee802154
|
||||
/examples/protocols/ @esp-idf-codeowners/network @esp-idf-codeowners/app-utilities
|
||||
/examples/security/ @esp-idf-codeowners/security
|
||||
/examples/storage/ @esp-idf-codeowners/storage
|
||||
/examples/system/ @esp-idf-codeowners/system
|
||||
/examples/system/ota/ @esp-idf-codeowners/app-utilities
|
||||
/examples/wifi/ @esp-idf-codeowners/wifi
|
||||
/examples/zigbee/ @esp-idf-codeowners/ieee802154
|
||||
|
||||
/tools/ @esp-idf-codeowners/tools
|
||||
/tools/ble/ @esp-idf-codeowners/app-utilities
|
||||
/tools/bt/ @esp-idf-codeowners/bluetooth
|
||||
/tools/ci/ @esp-idf-codeowners/ci
|
||||
/tools/cmake/ @esp-idf-codeowners/build-config
|
||||
/tools/cmake/toolchain-*.cmake @esp-idf-codeowners/toolchain
|
||||
/tools/cmakev2/ @esp-idf-codeowners/build-config
|
||||
/tools/esp_app_trace/ @esp-idf-codeowners/debugging
|
||||
/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/components/test_utils/ @esp-idf-codeowners/peripherals @esp-idf-codeowners/system
|
||||
/tools/test_apps/configs/ @esp-idf-codeowners/system
|
||||
/tools/test_apps/linux_compatible/ @esp-idf-codeowners/system
|
||||
/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
|
||||
|
||||
# sort-order-reset
|
||||
|
||||
/components/**/test_apps/**/*.py @esp-idf-codeowners/ci @esp-idf-codeowners/tools
|
||||
|
||||
# ignore lists
|
||||
/tools/ci/check_copyright_config.yaml @esp-idf-codeowners/all-maintainers
|
||||
/tools/ci/check_copyright_ignore.txt @esp-idf-codeowners/all-maintainers
|
||||
/tools/ci/mypy_ignore_list.txt @esp-idf-codeowners/tools
|
||||
* @esp-idf-codeowners/all-maintainers
|
||||
|
||||
@@ -250,9 +250,76 @@ We're using the latest version of [idf-build-apps][idf-build-apps]. Please refer
|
||||
In ESP-IDF CI, there's a few more special rules are additionally supported to disable the check app dependencies feature:
|
||||
|
||||
- Add MR labels `BUILD_AND_TEST_ALL_APPS`
|
||||
- Pipeline variable `IDF_CI_SELECT_ALL_PYTEST_CASES=1`
|
||||
- Run in protected branches
|
||||
|
||||
## Upload/Download Artifacts to Internal Minio Server
|
||||
|
||||
Please refer to the documentation [here](https://docs.espressif.com/projects/idf-ci/en/latest/guides/cli.html)
|
||||
### Users Without Access to Minio
|
||||
|
||||
If you don't have access to the internal Minio server, you can still download the artifacts from the shared link in the job log.
|
||||
|
||||
The log will look like this:
|
||||
|
||||
```shell
|
||||
Pipeline ID : 587355
|
||||
Job name : build_clang_test_apps_esp32
|
||||
Job ID : 40272275
|
||||
Created archive file: 40272275.zip, uploading as 587355/build_dir_without_map_and_elf_files/build_clang_test_apps_esp32/40272275.zip
|
||||
Please download the archive file includes build_dir_without_map_and_elf_files from [INTERNAL_URL]
|
||||
```
|
||||
|
||||
### Users With Access to Minio
|
||||
|
||||
#### Env Vars for Minio
|
||||
|
||||
Minio takes these env vars to connect to the server:
|
||||
|
||||
- `IDF_S3_SERVER`
|
||||
- `IDF_S3_ACCESS_KEY`
|
||||
- `IDF_S3_SECRET_KEY`
|
||||
- `IDF_S3_BUCKET`
|
||||
|
||||
#### Artifacts Types and File Patterns
|
||||
|
||||
The artifacts types and corresponding file patterns are defined in tools/ci/artifacts_handler.py, inside `ArtifactType` and `TYPE_PATTERNS_DICT`.
|
||||
|
||||
#### Upload
|
||||
|
||||
```shell
|
||||
python tools/ci/artifacts_handler.py upload
|
||||
```
|
||||
|
||||
will upload the files that match the file patterns to minio object storage with name:
|
||||
|
||||
`<pipeline_id>/<artifact_type>/<job_name>/<job_id>.zip`
|
||||
|
||||
For example, job 39043328 will upload these four files:
|
||||
|
||||
- `575500/map_and_elf_files/build_pytest_examples_esp32/39043328.zip`
|
||||
- `575500/build_dir_without_map_and_elf_files/build_pytest_examples_esp32/39043328.zip`
|
||||
- `575500/logs/build_pytest_examples_esp32/39043328.zip`
|
||||
- `575500/size_reports/build_pytest_examples_esp32/39043328.zip`
|
||||
|
||||
#### Download
|
||||
|
||||
You may run
|
||||
|
||||
```shell
|
||||
python tools/ci/artifacts_handler.py download --pipeline_id <pipeline_id>
|
||||
```
|
||||
|
||||
to download all files of the pipeline, or
|
||||
|
||||
```shell
|
||||
python tools/ci/artifacts_handler.py download --pipeline_id <pipeline_id> --job_name <job_name_or_pattern>
|
||||
```
|
||||
|
||||
to download all files with the specified job name or pattern, or
|
||||
|
||||
```shell
|
||||
python tools/ci/artifacts_handler.py download --pipeline_id <pipeline_id> --job_name <job_name_or_pattern> --type <artifact_type> <artifact_type> ...
|
||||
```
|
||||
|
||||
to download all files with the specified job name or pattern and artifact type(s).
|
||||
|
||||
You may check all detailed documentation with `python tools/ci/artifacts_handler.py download -h`
|
||||
|
||||
@@ -1,14 +1,55 @@
|
||||
.build_template:
|
||||
stage: build
|
||||
extends:
|
||||
- .before_script:build
|
||||
- .after_script:build
|
||||
- .after_script:build:ccache-show-stats:upload-failed-job-logs
|
||||
image: $ESP_ENV_IMAGE
|
||||
tags: [build, shiny]
|
||||
tags:
|
||||
- build
|
||||
# build only on shiny servers since shiny storage server is at the same location
|
||||
- shiny
|
||||
variables:
|
||||
# Enable ccache for all build jobs. See configure_ci_environment.sh for more ccache related settings.
|
||||
IDF_CCACHE_ENABLE: "1"
|
||||
dependencies: []
|
||||
|
||||
.build_cmake_clang_template:
|
||||
extends:
|
||||
- .build_template
|
||||
- .before_script:build
|
||||
- .after_script:build:ccache-show-stats
|
||||
dependencies: # set dependencies to null to avoid missing artifacts issue
|
||||
needs:
|
||||
- job: fast_template_app
|
||||
artifacts: false
|
||||
- pipeline_variables
|
||||
artifacts:
|
||||
paths:
|
||||
# The other artifacts patterns are defined under tools/ci/artifacts_handler.py
|
||||
# Now we're uploading/downloading the binary files from our internal storage server
|
||||
#
|
||||
# keep the log file to help debug
|
||||
- "**/build*/build_log.txt"
|
||||
# keep the size info to help track the binary size
|
||||
- size_info.txt
|
||||
- "**/build*/size.json"
|
||||
expire_in: 1 week
|
||||
when: always
|
||||
variables:
|
||||
IDF_TOOLCHAIN: clang
|
||||
TEST_BUILD_OPTS_EXTRA: ""
|
||||
TEST_DIR: tools/test_apps/system/clang_build_test
|
||||
PYTEST_IGNORE_COLLECT_IMPORT_ERROR: "1"
|
||||
script:
|
||||
# CI specific options start from "--parallel-count xxx". could ignore when running locally
|
||||
- run_cmd python tools/ci/ci_build_apps.py $TEST_DIR -v
|
||||
-t $IDF_TARGET
|
||||
--copy-sdkconfig
|
||||
--parallel-count ${CI_NODE_TOTAL:-1}
|
||||
--parallel-index ${CI_NODE_INDEX:-1}
|
||||
--modified-components ${MR_MODIFIED_COMPONENTS}
|
||||
--modified-files ${MR_MODIFIED_FILES}
|
||||
$TEST_BUILD_OPTS_EXTRA
|
||||
- python tools/ci/artifacts_handler.py upload
|
||||
|
||||
######################
|
||||
# build_template_app #
|
||||
@@ -16,11 +57,18 @@
|
||||
.build_template_app_template:
|
||||
extends:
|
||||
- .build_template
|
||||
- .before_script:build
|
||||
variables:
|
||||
LOG_PATH: "${CI_PROJECT_DIR}/log_template_app"
|
||||
BUILD_PATH: "${CI_PROJECT_DIR}/build_template_app"
|
||||
BUILD_DIR: "${BUILD_PATH}/@t/@w"
|
||||
BUILD_LOG_CMAKE: "${LOG_PATH}/cmake_@t_@w.txt"
|
||||
BUILD_COMMAND_ARGS: ""
|
||||
artifacts:
|
||||
paths:
|
||||
- log_template_app/*
|
||||
- size_info.txt
|
||||
- build_template_app/**/size*.json
|
||||
- build_template_app/**/size.json
|
||||
expire_in: 1 week
|
||||
when: always
|
||||
script:
|
||||
@@ -34,71 +82,61 @@
|
||||
# Only do the default cmake build for each target, remaining part are done in the build_template_app job
|
||||
- tools/ci/build_template_app.sh ${BUILD_COMMAND_ARGS}
|
||||
|
||||
# build-related-pre-check-jobs ------------------------------------------------
|
||||
# Build at least one project for each target at earliest stage to reduce build cost for obvious failing commits
|
||||
fast_template_app:
|
||||
extends:
|
||||
- .build_template_app_template
|
||||
- .rules:build
|
||||
- .rules:build:target_test
|
||||
stage: pre_check
|
||||
tags: [fast_run, shiny]
|
||||
variables:
|
||||
BUILD_COMMAND_ARGS: "-p"
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
# This job builds template app with permutations of targets and optimization levels
|
||||
build_template_app:
|
||||
#######################
|
||||
# gnu_static_analyzer #
|
||||
#######################
|
||||
gcc_static_analyzer:
|
||||
extends:
|
||||
- .build_template_app_template
|
||||
- .rules:build
|
||||
stage: host_test
|
||||
needs:
|
||||
- job: fast_template_app
|
||||
artifacts: false
|
||||
- .rules:build:target_test
|
||||
stage: pre_check
|
||||
tags: [build, shiny]
|
||||
variables:
|
||||
CI_CCACHE_DISABLE: 1
|
||||
ANALYZING_APP: "examples/get-started/hello_world"
|
||||
script:
|
||||
- echo "CONFIG_COMPILER_STATIC_ANALYZER=y" >> ${ANALYZING_APP}/sdkconfig.defaults
|
||||
- python -m idf_build_apps build -v -p ${ANALYZING_APP} -t all
|
||||
|
||||
########################################
|
||||
# Clang Build Apps Without Tests Cases #
|
||||
########################################
|
||||
.build_cmake_clang_template:
|
||||
build_clang_test_apps_esp32:
|
||||
extends:
|
||||
- .build_template
|
||||
- .build_cmake_clang_template
|
||||
- .rules:build
|
||||
needs:
|
||||
- job: fast_template_app
|
||||
artifacts: false
|
||||
- pipeline_variables
|
||||
artifacts:
|
||||
paths:
|
||||
# The other artifacts patterns are defined under .idf_ci.toml
|
||||
# Now we're uploading/downloading the binary files from our internal storage server
|
||||
#
|
||||
# keep the log file to help debug
|
||||
- "**/build*/build_log.txt"
|
||||
# keep the size info to help track the binary size
|
||||
- size_info.txt
|
||||
- "**/build*/size*.json"
|
||||
expire_in: 1 week
|
||||
when: always
|
||||
variables:
|
||||
IDF_TOOLCHAIN: clang
|
||||
TEST_BUILD_OPTS_EXTRA: ""
|
||||
script:
|
||||
# CI specific options start from "--parallel-count xxx". could ignore when running locally
|
||||
- run_cmd idf-build-apps build
|
||||
-p tools/test_apps/system/clang_build_test
|
||||
-t $IDF_TARGET
|
||||
--parallel-count ${CI_NODE_TOTAL:-1}
|
||||
--parallel-index ${CI_NODE_INDEX:-1}
|
||||
--modified-components ${MR_MODIFIED_COMPONENTS}
|
||||
--modified-files ${MR_MODIFIED_FILES}
|
||||
$TEST_BUILD_OPTS_EXTRA
|
||||
IDF_TARGET: esp32
|
||||
|
||||
build_clang_test_apps_xtensa:
|
||||
extends: .build_cmake_clang_template
|
||||
parallel:
|
||||
matrix:
|
||||
- IDF_TARGET: [esp32, esp32s2, esp32s3]
|
||||
build_clang_test_apps_esp32s2:
|
||||
extends:
|
||||
- .build_cmake_clang_template
|
||||
- .rules:build
|
||||
variables:
|
||||
IDF_TARGET: esp32s2
|
||||
|
||||
build_clang_test_apps_riscv:
|
||||
extends: .build_cmake_clang_template
|
||||
build_clang_test_apps_esp32s3:
|
||||
extends:
|
||||
- .build_cmake_clang_template
|
||||
- .rules:build
|
||||
variables:
|
||||
IDF_TARGET: esp32s3
|
||||
|
||||
.build_clang_test_apps_riscv:
|
||||
extends:
|
||||
- .build_cmake_clang_template
|
||||
variables:
|
||||
# https://reviews.llvm.org/D90108.
|
||||
# GNU 'as' lets .weak override .globl since binutils-gdb
|
||||
@@ -106,9 +144,134 @@ build_clang_test_apps_riscv:
|
||||
# while MC lets the last directive win (PR38921).
|
||||
# For RISCV chips we use integrated assembler by default, so suppress this warning to pass CI pipeline.
|
||||
TEST_BUILD_OPTS_EXTRA: "--ignore-warning-str 'changed binding to STB_WEAK'"
|
||||
parallel:
|
||||
matrix:
|
||||
- IDF_TARGET: [esp32c3, esp32c2, esp32c6, esp32c5, esp32h2, esp32p4]
|
||||
|
||||
build_clang_test_apps_esp32c3:
|
||||
extends:
|
||||
- .build_clang_test_apps_riscv
|
||||
- .rules:build
|
||||
variables:
|
||||
IDF_TARGET: esp32c3
|
||||
|
||||
build_clang_test_apps_esp32c2:
|
||||
extends:
|
||||
- .build_clang_test_apps_riscv
|
||||
- .rules:build
|
||||
variables:
|
||||
IDF_TARGET: esp32c2
|
||||
|
||||
build_clang_test_apps_esp32c6:
|
||||
extends:
|
||||
- .build_clang_test_apps_riscv
|
||||
- .rules:build
|
||||
variables:
|
||||
IDF_TARGET: esp32c6
|
||||
|
||||
build_clang_test_apps_esp32c5:
|
||||
extends:
|
||||
- .build_clang_test_apps_riscv
|
||||
- .rules:build
|
||||
variables:
|
||||
IDF_TARGET: esp32c5
|
||||
|
||||
build_clang_test_apps_esp32h2:
|
||||
extends:
|
||||
- .build_clang_test_apps_riscv
|
||||
- .rules:build
|
||||
variables:
|
||||
IDF_TARGET: esp32h2
|
||||
|
||||
build_clang_test_apps_esp32p4:
|
||||
extends:
|
||||
- .build_clang_test_apps_riscv
|
||||
- .rules:build
|
||||
variables:
|
||||
IDF_TARGET: esp32p4
|
||||
|
||||
######################
|
||||
# Build System Tests #
|
||||
######################
|
||||
.test_build_system_template:
|
||||
stage: host_test
|
||||
extends:
|
||||
- .build_template
|
||||
- .rules:build:check
|
||||
dependencies: # set dependencies to null to avoid missing artifacts issue
|
||||
needs:
|
||||
- job: fast_template_app
|
||||
artifacts: false
|
||||
optional: true
|
||||
artifacts:
|
||||
reports:
|
||||
junit: XUNIT_RESULT.xml
|
||||
paths:
|
||||
- XUNIT_RESULT.xml
|
||||
- test_build_system
|
||||
expire_in: 1 week
|
||||
when: always
|
||||
script:
|
||||
- ${IDF_PATH}/tools/ci/test_configure_ci_environment.sh
|
||||
- cd ${IDF_PATH}/tools/test_build_system
|
||||
- python ${IDF_PATH}/tools/ci/get_known_failure_cases_file.py
|
||||
- pytest
|
||||
--cleanup-idf-copy
|
||||
--parallel-count ${CI_NODE_TOTAL:-1}
|
||||
--parallel-index ${CI_NODE_INDEX:-1}
|
||||
--work-dir ${CI_PROJECT_DIR}/test_build_system
|
||||
--junitxml ${CI_PROJECT_DIR}/XUNIT_RESULT.xml
|
||||
--ignore-result-files ${KNOWN_FAILURE_CASES_FILE_NAME}
|
||||
|
||||
pytest_build_system:
|
||||
extends: .test_build_system_template
|
||||
parallel: 3
|
||||
|
||||
pytest_build_system_macos:
|
||||
extends:
|
||||
- .test_build_system_template
|
||||
- .before_script:build:macos
|
||||
- .after_script:build:macos:upload-failed-job-logs:ccache-show-stats
|
||||
- .rules:build:macos
|
||||
tags:
|
||||
- macos_shell
|
||||
parallel: 3
|
||||
variables:
|
||||
PYENV_VERSION: "3.9"
|
||||
# CCACHE_DIR: "/cache/idf_ccache". On macOS, you cannot write to this folder due to insufficient permissions.
|
||||
CCACHE_DIR: "" # ccache will use "$HOME/Library/Caches/ccache".
|
||||
CCACHE_MAXSIZE: "5G" # To preserve the limited Macbook storage. CCACHE automatically prunes old caches to fit the set limit.
|
||||
build_docker:
|
||||
extends:
|
||||
- .before_script:minimal
|
||||
- .rules:build:docker
|
||||
stage: host_test
|
||||
needs: []
|
||||
image: espressif/docker-builder:1
|
||||
tags:
|
||||
- build_docker_amd64_brno
|
||||
variables:
|
||||
DOCKER_TMP_IMAGE_NAME: "idf_tmp_image"
|
||||
script:
|
||||
- export LOCAL_CI_REPOSITORY_URL=$CI_REPOSITORY_URL
|
||||
- if [ -n "$LOCAL_GITLAB_HTTPS_HOST" ]; then export LOCAL_CI_REPOSITORY_URL="https://gitlab-ci-token:${CI_JOB_TOKEN}@${LOCAL_GITLAB_HTTPS_HOST}/${CI_PROJECT_PATH}"; fi
|
||||
- if [ -n "$LOCAL_GIT_MIRROR" ]; then export LOCAL_CI_REPOSITORY_URL="${LOCAL_GIT_MIRROR}/${CI_PROJECT_PATH}"; fi
|
||||
- echo "Using repository at $LOCAL_CI_REPOSITORY_URL"
|
||||
- export DOCKER_BUILD_ARGS="--build-arg IDF_CLONE_URL=${LOCAL_CI_REPOSITORY_URL} --build-arg IDF_CLONE_BRANCH_OR_TAG=${CI_COMMIT_REF_NAME} --build-arg IDF_CHECKOUT_REF=${CI_COMMIT_TAG:-$PIPELINE_COMMIT_SHA}"
|
||||
# Build
|
||||
- docker build --tag ${DOCKER_TMP_IMAGE_NAME} ${DOCKER_BUILD_ARGS} tools/docker/
|
||||
# We can't mount $PWD/examples/get-started/blink into the container, see https://gitlab.com/gitlab-org/gitlab-ce/issues/41227.
|
||||
# The workaround mentioned there works, but leaves around directories which need to be cleaned up manually.
|
||||
# Therefore, build a copy of the example located inside the container.
|
||||
- docker run --rm --workdir /opt/esp/idf/examples/get-started/blink ${DOCKER_TMP_IMAGE_NAME} idf.py build
|
||||
|
||||
# This job builds template app with permutations of targets and optimization levels
|
||||
build_template_app:
|
||||
extends:
|
||||
- .build_template_app_template
|
||||
- .rules:build
|
||||
stage: host_test
|
||||
dependencies: # set dependencies to null to avoid missing artifacts issue
|
||||
needs:
|
||||
- job: fast_template_app
|
||||
artifacts: false
|
||||
|
||||
####################
|
||||
# Dynamic Pipeline #
|
||||
@@ -129,12 +292,12 @@ generate_build_child_pipeline:
|
||||
- non_test_related_apps.txt
|
||||
expire_in: 1 week
|
||||
when: always
|
||||
variables:
|
||||
PYTEST_IGNORE_COLLECT_IMPORT_ERROR: "1"
|
||||
script:
|
||||
- run_cmd idf-ci --debug gitlab build-child-pipeline
|
||||
-p components
|
||||
-p examples
|
||||
-p tools/test_apps
|
||||
--modified-files $MR_MODIFIED_FILES
|
||||
# requires basic pytest dependencies
|
||||
- run_cmd bash install.sh --enable-pytest
|
||||
- run_cmd python tools/ci/dynamic_pipelines/scripts/generate_build_child_pipeline.py
|
||||
|
||||
build_child_pipeline:
|
||||
stage: build
|
||||
@@ -145,9 +308,12 @@ build_child_pipeline:
|
||||
- pipeline_variables
|
||||
- generate_build_child_pipeline
|
||||
variables:
|
||||
IS_MR_PIPELINE: $IS_MR_PIPELINE
|
||||
MR_MODIFIED_COMPONENTS: $MR_MODIFIED_COMPONENTS
|
||||
MR_MODIFIED_FILES: $MR_MODIFIED_FILES
|
||||
PARENT_PIPELINE_ID: $CI_PIPELINE_ID
|
||||
BUILD_AND_TEST_ALL_APPS: $BUILD_AND_TEST_ALL_APPS
|
||||
REPORT_EXIT_CODE: $REPORT_EXIT_CODE
|
||||
# https://gitlab.com/gitlab-org/gitlab/-/issues/214340
|
||||
inherit:
|
||||
variables: false
|
||||
@@ -156,22 +322,3 @@ build_child_pipeline:
|
||||
- artifact: build_child_pipeline.yml
|
||||
job: generate_build_child_pipeline
|
||||
strategy: depend
|
||||
|
||||
generate_disabled_apps_report:
|
||||
extends:
|
||||
- .build_template
|
||||
tags: [fast_run, shiny]
|
||||
dependencies: # set dependencies to null to avoid missing artifacts issue
|
||||
needs:
|
||||
- pipeline_variables
|
||||
- job: baseline_manifest_sha
|
||||
optional: true
|
||||
artifacts:
|
||||
paths:
|
||||
- disabled_report.html
|
||||
expire_in: 1 week
|
||||
when: always
|
||||
script:
|
||||
- pip install dominate idf-build-apps
|
||||
- run_cmd python tools/ci/gen_disabled_report.py --output disabled_report.html --verbose --enable-preview-targets
|
||||
- echo "Report generated at https://${CI_PAGES_HOSTNAME}:${CI_SERVER_PORT}/-/esp-idf/-/jobs/${CI_JOB_ID}/artifacts/disabled_report.html"
|
||||
|
||||
@@ -12,6 +12,7 @@ stages:
|
||||
- test_deploy
|
||||
- deploy
|
||||
- post_deploy
|
||||
- retry_failed_jobs
|
||||
|
||||
variables:
|
||||
# System environment
|
||||
@@ -29,14 +30,17 @@ variables:
|
||||
# - set GIT_STRATEGY: "clone" to shiny runners
|
||||
# - set GIT_STRATEGY: "fetch" to brew runners
|
||||
GIT_STRATEGY: clone
|
||||
GIT_DEPTH: 1
|
||||
GIT_SUBMODULE_STRATEGY: none # here we use cache for submodules, so we don't need to fetch them every time
|
||||
# we will download archive for each submodule instead of clone.
|
||||
# we don't do "recursive" when fetch submodule as they're not used in CI now.
|
||||
GIT_SUBMODULE_STRATEGY: none
|
||||
# since we're using merged-result pipelines, the last commit should work for most cases
|
||||
GIT_DEPTH: 1
|
||||
# --no-recurse-submodules: we use cache for submodules
|
||||
# --prune --prune-tags: in case remote branch or tag is force pushed
|
||||
GIT_FETCH_EXTRA_FLAGS: "--no-recurse-submodules --prune --prune-tags"
|
||||
# we're using .cache folder for caches
|
||||
GIT_CLEAN_FLAGS: -ffdx -e .cache/
|
||||
LATEST_GIT_TAG: v6.1-dev
|
||||
LATEST_GIT_TAG: v5.5
|
||||
|
||||
SUBMODULE_FETCH_TOOL: "tools/ci/ci_fetch_submodule.py"
|
||||
# by default we will fetch all submodules
|
||||
@@ -51,10 +55,11 @@ variables:
|
||||
CHECKOUT_REF_SCRIPT: "$CI_PROJECT_DIR/tools/ci/checkout_project_ref.py"
|
||||
|
||||
# Docker images
|
||||
ESP_ENV_IMAGE: "${CI_DOCKER_REGISTRY}/esp-env-v6.1:1"
|
||||
ESP_IDF_DOC_ENV_IMAGE: "${CI_DOCKER_REGISTRY}/esp-idf-doc-env-v6.1:1-1"
|
||||
TARGET_TEST_ENV_IMAGE: "${CI_DOCKER_REGISTRY}/target-test-env-v6.1:1"
|
||||
ESP_ENV_IMAGE: "${CI_DOCKER_REGISTRY}/esp-env-v5.5:3"
|
||||
ESP_IDF_DOC_ENV_IMAGE: "${CI_DOCKER_REGISTRY}/esp-idf-doc-env-v5.5:3-1"
|
||||
TARGET_TEST_ENV_IMAGE: "${CI_DOCKER_REGISTRY}/target-test-env-v5.5:2"
|
||||
SONARQUBE_SCANNER_IMAGE: "${CI_DOCKER_REGISTRY}/sonarqube-scanner:5"
|
||||
PRE_COMMIT_IMAGE: "${CI_DOCKER_REGISTRY}/esp-idf-pre-commit:1"
|
||||
|
||||
# cache python dependencies
|
||||
PIP_CACHE_DIR: "$CI_PROJECT_DIR/.cache/pip"
|
||||
@@ -65,7 +70,7 @@ variables:
|
||||
CI_PYTHON_CONSTRAINT_BRANCH: ""
|
||||
|
||||
# Update the filename for a specific ESP-IDF release. It is used only with CI_PYTHON_CONSTRAINT_BRANCH.
|
||||
CI_PYTHON_CONSTRAINT_FILE: "espidf.constraints.v6.1.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.
|
||||
@@ -96,7 +101,6 @@ variables:
|
||||
CCACHE_MAXSIZE: "50G"
|
||||
|
||||
FF_USE_NEW_BASH_EVAL_STRATEGY: "true"
|
||||
FORCE_COLOR: "1" # rich print with color
|
||||
|
||||
################################################
|
||||
# `before_script` and `after_script` Templates #
|
||||
@@ -119,7 +123,7 @@ variables:
|
||||
source tools/ci/configure_ci_environment.sh
|
||||
|
||||
# add extra python packages
|
||||
export PYTHONPATH="$IDF_PATH/tools:$IDF_PATH/tools/ci:$IDF_PATH/tools/esp_app_trace:$IDF_PATH/components/partition_table:$IDF_PATH/tools/ci/python_packages:$PYTHONPATH"
|
||||
export PYTHONPATH="$IDF_PATH/tools:$IDF_PATH/tools/esp_app_trace:$IDF_PATH/components/partition_table:$IDF_PATH/tools/ci/python_packages:$PYTHONPATH"
|
||||
|
||||
.setup_tools_and_idf_python_venv: &setup_tools_and_idf_python_venv |
|
||||
# must use after setup_tools_except_target_test
|
||||
@@ -127,7 +131,7 @@ variables:
|
||||
|
||||
# download constraint file for dev
|
||||
if [[ -n "$CI_PYTHON_CONSTRAINT_BRANCH" ]]; then
|
||||
wget -O /tmp/constraint.txt --header="Authorization:Bearer ${ESPCI_TOKEN}" "${GITLAB_HTTP_SERVER}/api/v4/projects/2581/repository/files/${CI_PYTHON_CONSTRAINT_FILE}/raw?ref=${CI_PYTHON_CONSTRAINT_BRANCH}"
|
||||
wget -O /tmp/constraint.txt --header="Authorization:Bearer ${ESPCI_TOKEN}" ${GITLAB_HTTP_SERVER}/api/v4/projects/2581/repository/files/${CI_PYTHON_CONSTRAINT_FILE}/raw?ref=${CI_PYTHON_CONSTRAINT_BRANCH}
|
||||
mkdir -p ~/.espressif
|
||||
mv /tmp/constraint.txt ~/.espressif/${CI_PYTHON_CONSTRAINT_FILE}
|
||||
fi
|
||||
@@ -136,64 +140,46 @@ variables:
|
||||
if [[ -n "$IDF_DONT_USE_MIRRORS" ]]; then
|
||||
export IDF_MIRROR_PREFIX_MAP=
|
||||
fi
|
||||
# Optimize pip install
|
||||
if echo "${CI_RUNNER_TAGS}" | grep "shiny"; then
|
||||
export PIP_INDEX_URL="${PIP_INDEX_URL_SHINY}"
|
||||
fi
|
||||
if [[ "$(uname -m)" == "x86_64" ]] || [[ "$(uname -m)" == "aarch64" ]]; then
|
||||
export IDF_PIP_WHEELS_URL=""
|
||||
fi
|
||||
|
||||
# install.sh
|
||||
if [[ "${CI_JOB_STAGE}" != "target_test" ]]; then
|
||||
section_start "running_install_sh" "Running install.sh"
|
||||
if [[ "${CI_JOB_STAGE}" == "build_doc" ]]; then
|
||||
run_cmd bash install.sh --enable-ci --enable-docs
|
||||
else
|
||||
elif [[ "${CI_JOB_STAGE}" == "build" ]]; then
|
||||
run_cmd bash install.sh --enable-ci
|
||||
else
|
||||
if ! echo "${CI_JOB_NAME}" | egrep ".*pytest.*"; then
|
||||
run_cmd bash install.sh --enable-ci
|
||||
else
|
||||
run_cmd bash install.sh --enable-ci --enable-pytest --enable-test-specific
|
||||
fi
|
||||
fi
|
||||
section_end "running_install_sh"
|
||||
else
|
||||
section_start "install_python_env" "Install Python environment, skip required tools check"
|
||||
run_cmd python tools/idf_tools.py install-python-env --features ci,test-specific
|
||||
export IDF_SKIP_TOOLS_CHECK=1
|
||||
section_start "install_python_env" "Install Python environment"
|
||||
run_cmd python tools/idf_tools.py install-python-env --features ci,pytest,test-specific
|
||||
section_end "install_python_env"
|
||||
fi
|
||||
|
||||
section_start "source_export" "Source export.sh"
|
||||
source ./export.sh
|
||||
section_end "source_export"
|
||||
|
||||
# Eager upgrade of CI dependencies
|
||||
# Done after sourcing export.sh so that we could easily invoke the right pip
|
||||
section_start "upgrade_ci_dependencies" "Upgrading CI dependencies"
|
||||
pip install --upgrade --upgrade-strategy=eager -r $IDF_PATH/tools/requirements/requirements.ci.txt -c ~/.espressif/${CI_PYTHON_CONSTRAINT_FILE}
|
||||
if [[ "${CI_JOB_STAGE}" == "target_test" ]]; then
|
||||
pip install --upgrade --upgrade-strategy=eager -r $IDF_PATH/tools/requirements/requirements.test-specific.txt -c ~/.espressif/${CI_PYTHON_CONSTRAINT_FILE}
|
||||
fi
|
||||
section_end "upgrade_ci_dependencies"
|
||||
|
||||
REEXPORT_NEEDED=0
|
||||
if [[ ! -z "$INSTALL_EXTRA_TOOLS" ]]; then
|
||||
section_start "installing_optional_tools" "Install optional tools ${INSTALL_EXTRA_TOOLS}"
|
||||
run_cmd $IDF_PATH/tools/idf_tools.py --non-interactive install $INSTALL_EXTRA_TOOLS
|
||||
$IDF_PATH/tools/idf_tools.py --non-interactive install $INSTALL_EXTRA_TOOLS
|
||||
section_end "installing_optional_tools"
|
||||
|
||||
REEXPORT_NEEDED=1
|
||||
fi
|
||||
|
||||
# Install esp-clang if necessary (esp-clang is separately installed)
|
||||
if [[ "$IDF_TOOLCHAIN" == "clang" && -z "$CI_CLANG_DISTRO_URL" ]]; then
|
||||
$IDF_PATH/tools/idf_tools.py --non-interactive install esp-clang
|
||||
|
||||
REEXPORT_NEEDED=1
|
||||
fi
|
||||
|
||||
if [[ $REEXPORT_NEEDED -eq 1 ]]; then
|
||||
section_start "re_source_export" "Re-source export.sh"
|
||||
source ./export.sh
|
||||
section_end "re_source_export"
|
||||
if [[ "${CI_JOB_STAGE}" == "target_test" ]]; then
|
||||
section_start "IDF_SKIP_TOOLS_CHECK" "Skip required tools check"
|
||||
export IDF_SKIP_TOOLS_CHECK=1
|
||||
section_end "IDF_SKIP_TOOLS_CHECK"
|
||||
fi
|
||||
section_start "source_export" "Source export.sh"
|
||||
source ./export.sh
|
||||
section_end "source_export"
|
||||
|
||||
# Custom clang toolchain
|
||||
if [[ "$IDF_TOOLCHAIN" == "clang" && ! -z "$CI_CLANG_DISTRO_URL" ]]; then
|
||||
@@ -232,19 +218,43 @@ variables:
|
||||
|
||||
.show_ccache_statistics: &show_ccache_statistics |
|
||||
# Show ccache statistics if enabled globally
|
||||
section_start "ccache_show_stats" "Show ccache statistics"
|
||||
test "$CI_CCACHE_STATS" == 1 && test -n "$(which ccache)" && ccache --show-stats -vv || true
|
||||
section_end "ccache_show_stats"
|
||||
|
||||
.upload_failed_job_log_artifacts: &upload_failed_job_log_artifacts |
|
||||
if [ $CI_JOB_STATUS = "failed" ]; then
|
||||
run_cmd idf-ci gitlab upload-artifacts --type log
|
||||
python tools/ci/artifacts_handler.py upload --type logs
|
||||
fi
|
||||
|
||||
.before_script:minimal:
|
||||
before_script:
|
||||
- *common-before_scripts
|
||||
|
||||
.before_script:build:macos:
|
||||
before_script:
|
||||
# macos is running shell executor, which means it would use
|
||||
# the system installed /usr/local/bin/python3 by default.
|
||||
# Ensure pyenv and PYENV_VERSION installed
|
||||
- eval "$(pyenv init -)"
|
||||
- *common-before_scripts
|
||||
# On macOS, these tools need to be installed
|
||||
- export IDF_TOOLS_PATH="${HOME}/.espressif_runner_${CI_RUNNER_ID}_${CI_CONCURRENT_ID}"
|
||||
# remove idf-env.json, since it may contains enabled "features"
|
||||
- rm -f $IDF_TOOLS_PATH/idf-env.json
|
||||
# This adds tools (compilers) and the version-specific Python environment to PATH
|
||||
- *setup_tools_and_idf_python_venv
|
||||
- fetch_submodules
|
||||
variables:
|
||||
INSTALL_EXTRA_TOOLS: cmake ninja
|
||||
|
||||
.after_script:build:macos:upload-failed-job-logs:ccache-show-stats:
|
||||
after_script:
|
||||
# macos is running shell executor, which means it would use
|
||||
# the system installed /usr/local/bin/python3 by default.
|
||||
# Ensure pyenv and PYENV_VERSION installed
|
||||
- eval "$(pyenv init -)"
|
||||
- *upload_failed_job_log_artifacts
|
||||
- *show_ccache_statistics
|
||||
|
||||
.before_script:build:
|
||||
before_script:
|
||||
- *common-before_scripts
|
||||
@@ -254,9 +264,12 @@ variables:
|
||||
- export EXTRA_CFLAGS=${PEDANTIC_CFLAGS}
|
||||
- export EXTRA_CXXFLAGS=${PEDANTIC_CXXFLAGS}
|
||||
|
||||
.after_script:build:
|
||||
.after_script:build:ccache-show-stats:
|
||||
after_script:
|
||||
- *show_ccache_statistics
|
||||
|
||||
.after_script:build:ccache-show-stats:upload-failed-job-logs:
|
||||
after_script:
|
||||
- source tools/ci/utils.sh
|
||||
- *show_ccache_statistics
|
||||
- *upload_failed_job_log_artifacts
|
||||
|
||||
@@ -296,7 +309,7 @@ variables:
|
||||
|
||||
.git_checkout_ci_commit_sha: &git_checkout_ci_commit_sha |
|
||||
git checkout $CI_COMMIT_SHA
|
||||
eval "git clean ${GIT_CLEAN_FLAGS}"
|
||||
git clean ${GIT_CLEAN_FLAGS}
|
||||
|
||||
# git diff requires two commits, with different CI env var
|
||||
#
|
||||
@@ -318,10 +331,9 @@ variables:
|
||||
TEMP_FILE=$(mktemp)
|
||||
# merged results pipelines, by default
|
||||
if [[ -n $CI_MERGE_REQUEST_SOURCE_BRANCH_SHA ]]; then
|
||||
git fetch origin $CI_MERGE_REQUEST_TARGET_BRANCH_SHA
|
||||
git fetch origin $CI_MERGE_REQUEST_SOURCE_BRANCH_SHA
|
||||
|
||||
git diff --name-only $CI_MERGE_REQUEST_TARGET_BRANCH_SHA...$CI_MERGE_REQUEST_SOURCE_BRANCH_SHA > "$TEMP_FILE"
|
||||
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}
|
||||
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
|
||||
@@ -355,48 +367,13 @@ variables:
|
||||
before_script:
|
||||
- *git_init
|
||||
- *git_fetch_from_mirror_url_if_exists
|
||||
- eval "git fetch --depth=1 ${GIT_FETCH_EXTRA_FLAGS} origin ${CI_COMMIT_SHA}"
|
||||
- git fetch origin "${CI_COMMIT_SHA}" --depth=1 ${GIT_FETCH_EXTRA_FLAGS}
|
||||
- *git_checkout_ci_commit_sha
|
||||
- *common-before_scripts
|
||||
- *setup_tools_and_idf_python_venv
|
||||
- add_gitlab_ssh_keys
|
||||
# no submodules
|
||||
|
||||
.brew-macos-settings:
|
||||
variables:
|
||||
GIT_STRATEGY: none # we do manual git clone to use local mirror
|
||||
IDF_CCACHE_ENABLE: "0"
|
||||
CCACHE_DIR: "/var/tmp/cache/idf_ccache"
|
||||
tags:
|
||||
- macos-tart
|
||||
image: macos-sequoia-idf-v6.1
|
||||
cache: [] # pip cache is created under amd64, and submodules are downloaded with brew mirror, so disable cache here
|
||||
before_script:
|
||||
# assert LOCAL_GIT_MIRROR is set
|
||||
- echo -e "section_start:`date +%s`:check_out\r\e[0Kchecking out from local git mirror, then reset to CI_COMMIT_SHA"
|
||||
- |
|
||||
if [ -z "${LOCAL_GIT_MIRROR:-}" ]; then
|
||||
echo "Error: LOCAL_GIT_MIRROR not set, cannot clone from mirror."
|
||||
exit 1
|
||||
fi
|
||||
- MIRROR_REPO_URL="${LOCAL_GIT_MIRROR}/${CI_PROJECT_PATH}"
|
||||
- cd "${CI_PROJECT_DIR}"
|
||||
# since .cache exists in CI_PROJECT_DIR, so can't direct `git clone .`
|
||||
- git clone -b ${CI_MERGE_REQUEST_TARGET_BRANCH_NAME:-${CI_COMMIT_BRANCH}} --depth=1 --recursive --shallow-submodules "${MIRROR_REPO_URL}" tmp
|
||||
- mv tmp/.git ./
|
||||
- rm -rf tmp
|
||||
- git reset --hard
|
||||
# set remote url back
|
||||
- git remote set-url origin "${CI_REPOSITORY_URL}"
|
||||
- eval "git fetch --depth=1 ${GIT_FETCH_EXTRA_FLAGS} origin ${CI_COMMIT_SHA}"
|
||||
- git checkout FETCH_HEAD
|
||||
- git submodule update --init --recursive --depth=1
|
||||
- echo -e "section_end:`date +%s`:check_out\r\e[0K"
|
||||
- *common-before_scripts
|
||||
- *setup_tools_and_idf_python_venv
|
||||
after_script: [] # ccache now is disabled for macos brew runners
|
||||
timeout: 30m
|
||||
|
||||
#############
|
||||
# `default` #
|
||||
#############
|
||||
|
||||
@@ -2,15 +2,19 @@
|
||||
# - extra_default_build_targets:
|
||||
# besides of the SUPPORTED_TARGETS in IDF,
|
||||
# enable build for the specified targets by default as well.
|
||||
# !!! DEPRECATED: use `additional_build_targets` in .idf_build_apps.toml instead
|
||||
#
|
||||
# - bypass_check_test_targets:
|
||||
# suppress the check_build_test_rules check-test-script warnings for the specified targets
|
||||
#
|
||||
# This file should ONLY be used during bringup. Should be reset to empty after the bringup process
|
||||
extra_default_build_targets:
|
||||
- esp32c5
|
||||
- esp32c61
|
||||
- esp32h21
|
||||
- esp32h4
|
||||
|
||||
bypass_check_test_targets:
|
||||
- esp32h21
|
||||
- esp32c61
|
||||
- esp32h4
|
||||
- esp32c5
|
||||
|
||||
|
||||
@@ -1,3 +1,19 @@
|
||||
.all_targets: &all_targets
|
||||
- esp32
|
||||
- esp32s2
|
||||
- esp32s3
|
||||
- esp32c3
|
||||
- esp32c2
|
||||
- esp32c6
|
||||
- esp32c5
|
||||
- esp32h2
|
||||
- esp32p4
|
||||
|
||||
.target_test: &target_test
|
||||
- example_test
|
||||
- custom_test
|
||||
- component_ut
|
||||
|
||||
##############
|
||||
# Build Jobs #
|
||||
##############
|
||||
@@ -9,6 +25,7 @@
|
||||
- build_system
|
||||
- downloadable-tools
|
||||
included_in:
|
||||
- build:target_test
|
||||
- build:check
|
||||
|
||||
# -------------------
|
||||
@@ -26,13 +43,13 @@
|
||||
|
||||
"build:macos":
|
||||
labels:
|
||||
# - build
|
||||
- build
|
||||
- macos
|
||||
- macos_test # for backward compatibility
|
||||
# patterns:
|
||||
# - build_system
|
||||
# - build_macos
|
||||
# - downloadable-tools
|
||||
patterns:
|
||||
- build_system
|
||||
- build_macos
|
||||
- downloadable-tools
|
||||
|
||||
# ---------------------------
|
||||
# Add patterns to build rules
|
||||
@@ -40,6 +57,8 @@
|
||||
"patterns:template-app":
|
||||
patterns:
|
||||
- build_template-app
|
||||
included_in:
|
||||
- build:target_test
|
||||
|
||||
"patterns:build-check":
|
||||
patterns:
|
||||
@@ -72,8 +91,4 @@
|
||||
specific_rules:
|
||||
- if-schedule-test-build-system-windows
|
||||
patterns:
|
||||
- build_system_win
|
||||
|
||||
"labels:buildv2":
|
||||
labels:
|
||||
- buildv2
|
||||
- build_system
|
||||
|
||||
@@ -3,27 +3,7 @@
|
||||
image: $ESP_ENV_IMAGE
|
||||
tags: [ deploy ]
|
||||
|
||||
.metrics_template:
|
||||
stage: deploy
|
||||
tags: [ fast_run, shiny ]
|
||||
image: python:3.13-slim
|
||||
dependencies: []
|
||||
needs: []
|
||||
variables:
|
||||
PIP_CACHE_DIR: ".cache/pip"
|
||||
# Metrics - related env vars
|
||||
ESP_METRICS_PROJECT_URL: "$CI_PROJECT_URL"
|
||||
ESP_METRICS_PROJECT_ID: "$CI_PROJECT_ID"
|
||||
ESP_METRICS_COMMIT_SHA: "$PIPELINE_COMMIT_SHA"
|
||||
ESP_METRICS_BRANCH_NAME: "$CI_COMMIT_REF_NAME"
|
||||
cache:
|
||||
key: metrics-pip
|
||||
paths:
|
||||
- .cache/pip
|
||||
before_script:
|
||||
- echo "Installing esp-metrics-cli tool"
|
||||
- pip install "esp-metrics-cli>=0.3,<1"
|
||||
|
||||
# Check this before push_to_github
|
||||
check_submodule_sync:
|
||||
extends:
|
||||
- .deploy_job_template
|
||||
@@ -32,13 +12,13 @@ check_submodule_sync:
|
||||
tags: [ brew, github_sync ]
|
||||
retry: 2
|
||||
variables:
|
||||
GIT_STRATEGY: fetch # use brew local mirror first
|
||||
# for brew runners, we always set GIT_STRATEGY to fetch
|
||||
GIT_STRATEGY: fetch
|
||||
SUBMODULES_TO_FETCH: "none"
|
||||
PUBLIC_IDF_URL: "https://github.com/espressif/esp-idf.git"
|
||||
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
|
||||
@@ -51,65 +31,31 @@ push_to_github:
|
||||
extends:
|
||||
- .deploy_job_template
|
||||
- .before_script:minimal
|
||||
- .rules:protected:deploy
|
||||
- .rules:push_to_github
|
||||
needs:
|
||||
# submodule must be synced before pushing to github
|
||||
- check_submodule_sync
|
||||
tags: [ brew, github_sync ]
|
||||
variables:
|
||||
GIT_STRATEGY: fetch # use brew local mirror first
|
||||
GIT_DEPTH: 0 # github needs full record of commits
|
||||
# for brew runners, we always set GIT_STRATEGY to fetch
|
||||
GIT_STRATEGY: fetch
|
||||
# github also need full record of commits
|
||||
GIT_DEPTH: 0
|
||||
script:
|
||||
- add_github_ssh_keys
|
||||
- git remote remove github &>/dev/null || true
|
||||
- git remote add github git@github.com:espressif/esp-idf.git
|
||||
- tools/ci/push_to_github.sh
|
||||
environment:
|
||||
name: push_to_github_production
|
||||
deployment_tier: production
|
||||
url: "https://github.com/espressif/esp-idf"
|
||||
|
||||
deploy_update_SHA_in_esp-dockerfiles:
|
||||
extends:
|
||||
- .deploy_job_template
|
||||
- .before_script:minimal
|
||||
- .rules:protected:deploy
|
||||
- .rules:protected-no_label-always
|
||||
dependencies: []
|
||||
variables:
|
||||
GIT_DEPTH: 2
|
||||
tags: [build, shiny]
|
||||
tags: [ shiny, build ]
|
||||
script:
|
||||
- 'curl --header "PRIVATE-TOKEN: ${ESPCI_SCRIPTS_TOKEN}" -o create_MR_in_esp_dockerfile.sh $GITLAB_HTTP_SERVER/api/v4/projects/1260/repository/files/create_MR_in_esp_dockerfile%2Fcreate_MR_in_esp_dockerfile.sh/raw\?ref\=master'
|
||||
- chmod +x create_MR_in_esp_dockerfile.sh
|
||||
- ./create_MR_in_esp_dockerfile.sh
|
||||
environment:
|
||||
name: deploy_update_SHA_in_esp-dockerfiles_production
|
||||
deployment_tier: production
|
||||
|
||||
upload_junit_report:
|
||||
extends:
|
||||
- .deploy_job_template
|
||||
tags: [ fast_run, shiny ]
|
||||
needs:
|
||||
- pipeline_variables
|
||||
- job: build_child_pipeline
|
||||
artifacts: false
|
||||
script:
|
||||
- run_cmd idf-ci gitlab download-artifacts --type junit
|
||||
rules:
|
||||
- when: always
|
||||
artifacts:
|
||||
reports:
|
||||
junit: XUNIT_RESULT_*.xml
|
||||
expire_in: 1 week
|
||||
when: always
|
||||
|
||||
target-examples-count-metrics:
|
||||
extends:
|
||||
- .metrics_template
|
||||
allow_failure: true
|
||||
script:
|
||||
- echo "Generating ESP-IDF examples count metrics"
|
||||
- cd tools/ci/metrics/examples_count
|
||||
- python3 generate_metrics.py
|
||||
- esp-metrics-cli upload -d schema.yaml -i metrics.json
|
||||
|
||||
@@ -4,11 +4,11 @@
|
||||
- "**/*.rst"
|
||||
- "CONTRIBUTING.rst"
|
||||
- "**/soc_caps.h"
|
||||
- "**/Kconfig*"
|
||||
|
||||
.patterns-docs-partial: &patterns-docs-partial
|
||||
- "components/**/*.h"
|
||||
- "components/**/CMakeLists.txt"
|
||||
- "components/**/Kconfig*"
|
||||
- "components/**/CMakeList.txt"
|
||||
- "components/**/sdkconfig*"
|
||||
- "tools/tools.json"
|
||||
- "tools/idf_tools.py"
|
||||
@@ -19,9 +19,12 @@
|
||||
.patterns-docs-preview: &patterns-docs-preview
|
||||
- "docs/**/*"
|
||||
|
||||
.if-protected-check: &if-protected-check
|
||||
.if-protected: &if-protected
|
||||
if: '($CI_COMMIT_REF_NAME == "master" || $CI_COMMIT_BRANCH =~ /^release\/v/ || $CI_COMMIT_TAG =~ /^v\d+\.\d+(\.\d+)?($|-)/)'
|
||||
|
||||
.if-protected-no_label: &if-protected-no_label
|
||||
if: '($CI_COMMIT_REF_NAME == "master" || $CI_COMMIT_BRANCH =~ /^release\/v/ || $CI_COMMIT_TAG =~ /^v\d+\.\d+(\.\d+)?($|-)/) && $BOT_TRIGGER_WITH_LABEL == null'
|
||||
|
||||
.if-qa-test-tag: &if-qa-test-tag
|
||||
if: '$CI_COMMIT_TAG =~ /^qa-test/'
|
||||
|
||||
@@ -38,7 +41,7 @@
|
||||
rules:
|
||||
- <<: *if-qa-test-tag
|
||||
when: never
|
||||
- <<: *if-protected-check
|
||||
- <<: *if-protected
|
||||
- <<: *if-label-build_docs
|
||||
- <<: *if-label-docs_full
|
||||
- <<: *if-dev-push
|
||||
@@ -58,10 +61,10 @@
|
||||
check_readme_links:
|
||||
extends:
|
||||
- .pre_check_template
|
||||
tags: ["amd64", "brew"]
|
||||
tags: ["build", "amd64", "internet"]
|
||||
allow_failure: true
|
||||
rules:
|
||||
- <<: *if-protected-check
|
||||
- <<: *if-protected
|
||||
- <<: *if-dev-push
|
||||
changes: *patterns-example-readme
|
||||
script:
|
||||
@@ -93,7 +96,7 @@ check_docs_lang_sync:
|
||||
parallel:
|
||||
matrix:
|
||||
- DOCLANG: ["en", "zh_CN"]
|
||||
DOCTGT: ["esp32", "esp32s2", "esp32s3", "esp32c3", "esp32c2", "esp32c6", "esp32c61", "esp32c5", "esp32h2", "esp32h4", "esp32h21", "esp32p4"]
|
||||
DOCTGT: ["esp32", "esp32s2", "esp32s3", "esp32c3", "esp32c2", "esp32c6", "esp32c61", "esp32c5","esp32h2", "esp32h21", "esp32p4"]
|
||||
|
||||
check_docs_gh_links:
|
||||
image: $ESP_IDF_DOC_ENV_IMAGE
|
||||
@@ -148,8 +151,8 @@ build_docs_html_partial:
|
||||
GIT_DEPTH: 0
|
||||
stage: test_deploy
|
||||
tags:
|
||||
- brew
|
||||
- amd64
|
||||
- deploy
|
||||
- shiny
|
||||
script:
|
||||
# ensure all tags are fetched, need to know the latest/stable tag for the docs
|
||||
- git fetch --tags --prune
|
||||
@@ -179,17 +182,14 @@ deploy_docs_preview:
|
||||
DOCS_DEPLOY_SERVER_USER: "$DOCS_SERVER_USER"
|
||||
DOCS_DEPLOY_PATH: "$DOCS_PATH"
|
||||
DOCS_DEPLOY_URL_BASE: "https://$DOCS_PREVIEW_SERVER_URL/docs/esp-idf"
|
||||
environment:
|
||||
name: deploy_docs_preview
|
||||
deployment_tier: staging
|
||||
url: "https://$DOCS_PREVIEW_SERVER_URL/docs/esp-idf"
|
||||
|
||||
# stage: post_deploy
|
||||
deploy_docs_production:
|
||||
# The DOCS_PROD_* variables used by this job are "Protected" so these branches must all be marked "Protected" in Gitlab settings
|
||||
extends:
|
||||
- .deploy_docs_template
|
||||
- .rules:protected:deploy
|
||||
rules:
|
||||
- <<: *if-protected-no_label
|
||||
stage: post_deploy
|
||||
dependencies: # set dependencies to null to avoid missing artifacts issue
|
||||
needs: # ensure runs after push_to_github succeeded
|
||||
@@ -204,15 +204,12 @@ deploy_docs_production:
|
||||
DOCS_DEPLOY_PATH: "$DOCS_PROD_PATH"
|
||||
DOCS_DEPLOY_URL_BASE: "https://docs.espressif.com/projects/esp-idf"
|
||||
DEPLOY_STABLE: 1
|
||||
environment:
|
||||
name: deploy_docs_production
|
||||
deployment_tier: production
|
||||
url: "https://docs.espressif.com/projects/esp-idf"
|
||||
|
||||
check_doc_links:
|
||||
extends:
|
||||
- .build_docs_template
|
||||
- .rules:protected:deploy
|
||||
rules:
|
||||
- <<: *if-protected-no_label
|
||||
stage: post_deploy
|
||||
needs:
|
||||
- job: deploy_docs_production
|
||||
|
||||
@@ -2,20 +2,18 @@
|
||||
extends: .rules:test:host_test
|
||||
stage: host_test
|
||||
image: $ESP_ENV_IMAGE
|
||||
tags: [build, shiny]
|
||||
tags:
|
||||
- host_test
|
||||
dependencies: # set dependencies to null to avoid missing artifacts issue
|
||||
# run host_test jobs immediately, only after upload cache
|
||||
needs:
|
||||
- pipeline_variables
|
||||
- job: upload-pip-cache
|
||||
optional: true
|
||||
artifacts: false
|
||||
- job: upload-submodules-cache
|
||||
optional: true
|
||||
artifacts: false
|
||||
- job: fast_template_app
|
||||
optional: true
|
||||
artifacts: false
|
||||
- pipeline_variables
|
||||
artifacts:
|
||||
expire_in: 1 week
|
||||
when: always
|
||||
@@ -55,14 +53,14 @@ test_partition_table_on_host:
|
||||
extends: .host_test_template
|
||||
script:
|
||||
- cd components/partition_table/test_gen_esp32part_host
|
||||
- pytest_for_ut ./gen_esp32part_tests.py
|
||||
- ./gen_esp32part_tests.py
|
||||
|
||||
test_ldgen_on_host:
|
||||
extends: .host_test_template
|
||||
script:
|
||||
- cd tools/ldgen/test
|
||||
- export PYTHONPATH=$PYTHONPATH:..
|
||||
- pytest_for_ut .
|
||||
- python -m unittest
|
||||
variables:
|
||||
LC_ALL: C.UTF-8
|
||||
|
||||
@@ -70,19 +68,33 @@ test_spiffs_on_host:
|
||||
extends: .host_test_template
|
||||
script:
|
||||
- cd components/spiffs/test_spiffsgen/
|
||||
- pytest_for_ut ./test_spiffsgen.py
|
||||
- ./test_spiffsgen.py
|
||||
|
||||
test_fatfsgen_on_host:
|
||||
extends: .host_test_template
|
||||
script:
|
||||
- cd components/fatfs/test_fatfsgen/
|
||||
- pytest_for_ut ./test_fatfsgen.py ./test_wl_fatfsgen.py ./test_fatfsparse.py
|
||||
- ./test_fatfsgen.py
|
||||
- ./test_wl_fatfsgen.py
|
||||
- ./test_fatfsparse.py
|
||||
|
||||
test_multi_heap_on_host:
|
||||
extends: .host_test_template
|
||||
script:
|
||||
- cd components/heap/test_multi_heap_host
|
||||
- ./test_all_configs.sh
|
||||
|
||||
test_certificate_bundle_on_host:
|
||||
extends: .host_test_template
|
||||
script:
|
||||
- cd components/mbedtls/esp_crt_bundle/test_gen_crt_bundle/
|
||||
- pytest_for_ut ./test_gen_crt_bundle.py
|
||||
- ./test_gen_crt_bundle.py
|
||||
|
||||
test_gdbstub_on_host:
|
||||
extends: .host_test_template
|
||||
script:
|
||||
- cd components/esp_gdbstub/test_gdbstub_host
|
||||
- make test
|
||||
|
||||
# Test for create virtualenv. It must be invoked from Python, not from virtualenv.
|
||||
# Use docker image system python without any extra dependencies
|
||||
@@ -101,21 +113,18 @@ 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.22.1
|
||||
- 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
|
||||
# Testing with system python3, so don't use any third-party packages
|
||||
- python3 ./test_idf_tools.py -v
|
||||
- python3 ./test_idf_tools_python_env.py
|
||||
# It runs at the end because it modifies dependencies
|
||||
- IDF_TEST_MAY_BREAK_DEPENDENCIES=1 python3 ./test_idf_tools.py -v TestSystemDependencies.test_commands_when_nodeps
|
||||
|
||||
test_efuse_table_on_host:
|
||||
.test_efuse_table_on_host_template:
|
||||
extends: .host_test_template
|
||||
parallel:
|
||||
matrix:
|
||||
- IDF_TARGET: [esp32, esp32s2, esp32c3, esp32s3, esp32c2, esp32c6, esp32h2, esp32p4, esp32c5, esp32c61]
|
||||
variables:
|
||||
IDF_TARGET: "esp32"
|
||||
artifacts:
|
||||
when: on_failure
|
||||
paths:
|
||||
@@ -125,7 +134,35 @@ test_efuse_table_on_host:
|
||||
- ./efuse_table_gen.py -t "${IDF_TARGET}" ${IDF_PATH}/components/efuse/${IDF_TARGET}/esp_efuse_table.csv
|
||||
- git diff --exit-code -- ${IDF_TARGET}/esp_efuse_table.c || { echo 'Differences found for ${IDF_TARGET} target. Please run idf.py efuse-common-table and commit the changes.'; exit 1; }
|
||||
- cd ${IDF_PATH}/components/efuse/test_efuse_host
|
||||
- pytest_for_ut ./efuse_tests.py
|
||||
- ./efuse_tests.py
|
||||
|
||||
test_efuse_table_on_host_esp32:
|
||||
extends: .test_efuse_table_on_host_template
|
||||
|
||||
test_efuse_table_on_host_esp32s2:
|
||||
extends: .test_efuse_table_on_host_template
|
||||
variables:
|
||||
IDF_TARGET: esp32s2
|
||||
|
||||
test_efuse_table_on_host_esp32s3:
|
||||
extends: .test_efuse_table_on_host_template
|
||||
variables:
|
||||
IDF_TARGET: esp32s3
|
||||
|
||||
test_efuse_table_on_host_esp32c3:
|
||||
extends: .test_efuse_table_on_host_template
|
||||
variables:
|
||||
IDF_TARGET: esp32c3
|
||||
|
||||
test_efuse_table_on_host_esp32h2:
|
||||
extends: .test_efuse_table_on_host_template
|
||||
variables:
|
||||
IDF_TARGET: esp32h2
|
||||
|
||||
test_efuse_table_on_host_esp32c6:
|
||||
extends: .test_efuse_table_on_host_template
|
||||
variables:
|
||||
IDF_TARGET: esp32c6
|
||||
|
||||
test_logtrace_proc:
|
||||
extends: .host_test_template
|
||||
@@ -163,21 +200,20 @@ test_tools:
|
||||
INSTALL_EXTRA_TOOLS: "qemu-xtensa qemu-riscv32" # for test_idf_qemu.py
|
||||
script:
|
||||
- stat=0
|
||||
- run_cmd idf-ci gitlab download-known-failure-cases-file ${KNOWN_FAILURE_CASES_FILE_NAME}
|
||||
- cd ${IDF_PATH}/tools/ci/test_autocomplete
|
||||
- run_cmd pytest --noconftest test_autocomplete.py --junitxml=${IDF_PATH}/XUNIT_AUTOCOMP.xml --ignore-result-files ${KNOWN_FAILURE_CASES_FILE_NAME} || stat=1
|
||||
- pytest --noconftest test_autocomplete.py --junitxml=${IDF_PATH}/XUNIT_AUTOCOMP.xml || stat=1
|
||||
- cd ${IDF_PATH}/tools/test_idf_py
|
||||
- run_cmd pytest --noconftest test_idf_py.py --junitxml=${IDF_PATH}/XUNIT_IDF_PY.xml --ignore-result-files ${KNOWN_FAILURE_CASES_FILE_NAME} || stat=1
|
||||
- run_cmd pytest --noconftest test_hints.py --junitxml=${IDF_PATH}/XUNIT_HINTS.xml --ignore-result-files ${KNOWN_FAILURE_CASES_FILE_NAME} || stat=1
|
||||
- run_cmd pytest --noconftest test_idf_qemu.py --junitxml=${IDF_PATH}/XUNIT_IDF_PY_QEMU.xml --ignore-result-files ${KNOWN_FAILURE_CASES_FILE_NAME} || stat=1
|
||||
- pytest --noconftest test_idf_py.py --junitxml=${IDF_PATH}/XUNIT_IDF_PY.xml || stat=1
|
||||
- pytest --noconftest test_hints.py --junitxml=${IDF_PATH}/XUNIT_HINTS.xml || stat=1
|
||||
- pytest --noconftest test_idf_qemu.py --junitxml=${IDF_PATH}/XUNIT_IDF_PY_QEMU.xml || stat=1
|
||||
- cd ${IDF_PATH}/tools/test_bsasm
|
||||
- run_cmd pytest --noconftest test_bsasm.py --junitxml=${IDF_PATH}/XUNIT_BSASM.xml --ignore-result-files ${KNOWN_FAILURE_CASES_FILE_NAME} || stat=1
|
||||
- pytest --noconftest test_bsasm.py --junitxml=${IDF_PATH}/XUNIT_BSASM.xml || stat=1
|
||||
- cd ${IDF_PATH}/tools/test_mkdfu
|
||||
- run_cmd pytest --noconftest test_mkdfu.py --junitxml=${IDF_PATH}/XUNIT_MKDFU.xml --ignore-result-files ${KNOWN_FAILURE_CASES_FILE_NAME} || stat=1
|
||||
- pytest --noconftest test_mkdfu.py --junitxml=${IDF_PATH}/XUNIT_MKDFU.xml || stat=1
|
||||
- cd ${IDF_PATH}/tools/test_idf_size
|
||||
- run_cmd pytest --noconftest test_idf_size.py --junitxml=${IDF_PATH}/XUNIT_IDF_SIZE.xml --ignore-result-files ${KNOWN_FAILURE_CASES_FILE_NAME} || stat=1
|
||||
- pytest --noconftest test_idf_size.py --junitxml=${IDF_PATH}/XUNIT_IDF_SIZE.xml || stat=1
|
||||
- cd ${IDF_PATH}/tools/test_idf_diag
|
||||
- run_cmd pytest --noconftest test_idf_diag.py --junitxml=${IDF_PATH}/XUNIT_IDF_DIAG.xml --ignore-result-files ${KNOWN_FAILURE_CASES_FILE_NAME} || stat=1
|
||||
- pytest --noconftest test_idf_diag.py --junitxml=${IDF_PATH}/XUNIT_IDF_DIAG.xml || stat=1
|
||||
- cd ${IDF_PATH}
|
||||
- shellcheck -s sh tools/detect_python.sh || stat=1
|
||||
- shellcheck -s bash tools/detect_python.sh || stat=1
|
||||
@@ -192,7 +228,14 @@ test_split_path_by_spaces:
|
||||
extends: .host_test_template
|
||||
script:
|
||||
- cd ${IDF_PATH}/tools
|
||||
- pytest_for_ut ./split_paths_by_spaces.py
|
||||
- python -m unittest split_paths_by_spaces.py
|
||||
|
||||
test_mqtt_on_host:
|
||||
extends: .host_test_template
|
||||
script:
|
||||
- cd ${IDF_PATH}/components/mqtt/esp-mqtt/host_test
|
||||
- idf.py build
|
||||
- LSAN_OPTIONS=verbosity=1:log_threads=1 build/host_mqtt_client_test.elf
|
||||
|
||||
test_transport_on_host:
|
||||
extends: .host_test_template
|
||||
@@ -231,78 +274,8 @@ test_gen_soc_caps_kconfig:
|
||||
extends: .host_test_template
|
||||
script:
|
||||
- cd ${IDF_PATH}/tools/gen_soc_caps_kconfig/
|
||||
- pytest_for_ut ./test/test_gen_soc_caps_kconfig.py
|
||||
- ./test/test_gen_soc_caps_kconfig.py
|
||||
|
||||
test_idf_build_apps_load_soc_caps:
|
||||
extends: .host_test_template
|
||||
script:
|
||||
- cd tools/ci
|
||||
- pytest_for_ut ./test_soc_headers_load_in_idf_build_apps.py
|
||||
|
||||
test_nvs_gen_check:
|
||||
extends: .host_test_template
|
||||
artifacts:
|
||||
paths:
|
||||
- XUNIT_RESULT.xml
|
||||
- components/nvs_flash/nvs_partition_tool
|
||||
reports:
|
||||
junit: XUNIT_RESULT.xml
|
||||
variables:
|
||||
LC_ALL: C.UTF-8
|
||||
script:
|
||||
- cd ${IDF_PATH}/components/nvs_flash/nvs_partition_tool
|
||||
- pytest_for_ut test_nvs_gen_check.py
|
||||
|
||||
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_for_ut test_esp_rom.py
|
||||
|
||||
make_sure_soc_caps_compatible_in_idf_build_apps:
|
||||
extends:
|
||||
- .host_test_template
|
||||
- .rules:dev-push
|
||||
artifacts:
|
||||
paths:
|
||||
- new.json
|
||||
- base.json
|
||||
when: always
|
||||
when: manual
|
||||
script:
|
||||
- python tools/ci/idf_build_apps_dump_soc_caps.py new.json
|
||||
- git fetch --depth=1 origin $CI_MERGE_REQUEST_DIFF_BASE_SHA
|
||||
- git checkout -f $CI_MERGE_REQUEST_DIFF_BASE_SHA
|
||||
- git checkout $CI_COMMIT_SHA -- tools/ci/idf_build_apps_dump_soc_caps.py
|
||||
- python tools/ci/idf_build_apps_dump_soc_caps.py base.json
|
||||
- diff new.json base.json
|
||||
|
||||
build_docker:
|
||||
extends:
|
||||
- .before_script:minimal
|
||||
- .rules:build:docker
|
||||
stage: host_test
|
||||
needs: []
|
||||
image: espressif/docker-builder:1
|
||||
tags: [shiny, dind]
|
||||
variables:
|
||||
DOCKER_TMP_IMAGE_NAME: "idf_tmp_image"
|
||||
script:
|
||||
- export DOCKER_BUILD_ARGS="--build-arg IDF_CLONE_URL=${CI_REPOSITORY_URL} --build-arg IDF_CLONE_BRANCH_OR_TAG=${CI_COMMIT_REF_NAME} --build-arg IDF_CHECKOUT_REF=${CI_COMMIT_TAG:-$CI_COMMIT_SHA} --build-arg IDF_CLONE_SHALLOW=1 --build-arg IDF_GITHUB_ASSETS=${INTERNAL_GITHUB_ASSETS}"
|
||||
- docker build --tag ${DOCKER_TMP_IMAGE_NAME} ${DOCKER_BUILD_ARGS} tools/docker/
|
||||
# We can't mount $PWD/examples/get-started/blink into the container, see https://gitlab.com/gitlab-org/gitlab-ce/issues/41227.
|
||||
# The workaround mentioned there works, but leaves around directories which need to be cleaned up manually.
|
||||
# Therefore, build a copy of the example located inside the container.
|
||||
- docker run --rm --workdir /opt/esp/idf/examples/get-started/blink ${DOCKER_TMP_IMAGE_NAME} idf.py build
|
||||
|
||||
############################
|
||||
# Host test with test apps #
|
||||
############################
|
||||
test_pytest_qemu:
|
||||
extends:
|
||||
- .host_test_template
|
||||
@@ -324,18 +297,22 @@ test_pytest_qemu:
|
||||
INSTALL_EXTRA_TOOLS: "qemu-riscv32"
|
||||
IDF_TOOLCHAIN: [gcc, clang]
|
||||
script:
|
||||
- run_cmd idf-ci build run
|
||||
--build-system cmake
|
||||
- run_cmd python tools/ci/ci_build_apps.py . -v
|
||||
--target $IDF_TARGET
|
||||
--pytest-apps
|
||||
-m qemu
|
||||
--collect-app-info "list_job_${CI_JOB_NAME_SLUG}.txt"
|
||||
--modified-components ${MR_MODIFIED_COMPONENTS}
|
||||
--modified-files ${MR_MODIFIED_FILES}
|
||||
- run_cmd idf-ci gitlab download-known-failure-cases-file ${KNOWN_FAILURE_CASES_FILE_NAME}
|
||||
- python tools/ci/get_known_failure_cases_file.py
|
||||
- run_cmd pytest
|
||||
--target $IDF_TARGET
|
||||
--log-cli-level DEBUG
|
||||
-m qemu
|
||||
--embedded-services idf,qemu
|
||||
--junitxml=XUNIT_RESULT.xml
|
||||
--ignore-result-files ${KNOWN_FAILURE_CASES_FILE_NAME}
|
||||
--app-info-filepattern \"list_job_*.txt\"
|
||||
--qemu-extra-args \"-global driver=timer.$IDF_TARGET.timg,property=wdt_disable,value=true\"
|
||||
|
||||
test_pytest_linux:
|
||||
@@ -350,23 +327,28 @@ test_pytest_linux:
|
||||
reports:
|
||||
junit: XUNIT_RESULT.xml
|
||||
script:
|
||||
- run_cmd idf-ci build run
|
||||
--build-system cmake
|
||||
-p components -p examples -p tools/test_apps
|
||||
- run_cmd python tools/ci/ci_build_apps.py components examples tools/test_apps -v
|
||||
--target linux
|
||||
--only-test-related
|
||||
--pytest-apps
|
||||
-m host_test
|
||||
--collect-app-info "list_job_${CI_JOB_NAME_SLUG}.txt"
|
||||
--modified-components ${MR_MODIFIED_COMPONENTS}
|
||||
--modified-files ${MR_MODIFIED_FILES}
|
||||
- run_cmd idf-ci gitlab download-known-failure-cases-file ${KNOWN_FAILURE_CASES_FILE_NAME}
|
||||
- python tools/ci/get_known_failure_cases_file.py
|
||||
- run_cmd pytest
|
||||
--target linux
|
||||
-m host_test
|
||||
--embedded-services idf
|
||||
--junitxml=XUNIT_RESULT.xml
|
||||
--ignore-result-files ${KNOWN_FAILURE_CASES_FILE_NAME}
|
||||
--app-info-filepattern \"list_job_*.txt\"
|
||||
|
||||
test_pytest_macos:
|
||||
extends:
|
||||
- .host_test_template
|
||||
- .brew-macos-settings
|
||||
- .before_script:build:macos
|
||||
tags:
|
||||
- macos_shell
|
||||
artifacts:
|
||||
paths:
|
||||
- XUNIT_RESULT.xml
|
||||
@@ -374,131 +356,84 @@ test_pytest_macos:
|
||||
- "**/build*/build_log.txt"
|
||||
reports:
|
||||
junit: XUNIT_RESULT.xml
|
||||
variables:
|
||||
PYENV_VERSION: "3.9"
|
||||
PYTEST_IGNORE_COLLECT_IMPORT_ERROR: "1"
|
||||
script:
|
||||
- run_cmd idf-ci build run
|
||||
-p components -p examples -p tools/test_apps
|
||||
--build-system cmake
|
||||
- run_cmd python tools/ci/ci_build_apps.py components examples tools/test_apps -v
|
||||
--target linux
|
||||
--only-test-related
|
||||
-m macos
|
||||
--pytest-apps
|
||||
-m \"host_test and macos_shell\"
|
||||
--collect-app-info "list_job_${CI_JOB_NAME_SLUG}.txt"
|
||||
--modified-components ${MR_MODIFIED_COMPONENTS}
|
||||
--modified-files ${MR_MODIFIED_FILES}
|
||||
- run_cmd idf-ci gitlab download-known-failure-cases-file ${KNOWN_FAILURE_CASES_FILE_NAME}
|
||||
- python tools/ci/get_known_failure_cases_file.py
|
||||
- run_cmd pytest
|
||||
--target linux
|
||||
-m macos
|
||||
-m \"host_test and macos_shell\"
|
||||
--junitxml=XUNIT_RESULT.xml
|
||||
--ignore-result-files ${KNOWN_FAILURE_CASES_FILE_NAME}
|
||||
--app-info-filepattern \"list_job_*.txt\"
|
||||
|
||||
######################
|
||||
# Build System Tests #
|
||||
######################
|
||||
.test_build_system_template:
|
||||
stage: host_test
|
||||
test_idf_pytest_plugin:
|
||||
extends:
|
||||
- .build_template
|
||||
- .rules:build:check
|
||||
dependencies: # set dependencies to null to avoid missing artifacts issue
|
||||
needs:
|
||||
- job: fast_template_app
|
||||
artifacts: false
|
||||
optional: true
|
||||
- .host_test_template
|
||||
- .rules:patterns:idf-pytest-plugin
|
||||
variables:
|
||||
SUBMODULES_TO_FETCH: "none"
|
||||
artifacts:
|
||||
reports:
|
||||
junit: XUNIT_RESULT.xml
|
||||
script:
|
||||
- cd ${IDF_PATH}/tools/ci/dynamic_pipelines/tests/test_report_generator
|
||||
- python -m unittest test_report_generator.py
|
||||
- cd ${IDF_PATH}/tools/ci/idf_pytest
|
||||
- pytest --junitxml=${CI_PROJECT_DIR}/XUNIT_RESULT.xml
|
||||
|
||||
test_idf_build_apps_load_soc_caps:
|
||||
extends: .host_test_template
|
||||
script:
|
||||
- python tools/ci/check_soc_headers_load_in_idf_build_apps.py
|
||||
|
||||
test_nvs_gen_check:
|
||||
extends: .host_test_template
|
||||
artifacts:
|
||||
paths:
|
||||
- XUNIT_RESULT.xml
|
||||
- test_build_system
|
||||
expire_in: 1 week
|
||||
when: always
|
||||
script:
|
||||
- ${IDF_PATH}/tools/ci/test_configure_ci_environment.sh
|
||||
- cd ${IDF_PATH}/tools/test_build_system
|
||||
- run_cmd idf-ci gitlab download-known-failure-cases-file ${KNOWN_FAILURE_CASES_FILE_NAME}
|
||||
- pytest
|
||||
--cleanup-idf-copy
|
||||
--parallel-count ${CI_NODE_TOTAL:-1}
|
||||
--parallel-index ${CI_NODE_INDEX:-1}
|
||||
--work-dir ${CI_PROJECT_DIR}/test_build_system
|
||||
--junitxml ${CI_PROJECT_DIR}/XUNIT_RESULT.xml
|
||||
--ignore-result-files ${KNOWN_FAILURE_CASES_FILE_NAME}
|
||||
|
||||
.test_build_system_minimal_cmake_template:
|
||||
extends: .test_build_system_template
|
||||
- components/nvs_flash/nvs_partition_tool
|
||||
reports:
|
||||
junit: XUNIT_RESULT.xml
|
||||
variables:
|
||||
INSTALL_EXTRA_TOOLS: cmake@3.22.1
|
||||
LC_ALL: C.UTF-8
|
||||
script:
|
||||
- MINIMAL_SUPPORTED_CMAKE_VERSION=$(echo "${INSTALL_EXTRA_TOOLS}" | sed -n 's/.*cmake@\([0-9.]*\).*/\1/p')
|
||||
- export PATH=$(echo "$PATH" | sed -E "s|/tools/cmake/[0-9.]+|/tools/cmake/${MINIMAL_SUPPORTED_CMAKE_VERSION}|")
|
||||
- ACTUAL_CMAKE_VERSION=$(cmake --version | head -n1 | awk '{print $3}')
|
||||
- |
|
||||
if [ "${ACTUAL_CMAKE_VERSION}" != "${MINIMAL_SUPPORTED_CMAKE_VERSION}" ]; then
|
||||
echo "ERROR: Wrong minimal CMake version! Detected: ${ACTUAL_CMAKE_VERSION}, but should be: ${MINIMAL_SUPPORTED_CMAKE_VERSION}"
|
||||
exit 1
|
||||
fi
|
||||
- ${IDF_PATH}/tools/ci/test_configure_ci_environment.sh
|
||||
- cd ${IDF_PATH}/tools/test_build_system
|
||||
- run_cmd idf-ci gitlab download-known-failure-cases-file ${KNOWN_FAILURE_CASES_FILE_NAME}
|
||||
- pytest
|
||||
-k cmake
|
||||
--cleanup-idf-copy
|
||||
--parallel-count ${CI_NODE_TOTAL:-1}
|
||||
--parallel-index ${CI_NODE_INDEX:-1}
|
||||
--work-dir ${CI_PROJECT_DIR}/test_build_system
|
||||
--junitxml ${CI_PROJECT_DIR}/XUNIT_RESULT.xml
|
||||
--ignore-result-files ${KNOWN_FAILURE_CASES_FILE_NAME}
|
||||
- cd ${IDF_PATH}/components/nvs_flash/nvs_partition_tool
|
||||
- pytest --noconftest test_nvs_gen_check.py --junitxml=XUNIT_RESULT.xml
|
||||
|
||||
pytest_build_system:
|
||||
extends: .test_build_system_template
|
||||
parallel: 3
|
||||
|
||||
pytest_buildv2_system:
|
||||
extends:
|
||||
- .test_build_system_template
|
||||
- .rules:labels:buildv2
|
||||
parallel: 3
|
||||
test_esp_rom:
|
||||
extends: .host_test_template
|
||||
artifacts:
|
||||
paths:
|
||||
- XUNIT_RESULT.xml
|
||||
reports:
|
||||
junit: XUNIT_RESULT.xml
|
||||
script:
|
||||
- ${IDF_PATH}/tools/ci/test_configure_ci_environment.sh
|
||||
- cd ${IDF_PATH}/tools/test_build_system
|
||||
- run_cmd idf-ci gitlab download-known-failure-cases-file ${KNOWN_FAILURE_CASES_FILE_NAME}
|
||||
- pytest
|
||||
--buildv2
|
||||
--cleanup-idf-copy
|
||||
--parallel-count ${CI_NODE_TOTAL:-1}
|
||||
--parallel-index ${CI_NODE_INDEX:-1}
|
||||
--work-dir ${CI_PROJECT_DIR}/test_build_system
|
||||
--junitxml ${CI_PROJECT_DIR}/XUNIT_RESULT.xml
|
||||
--ignore-result-files ${KNOWN_FAILURE_CASES_FILE_NAME}
|
||||
--
|
||||
test_non_default_target.py
|
||||
test_component_manager.py
|
||||
test_build.py
|
||||
test_bootloader.py
|
||||
test_git.py
|
||||
test_kconfig.py
|
||||
test_partition.py
|
||||
test_reproducible_build.py
|
||||
test_sdkconfig.py
|
||||
test_versions.py
|
||||
test_common.py
|
||||
test_components.py
|
||||
test_cmake.py
|
||||
test_idf_extension.py
|
||||
test_rebuild.py
|
||||
- cd ${IDF_PATH}/components/esp_rom/
|
||||
- pytest --noconftest test_esp_rom.py --junitxml=XUNIT_RESULT.xml
|
||||
|
||||
pytest_build_system_macos:
|
||||
extends:
|
||||
- .test_build_system_template
|
||||
- .brew-macos-settings
|
||||
- .rules:build:macos
|
||||
parallel: 3
|
||||
|
||||
pytest_build_system_minimal_cmake:
|
||||
extends: .test_build_system_minimal_cmake_template
|
||||
|
||||
pytest_build_system_macos_minimal_cmake:
|
||||
extends:
|
||||
- .test_build_system_minimal_cmake_template
|
||||
- .brew-macos-settings
|
||||
- .rules:build:macos
|
||||
variables:
|
||||
INSTALL_EXTRA_TOOLS: ninja cmake@3.22.1
|
||||
make_sure_soc_caps_compatible_in_idf_build_apps:
|
||||
extends:
|
||||
- .host_test_template
|
||||
- .rules:dev-push
|
||||
artifacts:
|
||||
paths:
|
||||
- new.json
|
||||
- base.json
|
||||
when: always
|
||||
when: manual
|
||||
script:
|
||||
- python tools/ci/idf_build_apps_dump_soc_caps.py new.json
|
||||
- git fetch --depth=1 origin $CI_MERGE_REQUEST_DIFF_BASE_SHA
|
||||
- git checkout -f $CI_MERGE_REQUEST_DIFF_BASE_SHA
|
||||
- git checkout $CI_COMMIT_SHA -- tools/ci/idf_build_apps_dump_soc_caps.py
|
||||
- python tools/ci/idf_build_apps_dump_soc_caps.py base.json
|
||||
- diff new.json base.json
|
||||
|
||||
@@ -60,9 +60,6 @@ child_integration_test_pipeline:
|
||||
stage: assign_test
|
||||
needs:
|
||||
- gen_integration_pipeline
|
||||
variables:
|
||||
IDF_S3_SERVER: $IDF_S3_NEW_SERVER
|
||||
IDF_S3_ACCESS_KEY: $IDF_S3_NEW_ACCESS_KEY
|
||||
trigger:
|
||||
include:
|
||||
- artifact: idf-integration-ci/child_pipeline/pipeline.yml
|
||||
|
||||
@@ -1,17 +1,11 @@
|
||||
.post_deploy_template:
|
||||
stage: post_deploy
|
||||
image: $ESP_ENV_IMAGE
|
||||
|
||||
generate_failed_jobs_report:
|
||||
extends:
|
||||
- .post_deploy_template
|
||||
stage: post_deploy
|
||||
tags: [build, shiny]
|
||||
image: $ESP_ENV_IMAGE
|
||||
when: always
|
||||
dependencies: # Do not download artifacts from the previous stages
|
||||
needs:
|
||||
- pipeline_variables
|
||||
dependencies: [] # Do not download artifacts from the previous stages
|
||||
artifacts:
|
||||
expire_in: 2 week
|
||||
expire_in: 1 week
|
||||
when: always
|
||||
paths:
|
||||
- job_report.html
|
||||
@@ -19,16 +13,12 @@ generate_failed_jobs_report:
|
||||
- python tools/ci/dynamic_pipelines/scripts/generate_report.py --report-type job
|
||||
|
||||
sync_support_status:
|
||||
stage: post_deploy
|
||||
extends:
|
||||
- .post_deploy_template
|
||||
- .rules:master:push
|
||||
tags: [ brew, github_sync ]
|
||||
- .rules:sync_support_status
|
||||
needs:
|
||||
- push_to_github
|
||||
cache: []
|
||||
before_script: []
|
||||
image: $ESP_ENV_IMAGE
|
||||
tags: [ brew, github_sync ]
|
||||
script:
|
||||
- curl --fail --request POST --form token="$IDF_STATUS_TRIG_TOKEN" --form ref="$IDF_STATUS_BRANCH" --form "variables[UPLOAD_TO_S3]=true" "$IDF_STATUS_TRIG_URL"
|
||||
environment:
|
||||
name: sync_support_status_production
|
||||
deployment_tier: production
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
.pre_check_template:
|
||||
stage: pre_check
|
||||
image: $ESP_ENV_IMAGE
|
||||
tags: [build, shiny]
|
||||
tags:
|
||||
- host_test
|
||||
dependencies: # set dependencies to null to avoid missing artifacts issue
|
||||
|
||||
check_version:
|
||||
@@ -9,7 +10,7 @@ check_version:
|
||||
# esp_idf_version.h in a branch before tagging the next version.
|
||||
extends:
|
||||
- .pre_check_template
|
||||
- .rules:protected:check
|
||||
- .rules:protected
|
||||
tags: [ brew, github_sync ]
|
||||
variables:
|
||||
# need a full clone to get the latest tag
|
||||
@@ -116,10 +117,22 @@ check_test_scripts_build_test_rules:
|
||||
extends:
|
||||
- .pre_check_template
|
||||
- .before_script:build
|
||||
variables:
|
||||
PYTEST_IGNORE_COLLECT_IMPORT_ERROR: "1"
|
||||
script:
|
||||
# requires basic pytest dependencies
|
||||
- run_cmd bash install.sh --enable-pytest
|
||||
- python tools/ci/check_build_test_rules.py check-test-scripts examples/ tools/test_apps components
|
||||
|
||||
check_configure_ci_environment_parsing:
|
||||
extends:
|
||||
- .pre_check_template
|
||||
- .before_script:build
|
||||
- .rules:build
|
||||
script:
|
||||
- cd tools/ci
|
||||
- python -m unittest ci_build_apps.py
|
||||
|
||||
pipeline_variables:
|
||||
extends:
|
||||
- .pre_check_template
|
||||
@@ -129,10 +142,11 @@ pipeline_variables:
|
||||
# MODIFIED_FILES is a list of files that changed, could be used everywhere
|
||||
- MODIFIED_FILES=$(echo "$GIT_DIFF_OUTPUT" | xargs)
|
||||
- echo "MODIFIED_FILES=$MODIFIED_FILES" >> pipeline.env
|
||||
- echo "REPORT_EXIT_CODE=0" >> pipeline.env
|
||||
# MR_MODIFIED_FILES and MR_MODIFIED_COMPONENTS are semicolon separated lists that is used in MR only
|
||||
# for non MR pipeline, these are empty lists
|
||||
- |
|
||||
if [ -z "$CI_MERGE_REQUEST_IID" ]; then
|
||||
if [ $IS_MR_PIPELINE == "0" ]; then
|
||||
echo "MR_MODIFIED_FILES=\"\"" >> pipeline.env
|
||||
echo "MR_MODIFIED_COMPONENTS=\"\"" >> pipeline.env
|
||||
else
|
||||
@@ -143,14 +157,19 @@ pipeline_variables:
|
||||
echo "MR_MODIFIED_COMPONENTS=\"$MR_MODIFIED_COMPONENTS\"" >> pipeline.env
|
||||
fi
|
||||
- |
|
||||
if [ -n "$PIPELINE_COMMIT_SHA" ]; then
|
||||
echo "PIPELINE_COMMIT_SHA=$PIPELINE_COMMIT_SHA" >> pipeline.env
|
||||
if echo "$CI_MERGE_REQUEST_LABELS" | egrep "(^|,)BUILD_AND_TEST_ALL_APPS(,|$)"; then
|
||||
echo "BUILD_AND_TEST_ALL_APPS=1" >> pipeline.env
|
||||
fi
|
||||
# run full pipeline if testing constraint branch
|
||||
- |
|
||||
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
|
||||
- run_cmd idf-ci gitlab pipeline-variables >> pipeline.env
|
||||
- python tools/ci/ci_process_description.py
|
||||
- cat pipeline.env
|
||||
- run_cmd idf-ci gitlab upload-artifacts --type env
|
||||
- python tools/ci/artifacts_handler.py upload --type modified_files_and_components_report
|
||||
artifacts:
|
||||
reports:
|
||||
dotenv: pipeline.env
|
||||
@@ -191,24 +210,14 @@ baseline_manifest_sha:
|
||||
expire_in: 1 week
|
||||
when: always
|
||||
|
||||
gcc_static_analyzer:
|
||||
extends:
|
||||
- .pre_check_template
|
||||
- .rules:build
|
||||
variables:
|
||||
CI_CCACHE_DISABLE: 1
|
||||
ANALYZING_APP: "examples/get-started/hello_world"
|
||||
script:
|
||||
- echo "CONFIG_COMPILER_STATIC_ANALYZER=y" >> ${ANALYZING_APP}/sdkconfig.defaults
|
||||
- idf-build-apps build -p ${ANALYZING_APP}
|
||||
|
||||
retry_failed_jobs:
|
||||
extends:
|
||||
- .pre_check_template
|
||||
- .rules:dev-push
|
||||
redundant_pass_job:
|
||||
stage: pre_check
|
||||
tags: [shiny, fast_run]
|
||||
allow_failure: true
|
||||
image: $ESP_ENV_IMAGE
|
||||
dependencies: null
|
||||
before_script: []
|
||||
cache: []
|
||||
extends: []
|
||||
script:
|
||||
- echo "Retrieving and retrying all failed jobs for the pipeline..."
|
||||
- python tools/ci/python_packages/gitlab_api.py retry_failed_jobs $CI_MERGE_REQUEST_PROJECT_ID --pipeline_id $CI_PIPELINE_ID
|
||||
when: manual
|
||||
- echo "This job is redundant to ensure the 'retry_failed_jobs' job can exist and not be skipped"
|
||||
when: always
|
||||
|
||||
@@ -2,20 +2,33 @@
|
||||
extends:
|
||||
- .before_script:minimal
|
||||
stage: pre_check
|
||||
image: "${CI_DOCKER_REGISTRY}/esp-idf-pre-commit:2"
|
||||
tags: [pre-commit]
|
||||
variables:
|
||||
# Both shiny and brew runners can pick this job
|
||||
GIT_STRATEGY: fetch
|
||||
GIT_DEPTH: 1
|
||||
SUBMODULES_TO_FETCH: "all"
|
||||
image: $PRE_COMMIT_IMAGE
|
||||
tags: [cache, shiny]
|
||||
needs:
|
||||
- pipeline_variables
|
||||
variables:
|
||||
# cache pre_commit
|
||||
PRE_COMMIT_HOME: "$CI_PROJECT_DIR/.cache/pre-commit"
|
||||
script:
|
||||
- fetch_submodules
|
||||
- pre-commit run --files $MODIFIED_FILES
|
||||
- pre-commit run --hook-stage post-commit validate-sbom-manifest
|
||||
|
||||
check_pre_commit_upload_cache:
|
||||
extends:
|
||||
- .check_pre_commit_template
|
||||
rules:
|
||||
- if: '($CI_COMMIT_REF_NAME == "master" || $CI_COMMIT_BRANCH =~ /^release\/v/) && $CI_PIPELINE_SOURCE == "push"'
|
||||
cache:
|
||||
- key: pre_commit-cache-${LATEST_GIT_TAG}
|
||||
paths:
|
||||
- .cache/pre-commit
|
||||
policy: pull-push
|
||||
- key: submodule-cache-${LATEST_GIT_TAG}
|
||||
paths:
|
||||
- .cache/submodule_archives
|
||||
policy: pull
|
||||
|
||||
check_pre_commit:
|
||||
extends:
|
||||
- .check_pre_commit_template
|
||||
@@ -24,6 +37,10 @@ check_pre_commit:
|
||||
when: never
|
||||
- when: on_success
|
||||
cache:
|
||||
- key: pre_commit-cache-${LATEST_GIT_TAG}
|
||||
paths:
|
||||
- .cache/pre-commit
|
||||
policy: pull
|
||||
- key: submodule-cache-${LATEST_GIT_TAG}
|
||||
paths:
|
||||
- .cache/submodule_archives
|
||||
@@ -39,20 +56,25 @@ check_powershell:
|
||||
tags:
|
||||
- dind
|
||||
- amd64
|
||||
- brew # faster "apk add"
|
||||
needs:
|
||||
- pipeline_variables
|
||||
variables:
|
||||
# brew runners always use fetch
|
||||
GIT_STRATEGY: fetch
|
||||
GIT_DEPTH: 1
|
||||
SUBMODULES_TO_FETCH: "none"
|
||||
# cache pre_commit
|
||||
PRE_COMMIT_HOME: "$CI_PROJECT_DIR/.cache/pre-commit"
|
||||
rules:
|
||||
- changes:
|
||||
- "*.ps1"
|
||||
- ".gitlab/ci/pre_commit.yml"
|
||||
script:
|
||||
- apk add python3
|
||||
- apk add py3-pip
|
||||
- pip install pre-commit --break-system-packages
|
||||
- pre-commit run --hook-stage manual check-powershell-scripts --files $MODIFIED_FILES
|
||||
cache:
|
||||
- key: pre_commit-cache-${LATEST_GIT_TAG}
|
||||
paths:
|
||||
- .cache/pre-commit
|
||||
policy: pull
|
||||
- key: submodule-cache-${LATEST_GIT_TAG}
|
||||
paths:
|
||||
- .cache/submodule_archives
|
||||
policy: pull
|
||||
|
||||
15
.gitlab/ci/retry_failed_jobs.yml
Normal file
15
.gitlab/ci/retry_failed_jobs.yml
Normal file
@@ -0,0 +1,15 @@
|
||||
retry_failed_jobs:
|
||||
stage: retry_failed_jobs
|
||||
tags: [shiny, fast_run]
|
||||
allow_failure: true
|
||||
image: $ESP_ENV_IMAGE
|
||||
dependencies: null
|
||||
before_script: []
|
||||
cache: []
|
||||
extends: []
|
||||
script:
|
||||
- echo "Retrieving and retrying all failed jobs for the pipeline..."
|
||||
- python tools/ci/python_packages/gitlab_api.py retry_failed_jobs $CI_MERGE_REQUEST_PROJECT_ID --pipeline_id $CI_PIPELINE_ID
|
||||
when: manual
|
||||
needs:
|
||||
- redundant_pass_job
|
||||
@@ -10,7 +10,7 @@
|
||||
- "**/*.{c,C,cpp}"
|
||||
- "**/*.{h,H,hpp}"
|
||||
- "components/**/Kconfig"
|
||||
- "components/**/CMakeLists.txt"
|
||||
- "components/**/CMakeList.txt"
|
||||
|
||||
.patterns-python-cache: &patterns-python-cache
|
||||
- "tools/requirements.json"
|
||||
@@ -41,9 +41,11 @@
|
||||
- "tools/idf_tools.py"
|
||||
- "tools/tools.json"
|
||||
|
||||
.patterns-build_template-app: &patterns-build_template-app
|
||||
- "tools/ci/build_template_app.sh"
|
||||
|
||||
.patterns-build_system: &patterns-build_system
|
||||
- "tools/cmake/**/*"
|
||||
- "tools/cmakev2/**/*"
|
||||
- "tools/kconfig_new/**/*"
|
||||
- "tools/idf.py"
|
||||
- "tools/idf_py_actions/**/*"
|
||||
@@ -51,11 +53,11 @@
|
||||
- "tools/ci/ignore_build_warnings.txt"
|
||||
- "tools/ci/test_build_system*.sh"
|
||||
- "tools/ci/test_build_system*.py"
|
||||
- "tools/ci/build_template_app.sh"
|
||||
- "tools/ci/ci_build_apps.py"
|
||||
- "tools/test_build_system/**/*"
|
||||
|
||||
.patterns-build_system_win: &patterns-build_system_win
|
||||
- "tools/test_build_system/**/*"
|
||||
.patterns-build_macos: &patterns-build_macos
|
||||
- "tools/ci/test_configure_ci_environment.sh"
|
||||
|
||||
.patterns-build_check: &patterns-build_check
|
||||
- "tools/test_build_system/**/*"
|
||||
@@ -129,8 +131,6 @@
|
||||
- "tools/bsasm.py"
|
||||
- "tools/test_bsasm/**/*"
|
||||
|
||||
- "tools/ci/test_soc_headers_load_in_idf_build_apps.py"
|
||||
|
||||
.patterns-docker: &patterns-docker
|
||||
- "tools/docker/**/*"
|
||||
|
||||
@@ -145,8 +145,10 @@
|
||||
- "components/esp_phy/lib"
|
||||
- "components/esp_wifi/lib"
|
||||
- "components/esp_coex/lib"
|
||||
- "components/json/cJSON"
|
||||
- "components/lwip/lwip"
|
||||
- "components/mbedtls/mbedtls"
|
||||
- "components/mqtt/esp-mqtt"
|
||||
- "components/openthread/lib"
|
||||
- "components/openthread/openthread"
|
||||
- "components/protobuf-c/protobuf-c"
|
||||
@@ -158,22 +160,29 @@
|
||||
- "components/bt/esp_ble_mesh/lib/lib"
|
||||
- ".gitmodules"
|
||||
|
||||
.patterns-idf-pytest-plugin: &patterns-idf-pytest-plugin
|
||||
- "tools/ci/idf_pytest/**/*"
|
||||
- "tools/ci/dynamic_pipelines/tests/**/*"
|
||||
|
||||
##############
|
||||
# if anchors #
|
||||
##############
|
||||
.if-master-push: &if-master-push
|
||||
if: '$CI_COMMIT_REF_NAME == "master" && $CI_PIPELINE_SOURCE == "push"'
|
||||
.if-ref-master: &if-ref-master
|
||||
if: '$CI_COMMIT_REF_NAME == "master"'
|
||||
|
||||
.if-release-tag: &if-release-tag
|
||||
.if-ref-master-no_label: &if-ref-master-no_label
|
||||
if: '$CI_COMMIT_REF_NAME == "master" && $BOT_TRIGGER_WITH_LABEL == null'
|
||||
|
||||
.if-tag-release: &if-tag-release
|
||||
if: '$CI_COMMIT_TAG =~ /^v\d+\.\d+(\.\d+)?($|-)/'
|
||||
|
||||
.if-protected-check: &if-protected-check
|
||||
.if-protected: &if-protected
|
||||
if: '($CI_COMMIT_REF_NAME == "master" || $CI_COMMIT_BRANCH =~ /^release\/v/ || $CI_COMMIT_TAG =~ /^v\d+\.\d+(\.\d+)?($|-)/) || $CI_COMMIT_TAG =~ /^qa-test/'
|
||||
|
||||
.if-protected-deploy: &if-protected-deploy
|
||||
if: '($CI_COMMIT_REF_NAME == "master" || $CI_COMMIT_BRANCH =~ /^release\/v/ || $CI_COMMIT_TAG =~ /^v\d+\.\d+(\.\d+)?($|-)/) && ($CI_PIPELINE_SOURCE == "push" || $CI_PIPELINE_SOURCE == "api")'
|
||||
.if-protected-no_label: &if-protected-no_label
|
||||
if: '($CI_COMMIT_REF_NAME == "master" || $CI_COMMIT_BRANCH =~ /^release\/v/ || $CI_COMMIT_TAG =~ /^v\d+\.\d+(\.\d+)?($|-)/) && $BOT_TRIGGER_WITH_LABEL == null'
|
||||
|
||||
.if-protected-branch-push: &if-protected-branch-push
|
||||
.if-protected-ref-push: &if-protected-ref-push
|
||||
# rules:changes always evaluates to true for new branch pipelines or when there is no Git push event
|
||||
if: '($CI_COMMIT_REF_NAME == "master" || $CI_COMMIT_BRANCH =~ /^release\/v/) && $CI_PIPELINE_SOURCE == "push"'
|
||||
|
||||
@@ -183,6 +192,9 @@
|
||||
.if-dev-push: &if-dev-push
|
||||
if: '$CI_COMMIT_REF_NAME != "master" && $CI_COMMIT_BRANCH !~ /^release\/v/ && $CI_COMMIT_TAG !~ /^v\d+\.\d+(\.\d+)?($|-)/ && $CI_COMMIT_TAG !~ /^qa-test/ && ($CI_PIPELINE_SOURCE == "push" || $CI_PIPELINE_SOURCE == "merge_request_event")'
|
||||
|
||||
.if-schedule: &if-schedule
|
||||
if: '$CI_PIPELINE_SOURCE == "schedule"'
|
||||
|
||||
.if-schedule-nightly: &if-schedule-nightly
|
||||
if: '$CI_PIPELINE_SOURCE == "schedule" && $INCLUDE_NIGHTLY_RUN == "1"'
|
||||
|
||||
@@ -202,41 +214,51 @@
|
||||
# Rules #
|
||||
#########
|
||||
### Branches ###
|
||||
.rules:protected:check:
|
||||
.rules:protected:
|
||||
rules:
|
||||
- <<: *if-protected-check
|
||||
- <<: *if-protected
|
||||
|
||||
.rules:protected:deploy:
|
||||
.rules:push_to_github:
|
||||
rules:
|
||||
- <<: *if-qa-test-tag
|
||||
when: never
|
||||
- <<: *if-protected-deploy
|
||||
- <<: *if-protected-no_label
|
||||
|
||||
.rules:master:push:
|
||||
# Not uploading on release branches
|
||||
.rules:sync_support_status:
|
||||
rules:
|
||||
- <<: *if-master-push
|
||||
- <<: *if-ref-master-no_label
|
||||
|
||||
.rules:protected-no_label-always:
|
||||
rules:
|
||||
- <<: *if-qa-test-tag
|
||||
when: never
|
||||
- <<: *if-protected-no_label
|
||||
when: always
|
||||
|
||||
.rules:tag:release:
|
||||
rules:
|
||||
- <<: *if-release-tag
|
||||
- <<: *if-tag-release
|
||||
|
||||
.rules:dev-push:
|
||||
rules:
|
||||
- <<: *if-dev-push
|
||||
|
||||
# Do not upload caches on dev branches by default
|
||||
.rules:upload-python-cache:
|
||||
rules:
|
||||
- <<: *if-release-tag
|
||||
- <<: *if-tag-release
|
||||
- <<: *if-schedule-nightly
|
||||
- <<: *if-protected-branch-push
|
||||
- <<: *if-protected-ref-push
|
||||
changes: *patterns-python-cache
|
||||
- <<: *if-label-upload_cache
|
||||
when: manual
|
||||
|
||||
.rules:upload-submodule-cache:
|
||||
rules:
|
||||
- <<: *if-release-tag
|
||||
- <<: *if-protected-branch-push
|
||||
# Needn't upload submodule cache in schedule pipeline
|
||||
- <<: *if-tag-release
|
||||
- <<: *if-protected-ref-push
|
||||
changes: *patterns-submodule
|
||||
- <<: *if-label-upload_cache
|
||||
when: manual
|
||||
@@ -244,10 +266,11 @@
|
||||
### Patterns ###
|
||||
.rules:patterns:clang_tidy:
|
||||
rules:
|
||||
- <<: *if-protected-check
|
||||
- <<: *if-protected
|
||||
- <<: *if-dev-push
|
||||
changes: *patterns-c-files
|
||||
|
||||
|
||||
#.rules:patterns:static-code-analysis-preview:
|
||||
# rules:
|
||||
# - <<: *if-dev-push
|
||||
@@ -257,6 +280,12 @@
|
||||
# - <<: *if-dev-push
|
||||
# changes: *patterns-sonarqube-files
|
||||
|
||||
.rules:patterns:idf-pytest-plugin:
|
||||
rules:
|
||||
- <<: *if-protected
|
||||
- <<: *if-dev-push
|
||||
changes: *patterns-idf-pytest-plugin
|
||||
|
||||
# !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
# DO NOT place comments or maintain any code from this line
|
||||
#
|
||||
@@ -272,9 +301,6 @@
|
||||
.if-label-build: &if-label-build
|
||||
if: '$BOT_LABEL_BUILD || $CI_MERGE_REQUEST_LABELS =~ /^(?:[^,\n\r]+,)*build(?:,[^,\n\r]+)*$/i'
|
||||
|
||||
.if-label-buildv2: &if-label-buildv2
|
||||
if: '$BOT_LABEL_BUILDV2 || $CI_MERGE_REQUEST_LABELS =~ /^(?:[^,\n\r]+,)*buildv2(?:,[^,\n\r]+)*$/i'
|
||||
|
||||
.if-label-docker: &if-label-docker
|
||||
if: '$BOT_LABEL_DOCKER || $CI_MERGE_REQUEST_LABELS =~ /^(?:[^,\n\r]+,)*docker(?:,[^,\n\r]+)*$/i'
|
||||
|
||||
@@ -300,7 +326,7 @@
|
||||
rules:
|
||||
- <<: *if-revert-branch
|
||||
when: never
|
||||
- <<: *if-protected-check
|
||||
- <<: *if-protected
|
||||
- <<: *if-label-build
|
||||
- <<: *if-dev-push
|
||||
changes: *patterns-build_components
|
||||
@@ -313,7 +339,7 @@
|
||||
rules:
|
||||
- <<: *if-revert-branch
|
||||
when: never
|
||||
- <<: *if-protected-check
|
||||
- <<: *if-protected
|
||||
- <<: *if-label-build
|
||||
- <<: *if-dev-push
|
||||
changes: *patterns-build_check
|
||||
@@ -328,7 +354,7 @@
|
||||
rules:
|
||||
- <<: *if-revert-branch
|
||||
when: never
|
||||
- <<: *if-protected-check
|
||||
- <<: *if-protected
|
||||
- <<: *if-label-build
|
||||
- <<: *if-label-docker
|
||||
- <<: *if-dev-push
|
||||
@@ -344,15 +370,31 @@
|
||||
rules:
|
||||
- <<: *if-revert-branch
|
||||
when: never
|
||||
- <<: *if-protected-check
|
||||
- <<: *if-protected
|
||||
- <<: *if-label-build
|
||||
- <<: *if-label-macos
|
||||
- <<: *if-label-macos_test
|
||||
- <<: *if-dev-push
|
||||
changes: *patterns-build_macos
|
||||
- <<: *if-dev-push
|
||||
changes: *patterns-build_system
|
||||
- <<: *if-dev-push
|
||||
changes: *patterns-downloadable-tools
|
||||
|
||||
.rules:labels:buildv2:
|
||||
.rules:build:target_test:
|
||||
rules:
|
||||
- <<: *if-revert-branch
|
||||
when: never
|
||||
- <<: *if-label-buildv2
|
||||
- <<: *if-protected
|
||||
- <<: *if-label-build
|
||||
- <<: *if-dev-push
|
||||
changes: *patterns-build_components
|
||||
- <<: *if-dev-push
|
||||
changes: *patterns-build_system
|
||||
- <<: *if-dev-push
|
||||
changes: *patterns-build_template-app
|
||||
- <<: *if-dev-push
|
||||
changes: *patterns-downloadable-tools
|
||||
|
||||
.rules:labels:nvs_coverage:
|
||||
rules:
|
||||
@@ -367,13 +409,13 @@
|
||||
- <<: *if-schedule-test-build-system-windows
|
||||
- <<: *if-label-windows
|
||||
- <<: *if-dev-push
|
||||
changes: *patterns-build_system_win
|
||||
changes: *patterns-build_system
|
||||
|
||||
.rules:test:host_test:
|
||||
rules:
|
||||
- <<: *if-revert-branch
|
||||
when: never
|
||||
- <<: *if-protected-check
|
||||
- <<: *if-protected
|
||||
- <<: *if-label-build-only
|
||||
when: never
|
||||
- <<: *if-label-host_test
|
||||
@@ -384,7 +426,7 @@
|
||||
rules:
|
||||
- <<: *if-revert-branch
|
||||
when: never
|
||||
- <<: *if-protected-check
|
||||
- <<: *if-protected
|
||||
- <<: *if-label-build-only
|
||||
when: never
|
||||
- <<: *if-label-submodule
|
||||
|
||||
@@ -85,7 +85,7 @@ clang_tidy_check:
|
||||
#code_quality_report:
|
||||
# extends:
|
||||
# - .sonar_scan_template
|
||||
# - .rules:protected:check
|
||||
# - .rules:protected
|
||||
# allow_failure: true # it's using exit code to indicate the code analysis result,
|
||||
# # we don't want to block ci when critical issues founded
|
||||
# script:
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
extends: .rules:test:host_test
|
||||
stage: host_test
|
||||
image: $ESP_ENV_IMAGE
|
||||
tags: [windows-build, brew]
|
||||
tags:
|
||||
- windows-build
|
||||
dependencies: # set dependencies to null to avoid missing artifacts issue
|
||||
# run host_test jobs immediately, only after upload cache
|
||||
needs:
|
||||
@@ -13,21 +14,13 @@
|
||||
- job: upload-submodules-cache
|
||||
optional: true
|
||||
artifacts: false
|
||||
variables:
|
||||
GIT_STRATEGY: fetch # use brew local mirror first
|
||||
before_script:
|
||||
- if ($env:IDF_DONT_USE_MIRRORS) {
|
||||
$env:IDF_MIRROR_PREFIX_MAP = ""
|
||||
}
|
||||
before_script: []
|
||||
after_script: []
|
||||
|
||||
test_cli_installer_win:
|
||||
rules:
|
||||
- when: never
|
||||
extends:
|
||||
- .host_test_win_template
|
||||
- .rules:labels:windows_pytest_build_system
|
||||
allow_failure: true
|
||||
artifacts:
|
||||
when: on_failure
|
||||
paths:
|
||||
@@ -37,10 +30,10 @@ test_cli_installer_win:
|
||||
variables:
|
||||
IDF_PATH: "$CI_PROJECT_DIR"
|
||||
timeout: 3h
|
||||
allow_failure: true
|
||||
script:
|
||||
# Tools must be downloaded for testing
|
||||
# cmake@version that is supported
|
||||
- python ${IDF_PATH}\tools\idf_tools.py download required qemu-riscv32 qemu-xtensa cmake cmake@3.22.1
|
||||
- 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
|
||||
@@ -50,7 +43,6 @@ test_tools_win:
|
||||
extends:
|
||||
- .host_test_win_template
|
||||
- .rules:labels:windows_pytest_build_system
|
||||
parallel: 4
|
||||
artifacts:
|
||||
paths:
|
||||
- ${IDF_PATH}/*.out
|
||||
@@ -64,12 +56,12 @@ test_tools_win:
|
||||
PYTHONPATH: "$PYTHONPATH;$IDF_PATH\\tools;$IDF_PATH\\tools\\esp_app_trace;$IDF_PATH\\components\\partition_table;$IDF_PATH\\tools\\ci\\python_packages"
|
||||
script:
|
||||
- python -m pip install jsonschema
|
||||
- .\install.ps1 --enable-ci
|
||||
- .\install.ps1 --enable-ci --enable-pytest
|
||||
- .\export.ps1
|
||||
- python "${SUBMODULE_FETCH_TOOL}" -s "all"
|
||||
- cd ${IDF_PATH}/tools/test_idf_py
|
||||
- idf-ci gitlab download-known-failure-cases-file ${KNOWN_FAILURE_CASES_FILE_NAME}
|
||||
- pytest --parallel-count ${CI_NODE_TOTAL} --parallel-index ${CI_NODE_INDEX} --junitxml=${IDF_PATH}/XUNIT_RESULT.xml --ignore-result-files ${KNOWN_FAILURE_CASES_FILE_NAME}
|
||||
- pytest --noconftest test_idf_py.py --junitxml=${IDF_PATH}/XUNIT_IDF_PY.xml
|
||||
- pytest --noconftest test_hints.py --junitxml=${IDF_PATH}/XUNIT_HINTS.xml
|
||||
|
||||
# Build tests
|
||||
.test_build_system_template_win:
|
||||
@@ -82,68 +74,20 @@ test_tools_win:
|
||||
after_script: []
|
||||
timeout: 4 hours
|
||||
script:
|
||||
- .\install.ps1 --enable-ci
|
||||
- .\install.ps1 --enable-ci --enable-pytest
|
||||
- . .\export.ps1
|
||||
- python "${SUBMODULE_FETCH_TOOL}" -s "all"
|
||||
- cd ${IDF_PATH}\tools\test_build_system
|
||||
- idf-ci gitlab download-known-failure-cases-file ${KNOWN_FAILURE_CASES_FILE_NAME}
|
||||
- pytest --parallel-count ${CI_NODE_TOTAL} --parallel-index ${CI_NODE_INDEX} --junitxml=${CI_PROJECT_DIR}\XUNIT_RESULT.xml --ignore-result-files ${KNOWN_FAILURE_CASES_FILE_NAME}
|
||||
- pytest --parallel-count ${CI_NODE_TOTAL} --parallel-index ${CI_NODE_INDEX} --junitxml=${CI_PROJECT_DIR}\XUNIT_RESULT.xml
|
||||
|
||||
pytest_build_system_win:
|
||||
extends:
|
||||
- .test_build_system_template_win
|
||||
- .rules:labels:windows_pytest_build_system
|
||||
parallel: 6
|
||||
needs: []
|
||||
tags: [windows-build, brew]
|
||||
artifacts:
|
||||
paths:
|
||||
- XUNIT_RESULT.xml
|
||||
- test_build_system
|
||||
expire_in: 2 days
|
||||
reports:
|
||||
junit: XUNIT_RESULT.xml
|
||||
when: always
|
||||
|
||||
pytest_build_system_win_minimal_cmake:
|
||||
extends:
|
||||
- .test_build_system_template_win
|
||||
- .rules:labels:windows_pytest_build_system
|
||||
needs: []
|
||||
tags: [windows-build, brew]
|
||||
artifacts:
|
||||
paths:
|
||||
- XUNIT_RESULT.xml
|
||||
- test_build_system
|
||||
expire_in: 2 days
|
||||
reports:
|
||||
junit: XUNIT_RESULT.xml
|
||||
when: always
|
||||
variables:
|
||||
MINIMAL_CMAKE_VERSION: "3.22.1"
|
||||
script:
|
||||
- .\install.ps1 --enable-ci
|
||||
- . .\export.ps1
|
||||
- python ${IDF_PATH}\tools\idf_tools.py install cmake@${MINIMAL_CMAKE_VERSION}
|
||||
- $Env:PATH = "$Env:USERPROFILE\.espressif\tools\cmake\${MINIMAL_CMAKE_VERSION}\bin;$Env:PATH"
|
||||
- |
|
||||
$actualVersion = (& cmake --version).Split()[2]
|
||||
if ($actualVersion -ne $Env:MINIMAL_CMAKE_VERSION) {
|
||||
Write-Error "ERROR: Wrong CMake version! Detected: $actualVersion, but expected: $Env:MINIMAL_CMAKE_VERSION"
|
||||
exit 1
|
||||
}
|
||||
- python "${SUBMODULE_FETCH_TOOL}" -s "all"
|
||||
- cd ${IDF_PATH}\tools\test_build_system
|
||||
- idf-ci gitlab download-known-failure-cases-file ${KNOWN_FAILURE_CASES_FILE_NAME}
|
||||
- pytest -k cmake --junitxml=${CI_PROJECT_DIR}\XUNIT_RESULT.xml --ignore-result-files ${KNOWN_FAILURE_CASES_FILE_NAME}
|
||||
|
||||
pytest_buildv2_system_win:
|
||||
extends:
|
||||
- .test_build_system_template_win
|
||||
- .rules:labels:buildv2
|
||||
parallel: 2
|
||||
needs: []
|
||||
tags: [windows-build, brew]
|
||||
tags:
|
||||
- windows-build
|
||||
artifacts:
|
||||
paths:
|
||||
- XUNIT_RESULT.xml
|
||||
@@ -152,31 +96,3 @@ pytest_buildv2_system_win:
|
||||
reports:
|
||||
junit: XUNIT_RESULT.xml
|
||||
when: always
|
||||
script:
|
||||
- .\install.ps1 --enable-ci
|
||||
- . .\export.ps1
|
||||
- python "${SUBMODULE_FETCH_TOOL}" -s "all"
|
||||
- cd ${IDF_PATH}\tools\test_build_system
|
||||
- idf-ci gitlab download-known-failure-cases-file ${KNOWN_FAILURE_CASES_FILE_NAME}
|
||||
- pytest
|
||||
--buildv2
|
||||
--parallel-count ${CI_NODE_TOTAL}
|
||||
--parallel-index ${CI_NODE_INDEX}
|
||||
--junitxml=${CI_PROJECT_DIR}\XUNIT_RESULT.xml
|
||||
--ignore-result-files ${KNOWN_FAILURE_CASES_FILE_NAME}
|
||||
--
|
||||
test_non_default_target.py
|
||||
test_component_manager.py
|
||||
test_build.py
|
||||
test_bootloader.py
|
||||
test_git.py
|
||||
test_kconfig.py
|
||||
test_partition.py
|
||||
test_reproducible_build.py
|
||||
test_sdkconfig.py
|
||||
test_versions.py
|
||||
test_common.py
|
||||
test_components.py
|
||||
test_cmake.py
|
||||
test_idf_extension.py
|
||||
test_rebuild.py
|
||||
|
||||
@@ -21,7 +21,7 @@ upload-pip-cache:
|
||||
policy: push
|
||||
script:
|
||||
- rm -rf .cache/pip # clear old packages
|
||||
- bash install.sh --enable-ci --enable-test-specific
|
||||
- bash install.sh --enable-ci --enable-pytest
|
||||
parallel:
|
||||
matrix:
|
||||
- GEO: [ 'shiny', 'brew' ]
|
||||
|
||||
@@ -9,6 +9,11 @@
|
||||
## Related <!-- Optional -->
|
||||
<!-- Related Jira issues and Github issues or write "No related issues"-->
|
||||
|
||||
## Release notes <!-- Mandatory -->
|
||||
<!-- Either state release notes or write "No release notes" -->
|
||||
|
||||
<!-- ## Breaking change notes --><!-- Optional -->
|
||||
|
||||
<!-- ## Dynamic Pipeline Configuration
|
||||
```yaml
|
||||
Test Case Filters:
|
||||
|
||||
@@ -39,5 +39,27 @@ _For other small/non-public changes, which are not expected to be in the release
|
||||
* Mention submodule MR, if there is
|
||||
* Mention backport(ed) MR, if there is
|
||||
|
||||
_Don't touch the subsection titles below, they will be parsed by scripts._
|
||||
|
||||
## Release notes <!-- Mandatory -->
|
||||
|
||||
_Changes made in this MR that should go into the **Release Notes** should be listed here. Please use **past tense** and *specify the area (see maintainers page of IDF internal wiki)*. If there is a subscope, include it and separate with slash (`/`). Minor changes can go to the descriptions above without a release notes entry._
|
||||
|
||||
_Write all the changes in a **list** (Start at the beginning of the line with `-` or `*`). If multiple changes are made, each of them should take a single line. If there is only one change to list, it should still be the only line of a list. If this MR does not need any release notes, write "No release notes" here without the `-` or `*`. e.g._
|
||||
|
||||
* [WiFi] Changed/fixed/updated xxx
|
||||
* [WiFi] Added support of xxx
|
||||
* [Peripheral Drivers/I2S] Fixed xxx (https://github.com/espressif/esp-idf/issues/xxxx)
|
||||
|
||||
## Breaking change notes
|
||||
|
||||
_Remove this subsection if not used._
|
||||
|
||||
_If there are any breaking changes, please mention it here. Talking about (1) what is not accepted any more, (2) the alternative solution and (3) the benefits/reason. e.g._
|
||||
|
||||
_Please strictly follow the breaking change restriction, which means, if there is a breaking change but you are merging to non-major versions, you have to separate the breaking part out to another MR for a major version. The breaking change subsection is only accepted in MRs merging to major versions._
|
||||
|
||||
* [VFS/UART] Now vfs_uart_set_rts_cts accept one more instance argument, to support configuration to different ports.
|
||||
|
||||
<!-- Don't remove the next line - assigns the MR author as the assignee -->
|
||||
/assign me
|
||||
|
||||
17
.gitmodules
vendored
17
.gitmodules
vendored
@@ -46,6 +46,19 @@
|
||||
sbom-description = Wear-leveled SPI flash file system for embedded devices
|
||||
sbom-hash = 0dbb3f71c5f6fae3747a9d935372773762baf852
|
||||
|
||||
[submodule "components/json/cJSON"]
|
||||
path = components/json/cJSON
|
||||
url = ../../DaveGamble/cJSON.git
|
||||
sbom-version = 1.7.18
|
||||
sbom-cpe = cpe:2.3:a:cjson_project:cjson:{}:*:*:*:*:*:*:*
|
||||
sbom-supplier = Person: Dave Gamble
|
||||
sbom-url = https://github.com/DaveGamble/cJSON
|
||||
sbom-description = Ultralightweight JSON parser in ANSI C
|
||||
sbom-hash = 8f2beb57ddad1f94bed899790b00f46df893ccac
|
||||
sbom-cve-exclude-list = CVE-2024-31755 Resolved in v1.7.18
|
||||
sbom-cve-exclude-list = CVE-2023-26819 Resolved in commit a328d65ad490b64da8c87523cbbfe16050ba5bf6
|
||||
sbom-cve-exclude-list = CVE-2023-53154 Resolved in v1.7.18
|
||||
|
||||
[submodule "components/mbedtls/mbedtls"]
|
||||
path = components/mbedtls/mbedtls
|
||||
url = ../../espressif/mbedtls.git
|
||||
@@ -54,6 +67,10 @@
|
||||
path = components/lwip/lwip
|
||||
url = ../../espressif/esp-lwip.git
|
||||
|
||||
[submodule "components/mqtt/esp-mqtt"]
|
||||
path = components/mqtt/esp-mqtt
|
||||
url = ../../espressif/esp-mqtt.git
|
||||
|
||||
[submodule "components/protobuf-c/protobuf-c"]
|
||||
path = components/protobuf-c/protobuf-c
|
||||
url = ../../protobuf-c/protobuf-c.git
|
||||
|
||||
@@ -1,68 +0,0 @@
|
||||
config_rules = [
|
||||
'sdkconfig.ci=default',
|
||||
'sdkconfig.ci.*=',
|
||||
'=default',
|
||||
]
|
||||
|
||||
extra_pythonpaths = [
|
||||
'$IDF_PATH/tools/ci/python_packages',
|
||||
'$IDF_PATH/tools/ci',
|
||||
'$IDF_PATH/tools',
|
||||
]
|
||||
build_system = "idf_ci_local.app:IdfCMakeApp"
|
||||
|
||||
recursive = true
|
||||
check_warnings = true
|
||||
keep_going = true
|
||||
copy_sdkconfig = true
|
||||
ignore_warning_files = [
|
||||
'$IDF_PATH/tools/ci/ignore_build_warnings.txt',
|
||||
]
|
||||
|
||||
build_dir = "build_@t_@w"
|
||||
build_log_filename = "build_log.txt"
|
||||
size_json_filename = "size_${CI_JOB_ID}.json"
|
||||
|
||||
verbose = 1 # INFO
|
||||
|
||||
additional_build_targets = [
|
||||
'esp32h21',
|
||||
'esp32h4',
|
||||
]
|
||||
|
||||
# collect
|
||||
collect_app_info_filename = "app_info_${CI_JOB_NAME_SLUG}.txt"
|
||||
junitxml = "build_summary_${CI_JOB_NAME_SLUG}.xml"
|
||||
|
||||
# manifest
|
||||
check_manifest_rules = true
|
||||
manifest_rootpath = "$IDF_PATH"
|
||||
manifest_filepatterns = [
|
||||
'**/.build-test-rules.yml',
|
||||
]
|
||||
|
||||
# dependency-driven build
|
||||
deactivate_dependency_driven_build_by_components = [
|
||||
'cxx',
|
||||
'esp_common',
|
||||
'esp_hw_support',
|
||||
'esp_rom',
|
||||
'esp_system',
|
||||
'esp_timer',
|
||||
'freertos',
|
||||
'hal',
|
||||
'heap',
|
||||
'log',
|
||||
'esp_libc',
|
||||
'riscv',
|
||||
'soc',
|
||||
'xtensa',
|
||||
]
|
||||
|
||||
deactivate_dependency_driven_build_by_filepatterns = [
|
||||
# tools
|
||||
'tools/cmake/**/*',
|
||||
'tools/tools.json',
|
||||
# ci
|
||||
'tools/ci/ignore_build_warnings.txt',
|
||||
]
|
||||
106
.idf_ci.toml
106
.idf_ci.toml
@@ -1,106 +0,0 @@
|
||||
preserve_non_test_related_apps = false
|
||||
exclude_dirs = [
|
||||
'tools/test_mkdfu',
|
||||
'tools/test_idf_size',
|
||||
'tools/test_idf_py',
|
||||
'tools/test_idf_diag',
|
||||
'tools/test_bsasm',
|
||||
'tools/ci/test_autocomplete',
|
||||
'tools/test_build_system',
|
||||
]
|
||||
|
||||
[local_runtime_envs]
|
||||
EXTRA_CFLAGS = "-Werror -Werror=deprecated-declarations -Werror=unused-variable -Werror=unused-but-set-variable -Werror=unused-function -Wstrict-prototypes"
|
||||
EXTRA_CXXFLAGS = "-Werror -Werror=deprecated-declarations -Werror=unused-variable -Werror=unused-but-set-variable -Werror=unused-function"
|
||||
LDGEN_CHECK_MAPPING = "1"
|
||||
IDF_CI_BUILD = "1"
|
||||
|
||||
[gitlab]
|
||||
|
||||
[gitlab.build_pipeline]
|
||||
workflow_name = "build_child_pipeline"
|
||||
presigned_json_job_name = 'generate_pytest_build_report'
|
||||
|
||||
job_tags = ['build', 'shiny']
|
||||
job_template_name = '.dynamic_build_template'
|
||||
job_template_jinja = '' # write in tools/ci/dynamic_pipelines/templates/.dynamic_jobs.yml
|
||||
pre_yaml_jinja = """
|
||||
include:
|
||||
- .gitlab/ci/common.yml
|
||||
- tools/ci/dynamic_pipelines/templates/.dynamic_jobs.yml
|
||||
- tools/ci/dynamic_pipelines/templates/test_child_pipeline.yml
|
||||
"""
|
||||
yaml_jinja = """
|
||||
{{ settings.gitlab.build_pipeline.pre_yaml_jinja }}
|
||||
|
||||
workflow:
|
||||
name: {{ settings.gitlab.build_pipeline.workflow_name }}
|
||||
rules:
|
||||
- when: always
|
||||
|
||||
{{ jobs }}
|
||||
""" # simplified since we included the tools/ci/dynamic_pipelines/templates/test_child_pipeline.yml
|
||||
|
||||
[gitlab.test_pipeline]
|
||||
job_template_name = '.dynamic_target_test_template'
|
||||
job_template_jinja = '' # write in tools/ci/dynamic_pipelines/templates/.dynamic_jobs.yml
|
||||
pre_yaml_jinja = """
|
||||
include:
|
||||
- .gitlab/ci/common.yml
|
||||
- tools/ci/dynamic_pipelines/templates/.dynamic_jobs.yml
|
||||
"""
|
||||
|
||||
[gitlab.artifacts.s3.debug]
|
||||
bucket = "idf-artifacts"
|
||||
patterns = [
|
||||
'**/build*/bootloader/*.map',
|
||||
'**/build*/bootloader/*.elf',
|
||||
'**/build*/*.map',
|
||||
'**/build*/*.elf',
|
||||
# customized
|
||||
'**/build*/esp_tee/*.map',
|
||||
'**/build*/esp_tee/*.elf',
|
||||
'**/build*/gdbinit/*',
|
||||
]
|
||||
|
||||
[gitlab.artifacts.s3.flash]
|
||||
bucket = "idf-artifacts"
|
||||
patterns = [
|
||||
'**/build*/bootloader/*.bin',
|
||||
'**/build*/*.bin',
|
||||
'**/build*/partition_table/*.bin',
|
||||
'**/build*/flasher_args.json',
|
||||
'**/build*/flash_project_args',
|
||||
'**/build*/config/sdkconfig.json',
|
||||
'**/build*/sdkconfig',
|
||||
'**/build*/project_description.json',
|
||||
# customized
|
||||
'**/build*/esp_tee/*.bin',
|
||||
]
|
||||
|
||||
[gitlab.artifacts.s3.log]
|
||||
bucket = "idf-artifacts"
|
||||
patterns = [
|
||||
'**/build*/build_log.txt',
|
||||
'**/build*/size*.json',
|
||||
]
|
||||
|
||||
[gitlab.artifacts.s3.junit]
|
||||
bucket = "idf-artifacts"
|
||||
patterns = [
|
||||
'**/XUNIT_RESULT_*.xml',
|
||||
'**/build_summary_*.xml',
|
||||
]
|
||||
|
||||
[gitlab.artifacts.s3.env]
|
||||
bucket = "idf-artifacts"
|
||||
patterns = [
|
||||
'**/pipeline.env',
|
||||
]
|
||||
|
||||
[gitlab.artifacts.s3.longterm]
|
||||
bucket = "longterm"
|
||||
if_clause = '"$CI_COMMIT_REF_NAME" == "master"'
|
||||
patterns = [
|
||||
'**/build*/size*.json',
|
||||
]
|
||||
@@ -1,7 +1,7 @@
|
||||
[mypy]
|
||||
|
||||
# Specifies the Python version used to parse and check the target program
|
||||
python_version = 3.10
|
||||
python_version = 3.9
|
||||
|
||||
# Disallows defining functions without type annotations or with incomplete type annotations
|
||||
# True => enforce type annotation in all function definitions
|
||||
|
||||
@@ -9,7 +9,27 @@ repos:
|
||||
hooks:
|
||||
- id: ruff-format
|
||||
- id: ruff
|
||||
args: [ "--fix", "--show-fixes" ]
|
||||
args: [ "--fix" ]
|
||||
- repo: local
|
||||
hooks:
|
||||
- id: pytest-linter
|
||||
name: Pytest Linter Check
|
||||
entry: tools/ci/check_test_files.py
|
||||
language: python
|
||||
files: 'pytest_.*\.py$'
|
||||
require_serial: true
|
||||
additional_dependencies:
|
||||
- pytest-embedded-idf[serial]~=1.16
|
||||
- pytest-embedded-jtag~=1.16
|
||||
- pytest-embedded-qemu~=1.16
|
||||
- pytest-ignore-test-results~=0.3
|
||||
- pytest-rerunfailures
|
||||
- pytest-timeout
|
||||
- idf-build-apps~=2.8
|
||||
- python-gitlab
|
||||
- minio
|
||||
- click
|
||||
- esp-idf-monitor
|
||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||
rev: v4.5.0
|
||||
hooks:
|
||||
@@ -31,7 +51,6 @@ repos:
|
||||
.*.pb-c.c|
|
||||
.*.yuv|
|
||||
.*.rgb|
|
||||
.*.gray|
|
||||
.*COPYING.*|
|
||||
docs/sphinx-known-warnings\.txt
|
||||
)$
|
||||
@@ -51,6 +70,7 @@ repos:
|
||||
rev: v2.3.0
|
||||
hooks:
|
||||
- id: codespell
|
||||
exclude: ^docs/sphinx-known-warnings\.txt$
|
||||
- repo: local
|
||||
hooks:
|
||||
- id: check-executables
|
||||
@@ -144,7 +164,7 @@ repos:
|
||||
require_serial: true
|
||||
additional_dependencies:
|
||||
- PyYAML == 5.3.1
|
||||
- idf-build-apps~=2.13
|
||||
- idf-build-apps>=2.8,<3
|
||||
- id: sort-yaml-files
|
||||
name: sort yaml files
|
||||
entry: tools/ci/sort_yaml.py
|
||||
@@ -159,6 +179,15 @@ repos:
|
||||
files: 'tools/ci/sort_yaml\.py$'
|
||||
additional_dependencies:
|
||||
- ruamel.yaml
|
||||
- id: check-build-test-rules-path-exists
|
||||
name: check path in .build-test-rules.yml exists
|
||||
entry: tools/ci/check_build_test_rules.py check-exist
|
||||
language: python
|
||||
additional_dependencies:
|
||||
- PyYAML == 5.3.1
|
||||
always_run: true
|
||||
pass_filenames: false
|
||||
require_serial: true
|
||||
- id: cleanup-ignore-lists
|
||||
name: Remove non-existing patterns from ignore lists
|
||||
entry: tools/ci/cleanup_ignore_lists.py
|
||||
@@ -177,19 +206,14 @@ repos:
|
||||
rev: v4.0.1
|
||||
hooks:
|
||||
- id: file-contents-sorter
|
||||
files: "tools/ci/(\
|
||||
executable-list\\.txt\
|
||||
|mypy_ignore_list\\.txt\
|
||||
|check_copyright_ignore\\.txt\
|
||||
|exclude_check_tools_files\\.txt\
|
||||
)"
|
||||
files: 'tools\/ci\/(executable-list\.txt|mypy_ignore_list\.txt|check_copyright_ignore\.txt)'
|
||||
- repo: https://github.com/espressif/check-copyright/
|
||||
rev: v1.1.1
|
||||
hooks:
|
||||
- id: check-copyright
|
||||
args: ['--ignore', 'tools/ci/check_copyright_ignore.txt', '--config', 'tools/ci/check_copyright_config.yaml']
|
||||
- repo: https://github.com/espressif/conventional-precommit-linter
|
||||
rev: v1.10.0
|
||||
rev: v1.7.0
|
||||
hooks:
|
||||
- id: conventional-precommit-linter
|
||||
stages: [commit-msg]
|
||||
@@ -227,7 +251,7 @@ 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: v3.2.0
|
||||
rev: v2.5.0
|
||||
hooks:
|
||||
- id: check-kconfig-files
|
||||
- id: check-deprecated-kconfig-options
|
||||
|
||||
21
.readthedocs.yml
Normal file
21
.readthedocs.yml
Normal file
@@ -0,0 +1,21 @@
|
||||
# .readthedocs.yml
|
||||
# Read the Docs configuration file
|
||||
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
|
||||
|
||||
# Required
|
||||
version: 2
|
||||
|
||||
# Optionally build your docs in additional formats such as PDF and ePub
|
||||
formats:
|
||||
- pdf
|
||||
|
||||
# Optionally set the version of Python and requirements required to build your docs
|
||||
python:
|
||||
version: 2.7
|
||||
install:
|
||||
- requirements: docs/requirements.txt
|
||||
|
||||
# We need to list all the submodules included in documentation build by Doxygen
|
||||
submodules:
|
||||
include:
|
||||
- components/mqtt/esp-mqtt
|
||||
@@ -1,12 +1,12 @@
|
||||
cmake_minimum_required(VERSION 3.22)
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
project(esp-idf C CXX ASM)
|
||||
|
||||
if(CMAKE_CURRENT_LIST_DIR STREQUAL CMAKE_SOURCE_DIR)
|
||||
message(FATAL_ERROR "Current directory '${CMAKE_CURRENT_LIST_DIR}' is not buildable. "
|
||||
"Change directories to one of the example projects in '${CMAKE_CURRENT_LIST_DIR}/examples' and try again.")
|
||||
"Change directories to one of the example projects in '${CMAKE_CURRENT_LIST_DIR}/examples' and try "
|
||||
"again.")
|
||||
endif()
|
||||
|
||||
project(esp-idf C CXX ASM)
|
||||
|
||||
# Variables compile_options, c_compile_options, cxx_compile_options, compile_definitions, link_options shall
|
||||
# not be unset as they may already contain flags, set by toolchain-TARGET.cmake files.
|
||||
|
||||
@@ -23,15 +23,14 @@ if(BOOTLOADER_BUILD)
|
||||
endif()
|
||||
if(CMAKE_C_COMPILER_ID MATCHES "GNU")
|
||||
list(APPEND compile_options "-freorder-blocks")
|
||||
if(CONFIG_IDF_TARGET_ARCH_XTENSA)
|
||||
list(APPEND compile_options "-mno-target-align")
|
||||
endif()
|
||||
endif()
|
||||
elseif(CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_DEBUG)
|
||||
list(APPEND compile_options "-Og")
|
||||
if(CMAKE_C_COMPILER_ID MATCHES "GNU" AND NOT CONFIG_IDF_TARGET_LINUX)
|
||||
list(APPEND compile_options "-fno-shrink-wrap") # Disable shrink-wrapping to reduce binary size
|
||||
endif()
|
||||
elseif(CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_NONE)
|
||||
list(APPEND compile_options "-O0")
|
||||
elseif(CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_PERF)
|
||||
list(APPEND compile_options "-O2")
|
||||
endif()
|
||||
@@ -55,9 +54,6 @@ else()
|
||||
endif()
|
||||
if(CMAKE_C_COMPILER_ID MATCHES "GNU")
|
||||
list(APPEND compile_options "-freorder-blocks")
|
||||
if(CONFIG_IDF_TARGET_ARCH_XTENSA)
|
||||
list(APPEND compile_options "-mno-target-align")
|
||||
endif()
|
||||
endif()
|
||||
elseif(CONFIG_COMPILER_OPTIMIZATION_DEBUG)
|
||||
list(APPEND compile_options "-Og")
|
||||
@@ -109,6 +105,8 @@ if(CMAKE_C_COMPILER_ID MATCHES "Clang")
|
||||
list(APPEND compile_options "-Wno-char-subscripts")
|
||||
# Clang seems to notice format string issues which GCC doesn't.
|
||||
list(APPEND compile_options "-Wno-format-security")
|
||||
# Logic bug in essl component
|
||||
list(APPEND compile_options "-Wno-tautological-overlap-compare")
|
||||
# Some pointer checks in mDNS component check addresses which can't be NULL
|
||||
list(APPEND compile_options "-Wno-tautological-pointer-compare")
|
||||
# Similar to the above, in tcp_transport
|
||||
@@ -159,10 +157,6 @@ if(CONFIG_COMPILER_NO_MERGE_CONSTANTS)
|
||||
list(APPEND compile_options "-fno-merge-constants")
|
||||
endif()
|
||||
|
||||
if(CONFIG_COMPILER_ENABLE_TEXT_SECTION_LITERALS)
|
||||
list(APPEND compile_options "-mtext-section-literals")
|
||||
endif()
|
||||
|
||||
if(CONFIG_COMPILER_STACK_CHECK_MODE_NORM)
|
||||
list(APPEND compile_options "-fstack-protector")
|
||||
elseif(CONFIG_COMPILER_STACK_CHECK_MODE_STRONG)
|
||||
@@ -175,18 +169,6 @@ if(CONFIG_COMPILER_DUMP_RTL_FILES)
|
||||
list(APPEND compile_options "-fdump-rtl-expand")
|
||||
endif()
|
||||
|
||||
if(CMAKE_C_COMPILER_ID MATCHES "GNU" AND CMAKE_C_COMPILER_VERSION VERSION_GREATER 15.0)
|
||||
list(APPEND c_compile_options "-fzero-init-padding-bits=all" "-fno-malloc-dce")
|
||||
endif()
|
||||
|
||||
if(CONFIG_COMPILER_CXX_GLIBCXX_CONSTEXPR_COLD_CONSTEXPR)
|
||||
list(APPEND cxx_compile_options "-D_GLIBCXX20_CONSTEXPR=__attribute__((cold)) constexpr")
|
||||
list(APPEND cxx_compile_options "-D_GLIBCXX23_CONSTEXPR=__attribute__((cold)) constexpr")
|
||||
elseif(CONFIG_COMPILER_CXX_GLIBCXX_CONSTEXPR_COLD)
|
||||
list(APPEND cxx_compile_options "-D_GLIBCXX20_CONSTEXPR=__attribute__((cold))")
|
||||
list(APPEND cxx_compile_options "-D_GLIBCXX23_CONSTEXPR=__attribute__((cold))")
|
||||
endif()
|
||||
|
||||
__generate_prefix_map(prefix_map_compile_options)
|
||||
list(APPEND compile_options ${prefix_map_compile_options})
|
||||
|
||||
@@ -206,15 +188,6 @@ if(CONFIG_COMPILER_DISABLE_GCC14_WARNINGS)
|
||||
list(APPEND compile_options "-Wno-calloc-transposed-args")
|
||||
endif()
|
||||
|
||||
if(CONFIG_COMPILER_DISABLE_GCC15_WARNINGS)
|
||||
list(APPEND c_compile_options "-Wno-unterminated-string-initialization")
|
||||
list(APPEND c_compile_options "-Wno-header-guard")
|
||||
list(APPEND cxx_compile_options "-Wno-self-move")
|
||||
list(APPEND cxx_compile_options "-Wno-template-body")
|
||||
list(APPEND cxx_compile_options "-Wno-dangling-reference")
|
||||
list(APPEND cxx_compile_options "-Wno-defaulted-function-deleted")
|
||||
endif()
|
||||
|
||||
if(CONFIG_COMPILER_DISABLE_DEFAULT_ERRORS)
|
||||
if(NOT CMAKE_C_COMPILER_ID MATCHES "Clang")
|
||||
idf_build_replace_option_from_property(COMPILE_OPTIONS "-Werror" "-Werror=all")
|
||||
@@ -332,12 +305,3 @@ foreach(component_target ${build_component_targets})
|
||||
endif()
|
||||
set(__idf_component_context 0)
|
||||
endforeach()
|
||||
|
||||
# Run component validation checks after all components have been processed
|
||||
# Only run validation for the main project, not subprojects like bootloader
|
||||
idf_build_get_property(bootloader_build BOOTLOADER_BUILD)
|
||||
idf_build_get_property(esp_tee_build ESP_TEE_BUILD)
|
||||
if(NOT bootloader_build AND NOT esp_tee_build)
|
||||
include("${CMAKE_CURRENT_LIST_DIR}/tools/cmake/component_validation.cmake")
|
||||
__component_validation_run_checks()
|
||||
endif()
|
||||
|
||||
@@ -8,9 +8,9 @@ This document describes the compatibility between ESP-IDF releases and Espressif
|
||||
|
||||
NOTE: This document on release branches may be out-of-date. Check the [Compatibility file on master](https://github.com/espressif/esp-idf/blob/master/COMPATIBILITY.md) for the most accurate information.
|
||||
|
||||
See [Compatibility Advisory for Chip Revision Numbering Scheme](https://www.espressif.com/sites/default/files/advisory_downloads/AR2022-005%20Compatibility%20Advisory%20for%20Chip%20Revision%20Numbering%20%20Scheme.pdf) on the versioning of Espressif SoC revisions.
|
||||
See [Compatibility Advisory for Chip Revision Numbering Scheme](https://www.espressif.com.cn/sites/default/files/advisory_downloads/AR2022-005%20Compatibility%20Advisory%20for%20Chip%20Revision%20Numbering%20%20Scheme.pdf) on the versioning of Espressif SoC revisions.
|
||||
|
||||
You can run `esptool chip-id` to detect the series and revision of an SoC. See [SoC Errata](https://www.espressif.com/en/support/documents/technical-documents?keys=errata) for more on how to distinguish between chip revisions, and the improvements provided by chip revisions. And run `idf.py --version` to know the version of current ESP-IDF.
|
||||
You can run `esptool chip_id` to detect the series and revision of an SoC. See [SoC Errata](https://www.espressif.com.cn/en/support/documents/technical-documents?keys=errata) for more on how to distinguish between chip revisions, and the improvements provided by chip revisions. And run `idf.py --version` to know the version of current ESP-IDF.
|
||||
|
||||
## ESP-IDF Support for Different Chip Revisions
|
||||
|
||||
@@ -140,12 +140,6 @@ Supported since ESP-IDF v5.1.
|
||||
| release/v5.4 | v5.4.1+ | v5.4.1 |
|
||||
| release/v5.5 and above | v5.5+ | v5.5 |
|
||||
|
||||
### ESP32-P4
|
||||
|
||||
#### v1.0, v1.3
|
||||
|
||||
Supported since ESP-IDF v5.3.
|
||||
|
||||
## What If the ESP-IDF Version Is Lower than the `Required` Version?
|
||||
|
||||
Latest ESP-IDF versions can prevent from downloading to, or even execute binaries on unsupported chips. ESP-IDF of versions v4.4.5+, v5.0.1+, v5.1 and above have both esptool download check and bootloader loading check against the chip revision. While ESP-IDF v4.3.5 has only esptool downloading check.
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
有关乐鑫芯片版本的编码方式,请参考 [关于芯片版本 (Chip Revision) 编码方式的兼容性公告](https://www.espressif.com/sites/default/files/advisory_downloads/AR2022-005%20%E5%85%B3%E4%BA%8E%E8%8A%AF%E7%89%87%E7%89%88%E6%9C%AC%E7%BC%96%E7%A0%81%E6%96%B9%E5%BC%8F%20%28Chip%20Revision%29%20%E7%9A%84%E5%85%BC%E5%AE%B9%E6%80%A7%E5%85%AC%E5%91%8A.pdf)。
|
||||
|
||||
运行 `esptool chip-id` 可查看芯片系列及其版本。有关区分芯片版本及版本改进内容的更多信息,请参考 [芯片勘误表](https://www.espressif.com.cn/zh-hans/support/documents/technical-documents?keys=%E5%8B%98%E8%AF%AF%E8%A1%A8)。运行 `idf.py --version` 可查看当前的 ESP-IDF 版本。
|
||||
运行 `esptool chip_id` 可查看芯片系列及其版本。有关区分芯片版本及版本改进内容的更多信息,请参考 [芯片勘误表](https://www.espressif.com.cn/zh-hans/support/documents/technical-documents?keys=%E5%8B%98%E8%AF%AF%E8%A1%A8)。运行 `idf.py --version` 可查看当前的 ESP-IDF 版本。
|
||||
|
||||
## ESP-IDF 对各芯片版本的支持
|
||||
|
||||
@@ -140,11 +140,6 @@
|
||||
| release/v5.4 | v5.4.1+ | v5.4.1 |
|
||||
| release/v5.5 及以上 | v5.5+ | v5.5 |
|
||||
|
||||
### ESP32-P4
|
||||
|
||||
#### v1.0, v1.3
|
||||
|
||||
从 ESP-IDF v5.3 开始支持。
|
||||
|
||||
## 如果 ESP-IDF 版本低于 `需求版本` 会出现什么情况?
|
||||
|
||||
|
||||
118
Kconfig
118
Kconfig
@@ -118,6 +118,8 @@ mainmenu "Espressif IoT Development Framework Configuration"
|
||||
default "y" if IDF_TARGET="esp32c5"
|
||||
select FREERTOS_UNICORE
|
||||
select IDF_TARGET_ARCH_RISCV
|
||||
# TODO: [ESPTOOL-1044] remove when stub supported
|
||||
select IDF_ENV_BRINGUP
|
||||
|
||||
config IDF_TARGET_ESP32P4
|
||||
bool
|
||||
@@ -141,19 +143,13 @@ mainmenu "Espressif IoT Development Framework Configuration"
|
||||
default "y" if IDF_TARGET="esp32h21"
|
||||
select FREERTOS_UNICORE
|
||||
select IDF_TARGET_ARCH_RISCV
|
||||
select IDF_ENV_FPGA
|
||||
select IDF_ENV_BRINGUP
|
||||
select IDF_ENV_FPGA if ESP32H21_SELECTS_REV_MP
|
||||
|
||||
config IDF_TARGET_ESP32H4
|
||||
bool
|
||||
default "y" if IDF_TARGET="esp32h4"
|
||||
select IDF_TARGET_ARCH_RISCV
|
||||
select IDF_ENV_BRINGUP
|
||||
select IDF_ENV_FPGA if ESP32H4_SELECTS_REV_MP
|
||||
|
||||
config IDF_TARGET_ESP32S31
|
||||
bool
|
||||
default "y" if IDF_TARGET="esp32s31"
|
||||
select FREERTOS_UNICORE # TODO: [ESP32H4] IDF-12319, need remove
|
||||
select IDF_TARGET_ARCH_RISCV
|
||||
select IDF_ENV_FPGA
|
||||
select IDF_ENV_BRINGUP
|
||||
@@ -176,7 +172,6 @@ mainmenu "Espressif IoT Development Framework Configuration"
|
||||
default 0x0014 if IDF_TARGET_ESP32C61
|
||||
default 0x0019 if IDF_TARGET_ESP32H21
|
||||
default 0x001C if IDF_TARGET_ESP32H4
|
||||
default 0x0020 if IDF_TARGET_ESP32S31
|
||||
default 0xFFFF
|
||||
|
||||
|
||||
@@ -227,10 +222,10 @@ mainmenu "Espressif IoT Development Framework Configuration"
|
||||
|
||||
When loading the BIN with UART, the ROM will jump to ram and run the app after finishing the ROM
|
||||
startup code, so there's no additional startup initialization required. You can use the
|
||||
`load-ram` in esptool to load the generated .bin file into ram and execute.
|
||||
`load_ram` in esptool.py to load the generated .bin file into ram and execute.
|
||||
|
||||
Example:
|
||||
esptool --chip {chip} -p {port} -b {baud} --no-stub load-ram {app.bin}
|
||||
esptool.py --chip {chip} -p {port} -b {baud} --no-stub load_ram {app.bin}
|
||||
|
||||
Recommended sdkconfig.defaults for building loadable ELF files is as follows.
|
||||
CONFIG_APP_BUILD_TYPE_RAM is required, other options help reduce application
|
||||
@@ -238,7 +233,7 @@ mainmenu "Espressif IoT Development Framework Configuration"
|
||||
|
||||
CONFIG_APP_BUILD_TYPE_RAM=y
|
||||
CONFIG_VFS_SUPPORT_TERMIOS=
|
||||
CONFIG_LIBC_NEWLIB_NANO_FORMAT=y
|
||||
CONFIG_NEWLIB_NANO_FORMAT=y
|
||||
CONFIG_ESP_SYSTEM_PANIC_PRINT_HALT=y
|
||||
CONFIG_ESP_DEBUG_STUBS_ENABLE=
|
||||
CONFIG_ESP_ERR_TO_NAME_LOOKUP=
|
||||
@@ -378,27 +373,6 @@ mainmenu "Espressif IoT Development Framework Configuration"
|
||||
|
||||
endchoice
|
||||
|
||||
config COMPILER_ENABLE_RISCV_ZCMP
|
||||
bool "Enable RISCV ZCMP extension"
|
||||
depends on SOC_CPU_ZCMP_WORKAROUND
|
||||
default n
|
||||
help
|
||||
Enable the RISC-V ZCMP (Compressed Macro) extension to reduce binary size
|
||||
by optimizing function prologue and epilogue sequences.
|
||||
|
||||
Note: Due to a hardware issue on some ESP32 chips (e.g., ESP32C5, ESP32C61,
|
||||
ESP32H4), executing "cm.push" may re-enable interrupts even when global
|
||||
interrupts are disabled (mstatus.mie = 0). This can cause unexpected interrupts
|
||||
during CPU retention or within critical sections.
|
||||
|
||||
Workarounds are implemented in the IDF codebase. However, if user code
|
||||
directly disables interrupts, additional actions may be required. Refer
|
||||
to code examples under the SOC_CPU_ZCMP_WORKAROUND macro, or disable
|
||||
the ZCMP extension for source files that contain functions which may
|
||||
execute while mstatus.mie = 0.
|
||||
|
||||
Even with these workarounds, the issue may still affect dual-core variants.
|
||||
|
||||
choice COMPILER_OPTIMIZATION_ASSERTION_LEVEL
|
||||
prompt "Assertion level"
|
||||
default COMPILER_OPTIMIZATION_ASSERTIONS_ENABLE
|
||||
@@ -436,7 +410,7 @@ mainmenu "Espressif IoT Development Framework Configuration"
|
||||
|
||||
config COMPILER_ASSERT_NDEBUG_EVALUATE
|
||||
bool "Enable the evaluation of the expression inside assert(X) when NDEBUG is set"
|
||||
default n
|
||||
default y
|
||||
help
|
||||
When NDEBUG is set, assert(X) will not cause code to trigger an assertion.
|
||||
With this option set, assert(X) will still evaluate the expression X, though
|
||||
@@ -446,6 +420,9 @@ mainmenu "Espressif IoT Development Framework Configuration"
|
||||
This is not according to the standard, which states that the assert(X) should
|
||||
be replaced with ((void)0) if NDEBUG is defined.
|
||||
|
||||
In ESP-IDF v6.0 the default behavior will change to "no" to be in line with the
|
||||
standard.
|
||||
|
||||
choice COMPILER_FLOAT_LIB_FROM
|
||||
prompt "Compiler float lib source"
|
||||
default COMPILER_FLOAT_LIB_FROM_RVFPLIB if ESP_ROM_HAS_RVFPLIB
|
||||
@@ -576,20 +553,6 @@ mainmenu "Espressif IoT Development Framework Configuration"
|
||||
distribution is more uniform across libraries. On downside, it may increase
|
||||
the binary size and hence should be used during development phase only.
|
||||
|
||||
config COMPILER_ENABLE_TEXT_SECTION_LITERALS
|
||||
bool
|
||||
depends on IDF_TOOLCHAIN_GCC
|
||||
depends on IDF_TARGET_ARCH_XTENSA
|
||||
default y if ESPTOOLPY_FAST_REFLASHING
|
||||
help
|
||||
Intersperse Xtensa literals within the text section to keep
|
||||
them as close as possible to their references. This prevents
|
||||
literals from being placed into a separate section in the
|
||||
output file and prevents the linker from combining literal
|
||||
pools from different object files. Enabling this is necessary
|
||||
for fast reflashing to prevent mixing code from mutable and
|
||||
immutable libraries.
|
||||
|
||||
config COMPILER_WARN_WRITE_STRINGS
|
||||
bool "Enable -Wwrite-strings warning flag"
|
||||
default "n"
|
||||
@@ -618,7 +581,7 @@ mainmenu "Espressif IoT Development Framework Configuration"
|
||||
|
||||
config COMPILER_DISABLE_DEFAULT_ERRORS
|
||||
bool "Disable errors for default warnings"
|
||||
default "n"
|
||||
default "y"
|
||||
help
|
||||
Enable this option if you do not want default warnings to be considered as errors,
|
||||
especially when updating IDF.
|
||||
@@ -651,13 +614,6 @@ mainmenu "Espressif IoT Development Framework Configuration"
|
||||
Enable this option if use GCC 14 or newer, and want to disable warnings which don't appear with
|
||||
GCC 13.
|
||||
|
||||
config COMPILER_DISABLE_GCC15_WARNINGS
|
||||
bool "Disable new warnings introduced in GCC 15"
|
||||
default "n"
|
||||
help
|
||||
Enable this option if use GCC 15 or newer, and want to disable warnings which don't appear with
|
||||
GCC 14.
|
||||
|
||||
config COMPILER_DUMP_RTL_FILES
|
||||
bool "Dump RTL files during compilation"
|
||||
help
|
||||
@@ -694,7 +650,7 @@ mainmenu "Espressif IoT Development Framework Configuration"
|
||||
|
||||
choice COMPILER_ORPHAN_SECTIONS
|
||||
prompt "Orphan sections handling"
|
||||
default COMPILER_ORPHAN_SECTIONS_ERROR
|
||||
default COMPILER_ORPHAN_SECTIONS_WARNING
|
||||
depends on !IDF_TARGET_LINUX
|
||||
help
|
||||
If the linker finds orphan sections, it attempts to place orphan sections after sections of the same
|
||||
@@ -702,11 +658,6 @@ mainmenu "Espressif IoT Development Framework Configuration"
|
||||
That means that orphan sections could placed between sections defined in IDF linker scripts.
|
||||
This could lead to corruption of the binary image. Configure the linker action here.
|
||||
|
||||
config COMPILER_ORPHAN_SECTIONS_ERROR
|
||||
bool "Fail if orphan sections found"
|
||||
help
|
||||
Fails the link step with an error if orphan sections are detected.
|
||||
|
||||
config COMPILER_ORPHAN_SECTIONS_WARNING
|
||||
bool "Place with warning"
|
||||
help
|
||||
@@ -725,34 +676,6 @@ mainmenu "Espressif IoT Development Framework Configuration"
|
||||
help
|
||||
Enable compiler static analyzer. This may produce false-positive results and increases compile time.
|
||||
|
||||
choice COMPILER_CXX_GLIBCXX_CONSTEXPR
|
||||
prompt "Define _GLIBCXX_CONSTEXPR"
|
||||
default COMPILER_CXX_GLIBCXX_CONSTEXPR_NO_CHANGE
|
||||
depends on IDF_TOOLCHAIN_GCC && !IDF_TARGET_LINUX
|
||||
help
|
||||
Modify libstdc++ _GLIBCXX20_CONSTEXPR and _GLIBCXX23_CONSTEXPR definitions to provide size
|
||||
optimizations. The total size optimization depends on the application's structure.
|
||||
There is no robust way to determine which option would be better in a particular case.
|
||||
Please try all available options to find the best size optimization.
|
||||
|
||||
config COMPILER_CXX_GLIBCXX_CONSTEXPR_NO_CHANGE
|
||||
bool "No change"
|
||||
help
|
||||
Use default _GLIBCXX20_CONSTEXPR and _GLIBCXX23_CONSTEXPR defined in libstdc++
|
||||
|
||||
config COMPILER_CXX_GLIBCXX_CONSTEXPR_COLD_CONSTEXPR
|
||||
bool "_GLIBCXX2X_CONSTEXPR=__attribute__((cold)) constexpr"
|
||||
help
|
||||
Define _GLIBCXX20_CONSTEXPR=__attribute__((cold)) constexpr
|
||||
Define _GLIBCXX23_CONSTEXPR=__attribute__((cold)) constexpr
|
||||
|
||||
config COMPILER_CXX_GLIBCXX_CONSTEXPR_COLD
|
||||
bool "_GLIBCXX2X_CONSTEXPR=__attribute__((cold))"
|
||||
help
|
||||
Define _GLIBCXX20_CONSTEXPR=__attribute__((cold)).
|
||||
Define _GLIBCXX23_CONSTEXPR=__attribute__((cold)).
|
||||
endchoice
|
||||
|
||||
endmenu # Compiler Options
|
||||
|
||||
menu "Component config"
|
||||
@@ -764,17 +687,6 @@ mainmenu "Espressif IoT Development Framework Configuration"
|
||||
depends on "${IDF_MINIMAL_BUILD}"
|
||||
|
||||
source "$COMPONENT_KCONFIGS_SOURCE_FILE"
|
||||
|
||||
menu "Configuration for components not included in the build"
|
||||
depends on "${IDF_BUILD_V2}"
|
||||
osource "$COMPONENT_KCONFIGS_EXCLUDED_SOURCE_FILE"
|
||||
endmenu
|
||||
|
||||
endmenu
|
||||
|
||||
menu "Project configuration for components not included in the build"
|
||||
depends on "${IDF_BUILD_V2}"
|
||||
osource "$COMPONENT_KCONFIGS_PROJBUILD_EXCLUDED_SOURCE_FILE"
|
||||
endmenu
|
||||
|
||||
config IDF_EXPERIMENTAL_FEATURES
|
||||
@@ -795,7 +707,3 @@ mainmenu "Espressif IoT Development Framework Configuration"
|
||||
- CONFIG_ESP_WIFI_ENABLE_ROAMING_APP
|
||||
- CONFIG_USB_HOST_EXT_PORT_RESET_ATTEMPTS
|
||||
- CONFIG_LIBC_PICOLIBC
|
||||
- CONFIG_GDMA_ENABLE_WEIGHTED_ARBITRATION
|
||||
- CONFIG_I3C_MASTER_ENABLED
|
||||
- CONFIG_MBEDTLS_ESP_IDF_USE_PSA_CRYPTO
|
||||
- CONFIG_ESPTOOLPY_FAST_REFLASHING
|
||||
|
||||
27
README.md
27
README.md
@@ -15,19 +15,18 @@ ESP-IDF is the development framework for Espressif SoCs supported on Windows, Li
|
||||
|
||||
The following table shows ESP-IDF support of Espressif SoCs where ![alt text][preview] and ![alt text][supported] denote preview status and support, respectively. The preview support is usually limited in time and intended for beta versions of chips. Please use an ESP-IDF release where the desired SoC is already supported.
|
||||
|
||||
|Chip | v5.1 | v5.2 | v5.3 | v5.4 | v5.5 | v6.0 | |
|
||||
|:----------- |:---------------------: |:---------------------: |:---------------------: | :---------------------: | :-------------------: | :--------------------: |:------------------------------------------------------------------- |
|
||||
|ESP32 | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | |
|
||||
|ESP32-S2 | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | |
|
||||
|ESP32-C3 | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | |
|
||||
|ESP32-S3 | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] |[Announcement](https://www.espressif.com/en/news/ESP32_S3) |
|
||||
|ESP32-C2 | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] |[Announcement](https://www.espressif.com/en/news/ESP32-C2) |
|
||||
|ESP32-C6 | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] |[Announcement](https://www.espressif.com/en/news/ESP32_C6) |
|
||||
|ESP32-H2 | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] |[Announcement](https://www.espressif.com/en/news/ESP32_H2) |
|
||||
|ESP32-P4 | | | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] |[Announcement](https://www.espressif.com/en/news/ESP32-P4) |
|
||||
|ESP32-C5 | | | | | ![alt text][supported] | ![alt text][supported] |[Announcement](https://www.espressif.com/en/news/ESP32-C5) |
|
||||
|ESP32-C61 | | | | | ![alt text][supported] | ![alt text][supported] |[Announcement](https://www.espressif.com/en/products/socs/esp32-c61) |
|
||||
|ESP32-H4 | | | | | | ![alt text][preview] |[Announcement](https://www.espressif.com/en/news/ESP32-H4) |
|
||||
|Chip | v5.1 | v5.2 | v5.3 | v5.4 | v5.5 | |
|
||||
|:----------- |:--------------------: | :--------------------: | :--------------------: | :--------------------: | :--------------------: |:------------------------------------------------------------------- |
|
||||
|ESP32 | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | |
|
||||
|ESP32-S2 |![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | |
|
||||
|ESP32-C3 | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | |
|
||||
|ESP32-S3 | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] |[Announcement](https://www.espressif.com/en/news/ESP32_S3) |
|
||||
|ESP32-C2 | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] |[Announcement](https://www.espressif.com/en/news/ESP32-C2) |
|
||||
|ESP32-C6 | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] |[Announcement](https://www.espressif.com/en/news/ESP32_C6) |
|
||||
|ESP32-H2 |![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] |[Announcement](https://www.espressif.com/en/news/ESP32_H2) |
|
||||
|ESP32-P4 | | | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] |[Announcement](https://www.espressif.com/en/news/ESP32-P4) |
|
||||
|ESP32-C5 | | | | |![alt text][preview] |[Announcement](https://www.espressif.com/en/news/ESP32-C5) |
|
||||
|ESP32-C61 | | | | |![alt text][preview] |[Announcement](https://www.espressif.com/en/products/socs/esp32-c61) |
|
||||
|
||||
[supported]: https://img.shields.io/badge/-supported-green "supported"
|
||||
[preview]: https://img.shields.io/badge/-preview-orange "preview"
|
||||
@@ -83,7 +82,7 @@ See the Getting Started guide links above for a detailed setup guide. This is a
|
||||
|
||||
## Flashing the Project
|
||||
|
||||
When the build finishes, it will print a command line to use `esptool` to flash the chip. However you can also do this automatically by running:
|
||||
When the build finishes, it will print a command line to use esptool.py to flash the chip. However you can also do this automatically by running:
|
||||
|
||||
`idf.py -p PORT flash`
|
||||
|
||||
|
||||
28
README_CN.md
28
README_CN.md
@@ -15,19 +15,19 @@ ESP-IDF 是乐鑫官方推出的物联网开发框架,支持 Windows、Linux
|
||||
|
||||
下表总结了乐鑫芯片在 ESP-IDF 各版本中的支持状态,其中 ![alt text][supported] 代表已支持,![alt text][preview] 代表目前处于预览支持状态。预览支持状态通常有时间限制,而且仅适用于测试版芯片。请确保使用与芯片相匹配的 ESP-IDF 版本。
|
||||
|
||||
|芯片 | v5.1 | v5.2 | v5.3 | v5.4 | v5.5 | v6.0 | |
|
||||
|:----------- | :-------------------: | :--------------------: | :--------------------: | :--------------------: | :-------------------: | :-------------------: |:------------------------------------------------------------------------- |
|
||||
|ESP32 |![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] |![alt text][supported] | |
|
||||
|ESP32-S2 |![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] |![alt text][supported] | |
|
||||
|ESP32-C3 |![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] |![alt text][supported] | |
|
||||
|ESP32-S3 |![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] |![alt text][supported] | [芯片发布公告](https://www.espressif.com/zh-hans/news/ESP32_S3) |
|
||||
|ESP32-C2 |![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] |![alt text][supported] | [芯片发布公告](https://www.espressif.com/zh-hans/news/ESP32-C2) |
|
||||
|ESP32-C6 |![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] |![alt text][supported] | [芯片发布公告](https://www.espressif.com/zh-hans/news/ESP32_C6) |
|
||||
|ESP32-H2 |![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] |![alt text][supported] | [芯片发布公告](https://www.espressif.com/zh-hans/news/ESP32_H2) |
|
||||
|ESP32-P4 | | | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] |![alt text][supported] | [芯片发布公告](https://www.espressif.com/zh-hans/news/ESP32-P4) |
|
||||
|ESP32-C5 | | | | | ![alt text][supported] |![alt text][supported] | [芯片发布公告](https://www.espressif.com/zh-hans/news/ESP32-C5) |
|
||||
|ESP32-C61 | | | | | ![alt text][supported] |![alt text][supported] | [芯片发布公告](https://www.espressif.com/zh-hans/products/socs/esp32-c61) |
|
||||
|ESP32-H4 | | | | | |![alt text][preview] | [芯片发布公告](https://www.espressif.com/zh-hans/news/ESP32-H4) |
|
||||
芯片 | v5.1 | v5.2 | v5.3 | v5.4 | v5.5 | |
|
||||
|:----------- | :--------------------: | :--------------------: | :--------------------: | :--------------------: | :--------------------: |:------------------------------------------------------------------------ |
|
||||
|ESP32 |![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] |![alt text][supported] | |
|
||||
|ESP32-S2 |![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | |
|
||||
|ESP32-C3 |![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | |
|
||||
|ESP32-S3 |![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] |![alt text][supported] | [芯片发布公告](https://www.espressif.com/zh-hans/news/ESP32_S3) |
|
||||
|ESP32-C2 |![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] |![alt text][supported] | [芯片发布公告](https://www.espressif.com/zh-hans/news/ESP32-C2) |
|
||||
|ESP32-C6 |![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] |![alt text][supported] | [芯片发布公告](https://www.espressif.com/zh-hans/news/ESP32_C6) |
|
||||
|ESP32-H2 |![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] |![alt text][supported] | [芯片发布公告](https://www.espressif.com/zh-hans/news/ESP32_H2) |
|
||||
|ESP32-P4 | | | ![alt text][supported] | ![alt text][supported] |![alt text][supported] | [芯片发布公告](https://www.espressif.com/zh-hans/news/ESP32-P4) |
|
||||
|ESP32-C5 | | | | |![alt text][preview] | [芯片发布公告](https://www.espressif.com/zh-hans/news/ESP32-C5) |
|
||||
|ESP32-C61 | | | | |![alt text][preview] | [芯片发布公告](https://www.espressif.com/zh-hans/products/socs/esp32-c61) |
|
||||
|
||||
|
||||
[supported]: https://img.shields.io/badge/-%E6%94%AF%E6%8C%81-green "supported"
|
||||
[preview]: https://img.shields.io/badge/-%E9%A2%84%E8%A7%88-orange "preview"
|
||||
@@ -83,7 +83,7 @@ ESP-IDF 中的子模块采用相对路径([详见 .gitmodules 文件](.gitmodu
|
||||
|
||||
## 烧写项目
|
||||
|
||||
当构建结束,终端会打印出一条命令行,告知如何使用 `esptool` 工具烧写项目到芯片中。但你也可以运行下面这条命令来自动烧写:
|
||||
当构建结束,终端会打印出一条命令行,告知如何使用 esptool.py 工具烧写项目到芯片中。但你也可以运行下面这条命令来自动烧写:
|
||||
|
||||
`idf.py -p PORT flash`
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ The core components are organized into two groups.
|
||||
|
||||
The first group (referred to as `G0`) includes `hal`, `arch` (where `arch` is either `riscv` or `xtensa` depending on the chip), `esp_rom`, `esp_common`, and `soc`. This group contains information about and provides low-level access to the underlying hardware. In the case of `esp_common`, it contains hardware-agnostic code and utilities. These components may have dependencies on each other within the group, but outside dependencies should be minimized. The reason for this approach is that these components are fundamental, and many other components may require them. Ideally, the dependency relationship only goes one way, making it easier for this group to be usable in other projects.
|
||||
|
||||
The second group (referred to as `G1`) operates at a higher level than the first group. `G1` includes the components `esp_hw_support`, `esp_system`, `esp_libc`, `spi_flash`, `freertos`, `log`, and `heap`. Like the first group, circular dependencies within this group are allowed, and these components can have dependencies on the first group. G1 components represent essential software mechanisms for building other components.
|
||||
The second group (referred to as `G1`) operates at a higher level than the first group. `G1` includes the components `esp_hw_support`, `esp_system`, `newlib`, `spi_flash`, `freertos`, `log`, and `heap`. Like the first group, circular dependencies within this group are allowed, and these components can have dependencies on the first group. G1 components represent essential software mechanisms for building other components.
|
||||
|
||||
## Descriptions
|
||||
|
||||
@@ -40,7 +40,7 @@ Example:
|
||||
|
||||
#### `esp_common`
|
||||
|
||||
Contains hardware-agnostic definitions, constants, macros, utilities, 'pure' and/or algorithmic functions that is usable by all other components (that is, barring there being a more appropriate component to put them in).
|
||||
Contains hardware-agnostic definitions, constants, macros, utilities, 'pure' and/or algorithmic functions that is useable by all other components (that is, barring there being a more appropriate component to put them in).
|
||||
|
||||
Example:
|
||||
|
||||
@@ -85,7 +85,7 @@ Logging library.
|
||||
|
||||
Heap implementation.
|
||||
|
||||
#### `esp_libc`
|
||||
#### `newlib`
|
||||
|
||||
Some functions n the standard library are implemented here, especially those needing other `G1` components.
|
||||
|
||||
|
||||
@@ -4,38 +4,120 @@ if(${target} STREQUAL "linux")
|
||||
return() # This component is not supported by the POSIX/Linux simulator
|
||||
endif()
|
||||
|
||||
if(CONFIG_ESP_TRACE_TRANSPORT_APPTRACE)
|
||||
set(srcs
|
||||
"app_trace.c"
|
||||
"app_trace_util.c"
|
||||
"host_file_io.c"
|
||||
)
|
||||
|
||||
if(NOT CONFIG_APPTRACE_DEST_UART) # JTAG or None
|
||||
if(CONFIG_IDF_TARGET_ARCH_XTENSA)
|
||||
list(APPEND srcs "port/xtensa/port_jtag.c")
|
||||
elseif(CONFIG_IDF_TARGET_ARCH_RISCV)
|
||||
list(APPEND srcs "port/riscv/port_jtag.c")
|
||||
endif()
|
||||
list(APPEND srcs "app_trace_membufs_proto.c")
|
||||
endif()
|
||||
|
||||
if(NOT CONFIG_APPTRACE_DEST_JTAG) # UART or None
|
||||
list(APPEND srcs "port/port_uart.c")
|
||||
endif()
|
||||
endif()
|
||||
set(srcs
|
||||
"app_trace.c"
|
||||
"app_trace_util.c"
|
||||
"host_file_io.c")
|
||||
|
||||
if(CONFIG_ESP_DEBUG_STUBS_ENABLE)
|
||||
list(APPEND srcs "debug_stubs.c")
|
||||
list(APPEND srcs
|
||||
"debug_stubs.c")
|
||||
endif()
|
||||
|
||||
if(CONFIG_APPTRACE_GCOV_ENABLE)
|
||||
if("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU")
|
||||
list(APPEND srcs
|
||||
"gcov/gcov_rtio.c")
|
||||
else()
|
||||
fail_at_build_time(app_trace "Only GNU compiler can link with Gcov library")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(include_dirs "include")
|
||||
|
||||
set(priv_include_dirs "private_include" "port/include")
|
||||
|
||||
if(CONFIG_APPTRACE_MEMBUFS_APPTRACE_PROTO_ENABLE)
|
||||
list(APPEND srcs
|
||||
"app_trace_membufs_proto.c")
|
||||
|
||||
if(CONFIG_IDF_TARGET_ARCH_XTENSA)
|
||||
list(APPEND srcs
|
||||
"port/xtensa/port.c")
|
||||
endif()
|
||||
if(CONFIG_IDF_TARGET_ARCH_RISCV)
|
||||
list(APPEND srcs
|
||||
"port/riscv/port.c")
|
||||
endif()
|
||||
endif()
|
||||
list(APPEND srcs
|
||||
"port/port_uart.c")
|
||||
|
||||
if(CONFIG_APPTRACE_SV_ENABLE)
|
||||
list(APPEND include_dirs
|
||||
sys_view/Config
|
||||
sys_view/SEGGER
|
||||
sys_view/Sample/FreeRTOSV10.4)
|
||||
|
||||
list(APPEND srcs
|
||||
"sys_view/SEGGER/SEGGER_SYSVIEW.c"
|
||||
"sys_view/Sample/FreeRTOSV10.4/Config/esp/SEGGER_SYSVIEW_Config_FreeRTOS.c"
|
||||
"sys_view/Sample/FreeRTOSV10.4/SEGGER_SYSVIEW_FreeRTOS.c"
|
||||
"sys_view/esp/SEGGER_RTT_esp.c"
|
||||
"sys_view/ext/heap_trace_module.c"
|
||||
"sys_view/ext/logging.c")
|
||||
endif()
|
||||
|
||||
if(CONFIG_HEAP_TRACING_TOHOST)
|
||||
list(APPEND srcs "heap_trace_tohost.c")
|
||||
if(CONFIG_IDF_TARGET_ARCH_XTENSA)
|
||||
set_source_files_properties(heap_trace_tohost.c PROPERTIES COMPILE_FLAGS -Wno-frame-address)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
idf_component_register(SRCS "${srcs}"
|
||||
INCLUDE_DIRS "${include_dirs}"
|
||||
PRIV_INCLUDE_DIRS "${priv_include_dirs}"
|
||||
PRIV_REQUIRES esp_driver_gptimer
|
||||
REQUIRES esp_timer esp_driver_uart
|
||||
PRIV_REQUIRES esp_driver_gptimer esp_driver_gpio esp_driver_uart
|
||||
REQUIRES esp_timer
|
||||
LDFRAGMENTS linker.lf)
|
||||
|
||||
# Force app_trace to also appear later than gcov in link line
|
||||
idf_component_get_property(app_trace app_trace COMPONENT_LIB)
|
||||
|
||||
if(CONFIG_APPTRACE_GCOV_ENABLE)
|
||||
if(CMAKE_C_COMPILER_ID MATCHES "Clang")
|
||||
# Coverage info is not supported when clang is used
|
||||
# TODO: LLVM-214
|
||||
message(FATAL_ERROR "Coverage info is not supported when building with Clang!")
|
||||
endif()
|
||||
|
||||
# The original Gcov library from toolchain will be objcopy with symbols redefinitions (see file gcov/io_sym.map).
|
||||
# This needs because ESP has no file-system onboard, and redefined functions solves this problem and transmits
|
||||
# output file to host PC.
|
||||
|
||||
# Set a name for Gcov library
|
||||
set(GCOV_LIB libgcov_rtio)
|
||||
|
||||
# Set include direcrory of Gcov internal headers
|
||||
execute_process(COMMAND ${CMAKE_C_COMPILER} -print-file-name=plugin
|
||||
OUTPUT_VARIABLE gcc_plugin_dir
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
ERROR_QUIET)
|
||||
set_source_files_properties(gcov/gcov_rtio.c
|
||||
PROPERTIES COMPILE_FLAGS "-I${gcc_plugin_dir}/include")
|
||||
|
||||
# Copy libgcov.a with symbols redefinition
|
||||
find_library(GCOV_LIBRARY_PATH gcov ${CMAKE_C_IMPLICIT_LINK_DIRECTORIES})
|
||||
add_custom_command(OUTPUT ${GCOV_LIB}.a
|
||||
COMMAND ${_CMAKE_TOOLCHAIN_PREFIX}objcopy
|
||||
--redefine-syms ${CMAKE_CURRENT_LIST_DIR}/gcov/io_sym.map
|
||||
${GCOV_LIBRARY_PATH} ${GCOV_LIB}.a
|
||||
MAIN_DEPENDENCY ${GCOV_LIBRARY_PATH}
|
||||
VERBATIM)
|
||||
add_custom_target(${GCOV_LIB}_target DEPENDS ${GCOV_LIB}.a)
|
||||
add_library(${GCOV_LIB} STATIC IMPORTED)
|
||||
set_target_properties(${GCOV_LIB}
|
||||
PROPERTIES
|
||||
IMPORTED_LOCATION ${CMAKE_CURRENT_BINARY_DIR}/${GCOV_LIB}.a)
|
||||
add_dependencies(${GCOV_LIB} ${GCOV_LIB}_target)
|
||||
add_dependencies(${COMPONENT_LIB} ${GCOV_LIB})
|
||||
|
||||
# disable --coverage for this component, as it is used as transport for gcov
|
||||
target_compile_options(${COMPONENT_LIB} PRIVATE "-fno-profile-arcs" "-fno-test-coverage")
|
||||
target_link_options(${COMPONENT_LIB} INTERFACE "-Wl,--wrap=__gcov_init")
|
||||
|
||||
target_link_libraries(${COMPONENT_LIB} INTERFACE ${GCOV_LIB} $<TARGET_FILE:${app_trace}> c)
|
||||
else()
|
||||
target_link_libraries(${COMPONENT_LIB} INTERFACE $<TARGET_FILE:${app_trace}> c)
|
||||
endif()
|
||||
|
||||
400
components/app_trace/Kconfig
Normal file
400
components/app_trace/Kconfig
Normal file
@@ -0,0 +1,400 @@
|
||||
menu "Application Level Tracing"
|
||||
|
||||
choice APPTRACE_DESTINATION1
|
||||
prompt "Data Destination 1"
|
||||
default APPTRACE_DEST_NONE
|
||||
help
|
||||
Select destination for application trace: JTAG or none (to disable).
|
||||
|
||||
config APPTRACE_DEST_JTAG
|
||||
bool "JTAG"
|
||||
select APPTRACE_DEST_TRAX if IDF_TARGET_ARCH_XTENSA
|
||||
select APPTRACE_MEMBUFS_APPTRACE_PROTO_ENABLE
|
||||
select APPTRACE_ENABLE
|
||||
|
||||
config APPTRACE_DEST_NONE
|
||||
bool "None"
|
||||
|
||||
endchoice
|
||||
|
||||
config APPTRACE_DEST_UART
|
||||
bool
|
||||
|
||||
config APPTRACE_DEST_UART_NOUSB
|
||||
bool
|
||||
|
||||
choice APPTRACE_DESTINATION2
|
||||
prompt "Data Destination 2"
|
||||
default APPTRACE_DEST_UART_NONE
|
||||
help
|
||||
Select destination for application trace: UART(XX) or none (to disable).
|
||||
|
||||
config APPTRACE_DEST_UART0
|
||||
bool "UART0"
|
||||
select APPTRACE_ENABLE
|
||||
select APPTRACE_DEST_UART
|
||||
select APPTRACE_DEST_UART_NOUSB
|
||||
depends on (ESP_CONSOLE_UART_NUM !=0)
|
||||
|
||||
config APPTRACE_DEST_UART1
|
||||
bool "UART1"
|
||||
select APPTRACE_ENABLE
|
||||
select APPTRACE_DEST_UART
|
||||
select APPTRACE_DEST_UART_NOUSB
|
||||
depends on (ESP_CONSOLE_UART_NUM !=1)
|
||||
|
||||
config APPTRACE_DEST_UART2
|
||||
bool "UART2"
|
||||
select APPTRACE_ENABLE
|
||||
select APPTRACE_DEST_UART
|
||||
select APPTRACE_DEST_UART_NOUSB
|
||||
depends on (ESP_CONSOLE_UART_NUM !=2) && (SOC_UART_NUM > 2)
|
||||
|
||||
config APPTRACE_DEST_USB_CDC
|
||||
bool "USB_CDC"
|
||||
select APPTRACE_ENABLE
|
||||
select APPTRACE_DEST_UART
|
||||
depends on !ESP_CONSOLE_USB_CDC && (IDF_TARGET_ESP32C3 || IDF_TARGET_ESP32S3) && !USB_ENABLED
|
||||
|
||||
config APPTRACE_DEST_UART_NONE
|
||||
bool "None"
|
||||
endchoice
|
||||
|
||||
config APPTRACE_UART_TX_GPIO
|
||||
int "UART TX on GPIO<num>"
|
||||
depends on APPTRACE_DEST_UART_NOUSB
|
||||
range 0 46
|
||||
default 12 if IDF_TARGET_ESP32
|
||||
default 12 if IDF_TARGET_ESP32C3
|
||||
default 12
|
||||
help
|
||||
This GPIO is used for UART TX pin.
|
||||
|
||||
config APPTRACE_UART_RX_GPIO
|
||||
int "UART RX on GPIO<num>"
|
||||
depends on APPTRACE_DEST_UART_NOUSB
|
||||
range 0 46
|
||||
default 13 if IDF_TARGET_ESP32
|
||||
default 13 if IDF_TARGET_ESP32C3
|
||||
default 13
|
||||
help
|
||||
This GPIO is used for UART RX pin.
|
||||
|
||||
config APPTRACE_UART_BAUDRATE
|
||||
int
|
||||
prompt "UART baud rate" if APPTRACE_DEST_UART
|
||||
depends on APPTRACE_DEST_UART
|
||||
default 1000000
|
||||
range 1200 8000000
|
||||
range 1200 1000000
|
||||
help
|
||||
This baud rate is used for UART.
|
||||
|
||||
The app's maximum baud rate depends on the UART clock source. If Power Management is disabled,
|
||||
the UART clock source is the APB clock and all baud rates in the available range will be sufficiently
|
||||
accurate. If Power Management is enabled, REF_TICK clock source is used so the baud rate is divided
|
||||
from 1MHz. Baud rates above 1Mbps are not possible and values between 500Kbps and 1Mbps may not be
|
||||
accurate.
|
||||
|
||||
config APPTRACE_UART_RX_BUFF_SIZE
|
||||
int
|
||||
prompt "UART RX ring buffer size" if APPTRACE_DEST_UART
|
||||
depends on APPTRACE_DEST_UART
|
||||
default 128
|
||||
range 64 32768
|
||||
help
|
||||
Size of the UART input ring buffer.
|
||||
This size related to the baudrate, system tick frequency and amount of data to transfer.
|
||||
The data placed to this buffer before sent out to the interface.
|
||||
|
||||
config APPTRACE_UART_TX_BUFF_SIZE
|
||||
int
|
||||
prompt "UART TX ring buffer size" if APPTRACE_DEST_UART
|
||||
depends on APPTRACE_DEST_UART
|
||||
default 4096
|
||||
range 2048 32768
|
||||
help
|
||||
Size of the UART output ring buffer.
|
||||
This size related to the baudrate, system tick frequency and amount of data to transfer.
|
||||
|
||||
config APPTRACE_UART_TX_MSG_SIZE
|
||||
int
|
||||
prompt "UART TX message size" if APPTRACE_DEST_UART
|
||||
depends on APPTRACE_DEST_UART
|
||||
default 128
|
||||
range 64 32768
|
||||
help
|
||||
Maximum size of the single message to transfer.
|
||||
|
||||
config APPTRACE_UART_TASK_PRIO
|
||||
int
|
||||
prompt "UART Task Priority" if APPTRACE_DEST_UART
|
||||
default 1
|
||||
range 1 32
|
||||
help
|
||||
UART task priority. In case of high events rate,
|
||||
this parameter could be changed up to (configMAX_PRIORITIES-1).
|
||||
|
||||
config APPTRACE_DEST_TRAX
|
||||
bool
|
||||
depends on IDF_TARGET_ARCH_XTENSA && !ESP32_TRAX && !ESP32S2_TRAX && !ESP32S3_TRAX
|
||||
select ESP32_MEMMAP_TRACEMEM
|
||||
select ESP32S2_MEMMAP_TRACEMEM
|
||||
select ESP32S3_MEMMAP_TRACEMEM
|
||||
select ESP32_MEMMAP_TRACEMEM_TWOBANKS
|
||||
select ESP32S2_MEMMAP_TRACEMEM_TWOBANKS
|
||||
select ESP32S3_MEMMAP_TRACEMEM_TWOBANKS
|
||||
default n
|
||||
help
|
||||
Enables/disable TRAX tracing HW.
|
||||
|
||||
config APPTRACE_MEMBUFS_APPTRACE_PROTO_ENABLE
|
||||
bool
|
||||
default n
|
||||
help
|
||||
Enables/disable swapping memory buffers tracing protocol.
|
||||
|
||||
config APPTRACE_ENABLE
|
||||
bool
|
||||
default n
|
||||
help
|
||||
Enables/disable application tracing module.
|
||||
|
||||
config APPTRACE_LOCK_ENABLE
|
||||
bool
|
||||
default !APPTRACE_SV_ENABLE
|
||||
help
|
||||
Enables/disable application tracing module internal sync lock.
|
||||
|
||||
config APPTRACE_ONPANIC_HOST_FLUSH_TMO
|
||||
int "Timeout for flushing last trace data to host on panic"
|
||||
depends on APPTRACE_ENABLE
|
||||
range -1 5000
|
||||
default -1
|
||||
help
|
||||
Timeout for flushing last trace data to host in case of panic. In ms.
|
||||
Use -1 to disable timeout and wait forever.
|
||||
|
||||
config APPTRACE_POSTMORTEM_FLUSH_THRESH
|
||||
int "Threshold for flushing last trace data to host on panic"
|
||||
depends on APPTRACE_ENABLE
|
||||
range 0 16384
|
||||
default 0
|
||||
help
|
||||
Threshold for flushing last trace data to host on panic in post-mortem mode.
|
||||
This is minimal amount of data needed to perform flush. In bytes.
|
||||
|
||||
config APPTRACE_BUF_SIZE
|
||||
int "Size of the apptrace buffer"
|
||||
depends on APPTRACE_MEMBUFS_APPTRACE_PROTO_ENABLE && !APPTRACE_DEST_TRAX
|
||||
default 16384
|
||||
help
|
||||
Size of the memory buffer for trace data in bytes.
|
||||
|
||||
config APPTRACE_PENDING_DATA_SIZE_MAX
|
||||
int "Size of the pending data buffer"
|
||||
depends on APPTRACE_MEMBUFS_APPTRACE_PROTO_ENABLE
|
||||
default 0
|
||||
help
|
||||
Size of the buffer for events in bytes. It is useful for buffering events from
|
||||
the time critical code (scheduler, ISRs etc). If this parameter is 0 then
|
||||
events will be discarded when main HW buffer is full.
|
||||
|
||||
menu "FreeRTOS SystemView Tracing"
|
||||
depends on APPTRACE_ENABLE
|
||||
config APPTRACE_SV_ENABLE
|
||||
bool "SystemView Tracing Enable"
|
||||
depends on APPTRACE_ENABLE
|
||||
default n
|
||||
help
|
||||
Enables support for SEGGER SystemView tracing functionality.
|
||||
|
||||
choice APPTRACE_SV_DEST
|
||||
prompt "SystemView destination"
|
||||
depends on APPTRACE_SV_ENABLE
|
||||
default APPTRACE_SV_DEST_JTAG
|
||||
help
|
||||
SystemView will transfer data through the defined interface.
|
||||
|
||||
config APPTRACE_SV_DEST_JTAG
|
||||
bool "Data destination JTAG"
|
||||
depends on !PM_ENABLE && !APPTRACE_DEST_NONE
|
||||
help
|
||||
Send SEGGER SystemView events through JTAG interface.
|
||||
|
||||
config APPTRACE_SV_DEST_UART
|
||||
bool "Data destination UART"
|
||||
depends on APPTRACE_DEST_UART
|
||||
help
|
||||
Send SEGGER SystemView events through UART interface.
|
||||
|
||||
endchoice
|
||||
|
||||
choice APPTRACE_SV_CPU
|
||||
prompt "CPU to trace"
|
||||
depends on APPTRACE_SV_DEST_UART && !ESP_SYSTEM_SINGLE_CORE_MODE
|
||||
default APPTRACE_SV_DEST_CPU_0
|
||||
help
|
||||
Define the CPU to trace by SystemView.
|
||||
|
||||
config APPTRACE_SV_DEST_CPU_0
|
||||
bool "CPU0"
|
||||
help
|
||||
Send SEGGER SystemView events for Pro CPU.
|
||||
|
||||
config APPTRACE_SV_DEST_CPU_1
|
||||
bool "CPU1"
|
||||
help
|
||||
Send SEGGER SystemView events for App CPU.
|
||||
|
||||
endchoice
|
||||
|
||||
|
||||
choice APPTRACE_SV_TS_SOURCE
|
||||
prompt "Timer to use as timestamp source"
|
||||
depends on APPTRACE_SV_ENABLE
|
||||
default APPTRACE_SV_TS_SOURCE_CCOUNT if ESP_SYSTEM_SINGLE_CORE_MODE && !PM_ENABLE && !IDF_TARGET_ESP32C3
|
||||
default APPTRACE_SV_TS_SOURCE_GPTIMER if !ESP_SYSTEM_SINGLE_CORE_MODE && !PM_ENABLE && !IDF_TARGET_ESP32C3
|
||||
default APPTRACE_SV_TS_SOURCE_ESP_TIMER if PM_ENABLE || IDF_TARGET_ESP32C3
|
||||
help
|
||||
SystemView needs to use a hardware timer as the source of timestamps
|
||||
when tracing. This option selects the timer for it.
|
||||
|
||||
config APPTRACE_SV_TS_SOURCE_CCOUNT
|
||||
bool "CPU cycle counter (CCOUNT)"
|
||||
depends on ESP_SYSTEM_SINGLE_CORE_MODE && !PM_ENABLE && !IDF_TARGET_ESP32C3
|
||||
|
||||
config APPTRACE_SV_TS_SOURCE_GPTIMER
|
||||
bool "General Purpose Timer (Timer Group)"
|
||||
depends on !PM_ENABLE && !IDF_TARGET_ESP32C3
|
||||
|
||||
config APPTRACE_SV_TS_SOURCE_ESP_TIMER
|
||||
bool "esp_timer high resolution timer"
|
||||
|
||||
endchoice
|
||||
|
||||
config APPTRACE_SV_MAX_TASKS
|
||||
int "Maximum supported tasks"
|
||||
depends on APPTRACE_SV_ENABLE
|
||||
range 1 64
|
||||
default 16
|
||||
help
|
||||
Configures maximum supported tasks in sysview debug
|
||||
|
||||
config APPTRACE_SV_BUF_WAIT_TMO
|
||||
int "Trace buffer wait timeout"
|
||||
depends on APPTRACE_SV_ENABLE
|
||||
default 500
|
||||
help
|
||||
Configures timeout (in us) to wait for free space in trace buffer.
|
||||
Set to -1 to wait forever and avoid lost events.
|
||||
|
||||
config APPTRACE_SV_EVT_OVERFLOW_ENABLE
|
||||
bool "Trace Buffer Overflow Event"
|
||||
depends on APPTRACE_SV_ENABLE
|
||||
default y
|
||||
help
|
||||
Enables "Trace Buffer Overflow" event.
|
||||
|
||||
config APPTRACE_SV_EVT_ISR_ENTER_ENABLE
|
||||
bool "ISR Enter Event"
|
||||
depends on APPTRACE_SV_ENABLE
|
||||
default y
|
||||
help
|
||||
Enables "ISR Enter" event.
|
||||
|
||||
config APPTRACE_SV_EVT_ISR_EXIT_ENABLE
|
||||
bool "ISR Exit Event"
|
||||
depends on APPTRACE_SV_ENABLE
|
||||
default y
|
||||
help
|
||||
Enables "ISR Exit" event.
|
||||
|
||||
config APPTRACE_SV_EVT_ISR_TO_SCHED_ENABLE
|
||||
bool "ISR Exit to Scheduler Event"
|
||||
depends on APPTRACE_SV_ENABLE
|
||||
default y
|
||||
help
|
||||
Enables "ISR to Scheduler" event.
|
||||
|
||||
config APPTRACE_SV_EVT_TASK_START_EXEC_ENABLE
|
||||
bool "Task Start Execution Event"
|
||||
depends on APPTRACE_SV_ENABLE
|
||||
default y
|
||||
help
|
||||
Enables "Task Start Execution" event.
|
||||
|
||||
config APPTRACE_SV_EVT_TASK_STOP_EXEC_ENABLE
|
||||
bool "Task Stop Execution Event"
|
||||
depends on APPTRACE_SV_ENABLE
|
||||
default y
|
||||
help
|
||||
Enables "Task Stop Execution" event.
|
||||
|
||||
config APPTRACE_SV_EVT_TASK_START_READY_ENABLE
|
||||
bool "Task Start Ready State Event"
|
||||
depends on APPTRACE_SV_ENABLE
|
||||
default y
|
||||
help
|
||||
Enables "Task Start Ready State" event.
|
||||
|
||||
config APPTRACE_SV_EVT_TASK_STOP_READY_ENABLE
|
||||
bool "Task Stop Ready State Event"
|
||||
depends on APPTRACE_SV_ENABLE
|
||||
default y
|
||||
help
|
||||
Enables "Task Stop Ready State" event.
|
||||
|
||||
config APPTRACE_SV_EVT_TASK_CREATE_ENABLE
|
||||
bool "Task Create Event"
|
||||
depends on APPTRACE_SV_ENABLE
|
||||
default y
|
||||
help
|
||||
Enables "Task Create" event.
|
||||
|
||||
config APPTRACE_SV_EVT_TASK_TERMINATE_ENABLE
|
||||
bool "Task Terminate Event"
|
||||
depends on APPTRACE_SV_ENABLE
|
||||
default y
|
||||
help
|
||||
Enables "Task Terminate" event.
|
||||
|
||||
config APPTRACE_SV_EVT_IDLE_ENABLE
|
||||
bool "System Idle Event"
|
||||
depends on APPTRACE_SV_ENABLE
|
||||
default y
|
||||
help
|
||||
Enables "System Idle" event.
|
||||
|
||||
config APPTRACE_SV_EVT_TIMER_ENTER_ENABLE
|
||||
bool "Timer Enter Event"
|
||||
depends on APPTRACE_SV_ENABLE
|
||||
default y
|
||||
help
|
||||
Enables "Timer Enter" event.
|
||||
|
||||
config APPTRACE_SV_EVT_TIMER_EXIT_ENABLE
|
||||
bool "Timer Exit Event"
|
||||
depends on APPTRACE_SV_ENABLE
|
||||
default y
|
||||
help
|
||||
Enables "Timer Exit" event.
|
||||
|
||||
endmenu
|
||||
|
||||
config APPTRACE_GCOV_ENABLE
|
||||
bool "GCOV to Host Enable"
|
||||
depends on APPTRACE_ENABLE && !APPTRACE_SV_ENABLE
|
||||
select ESP_DEBUG_STUBS_ENABLE
|
||||
default n
|
||||
help
|
||||
Enables support for GCOV data transfer to host.
|
||||
|
||||
config APPTRACE_GCOV_DUMP_TASK_STACK_SIZE
|
||||
int "Gcov dump task stack size"
|
||||
depends on APPTRACE_GCOV_ENABLE
|
||||
default 2048
|
||||
help
|
||||
Configures stack size of Gcov dump task
|
||||
|
||||
endmenu
|
||||
@@ -1,134 +0,0 @@
|
||||
menu "Application Level Tracing"
|
||||
depends on ESP_TRACE_TRANSPORT_APPTRACE
|
||||
choice APPTRACE_DESTINATION
|
||||
prompt "Data Destination"
|
||||
default APPTRACE_DEST_JTAG if !PM_ENABLE
|
||||
default APPTRACE_DEST_UART if PM_ENABLE
|
||||
help
|
||||
Select destination for application trace: JTAG, UART, or both.
|
||||
|
||||
config APPTRACE_DEST_JTAG
|
||||
bool "JTAG"
|
||||
select APPTRACE_TRAX_ENABLE if IDF_TARGET_ARCH_XTENSA
|
||||
depends on !PM_ENABLE
|
||||
|
||||
config APPTRACE_DEST_UART
|
||||
bool "UART"
|
||||
|
||||
config APPTRACE_DEST_ALL
|
||||
bool "All (runtime selection)"
|
||||
help
|
||||
Compile both JTAG and UART interfaces in advance (higher IRAM usage).
|
||||
Allows runtime switching between JTAG and UART via esp_apptrace_get_user_params().
|
||||
|
||||
If esp_apptrace_get_user_params() is not provided by the
|
||||
application, JTAG is used by default with the default
|
||||
configuration defined in components/app_trace/include/esp_app_trace_config.h.
|
||||
endchoice
|
||||
|
||||
config APPTRACE_BUF_SIZE
|
||||
int "Size of the apptrace buffer"
|
||||
depends on APPTRACE_DEST_JTAG && !APPTRACE_TRAX_ENABLE
|
||||
default 16384
|
||||
help
|
||||
Size of the memory buffer for trace data in bytes.
|
||||
|
||||
config APPTRACE_DEST_UART_NUM
|
||||
int "UART port number"
|
||||
depends on APPTRACE_DEST_UART
|
||||
range 0 1 if (SOC_UART_HP_NUM <= 2)
|
||||
range 0 2 if (SOC_UART_HP_NUM <= 3)
|
||||
range 0 4 if (SOC_UART_HP_NUM <= 5)
|
||||
default 1
|
||||
help
|
||||
UART communication port number for the apptrace destination.
|
||||
See UART documentation for available port numbers.
|
||||
|
||||
config APPTRACE_UART_TX_GPIO
|
||||
int "UART TX on GPIO<num>"
|
||||
depends on APPTRACE_DEST_UART
|
||||
range 0 46
|
||||
default 12
|
||||
help
|
||||
This GPIO is used for UART TX pin.
|
||||
|
||||
config APPTRACE_UART_RX_GPIO
|
||||
int "UART RX on GPIO<num>"
|
||||
depends on APPTRACE_DEST_UART
|
||||
range 0 46
|
||||
default 13
|
||||
help
|
||||
This GPIO is used for UART RX pin.
|
||||
|
||||
config APPTRACE_UART_BAUDRATE
|
||||
int
|
||||
prompt "UART baud rate" if APPTRACE_DEST_UART
|
||||
depends on APPTRACE_DEST_UART
|
||||
default 1000000
|
||||
range 1200 8000000
|
||||
range 1200 1000000
|
||||
help
|
||||
This baud rate is used for UART.
|
||||
|
||||
The app's maximum baud rate depends on the UART clock source. If Power Management is disabled,
|
||||
the UART clock source is the APB clock and all baud rates in the available range will be sufficiently
|
||||
accurate. If Power Management is enabled, REF_TICK clock source is used so the baud rate is divided
|
||||
from 1MHz. Baud rates above 1Mbps are not possible and values between 500Kbps and 1Mbps may not be
|
||||
accurate.
|
||||
|
||||
config APPTRACE_UART_TX_BUFF_SIZE
|
||||
int
|
||||
prompt "UART TX ring buffer size" if APPTRACE_DEST_UART
|
||||
depends on APPTRACE_DEST_UART
|
||||
default 4096
|
||||
range 2048 32768
|
||||
help
|
||||
Size of the UART output ring buffer. Must be power of two.
|
||||
This size related to the baudrate, system tick frequency and amount of data to transfer.
|
||||
|
||||
config APPTRACE_UART_TX_MSG_SIZE
|
||||
int
|
||||
prompt "UART TX message size" if APPTRACE_DEST_UART
|
||||
depends on APPTRACE_DEST_UART
|
||||
default 128
|
||||
range 64 32768
|
||||
help
|
||||
Maximum size of the single message to transfer.
|
||||
|
||||
config APPTRACE_TRAX_ENABLE
|
||||
bool
|
||||
depends on IDF_TARGET_ARCH_XTENSA && !ESP32_TRAX && !ESP32S2_TRAX && !ESP32S3_TRAX
|
||||
select ESP32_MEMMAP_TRACEMEM
|
||||
select ESP32S2_MEMMAP_TRACEMEM
|
||||
select ESP32S3_MEMMAP_TRACEMEM
|
||||
select ESP32_MEMMAP_TRACEMEM_TWOBANKS
|
||||
select ESP32S2_MEMMAP_TRACEMEM_TWOBANKS
|
||||
select ESP32S3_MEMMAP_TRACEMEM_TWOBANKS
|
||||
default n
|
||||
help
|
||||
Enables/disable TRAX tracing HW.
|
||||
|
||||
config APPTRACE_LOCK_ENABLE
|
||||
bool "Internal Sync Lock Enable"
|
||||
default n
|
||||
help
|
||||
Enables/disable application tracing module internal sync lock to prevent data corruption
|
||||
when multiple tasks are writing to the same trace buffer.
|
||||
Keep in mind this will slow down the trace data transfer to the host.
|
||||
|
||||
config APPTRACE_ONPANIC_HOST_FLUSH_TMO
|
||||
int "Timeout for flushing last trace data to host on panic"
|
||||
range -1 5000
|
||||
default -1
|
||||
help
|
||||
Timeout for flushing last trace data to host in case of panic. In ms.
|
||||
Use -1 to disable timeout and wait forever.
|
||||
|
||||
config APPTRACE_POSTMORTEM_FLUSH_THRESH
|
||||
int "Threshold for flushing last trace data to host on panic"
|
||||
range 0 16384
|
||||
default 0
|
||||
help
|
||||
Threshold for flushing last trace data to host on panic in post-mortem mode.
|
||||
This is minimal amount of data needed to perform flush. In bytes.
|
||||
endmenu
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2017-2025 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2017-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*/
|
||||
@@ -7,14 +7,20 @@
|
||||
#include <string.h>
|
||||
#include "esp_cpu.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_rom_sys.h"
|
||||
#include "esp_app_trace.h"
|
||||
#include "esp_app_trace_port.h"
|
||||
#include "esp_app_trace_types.h"
|
||||
#include "esp_private/startup_internal.h"
|
||||
|
||||
#if CONFIG_ESP_CONSOLE_UART && CONFIG_APPTRACE_DEST_UART && (CONFIG_APPTRACE_DEST_UART_NUM == CONFIG_ESP_CONSOLE_UART_NUM)
|
||||
#error "Application trace UART and console UART cannot use the same port number"
|
||||
#ifdef CONFIG_APPTRACE_DEST_UART0
|
||||
#define ESP_APPTRACE_DEST_UART_NUM 0
|
||||
#elif CONFIG_APPTRACE_DEST_UART1
|
||||
#define ESP_APPTRACE_DEST_UART_NUM 1
|
||||
#elif CONFIG_APPTRACE_DEST_UART2
|
||||
#define ESP_APPTRACE_DEST_UART_NUM 2
|
||||
#elif CONFIG_APPTRACE_DEST_USB_CDC
|
||||
#define ESP_APPTRACE_DEST_UART_NUM 10
|
||||
#else
|
||||
#define ESP_APPTRACE_DEST_UART_NUM 0
|
||||
#endif
|
||||
|
||||
#define ESP_APPTRACE_MAX_VPRINTF_ARGS 256
|
||||
@@ -26,205 +32,263 @@ const static char *TAG = "esp_apptrace";
|
||||
typedef struct {
|
||||
esp_apptrace_hw_t *hw;
|
||||
void *hw_data;
|
||||
esp_apptrace_dest_t dest;
|
||||
} esp_apptrace_channel_t;
|
||||
|
||||
static esp_apptrace_channel_t s_trace_ch;
|
||||
static volatile int s_trace_ch_hw_initialized = 0;
|
||||
static esp_apptrace_channel_t s_trace_channels[ESP_APPTRACE_DEST_MAX];
|
||||
static bool s_inited;
|
||||
|
||||
esp_err_t esp_apptrace_init(const esp_apptrace_config_t *config)
|
||||
esp_err_t esp_apptrace_init(void)
|
||||
{
|
||||
__attribute__((unused)) void *hw_data = NULL;
|
||||
int res;
|
||||
esp_apptrace_hw_t *hw = NULL;
|
||||
void *hw_data = NULL;
|
||||
|
||||
// 'esp_apptrace_init()' is called on every core, so ensure to do main initialization only once
|
||||
if (esp_cpu_get_core_id() == 0) {
|
||||
#if CONFIG_APPTRACE_DEST_JTAG
|
||||
s_trace_ch.hw = esp_apptrace_jtag_hw_get(&hw_data);
|
||||
s_trace_ch.hw_data = hw_data;
|
||||
#elif CONFIG_APPTRACE_DEST_UART
|
||||
const esp_apptrace_uart_config_t *uart_config = &config->dest_cfg.uart;
|
||||
s_trace_ch.hw = esp_apptrace_uart_hw_get(uart_config->uart_num, &hw_data);
|
||||
s_trace_ch.hw_data = hw_data;
|
||||
#else // CONFIG_APPTRACE_DEST_ALL allows runtime selection between destinations
|
||||
if (config->dest == ESP_APPTRACE_DEST_JTAG) {
|
||||
s_trace_ch.hw = esp_apptrace_jtag_hw_get(&hw_data);
|
||||
s_trace_ch.hw_data = hw_data;
|
||||
} else if (config->dest == ESP_APPTRACE_DEST_UART) {
|
||||
const esp_apptrace_uart_config_t *uart_config = &config->dest_cfg.uart;
|
||||
s_trace_ch.hw = esp_apptrace_uart_hw_get(uart_config->uart_num, &hw_data);
|
||||
s_trace_ch.hw_data = hw_data;
|
||||
} else {
|
||||
s_trace_ch.hw = NULL;
|
||||
s_trace_ch.hw_data = NULL;
|
||||
ESP_APPTRACE_LOGE("Invalid destination type (%d)!", config->dest);
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
memset(&s_trace_channels, 0, sizeof(s_trace_channels));
|
||||
hw = esp_apptrace_jtag_hw_get(&hw_data);
|
||||
ESP_APPTRACE_LOGD("HW interface %p", hw);
|
||||
if (hw != NULL) {
|
||||
s_trace_channels[ESP_APPTRACE_DEST_JTAG].hw = hw;
|
||||
s_trace_channels[ESP_APPTRACE_DEST_JTAG].hw_data = hw_data;
|
||||
}
|
||||
hw = esp_apptrace_uart_hw_get(ESP_APPTRACE_DEST_UART_NUM, &hw_data);
|
||||
if (hw != NULL) {
|
||||
s_trace_channels[ESP_APPTRACE_DEST_UART].hw = hw;
|
||||
s_trace_channels[ESP_APPTRACE_DEST_UART].hw_data = hw_data;
|
||||
}
|
||||
s_inited = true;
|
||||
}
|
||||
|
||||
// esp_apptrace_init() is called on every core, so initialize trace channel on every core
|
||||
for (int i = 0; i < sizeof(s_trace_channels) / sizeof(s_trace_channels[0]); i++) {
|
||||
esp_apptrace_channel_t *ch = &s_trace_channels[i];
|
||||
if (ch->hw) {
|
||||
res = ch->hw->init(ch->hw_data);
|
||||
if (res != ESP_OK) {
|
||||
ESP_APPTRACE_LOGE("Failed to init trace channel HW interface (%d)!", res);
|
||||
return res;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
ESP_SYSTEM_INIT_FN(esp_apptrace_init, SECONDARY, ESP_SYSTEM_INIT_ALL_CORES, 115)
|
||||
{
|
||||
return esp_apptrace_init();
|
||||
}
|
||||
|
||||
void esp_apptrace_down_buffer_config(uint8_t *buf, uint32_t size)
|
||||
{
|
||||
esp_apptrace_channel_t *ch;
|
||||
|
||||
if (!s_inited) {
|
||||
return;
|
||||
}
|
||||
// currently down buffer is supported for JTAG interface only
|
||||
// TODO: one more argument should be added to this function to specify HW interface: JTAG, UART0 etc
|
||||
ch = &s_trace_channels[ESP_APPTRACE_DEST_JTAG];
|
||||
if (ch->hw != NULL) {
|
||||
if (ch->hw->down_buffer_config != NULL) {
|
||||
ch->hw->down_buffer_config(ch->hw_data, buf, size);
|
||||
}
|
||||
#endif
|
||||
s_trace_ch.dest = config->dest;
|
||||
s_trace_ch_hw_initialized = 1;
|
||||
} else {
|
||||
// There is NO guarantee that system init functions will execute on core 0 first
|
||||
// So we need to wait for core 0 to set up the hardware interface
|
||||
while (!s_trace_ch_hw_initialized) {
|
||||
esp_rom_delay_us(10);
|
||||
}
|
||||
ESP_APPTRACE_LOGD("Trace destination for JTAG not supported!");
|
||||
}
|
||||
|
||||
if (s_trace_ch.hw) {
|
||||
int res = s_trace_ch.hw->init(s_trace_ch.hw_data, config);
|
||||
if (res != ESP_OK) {
|
||||
ESP_APPTRACE_LOGE("Failed to init trace channel HW interface (%d)!", res);
|
||||
return res;
|
||||
ch = &s_trace_channels[ESP_APPTRACE_DEST_UART];
|
||||
if (ch->hw != NULL) {
|
||||
if (ch->hw->down_buffer_config != NULL) {
|
||||
ch->hw->down_buffer_config(ch->hw_data, buf, size);
|
||||
}
|
||||
} else {
|
||||
ESP_APPTRACE_LOGD("Trace destination for UART not supported!");
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_apptrace_down_buffer_config(uint8_t *buf, uint32_t size)
|
||||
uint8_t *esp_apptrace_down_buffer_get(esp_apptrace_dest_t dest, uint32_t *size, uint32_t user_tmo)
|
||||
{
|
||||
if (!buf || size == 0) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
if (!s_trace_ch.hw) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
if (s_trace_ch.hw->down_buffer_config) {
|
||||
s_trace_ch.hw->down_buffer_config(s_trace_ch.hw_data, buf, size);
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
uint8_t *esp_apptrace_down_buffer_get(uint32_t *size, uint32_t user_tmo)
|
||||
{
|
||||
ESP_APPTRACE_LOGV("%s(): enter", __func__);
|
||||
|
||||
if (!size || *size == 0) {
|
||||
return NULL;
|
||||
}
|
||||
if (!s_trace_ch.hw) {
|
||||
return NULL;
|
||||
}
|
||||
if (!s_trace_ch.hw->get_down_buffer) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
esp_apptrace_tmo_t tmo;
|
||||
esp_apptrace_tmo_init(&tmo, user_tmo);
|
||||
esp_apptrace_channel_t *ch;
|
||||
|
||||
return s_trace_ch.hw->get_down_buffer(s_trace_ch.hw_data, size, &tmo);
|
||||
ESP_APPTRACE_LOGV("%s(): enter", __func__);
|
||||
if (dest >= ESP_APPTRACE_DEST_MAX) {
|
||||
return NULL;
|
||||
}
|
||||
if (size == NULL || *size == 0) {
|
||||
return NULL;
|
||||
}
|
||||
if (!s_inited) {
|
||||
return NULL;
|
||||
}
|
||||
ch = &s_trace_channels[dest];
|
||||
if (ch->hw == NULL) {
|
||||
ESP_APPTRACE_LOGE("Trace destination %d not supported!", dest);
|
||||
return NULL;
|
||||
}
|
||||
if (ch->hw->get_down_buffer == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
esp_apptrace_tmo_init(&tmo, user_tmo);
|
||||
return ch->hw->get_down_buffer(ch->hw_data, size, &tmo);
|
||||
}
|
||||
|
||||
esp_err_t esp_apptrace_down_buffer_put(uint8_t *ptr, uint32_t user_tmo)
|
||||
esp_err_t esp_apptrace_down_buffer_put(esp_apptrace_dest_t dest, uint8_t *ptr, uint32_t user_tmo)
|
||||
{
|
||||
ESP_APPTRACE_LOGV("%s(): enter", __func__);
|
||||
esp_apptrace_tmo_t tmo;
|
||||
esp_apptrace_channel_t *ch;
|
||||
|
||||
if (!ptr) {
|
||||
ESP_APPTRACE_LOGV("%s(): enter", __func__);
|
||||
if (dest >= ESP_APPTRACE_DEST_MAX) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
if (!s_trace_ch.hw) {
|
||||
if (ptr == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
if (!s_inited) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
if (!s_trace_ch.hw->get_down_buffer) {
|
||||
ch = &s_trace_channels[dest];
|
||||
if (ch->hw == NULL) {
|
||||
ESP_APPTRACE_LOGE("Trace destination %d not supported!", dest);
|
||||
return ESP_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
if (ch->hw->get_down_buffer == NULL) {
|
||||
return ESP_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
esp_apptrace_tmo_t tmo;
|
||||
esp_apptrace_tmo_init(&tmo, user_tmo);
|
||||
|
||||
return s_trace_ch.hw->put_down_buffer(s_trace_ch.hw_data, ptr, &tmo);
|
||||
return ch->hw->put_down_buffer(ch->hw_data, ptr, &tmo);
|
||||
}
|
||||
|
||||
esp_err_t esp_apptrace_read(void *buf, uint32_t *size, uint32_t user_tmo)
|
||||
esp_err_t esp_apptrace_read(esp_apptrace_dest_t dest, void *buf, uint32_t *size, uint32_t user_tmo)
|
||||
{
|
||||
ESP_APPTRACE_LOGV("%s(): enter", __func__);
|
||||
int res = ESP_OK;
|
||||
esp_apptrace_tmo_t tmo;
|
||||
esp_apptrace_channel_t *ch;
|
||||
|
||||
if (!buf || !size || *size == 0) {
|
||||
ESP_APPTRACE_LOGV("%s(): enter", __func__);
|
||||
if (dest >= ESP_APPTRACE_DEST_MAX) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
if (!s_trace_ch.hw) {
|
||||
if (buf == NULL || size == NULL || *size == 0) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
if (!s_inited) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
if (!s_trace_ch.hw->get_down_buffer || !s_trace_ch.hw->put_down_buffer) {
|
||||
ch = &s_trace_channels[dest];
|
||||
if (ch->hw == NULL) {
|
||||
ESP_APPTRACE_LOGE("Trace destination %d not supported!", dest);
|
||||
return ESP_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
if (ch->hw->get_down_buffer == NULL || ch->hw->put_down_buffer == NULL) {
|
||||
return ESP_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
//TODO: callback system
|
||||
esp_apptrace_tmo_t tmo;
|
||||
esp_apptrace_tmo_init(&tmo, user_tmo);
|
||||
|
||||
uint32_t act_sz = *size;
|
||||
*size = 0;
|
||||
uint8_t *ptr = s_trace_ch.hw->get_down_buffer(s_trace_ch.hw_data, &act_sz, &tmo);
|
||||
uint8_t *ptr = ch->hw->get_down_buffer(ch->hw_data, &act_sz, &tmo);
|
||||
if (ptr && act_sz > 0) {
|
||||
ESP_APPTRACE_LOGD("Read %" PRIu32 " bytes from host", act_sz);
|
||||
memcpy(buf, ptr, act_sz);
|
||||
res = ch->hw->put_down_buffer(ch->hw_data, ptr, &tmo);
|
||||
*size = act_sz;
|
||||
return s_trace_ch.hw->put_down_buffer(s_trace_ch.hw_data, ptr, &tmo);
|
||||
} else {
|
||||
res = ESP_ERR_TIMEOUT;
|
||||
}
|
||||
|
||||
return ESP_ERR_TIMEOUT;
|
||||
return res;
|
||||
}
|
||||
|
||||
uint8_t *esp_apptrace_buffer_get(uint32_t size, uint32_t user_tmo)
|
||||
uint8_t *esp_apptrace_buffer_get(esp_apptrace_dest_t dest, uint32_t size, uint32_t user_tmo)
|
||||
{
|
||||
ESP_APPTRACE_LOGV("%s(): enter", __func__);
|
||||
esp_apptrace_tmo_t tmo;
|
||||
esp_apptrace_channel_t *ch;
|
||||
|
||||
ESP_APPTRACE_LOGV("%s(): enter", __func__);
|
||||
if (dest >= ESP_APPTRACE_DEST_MAX) {
|
||||
return NULL;
|
||||
}
|
||||
if (size == 0) {
|
||||
return NULL;
|
||||
}
|
||||
if (!s_trace_ch.hw) {
|
||||
if (!s_inited) {
|
||||
return NULL;
|
||||
}
|
||||
if (!s_trace_ch.hw->get_up_buffer) {
|
||||
ch = &s_trace_channels[dest];
|
||||
if (ch->hw == NULL) {
|
||||
ESP_APPTRACE_LOGE("Trace destination %d not supported!", dest);
|
||||
return NULL;
|
||||
}
|
||||
if (ch->hw->get_up_buffer == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
esp_apptrace_tmo_t tmo;
|
||||
esp_apptrace_tmo_init(&tmo, user_tmo);
|
||||
|
||||
return s_trace_ch.hw->get_up_buffer(s_trace_ch.hw_data, size, &tmo);
|
||||
return ch->hw->get_up_buffer(ch->hw_data, size, &tmo);
|
||||
}
|
||||
|
||||
esp_err_t esp_apptrace_buffer_put(uint8_t *ptr, uint32_t user_tmo)
|
||||
esp_err_t esp_apptrace_buffer_put(esp_apptrace_dest_t dest, uint8_t *ptr, uint32_t user_tmo)
|
||||
{
|
||||
ESP_APPTRACE_LOGV("%s(): enter", __func__);
|
||||
esp_apptrace_tmo_t tmo;
|
||||
esp_apptrace_channel_t *ch;
|
||||
|
||||
if (!ptr) {
|
||||
ESP_APPTRACE_LOGV("%s(): enter", __func__);
|
||||
if (dest >= ESP_APPTRACE_DEST_MAX) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
if (!s_trace_ch.hw) {
|
||||
if (ptr == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
if (!s_inited) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
if (!s_trace_ch.hw->put_up_buffer) {
|
||||
ch = &s_trace_channels[dest];
|
||||
if (ch->hw == NULL) {
|
||||
ESP_APPTRACE_LOGE("Trace destination %d not supported!", dest);
|
||||
return ESP_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
if (ch->hw->put_up_buffer == NULL) {
|
||||
return ESP_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
esp_apptrace_tmo_t tmo;
|
||||
esp_apptrace_tmo_init(&tmo, user_tmo);
|
||||
|
||||
return s_trace_ch.hw->put_up_buffer(s_trace_ch.hw_data, ptr, &tmo);
|
||||
return ch->hw->put_up_buffer(ch->hw_data, ptr, &tmo);
|
||||
}
|
||||
|
||||
esp_err_t esp_apptrace_write(const void *data, uint32_t size, uint32_t user_tmo)
|
||||
esp_err_t esp_apptrace_write(esp_apptrace_dest_t dest, const void *data, uint32_t size, uint32_t user_tmo)
|
||||
{
|
||||
ESP_APPTRACE_LOGV("%s(): enter", __func__);
|
||||
uint8_t *ptr = NULL;
|
||||
esp_apptrace_tmo_t tmo;
|
||||
esp_apptrace_channel_t *ch;
|
||||
|
||||
if (!data || size == 0) {
|
||||
ESP_APPTRACE_LOGV("%s(): enter", __func__);
|
||||
if (dest >= ESP_APPTRACE_DEST_MAX) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
if (!s_trace_ch.hw) {
|
||||
if (data == NULL || size == 0) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
if (!s_inited) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
if (!s_trace_ch.hw->get_up_buffer || !s_trace_ch.hw->put_up_buffer) {
|
||||
ch = &s_trace_channels[dest];
|
||||
if (ch->hw == NULL) {
|
||||
ESP_APPTRACE_LOGE("Trace destination %d not supported!", dest);
|
||||
return ESP_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
if (ch->hw->get_up_buffer == NULL || ch->hw->put_up_buffer == NULL) {
|
||||
return ESP_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
esp_apptrace_tmo_t tmo;
|
||||
esp_apptrace_tmo_init(&tmo, user_tmo);
|
||||
|
||||
uint8_t *ptr = s_trace_ch.hw->get_up_buffer(s_trace_ch.hw_data, size, &tmo);
|
||||
if (!ptr) {
|
||||
ptr = ch->hw->get_up_buffer(ch->hw_data, size, &tmo);
|
||||
if (ptr == NULL) {
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
|
||||
@@ -233,29 +297,36 @@ esp_err_t esp_apptrace_write(const void *data, uint32_t size, uint32_t user_tmo)
|
||||
memcpy(ptr, data, size);
|
||||
|
||||
// now indicate that this buffer is ready to be sent off to host
|
||||
return s_trace_ch.hw->put_up_buffer(s_trace_ch.hw_data, ptr, &tmo);
|
||||
return ch->hw->put_up_buffer(ch->hw_data, ptr, &tmo);
|
||||
}
|
||||
|
||||
int esp_apptrace_vprintf_to(uint32_t user_tmo, const char *fmt, va_list ap)
|
||||
int esp_apptrace_vprintf_to(esp_apptrace_dest_t dest, uint32_t user_tmo, const char *fmt, va_list ap)
|
||||
{
|
||||
uint16_t nargs = 0;
|
||||
uint8_t *pout, *p = (uint8_t *)fmt;
|
||||
esp_apptrace_tmo_t tmo;
|
||||
esp_apptrace_channel_t *ch;
|
||||
|
||||
ESP_APPTRACE_LOGV("%s(): enter", __func__);
|
||||
|
||||
if (!fmt) {
|
||||
if (dest >= ESP_APPTRACE_DEST_MAX) {
|
||||
return -1;
|
||||
}
|
||||
if (!s_trace_ch.hw) {
|
||||
if (fmt == NULL) {
|
||||
return -1;
|
||||
}
|
||||
if (!s_trace_ch.hw->get_up_buffer || !s_trace_ch.hw->put_up_buffer) {
|
||||
if (!s_inited) {
|
||||
return -1;
|
||||
}
|
||||
ch = &s_trace_channels[dest];
|
||||
if (ch->hw == NULL) {
|
||||
ESP_APPTRACE_LOGE("Trace destination %d not supported!", dest);
|
||||
return -1;
|
||||
}
|
||||
if (ch->hw->get_up_buffer == NULL || ch->hw->put_up_buffer == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
esp_apptrace_tmo_t tmo;
|
||||
esp_apptrace_tmo_init(&tmo, user_tmo);
|
||||
|
||||
ESP_APPTRACE_LOGD("fmt %p", fmt);
|
||||
while ((p = (uint8_t *)strchr((char *)p, '%')) && nargs < ESP_APPTRACE_MAX_VPRINTF_ARGS) {
|
||||
p++;
|
||||
@@ -268,8 +339,8 @@ int esp_apptrace_vprintf_to(uint32_t user_tmo, const char *fmt, va_list ap)
|
||||
ESP_APPTRACE_LOGE("Failed to store all printf args!");
|
||||
}
|
||||
|
||||
pout = s_trace_ch.hw->get_up_buffer(s_trace_ch.hw_data, 1 + sizeof(char *) + nargs * sizeof(uint32_t), &tmo);
|
||||
if (!pout) {
|
||||
pout = ch->hw->get_up_buffer(ch->hw_data, 1 + sizeof(char *) + nargs * sizeof(uint32_t), &tmo);
|
||||
if (pout == NULL) {
|
||||
ESP_APPTRACE_LOGE("Failed to get buffer!");
|
||||
return -1;
|
||||
}
|
||||
@@ -285,7 +356,7 @@ int esp_apptrace_vprintf_to(uint32_t user_tmo, const char *fmt, va_list ap)
|
||||
ESP_APPTRACE_LOGD("arg %" PRIx32, arg);
|
||||
}
|
||||
|
||||
int ret = s_trace_ch.hw->put_up_buffer(s_trace_ch.hw_data, p, &tmo);
|
||||
int ret = ch->hw->put_up_buffer(ch->hw_data, p, &tmo);
|
||||
if (ret != ESP_OK) {
|
||||
ESP_APPTRACE_LOGE("Failed to put printf buf (%d)!", ret);
|
||||
return -1;
|
||||
@@ -296,87 +367,85 @@ int esp_apptrace_vprintf_to(uint32_t user_tmo, const char *fmt, va_list ap)
|
||||
|
||||
int esp_apptrace_vprintf(const char *fmt, va_list ap)
|
||||
{
|
||||
return esp_apptrace_vprintf_to(0, fmt, ap);
|
||||
return esp_apptrace_vprintf_to(ESP_APPTRACE_DEST_JTAG, 0, fmt, ap);
|
||||
}
|
||||
|
||||
esp_err_t esp_apptrace_flush_nolock(uint32_t min_sz, uint32_t usr_tmo)
|
||||
esp_err_t esp_apptrace_flush_nolock(esp_apptrace_dest_t dest, uint32_t min_sz, uint32_t usr_tmo)
|
||||
{
|
||||
ESP_APPTRACE_LOGV("%s(): enter", __func__);
|
||||
esp_apptrace_tmo_t tmo;
|
||||
esp_apptrace_channel_t *ch;
|
||||
|
||||
if (!s_trace_ch.hw) {
|
||||
ESP_APPTRACE_LOGV("%s(): enter", __func__);
|
||||
if (dest >= ESP_APPTRACE_DEST_MAX) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
if (!s_inited) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
if (!s_trace_ch.hw->flush_up_buffer_nolock) {
|
||||
ch = &s_trace_channels[dest];
|
||||
if (ch->hw == NULL) {
|
||||
ESP_APPTRACE_LOGE("Trace destination %d not supported!", dest);
|
||||
return ESP_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
if (ch->hw->flush_up_buffer_nolock == NULL) {
|
||||
return ESP_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
esp_apptrace_tmo_t tmo;
|
||||
esp_apptrace_tmo_init(&tmo, usr_tmo);
|
||||
|
||||
return s_trace_ch.hw->flush_up_buffer_nolock(s_trace_ch.hw_data, min_sz, &tmo);
|
||||
return ch->hw->flush_up_buffer_nolock(ch->hw_data, min_sz, &tmo);
|
||||
}
|
||||
|
||||
esp_err_t esp_apptrace_flush(uint32_t usr_tmo)
|
||||
esp_err_t esp_apptrace_flush(esp_apptrace_dest_t dest, uint32_t usr_tmo)
|
||||
{
|
||||
ESP_APPTRACE_LOGV("%s(): enter", __func__);
|
||||
esp_apptrace_tmo_t tmo;
|
||||
esp_apptrace_channel_t *ch;
|
||||
|
||||
if (!s_trace_ch.hw) {
|
||||
ESP_APPTRACE_LOGV("%s(): enter", __func__);
|
||||
if (dest >= ESP_APPTRACE_DEST_MAX) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
if (!s_inited) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
if (!s_trace_ch.hw->flush_up_buffer) {
|
||||
ch = &s_trace_channels[dest];
|
||||
if (ch->hw == NULL) {
|
||||
ESP_APPTRACE_LOGE("Trace destination %d not supported!", dest);
|
||||
return ESP_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
if (ch->hw->flush_up_buffer == NULL) {
|
||||
return ESP_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
esp_apptrace_tmo_t tmo;
|
||||
esp_apptrace_tmo_init(&tmo, usr_tmo);
|
||||
|
||||
return s_trace_ch.hw->flush_up_buffer(s_trace_ch.hw_data, &tmo);
|
||||
return ch->hw->flush_up_buffer(ch->hw_data, &tmo);
|
||||
}
|
||||
|
||||
bool esp_apptrace_host_is_connected(void)
|
||||
bool esp_apptrace_host_is_connected(esp_apptrace_dest_t dest)
|
||||
{
|
||||
esp_apptrace_channel_t *ch;
|
||||
|
||||
ESP_APPTRACE_LOGV("%s(): enter", __func__);
|
||||
|
||||
if (!s_trace_ch.hw) {
|
||||
if (dest >= ESP_APPTRACE_DEST_MAX) {
|
||||
return false;
|
||||
}
|
||||
if (!s_trace_ch.hw->host_is_connected) {
|
||||
if (!s_inited) {
|
||||
return false;
|
||||
}
|
||||
ch = &s_trace_channels[dest];
|
||||
if (ch->hw == NULL) {
|
||||
ESP_APPTRACE_LOGE("Trace destination %d not supported!", dest);
|
||||
return false;
|
||||
}
|
||||
if (ch->hw->host_is_connected == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return s_trace_ch.hw->host_is_connected(s_trace_ch.hw_data);
|
||||
return ch->hw->host_is_connected(ch->hw_data);
|
||||
}
|
||||
|
||||
esp_apptrace_dest_t esp_apptrace_get_destination(void)
|
||||
#if !CONFIG_APPTRACE_DEST_JTAG
|
||||
esp_apptrace_hw_t *esp_apptrace_jtag_hw_get(void **data)
|
||||
{
|
||||
return s_trace_ch.dest;
|
||||
}
|
||||
|
||||
esp_err_t esp_apptrace_set_header_size(esp_apptrace_header_size_t header_size)
|
||||
{
|
||||
if (!s_trace_ch.hw) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
if (s_trace_ch.hw->set_header_size) {
|
||||
s_trace_ch.hw->set_header_size(s_trace_ch.hw_data, header_size);
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/* If any trace library (sysview or external) is selected with the apptrace transport,
|
||||
* initialization will be handled by the esp_trace component
|
||||
*/
|
||||
#if CONFIG_ESP_TRACE_LIB_NONE && CONFIG_ESP_TRACE_TRANSPORT_APPTRACE
|
||||
|
||||
esp_apptrace_config_t __attribute__((weak)) esp_apptrace_get_user_params(void)
|
||||
{
|
||||
esp_apptrace_config_t default_config = APPTRACE_CONFIG_DEFAULT();
|
||||
return default_config;
|
||||
}
|
||||
|
||||
ESP_SYSTEM_INIT_FN(apptrace_early_init, SECONDARY, ESP_SYSTEM_INIT_ALL_CORES, 115)
|
||||
{
|
||||
esp_apptrace_config_t config = esp_apptrace_get_user_params();
|
||||
return esp_apptrace_init(&config);
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -18,16 +18,13 @@
|
||||
* In this case host SW will see that wr_sz < block_sz and will report error.
|
||||
*/
|
||||
typedef struct {
|
||||
union {
|
||||
struct {
|
||||
uint8_t block_sz_8;
|
||||
uint8_t wr_sz_8;
|
||||
};
|
||||
struct {
|
||||
uint16_t block_sz_16;
|
||||
uint16_t wr_sz_16;
|
||||
};
|
||||
};
|
||||
#if CONFIG_APPTRACE_SV_ENABLE
|
||||
uint8_t block_sz; // size of allocated block for user data
|
||||
uint8_t wr_sz; // size of actually written data
|
||||
#else
|
||||
uint16_t block_sz; // size of allocated block for user data
|
||||
uint16_t wr_sz; // size of actually written data
|
||||
#endif
|
||||
} esp_tracedata_hdr_t;
|
||||
|
||||
/** TODO: docs
|
||||
@@ -36,29 +33,41 @@ typedef struct {
|
||||
uint16_t block_sz; // size of allocated block for user data
|
||||
} esp_hostdata_hdr_t;
|
||||
|
||||
#define ESP_APPTRACE_INBLOCK_MARKER(_hw_data_) \
|
||||
((_hw_data_)->state.markers[(_hw_data_)->state.in_block % 2])
|
||||
#if CONFIG_APPTRACE_SV_ENABLE
|
||||
#define ESP_APPTRACE_USR_BLOCK_CORE(_cid_) (0)
|
||||
#define ESP_APPTRACE_USR_BLOCK_LEN(_v_) (_v_)
|
||||
#define ESP_APPTRACE_USR_DATA_LEN_MAX(_hw_data_) 255UL
|
||||
#else
|
||||
#define ESP_APPTRACE_USR_BLOCK_CORE(_cid_) ((_cid_) << 15)
|
||||
#define ESP_APPTRACE_USR_BLOCK_LEN(_v_) (~(1 << 15) & (_v_))
|
||||
#define ESP_APPTRACE_USR_DATA_LEN_MAX(_hw_data_) (ESP_APPTRACE_INBLOCK(_hw_data_)->sz - sizeof(esp_tracedata_hdr_t))
|
||||
#endif
|
||||
#define ESP_APPTRACE_USR_BLOCK_RAW_SZ(_s_) ((_s_) + sizeof(esp_tracedata_hdr_t))
|
||||
|
||||
#define ESP_APPTRACE_INBLOCK(_hw_data_) \
|
||||
(&(_hw_data_)->blocks[(_hw_data_)->state.in_block % 2])
|
||||
#define ESP_APPTRACE_INBLOCK_MARKER(_hw_data_) ((_hw_data_)->state.markers[(_hw_data_)->state.in_block % 2])
|
||||
#define ESP_APPTRACE_INBLOCK_MARKER_UPD(_hw_data_, _v_) do {(_hw_data_)->state.markers[(_hw_data_)->state.in_block % 2] += (_v_);}while(0)
|
||||
#define ESP_APPTRACE_INBLOCK(_hw_data_) (&(_hw_data_)->blocks[(_hw_data_)->state.in_block % 2])
|
||||
|
||||
const static char *TAG = "esp_apptrace";
|
||||
|
||||
static uint32_t esp_apptrace_membufs_down_buffer_write_nolock(esp_apptrace_membufs_proto_data_t *proto,
|
||||
uint8_t *data, uint32_t size);
|
||||
static uint32_t esp_apptrace_membufs_down_buffer_write_nolock(esp_apptrace_membufs_proto_data_t *proto, uint8_t *data, uint32_t size);
|
||||
|
||||
esp_err_t esp_apptrace_membufs_init(esp_apptrace_membufs_proto_data_t *proto,
|
||||
const esp_apptrace_mem_block_t blocks_cfg[2])
|
||||
|
||||
esp_err_t esp_apptrace_membufs_init(esp_apptrace_membufs_proto_data_t *proto, const esp_apptrace_mem_block_t blocks_cfg[2])
|
||||
{
|
||||
// disabled by default
|
||||
esp_apptrace_rb_init(&proto->rb_down, NULL, 0);
|
||||
// membufs proto init
|
||||
for (unsigned int i = 0; i < 2; i++) {
|
||||
for (unsigned i = 0; i < 2; i++) {
|
||||
proto->blocks[i].start = blocks_cfg[i].start;
|
||||
proto->blocks[i].sz = blocks_cfg[i].sz;
|
||||
proto->state.markers[i] = 0;
|
||||
}
|
||||
proto->state.in_block = 0;
|
||||
#if CONFIG_APPTRACE_PENDING_DATA_SIZE_MAX > 0
|
||||
esp_apptrace_rb_init(&proto->rb_pend, proto->pending_data,
|
||||
sizeof(proto->pending_data));
|
||||
#endif
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
@@ -72,10 +81,10 @@ static esp_err_t esp_apptrace_membufs_swap(esp_apptrace_membufs_proto_data_t *pr
|
||||
{
|
||||
int prev_block_num = proto->state.in_block % 2;
|
||||
int new_block_num = prev_block_num ? (0) : (1);
|
||||
esp_err_t res = ESP_OK;
|
||||
|
||||
esp_err_t res = proto->hw->swap_start(proto->state.in_block);
|
||||
res = proto->hw->swap_start(proto->state.in_block);
|
||||
if (res != ESP_OK) {
|
||||
ESP_APPTRACE_LOGE("Failed to swap to new block: %d", res);
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -83,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;
|
||||
@@ -92,19 +101,40 @@ static esp_err_t esp_apptrace_membufs_swap(esp_apptrace_membufs_proto_data_t *pr
|
||||
// TODO: add support for multiple blocks from host, currently there is no need for that
|
||||
uint8_t *p = proto->blocks[new_block_num].start + proto->blocks[new_block_num].sz;
|
||||
ESP_APPTRACE_LOGD("Recvd %" PRIu16 " bytes from host (@ %p) [%x %x %x %x %x %x %x %x .. %x %x %x %x %x %x %x %x]",
|
||||
hdr->block_sz, proto->blocks[new_block_num].start,
|
||||
*(proto->blocks[new_block_num].start + 0), *(proto->blocks[new_block_num].start + 1),
|
||||
*(proto->blocks[new_block_num].start + 2), *(proto->blocks[new_block_num].start + 3),
|
||||
*(proto->blocks[new_block_num].start + 4), *(proto->blocks[new_block_num].start + 5),
|
||||
*(proto->blocks[new_block_num].start + 6), *(proto->blocks[new_block_num].start + 7),
|
||||
*(p - 8), *(p - 7), *(p - 6), *(p - 5), *(p - 4), *(p - 3), *(p - 2), *(p - 1));
|
||||
uint32_t sz = esp_apptrace_membufs_down_buffer_write_nolock(proto, (uint8_t *)(hdr + 1), hdr->block_sz);
|
||||
hdr->block_sz, proto->blocks[new_block_num].start,
|
||||
*(proto->blocks[new_block_num].start+0), *(proto->blocks[new_block_num].start+1),
|
||||
*(proto->blocks[new_block_num].start+2), *(proto->blocks[new_block_num].start+3),
|
||||
*(proto->blocks[new_block_num].start+4), *(proto->blocks[new_block_num].start+5),
|
||||
*(proto->blocks[new_block_num].start+6), *(proto->blocks[new_block_num].start+7),
|
||||
*(p-8), *(p-7), *(p-6), *(p-5), *(p-4), *(p-3), *(p-2), *(p-1));
|
||||
uint32_t sz = esp_apptrace_membufs_down_buffer_write_nolock(proto, (uint8_t *)(hdr+1), hdr->block_sz);
|
||||
if (sz != hdr->block_sz) {
|
||||
ESP_APPTRACE_LOGE("Failed to write %" PRIu32 " bytes to down buffer (%" PRIu16 " %" PRIu32 ")!",
|
||||
hdr->block_sz - sz, hdr->block_sz, sz);
|
||||
ESP_APPTRACE_LOGE("Failed to write %" PRIu32 " bytes to down buffer (%" PRIu16 " %" PRIu32 ")!", hdr->block_sz - sz, hdr->block_sz, sz);
|
||||
}
|
||||
hdr->block_sz = 0;
|
||||
}
|
||||
#if CONFIG_APPTRACE_PENDING_DATA_SIZE_MAX > 0
|
||||
// copy pending data to block if any
|
||||
while (proto->state.markers[new_block_num] < proto->blocks[new_block_num].sz) {
|
||||
uint32_t read_sz = esp_apptrace_rb_read_size_get(&proto->rb_pend);
|
||||
if (read_sz == 0) {
|
||||
break; // no more data in pending buffer
|
||||
}
|
||||
if (read_sz > proto->blocks[new_block_num].sz - proto->state.markers[new_block_num]) {
|
||||
read_sz = proto->blocks[new_block_num].sz - proto->state.markers[new_block_num];
|
||||
}
|
||||
uint8_t *ptr = esp_apptrace_rb_consume(&proto->rb_pend, read_sz);
|
||||
if (!ptr) {
|
||||
assert(false && "Failed to consume pended bytes!!");
|
||||
break;
|
||||
}
|
||||
ESP_APPTRACE_LOGD("Pump %d pend bytes [%x %x %x %x : %x %x %x %x : %x %x %x %x : %x %x...%x %x]",
|
||||
read_sz, *(ptr+0), *(ptr+1), *(ptr+2), *(ptr+3), *(ptr+4),
|
||||
*(ptr+5), *(ptr+6), *(ptr+7), *(ptr+8), *(ptr+9), *(ptr+10), *(ptr+11), *(ptr+12), *(ptr+13), *(ptr+read_sz-2), *(ptr+read_sz-1));
|
||||
memcpy(proto->blocks[new_block_num].start + proto->state.markers[new_block_num], ptr, read_sz);
|
||||
proto->state.markers[new_block_num] += read_sz;
|
||||
}
|
||||
#endif
|
||||
proto->hw->swap_end(proto->state.in_block, proto->state.markers[prev_block_num]);
|
||||
return res;
|
||||
}
|
||||
@@ -134,8 +164,7 @@ static esp_err_t esp_apptrace_membufs_swap_waitus(esp_apptrace_membufs_proto_dat
|
||||
return res;
|
||||
}
|
||||
|
||||
uint8_t *esp_apptrace_membufs_down_buffer_get(esp_apptrace_membufs_proto_data_t *proto,
|
||||
uint32_t *size, esp_apptrace_tmo_t *tmo)
|
||||
uint8_t *esp_apptrace_membufs_down_buffer_get(esp_apptrace_membufs_proto_data_t *proto, uint32_t *size, esp_apptrace_tmo_t *tmo)
|
||||
{
|
||||
uint8_t *ptr = NULL;
|
||||
|
||||
@@ -168,21 +197,19 @@ uint8_t *esp_apptrace_membufs_down_buffer_get(esp_apptrace_membufs_proto_data_t
|
||||
return ptr;
|
||||
}
|
||||
|
||||
esp_err_t esp_apptrace_membufs_down_buffer_put(esp_apptrace_membufs_proto_data_t *proto,
|
||||
uint8_t *ptr, esp_apptrace_tmo_t *tmo)
|
||||
esp_err_t esp_apptrace_membufs_down_buffer_put(esp_apptrace_membufs_proto_data_t *proto, uint8_t *ptr, esp_apptrace_tmo_t *tmo)
|
||||
{
|
||||
/* nothing todo */
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static uint32_t esp_apptrace_membufs_down_buffer_write_nolock(esp_apptrace_membufs_proto_data_t *proto,
|
||||
uint8_t *data, uint32_t size)
|
||||
static uint32_t esp_apptrace_membufs_down_buffer_write_nolock(esp_apptrace_membufs_proto_data_t *proto, uint8_t *data, uint32_t size)
|
||||
{
|
||||
uint32_t total_sz = 0;
|
||||
|
||||
while (total_sz < size) {
|
||||
ESP_APPTRACE_LOGD("esp_apptrace_trax_down_buffer_write_nolock WRS %" PRIu32 "-%" PRIu32 "-%" PRIu32 " %" PRIu32, proto->rb_down.wr, proto->rb_down.rd,
|
||||
proto->rb_down.cur_size, size);
|
||||
proto->rb_down.cur_size, size);
|
||||
uint32_t wr_sz = esp_apptrace_rb_write_size_get(&proto->rb_down);
|
||||
if (wr_sz == 0) {
|
||||
break;
|
||||
@@ -204,55 +231,126 @@ static uint32_t esp_apptrace_membufs_down_buffer_write_nolock(esp_apptrace_membu
|
||||
return total_sz;
|
||||
}
|
||||
|
||||
static inline uint32_t esp_apptrace_membufs_usr_data_len_max(esp_apptrace_membufs_proto_data_t *proto)
|
||||
static inline uint8_t *esp_apptrace_membufs_wait4buf(esp_apptrace_membufs_proto_data_t *proto, uint16_t size, esp_apptrace_tmo_t *tmo, int *pended)
|
||||
{
|
||||
return proto->header_size == ESP_APPTRACE_HEADER_SIZE_32 ?
|
||||
ESP_APPTRACE_INBLOCK(proto)->sz - ESP_APPTRACE_HEADER_SIZE_32 : 255;
|
||||
uint8_t *ptr = NULL;
|
||||
|
||||
int res = esp_apptrace_membufs_swap_waitus(proto, tmo);
|
||||
if (res != ESP_OK) {
|
||||
return NULL;
|
||||
}
|
||||
#if CONFIG_APPTRACE_PENDING_DATA_SIZE_MAX > 0
|
||||
// check if we still have pending data
|
||||
if (esp_apptrace_rb_read_size_get(&proto->rb_pend) > 0) {
|
||||
// if after block switch we still have pending data (not all pending data have been pumped to block)
|
||||
// alloc new pending buffer
|
||||
*pended = 1;
|
||||
ptr = esp_apptrace_rb_produce(&proto->rb_pend, size);
|
||||
if (!ptr) {
|
||||
ESP_APPTRACE_LOGE("Failed to alloc pend buf 1: w-r-s %d-%d-%d!", proto->rb_pend.wr, proto->rb_pend.rd, proto->rb_pend.cur_size);
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
// update block pointers
|
||||
if (ESP_APPTRACE_INBLOCK_MARKER(proto) + size > ESP_APPTRACE_INBLOCK(proto)->sz) {
|
||||
#if CONFIG_APPTRACE_PENDING_DATA_SIZE_MAX > 0
|
||||
*pended = 1;
|
||||
ptr = esp_apptrace_rb_produce(&proto->rb_pend, size);
|
||||
if (ptr == NULL) {
|
||||
ESP_APPTRACE_LOGE("Failed to alloc pend buf 2: w-r-s %d-%d-%d!", proto->rb_pend.wr, proto->rb_pend.rd, proto->rb_pend.cur_size);
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
*pended = 0;
|
||||
ptr = ESP_APPTRACE_INBLOCK(proto)->start + ESP_APPTRACE_INBLOCK_MARKER(proto);
|
||||
}
|
||||
}
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
uint8_t *esp_apptrace_membufs_up_buffer_get(esp_apptrace_membufs_proto_data_t *proto,
|
||||
uint32_t size, esp_apptrace_tmo_t *tmo)
|
||||
static inline uint8_t *esp_apptrace_membufs_pkt_start(uint8_t *ptr, uint16_t size)
|
||||
{
|
||||
if (size > esp_apptrace_membufs_usr_data_len_max(proto)) {
|
||||
// it is safe to use esp_cpu_get_core_id() in macro call because arg is used only once inside it
|
||||
((esp_tracedata_hdr_t *)ptr)->block_sz = ESP_APPTRACE_USR_BLOCK_CORE(esp_cpu_get_core_id()) | size;
|
||||
((esp_tracedata_hdr_t *)ptr)->wr_sz = 0;
|
||||
return ptr + sizeof(esp_tracedata_hdr_t);
|
||||
}
|
||||
|
||||
static inline void esp_apptrace_membufs_pkt_end(uint8_t *ptr)
|
||||
{
|
||||
esp_tracedata_hdr_t *hdr = (esp_tracedata_hdr_t *)(ptr - sizeof(esp_tracedata_hdr_t));
|
||||
// update written size
|
||||
hdr->wr_sz = hdr->block_sz;
|
||||
}
|
||||
|
||||
uint8_t *esp_apptrace_membufs_up_buffer_get(esp_apptrace_membufs_proto_data_t *proto, uint32_t size, esp_apptrace_tmo_t *tmo)
|
||||
{
|
||||
uint8_t *buf_ptr = NULL;
|
||||
|
||||
if (size > ESP_APPTRACE_USR_DATA_LEN_MAX(proto)) {
|
||||
ESP_APPTRACE_LOGE("Too large user data size %" PRIu32 "!", size);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (ESP_APPTRACE_INBLOCK_MARKER(proto) + size + proto->header_size > ESP_APPTRACE_INBLOCK(proto)->sz) {
|
||||
int res = esp_apptrace_membufs_swap_waitus(proto, tmo);
|
||||
if (res != ESP_OK) {
|
||||
return NULL;
|
||||
// check for data in the pending buffer
|
||||
#if CONFIG_APPTRACE_PENDING_DATA_SIZE_MAX > 0
|
||||
if (esp_apptrace_rb_read_size_get(&proto->rb_pend) > 0) {
|
||||
// if we have buffered data try to switch block
|
||||
esp_apptrace_membufs_swap(proto);
|
||||
// if switch was successful, part or all pended data have been copied to block
|
||||
}
|
||||
if (esp_apptrace_rb_read_size_get(&proto->rb_pend) > 0) {
|
||||
// if we have buffered data alloc new pending buffer
|
||||
ESP_APPTRACE_LOGD("Get %d bytes from PEND buffer", size);
|
||||
buf_ptr = esp_apptrace_rb_produce(&proto->rb_pend, ESP_APPTRACE_USR_BLOCK_RAW_SZ(size));
|
||||
if (buf_ptr == NULL) {
|
||||
int pended_buf;
|
||||
buf_ptr = esp_apptrace_membufs_wait4buf(proto, ESP_APPTRACE_USR_BLOCK_RAW_SZ(size), tmo, &pended_buf);
|
||||
if (buf_ptr && !pended_buf) {
|
||||
ESP_APPTRACE_LOGD("Get %d bytes from block", size);
|
||||
// update cur block marker
|
||||
ESP_APPTRACE_INBLOCK_MARKER_UPD(proto, ESP_APPTRACE_USR_BLOCK_RAW_SZ(size));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
#else
|
||||
if (1) {
|
||||
#endif
|
||||
if (ESP_APPTRACE_INBLOCK_MARKER(proto) + ESP_APPTRACE_USR_BLOCK_RAW_SZ(size) > ESP_APPTRACE_INBLOCK(proto)->sz) {
|
||||
#if CONFIG_APPTRACE_PENDING_DATA_SIZE_MAX > 0
|
||||
ESP_APPTRACE_LOGD("Block full. Get %" PRIu32 " bytes from PEND buffer", size);
|
||||
buf_ptr = esp_apptrace_rb_produce(&proto->rb_pend, ESP_APPTRACE_USR_BLOCK_RAW_SZ(size));
|
||||
#endif
|
||||
if (buf_ptr == NULL) {
|
||||
int pended_buf;
|
||||
ESP_APPTRACE_LOGD(" full. Get %" PRIu32 " bytes from pend buffer", size);
|
||||
buf_ptr = esp_apptrace_membufs_wait4buf(proto, ESP_APPTRACE_USR_BLOCK_RAW_SZ(size), tmo, &pended_buf);
|
||||
if (buf_ptr && !pended_buf) {
|
||||
ESP_APPTRACE_LOGD("Got %" PRIu32 " bytes from block", size);
|
||||
// update cur block marker
|
||||
ESP_APPTRACE_INBLOCK_MARKER_UPD(proto, ESP_APPTRACE_USR_BLOCK_RAW_SZ(size));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ESP_APPTRACE_LOGD("Get %" PRIu32 " bytes from buffer", size);
|
||||
// fit to curr nlock
|
||||
buf_ptr = ESP_APPTRACE_INBLOCK(proto)->start + ESP_APPTRACE_INBLOCK_MARKER(proto);
|
||||
// update cur block marker
|
||||
ESP_APPTRACE_INBLOCK_MARKER_UPD(proto, ESP_APPTRACE_USR_BLOCK_RAW_SZ(size));
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t *buf_ptr = ESP_APPTRACE_INBLOCK(proto)->start + ESP_APPTRACE_INBLOCK_MARKER(proto);
|
||||
// update cur block marker
|
||||
proto->state.markers[proto->state.in_block % 2] += size + proto->header_size;
|
||||
|
||||
// update header
|
||||
esp_tracedata_hdr_t *hdr = (esp_tracedata_hdr_t *)buf_ptr;
|
||||
if (proto->header_size == ESP_APPTRACE_HEADER_SIZE_32) {
|
||||
hdr->block_sz_16 = (esp_cpu_get_core_id() << 15) | size;
|
||||
hdr->wr_sz_16 = 0;
|
||||
} else {
|
||||
hdr->block_sz_8 = size;
|
||||
hdr->wr_sz_8 = 0;
|
||||
if (buf_ptr) {
|
||||
buf_ptr = esp_apptrace_membufs_pkt_start(buf_ptr, size);
|
||||
}
|
||||
ESP_APPTRACE_LOGD("Got %" PRIu32 " bytes from block", size);
|
||||
|
||||
return buf_ptr + proto->header_size;
|
||||
return buf_ptr;
|
||||
}
|
||||
|
||||
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_err_t esp_apptrace_membufs_up_buffer_put(esp_apptrace_membufs_proto_data_t *proto, uint8_t *ptr, esp_apptrace_tmo_t *tmo)
|
||||
{
|
||||
// update header
|
||||
esp_tracedata_hdr_t *hdr = (esp_tracedata_hdr_t *)(ptr - proto->header_size);
|
||||
if (proto->header_size == ESP_APPTRACE_HEADER_SIZE_32) {
|
||||
hdr->wr_sz_16 = hdr->block_sz_16;
|
||||
} else {
|
||||
hdr->wr_sz_8 = hdr->block_sz_8;
|
||||
}
|
||||
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: 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
|
||||
@@ -261,8 +359,7 @@ esp_err_t esp_apptrace_membufs_up_buffer_put(esp_apptrace_membufs_proto_data_t *
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_apptrace_membufs_flush_nolock(esp_apptrace_membufs_proto_data_t *proto,
|
||||
uint32_t min_sz, esp_apptrace_tmo_t *tmo)
|
||||
esp_err_t esp_apptrace_membufs_flush_nolock(esp_apptrace_membufs_proto_data_t *proto, uint32_t min_sz, esp_apptrace_tmo_t *tmo)
|
||||
{
|
||||
int res = ESP_OK;
|
||||
|
||||
@@ -270,16 +367,15 @@ esp_err_t esp_apptrace_membufs_flush_nolock(esp_apptrace_membufs_proto_data_t *p
|
||||
ESP_APPTRACE_LOGI("Ignore flush request for min %" PRIu32 " bytes. Bytes in block: %" PRIu32, min_sz, ESP_APPTRACE_INBLOCK_MARKER(proto));
|
||||
return ESP_OK;
|
||||
}
|
||||
// switch block while size of data is more than min size
|
||||
// switch block while size of data (including that in pending buffer) is more than min size
|
||||
while (ESP_APPTRACE_INBLOCK_MARKER(proto) > min_sz) {
|
||||
ESP_APPTRACE_LOGD("Try to flush %" PRIu32 " bytes", ESP_APPTRACE_INBLOCK_MARKER(proto));
|
||||
ESP_APPTRACE_LOGD("Try to flush %" PRIu32 " bytes. Wait until block switch for %" PRIi64 " us", ESP_APPTRACE_INBLOCK_MARKER(proto), tmo->tmo);
|
||||
res = esp_apptrace_membufs_swap_waitus(proto, tmo);
|
||||
if (res != ESP_OK) {
|
||||
if (res == ESP_ERR_TIMEOUT) {
|
||||
ESP_APPTRACE_LOGW("Failed to switch to another block in %" PRId32 " us!", (int32_t)tmo->elapsed);
|
||||
} else {
|
||||
ESP_APPTRACE_LOGE("Failed to switch to another block, res: %d", res);
|
||||
}
|
||||
if (tmo->tmo != ESP_APPTRACE_TMO_INFINITE)
|
||||
ESP_APPTRACE_LOGW("Failed to switch to another block in %lld us!", tmo->tmo);
|
||||
else
|
||||
ESP_APPTRACE_LOGE("Failed to switch to another block in %lld us!", tmo->tmo);
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2017-2025 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2017-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*/
|
||||
@@ -44,7 +44,7 @@ void esp_apptrace_log_unlock(void)
|
||||
|
||||
esp_err_t esp_apptrace_tmo_check(esp_apptrace_tmo_t *tmo)
|
||||
{
|
||||
if (tmo->tmo != (int64_t) -1) {
|
||||
if (tmo->tmo != (int64_t)-1) {
|
||||
tmo->elapsed = esp_timer_get_time() - tmo->start;
|
||||
if (tmo->elapsed >= tmo->tmo) {
|
||||
return ESP_ERR_TIMEOUT;
|
||||
@@ -57,12 +57,6 @@ esp_err_t esp_apptrace_tmo_check(esp_apptrace_tmo_t *tmo)
|
||||
///////////////////////////////// LOCK ////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void esp_apptrace_lock_init(esp_apptrace_lock_t *lock)
|
||||
{
|
||||
portMUX_INITIALIZE(&lock->mux);
|
||||
lock->int_state = 0;
|
||||
}
|
||||
|
||||
esp_err_t esp_apptrace_lock_take(esp_apptrace_lock_t *lock, esp_apptrace_tmo_t *tmo)
|
||||
{
|
||||
esp_err_t ret;
|
||||
|
||||
@@ -9,11 +9,11 @@
|
||||
//
|
||||
|
||||
#include "esp_private/startup_internal.h"
|
||||
#include "esp_dbg_stubs.h"
|
||||
#include "dbg_stubs.h"
|
||||
#include "esp_attr.h"
|
||||
|
||||
/*
|
||||
Debug stubs is actually a table of 4-byte entries. Every entry is equal to zero or must contain meaningful data.
|
||||
Debug stubs is actually a table of 4-byte entries. Every entry is equal to zero or must contain meaningfull data.
|
||||
The first entry is a service one and has the followinf format:
|
||||
- tramp_addr, 4 bytes; Address of buffer for trampoline/code. Max size is ESP_DBG_STUBS_CODE_BUF_SIZE.
|
||||
- min_stack_addr, 4 bytes; Start of the buffer for minimal onboard stack or data. Max size is ESP_DBG_STUBS_STACK_MIN_SIZE.
|
||||
|
||||
197
components/app_trace/gcov/gcov_rtio.c
Normal file
197
components/app_trace/gcov/gcov_rtio.c
Normal file
@@ -0,0 +1,197 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2017-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
// This module implements runtime file I/O API for GCOV.
|
||||
|
||||
#include <string.h>
|
||||
#include "esp_task_wdt.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/semphr.h"
|
||||
#include "soc/timer_periph.h"
|
||||
#include "esp_app_trace.h"
|
||||
#include "esp_freertos_hooks.h"
|
||||
#include "dbg_stubs.h"
|
||||
#include "esp_private/esp_ipc.h"
|
||||
#include "esp_attr.h"
|
||||
#include "hal/wdt_hal.h"
|
||||
|
||||
#if CONFIG_APPTRACE_GCOV_ENABLE
|
||||
|
||||
#define ESP_GCOV_DOWN_BUF_SIZE 4200
|
||||
|
||||
#include "esp_log.h"
|
||||
const static char *TAG = "esp_gcov_rtio";
|
||||
static volatile bool s_create_gcov_task = false;
|
||||
static volatile bool s_gcov_task_running = false;
|
||||
|
||||
extern void __gcov_dump(void);
|
||||
extern void __gcov_reset(void);
|
||||
|
||||
void gcov_dump_task(void *pvParameter)
|
||||
{
|
||||
int dump_result = 0;
|
||||
bool *running = (bool *)pvParameter;
|
||||
|
||||
ESP_EARLY_LOGV(TAG, "%s stack use in %d", __FUNCTION__, uxTaskGetStackHighWaterMark(NULL));
|
||||
|
||||
ESP_EARLY_LOGV(TAG, "Alloc apptrace down buf %d bytes", ESP_GCOV_DOWN_BUF_SIZE);
|
||||
void *down_buf = malloc(ESP_GCOV_DOWN_BUF_SIZE);
|
||||
if (down_buf == NULL) {
|
||||
ESP_EARLY_LOGE(TAG, "Could not allocate memory for the buffer");
|
||||
dump_result = ESP_ERR_NO_MEM;
|
||||
goto gcov_exit;
|
||||
}
|
||||
ESP_EARLY_LOGV(TAG, "Config apptrace down buf");
|
||||
esp_apptrace_down_buffer_config(down_buf, ESP_GCOV_DOWN_BUF_SIZE);
|
||||
ESP_EARLY_LOGV(TAG, "Dump data...");
|
||||
__gcov_dump();
|
||||
// reset dump status to allow incremental data accumulation
|
||||
__gcov_reset();
|
||||
free(down_buf);
|
||||
ESP_EARLY_LOGV(TAG, "Finish file transfer session");
|
||||
dump_result = esp_apptrace_fstop(ESP_APPTRACE_DEST_TRAX);
|
||||
if (dump_result != ESP_OK) {
|
||||
ESP_EARLY_LOGE(TAG, "Failed to send files transfer stop cmd (%d)!", dump_result);
|
||||
}
|
||||
|
||||
gcov_exit:
|
||||
ESP_EARLY_LOGV(TAG, "dump_result %d", dump_result);
|
||||
if (running) {
|
||||
*running = false;
|
||||
}
|
||||
|
||||
ESP_EARLY_LOGV(TAG, "%s stack use out %d", __FUNCTION__, uxTaskGetStackHighWaterMark(NULL));
|
||||
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
void gcov_create_task(void *arg)
|
||||
{
|
||||
ESP_EARLY_LOGV(TAG, "%s", __FUNCTION__);
|
||||
xTaskCreatePinnedToCore(&gcov_dump_task, "gcov_dump_task", CONFIG_APPTRACE_GCOV_DUMP_TASK_STACK_SIZE,
|
||||
(void *)&s_gcov_task_running, configMAX_PRIORITIES - 1, NULL, 0);
|
||||
}
|
||||
|
||||
static IRAM_ATTR
|
||||
void gcov_create_task_tick_hook(void)
|
||||
{
|
||||
if (s_create_gcov_task) {
|
||||
if (esp_ipc_call_nonblocking(xPortGetCoreID(), &gcov_create_task, NULL) == ESP_OK) {
|
||||
s_create_gcov_task = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Triggers gcov info dump task
|
||||
* This function is to be called by OpenOCD, not by normal user code.
|
||||
* TODO: what about interrupted flash access (when cache disabled)
|
||||
*
|
||||
* @return ESP_OK on success, otherwise see esp_err_t
|
||||
*/
|
||||
static int esp_dbg_stub_gcov_entry(void)
|
||||
{
|
||||
/* we are in isr context here */
|
||||
s_create_gcov_task = true;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
void gcov_rtio_init(void)
|
||||
{
|
||||
uint32_t stub_entry = 0;
|
||||
ESP_EARLY_LOGV(TAG, "%s", __FUNCTION__);
|
||||
assert(esp_dbg_stub_entry_get(ESP_DBG_STUB_ENTRY_GCOV, &stub_entry) == ESP_OK);
|
||||
if (stub_entry != 0) {
|
||||
/* "__gcov_init()" can be called several times. We must avoid multiple tick hook registration */
|
||||
return;
|
||||
}
|
||||
esp_dbg_stub_entry_set(ESP_DBG_STUB_ENTRY_GCOV, (uint32_t)&esp_dbg_stub_gcov_entry);
|
||||
assert(esp_dbg_stub_entry_get(ESP_DBG_STUB_ENTRY_CAPABILITIES, &stub_entry) == ESP_OK);
|
||||
esp_dbg_stub_entry_set(ESP_DBG_STUB_ENTRY_CAPABILITIES, stub_entry | ESP_DBG_STUB_CAP_GCOV_TASK);
|
||||
esp_register_freertos_tick_hook(gcov_create_task_tick_hook);
|
||||
}
|
||||
|
||||
void esp_gcov_dump(void)
|
||||
{
|
||||
ESP_EARLY_LOGV(TAG, "%s", __FUNCTION__);
|
||||
|
||||
while (!esp_apptrace_host_is_connected(ESP_APPTRACE_DEST_TRAX)) {
|
||||
vTaskDelay(pdMS_TO_TICKS(10));
|
||||
}
|
||||
|
||||
/* We are not in isr context here. Waiting for the completion is safe */
|
||||
s_gcov_task_running = true;
|
||||
s_create_gcov_task = true;
|
||||
while (s_gcov_task_running) {
|
||||
vTaskDelay(pdMS_TO_TICKS(10));
|
||||
}
|
||||
}
|
||||
|
||||
void *gcov_rtio_fopen(const char *path, const char *mode)
|
||||
{
|
||||
ESP_EARLY_LOGV(TAG, "%s '%s' '%s'", __FUNCTION__, path, mode);
|
||||
void *f = esp_apptrace_fopen(ESP_APPTRACE_DEST_TRAX, path, mode);
|
||||
ESP_EARLY_LOGV(TAG, "%s ret %p", __FUNCTION__, f);
|
||||
return f;
|
||||
}
|
||||
|
||||
int gcov_rtio_fclose(void *stream)
|
||||
{
|
||||
ESP_EARLY_LOGV(TAG, "%s", __FUNCTION__);
|
||||
return esp_apptrace_fclose(ESP_APPTRACE_DEST_TRAX, stream);
|
||||
}
|
||||
|
||||
size_t gcov_rtio_fread(void *ptr, size_t size, size_t nmemb, void *stream)
|
||||
{
|
||||
ESP_EARLY_LOGV(TAG, "%s read %u", __FUNCTION__, size * nmemb);
|
||||
size_t sz = esp_apptrace_fread(ESP_APPTRACE_DEST_TRAX, ptr, size, nmemb, stream);
|
||||
ESP_EARLY_LOGV(TAG, "%s actually read %u", __FUNCTION__, sz);
|
||||
return sz;
|
||||
}
|
||||
|
||||
size_t gcov_rtio_fwrite(const void *ptr, size_t size, size_t nmemb, void *stream)
|
||||
{
|
||||
ESP_EARLY_LOGV(TAG, "%s", __FUNCTION__);
|
||||
return esp_apptrace_fwrite(ESP_APPTRACE_DEST_TRAX, ptr, size, nmemb, stream);
|
||||
}
|
||||
|
||||
int gcov_rtio_fseek(void *stream, long offset, int whence)
|
||||
{
|
||||
int ret = esp_apptrace_fseek(ESP_APPTRACE_DEST_TRAX, stream, offset, whence);
|
||||
ESP_EARLY_LOGV(TAG, "%s(%p %ld %d) = %d", __FUNCTION__, stream, offset, whence, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
long gcov_rtio_ftell(void *stream)
|
||||
{
|
||||
long ret = esp_apptrace_ftell(ESP_APPTRACE_DEST_TRAX, stream);
|
||||
ESP_EARLY_LOGV(TAG, "%s(%p) = %ld", __FUNCTION__, stream, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int gcov_rtio_feof(void *stream)
|
||||
{
|
||||
int ret = esp_apptrace_feof(ESP_APPTRACE_DEST_TRAX, stream);
|
||||
ESP_EARLY_LOGV(TAG, "%s(%p) = %d", __FUNCTION__, stream, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void gcov_rtio_setbuf(void *arg1 __attribute__ ((unused)), void *arg2 __attribute__ ((unused)))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* Wrappers for Gcov functions */
|
||||
|
||||
extern void __real___gcov_init(void *info);
|
||||
void __wrap___gcov_init(void *info)
|
||||
{
|
||||
__real___gcov_init(info);
|
||||
gcov_rtio_init();
|
||||
}
|
||||
|
||||
#endif
|
||||
8
components/app_trace/gcov/io_sym.map
Normal file
8
components/app_trace/gcov/io_sym.map
Normal file
@@ -0,0 +1,8 @@
|
||||
fopen gcov_rtio_fopen
|
||||
fclose gcov_rtio_fclose
|
||||
fwrite gcov_rtio_fwrite
|
||||
fread gcov_rtio_fread
|
||||
fseek gcov_rtio_fseek
|
||||
ftell gcov_rtio_ftell
|
||||
setbuf gcov_rtio_setbuf
|
||||
feof gcov_rtio_feof
|
||||
113
components/app_trace/heap_trace_tohost.c
Normal file
113
components/app_trace/heap_trace_tohost.c
Normal file
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#include "esp_heap_trace.h"
|
||||
#include "esp_heap_caps.h"
|
||||
#if CONFIG_APPTRACE_SV_ENABLE
|
||||
#include "esp_app_trace.h"
|
||||
#include "esp_sysview_trace.h"
|
||||
#endif
|
||||
|
||||
#define STACK_DEPTH CONFIG_HEAP_TRACING_STACK_DEPTH
|
||||
|
||||
#if CONFIG_HEAP_TRACING_TOHOST
|
||||
|
||||
#if !CONFIG_APPTRACE_SV_ENABLE
|
||||
#error None of the heap tracing backends is enabled! You must enable SystemView compatible tracing to use this feature.
|
||||
#endif
|
||||
|
||||
static bool s_tracing;
|
||||
|
||||
esp_err_t heap_trace_init_tohost(void)
|
||||
{
|
||||
if (s_tracing) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t heap_trace_start(heap_trace_mode_t mode_param)
|
||||
{
|
||||
#if CONFIG_APPTRACE_SV_ENABLE
|
||||
esp_err_t ret = esp_sysview_heap_trace_start((uint32_t)-1);
|
||||
if (ret != ESP_OK) {
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
s_tracing = true;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t heap_trace_stop(void)
|
||||
{
|
||||
esp_err_t ret = ESP_ERR_NOT_SUPPORTED;
|
||||
#if CONFIG_APPTRACE_SV_ENABLE
|
||||
ret = esp_sysview_heap_trace_stop();
|
||||
#endif
|
||||
s_tracing = false;
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t heap_trace_resume(void)
|
||||
{
|
||||
return heap_trace_start(HEAP_TRACE_ALL);
|
||||
}
|
||||
|
||||
size_t heap_trace_get_count(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
esp_err_t heap_trace_get(size_t index, heap_trace_record_t *record)
|
||||
{
|
||||
return ESP_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
esp_err_t heap_trace_summary(heap_trace_summary_t *summary)
|
||||
{
|
||||
return ESP_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
void heap_trace_dump(void)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
void heap_trace_dump_caps(__attribute__((unused)) const uint32_t caps)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* Add a new allocation to the heap trace records */
|
||||
static HEAP_IRAM_ATTR void record_allocation(const heap_trace_record_t *record)
|
||||
{
|
||||
if (!s_tracing) {
|
||||
return;
|
||||
}
|
||||
#if CONFIG_APPTRACE_SV_ENABLE
|
||||
esp_sysview_heap_trace_alloc(record->address, record->size, record->alloced_by);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* record a free event in the heap trace log
|
||||
|
||||
For HEAP_TRACE_ALL, this means filling in the freed_by pointer.
|
||||
For HEAP_TRACE_LEAKS, this means removing the record from the log.
|
||||
*/
|
||||
static HEAP_IRAM_ATTR void record_free(void *p, void **callers)
|
||||
{
|
||||
if (!s_tracing) {
|
||||
return;
|
||||
}
|
||||
#if CONFIG_APPTRACE_SV_ENABLE
|
||||
esp_sysview_heap_trace_free(p, callers);
|
||||
#endif
|
||||
}
|
||||
|
||||
#include "heap_trace.inc"
|
||||
|
||||
#endif /*CONFIG_HEAP_TRACING_TOHOST*/
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2017-2025 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2017-2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -17,6 +17,8 @@
|
||||
#include <string.h>
|
||||
#include "esp_app_trace.h"
|
||||
|
||||
#if CONFIG_APPTRACE_ENABLE
|
||||
|
||||
#include "esp_log.h"
|
||||
const static char *TAG = "esp_host_file_io";
|
||||
|
||||
@@ -77,13 +79,13 @@ typedef struct {
|
||||
void *file;
|
||||
} esp_apptrace_ftell_args_t;
|
||||
|
||||
static esp_err_t esp_apptrace_file_cmd_send(uint8_t cmd, void (*prep_args)(uint8_t *, void *), void *args, uint32_t args_len)
|
||||
static esp_err_t esp_apptrace_file_cmd_send(esp_apptrace_dest_t dest, uint8_t cmd, void (*prep_args)(uint8_t *, void *), void *args, uint32_t args_len)
|
||||
{
|
||||
esp_err_t ret;
|
||||
esp_apptrace_fcmd_hdr_t *hdr;
|
||||
|
||||
ESP_EARLY_LOGV(TAG, "%s %d", __func__, cmd);
|
||||
uint8_t *ptr = esp_apptrace_buffer_get(sizeof(*hdr) + args_len, ESP_APPTRACE_TMO_INFINITE); //TODO: finite tmo
|
||||
uint8_t *ptr = esp_apptrace_buffer_get(dest, sizeof(*hdr) + args_len, ESP_APPTRACE_TMO_INFINITE); //TODO: finite tmo
|
||||
if (ptr == NULL) {
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
@@ -95,13 +97,13 @@ static esp_err_t esp_apptrace_file_cmd_send(uint8_t cmd, void (*prep_args)(uint8
|
||||
}
|
||||
|
||||
// now indicate that this buffer is ready to be sent off to host
|
||||
ret = esp_apptrace_buffer_put(ptr, ESP_APPTRACE_TMO_INFINITE);//TODO: finite tmo
|
||||
ret = esp_apptrace_buffer_put(dest, ptr, ESP_APPTRACE_TMO_INFINITE);//TODO: finite tmo
|
||||
if (ret != ESP_OK) {
|
||||
ESP_EARLY_LOGE(TAG, "Failed to put apptrace buffer (%d)!", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = esp_apptrace_flush(ESP_APPTRACE_TMO_INFINITE);//TODO: finite tmo
|
||||
ret = esp_apptrace_flush(dest, ESP_APPTRACE_TMO_INFINITE);//TODO: finite tmo
|
||||
if (ret != ESP_OK) {
|
||||
ESP_EARLY_LOGE(TAG, "Failed to flush apptrace buffer (%d)!", ret);
|
||||
return ret;
|
||||
@@ -110,12 +112,12 @@ static esp_err_t esp_apptrace_file_cmd_send(uint8_t cmd, void (*prep_args)(uint8
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t esp_apptrace_file_rsp_recv(uint8_t *buf, uint32_t buf_len)
|
||||
static esp_err_t esp_apptrace_file_rsp_recv(esp_apptrace_dest_t dest, uint8_t *buf, uint32_t buf_len)
|
||||
{
|
||||
uint32_t tot_rd = 0;
|
||||
while (tot_rd < buf_len) {
|
||||
uint32_t rd_size = buf_len - tot_rd;
|
||||
esp_err_t ret = esp_apptrace_read(buf + tot_rd, &rd_size, ESP_APPTRACE_TMO_INFINITE); //TODO: finite tmo
|
||||
esp_err_t ret = esp_apptrace_read(dest, buf + tot_rd, &rd_size, ESP_APPTRACE_TMO_INFINITE); //TODO: finite tmo
|
||||
if (ret != ESP_OK) {
|
||||
ESP_EARLY_LOGE(TAG, "Failed to read (%d)!", ret);
|
||||
return ret;
|
||||
@@ -135,7 +137,7 @@ static void esp_apptrace_fopen_args_prepare(uint8_t *buf, void *priv)
|
||||
memcpy(buf + args->path_len, args->mode, args->mode_len);
|
||||
}
|
||||
|
||||
void *esp_apptrace_fopen(const char *path, const char *mode)
|
||||
void *esp_apptrace_fopen(esp_apptrace_dest_t dest, const char *path, const char *mode)
|
||||
{
|
||||
esp_apptrace_fopen_args_t cmd_args;
|
||||
|
||||
@@ -149,8 +151,8 @@ void *esp_apptrace_fopen(const char *path, const char *mode)
|
||||
cmd_args.mode = mode;
|
||||
cmd_args.mode_len = strlen(mode) + 1;
|
||||
|
||||
esp_err_t ret = esp_apptrace_file_cmd_send(ESP_APPTRACE_FILE_CMD_FOPEN, esp_apptrace_fopen_args_prepare,
|
||||
&cmd_args, cmd_args.path_len + cmd_args.mode_len);
|
||||
esp_err_t ret = esp_apptrace_file_cmd_send(dest, ESP_APPTRACE_FILE_CMD_FOPEN, esp_apptrace_fopen_args_prepare,
|
||||
&cmd_args, cmd_args.path_len+cmd_args.mode_len);
|
||||
if (ret != ESP_OK) {
|
||||
ESP_EARLY_LOGE(TAG, "Failed to send file cmd (%d)!", ret);
|
||||
return NULL;
|
||||
@@ -158,7 +160,7 @@ void *esp_apptrace_fopen(const char *path, const char *mode)
|
||||
|
||||
// now read the answer
|
||||
void *resp;
|
||||
ret = esp_apptrace_file_rsp_recv((uint8_t *)&resp, sizeof(resp));
|
||||
ret = esp_apptrace_file_rsp_recv(dest, (uint8_t *)&resp, sizeof(resp));
|
||||
if (ret != ESP_OK) {
|
||||
ESP_EARLY_LOGE(TAG, "Failed to read response (%d)!", ret);
|
||||
return NULL;
|
||||
@@ -174,13 +176,13 @@ static void esp_apptrace_fclose_args_prepare(uint8_t *buf, void *priv)
|
||||
memcpy(buf, &args->file, sizeof(args->file));
|
||||
}
|
||||
|
||||
int esp_apptrace_fclose(void *stream)
|
||||
int esp_apptrace_fclose(esp_apptrace_dest_t dest, void *stream)
|
||||
{
|
||||
esp_apptrace_fclose_args_t cmd_args;
|
||||
|
||||
cmd_args.file = stream;
|
||||
esp_err_t ret = esp_apptrace_file_cmd_send(ESP_APPTRACE_FILE_CMD_FCLOSE, esp_apptrace_fclose_args_prepare,
|
||||
&cmd_args, sizeof(cmd_args));
|
||||
esp_err_t ret = esp_apptrace_file_cmd_send(dest, ESP_APPTRACE_FILE_CMD_FCLOSE, esp_apptrace_fclose_args_prepare,
|
||||
&cmd_args, sizeof(cmd_args));
|
||||
if (ret != ESP_OK) {
|
||||
ESP_EARLY_LOGE(TAG, "Failed to send file cmd (%d)!", ret);
|
||||
return EOF;
|
||||
@@ -188,7 +190,7 @@ int esp_apptrace_fclose(void *stream)
|
||||
|
||||
// now read the answer
|
||||
int resp;
|
||||
ret = esp_apptrace_file_rsp_recv((uint8_t *)&resp, sizeof(resp));
|
||||
ret = esp_apptrace_file_rsp_recv(dest, (uint8_t *)&resp, sizeof(resp));
|
||||
if (ret != ESP_OK) {
|
||||
ESP_EARLY_LOGE(TAG, "Failed to read response (%d)!", ret);
|
||||
return EOF;
|
||||
@@ -205,11 +207,11 @@ static void esp_apptrace_fwrite_args_prepare(uint8_t *buf, void *priv)
|
||||
memcpy(buf + sizeof(args->file), args->buf, args->size);
|
||||
}
|
||||
|
||||
size_t esp_apptrace_fwrite(const void *ptr, size_t size, size_t nmemb, void *stream)
|
||||
size_t esp_apptrace_fwrite(esp_apptrace_dest_t dest, const void *ptr, size_t size, size_t nmemb, void *stream)
|
||||
{
|
||||
esp_apptrace_fwrite_args_t cmd_args;
|
||||
|
||||
ESP_EARLY_LOGV(TAG, "esp_apptrace_fwrite f %p l %d", stream, size * nmemb);
|
||||
ESP_EARLY_LOGV(TAG, "esp_apptrace_fwrite f %p l %d", stream, size*nmemb);
|
||||
|
||||
if (ptr == NULL) {
|
||||
return 0;
|
||||
@@ -218,8 +220,8 @@ size_t esp_apptrace_fwrite(const void *ptr, size_t size, size_t nmemb, void *str
|
||||
cmd_args.buf = (void *)ptr;
|
||||
cmd_args.size = size * nmemb;
|
||||
cmd_args.file = stream;
|
||||
esp_err_t ret = esp_apptrace_file_cmd_send(ESP_APPTRACE_FILE_CMD_FWRITE, esp_apptrace_fwrite_args_prepare,
|
||||
&cmd_args, sizeof(cmd_args.file) + cmd_args.size);
|
||||
esp_err_t ret = esp_apptrace_file_cmd_send(dest, ESP_APPTRACE_FILE_CMD_FWRITE, esp_apptrace_fwrite_args_prepare,
|
||||
&cmd_args, sizeof(cmd_args.file)+cmd_args.size);
|
||||
if (ret != ESP_OK) {
|
||||
ESP_EARLY_LOGE(TAG, "Failed to send file cmd (%d)!", ret);
|
||||
return 0;
|
||||
@@ -227,7 +229,7 @@ size_t esp_apptrace_fwrite(const void *ptr, size_t size, size_t nmemb, void *str
|
||||
|
||||
// now read the answer
|
||||
size_t resp;
|
||||
ret = esp_apptrace_file_rsp_recv((uint8_t *)&resp, sizeof(resp));
|
||||
ret = esp_apptrace_file_rsp_recv(dest, (uint8_t *)&resp, sizeof(resp));
|
||||
if (ret != ESP_OK) {
|
||||
ESP_EARLY_LOGE(TAG, "Failed to read response (%d)!", ret);
|
||||
return 0;
|
||||
@@ -247,11 +249,11 @@ static void esp_apptrace_fread_args_prepare(uint8_t *buf, void *priv)
|
||||
memcpy(buf + sizeof(args->file), &args->size, sizeof(args->size));
|
||||
}
|
||||
|
||||
size_t esp_apptrace_fread(void *ptr, size_t size, size_t nmemb, void *stream)
|
||||
size_t esp_apptrace_fread(esp_apptrace_dest_t dest, void *ptr, size_t size, size_t nmemb, void *stream)
|
||||
{
|
||||
esp_apptrace_fread_args_t cmd_args;
|
||||
|
||||
ESP_EARLY_LOGV(TAG, "esp_apptrace_fread f %p l %d", stream, size * nmemb);
|
||||
ESP_EARLY_LOGV(TAG, "esp_apptrace_fread f %p l %d", stream, size*nmemb);
|
||||
|
||||
if (ptr == NULL) {
|
||||
return 0;
|
||||
@@ -259,8 +261,8 @@ size_t esp_apptrace_fread(void *ptr, size_t size, size_t nmemb, void *stream)
|
||||
|
||||
cmd_args.size = size * nmemb;
|
||||
cmd_args.file = stream;
|
||||
esp_err_t ret = esp_apptrace_file_cmd_send(ESP_APPTRACE_FILE_CMD_FREAD, esp_apptrace_fread_args_prepare,
|
||||
&cmd_args, sizeof(cmd_args));
|
||||
esp_err_t ret = esp_apptrace_file_cmd_send(dest, ESP_APPTRACE_FILE_CMD_FREAD, esp_apptrace_fread_args_prepare,
|
||||
&cmd_args, sizeof(cmd_args));
|
||||
if (ret != ESP_OK) {
|
||||
ESP_EARLY_LOGE(TAG, "Failed to send file cmd (%d)!", ret);
|
||||
return 0;
|
||||
@@ -268,7 +270,7 @@ size_t esp_apptrace_fread(void *ptr, size_t size, size_t nmemb, void *stream)
|
||||
|
||||
// now read the answer
|
||||
size_t resp;
|
||||
ret = esp_apptrace_file_rsp_recv((uint8_t *)&resp, sizeof(resp));
|
||||
ret = esp_apptrace_file_rsp_recv(dest, (uint8_t *)&resp, sizeof(resp));
|
||||
if (ret != ESP_OK) {
|
||||
ESP_EARLY_LOGE(TAG, "Failed to read response (%d)!", ret);
|
||||
return 0;
|
||||
@@ -277,7 +279,7 @@ size_t esp_apptrace_fread(void *ptr, size_t size, size_t nmemb, void *stream)
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = esp_apptrace_file_rsp_recv(ptr, resp);
|
||||
ret = esp_apptrace_file_rsp_recv(dest, ptr, resp);
|
||||
if (ret != ESP_OK) {
|
||||
ESP_EARLY_LOGE(TAG, "Failed to read file data (%d)!", ret);
|
||||
return 0;
|
||||
@@ -286,7 +288,7 @@ size_t esp_apptrace_fread(void *ptr, size_t size, size_t nmemb, void *stream)
|
||||
* fread(buf, 1 ,size, file);
|
||||
* So, total read bytes count returns
|
||||
*/
|
||||
return resp / size; // return the number of items read
|
||||
return resp/size; // return the number of items read
|
||||
}
|
||||
|
||||
static void esp_apptrace_fseek_args_prepare(uint8_t *buf, void *priv)
|
||||
@@ -298,7 +300,7 @@ static void esp_apptrace_fseek_args_prepare(uint8_t *buf, void *priv)
|
||||
memcpy(buf + sizeof(args->file) + sizeof(args->offset), &args->whence, sizeof(args->whence));
|
||||
}
|
||||
|
||||
int esp_apptrace_fseek(void *stream, long offset, int whence)
|
||||
int esp_apptrace_fseek(esp_apptrace_dest_t dest, void *stream, long offset, int whence)
|
||||
{
|
||||
esp_apptrace_fseek_args_t cmd_args;
|
||||
|
||||
@@ -307,8 +309,8 @@ int esp_apptrace_fseek(void *stream, long offset, int whence)
|
||||
cmd_args.file = stream;
|
||||
cmd_args.offset = offset;
|
||||
cmd_args.whence = whence;
|
||||
esp_err_t ret = esp_apptrace_file_cmd_send(ESP_APPTRACE_FILE_CMD_FSEEK, esp_apptrace_fseek_args_prepare,
|
||||
&cmd_args, sizeof(cmd_args));
|
||||
esp_err_t ret = esp_apptrace_file_cmd_send(dest, ESP_APPTRACE_FILE_CMD_FSEEK, esp_apptrace_fseek_args_prepare,
|
||||
&cmd_args, sizeof(cmd_args));
|
||||
if (ret != ESP_OK) {
|
||||
ESP_EARLY_LOGE(TAG, "Failed to send file cmd (%d)!", ret);
|
||||
return -1;
|
||||
@@ -316,7 +318,7 @@ int esp_apptrace_fseek(void *stream, long offset, int whence)
|
||||
|
||||
// now read the answer
|
||||
int resp;
|
||||
ret = esp_apptrace_file_rsp_recv((uint8_t *)&resp, sizeof(resp));
|
||||
ret = esp_apptrace_file_rsp_recv(dest, (uint8_t *)&resp, sizeof(resp));
|
||||
if (ret != ESP_OK) {
|
||||
ESP_EARLY_LOGE(TAG, "Failed to read response (%d)!", ret);
|
||||
return -1;
|
||||
@@ -332,13 +334,13 @@ static void esp_apptrace_ftell_args_prepare(uint8_t *buf, void *priv)
|
||||
memcpy(buf, &args->file, sizeof(args->file));
|
||||
}
|
||||
|
||||
int esp_apptrace_ftell(void *stream)
|
||||
int esp_apptrace_ftell(esp_apptrace_dest_t dest, void *stream)
|
||||
{
|
||||
esp_apptrace_ftell_args_t cmd_args;
|
||||
|
||||
cmd_args.file = stream;
|
||||
esp_err_t ret = esp_apptrace_file_cmd_send(ESP_APPTRACE_FILE_CMD_FTELL, esp_apptrace_ftell_args_prepare,
|
||||
&cmd_args, sizeof(cmd_args));
|
||||
esp_err_t ret = esp_apptrace_file_cmd_send(dest, ESP_APPTRACE_FILE_CMD_FTELL, esp_apptrace_ftell_args_prepare,
|
||||
&cmd_args, sizeof(cmd_args));
|
||||
if (ret != ESP_OK) {
|
||||
ESP_EARLY_LOGE(TAG, "Failed to send file cmd (%d)!", ret);
|
||||
return -1;
|
||||
@@ -346,7 +348,7 @@ int esp_apptrace_ftell(void *stream)
|
||||
|
||||
// now read the answer
|
||||
int resp;
|
||||
ret = esp_apptrace_file_rsp_recv((uint8_t *)&resp, sizeof(resp));
|
||||
ret = esp_apptrace_file_rsp_recv(dest, (uint8_t *)&resp, sizeof(resp));
|
||||
if (ret != ESP_OK) {
|
||||
ESP_EARLY_LOGE(TAG, "Failed to read response (%d)!", ret);
|
||||
return -1;
|
||||
@@ -355,10 +357,10 @@ int esp_apptrace_ftell(void *stream)
|
||||
return resp;
|
||||
}
|
||||
|
||||
int esp_apptrace_fstop(void)
|
||||
int esp_apptrace_fstop(esp_apptrace_dest_t dest)
|
||||
{
|
||||
ESP_EARLY_LOGV(TAG, "%s", __func__);
|
||||
esp_err_t ret = esp_apptrace_file_cmd_send(ESP_APPTRACE_FILE_CMD_STOP, NULL, NULL, 0);
|
||||
esp_err_t ret = esp_apptrace_file_cmd_send(dest, ESP_APPTRACE_FILE_CMD_STOP, NULL, NULL, 0);
|
||||
if (ret != ESP_OK) {
|
||||
ESP_EARLY_LOGE(TAG, "Failed to send files transfer stop cmd (%d)!", ret);
|
||||
}
|
||||
@@ -372,13 +374,13 @@ static void esp_apptrace_feof_args_prepare(uint8_t *buf, void *priv)
|
||||
memcpy(buf, &args->file, sizeof(args->file));
|
||||
}
|
||||
|
||||
int esp_apptrace_feof(void *stream)
|
||||
int esp_apptrace_feof(esp_apptrace_dest_t dest, void *stream)
|
||||
{
|
||||
esp_apptrace_feof_args_t cmd_args;
|
||||
|
||||
cmd_args.file = stream;
|
||||
esp_err_t ret = esp_apptrace_file_cmd_send(ESP_APPTRACE_FILE_CMD_FEOF, esp_apptrace_feof_args_prepare,
|
||||
&cmd_args, sizeof(cmd_args));
|
||||
esp_err_t ret = esp_apptrace_file_cmd_send(dest, ESP_APPTRACE_FILE_CMD_FEOF, esp_apptrace_feof_args_prepare,
|
||||
&cmd_args, sizeof(cmd_args));
|
||||
if (ret != ESP_OK) {
|
||||
ESP_EARLY_LOGE(TAG, "Failed to send file cmd (%d)!", ret);
|
||||
return EOF;
|
||||
@@ -386,7 +388,7 @@ int esp_apptrace_feof(void *stream)
|
||||
|
||||
// now read the answer
|
||||
int resp;
|
||||
ret = esp_apptrace_file_rsp_recv((uint8_t *)&resp, sizeof(resp));
|
||||
ret = esp_apptrace_file_rsp_recv(dest, (uint8_t *)&resp, sizeof(resp));
|
||||
if (ret != ESP_OK) {
|
||||
ESP_EARLY_LOGE(TAG, "Failed to read response (%d)!", ret);
|
||||
return EOF;
|
||||
@@ -394,3 +396,5 @@ int esp_apptrace_feof(void *stream)
|
||||
|
||||
return resp;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2017-2025 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2017-2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -8,7 +8,6 @@
|
||||
|
||||
#include <stdarg.h>
|
||||
#include "esp_err.h"
|
||||
#include "esp_app_trace_config.h"
|
||||
#include "esp_app_trace_util.h" // ESP_APPTRACE_TMO_INFINITE
|
||||
|
||||
#ifdef __cplusplus
|
||||
@@ -16,70 +15,82 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Initializes application tracing module for the selected destination and configuration.
|
||||
* Application trace data destinations bits.
|
||||
*/
|
||||
typedef enum {
|
||||
ESP_APPTRACE_DEST_JTAG = 1, ///< JTAG destination
|
||||
ESP_APPTRACE_DEST_TRAX = ESP_APPTRACE_DEST_JTAG, ///< xxx_TRAX name is obsolete, use more common xxx_JTAG
|
||||
ESP_APPTRACE_DEST_UART, ///< UART destination
|
||||
ESP_APPTRACE_DEST_MAX = ESP_APPTRACE_DEST_UART+1,
|
||||
ESP_APPTRACE_DEST_NUM
|
||||
} esp_apptrace_dest_t;
|
||||
|
||||
/**
|
||||
* @brief Initializes application tracing module.
|
||||
*
|
||||
* @note Should be called before any esp_apptrace_xxx call.
|
||||
*
|
||||
* @return ESP_OK on success, otherwise see esp_err_t
|
||||
*/
|
||||
esp_err_t esp_apptrace_init(const esp_apptrace_config_t *config);
|
||||
esp_err_t esp_apptrace_init(void);
|
||||
|
||||
/**
|
||||
* @brief Configures down buffer.
|
||||
*
|
||||
* @note Needs to be called before attempting to receive any data using esp_apptrace_down_buffer_get and
|
||||
* esp_apptrace_read. This function does not protect internal data by lock.
|
||||
* @note Needs to be called before attempting to receive any data using esp_apptrace_down_buffer_get and esp_apptrace_read.
|
||||
* This function does not protect internal data by lock.
|
||||
*
|
||||
* @param buf Address of buffer to use for down channel (host to target) data.
|
||||
* @param size Size of the buffer.
|
||||
*
|
||||
* @return ESP_OK on success, otherwise see esp_err_t
|
||||
*/
|
||||
esp_err_t esp_apptrace_down_buffer_config(uint8_t *buf, uint32_t size);
|
||||
void esp_apptrace_down_buffer_config(uint8_t *buf, uint32_t size);
|
||||
|
||||
/**
|
||||
* @brief Allocates buffer for trace data.
|
||||
* Once the data in the buffer is ready to be sent, esp_apptrace_buffer_put must be called to indicate it.
|
||||
*
|
||||
* @param dest Indicates HW interface to send data.
|
||||
* @param size Size of data to write to trace buffer.
|
||||
* @param tmo Timeout for operation (in us). Use ESP_APPTRACE_TMO_INFINITE to wait indefinitely.
|
||||
*
|
||||
* @return non-NULL on success, otherwise NULL.
|
||||
*/
|
||||
uint8_t *esp_apptrace_buffer_get(uint32_t size, uint32_t tmo);
|
||||
uint8_t *esp_apptrace_buffer_get(esp_apptrace_dest_t dest, uint32_t size, uint32_t tmo);
|
||||
|
||||
/**
|
||||
* @brief Indicates that the data in the buffer is ready to be sent.
|
||||
* This function is a counterpart of and must be preceded by esp_apptrace_buffer_get.
|
||||
*
|
||||
* @param dest Indicates HW interface to send data. Should be identical to the same parameter in call to esp_apptrace_buffer_get.
|
||||
* @param ptr Address of trace buffer to release. Should be the value returned by call to esp_apptrace_buffer_get.
|
||||
* @param tmo Timeout for operation (in us). Use ESP_APPTRACE_TMO_INFINITE to wait indefinitely.
|
||||
*
|
||||
* @return ESP_OK on success, otherwise see esp_err_t
|
||||
*/
|
||||
esp_err_t esp_apptrace_buffer_put(uint8_t *ptr, uint32_t tmo);
|
||||
esp_err_t esp_apptrace_buffer_put(esp_apptrace_dest_t dest, uint8_t *ptr, uint32_t tmo);
|
||||
|
||||
/**
|
||||
* @brief Writes data to trace buffer.
|
||||
*
|
||||
* @param dest Indicates HW interface to send data.
|
||||
* @param data Address of data to write to trace buffer.
|
||||
* @param size Size of data to write to trace buffer.
|
||||
* @param tmo Timeout for operation (in us). Use ESP_APPTRACE_TMO_INFINITE to wait indefinitely.
|
||||
*
|
||||
* @return ESP_OK on success, otherwise see esp_err_t
|
||||
*/
|
||||
esp_err_t esp_apptrace_write(const void *data, uint32_t size, uint32_t tmo);
|
||||
esp_err_t esp_apptrace_write(esp_apptrace_dest_t dest, const void *data, uint32_t size, uint32_t tmo);
|
||||
|
||||
/**
|
||||
* @brief vprintf-like function to send log messages to host via specified HW interface.
|
||||
*
|
||||
* @param dest Indicates HW interface to send data.
|
||||
* @param tmo Timeout for operation (in us). Use ESP_APPTRACE_TMO_INFINITE to wait indefinitely.
|
||||
* @param fmt Address of format string.
|
||||
* @param ap List of arguments.
|
||||
*
|
||||
* @return Number of bytes written.
|
||||
*/
|
||||
int esp_apptrace_vprintf_to(uint32_t tmo, const char *fmt, va_list ap);
|
||||
int esp_apptrace_vprintf_to(esp_apptrace_dest_t dest, uint32_t tmo, const char *fmt, va_list ap);
|
||||
|
||||
/**
|
||||
* @brief vprintf-like function to send log messages to host.
|
||||
@@ -94,198 +105,172 @@ int esp_apptrace_vprintf(const char *fmt, va_list ap);
|
||||
/**
|
||||
* @brief Flushes remaining data in trace buffer to host.
|
||||
*
|
||||
* @param dest Indicates HW interface to flush data on.
|
||||
* @param tmo Timeout for operation (in us). Use ESP_APPTRACE_TMO_INFINITE to wait indefinitely.
|
||||
*
|
||||
* @return ESP_OK on success, otherwise see esp_err_t
|
||||
*/
|
||||
esp_err_t esp_apptrace_flush(uint32_t tmo);
|
||||
esp_err_t esp_apptrace_flush(esp_apptrace_dest_t dest, uint32_t tmo);
|
||||
|
||||
/**
|
||||
* @brief Flushes remaining data in trace buffer to host without locking internal data.
|
||||
* This is a special version of esp_apptrace_flush which should be called from panic handler.
|
||||
*
|
||||
* @param min_sz Threshold for flushing data. If current filling level is above this value, data will be flushed. JTAG destinations only.
|
||||
* @param dest Indicates HW interface to flush data on.
|
||||
* @param min_sz Threshold for flushing data. If current filling level is above this value, data will be flushed. TRAX destinations only.
|
||||
* @param tmo Timeout for operation (in us). Use ESP_APPTRACE_TMO_INFINITE to wait indefinitely.
|
||||
*
|
||||
* @return ESP_OK on success, otherwise see esp_err_t
|
||||
*/
|
||||
esp_err_t esp_apptrace_flush_nolock(uint32_t min_sz, uint32_t tmo);
|
||||
esp_err_t esp_apptrace_flush_nolock(esp_apptrace_dest_t dest, uint32_t min_sz, uint32_t tmo);
|
||||
|
||||
/**
|
||||
* @brief Reads host data from trace buffer.
|
||||
*
|
||||
* @param dest Indicates HW interface to read the data on.
|
||||
* @param data Address of buffer to put data from trace buffer.
|
||||
* @param size Pointer to store size of read data. Before call to this function pointed memory must hold requested size of data
|
||||
* @param tmo Timeout for operation (in us). Use ESP_APPTRACE_TMO_INFINITE to wait indefinitely.
|
||||
*
|
||||
* @return ESP_OK on success, otherwise see esp_err_t
|
||||
*/
|
||||
esp_err_t esp_apptrace_read(void *data, uint32_t *size, uint32_t tmo);
|
||||
esp_err_t esp_apptrace_read(esp_apptrace_dest_t dest, void *data, uint32_t *size, uint32_t tmo);
|
||||
|
||||
/**
|
||||
* @brief Retrieves incoming data buffer if any.
|
||||
* Once data in the buffer is processed, esp_apptrace_down_buffer_put must be called to indicate it.
|
||||
*
|
||||
* @param dest Indicates HW interface to receive data.
|
||||
* @param size Address to store size of available data in down buffer. Must be initialized with requested value.
|
||||
* @param tmo Timeout for operation (in us). Use ESP_APPTRACE_TMO_INFINITE to wait indefinitely.
|
||||
*
|
||||
* @return non-NULL on success, otherwise NULL.
|
||||
*/
|
||||
uint8_t *esp_apptrace_down_buffer_get(uint32_t *size, uint32_t tmo);
|
||||
uint8_t *esp_apptrace_down_buffer_get(esp_apptrace_dest_t dest, uint32_t *size, uint32_t tmo);
|
||||
|
||||
/**
|
||||
* @brief Indicates that the data in the down buffer is processed.
|
||||
* This function is a counterpart of and must be preceded by esp_apptrace_down_buffer_get.
|
||||
*
|
||||
* @param dest Indicates HW interface to receive data. Should be identical to the same parameter in call to esp_apptrace_down_buffer_get.
|
||||
* @param ptr Address of trace buffer to release. Should be the value returned by call to esp_apptrace_down_buffer_get.
|
||||
* @param tmo Timeout for operation (in us). Use ESP_APPTRACE_TMO_INFINITE to wait indefinitely.
|
||||
*
|
||||
* @return ESP_OK on success, otherwise see esp_err_t
|
||||
*/
|
||||
esp_err_t esp_apptrace_down_buffer_put(uint8_t *ptr, uint32_t tmo);
|
||||
esp_err_t esp_apptrace_down_buffer_put(esp_apptrace_dest_t dest, uint8_t *ptr, uint32_t tmo);
|
||||
|
||||
/**
|
||||
* @brief Checks whether host is connected.
|
||||
*
|
||||
* @param dest Indicates HW interface to use.
|
||||
*
|
||||
* @return true if host is connected, otherwise false
|
||||
*/
|
||||
bool esp_apptrace_host_is_connected(void);
|
||||
|
||||
/**
|
||||
* @brief Gets the destination of the application trace.
|
||||
*
|
||||
* @return The destination of the application trace.
|
||||
*/
|
||||
esp_apptrace_dest_t esp_apptrace_get_destination(void);
|
||||
|
||||
/**
|
||||
* @brief Sets the header size of the application trace packet.
|
||||
*
|
||||
* @param header_size The header size to set.
|
||||
*
|
||||
* @return ESP_OK on success, otherwise see esp_err_t
|
||||
*/
|
||||
esp_err_t esp_apptrace_set_header_size(esp_apptrace_header_size_t header_size);
|
||||
bool esp_apptrace_host_is_connected(esp_apptrace_dest_t dest);
|
||||
|
||||
/**
|
||||
* @brief Opens file on host.
|
||||
* This function has the same semantic as 'fopen' except for the first argument.
|
||||
* This function has the same semantic as 'fopen' except for the first argument.
|
||||
*
|
||||
* @param dest Indicates HW interface to use.
|
||||
* @param path Path to file.
|
||||
* @param mode Mode string. See fopen for details.
|
||||
*
|
||||
* @return non zero file handle on success, otherwise 0
|
||||
*/
|
||||
void *esp_apptrace_fopen(const char *path, const char *mode);
|
||||
void *esp_apptrace_fopen(esp_apptrace_dest_t dest, const char *path, const char *mode);
|
||||
|
||||
/**
|
||||
* @brief Closes file on host.
|
||||
* This function has the same semantic as 'fclose' except for the first argument.
|
||||
* This function has the same semantic as 'fclose' except for the first argument.
|
||||
*
|
||||
* @param dest Indicates HW interface to use.
|
||||
* @param stream File handle returned by esp_apptrace_fopen.
|
||||
*
|
||||
* @return Zero on success, otherwise non-zero. See fclose for details.
|
||||
*/
|
||||
int esp_apptrace_fclose(void *stream);
|
||||
int esp_apptrace_fclose(esp_apptrace_dest_t dest, void *stream);
|
||||
|
||||
/**
|
||||
* @brief Writes to file on host.
|
||||
* This function has the same semantic as 'fwrite' except for the first argument.
|
||||
* This function has the same semantic as 'fwrite' except for the first argument.
|
||||
*
|
||||
* @param ptr Address of data to write.
|
||||
* @param size Size of an item.
|
||||
* @param dest Indicates HW interface to use.
|
||||
* @param ptr Address of data to write.
|
||||
* @param size Size of an item.
|
||||
* @param nmemb Number of items to write.
|
||||
* @param stream File handle returned by esp_apptrace_fopen.
|
||||
*
|
||||
* @return Number of written items. See fwrite for details.
|
||||
*/
|
||||
size_t esp_apptrace_fwrite(const void *ptr, size_t size, size_t nmemb, void *stream);
|
||||
size_t esp_apptrace_fwrite(esp_apptrace_dest_t dest, const void *ptr, size_t size, size_t nmemb, void *stream);
|
||||
|
||||
/**
|
||||
* @brief Read file on host.
|
||||
* This function has the same semantic as 'fread' except for the first argument.
|
||||
* This function has the same semantic as 'fread' except for the first argument.
|
||||
*
|
||||
* @param ptr Address to store read data.
|
||||
* @param size Size of an item.
|
||||
* @param dest Indicates HW interface to use.
|
||||
* @param ptr Address to store read data.
|
||||
* @param size Size of an item.
|
||||
* @param nmemb Number of items to read.
|
||||
* @param stream File handle returned by esp_apptrace_fopen.
|
||||
*
|
||||
* @return Number of read items. See fread for details.
|
||||
*/
|
||||
size_t esp_apptrace_fread(void *ptr, size_t size, size_t nmemb, void *stream);
|
||||
size_t esp_apptrace_fread(esp_apptrace_dest_t dest, void *ptr, size_t size, size_t nmemb, void *stream);
|
||||
|
||||
/**
|
||||
* @brief Set position indicator in file on host.
|
||||
* This function has the same semantic as 'fseek' except for the first argument.
|
||||
* This function has the same semantic as 'fseek' except for the first argument.
|
||||
*
|
||||
* @param dest Indicates HW interface to use.
|
||||
* @param stream File handle returned by esp_apptrace_fopen.
|
||||
* @param offset Offset. See fseek for details.
|
||||
* @param whence Position in file. See fseek for details.
|
||||
*
|
||||
* @return Zero on success, otherwise non-zero. See fseek for details.
|
||||
*/
|
||||
int esp_apptrace_fseek(void *stream, long offset, int whence);
|
||||
int esp_apptrace_fseek(esp_apptrace_dest_t dest, void *stream, long offset, int whence);
|
||||
|
||||
/**
|
||||
* @brief Get current position indicator for file on host.
|
||||
* This function has the same semantic as 'ftell' except for the first argument.
|
||||
* This function has the same semantic as 'ftell' except for the first argument.
|
||||
*
|
||||
* @param dest Indicates HW interface to use.
|
||||
* @param stream File handle returned by esp_apptrace_fopen.
|
||||
*
|
||||
* @return Current position in file. See ftell for details.
|
||||
*/
|
||||
int esp_apptrace_ftell(void *stream);
|
||||
int esp_apptrace_ftell(esp_apptrace_dest_t dest, void *stream);
|
||||
|
||||
/**
|
||||
* @brief Indicates to the host that all file operations are complete.
|
||||
* This function should be called after all file operations are finished and
|
||||
* indicate to the host that it can perform cleanup operations (close open files etc.).
|
||||
* This function should be called after all file operations are finished and
|
||||
* indicate to the host that it can perform cleanup operations (close open files etc.).
|
||||
*
|
||||
* @param dest Indicates HW interface to use.
|
||||
*
|
||||
* @return ESP_OK on success, otherwise see esp_err_t
|
||||
*/
|
||||
int esp_apptrace_fstop(void);
|
||||
int esp_apptrace_fstop(esp_apptrace_dest_t dest);
|
||||
|
||||
/**
|
||||
* @brief Test end-of-file indicator on a stream.
|
||||
* This function has the same semantic as 'feof' except for the first argument.
|
||||
* This function has the same semantic as 'feof' except for the first argument.
|
||||
*
|
||||
* @param dest Indicates HW interface to use.
|
||||
* @param stream File handle returned by esp_apptrace_fopen.
|
||||
*
|
||||
* @return Non-Zero if end-of-file indicator is set for stream. See feof for details.
|
||||
*/
|
||||
int esp_apptrace_feof(void *stream);
|
||||
int esp_apptrace_feof(esp_apptrace_dest_t dest, void *stream);
|
||||
|
||||
#if !CONFIG_APPTRACE_DEST_UART // JTAG or NONE
|
||||
#define APPTRACE_JTAG_CONFIG_DEFAULT() { \
|
||||
.dest = ESP_APPTRACE_DEST_JTAG, \
|
||||
.dest_cfg.jtag = {0}, \
|
||||
.flush_tmo = CONFIG_APPTRACE_ONPANIC_HOST_FLUSH_TMO, \
|
||||
.flush_thresh = CONFIG_APPTRACE_POSTMORTEM_FLUSH_THRESH, \
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !CONFIG_APPTRACE_DEST_JTAG // UART or NONE
|
||||
#define APPTRACE_UART_CONFIG_DEFAULT() { \
|
||||
.dest = ESP_APPTRACE_DEST_UART, \
|
||||
.dest_cfg.uart = { \
|
||||
.uart_num = CONFIG_APPTRACE_DEST_UART_NUM, \
|
||||
.tx_pin_num = CONFIG_APPTRACE_UART_TX_GPIO, \
|
||||
.rx_pin_num = CONFIG_APPTRACE_UART_RX_GPIO, \
|
||||
.baud_rate = CONFIG_APPTRACE_UART_BAUDRATE, \
|
||||
.tx_buff_size = CONFIG_APPTRACE_UART_TX_BUFF_SIZE, \
|
||||
.tx_msg_size = CONFIG_APPTRACE_UART_TX_MSG_SIZE, \
|
||||
}, \
|
||||
.flush_tmo = CONFIG_APPTRACE_ONPANIC_HOST_FLUSH_TMO, \
|
||||
.flush_thresh = CONFIG_APPTRACE_POSTMORTEM_FLUSH_THRESH, \
|
||||
}
|
||||
#endif
|
||||
|
||||
// Default picks JTAG if available, otherwise UART
|
||||
#if !CONFIG_APPTRACE_DEST_UART
|
||||
#define APPTRACE_CONFIG_DEFAULT() APPTRACE_JTAG_CONFIG_DEFAULT()
|
||||
#else
|
||||
#define APPTRACE_CONFIG_DEFAULT() APPTRACE_UART_CONFIG_DEFAULT()
|
||||
#endif
|
||||
/**
|
||||
* @brief Triggers gcov info dump.
|
||||
* This function waits for the host to connect to target before dumping data.
|
||||
*/
|
||||
void esp_gcov_dump(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -1,51 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#ifndef ESP_APP_TRACE_CONFIG_H_
|
||||
#define ESP_APP_TRACE_CONFIG_H_
|
||||
|
||||
#include "sdkconfig.h"
|
||||
|
||||
/* Default configurations for runtime selection (APPTRACE_DEST_ALL)
|
||||
* These values are used when building with both JTAG and UART enabled
|
||||
* to allow runtime selection. You can switch between destinations
|
||||
* via esp_apptrace_get_user_params(). If this function is
|
||||
* not provided by the application, JTAG is used by default with the
|
||||
* configuration defined below. See esp_app_trace.h for details.
|
||||
*/
|
||||
|
||||
#if !defined(CONFIG_APPTRACE_UART_TX_GPIO) || !defined(CONFIG_APPTRACE_UART_RX_GPIO)
|
||||
#include "soc/uart_pins.h"
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_APPTRACE_BUF_SIZE
|
||||
#define CONFIG_APPTRACE_BUF_SIZE 16384
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_APPTRACE_UART_TX_BUFF_SIZE
|
||||
#define CONFIG_APPTRACE_UART_TX_BUFF_SIZE 4096
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_APPTRACE_UART_TX_MSG_SIZE
|
||||
#define CONFIG_APPTRACE_UART_TX_MSG_SIZE 128
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_APPTRACE_UART_BAUDRATE
|
||||
#define CONFIG_APPTRACE_UART_BAUDRATE 1000000
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_APPTRACE_UART_TX_GPIO
|
||||
#define CONFIG_APPTRACE_UART_TX_GPIO U1TXD_GPIO_NUM
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_APPTRACE_UART_RX_GPIO
|
||||
#define CONFIG_APPTRACE_UART_RX_GPIO U1RXD_GPIO_NUM
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_APPTRACE_DEST_UART_NUM
|
||||
#define CONFIG_APPTRACE_DEST_UART_NUM 1
|
||||
#endif
|
||||
|
||||
#endif /* ESP_APP_TRACE_CONFIG_H_ */
|
||||
@@ -1,95 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#ifndef ESP_APP_TRACE_TYPES_H_
|
||||
#define ESP_APP_TRACE_TYPES_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include "spinlock.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** Structure which holds data necessary for measuring time intervals.
|
||||
*
|
||||
* After initialization via esp_apptrace_tmo_init() user needs to call esp_apptrace_tmo_check()
|
||||
* periodically to check timeout for expiration.
|
||||
*/
|
||||
typedef struct {
|
||||
int64_t start; ///< time interval start (in us)
|
||||
int64_t tmo; ///< timeout value (in us)
|
||||
int64_t elapsed; ///< elapsed time (in us)
|
||||
} esp_apptrace_tmo_t;
|
||||
|
||||
/** Tracing module synchronization lock */
|
||||
typedef struct {
|
||||
spinlock_t mux;
|
||||
unsigned int int_state;
|
||||
} esp_apptrace_lock_t;
|
||||
|
||||
/** Ring buffer control structure.
|
||||
*
|
||||
* @note For purposes of application tracing module if there is no enough space for user data and write pointer can be wrapped
|
||||
* current ring buffer size can be temporarily shrunk in order to provide buffer with requested size.
|
||||
*/
|
||||
typedef struct {
|
||||
uint8_t *data; ///< pointer to data storage
|
||||
volatile uint32_t size; ///< size of data storage
|
||||
volatile uint32_t cur_size; ///< current size of data storage
|
||||
volatile uint32_t rd; ///< read pointer
|
||||
volatile uint32_t wr; ///< write pointer
|
||||
} esp_apptrace_rb_t;
|
||||
|
||||
/**
|
||||
* Application trace data destinations
|
||||
*/
|
||||
typedef enum {
|
||||
ESP_APPTRACE_DEST_JTAG,
|
||||
ESP_APPTRACE_DEST_UART,
|
||||
} esp_apptrace_dest_t;
|
||||
|
||||
/**
|
||||
* Application trace configuration for UART destination
|
||||
*/
|
||||
typedef struct {
|
||||
int uart_num; ///< Port number
|
||||
int tx_pin_num; ///< TX pin number
|
||||
int rx_pin_num; ///< RX pin number
|
||||
int baud_rate; ///< Baud rate
|
||||
uint32_t tx_buff_size; ///< TX ring buffer size
|
||||
uint32_t tx_msg_size; ///< Maximum size of the single message to transfer.
|
||||
} esp_apptrace_uart_config_t;
|
||||
|
||||
/**
|
||||
* Application trace trace header size in bytes. It is 2 bytes for SEGGER SystemView
|
||||
*/
|
||||
typedef enum {
|
||||
ESP_APPTRACE_HEADER_SIZE_16 = 2,
|
||||
ESP_APPTRACE_HEADER_SIZE_32 = 4,
|
||||
} esp_apptrace_header_size_t;
|
||||
|
||||
/**
|
||||
* Application trace configuration
|
||||
*/
|
||||
typedef struct {
|
||||
esp_apptrace_dest_t dest; ///< Destination type (JTAG or UART)
|
||||
|
||||
union {
|
||||
esp_apptrace_uart_config_t uart; ///< UART configuration (when dest is ESP_APPTRACE_DEST_UART)
|
||||
struct { ///< Reserved for JTAG (when dest is ESP_APPTRACE_DEST_JTAG)
|
||||
uint8_t _unused;
|
||||
} jtag;
|
||||
} dest_cfg; ///< Destination-specific configuration
|
||||
|
||||
uint32_t flush_tmo; ///< Flush timeout in milliseconds
|
||||
uint32_t flush_thresh; ///< Flush threshold in bytes
|
||||
} esp_apptrace_config_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ESP_APP_TRACE_TYPES_H_ */
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2017-2025 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2017-2021 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -10,23 +10,34 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "esp_err.h"
|
||||
#include "esp_timer.h"
|
||||
#include "esp_app_trace_types.h"
|
||||
|
||||
/** Infinite waiting timeout */
|
||||
#define ESP_APPTRACE_TMO_INFINITE ((uint32_t)-1)
|
||||
|
||||
/** Structure which holds data necessary for measuring time intervals.
|
||||
*
|
||||
* After initialization via esp_apptrace_tmo_init() user needs to call esp_apptrace_tmo_check()
|
||||
* periodically to check timeout for expiration.
|
||||
*/
|
||||
typedef struct {
|
||||
int64_t start; ///< time interval start (in us)
|
||||
int64_t tmo; ///< timeout value (in us)
|
||||
int64_t elapsed; ///< elapsed time (in us)
|
||||
} esp_apptrace_tmo_t;
|
||||
|
||||
/**
|
||||
* @brief Initializes timeout structure.
|
||||
*
|
||||
* @param tmo Pointer to timeout structure to be initialized.
|
||||
* @param user_tmo Timeout value (in us). Use ESP_APPTRACE_TMO_INFINITE to wait indefinitely.
|
||||
* @param user_tmo Timeout value (in us). Use ESP_APPTRACE_TMO_INFINITE to wait indefinetly.
|
||||
*/
|
||||
static inline void esp_apptrace_tmo_init(esp_apptrace_tmo_t *tmo, uint32_t user_tmo)
|
||||
{
|
||||
tmo->start = esp_timer_get_time();
|
||||
tmo->tmo = user_tmo == ESP_APPTRACE_TMO_INFINITE ? (int64_t) -1 : (int64_t)user_tmo;
|
||||
tmo->tmo = user_tmo == ESP_APPTRACE_TMO_INFINITE ? (int64_t)-1 : (int64_t)user_tmo;
|
||||
tmo->elapsed = 0;
|
||||
}
|
||||
|
||||
@@ -41,15 +52,25 @@ esp_err_t esp_apptrace_tmo_check(esp_apptrace_tmo_t *tmo);
|
||||
|
||||
static inline uint32_t esp_apptrace_tmo_remaining_us(esp_apptrace_tmo_t *tmo)
|
||||
{
|
||||
return tmo->tmo != (int64_t) -1 ? (tmo->elapsed - tmo->tmo) : ESP_APPTRACE_TMO_INFINITE;
|
||||
return tmo->tmo != (int64_t)-1 ? (tmo->elapsed - tmo->tmo) : ESP_APPTRACE_TMO_INFINITE;
|
||||
}
|
||||
|
||||
/** Tracing module synchronization lock */
|
||||
typedef struct {
|
||||
spinlock_t mux;
|
||||
unsigned int_state;
|
||||
} esp_apptrace_lock_t;
|
||||
|
||||
/**
|
||||
* @brief Initializes lock structure.
|
||||
*
|
||||
* @param lock Pointer to lock structure to be initialized.
|
||||
*/
|
||||
void esp_apptrace_lock_init(esp_apptrace_lock_t *lock);
|
||||
static inline void esp_apptrace_lock_init(esp_apptrace_lock_t *lock)
|
||||
{
|
||||
portMUX_INITIALIZE(&lock->mux);
|
||||
lock->int_state = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Tries to acquire lock in specified time period.
|
||||
@@ -70,6 +91,19 @@ esp_err_t esp_apptrace_lock_take(esp_apptrace_lock_t *lock, esp_apptrace_tmo_t *
|
||||
*/
|
||||
esp_err_t esp_apptrace_lock_give(esp_apptrace_lock_t *lock);
|
||||
|
||||
/** Ring buffer control structure.
|
||||
*
|
||||
* @note For purposes of application tracing module if there is no enough space for user data and write pointer can be wrapped
|
||||
* current ring buffer size can be temporarily shrinked in order to provide buffer with requested size.
|
||||
*/
|
||||
typedef struct {
|
||||
uint8_t *data; ///< pointer to data storage
|
||||
volatile uint32_t size; ///< size of data storage
|
||||
volatile uint32_t cur_size; ///< current size of data storage
|
||||
volatile uint32_t rd; ///< read pointer
|
||||
volatile uint32_t wr; ///< write pointer
|
||||
} esp_apptrace_rb_t;
|
||||
|
||||
/**
|
||||
* @brief Initializes ring buffer control structure.
|
||||
*
|
||||
|
||||
@@ -1,69 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2017-2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef ESP_DBG_STUBS_H_
|
||||
#define ESP_DBG_STUBS_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "esp_err.h"
|
||||
|
||||
/**
|
||||
* Debug stubs entries IDs
|
||||
*/
|
||||
typedef enum {
|
||||
ESP_DBG_STUB_MAGIC_NUM,
|
||||
ESP_DBG_STUB_TABLE_SIZE,
|
||||
ESP_DBG_STUB_CONTROL_DATA, ///< stubs descriptor entry
|
||||
ESP_DBG_STUB_ENTRY_FIRST,
|
||||
ESP_DBG_STUB_ENTRY_GCOV ///< GCOV entry
|
||||
= ESP_DBG_STUB_ENTRY_FIRST,
|
||||
ESP_DBG_STUB_ENTRY_CAPABILITIES,
|
||||
ESP_DBG_STUB_ENTRY_MAX
|
||||
} esp_dbg_stub_id_t;
|
||||
|
||||
#define ESP_DBG_STUB_MAGIC_NUM_VAL 0xFEEDBEEF
|
||||
#define ESP_DBG_STUB_CAP_GCOV_TASK (1 << 0)
|
||||
|
||||
/**
|
||||
* @brief Initializes debug stubs.
|
||||
*
|
||||
* @note Must be called after esp_apptrace_init() if app tracing is enabled.
|
||||
*/
|
||||
void esp_dbg_stubs_init(void);
|
||||
|
||||
/**
|
||||
* @brief Initializes application tracing module.
|
||||
*
|
||||
* @note Should be called before any esp_apptrace_xxx call.
|
||||
*
|
||||
* @param id Stub ID.
|
||||
* @param entry Stub entry. Usually it is stub entry function address,
|
||||
* but can be any value meaningful for OpenOCD command/code
|
||||
* such as capabilities
|
||||
* @return ESP_OK on success, otherwise see esp_err_t
|
||||
*/
|
||||
esp_err_t esp_dbg_stub_entry_set(esp_dbg_stub_id_t id, uint32_t entry);
|
||||
|
||||
/**
|
||||
* @brief Retrieves the corresponding stub entry
|
||||
*
|
||||
* @param id Stub ID.
|
||||
* @param entry Stub entry. Usually it is stub entry function address,
|
||||
* but can be any value meaningful for OpenOCD command/code
|
||||
* such as capabilities
|
||||
*
|
||||
* @return ESP_OK on success, otherwise see esp_err_t
|
||||
*/
|
||||
esp_err_t esp_dbg_stub_entry_get(esp_dbg_stub_id_t id, uint32_t *entry);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // ESP_DBG_STUBS_H_
|
||||
80
components/app_trace/include/esp_sysview_trace.h
Normal file
80
components/app_trace/include/esp_sysview_trace.h
Normal file
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2018-2021 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#ifndef ESP_SYSVIEW_TRACE_H_
|
||||
#define ESP_SYSVIEW_TRACE_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdarg.h>
|
||||
#include "esp_err.h"
|
||||
#include "SEGGER_RTT.h" // SEGGER_RTT_ESP_Flush
|
||||
#include "esp_app_trace_util.h" // ESP_APPTRACE_TMO_INFINITE
|
||||
|
||||
/**
|
||||
* @brief Flushes remaining data in SystemView trace buffer to host.
|
||||
*
|
||||
* @param tmo Timeout for operation (in us). Use ESP_APPTRACE_TMO_INFINITE to wait indefinetly.
|
||||
*
|
||||
* @return ESP_OK.
|
||||
*/
|
||||
static inline esp_err_t esp_sysview_flush(uint32_t tmo)
|
||||
{
|
||||
SEGGER_RTT_ESP_Flush(0, tmo);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief vprintf-like function to sent log messages to the host.
|
||||
*
|
||||
* @param format Address of format string.
|
||||
* @param args List of arguments.
|
||||
*
|
||||
* @return Number of bytes written.
|
||||
*/
|
||||
int esp_sysview_vprintf(const char * format, va_list args);
|
||||
|
||||
/**
|
||||
* @brief Starts SystemView heap tracing.
|
||||
*
|
||||
* @param tmo Timeout (in us) to wait for the host to be connected. Use -1 to wait forever.
|
||||
*
|
||||
* @return ESP_OK on success, ESP_ERR_TIMEOUT if operation has been timed out.
|
||||
*/
|
||||
esp_err_t esp_sysview_heap_trace_start(uint32_t tmo);
|
||||
|
||||
/**
|
||||
* @brief Stops SystemView heap tracing.
|
||||
*
|
||||
* @return ESP_OK.
|
||||
*/
|
||||
esp_err_t esp_sysview_heap_trace_stop(void);
|
||||
|
||||
/**
|
||||
* @brief Sends heap allocation event to the host.
|
||||
*
|
||||
* @param addr Address of allocated block.
|
||||
* @param size Size of allocated block.
|
||||
* @param callers Pointer to array with callstack addresses.
|
||||
* Array size must be CONFIG_HEAP_TRACING_STACK_DEPTH.
|
||||
*/
|
||||
void esp_sysview_heap_trace_alloc(void *addr, uint32_t size, const void *callers);
|
||||
|
||||
/**
|
||||
* @brief Sends heap de-allocation event to the host.
|
||||
*
|
||||
* @param addr Address of de-allocated block.
|
||||
* @param callers Pointer to array with callstack addresses.
|
||||
* Array size must be CONFIG_HEAP_TRACING_STACK_DEPTH.
|
||||
*/
|
||||
void esp_sysview_heap_trace_free(void *addr, const void *callers);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif //ESP_SYSVIEW_TRACE_H_
|
||||
@@ -1,11 +1,23 @@
|
||||
[mapping:app_trace]
|
||||
archive: libapp_trace.a
|
||||
entries:
|
||||
if ESP_TRACE_TRANSPORT_APPTRACE = y:
|
||||
app_trace (noflash)
|
||||
app_trace_util (noflash)
|
||||
if APPTRACE_DEST_JTAG = y || APPTRACE_DEST_ALL = y:
|
||||
port_jtag (noflash)
|
||||
app_trace_membufs_proto (noflash)
|
||||
if APPTRACE_DEST_UART = y || APPTRACE_DEST_ALL = y:
|
||||
port_uart (noflash)
|
||||
app_trace (noflash)
|
||||
port_uart (noflash)
|
||||
app_trace_util (noflash)
|
||||
if APPTRACE_MEMBUFS_APPTRACE_PROTO_ENABLE:
|
||||
app_trace_membufs_proto (noflash)
|
||||
if APPTRACE_DEST_JTAG = y:
|
||||
port (noflash)
|
||||
if APPTRACE_SV_ENABLE = y:
|
||||
SEGGER_SYSVIEW (noflash)
|
||||
SEGGER_RTT_esp (noflash)
|
||||
SEGGER_SYSVIEW_Config_FreeRTOS (noflash)
|
||||
SEGGER_SYSVIEW_FreeRTOS (noflash)
|
||||
|
||||
[mapping:app_trace_driver]
|
||||
archive: libesp_driver_gptimer.a
|
||||
entries:
|
||||
if APPTRACE_SV_TS_SOURCE_GPTIMER = y:
|
||||
gptimer: gptimer_get_raw_count (noflash)
|
||||
else:
|
||||
* (default)
|
||||
|
||||
@@ -15,7 +15,7 @@ extern "C" {
|
||||
|
||||
/** Apptrace HW interface. */
|
||||
typedef struct {
|
||||
esp_err_t (*init)(void *hw_data, const esp_apptrace_config_t *config);
|
||||
esp_err_t (*init)(void *hw_data);
|
||||
uint8_t *(*get_up_buffer)(void *hw_data, uint32_t, esp_apptrace_tmo_t *);
|
||||
esp_err_t (*put_up_buffer)(void *hw_data, uint8_t *, esp_apptrace_tmo_t *);
|
||||
esp_err_t (*flush_up_buffer_nolock)(void *hw_data, uint32_t, esp_apptrace_tmo_t *);
|
||||
@@ -24,7 +24,6 @@ typedef struct {
|
||||
uint8_t *(*get_down_buffer)(void *hw_data, uint32_t *, esp_apptrace_tmo_t *);
|
||||
esp_err_t (*put_down_buffer)(void *hw_data, uint8_t *, esp_apptrace_tmo_t *);
|
||||
bool (*host_is_connected)(void *hw_data);
|
||||
void (*set_header_size)(void *hw_data, esp_apptrace_header_size_t header_size);
|
||||
} esp_apptrace_hw_t;
|
||||
|
||||
esp_apptrace_hw_t *esp_apptrace_jtag_hw_get(void **data);
|
||||
|
||||
@@ -1,126 +1,93 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2017-2025 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2017-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
#include "esp_err.h"
|
||||
|
||||
#include "soc/soc.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_cpu.h"
|
||||
#include "esp_attr.h"
|
||||
#include "esp_private/uart_share_hw_ctrl.h"
|
||||
#include "hal/uart_hal.h"
|
||||
#include "hal/gpio_hal.h"
|
||||
#include "driver/uart.h"
|
||||
#include "soc/uart_periph.h"
|
||||
#include "esp_clk_tree.h"
|
||||
#include "esp_private/esp_clk_tree_common.h"
|
||||
#include "soc/gpio_periph.h"
|
||||
#include "esp_rom_gpio.h"
|
||||
#include "hal/uart_ll.h"
|
||||
#include "esp_intr_alloc.h"
|
||||
#include "esp_heap_caps.h"
|
||||
#include "esp_private/esp_gpio_reserve.h"
|
||||
|
||||
#include "esp_app_trace_port.h"
|
||||
#include "esp_app_trace_util.h"
|
||||
#include "esp_app_trace_types.h"
|
||||
|
||||
static const char *TAG = "esp_apptrace_uart";
|
||||
#include "driver/uart.h"
|
||||
#include "hal/uart_ll.h"
|
||||
#include "string.h"
|
||||
#include "driver/gpio.h"
|
||||
|
||||
#ifndef MIN
|
||||
#define MIN(a, b) ((a) < (b) ? (a) : (b))
|
||||
#endif
|
||||
|
||||
#define APPTRACE_DEST_UART (CONFIG_APPTRACE_DEST_UART0 | CONFIG_APPTRACE_DEST_UART1 | CONFIG_APPTRACE_DEST_UART2)
|
||||
|
||||
#define APP_TRACE_MAX_TX_BUFF_UART CONFIG_APPTRACE_UART_TX_BUFF_SIZE
|
||||
#define APP_TRACE_MAX_TX_MSG_UART CONFIG_APPTRACE_UART_TX_MSG_SIZE
|
||||
|
||||
/** UART HW transport data */
|
||||
typedef struct {
|
||||
uint8_t *buffer; ///< Ring buffer data
|
||||
uint32_t max_size; ///< Ring buffer maximum size (must be power of 2)
|
||||
volatile uint32_t count; ///< Number of bytes currently in the buffer
|
||||
volatile uint32_t head; ///< Write pointer index
|
||||
volatile uint32_t tail; ///< Read pointer index
|
||||
} esp_apptrace_uart_rb_t;
|
||||
|
||||
typedef struct {
|
||||
int inited;
|
||||
volatile bool tx_busy; ///< TX busy flag
|
||||
uart_hal_context_t hal_ctx; ///< UART HAL context
|
||||
esp_apptrace_uart_rb_t tx_ring; ///< TX ring buffer
|
||||
intr_handle_t intr_handle; ///< Interrupt handle
|
||||
|
||||
/* TX message buffer */
|
||||
uint8_t *tx_msg_buff; ///< TX message buffer to provide with get_up_buffer
|
||||
uint32_t tx_msg_buff_size; ///< TX message buffer size & maximum size of the single message to transfer.
|
||||
uint32_t tx_pending_msg_size; ///< Pending message size to send with put_up_buffer
|
||||
|
||||
/* RX message buffer */
|
||||
uint8_t *rx_msg_buff; ///< RX message buffer provided with down_buffer_config function
|
||||
uint32_t rx_msg_buff_size; ///< RX message buffer size provided with down_buffer_config function
|
||||
|
||||
uint8_t inited;
|
||||
#if CONFIG_APPTRACE_LOCK_ENABLE
|
||||
esp_apptrace_lock_t lock; ///< Sync lock
|
||||
esp_apptrace_lock_t lock; // sync lock
|
||||
#endif
|
||||
uart_port_t port_num;
|
||||
// TX data ring buffer
|
||||
uint8_t *tx_data_buff;
|
||||
int32_t tx_data_buff_in;
|
||||
int32_t tx_data_buff_out;
|
||||
// TX message buffer
|
||||
uint8_t *tx_msg_buff;
|
||||
uint32_t tx_msg_buff_size;
|
||||
|
||||
// RX message buffer
|
||||
uint8_t *down_buffer;
|
||||
uint32_t down_buffer_size;
|
||||
// Buffer overflow flags
|
||||
bool message_buff_overflow;
|
||||
bool circular_buff_overflow;
|
||||
} esp_apptrace_uart_data_t;
|
||||
|
||||
static inline bool is_power_of_two(uint32_t n)
|
||||
#if APPTRACE_DEST_UART
|
||||
static esp_err_t esp_apptrace_uart_init(esp_apptrace_uart_data_t *hw_data);
|
||||
static esp_err_t esp_apptrace_uart_flush(esp_apptrace_uart_data_t *hw_data, esp_apptrace_tmo_t *tmo);
|
||||
static esp_err_t esp_apptrace_uart_flush_nolock(esp_apptrace_uart_data_t *hw_data, uint32_t min_sz, esp_apptrace_tmo_t *tmo);
|
||||
static uint8_t *esp_apptrace_uart_up_buffer_get(esp_apptrace_uart_data_t *hw_data, uint32_t size, esp_apptrace_tmo_t *tmo);
|
||||
static esp_err_t esp_apptrace_uart_up_buffer_put(esp_apptrace_uart_data_t *hw_data, uint8_t *ptr, esp_apptrace_tmo_t *tmo);
|
||||
static void esp_apptrace_uart_down_buffer_config(esp_apptrace_uart_data_t *hw_data, uint8_t *buf, uint32_t size);
|
||||
static uint8_t *esp_apptrace_uart_down_buffer_get(esp_apptrace_uart_data_t *hw_data, uint32_t *size, esp_apptrace_tmo_t *tmo);
|
||||
static esp_err_t esp_apptrace_uart_down_buffer_put(esp_apptrace_uart_data_t *hw_data, uint8_t *ptr, esp_apptrace_tmo_t *tmo);
|
||||
static bool esp_apptrace_uart_host_is_connected(esp_apptrace_uart_data_t *hw_data);
|
||||
|
||||
#endif // APPTRACE_DEST_UART
|
||||
const static char *TAG = "esp_apptrace_uart";
|
||||
|
||||
esp_apptrace_hw_t *esp_apptrace_uart_hw_get(int num, void **data)
|
||||
{
|
||||
return n != 0 && (n & (n - 1)) == 0;
|
||||
ESP_LOGD(TAG,"esp_apptrace_uart_hw_get - %i", num);
|
||||
#if APPTRACE_DEST_UART
|
||||
static esp_apptrace_uart_data_t s_uart_hw_data = {
|
||||
};
|
||||
static esp_apptrace_hw_t s_uart_hw = {
|
||||
.init = (esp_err_t (*)(void *))esp_apptrace_uart_init,
|
||||
.get_up_buffer = (uint8_t *(*)(void *, uint32_t, esp_apptrace_tmo_t *))esp_apptrace_uart_up_buffer_get,
|
||||
.put_up_buffer = (esp_err_t (*)(void *, uint8_t *, esp_apptrace_tmo_t *))esp_apptrace_uart_up_buffer_put,
|
||||
.flush_up_buffer_nolock = (esp_err_t (*)(void *, uint32_t, esp_apptrace_tmo_t *))esp_apptrace_uart_flush_nolock,
|
||||
.flush_up_buffer = (esp_err_t (*)(void *, esp_apptrace_tmo_t *))esp_apptrace_uart_flush,
|
||||
.down_buffer_config = (void (*)(void *, uint8_t *, uint32_t ))esp_apptrace_uart_down_buffer_config,
|
||||
.get_down_buffer = (uint8_t *(*)(void *, uint32_t *, esp_apptrace_tmo_t *))esp_apptrace_uart_down_buffer_get,
|
||||
.put_down_buffer = (esp_err_t (*)(void *, uint8_t *, esp_apptrace_tmo_t *))esp_apptrace_uart_down_buffer_put,
|
||||
.host_is_connected = (bool (*)(void *))esp_apptrace_uart_host_is_connected,
|
||||
};
|
||||
s_uart_hw_data.port_num = num;
|
||||
*data = &s_uart_hw_data;
|
||||
return &s_uart_hw;
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline uint32_t ring_buffer_mask(const esp_apptrace_uart_rb_t *rb)
|
||||
{
|
||||
return rb->max_size - 1;
|
||||
}
|
||||
#if APPTRACE_DEST_UART
|
||||
|
||||
/* Get the length of the data in the ring buffer */
|
||||
static inline uint32_t ring_buffer_data_len(const esp_apptrace_uart_rb_t *rb)
|
||||
{
|
||||
return rb->count;
|
||||
}
|
||||
|
||||
/* Get the length of the free space in the ring buffer */
|
||||
static inline uint32_t ring_buffer_free_len(const esp_apptrace_uart_rb_t *rb)
|
||||
{
|
||||
return rb->max_size - rb->count;
|
||||
}
|
||||
|
||||
static inline void ring_buffer_advance_tail(esp_apptrace_uart_rb_t *rb, uint32_t count)
|
||||
{
|
||||
rb->tail = (rb->tail + count) & ring_buffer_mask(rb);
|
||||
rb->count -= count;
|
||||
}
|
||||
|
||||
static inline void ring_buffer_advance_head(esp_apptrace_uart_rb_t *rb, uint32_t count)
|
||||
{
|
||||
rb->head = (rb->head + count) & ring_buffer_mask(rb);
|
||||
rb->count += count;
|
||||
}
|
||||
|
||||
static inline uint32_t ring_buffer_calc_to_send(const esp_apptrace_uart_rb_t *rb, uint32_t tx_msg_size)
|
||||
{
|
||||
uint32_t used = ring_buffer_data_len(rb);
|
||||
if (used == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t cont = rb->max_size - rb->tail;
|
||||
uint32_t n = MIN(used, cont);
|
||||
|
||||
/* Apply message size limit if specified */
|
||||
if (tx_msg_size && tx_msg_size < n) {
|
||||
return tx_msg_size;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
static esp_err_t esp_apptrace_uart_lock(void *hw_data, esp_apptrace_tmo_t *tmo)
|
||||
static esp_err_t esp_apptrace_uart_lock(esp_apptrace_uart_data_t *hw_data, esp_apptrace_tmo_t *tmo)
|
||||
{
|
||||
#if CONFIG_APPTRACE_LOCK_ENABLE
|
||||
esp_apptrace_uart_data_t *uart_data = hw_data;
|
||||
esp_err_t ret = esp_apptrace_lock_take(&uart_data->lock, tmo);
|
||||
esp_err_t ret = esp_apptrace_lock_take(&hw_data->lock, tmo);
|
||||
if (ret != ESP_OK) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
@@ -128,395 +95,261 @@ static esp_err_t esp_apptrace_uart_lock(void *hw_data, esp_apptrace_tmo_t *tmo)
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t esp_apptrace_uart_unlock(void *hw_data)
|
||||
static esp_err_t esp_apptrace_uart_unlock(esp_apptrace_uart_data_t *hw_data)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
#if CONFIG_APPTRACE_LOCK_ENABLE
|
||||
esp_apptrace_uart_data_t *uart_data = hw_data;
|
||||
ret = esp_apptrace_lock_give(&uart_data->lock);
|
||||
assert(ret == ESP_OK && "Failed to unlock apptrace uart lock!");
|
||||
ret = esp_apptrace_lock_give(&hw_data->lock);
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
static esp_err_t ring_buffer_put(esp_apptrace_uart_rb_t *rb, const uint8_t *data, uint32_t len)
|
||||
static inline void esp_apptrace_uart_hw_init(void)
|
||||
{
|
||||
/* Drop oldest. Make available space if needed */
|
||||
uint32_t free_len = ring_buffer_free_len(rb);
|
||||
if (len > free_len) {
|
||||
uint32_t need = len - free_len;
|
||||
ring_buffer_advance_tail(rb, need);
|
||||
ESP_APPTRACE_LOGI("Initialized UART on CPU%d", esp_cpu_get_core_id());
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************************/
|
||||
/***************************** Apptrace HW iface *****************************************/
|
||||
/*****************************************************************************************/
|
||||
|
||||
static esp_err_t esp_apptrace_send_uart_data(esp_apptrace_uart_data_t *hw_data, const char *data, uint32_t size, esp_apptrace_tmo_t *tmo)
|
||||
{
|
||||
esp_err_t res = esp_apptrace_uart_lock(hw_data, tmo);
|
||||
if (res != ESP_OK) {
|
||||
return res;
|
||||
}
|
||||
// We store current out position to handle it without lock
|
||||
volatile int32_t out_position = hw_data->tx_data_buff_out;
|
||||
|
||||
uint32_t head = rb->head;
|
||||
uint32_t space_to_end = rb->max_size - head;
|
||||
|
||||
if (len <= space_to_end) {
|
||||
memcpy(&rb->buffer[head], data, len);
|
||||
int len_free = APP_TRACE_MAX_TX_BUFF_UART - (hw_data->tx_data_buff_in - out_position);
|
||||
if (out_position > hw_data->tx_data_buff_in) {
|
||||
len_free = out_position - hw_data->tx_data_buff_in;
|
||||
}
|
||||
int check_len = APP_TRACE_MAX_TX_BUFF_UART - hw_data->tx_data_buff_in;
|
||||
if (size <= len_free)
|
||||
{
|
||||
if ( check_len >= size) {
|
||||
memcpy(&hw_data->tx_data_buff[hw_data->tx_data_buff_in], data, size);
|
||||
hw_data->tx_data_buff_in += size;
|
||||
} else {
|
||||
memcpy(&hw_data->tx_data_buff[hw_data->tx_data_buff_in], data, APP_TRACE_MAX_TX_BUFF_UART - hw_data->tx_data_buff_in);
|
||||
memcpy(&hw_data->tx_data_buff[0], &data[APP_TRACE_MAX_TX_BUFF_UART - hw_data->tx_data_buff_in], size - (APP_TRACE_MAX_TX_BUFF_UART - hw_data->tx_data_buff_in));
|
||||
hw_data->tx_data_buff_in = size - (APP_TRACE_MAX_TX_BUFF_UART - hw_data->tx_data_buff_in);
|
||||
}
|
||||
if (hw_data->tx_data_buff_in >= APP_TRACE_MAX_TX_BUFF_UART) {
|
||||
hw_data->tx_data_buff_in = 0;
|
||||
}
|
||||
} else {
|
||||
memcpy(&rb->buffer[head], data, space_to_end);
|
||||
memcpy(&rb->buffer[0], &data[space_to_end], len - space_to_end);
|
||||
hw_data->circular_buff_overflow = true;
|
||||
}
|
||||
|
||||
ring_buffer_advance_head(rb, len);
|
||||
if (esp_apptrace_uart_unlock(hw_data) != ESP_OK) {
|
||||
assert(false && "Failed to unlock apptrace data!");
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t ring_buffer_init(esp_apptrace_uart_rb_t *rb, uint32_t size)
|
||||
static void send_buff_data(esp_apptrace_uart_data_t *hw_data, esp_apptrace_tmo_t *tmo)
|
||||
{
|
||||
rb->buffer = heap_caps_malloc(size, MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
|
||||
if (!rb->buffer) {
|
||||
return ESP_ERR_NO_MEM;
|
||||
if (hw_data->tx_data_buff_in == hw_data->tx_data_buff_out) {
|
||||
return;
|
||||
}
|
||||
|
||||
rb->max_size = size;
|
||||
rb->count = 0;
|
||||
rb->head = 0;
|
||||
rb->tail = 0;
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static void IRAM_ATTR esp_apptrace_uart_isr_handler(void *arg)
|
||||
{
|
||||
esp_apptrace_uart_data_t *uart_data = arg;
|
||||
esp_apptrace_uart_rb_t *rb = &uart_data->tx_ring;
|
||||
|
||||
uint32_t intr_status = uart_hal_get_intsts_mask(&uart_data->hal_ctx);
|
||||
|
||||
if (intr_status & UART_INTR_TXFIFO_EMPTY) {
|
||||
uart_hal_clr_intsts_mask(&uart_data->hal_ctx, UART_INTR_TXFIFO_EMPTY);
|
||||
|
||||
uint32_t to_send = ring_buffer_calc_to_send(rb, uart_data->tx_msg_buff_size);
|
||||
if (to_send > 0) {
|
||||
uint32_t written = 0;
|
||||
uart_hal_write_txfifo(&uart_data->hal_ctx, &rb->buffer[rb->tail], to_send, &written);
|
||||
ring_buffer_advance_tail(rb, written);
|
||||
}
|
||||
|
||||
/* If ring buffer is empty, disable TX interrupt */
|
||||
if (ring_buffer_data_len(rb) == 0) {
|
||||
uart_ll_disable_intr_mask(uart_data->hal_ctx.dev, UART_INTR_TXFIFO_EMPTY);
|
||||
uart_data->tx_busy = false;
|
||||
// We store current in position to handle it without lock
|
||||
volatile int32_t in_position = hw_data->tx_data_buff_in;
|
||||
if (in_position > hw_data->tx_data_buff_out) {
|
||||
int bytes_sent = uart_write_bytes(hw_data->port_num, &hw_data->tx_data_buff[hw_data->tx_data_buff_out], in_position - hw_data->tx_data_buff_out);
|
||||
hw_data->tx_data_buff_out += bytes_sent;
|
||||
} else {
|
||||
int bytes_sent = uart_write_bytes(hw_data->port_num, &hw_data->tx_data_buff[hw_data->tx_data_buff_out], APP_TRACE_MAX_TX_BUFF_UART - hw_data->tx_data_buff_out);
|
||||
hw_data->tx_data_buff_out += bytes_sent;
|
||||
if (hw_data->tx_data_buff_out >= APP_TRACE_MAX_TX_BUFF_UART) {
|
||||
hw_data->tx_data_buff_out = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static esp_err_t esp_apptrace_uart_init(void *hw_data, const esp_apptrace_config_t *config)
|
||||
{
|
||||
esp_err_t ret = ESP_ERR_INVALID_ARG;
|
||||
uint64_t gpio_mask = 0;
|
||||
esp_apptrace_uart_data_t *uart_data = hw_data;
|
||||
const esp_apptrace_uart_config_t *uart_config = &config->dest_cfg.uart;
|
||||
#define APP_TRACE_UART_STOP_WAIT_TMO 1000000 //us
|
||||
|
||||
/* Init function is called on every core, so ensure to do main setup only once */
|
||||
static void esp_apptrace_send_uart_tx_task(void *arg)
|
||||
{
|
||||
esp_apptrace_uart_data_t *hw_data = (esp_apptrace_uart_data_t *)arg;
|
||||
esp_apptrace_tmo_t tmo;
|
||||
esp_apptrace_tmo_init(&tmo, APP_TRACE_UART_STOP_WAIT_TMO);
|
||||
|
||||
vTaskDelay(10);
|
||||
while (1) {
|
||||
send_buff_data(hw_data, &tmo);
|
||||
vTaskDelay(10);
|
||||
if (hw_data->circular_buff_overflow == true)
|
||||
{
|
||||
hw_data->circular_buff_overflow = false;
|
||||
ESP_LOGE(TAG, "Buffer overflow. Please increase UART baudrate, or increase UART TX ring buffer size in menuconfig.");
|
||||
}
|
||||
if (hw_data->message_buff_overflow == true)
|
||||
{
|
||||
hw_data->message_buff_overflow = false;
|
||||
ESP_LOGE(TAG, "Message size more then message buffer!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static const int APP_TRACE_UART_RX_BUF_SIZE = 4024;
|
||||
|
||||
static esp_err_t esp_apptrace_uart_init(esp_apptrace_uart_data_t *hw_data)
|
||||
{
|
||||
int core_id = esp_cpu_get_core_id();
|
||||
if (core_id == 0) {
|
||||
|
||||
if (uart_config->uart_num == CONFIG_ESP_CONSOLE_UART_NUM) {
|
||||
ESP_APPTRACE_LOGE("Application trace UART and console UART cannot use the same port number");
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
hw_data->tx_data_buff = (uint8_t *)heap_caps_malloc(APP_TRACE_MAX_TX_BUFF_UART, MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT);
|
||||
if (hw_data->tx_data_buff == NULL){
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
|
||||
if (uart_config->uart_num >= SOC_UART_HP_NUM) {
|
||||
ESP_APPTRACE_LOGE("UART port number %d is not supported!", uart_config->uart_num);
|
||||
return ESP_ERR_NOT_SUPPORTED;
|
||||
hw_data->tx_data_buff_in = 0;
|
||||
hw_data->tx_data_buff_out = 0;
|
||||
hw_data->tx_msg_buff = (uint8_t *)heap_caps_malloc(APP_TRACE_MAX_TX_MSG_UART, MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT);
|
||||
if (hw_data->tx_msg_buff == NULL)
|
||||
{
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
hw_data->tx_msg_buff_size = 0;
|
||||
hw_data->down_buffer_size = 0;
|
||||
hw_data->message_buff_overflow = false;
|
||||
hw_data->circular_buff_overflow = false;
|
||||
|
||||
if (GPIO_IS_VALID_GPIO(uart_config->tx_pin_num)) {
|
||||
gpio_mask |= BIT64(uart_config->tx_pin_num);
|
||||
}
|
||||
if (GPIO_IS_VALID_GPIO(uart_config->rx_pin_num)) {
|
||||
gpio_mask |= BIT64(uart_config->rx_pin_num);
|
||||
}
|
||||
assert((hw_data->port_num <= SOC_UART_NUM) && "Not possible to configure UART. Please check selected UART port");
|
||||
|
||||
if (gpio_mask == 0) {
|
||||
ESP_LOGE(TAG, "No valid GPIOs to reserve");
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
uint64_t r = esp_gpio_reserve(gpio_mask);
|
||||
if (r & gpio_mask) {
|
||||
ESP_LOGE(TAG, "GPIO(s) are already reserved: 0x%"PRIx64, r & gpio_mask);
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
uart_data->hal_ctx.dev = UART_LL_GET_HW(uart_config->uart_num);
|
||||
|
||||
HP_UART_BUS_CLK_ATOMIC() {
|
||||
uart_ll_enable_bus_clock(uart_config->uart_num, true);
|
||||
uart_ll_reset_register(uart_config->uart_num);
|
||||
}
|
||||
HP_UART_SRC_CLK_ATOMIC() {
|
||||
uart_ll_sclk_enable(uart_data->hal_ctx.dev);
|
||||
}
|
||||
|
||||
uint32_t sclk_hz;
|
||||
esp_clk_tree_src_get_freq_hz(UART_SCLK_DEFAULT, ESP_CLK_TREE_SRC_FREQ_PRECISION_CACHED, &sclk_hz);
|
||||
/* Enable the default clock source */
|
||||
esp_clk_tree_enable_src(UART_SCLK_DEFAULT, true);
|
||||
|
||||
/* Initialize UART HAL (sets default 8N1 mode) */
|
||||
uart_hal_init(&uart_data->hal_ctx, uart_config->uart_num);
|
||||
|
||||
ESP_LOGI(TAG, "uart_hal_init: %d", uart_config->uart_num);
|
||||
|
||||
HP_UART_SRC_CLK_ATOMIC() {
|
||||
uart_hal_set_sclk(&uart_data->hal_ctx, UART_SCLK_DEFAULT);
|
||||
uart_hal_set_baudrate(&uart_data->hal_ctx, uart_config->baud_rate, sclk_hz);
|
||||
}
|
||||
|
||||
/* Configure FIFO thresholds */
|
||||
uart_hal_set_txfifo_empty_thr(&uart_data->hal_ctx, 16); /* Slow down IRQ rate */
|
||||
uart_hal_set_rxfifo_full_thr(&uart_data->hal_ctx, 1);
|
||||
|
||||
/* Initialize TX ring buffer */
|
||||
if (uart_config->tx_buff_size == 0 || !is_power_of_two(uart_config->tx_buff_size)) {
|
||||
ESP_APPTRACE_LOGE("TX ring buffer size (%u) must be a power of two and greater than 0",
|
||||
uart_config->tx_buff_size);
|
||||
goto err_init_ring_buff;
|
||||
}
|
||||
ret = ring_buffer_init(&uart_data->tx_ring, uart_config->tx_buff_size);
|
||||
if (ret != ESP_OK) {
|
||||
ESP_APPTRACE_LOGE("Failed to initialize TX ring buffer");
|
||||
goto err_init_ring_buff;
|
||||
}
|
||||
|
||||
/* Initialize TX message buffer for providing with get_up_buffer */
|
||||
uart_data->tx_msg_buff_size = uart_config->tx_msg_size;
|
||||
uart_data->tx_msg_buff = heap_caps_malloc(uart_data->tx_msg_buff_size, MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
|
||||
if (uart_data->tx_msg_buff == NULL) {
|
||||
ESP_APPTRACE_LOGE("Failed to initialize TX message buffer");
|
||||
ret = ESP_ERR_NO_MEM;
|
||||
goto err_alloc_msg_buff;
|
||||
}
|
||||
|
||||
/* Disable all interrupts and clear status */
|
||||
uart_ll_disable_intr_mask(uart_data->hal_ctx.dev, UART_LL_INTR_MASK);
|
||||
uart_ll_clr_intsts_mask(uart_data->hal_ctx.dev, UART_LL_INTR_MASK);
|
||||
|
||||
/* Install interrupt handler */
|
||||
int intr_alloc_flags = 0;
|
||||
ret = esp_intr_alloc(uart_periph_signal[uart_config->uart_num].irq, intr_alloc_flags,
|
||||
esp_apptrace_uart_isr_handler, uart_data, &uart_data->intr_handle);
|
||||
if (ret != ESP_OK) {
|
||||
ESP_APPTRACE_LOGE("Failed to allocate interrupt: %s", esp_err_to_name(ret));
|
||||
goto err_alloc_intr;
|
||||
}
|
||||
|
||||
/* Reset FIFOs */
|
||||
uart_hal_rxfifo_rst(&uart_data->hal_ctx);
|
||||
uart_hal_txfifo_rst(&uart_data->hal_ctx);
|
||||
|
||||
/* Configure GPIO pins for RX and TX */
|
||||
const uint32_t tx_idx = UART_PERIPH_SIGNAL(uart_config->uart_num, SOC_UART_PERIPH_SIGNAL_TX);
|
||||
const uint32_t rx_idx = UART_PERIPH_SIGNAL(uart_config->uart_num, SOC_UART_PERIPH_SIGNAL_RX);
|
||||
|
||||
/* Configure TX pin */
|
||||
gpio_ll_func_sel(&GPIO, uart_config->tx_pin_num, PIN_FUNC_GPIO);
|
||||
esp_rom_gpio_pad_pullup_only(uart_config->tx_pin_num);
|
||||
esp_rom_gpio_connect_out_signal(uart_config->tx_pin_num, tx_idx, 0, 0);
|
||||
|
||||
/* Configure RX pin */
|
||||
gpio_ll_input_enable(&GPIO, uart_config->rx_pin_num);
|
||||
esp_rom_gpio_pad_pullup_only(uart_config->rx_pin_num);
|
||||
esp_rom_gpio_connect_in_signal(uart_config->rx_pin_num, rx_idx, 0);
|
||||
|
||||
#if CONFIG_APPTRACE_LOCK_ENABLE
|
||||
esp_apptrace_lock_init(&uart_data->lock);
|
||||
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,
|
||||
.data_bits = UART_DATA_8_BITS,
|
||||
.parity = UART_PARITY_DISABLE,
|
||||
.stop_bits = UART_STOP_BITS_1,
|
||||
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
|
||||
.source_clk = source_clk,
|
||||
};
|
||||
ESP_LOGI(TAG, "UART baud rate: %i", CONFIG_APPTRACE_UART_BAUDRATE);
|
||||
// We won't use a buffer for sending data.
|
||||
esp_err_t err = uart_driver_install(hw_data->port_num, APP_TRACE_UART_RX_BUF_SIZE, APP_TRACE_UART_RX_BUF_SIZE, 0, NULL, 0);
|
||||
assert((err == ESP_OK) && "Not possible to install UART. Please check and change menuconfig parameters!");
|
||||
err = uart_param_config(hw_data->port_num, &uart_config);
|
||||
assert((err == ESP_OK) && "Not possible to configure UART. Please check and change menuconfig parameters!");
|
||||
err = uart_set_pin(hw_data->port_num, CONFIG_APPTRACE_UART_TX_GPIO, CONFIG_APPTRACE_UART_RX_GPIO, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
|
||||
assert((err == ESP_OK) && "Not possible to configure UART RX/TX pins. Please check and change menuconfig parameters!");
|
||||
|
||||
uart_data->inited |= 1 << core_id;
|
||||
uart_data->tx_busy = false;
|
||||
int uart_prio = CONFIG_APPTRACE_UART_TASK_PRIO;
|
||||
if (uart_prio >= (configMAX_PRIORITIES-1)) uart_prio = configMAX_PRIORITIES - 1;
|
||||
err = xTaskCreate(esp_apptrace_send_uart_tx_task, "app_trace_uart_tx_task", 2500, hw_data, uart_prio, NULL);
|
||||
assert((err == pdPASS) && "Not possible to configure UART. Not possible to create task!");
|
||||
|
||||
#if CONFIG_APPTRACE_LOCK_ENABLE
|
||||
esp_apptrace_lock_init(&hw_data->lock);
|
||||
#endif
|
||||
}
|
||||
// init UART on this CPU
|
||||
esp_apptrace_uart_hw_init();
|
||||
hw_data->inited |= 1 << core_id;
|
||||
|
||||
return ESP_OK;
|
||||
|
||||
err_alloc_intr:
|
||||
heap_caps_free(uart_data->tx_msg_buff);
|
||||
err_alloc_msg_buff:
|
||||
heap_caps_free(uart_data->tx_ring.buffer);
|
||||
err_init_ring_buff:
|
||||
esp_clk_tree_enable_src(UART_SCLK_DEFAULT, false);
|
||||
HP_UART_SRC_CLK_ATOMIC() {
|
||||
uart_ll_sclk_disable(uart_data->hal_ctx.dev);
|
||||
}
|
||||
HP_UART_BUS_CLK_ATOMIC() {
|
||||
uart_ll_enable_bus_clock(uart_config->uart_num, false);
|
||||
}
|
||||
esp_gpio_revoke(gpio_mask);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static uint8_t *esp_apptrace_uart_up_buffer_get(void *hw_data, uint32_t size, esp_apptrace_tmo_t *tmo)
|
||||
static uint8_t *esp_apptrace_uart_up_buffer_get(esp_apptrace_uart_data_t *hw_data, uint32_t size, esp_apptrace_tmo_t *tmo)
|
||||
{
|
||||
esp_apptrace_uart_data_t *uart_data = hw_data;
|
||||
|
||||
if (size == 0 || size > uart_data->tx_msg_buff_size) {
|
||||
uint8_t *ptr;
|
||||
if (size > APP_TRACE_MAX_TX_MSG_UART) {
|
||||
hw_data->message_buff_overflow = true;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (esp_apptrace_uart_lock(uart_data, tmo) != ESP_OK) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (uart_data->tx_pending_msg_size != 0) {
|
||||
if (hw_data->tx_msg_buff_size != 0)
|
||||
{
|
||||
// A previous message was not sent.
|
||||
esp_apptrace_uart_unlock(uart_data);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uart_data->tx_pending_msg_size = size;
|
||||
|
||||
esp_apptrace_uart_unlock(uart_data);
|
||||
|
||||
return uart_data->tx_msg_buff;
|
||||
}
|
||||
|
||||
static esp_err_t esp_apptrace_uart_up_buffer_put(void *hw_data, uint8_t *ptr, esp_apptrace_tmo_t *tmo)
|
||||
{
|
||||
esp_apptrace_uart_data_t *uart_data = hw_data;
|
||||
esp_apptrace_uart_rb_t *rb = &uart_data->tx_ring;
|
||||
|
||||
esp_err_t res = esp_apptrace_uart_lock(uart_data, tmo);
|
||||
esp_err_t res = esp_apptrace_uart_lock(hw_data, tmo);
|
||||
if (res != ESP_OK) {
|
||||
return res;
|
||||
return NULL;
|
||||
}
|
||||
ptr = hw_data->tx_msg_buff;
|
||||
hw_data->tx_msg_buff_size = size;
|
||||
|
||||
/* Add data to ring buffer */
|
||||
ring_buffer_put(rb, ptr, uart_data->tx_pending_msg_size);
|
||||
uart_data->tx_pending_msg_size = 0;
|
||||
|
||||
esp_apptrace_uart_unlock(uart_data);
|
||||
|
||||
// Trigger transmission if not already in progress
|
||||
if (!uart_data->tx_busy) {
|
||||
uart_data->tx_busy = true;
|
||||
/* Enable TX interrupt */
|
||||
uart_ll_clr_intsts_mask(uart_data->hal_ctx.dev, UART_INTR_TXFIFO_EMPTY);
|
||||
uart_ll_ena_intr_mask(uart_data->hal_ctx.dev, UART_INTR_TXFIFO_EMPTY);
|
||||
// now we can safely unlock apptrace to allow other tasks/ISRs to get other buffers and write their data
|
||||
if (esp_apptrace_uart_unlock(hw_data) != ESP_OK) {
|
||||
assert(false && "Failed to unlock apptrace data!");
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
static void esp_apptrace_uart_down_buffer_config(void *hw_data, uint8_t *buf, uint32_t size)
|
||||
static esp_err_t esp_apptrace_uart_up_buffer_put(esp_apptrace_uart_data_t *hw_data, uint8_t *ptr, esp_apptrace_tmo_t *tmo)
|
||||
{
|
||||
esp_apptrace_uart_data_t *uart_data = hw_data;
|
||||
|
||||
assert(buf != NULL && "Down buffer cannot be NULL");
|
||||
assert(size > 0 && "Down buffer size must be greater than 0");
|
||||
|
||||
uart_data->rx_msg_buff = buf;
|
||||
uart_data->rx_msg_buff_size = size;
|
||||
esp_err_t res = esp_apptrace_send_uart_data(hw_data, (const char *)ptr, hw_data->tx_msg_buff_size, tmo);
|
||||
// Clear size to indicate that we've sent data
|
||||
hw_data->tx_msg_buff_size = 0;
|
||||
return res;
|
||||
}
|
||||
|
||||
static uint8_t *esp_apptrace_uart_down_buffer_get(void *hw_data, uint32_t *size, esp_apptrace_tmo_t *tmo)
|
||||
static void esp_apptrace_uart_down_buffer_config(esp_apptrace_uart_data_t *hw_data, uint8_t *buf, uint32_t size)
|
||||
{
|
||||
esp_apptrace_uart_data_t *uart_data = hw_data;
|
||||
if (!size || *size == 0) {
|
||||
hw_data->down_buffer = (uint8_t *)malloc(size);
|
||||
if (hw_data->down_buffer == NULL){
|
||||
assert(false && "Failed to allocate apptrace uart down buffer!");
|
||||
}
|
||||
hw_data->down_buffer_size = size;
|
||||
}
|
||||
|
||||
static uint8_t *esp_apptrace_uart_down_buffer_get(esp_apptrace_uart_data_t *hw_data, uint32_t *size, esp_apptrace_tmo_t *tmo)
|
||||
{
|
||||
uint8_t *ptr = NULL;
|
||||
|
||||
if (*size > hw_data->down_buffer_size) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!uart_data->rx_msg_buff) {
|
||||
ESP_APPTRACE_LOGE("RX message buffer is not configured. Call down_buffer_config() first.");
|
||||
esp_err_t res = esp_apptrace_uart_lock(hw_data, tmo);
|
||||
if (res != ESP_OK) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (esp_apptrace_uart_lock(uart_data, tmo) != ESP_OK) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uint32_t rx_len = uart_ll_get_rxfifo_len(uart_data->hal_ctx.dev);
|
||||
int to_read = MIN(rx_len, MIN(uart_data->rx_msg_buff_size, *size));
|
||||
if (to_read) {
|
||||
uart_hal_read_rxfifo(&uart_data->hal_ctx, uart_data->rx_msg_buff, &to_read);
|
||||
}
|
||||
*size = to_read;
|
||||
|
||||
esp_apptrace_uart_unlock(uart_data);
|
||||
|
||||
return (*size > 0) ? uart_data->rx_msg_buff : NULL;
|
||||
}
|
||||
|
||||
static esp_err_t esp_apptrace_uart_down_buffer_put(void *hw_data, uint8_t *ptr, esp_apptrace_tmo_t *tmo)
|
||||
{
|
||||
(void)hw_data;
|
||||
(void)ptr;
|
||||
(void)tmo;
|
||||
|
||||
/* No action needed - data was already read in get function */
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static bool esp_apptrace_uart_host_is_connected(void *hw_data)
|
||||
{
|
||||
esp_apptrace_uart_data_t *uart_data = hw_data;
|
||||
|
||||
return uart_data->inited & 1;
|
||||
}
|
||||
|
||||
static esp_err_t esp_apptrace_uart_flush_nolock(void *hw_data, uint32_t min_sz, esp_apptrace_tmo_t *tmo)
|
||||
{
|
||||
esp_apptrace_uart_data_t *uart_data = hw_data;
|
||||
esp_apptrace_uart_rb_t *rb = &uart_data->tx_ring;
|
||||
|
||||
uint32_t pending = ring_buffer_data_len(rb);
|
||||
if (pending < min_sz) {
|
||||
ESP_APPTRACE_LOGD("Ignore UART flush request for min %" PRIu32 " bytes. Pending bytes: %" PRIu32, min_sz, pending);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/* Trigger transmission if there's data but not busy */
|
||||
if (pending > 0 && !uart_data->tx_busy) {
|
||||
uart_data->tx_busy = true;
|
||||
uart_ll_clr_intsts_mask(uart_data->hal_ctx.dev, UART_INTR_TXFIFO_EMPTY);
|
||||
uart_ll_ena_intr_mask(uart_data->hal_ctx.dev, UART_INTR_TXFIFO_EMPTY);
|
||||
}
|
||||
|
||||
while (uart_data->tx_busy || ring_buffer_data_len(rb) > 0) {
|
||||
if (esp_apptrace_tmo_check(tmo) != ESP_OK) {
|
||||
return ESP_ERR_TIMEOUT;
|
||||
size_t uart_fifolen = 0;
|
||||
uart_get_buffered_data_len(hw_data->port_num, &uart_fifolen);
|
||||
if (uart_fifolen > 0) {
|
||||
if (*size < uart_fifolen) {
|
||||
uart_fifolen = *size;
|
||||
}
|
||||
esp_rom_delay_us(100);
|
||||
*size = uart_fifolen;
|
||||
ptr = hw_data->down_buffer;
|
||||
*size =uart_read_bytes(hw_data->port_num, ptr, uart_fifolen, 0);
|
||||
}
|
||||
|
||||
if (esp_apptrace_uart_unlock(hw_data) != ESP_OK) {
|
||||
assert(false && "Failed to unlock apptrace data!");
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
|
||||
static esp_err_t esp_apptrace_uart_down_buffer_put(esp_apptrace_uart_data_t *hw_data, uint8_t *ptr, esp_apptrace_tmo_t *tmo)
|
||||
{
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t esp_apptrace_uart_flush(void *hw_data, esp_apptrace_tmo_t *tmo)
|
||||
static bool esp_apptrace_uart_host_is_connected(esp_apptrace_uart_data_t *hw_data)
|
||||
{
|
||||
esp_apptrace_uart_data_t *uart_data = hw_data;
|
||||
esp_err_t res = esp_apptrace_uart_lock(uart_data, tmo);
|
||||
if (res != ESP_OK) {
|
||||
return res;
|
||||
}
|
||||
|
||||
esp_err_t ret = esp_apptrace_uart_flush_nolock(hw_data, 0, tmo);
|
||||
|
||||
esp_apptrace_uart_unlock(uart_data);
|
||||
|
||||
return ret;
|
||||
return hw_data->inited & 1;
|
||||
}
|
||||
|
||||
esp_apptrace_hw_t *esp_apptrace_uart_hw_get(int num, void **data)
|
||||
static esp_err_t esp_apptrace_uart_flush_nolock(esp_apptrace_uart_data_t *hw_data, uint32_t min_sz, esp_apptrace_tmo_t *tmo)
|
||||
{
|
||||
ESP_APPTRACE_LOGD("esp_apptrace_uart_hw_get - %i", num);
|
||||
|
||||
static esp_apptrace_uart_data_t s_uart_hw_data;
|
||||
static esp_apptrace_hw_t s_uart_hw = {
|
||||
.init = esp_apptrace_uart_init,
|
||||
.get_up_buffer = esp_apptrace_uart_up_buffer_get,
|
||||
.put_up_buffer = esp_apptrace_uart_up_buffer_put,
|
||||
.flush_up_buffer_nolock = esp_apptrace_uart_flush_nolock,
|
||||
.flush_up_buffer = esp_apptrace_uart_flush,
|
||||
.down_buffer_config = esp_apptrace_uart_down_buffer_config,
|
||||
.get_down_buffer = esp_apptrace_uart_down_buffer_get,
|
||||
.put_down_buffer = esp_apptrace_uart_down_buffer_put,
|
||||
.host_is_connected = esp_apptrace_uart_host_is_connected,
|
||||
};
|
||||
*data = &s_uart_hw_data;
|
||||
return &s_uart_hw;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t esp_apptrace_uart_flush(esp_apptrace_uart_data_t *hw_data, esp_apptrace_tmo_t *tmo)
|
||||
{
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
#endif // APPTRACE_DEST_UART
|
||||
|
||||
367
components/app_trace/port/riscv/port.c
Normal file
367
components/app_trace/port/riscv/port.c
Normal file
@@ -0,0 +1,367 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*/
|
||||
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_cpu.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_app_trace_membufs_proto.h"
|
||||
#include "esp_app_trace_port.h"
|
||||
#include "riscv/semihosting.h"
|
||||
|
||||
/** RISCV HW transport data */
|
||||
typedef struct {
|
||||
uint8_t inited; // initialization state flags for every core
|
||||
#if CONFIG_APPTRACE_LOCK_ENABLE
|
||||
esp_apptrace_lock_t lock; // sync lock
|
||||
#endif
|
||||
esp_apptrace_membufs_proto_data_t membufs;
|
||||
} esp_apptrace_riscv_data_t;
|
||||
|
||||
/** RISCV memory host iface control block */
|
||||
typedef struct {
|
||||
uint32_t ctrl;
|
||||
// - Guard field. If this register is not zero then CPU is changing this struct and
|
||||
// this guard field holds address of the instruction which application will execute when CPU finishes with those modifications.
|
||||
uint32_t stat;
|
||||
esp_apptrace_mem_block_t * mem_blocks;
|
||||
} esp_apptrace_riscv_ctrl_block_t;
|
||||
|
||||
#define ESP_APPTRACE_RISCV_BLOCK_LEN_MSK 0x7FFFUL
|
||||
#define ESP_APPTRACE_RISCV_BLOCK_LEN(_l_) ((_l_) & ESP_APPTRACE_RISCV_BLOCK_LEN_MSK)
|
||||
#define ESP_APPTRACE_RISCV_BLOCK_LEN_GET(_v_) ((_v_) & ESP_APPTRACE_RISCV_BLOCK_LEN_MSK)
|
||||
#define ESP_APPTRACE_RISCV_BLOCK_ID_MSK 0x7FUL
|
||||
#define ESP_APPTRACE_RISCV_BLOCK_ID(_id_) (((_id_) & ESP_APPTRACE_RISCV_BLOCK_ID_MSK) << 15)
|
||||
#define ESP_APPTRACE_RISCV_BLOCK_ID_GET(_v_) (((_v_) >> 15) & ESP_APPTRACE_RISCV_BLOCK_ID_MSK)
|
||||
#define ESP_APPTRACE_RISCV_HOST_DATA (1 << 22)
|
||||
#define ESP_APPTRACE_RISCV_HOST_CONNECT (1 << 23)
|
||||
|
||||
#define ESP_APPTRACE_RISCV_INITED(_hw_) ((_hw_)->inited & (1 << 0/*esp_cpu_get_core_id()*/))
|
||||
|
||||
static esp_err_t esp_apptrace_riscv_init(esp_apptrace_riscv_data_t *hw_data);
|
||||
static esp_err_t esp_apptrace_riscv_flush(esp_apptrace_riscv_data_t *hw_data, esp_apptrace_tmo_t *tmo);
|
||||
static esp_err_t esp_apptrace_riscv_flush_nolock(esp_apptrace_riscv_data_t *hw_data, uint32_t min_sz, esp_apptrace_tmo_t *tmo);
|
||||
static uint8_t *esp_apptrace_riscv_up_buffer_get(esp_apptrace_riscv_data_t *hw_data, uint32_t size, esp_apptrace_tmo_t *tmo);
|
||||
static esp_err_t esp_apptrace_riscv_up_buffer_put(esp_apptrace_riscv_data_t *hw_data, uint8_t *ptr, esp_apptrace_tmo_t *tmo);
|
||||
static void esp_apptrace_riscv_down_buffer_config(esp_apptrace_riscv_data_t *hw_data, uint8_t *buf, uint32_t size);
|
||||
static uint8_t *esp_apptrace_riscv_down_buffer_get(esp_apptrace_riscv_data_t *hw_data, uint32_t *size, esp_apptrace_tmo_t *tmo);
|
||||
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);
|
||||
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);
|
||||
|
||||
|
||||
const static char *TAG = "esp_apptrace";
|
||||
|
||||
#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE
|
||||
#define APPTRACE_DRAM_ATTR TCM_DRAM_ATTR
|
||||
#else
|
||||
#define APPTRACE_DRAM_ATTR
|
||||
#endif
|
||||
|
||||
static APPTRACE_DRAM_ATTR esp_apptrace_riscv_ctrl_block_t s_tracing_ctrl[CONFIG_FREERTOS_NUMBER_OF_CORES];
|
||||
|
||||
esp_apptrace_hw_t *esp_apptrace_jtag_hw_get(void **data)
|
||||
{
|
||||
#if CONFIG_APPTRACE_DEST_JTAG
|
||||
static esp_apptrace_membufs_proto_hw_t s_trace_proto_hw = {
|
||||
.swap_start = esp_apptrace_riscv_buffer_swap_start,
|
||||
.swap = esp_apptrace_riscv_buffer_swap,
|
||||
.swap_end = esp_apptrace_riscv_buffer_swap_end,
|
||||
.host_data_pending = esp_apptrace_riscv_host_data_pending,
|
||||
};
|
||||
static esp_apptrace_riscv_data_t s_trace_hw_data = {
|
||||
.membufs = {
|
||||
.hw = &s_trace_proto_hw,
|
||||
},
|
||||
};
|
||||
static esp_apptrace_hw_t s_trace_hw = {
|
||||
.init = (esp_err_t (*)(void *))esp_apptrace_riscv_init,
|
||||
.get_up_buffer = (uint8_t *(*)(void *, uint32_t, esp_apptrace_tmo_t *))esp_apptrace_riscv_up_buffer_get,
|
||||
.put_up_buffer = (esp_err_t (*)(void *, uint8_t *, esp_apptrace_tmo_t *))esp_apptrace_riscv_up_buffer_put,
|
||||
.flush_up_buffer_nolock = (esp_err_t (*)(void *, uint32_t, esp_apptrace_tmo_t *))esp_apptrace_riscv_flush_nolock,
|
||||
.flush_up_buffer = (esp_err_t (*)(void *, esp_apptrace_tmo_t *))esp_apptrace_riscv_flush,
|
||||
.down_buffer_config = (void (*)(void *, uint8_t *, uint32_t ))esp_apptrace_riscv_down_buffer_config,
|
||||
.get_down_buffer = (uint8_t *(*)(void *, uint32_t *, esp_apptrace_tmo_t *))esp_apptrace_riscv_down_buffer_get,
|
||||
.put_down_buffer = (esp_err_t (*)(void *, uint8_t *, esp_apptrace_tmo_t *))esp_apptrace_riscv_down_buffer_put,
|
||||
.host_is_connected = (bool (*)(void *))esp_apptrace_riscv_host_is_connected,
|
||||
};
|
||||
*data = &s_trace_hw_data;
|
||||
return &s_trace_hw;
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Advertises apptrace control block address to host.
|
||||
This function can be overridden with custom implementation,
|
||||
e.g. OpenOCD flasher stub use own implementation of it. */
|
||||
__attribute__((weak)) int esp_apptrace_advertise_ctrl_block(void *ctrl_block_addr)
|
||||
{
|
||||
if (!esp_cpu_dbgr_is_attached()) {
|
||||
return 0;
|
||||
}
|
||||
return (int) semihosting_call_noerrno(ESP_SEMIHOSTING_SYS_APPTRACE_INIT, (long*)ctrl_block_addr);
|
||||
}
|
||||
|
||||
/* Returns up buffers config.
|
||||
This function can be overridden with custom implementation,
|
||||
e.g. OpenOCD flasher stub use own implementation of it. */
|
||||
__attribute__((weak)) void esp_apptrace_get_up_buffers(esp_apptrace_mem_block_t mem_blocks_cfg[2])
|
||||
{
|
||||
static uint8_t s_mem_blocks[2][CONFIG_APPTRACE_BUF_SIZE];
|
||||
|
||||
mem_blocks_cfg[0].start = s_mem_blocks[0];
|
||||
mem_blocks_cfg[0].sz = CONFIG_APPTRACE_BUF_SIZE;
|
||||
mem_blocks_cfg[1].start = s_mem_blocks[1];
|
||||
mem_blocks_cfg[1].sz = CONFIG_APPTRACE_BUF_SIZE;
|
||||
}
|
||||
|
||||
static esp_err_t esp_apptrace_riscv_lock(esp_apptrace_riscv_data_t *hw_data, esp_apptrace_tmo_t *tmo)
|
||||
{
|
||||
#if CONFIG_APPTRACE_LOCK_ENABLE
|
||||
esp_err_t ret = esp_apptrace_lock_take(&hw_data->lock, tmo);
|
||||
if (ret != ESP_OK) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
#endif
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t esp_apptrace_riscv_unlock(esp_apptrace_riscv_data_t *hw_data)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
#if CONFIG_APPTRACE_LOCK_ENABLE
|
||||
ret = esp_apptrace_lock_give(&hw_data->lock);
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*****************************************************************************************/
|
||||
/***************************** Apptrace HW iface *****************************************/
|
||||
/*****************************************************************************************/
|
||||
|
||||
static esp_err_t esp_apptrace_riscv_init(esp_apptrace_riscv_data_t *hw_data)
|
||||
{
|
||||
int core_id = esp_cpu_get_core_id();
|
||||
|
||||
if (hw_data->inited == 0) {
|
||||
esp_apptrace_mem_block_t mem_blocks_cfg[2];
|
||||
esp_apptrace_get_up_buffers(mem_blocks_cfg);
|
||||
esp_err_t res = esp_apptrace_membufs_init(&hw_data->membufs, mem_blocks_cfg);
|
||||
if (res != ESP_OK) {
|
||||
ESP_APPTRACE_LOGE("Failed to init membufs proto (%d)!", res);
|
||||
return res;
|
||||
}
|
||||
#if CONFIG_APPTRACE_LOCK_ENABLE
|
||||
esp_apptrace_lock_init(&hw_data->lock);
|
||||
#endif
|
||||
}
|
||||
hw_data->inited |= 1 << core_id;
|
||||
ESP_APPTRACE_LOGI("Apptrace initialized on CPU%d. Tracing control block @ %p.", core_id, &s_tracing_ctrl[core_id]);
|
||||
s_tracing_ctrl[core_id].mem_blocks = hw_data->membufs.blocks;
|
||||
for (int i = 0; i < 2; i++) {
|
||||
ESP_APPTRACE_LOGD("Mem buf[%d] %" PRIu32 " bytes @ %p (%p/%p)", i,
|
||||
s_tracing_ctrl[core_id].mem_blocks[i].sz, s_tracing_ctrl[core_id].mem_blocks[i].start,
|
||||
&(s_tracing_ctrl[core_id].mem_blocks[i].start), &(s_tracing_ctrl[core_id].mem_blocks[i].sz));
|
||||
}
|
||||
// notify host about control block address
|
||||
int res = esp_apptrace_advertise_ctrl_block(&s_tracing_ctrl[core_id]);
|
||||
assert(res == 0 && "Failed to send config to host!");
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static uint8_t *esp_apptrace_riscv_up_buffer_get(esp_apptrace_riscv_data_t *hw_data, uint32_t size, esp_apptrace_tmo_t *tmo)
|
||||
{
|
||||
uint8_t *ptr;
|
||||
|
||||
if (!ESP_APPTRACE_RISCV_INITED(hw_data)) {
|
||||
return NULL;
|
||||
}
|
||||
esp_err_t res = esp_apptrace_riscv_lock(hw_data, tmo);
|
||||
if (res != ESP_OK) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ptr = esp_apptrace_membufs_up_buffer_get(&hw_data->membufs, size, tmo);
|
||||
|
||||
// now we can safely unlock apptrace to allow other tasks/ISRs to get other buffers and write their data
|
||||
if (esp_apptrace_riscv_unlock(hw_data) != ESP_OK) {
|
||||
assert(false && "Failed to unlock apptrace data!");
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
|
||||
static esp_err_t esp_apptrace_riscv_up_buffer_put(esp_apptrace_riscv_data_t *hw_data, uint8_t *ptr, esp_apptrace_tmo_t *tmo)
|
||||
{
|
||||
if (!ESP_APPTRACE_RISCV_INITED(hw_data)) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
// Can avoid locking because esp_apptrace_membufs_up_buffer_put() just modifies buffer's header
|
||||
esp_err_t res = esp_apptrace_membufs_up_buffer_put(&hw_data->membufs, ptr, tmo);
|
||||
return res;
|
||||
}
|
||||
|
||||
static void esp_apptrace_riscv_down_buffer_config(esp_apptrace_riscv_data_t *hw_data, uint8_t *buf, uint32_t size)
|
||||
{
|
||||
if (!ESP_APPTRACE_RISCV_INITED(hw_data)) {
|
||||
return;
|
||||
}
|
||||
esp_apptrace_membufs_down_buffer_config(&hw_data->membufs, buf, size);
|
||||
}
|
||||
|
||||
static uint8_t *esp_apptrace_riscv_down_buffer_get(esp_apptrace_riscv_data_t *hw_data, uint32_t *size, esp_apptrace_tmo_t *tmo)
|
||||
{
|
||||
uint8_t *ptr;
|
||||
|
||||
if (!ESP_APPTRACE_RISCV_INITED(hw_data)) {
|
||||
return NULL;
|
||||
}
|
||||
esp_err_t res = esp_apptrace_riscv_lock(hw_data, tmo);
|
||||
if (res != ESP_OK) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ptr = esp_apptrace_membufs_down_buffer_get(&hw_data->membufs, size, tmo);
|
||||
|
||||
// now we can safely unlock apptrace to allow other tasks/ISRs to get other buffers and write their data
|
||||
if (esp_apptrace_riscv_unlock(hw_data) != ESP_OK) {
|
||||
assert(false && "Failed to unlock apptrace data!");
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
if (!ESP_APPTRACE_RISCV_INITED(hw_data)) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
// Can avoid locking because esp_apptrace_membufs_down_buffer_put() does nothing
|
||||
/*esp_err_t res = esp_apptrace_riscv_lock(hw_data, tmo);
|
||||
if (res != ESP_OK) {
|
||||
return res;
|
||||
}*/
|
||||
|
||||
esp_err_t res = esp_apptrace_membufs_down_buffer_put(&hw_data->membufs, ptr, tmo);
|
||||
|
||||
// now we can safely unlock apptrace to allow other tasks/ISRs to get other buffers and write their data
|
||||
/*if (esp_apptrace_riscv_unlock(hw_data) != ESP_OK) {
|
||||
assert(false && "Failed to unlock apptrace data!");
|
||||
}*/
|
||||
return res;
|
||||
}
|
||||
|
||||
static bool esp_apptrace_riscv_host_is_connected(esp_apptrace_riscv_data_t *hw_data)
|
||||
{
|
||||
if (!ESP_APPTRACE_RISCV_INITED(hw_data)) {
|
||||
return false;
|
||||
}
|
||||
return s_tracing_ctrl[esp_cpu_get_core_id()].ctrl & ESP_APPTRACE_RISCV_HOST_CONNECT ? true : false;
|
||||
}
|
||||
|
||||
static esp_err_t esp_apptrace_riscv_flush_nolock(esp_apptrace_riscv_data_t *hw_data, uint32_t min_sz, esp_apptrace_tmo_t *tmo)
|
||||
{
|
||||
if (!ESP_APPTRACE_RISCV_INITED(hw_data)) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
return esp_apptrace_membufs_flush_nolock(&hw_data->membufs, min_sz, tmo);
|
||||
}
|
||||
|
||||
static esp_err_t esp_apptrace_riscv_flush(esp_apptrace_riscv_data_t *hw_data, esp_apptrace_tmo_t *tmo)
|
||||
{
|
||||
if (!ESP_APPTRACE_RISCV_INITED(hw_data)) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
esp_err_t res = esp_apptrace_riscv_lock(hw_data, tmo);
|
||||
if (res != ESP_OK) {
|
||||
return res;
|
||||
}
|
||||
|
||||
res = esp_apptrace_membufs_flush_nolock(&hw_data->membufs, 0, tmo);
|
||||
|
||||
// now we can safely unlock apptrace to allow other tasks/ISRs to get other buffers and write their data
|
||||
if (esp_apptrace_riscv_unlock(hw_data) != ESP_OK) {
|
||||
assert(false && "Failed to unlock apptrace data!");
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/*****************************************************************************************/
|
||||
/************************** Membufs proto HW iface ***************************************/
|
||||
/*****************************************************************************************/
|
||||
|
||||
static inline void esp_apptrace_riscv_buffer_swap_lock(void)
|
||||
{
|
||||
extern uint32_t __esp_apptrace_riscv_updated;
|
||||
|
||||
// indicate to host that we are about to update.
|
||||
// this is used only to place CPU into streaming mode at tracing startup
|
||||
// before starting streaming host can halt us after we read ESP_APPTRACE_RISCV_CTRL_REG and before we updated it
|
||||
// HACK: in this case host will set breakpoint just after ESP_APPTRACE_RISCV_CTRL_REG update,
|
||||
// here we set address to set bp at
|
||||
// enter ERI update critical section
|
||||
s_tracing_ctrl[esp_cpu_get_core_id()].stat = (uint32_t)&__esp_apptrace_riscv_updated;
|
||||
}
|
||||
|
||||
static __attribute__((noinline)) void esp_apptrace_riscv_buffer_swap_unlock(void)
|
||||
{
|
||||
// exit ERI update critical section
|
||||
s_tracing_ctrl[esp_cpu_get_core_id()].stat = 0;
|
||||
// TODO: currently host sets breakpoint, use break instruction to stop;
|
||||
// it will allow to use ESP_APPTRACE_RISCV_STAT_REG for other purposes
|
||||
asm volatile (
|
||||
" .global __esp_apptrace_riscv_updated\n"
|
||||
"__esp_apptrace_riscv_updated:\n"); // host will set bp here to resolve collision at streaming start
|
||||
}
|
||||
|
||||
static esp_err_t esp_apptrace_riscv_buffer_swap_start(uint32_t curr_block_id)
|
||||
{
|
||||
esp_err_t res = ESP_OK;
|
||||
|
||||
esp_apptrace_riscv_buffer_swap_lock();
|
||||
|
||||
uint32_t ctrl_reg = s_tracing_ctrl[esp_cpu_get_core_id()].ctrl;
|
||||
uint32_t host_connected = ESP_APPTRACE_RISCV_HOST_CONNECT & ctrl_reg;
|
||||
if (host_connected) {
|
||||
uint32_t acked_block = ESP_APPTRACE_RISCV_BLOCK_ID_GET(ctrl_reg);
|
||||
uint32_t host_to_read = ESP_APPTRACE_RISCV_BLOCK_LEN_GET(ctrl_reg);
|
||||
if (host_to_read != 0 || acked_block != (curr_block_id & ESP_APPTRACE_RISCV_BLOCK_ID_MSK)) {
|
||||
ESP_APPTRACE_LOGD("[%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_RISCV_BLOCK_ID_MSK, curr_block_id);
|
||||
res = ESP_ERR_NO_MEM;
|
||||
goto _on_err;
|
||||
}
|
||||
}
|
||||
return ESP_OK;
|
||||
_on_err:
|
||||
esp_apptrace_riscv_buffer_swap_unlock();
|
||||
return res;
|
||||
}
|
||||
|
||||
static esp_err_t esp_apptrace_riscv_buffer_swap_end(uint32_t new_block_id, uint32_t prev_block_len)
|
||||
{
|
||||
uint32_t ctrl_reg = s_tracing_ctrl[esp_cpu_get_core_id()].ctrl;
|
||||
uint32_t host_connected = ESP_APPTRACE_RISCV_HOST_CONNECT & ctrl_reg;
|
||||
s_tracing_ctrl[esp_cpu_get_core_id()].ctrl = ESP_APPTRACE_RISCV_BLOCK_ID(new_block_id) |
|
||||
host_connected | ESP_APPTRACE_RISCV_BLOCK_LEN(prev_block_len);
|
||||
esp_apptrace_riscv_buffer_swap_unlock();
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t esp_apptrace_riscv_buffer_swap(uint32_t new_block_id)
|
||||
{
|
||||
/* do nothing */
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static bool esp_apptrace_riscv_host_data_pending(void)
|
||||
{
|
||||
uint32_t ctrl_reg = s_tracing_ctrl[esp_cpu_get_core_id()].ctrl;
|
||||
// ESP_APPTRACE_LOGV("%s() 0x%x", __func__, ctrl_reg);
|
||||
return (ctrl_reg & ESP_APPTRACE_RISCV_HOST_DATA) ? true : false;
|
||||
}
|
||||
@@ -1,373 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*/
|
||||
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_cpu.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_app_trace_config.h"
|
||||
#include "esp_app_trace_membufs_proto.h"
|
||||
#include "esp_app_trace_port.h"
|
||||
#include "riscv/semihosting.h"
|
||||
|
||||
/** RISCV HW transport data */
|
||||
typedef struct {
|
||||
uint8_t inited; // initialization state flags for every core
|
||||
#if CONFIG_APPTRACE_LOCK_ENABLE
|
||||
esp_apptrace_lock_t lock; // sync lock
|
||||
#endif
|
||||
esp_apptrace_membufs_proto_data_t membufs;
|
||||
} esp_apptrace_riscv_data_t;
|
||||
|
||||
/** RISCV memory host iface control block */
|
||||
typedef struct {
|
||||
uint32_t ctrl;
|
||||
// - Guard field. If this register is not zero then CPU is changing this struct and
|
||||
// this guard field holds address of the instruction which application will execute when CPU finishes with those modifications.
|
||||
uint32_t stat;
|
||||
esp_apptrace_mem_block_t * mem_blocks;
|
||||
} esp_apptrace_riscv_ctrl_block_t;
|
||||
|
||||
#define ESP_APPTRACE_RISCV_BLOCK_LEN_MSK 0x7FFFUL
|
||||
#define ESP_APPTRACE_RISCV_BLOCK_LEN(_l_) ((_l_) & ESP_APPTRACE_RISCV_BLOCK_LEN_MSK)
|
||||
#define ESP_APPTRACE_RISCV_BLOCK_LEN_GET(_v_) ((_v_) & ESP_APPTRACE_RISCV_BLOCK_LEN_MSK)
|
||||
#define ESP_APPTRACE_RISCV_BLOCK_ID_MSK 0x7FUL
|
||||
#define ESP_APPTRACE_RISCV_BLOCK_ID(_id_) (((_id_) & ESP_APPTRACE_RISCV_BLOCK_ID_MSK) << 15)
|
||||
#define ESP_APPTRACE_RISCV_BLOCK_ID_GET(_v_) (((_v_) >> 15) & ESP_APPTRACE_RISCV_BLOCK_ID_MSK)
|
||||
#define ESP_APPTRACE_RISCV_HOST_DATA (1 << 22)
|
||||
#define ESP_APPTRACE_RISCV_HOST_CONNECT (1 << 23)
|
||||
|
||||
#define ESP_APPTRACE_RISCV_INITED(_hw_) ((_hw_)->inited & (1 << 0/*esp_cpu_get_core_id()*/))
|
||||
|
||||
const static char *TAG = "esp_apptrace";
|
||||
|
||||
#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE
|
||||
#define APPTRACE_DRAM_ATTR TCM_DRAM_ATTR
|
||||
#else
|
||||
#define APPTRACE_DRAM_ATTR
|
||||
#endif
|
||||
|
||||
static APPTRACE_DRAM_ATTR esp_apptrace_riscv_ctrl_block_t s_tracing_ctrl[CONFIG_FREERTOS_NUMBER_OF_CORES];
|
||||
|
||||
/* Advertises apptrace control block address to host.
|
||||
This function can be overridden with custom implementation,
|
||||
e.g. OpenOCD flasher stub use own implementation of it. */
|
||||
__attribute__((weak)) int esp_apptrace_advertise_ctrl_block(void *ctrl_block_addr)
|
||||
{
|
||||
if (!esp_cpu_dbgr_is_attached()) {
|
||||
return 0;
|
||||
}
|
||||
return (int) semihosting_call_noerrno(ESP_SEMIHOSTING_SYS_APPTRACE_INIT, (long*)ctrl_block_addr);
|
||||
}
|
||||
|
||||
/* Returns up buffers config.
|
||||
This function can be overridden with custom implementation,
|
||||
e.g. OpenOCD flasher stub use own implementation of it. */
|
||||
__attribute__((weak)) void esp_apptrace_get_up_buffers(esp_apptrace_mem_block_t mem_blocks_cfg[2])
|
||||
{
|
||||
static uint8_t s_mem_blocks[2][CONFIG_APPTRACE_BUF_SIZE];
|
||||
|
||||
mem_blocks_cfg[0].start = s_mem_blocks[0];
|
||||
mem_blocks_cfg[0].sz = CONFIG_APPTRACE_BUF_SIZE;
|
||||
mem_blocks_cfg[1].start = s_mem_blocks[1];
|
||||
mem_blocks_cfg[1].sz = CONFIG_APPTRACE_BUF_SIZE;
|
||||
}
|
||||
|
||||
static esp_err_t esp_apptrace_riscv_lock(void *hw_data, esp_apptrace_tmo_t *tmo)
|
||||
{
|
||||
#if CONFIG_APPTRACE_LOCK_ENABLE
|
||||
esp_apptrace_riscv_data_t *riscv_data = hw_data;
|
||||
esp_err_t ret = esp_apptrace_lock_take(&riscv_data->lock, tmo);
|
||||
if (ret != ESP_OK) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
#endif
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t esp_apptrace_riscv_unlock(void *hw_data)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
#if CONFIG_APPTRACE_LOCK_ENABLE
|
||||
esp_apptrace_riscv_data_t *riscv_data = hw_data;
|
||||
ret = esp_apptrace_lock_give(&riscv_data->lock);
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*****************************************************************************************/
|
||||
/***************************** Apptrace HW iface *****************************************/
|
||||
/*****************************************************************************************/
|
||||
|
||||
static esp_err_t esp_apptrace_riscv_init(void *hw_data, const esp_apptrace_config_t *config)
|
||||
{
|
||||
esp_apptrace_riscv_data_t *riscv_data = hw_data;
|
||||
|
||||
/* esp_apptrace_riscv_init() is called on every core, so ensure to do main initialization only once */
|
||||
int core_id = esp_cpu_get_core_id();
|
||||
if (core_id == 0) {
|
||||
esp_apptrace_mem_block_t mem_blocks_cfg[2];
|
||||
esp_apptrace_get_up_buffers(mem_blocks_cfg);
|
||||
riscv_data->membufs.header_size = ESP_APPTRACE_HEADER_SIZE_32;
|
||||
esp_err_t res = esp_apptrace_membufs_init(&riscv_data->membufs, mem_blocks_cfg);
|
||||
if (res != ESP_OK) {
|
||||
ESP_APPTRACE_LOGE("Failed to init membufs proto (%d)!", res);
|
||||
return res;
|
||||
}
|
||||
#if CONFIG_APPTRACE_LOCK_ENABLE
|
||||
esp_apptrace_lock_init(&riscv_data->lock);
|
||||
#endif
|
||||
}
|
||||
riscv_data->inited |= 1 << core_id;
|
||||
ESP_APPTRACE_LOGI("Apptrace initialized on CPU%d. Tracing control block @ %p.", core_id, &s_tracing_ctrl[core_id]);
|
||||
s_tracing_ctrl[core_id].mem_blocks = riscv_data->membufs.blocks;
|
||||
for (int i = 0; i < 2; i++) {
|
||||
ESP_APPTRACE_LOGD("Mem buf[%d] %" PRIu32 " bytes @ %p (%p/%p)", i,
|
||||
s_tracing_ctrl[core_id].mem_blocks[i].sz, s_tracing_ctrl[core_id].mem_blocks[i].start,
|
||||
&(s_tracing_ctrl[core_id].mem_blocks[i].start), &(s_tracing_ctrl[core_id].mem_blocks[i].sz));
|
||||
}
|
||||
// notify host about control block address
|
||||
int __attribute__((unused)) res = esp_apptrace_advertise_ctrl_block(&s_tracing_ctrl[core_id]);
|
||||
assert(res == 0 && "Failed to send config to host!");
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static uint8_t *esp_apptrace_riscv_up_buffer_get(void *hw_data, uint32_t size, esp_apptrace_tmo_t *tmo)
|
||||
{
|
||||
esp_apptrace_riscv_data_t *riscv_data = hw_data;
|
||||
|
||||
if (!ESP_APPTRACE_RISCV_INITED(riscv_data)) {
|
||||
return NULL;
|
||||
}
|
||||
esp_err_t res = esp_apptrace_riscv_lock(riscv_data, tmo);
|
||||
if (res != ESP_OK) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uint8_t *ptr = esp_apptrace_membufs_up_buffer_get(&riscv_data->membufs, size, tmo);
|
||||
|
||||
// now we can safely unlock apptrace to allow other tasks/ISRs to get other buffers and write their data
|
||||
if (esp_apptrace_riscv_unlock(riscv_data) != ESP_OK) {
|
||||
assert(false && "Failed to unlock apptrace data!");
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
|
||||
static esp_err_t esp_apptrace_riscv_up_buffer_put(void *hw_data, uint8_t *ptr, esp_apptrace_tmo_t *tmo)
|
||||
{
|
||||
esp_apptrace_riscv_data_t *riscv_data = hw_data;
|
||||
|
||||
if (!ESP_APPTRACE_RISCV_INITED(riscv_data)) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
// Can avoid locking because esp_apptrace_membufs_up_buffer_put() just modifies buffer's header
|
||||
esp_err_t res = esp_apptrace_membufs_up_buffer_put(&riscv_data->membufs, ptr, tmo);
|
||||
return res;
|
||||
}
|
||||
|
||||
static void esp_apptrace_riscv_down_buffer_config(void *hw_data, uint8_t *buf, uint32_t size)
|
||||
{
|
||||
esp_apptrace_riscv_data_t *riscv_data = hw_data;
|
||||
|
||||
if (!ESP_APPTRACE_RISCV_INITED(riscv_data)) {
|
||||
return;
|
||||
}
|
||||
esp_apptrace_membufs_down_buffer_config(&riscv_data->membufs, buf, size);
|
||||
}
|
||||
|
||||
static uint8_t *esp_apptrace_riscv_down_buffer_get(void *hw_data, uint32_t *size, esp_apptrace_tmo_t *tmo)
|
||||
{
|
||||
esp_apptrace_riscv_data_t *riscv_data = hw_data;
|
||||
|
||||
if (!ESP_APPTRACE_RISCV_INITED(riscv_data)) {
|
||||
return NULL;
|
||||
}
|
||||
esp_err_t res = esp_apptrace_riscv_lock(riscv_data, tmo);
|
||||
if (res != ESP_OK) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uint8_t *ptr = esp_apptrace_membufs_down_buffer_get(&riscv_data->membufs, size, tmo);
|
||||
|
||||
// now we can safely unlock apptrace to allow other tasks/ISRs to get other buffers and write their data
|
||||
if (esp_apptrace_riscv_unlock(hw_data) != ESP_OK) {
|
||||
assert(false && "Failed to unlock apptrace data!");
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
|
||||
static esp_err_t esp_apptrace_riscv_down_buffer_put(void *hw_data, uint8_t *ptr, esp_apptrace_tmo_t *tmo)
|
||||
{
|
||||
esp_apptrace_riscv_data_t *riscv_data = hw_data;
|
||||
|
||||
if (!ESP_APPTRACE_RISCV_INITED(riscv_data)) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
// Can avoid locking because esp_apptrace_membufs_down_buffer_put() does nothing
|
||||
/*esp_err_t res = esp_apptrace_riscv_lock(hw_data, tmo);
|
||||
if (res != ESP_OK) {
|
||||
return res;
|
||||
}*/
|
||||
|
||||
esp_err_t res = esp_apptrace_membufs_down_buffer_put(&riscv_data->membufs, ptr, tmo);
|
||||
|
||||
// now we can safely unlock apptrace to allow other tasks/ISRs to get other buffers and write their data
|
||||
/*if (esp_apptrace_riscv_unlock(hw_data) != ESP_OK) {
|
||||
assert(false && "Failed to unlock apptrace data!");
|
||||
}*/
|
||||
return res;
|
||||
}
|
||||
|
||||
static bool esp_apptrace_riscv_host_is_connected(void *hw_data)
|
||||
{
|
||||
esp_apptrace_riscv_data_t *riscv_data = hw_data;
|
||||
|
||||
if (!ESP_APPTRACE_RISCV_INITED(riscv_data)) {
|
||||
return false;
|
||||
}
|
||||
return s_tracing_ctrl[esp_cpu_get_core_id()].ctrl & ESP_APPTRACE_RISCV_HOST_CONNECT ? true : false;
|
||||
}
|
||||
|
||||
static esp_err_t esp_apptrace_riscv_flush_nolock(void *hw_data, uint32_t min_sz, esp_apptrace_tmo_t *tmo)
|
||||
{
|
||||
esp_apptrace_riscv_data_t *riscv_data = hw_data;
|
||||
|
||||
if (!ESP_APPTRACE_RISCV_INITED(riscv_data)) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
return esp_apptrace_membufs_flush_nolock(&riscv_data->membufs, min_sz, tmo);
|
||||
}
|
||||
|
||||
static esp_err_t esp_apptrace_riscv_flush(void *hw_data, esp_apptrace_tmo_t *tmo)
|
||||
{
|
||||
esp_apptrace_riscv_data_t *riscv_data = hw_data;
|
||||
|
||||
if (!ESP_APPTRACE_RISCV_INITED(riscv_data)) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
esp_err_t res = esp_apptrace_riscv_lock(riscv_data, tmo);
|
||||
if (res != ESP_OK) {
|
||||
return res;
|
||||
}
|
||||
|
||||
res = esp_apptrace_membufs_flush_nolock(&riscv_data->membufs, 0, tmo);
|
||||
|
||||
// now we can safely unlock apptrace to allow other tasks/ISRs to get other buffers and write their data
|
||||
if (esp_apptrace_riscv_unlock(riscv_data) != ESP_OK) {
|
||||
assert(false && "Failed to unlock apptrace data!");
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/*****************************************************************************************/
|
||||
/************************** Membufs proto HW iface ***************************************/
|
||||
/*****************************************************************************************/
|
||||
|
||||
static inline void esp_apptrace_riscv_buffer_swap_lock(void)
|
||||
{
|
||||
extern uint32_t __esp_apptrace_riscv_updated;
|
||||
|
||||
// indicate to host that we are about to update.
|
||||
// this is used only to place CPU into streaming mode at tracing startup
|
||||
// before starting streaming host can halt us after we read ESP_APPTRACE_RISCV_CTRL_REG and before we updated it
|
||||
// HACK: in this case host will set breakpoint just after ESP_APPTRACE_RISCV_CTRL_REG update,
|
||||
// here we set address to set bp at
|
||||
// enter ERI update critical section
|
||||
s_tracing_ctrl[esp_cpu_get_core_id()].stat = (uint32_t)&__esp_apptrace_riscv_updated;
|
||||
}
|
||||
|
||||
static __attribute__((noinline)) void esp_apptrace_riscv_buffer_swap_unlock(void)
|
||||
{
|
||||
// exit ERI update critical section
|
||||
s_tracing_ctrl[esp_cpu_get_core_id()].stat = 0;
|
||||
// TODO: currently host sets breakpoint, use break instruction to stop;
|
||||
// it will allow to use ESP_APPTRACE_RISCV_STAT_REG for other purposes
|
||||
asm volatile(
|
||||
" .global __esp_apptrace_riscv_updated\n"
|
||||
"__esp_apptrace_riscv_updated:\n"); // host will set bp here to resolve collision at streaming start
|
||||
}
|
||||
|
||||
static esp_err_t esp_apptrace_riscv_buffer_swap_start(uint32_t curr_block_id)
|
||||
{
|
||||
esp_err_t res = ESP_OK;
|
||||
|
||||
esp_apptrace_riscv_buffer_swap_lock();
|
||||
|
||||
uint32_t ctrl_reg = s_tracing_ctrl[esp_cpu_get_core_id()].ctrl;
|
||||
uint32_t host_connected = ESP_APPTRACE_RISCV_HOST_CONNECT & ctrl_reg;
|
||||
if (host_connected) {
|
||||
uint32_t acked_block = ESP_APPTRACE_RISCV_BLOCK_ID_GET(ctrl_reg);
|
||||
uint32_t host_to_read = ESP_APPTRACE_RISCV_BLOCK_LEN_GET(ctrl_reg);
|
||||
if (host_to_read != 0 || acked_block != (curr_block_id & ESP_APPTRACE_RISCV_BLOCK_ID_MSK)) {
|
||||
ESP_APPTRACE_LOGD("[%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_RISCV_BLOCK_ID_MSK, curr_block_id);
|
||||
res = ESP_ERR_NO_MEM;
|
||||
goto _on_err;
|
||||
}
|
||||
}
|
||||
return ESP_OK;
|
||||
_on_err:
|
||||
esp_apptrace_riscv_buffer_swap_unlock();
|
||||
return res;
|
||||
}
|
||||
|
||||
static esp_err_t esp_apptrace_riscv_buffer_swap_end(uint32_t new_block_id, uint32_t prev_block_len)
|
||||
{
|
||||
uint32_t ctrl_reg = s_tracing_ctrl[esp_cpu_get_core_id()].ctrl;
|
||||
uint32_t host_connected = ESP_APPTRACE_RISCV_HOST_CONNECT & ctrl_reg;
|
||||
s_tracing_ctrl[esp_cpu_get_core_id()].ctrl = ESP_APPTRACE_RISCV_BLOCK_ID(new_block_id) |
|
||||
host_connected | ESP_APPTRACE_RISCV_BLOCK_LEN(prev_block_len);
|
||||
esp_apptrace_riscv_buffer_swap_unlock();
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t esp_apptrace_riscv_buffer_swap(uint32_t new_block_id, uint32_t prev_block_len)
|
||||
{
|
||||
/* do nothing */
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static bool esp_apptrace_riscv_host_data_pending(void)
|
||||
{
|
||||
uint32_t ctrl_reg = s_tracing_ctrl[esp_cpu_get_core_id()].ctrl;
|
||||
// ESP_APPTRACE_LOGV("%s() 0x%x", __func__, ctrl_reg);
|
||||
return (ctrl_reg & ESP_APPTRACE_RISCV_HOST_DATA) ? true : false;
|
||||
}
|
||||
|
||||
static void esp_apptrace_riscv_set_header_size(void *hw_data, esp_apptrace_header_size_t header_size)
|
||||
{
|
||||
esp_apptrace_riscv_data_t *riscv_data = hw_data;
|
||||
riscv_data->membufs.header_size = header_size;
|
||||
}
|
||||
|
||||
esp_apptrace_hw_t *esp_apptrace_jtag_hw_get(void **data)
|
||||
{
|
||||
static esp_apptrace_membufs_proto_hw_t s_trace_proto_hw = {
|
||||
.swap_start = esp_apptrace_riscv_buffer_swap_start,
|
||||
.swap = esp_apptrace_riscv_buffer_swap,
|
||||
.swap_end = esp_apptrace_riscv_buffer_swap_end,
|
||||
.host_data_pending = esp_apptrace_riscv_host_data_pending,
|
||||
};
|
||||
static esp_apptrace_riscv_data_t s_trace_hw_data = {
|
||||
.membufs = {
|
||||
.hw = &s_trace_proto_hw,
|
||||
},
|
||||
};
|
||||
static esp_apptrace_hw_t s_trace_hw = {
|
||||
.init = esp_apptrace_riscv_init,
|
||||
.get_up_buffer = esp_apptrace_riscv_up_buffer_get,
|
||||
.put_up_buffer = esp_apptrace_riscv_up_buffer_put,
|
||||
.flush_up_buffer_nolock = esp_apptrace_riscv_flush_nolock,
|
||||
.flush_up_buffer = esp_apptrace_riscv_flush,
|
||||
.down_buffer_config = esp_apptrace_riscv_down_buffer_config,
|
||||
.get_down_buffer = esp_apptrace_riscv_down_buffer_get,
|
||||
.put_down_buffer = esp_apptrace_riscv_down_buffer_put,
|
||||
.host_is_connected = esp_apptrace_riscv_host_is_connected,
|
||||
.set_header_size = esp_apptrace_riscv_set_header_size,
|
||||
};
|
||||
*data = &s_trace_hw_data;
|
||||
return &s_trace_hw;
|
||||
}
|
||||
552
components/app_trace/port/xtensa/port.c
Normal file
552
components/app_trace/port/xtensa/port.c
Normal file
@@ -0,0 +1,552 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*/
|
||||
|
||||
//
|
||||
// How It Works
|
||||
// ************
|
||||
|
||||
// 1. Components Overview
|
||||
// ======================
|
||||
|
||||
// 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
|
||||
// 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
|
||||
// by means of reading/writing TRAX registers via JTAG. Blocks muxing is configurable at run-time and allows switching trace memory blocks between
|
||||
// accessors in round-robin fashion so they can read/write separate memory blocks without disturbing each other.
|
||||
// This module implements application tracing feature based on above mechanisms. It allows to transfer arbitrary user data to/from
|
||||
// host via JTAG with minimal impact on system performance. This module is implied to be used in the following tracing scheme.
|
||||
|
||||
// ------>------ ----- (host components) -----
|
||||
// | | | |
|
||||
// ------------------- ----------------------- ----------------------- ---------------- ------ --------- -----------------
|
||||
// |trace data source|-->|target tracing module|<--->|TRAX_MEM0 | TRAX_MEM1|---->|TRAX_DATA_REGS|<-->|JTAG|<--->|OpenOCD|-->|trace data sink|
|
||||
// ------------------- ----------------------- ----------------------- ---------------- ------ --------- -----------------
|
||||
// | | | |
|
||||
// | ------<------ ---------------- |
|
||||
// |<------------------------------------------->|TRAX_CTRL_REGS|<---->|
|
||||
// ----------------
|
||||
|
||||
// In general tracing goes in the following way. User application requests tracing module to send some data by calling esp_apptrace_buffer_get(),
|
||||
// module allocates necessary buffer in current input trace block. Then user fills received buffer with data and calls esp_apptrace_buffer_put().
|
||||
// When current input trace block is filled with app data it is exposed to host and the second block becomes input one and buffer filling restarts.
|
||||
// While target application fills one TRAX block host reads another one via JTAG.
|
||||
// This module also allows communication in the opposite direction: from host to target. As it was said ESP32 and host can access different TRAX blocks
|
||||
// simultaneously, so while target writes trace data to one block host can write its own data (e.g. tracing commands) to another one then when
|
||||
// blocks are switched host receives trace data and target receives data written by host application. Target user application can read host data
|
||||
// by calling esp_apptrace_read() API.
|
||||
// To control buffer switching and for other communication purposes this implementation uses some TRAX registers. It is safe since HW TRAX tracing
|
||||
// can not be used along with application tracing feature so these registers are freely readable/writeable via JTAG from host and via ERI from ESP32 cores.
|
||||
// Overhead of this implementation on target CPU is produced only by allocating/managing buffers and copying of data.
|
||||
// On the host side special OpenOCD command must be used to read trace data.
|
||||
|
||||
// 2. TRAX Registers layout
|
||||
// ========================
|
||||
|
||||
// This module uses two TRAX HW registers and one Performance Monitor register 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.
|
||||
// Host writes zero to this field when it finishes reading exposed block;
|
||||
// 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.
|
||||
|
||||
// 3. Modes of operation
|
||||
// =====================
|
||||
|
||||
// This module supports two modes of operation:
|
||||
// - Post-mortem mode. This is the default mode. In this mode application tracing module does not check whether host has read all the data from block
|
||||
// exposed to it and switches block in any case. The mode does not need host interaction for operation and so can be useful when only the latest
|
||||
// trace data are necessary, e.g. for analyzing crashes. On panic the latest data from current input block are exposed to host and host can read them.
|
||||
// It can happen that system panic occurs when there are very small amount of data which are not exposed to host yet (e.g. crash just after the
|
||||
// TRAX block switch). In this case the previous 16KB of collected data will be dropped and host will see the latest, but very small piece of trace.
|
||||
// It can be insufficient to diagnose the problem. To avoid such situations there is menuconfig option
|
||||
// CONFIG_APPTRACE_POSTMORTEM_FLUSH_THRESH
|
||||
// which controls the threshold for flushing data in case of panic.
|
||||
// - Streaming mode. Tracing module enters this mode when host connects to target and sets respective bits in control registers (per core).
|
||||
// In this mode before switching the block tracing module waits for the host to read all the data from the previously exposed block.
|
||||
// On panic tracing module also waits (timeout is configured via menuconfig via CONFIG_APPTRACE_ONPANIC_HOST_FLUSH_TMO) for the host to read all data.
|
||||
|
||||
// 4. Communication Protocol
|
||||
// =========================
|
||||
|
||||
// 4.1 Trace Memory Blocks
|
||||
// -----------------------
|
||||
|
||||
// Communication is controlled via special register. Host periodically polls control register on each core to find out if there are any data available.
|
||||
// When current input memory block is filled it is exposed to host and 'block_len' and 'block_id' fields are updated in the control register.
|
||||
// Host reads new register value and according to it's value starts reading data from exposed block. Meanwhile target starts filling another trace block.
|
||||
// When host finishes reading the block it clears 'block_len' field in control register indicating to the target that it is ready to accept the next one.
|
||||
// If the host has some data to transfer to the target it writes them to trace memory block before clearing 'block_len' field. Then it sets
|
||||
// 'host_data_present' bit and clears 'block_len' field in control register. Upon every block switch target checks 'host_data_present' bit and if it is set
|
||||
// reads them to down buffer before writing any trace data to switched TRAX block.
|
||||
|
||||
// 4.2 User Data Chunks Level
|
||||
// --------------------------
|
||||
|
||||
// Since trace memory block is shared between user data chunks and data copying is performed on behalf of the API user (in its normal context) in
|
||||
// multithreading environment it can happen that task/ISR which copies data is preempted by another high prio task/ISR. So it is possible situation
|
||||
// that task/ISR will fail to complete filling its data chunk before the whole trace block is exposed to the host. To handle such conditions tracing
|
||||
// module prepends all user data chunks with header which contains allocated buffer size and actual data length within it. OpenOCD command
|
||||
// which reads application traces reports error when it reads incomplete user data block.
|
||||
// Data which are transffered from host to target are also prepended with a header. Down channel data header is simple and consists of one two bytes field
|
||||
// containing length of host data following the header.
|
||||
|
||||
// 4.3 Data Buffering
|
||||
// ------------------
|
||||
|
||||
// It takes some time for the host to read TRAX memory block via JTAG. In streaming mode it can happen that target has filled its TRAX block, but host
|
||||
// has not completed reading of the previous one yet. So in this case time critical tracing calls (which can not be delayed for too long time due to
|
||||
// the lack of free memory in TRAX block) can be dropped. To avoid such scenarios tracing module implements data buffering. Buffered data will be sent
|
||||
// to the host later when TRAX block switch occurs. The maximum size of the buffered data is controlled by menuconfig option
|
||||
// CONFIG_APPTRACE_PENDING_DATA_SIZE_MAX.
|
||||
|
||||
// 4.4 Target Connection/Disconnection
|
||||
// -----------------------------------
|
||||
|
||||
// When host is going to start tracing in streaming mode it needs to put both ESP32 cores into initial state when 'host connected' bit is set
|
||||
// on both cores. To accomplish this host halts both cores and sets this bit in TRAX registers. But target code can be halted in state when it has read control
|
||||
// register but has not updated its value. To handle such situations target code indicates to the host that it is updating control register by writing
|
||||
// non-zero value to status register. Actually it writes address of the instruction which it will execute when it finishes with
|
||||
// the registers update. When target is halted during control register update host sets breakpoint at the address from status register and resumes CPU.
|
||||
// After target code finishes with register update it is halted on breakpoint, host detects it and safely sets 'host connected' bit. When both cores
|
||||
// are set up they are resumed. Tracing starts without further intrusion into CPUs work.
|
||||
// When host is going to stop tracing in streaming mode it needs to disconnect targets. Disconnection process is done using the same algorithm
|
||||
// as for connecting, but 'host connected' bits are cleared on ESP32 cores.
|
||||
|
||||
// 5. Module Access Synchronization
|
||||
// ================================
|
||||
|
||||
// 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
|
||||
// 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.
|
||||
// When low prio task takes mutex and enables local IRQs gets preempted by high prio task which in its turn can try to acquire mutex using infinite timeout.
|
||||
// So no local task switch occurs when mutex is locked. But this does not apply to tasks on another CPU.
|
||||
// WARNING: Priority inversion can happen when low prio task works on one CPU and medium and high prio tasks work on another.
|
||||
// WARNING: Care must be taken when selecting timeout values for trace calls from ISRs. Tracing module does not care about watchdogs when waiting
|
||||
// on internal locks and for host to complete previous block reading, so if timeout value exceeds watchdog's one it can lead to the system reboot.
|
||||
|
||||
// 6. Timeouts
|
||||
// ===========
|
||||
|
||||
// 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.
|
||||
// - 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
|
||||
// time exceeds specified timeout value operation is canceled and ESP_ERR_TIMEOUT code is returned.
|
||||
#include "sdkconfig.h"
|
||||
#include "soc/soc.h"
|
||||
#include "soc/dport_reg.h"
|
||||
#include "soc/tracemem_config.h"
|
||||
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
|
||||
#include "soc/sensitive_reg.h"
|
||||
#endif
|
||||
#include "eri.h"
|
||||
#include "esp_private/trax.h"
|
||||
#include "esp_cpu.h"
|
||||
#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)
|
||||
#define ESP_APPTRACE_TRAX_BLOCK_LEN_GET(_v_) ((_v_) & ESP_APPTRACE_TRAX_BLOCK_LEN_MSK)
|
||||
#define ESP_APPTRACE_TRAX_BLOCK_ID_MSK 0x7FUL
|
||||
#define ESP_APPTRACE_TRAX_BLOCK_ID(_id_) (((_id_) & ESP_APPTRACE_TRAX_BLOCK_ID_MSK) << 15)
|
||||
#define ESP_APPTRACE_TRAX_BLOCK_ID_GET(_v_) (((_v_) >> 15) & ESP_APPTRACE_TRAX_BLOCK_ID_MSK)
|
||||
#define ESP_APPTRACE_TRAX_HOST_DATA (1 << 22)
|
||||
#define ESP_APPTRACE_TRAX_HOST_CONNECT (1 << 23)
|
||||
|
||||
#define ESP_APPTRACE_TRAX_INITED(_hw_) ((_hw_)->inited & (1 << esp_cpu_get_core_id()))
|
||||
|
||||
#define ESP_APPTRACE_TRAX_BLOCK_SIZE (0x4000UL)
|
||||
|
||||
/** TRAX HW transport data */
|
||||
typedef struct {
|
||||
uint8_t inited;
|
||||
#if CONFIG_APPTRACE_LOCK_ENABLE
|
||||
esp_apptrace_lock_t lock; // sync lock
|
||||
#endif
|
||||
esp_apptrace_membufs_proto_data_t membufs;
|
||||
} esp_apptrace_trax_data_t;
|
||||
|
||||
|
||||
static esp_err_t esp_apptrace_trax_init(esp_apptrace_trax_data_t *hw_data);
|
||||
static esp_err_t esp_apptrace_trax_flush(esp_apptrace_trax_data_t *hw_data, esp_apptrace_tmo_t *tmo);
|
||||
static esp_err_t esp_apptrace_trax_flush_nolock(esp_apptrace_trax_data_t *hw_data, uint32_t min_sz, esp_apptrace_tmo_t *tmo);
|
||||
static uint8_t *esp_apptrace_trax_up_buffer_get(esp_apptrace_trax_data_t *hw_data, uint32_t size, esp_apptrace_tmo_t *tmo);
|
||||
static esp_err_t esp_apptrace_trax_up_buffer_put(esp_apptrace_trax_data_t *hw_data, uint8_t *ptr, esp_apptrace_tmo_t *tmo);
|
||||
static void esp_apptrace_trax_down_buffer_config(esp_apptrace_trax_data_t *hw_data, uint8_t *buf, uint32_t size);
|
||||
static uint8_t *esp_apptrace_trax_down_buffer_get(esp_apptrace_trax_data_t *hw_data, uint32_t *size, esp_apptrace_tmo_t *tmo);
|
||||
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);
|
||||
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);
|
||||
|
||||
|
||||
const static char *TAG = "esp_apptrace";
|
||||
|
||||
static uint8_t * const s_trax_blocks[] = {
|
||||
(uint8_t *)TRACEMEM_BLK0_ADDR,
|
||||
(uint8_t *)TRACEMEM_BLK1_ADDR
|
||||
};
|
||||
|
||||
esp_apptrace_hw_t *esp_apptrace_jtag_hw_get(void **data)
|
||||
{
|
||||
#if CONFIG_APPTRACE_DEST_JTAG
|
||||
static esp_apptrace_membufs_proto_hw_t s_trax_proto_hw = {
|
||||
.swap_start = esp_apptrace_trax_buffer_swap_start,
|
||||
.swap = esp_apptrace_trax_buffer_swap,
|
||||
.swap_end = esp_apptrace_trax_buffer_swap_end,
|
||||
.host_data_pending = esp_apptrace_trax_host_data_pending,
|
||||
};
|
||||
static esp_apptrace_trax_data_t s_trax_hw_data = {
|
||||
.membufs = {
|
||||
.hw = &s_trax_proto_hw,
|
||||
},
|
||||
};
|
||||
static esp_apptrace_hw_t s_trax_hw = {
|
||||
.init = (esp_err_t (*)(void *))esp_apptrace_trax_init,
|
||||
.get_up_buffer = (uint8_t *(*)(void *, uint32_t, esp_apptrace_tmo_t *))esp_apptrace_trax_up_buffer_get,
|
||||
.put_up_buffer = (esp_err_t (*)(void *, uint8_t *, esp_apptrace_tmo_t *))esp_apptrace_trax_up_buffer_put,
|
||||
.flush_up_buffer_nolock = (esp_err_t (*)(void *, uint32_t, esp_apptrace_tmo_t *))esp_apptrace_trax_flush_nolock,
|
||||
.flush_up_buffer = (esp_err_t (*)(void *, esp_apptrace_tmo_t *))esp_apptrace_trax_flush,
|
||||
.down_buffer_config = (void (*)(void *, uint8_t *, uint32_t ))esp_apptrace_trax_down_buffer_config,
|
||||
.get_down_buffer = (uint8_t *(*)(void *, uint32_t *, esp_apptrace_tmo_t *))esp_apptrace_trax_down_buffer_get,
|
||||
.put_down_buffer = (esp_err_t (*)(void *, uint8_t *, esp_apptrace_tmo_t *))esp_apptrace_trax_down_buffer_put,
|
||||
.host_is_connected = (bool (*)(void *))esp_apptrace_trax_host_is_connected,
|
||||
};
|
||||
*data = &s_trax_hw_data;
|
||||
return &s_trax_hw;
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
static esp_err_t esp_apptrace_trax_lock(esp_apptrace_trax_data_t *hw_data, esp_apptrace_tmo_t *tmo)
|
||||
{
|
||||
#if CONFIG_APPTRACE_LOCK_ENABLE
|
||||
esp_err_t ret = esp_apptrace_lock_take(&hw_data->lock, tmo);
|
||||
if (ret != ESP_OK) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
#endif
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t esp_apptrace_trax_unlock(esp_apptrace_trax_data_t *hw_data)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
#if CONFIG_APPTRACE_LOCK_ENABLE
|
||||
ret = esp_apptrace_lock_give(&hw_data->lock);
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline void esp_apptrace_trax_hw_init(void)
|
||||
{
|
||||
// Stop trace, if any (on the current CPU)
|
||||
eri_write(ERI_TRAX_TRAXCTRL, TRAXCTRL_TRSTP);
|
||||
eri_write(ERI_TRAX_TRAXCTRL, TRAXCTRL_TMEN);
|
||||
eri_write(ESP_APPTRACE_TRAX_CTRL_REG, ESP_APPTRACE_TRAX_BLOCK_ID(0));
|
||||
// this is for OpenOCD to let him know where stub entries vector is resided
|
||||
// must be read by host before any transfer using TRAX
|
||||
eri_write(ESP_APPTRACE_TRAX_STAT_REG, 0);
|
||||
|
||||
ESP_APPTRACE_LOGI("Initialized TRAX on CPU%d", esp_cpu_get_core_id());
|
||||
}
|
||||
|
||||
static inline void esp_apptrace_trax_select_memory_block(int block_num)
|
||||
{
|
||||
// select memory block to be exposed to the TRAX module (accessed by host)
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
DPORT_WRITE_PERI_REG(DPORT_TRACEMEM_MUX_MODE_REG, block_num ? TRACEMEM_MUX_BLK0_ONLY : TRACEMEM_MUX_BLK1_ONLY);
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||
WRITE_PERI_REG(DPORT_PMS_OCCUPY_3_REG, block_num ? BIT(TRACEMEM_MUX_BLK0_NUM-4) : BIT(TRACEMEM_MUX_BLK1_NUM-4));
|
||||
#elif CONFIG_IDF_TARGET_ESP32S3
|
||||
// select memory block to be exposed to the TRAX module (accessed by host)
|
||||
uint32_t block_bits = block_num ? TRACEMEM_CORE0_MUX_BLK_BITS(TRACEMEM_MUX_BLK0_NUM)
|
||||
: TRACEMEM_CORE0_MUX_BLK_BITS(TRACEMEM_MUX_BLK1_NUM);
|
||||
block_bits |= block_num ? TRACEMEM_CORE1_MUX_BLK_BITS(TRACEMEM_MUX_BLK0_NUM)
|
||||
: TRACEMEM_CORE1_MUX_BLK_BITS(TRACEMEM_MUX_BLK1_NUM);
|
||||
ESP_EARLY_LOGV(TAG, "Select block %d @ %p (bits 0x%" PRIx32 ")", block_num, s_trax_blocks[block_num], block_bits);
|
||||
DPORT_WRITE_PERI_REG(SENSITIVE_INTERNAL_SRAM_USAGE_2_REG, block_bits);
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void esp_apptrace_trax_memory_enable(void)
|
||||
{
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
/* Enable trace memory on PRO CPU */
|
||||
DPORT_WRITE_PERI_REG(DPORT_PRO_TRACEMEM_ENA_REG, DPORT_PRO_TRACEMEM_ENA_M);
|
||||
#if CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE == 0
|
||||
/* Enable trace memory on APP CPU */
|
||||
DPORT_WRITE_PERI_REG(DPORT_APP_TRACEMEM_ENA_REG, DPORT_APP_TRACEMEM_ENA_M);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
/*****************************************************************************************/
|
||||
/***************************** Apptrace HW iface *****************************************/
|
||||
/*****************************************************************************************/
|
||||
|
||||
static esp_err_t esp_apptrace_trax_init(esp_apptrace_trax_data_t *hw_data)
|
||||
{
|
||||
int core_id = esp_cpu_get_core_id();
|
||||
|
||||
// 'esp_apptrace_trax_init()' is called on every core, so ensure to do main initialization only once
|
||||
if (core_id == 0) {
|
||||
esp_apptrace_mem_block_t mem_blocks_cfg[2] = {
|
||||
{
|
||||
.start = s_trax_blocks[0],
|
||||
.sz = ESP_APPTRACE_TRAX_BLOCK_SIZE
|
||||
},
|
||||
{
|
||||
.start = s_trax_blocks[1],
|
||||
.sz = ESP_APPTRACE_TRAX_BLOCK_SIZE
|
||||
},
|
||||
};
|
||||
esp_err_t res = esp_apptrace_membufs_init(&hw_data->membufs, mem_blocks_cfg);
|
||||
if (res != ESP_OK) {
|
||||
ESP_APPTRACE_LOGE("Failed to init membufs proto (%d)!", res);
|
||||
return res;
|
||||
}
|
||||
#if CONFIG_APPTRACE_LOCK_ENABLE
|
||||
esp_apptrace_lock_init(&hw_data->lock);
|
||||
#endif
|
||||
esp_apptrace_trax_memory_enable();
|
||||
esp_apptrace_trax_select_memory_block(0);
|
||||
}
|
||||
// init TRAX on this CPU
|
||||
esp_apptrace_trax_hw_init();
|
||||
hw_data->inited |= 1 << core_id;
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static uint8_t *esp_apptrace_trax_up_buffer_get(esp_apptrace_trax_data_t *hw_data, uint32_t size, esp_apptrace_tmo_t *tmo)
|
||||
{
|
||||
uint8_t *ptr;
|
||||
|
||||
if (!ESP_APPTRACE_TRAX_INITED(hw_data)) {
|
||||
return NULL;
|
||||
}
|
||||
esp_err_t res = esp_apptrace_trax_lock(hw_data, tmo);
|
||||
if (res != ESP_OK) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ptr = esp_apptrace_membufs_up_buffer_get(&hw_data->membufs, size, tmo);
|
||||
|
||||
// now we can safely unlock apptrace to allow other tasks/ISRs to get other buffers and write their data
|
||||
if (esp_apptrace_trax_unlock(hw_data) != ESP_OK) {
|
||||
assert(false && "Failed to unlock apptrace data!");
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
|
||||
static esp_err_t esp_apptrace_trax_up_buffer_put(esp_apptrace_trax_data_t *hw_data, uint8_t *ptr, esp_apptrace_tmo_t *tmo)
|
||||
{
|
||||
if (!ESP_APPTRACE_TRAX_INITED(hw_data)) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
// Can avoid locking because esp_apptrace_membufs_up_buffer_put() just modifies buffer's header
|
||||
esp_err_t res = esp_apptrace_membufs_up_buffer_put(&hw_data->membufs, ptr, tmo);
|
||||
return res;
|
||||
}
|
||||
|
||||
static void esp_apptrace_trax_down_buffer_config(esp_apptrace_trax_data_t *hw_data, uint8_t *buf, uint32_t size)
|
||||
{
|
||||
if (!ESP_APPTRACE_TRAX_INITED(hw_data)) {
|
||||
return;
|
||||
}
|
||||
esp_apptrace_membufs_down_buffer_config(&hw_data->membufs, buf, size);
|
||||
}
|
||||
|
||||
static uint8_t *esp_apptrace_trax_down_buffer_get(esp_apptrace_trax_data_t *hw_data, uint32_t *size, esp_apptrace_tmo_t *tmo)
|
||||
{
|
||||
uint8_t *ptr;
|
||||
|
||||
if (!ESP_APPTRACE_TRAX_INITED(hw_data)) {
|
||||
return NULL;
|
||||
}
|
||||
esp_err_t res = esp_apptrace_trax_lock(hw_data, tmo);
|
||||
if (res != ESP_OK) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ptr = esp_apptrace_membufs_down_buffer_get(&hw_data->membufs, size, tmo);
|
||||
|
||||
// now we can safely unlock apptrace to allow other tasks/ISRs to get other buffers and write their data
|
||||
if (esp_apptrace_trax_unlock(hw_data) != ESP_OK) {
|
||||
assert(false && "Failed to unlock apptrace data!");
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
if (!ESP_APPTRACE_TRAX_INITED(hw_data)) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
// Can avoid locking because esp_apptrace_membufs_down_buffer_put() does nothing
|
||||
/*esp_err_t res = esp_apptrace_trax_lock(hw_data, tmo);
|
||||
if (res != ESP_OK) {
|
||||
return res;
|
||||
}*/
|
||||
|
||||
esp_err_t res = esp_apptrace_membufs_down_buffer_put(&hw_data->membufs, ptr, tmo);
|
||||
|
||||
// now we can safely unlock apptrace to allow other tasks/ISRs to get other buffers and write their data
|
||||
/*if (esp_apptrace_trax_unlock(hw_data) != ESP_OK) {
|
||||
assert(false && "Failed to unlock apptrace data!");
|
||||
}*/
|
||||
return res;
|
||||
}
|
||||
|
||||
static bool esp_apptrace_trax_host_is_connected(esp_apptrace_trax_data_t *hw_data)
|
||||
{
|
||||
if (!ESP_APPTRACE_TRAX_INITED(hw_data)) {
|
||||
return false;
|
||||
}
|
||||
return eri_read(ESP_APPTRACE_TRAX_CTRL_REG) & ESP_APPTRACE_TRAX_HOST_CONNECT ? true : false;
|
||||
}
|
||||
|
||||
static esp_err_t esp_apptrace_trax_flush_nolock(esp_apptrace_trax_data_t *hw_data, uint32_t min_sz, esp_apptrace_tmo_t *tmo)
|
||||
{
|
||||
if (!ESP_APPTRACE_TRAX_INITED(hw_data)) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
return esp_apptrace_membufs_flush_nolock(&hw_data->membufs, min_sz, tmo);
|
||||
}
|
||||
|
||||
static esp_err_t esp_apptrace_trax_flush(esp_apptrace_trax_data_t *hw_data, esp_apptrace_tmo_t *tmo)
|
||||
{
|
||||
if (!ESP_APPTRACE_TRAX_INITED(hw_data)) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
esp_err_t res = esp_apptrace_trax_lock(hw_data, tmo);
|
||||
if (res != ESP_OK) {
|
||||
return res;
|
||||
}
|
||||
|
||||
res = esp_apptrace_membufs_flush_nolock(&hw_data->membufs, 0, tmo);
|
||||
|
||||
// now we can safely unlock apptrace to allow other tasks/ISRs to get other buffers and write their data
|
||||
if (esp_apptrace_trax_unlock(hw_data) != ESP_OK) {
|
||||
assert(false && "Failed to unlock apptrace data!");
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/*****************************************************************************************/
|
||||
/************************** Membufs proto HW iface ***************************************/
|
||||
/*****************************************************************************************/
|
||||
|
||||
static inline void esp_apptrace_trax_buffer_swap_lock(void)
|
||||
{
|
||||
extern uint32_t __esp_apptrace_trax_eri_updated;
|
||||
|
||||
// indicate to host that we are about to update.
|
||||
// this is used only to place CPU into streaming mode at tracing startup
|
||||
// before starting streaming host can halt us after we read ESP_APPTRACE_TRAX_CTRL_REG and before we updated it
|
||||
// HACK: in this case host will set breakpoint just after ESP_APPTRACE_TRAX_CTRL_REG update,
|
||||
// here we set address to set bp at
|
||||
// enter ERI update critical section
|
||||
eri_write(ESP_APPTRACE_TRAX_STAT_REG, (uint32_t)&__esp_apptrace_trax_eri_updated);
|
||||
}
|
||||
|
||||
static __attribute__((noinline)) void esp_apptrace_trax_buffer_swap_unlock(void)
|
||||
{
|
||||
// exit ERI update critical section
|
||||
eri_write(ESP_APPTRACE_TRAX_STAT_REG, 0x0);
|
||||
// TODO: currently host sets breakpoint, use break instruction to stop;
|
||||
// it will allow to use ESP_APPTRACE_TRAX_STAT_REG for other purposes
|
||||
asm volatile (
|
||||
" .global __esp_apptrace_trax_eri_updated\n"
|
||||
"__esp_apptrace_trax_eri_updated:\n"); // host will set bp here to resolve collision at streaming start
|
||||
}
|
||||
|
||||
static esp_err_t esp_apptrace_trax_buffer_swap_start(uint32_t curr_block_id)
|
||||
{
|
||||
esp_err_t res = ESP_OK;
|
||||
|
||||
esp_apptrace_trax_buffer_swap_lock();
|
||||
|
||||
uint32_t ctrl_reg = eri_read(ESP_APPTRACE_TRAX_CTRL_REG);
|
||||
uint32_t host_connected = ESP_APPTRACE_TRAX_HOST_CONNECT & ctrl_reg;
|
||||
if (host_connected) {
|
||||
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,
|
||||
curr_block_id & ESP_APPTRACE_TRAX_BLOCK_ID_MSK, curr_block_id);
|
||||
res = ESP_ERR_NO_MEM;
|
||||
goto _on_err;
|
||||
}
|
||||
}
|
||||
return ESP_OK;
|
||||
_on_err:
|
||||
esp_apptrace_trax_buffer_swap_unlock();
|
||||
return res;
|
||||
}
|
||||
|
||||
static esp_err_t esp_apptrace_trax_buffer_swap_end(uint32_t new_block_id, uint32_t prev_block_len)
|
||||
{
|
||||
uint32_t ctrl_reg = eri_read(ESP_APPTRACE_TRAX_CTRL_REG);
|
||||
uint32_t host_connected = ESP_APPTRACE_TRAX_HOST_CONNECT & ctrl_reg;
|
||||
|
||||
/* calculate CRC16 of the already switched block */
|
||||
if (prev_block_len > 0) {
|
||||
const uint8_t *prev_block_start = s_trax_blocks[!((new_block_id % 2))];
|
||||
uint16_t crc16 = esp_rom_crc16_le(0, prev_block_start, prev_block_len);
|
||||
eri_write(ESP_APPTRACE_TRAX_CRC16_REG, crc16 | ESP_APPTRACE_CRC_INDICATOR);
|
||||
ESP_APPTRACE_LOGD("CRC16:%x %d @%x", crc16, prev_block_len, prev_block_start);
|
||||
}
|
||||
eri_write(ESP_APPTRACE_TRAX_CTRL_REG, ESP_APPTRACE_TRAX_BLOCK_ID(new_block_id) |
|
||||
host_connected | ESP_APPTRACE_TRAX_BLOCK_LEN(prev_block_len));
|
||||
esp_apptrace_trax_buffer_swap_unlock();
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t esp_apptrace_trax_buffer_swap(uint32_t new_block_id)
|
||||
{
|
||||
esp_apptrace_trax_select_memory_block(new_block_id);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static bool esp_apptrace_trax_host_data_pending(void)
|
||||
{
|
||||
uint32_t ctrl_reg = eri_read(ESP_APPTRACE_TRAX_CTRL_REG);
|
||||
return (ctrl_reg & ESP_APPTRACE_TRAX_HOST_DATA) ? true : false;
|
||||
}
|
||||
@@ -1,546 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*/
|
||||
|
||||
//
|
||||
// How It Works
|
||||
// ************
|
||||
|
||||
// 1. Components Overview
|
||||
// ======================
|
||||
|
||||
// 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
|
||||
// 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
|
||||
// by means of reading/writing TRAX registers via JTAG. Blocks muxing is configurable at run-time and allows switching trace memory blocks between
|
||||
// accessors in round-robin fashion so they can read/write separate memory blocks without disturbing each other.
|
||||
// This module implements application tracing feature based on above mechanisms. It allows to transfer arbitrary user data to/from
|
||||
// host via JTAG with minimal impact on system performance. This module is implied to be used in the following tracing scheme.
|
||||
|
||||
// ------>------ ----- (host components) -----
|
||||
// | | | |
|
||||
// ------------------- ----------------------- ----------------------- ---------------- ------ --------- -----------------
|
||||
// |trace data source|-->|target tracing module|<--->|TRAX_MEM0 | TRAX_MEM1|---->|TRAX_DATA_REGS|<-->|JTAG|<--->|OpenOCD|-->|trace data sink|
|
||||
// ------------------- ----------------------- ----------------------- ---------------- ------ --------- -----------------
|
||||
// | | | |
|
||||
// | ------<------ ---------------- |
|
||||
// |<------------------------------------------->|TRAX_CTRL_REGS|<---->|
|
||||
// ----------------
|
||||
|
||||
// In general tracing goes in the following way. User application requests tracing module to send some data by calling esp_apptrace_buffer_get(),
|
||||
// module allocates necessary buffer in current input trace block. Then user fills received buffer with data and calls esp_apptrace_buffer_put().
|
||||
// When current input trace block is filled with app data it is exposed to host and the second block becomes input one and buffer filling restarts.
|
||||
// While target application fills one TRAX block host reads another one via JTAG.
|
||||
// This module also allows communication in the opposite direction: from host to target. As it was said ESP32 and host can access different TRAX blocks
|
||||
// simultaneously, so while target writes trace data to one block host can write its own data (e.g. tracing commands) to another one then when
|
||||
// blocks are switched host receives trace data and target receives data written by host application. Target user application can read host data
|
||||
// by calling esp_apptrace_read() API.
|
||||
// To control buffer switching and for other communication purposes this implementation uses some TRAX registers. It is safe since HW TRAX tracing
|
||||
// can not be used along with application tracing feature so these registers are freely readable/writeable via JTAG from host and via ERI from ESP32 cores.
|
||||
// Overhead of this implementation on target CPU is produced only by allocating/managing buffers and copying of data.
|
||||
// On the host side special OpenOCD command must be used to read trace data.
|
||||
|
||||
// 2. TRAX Registers layout
|
||||
// ========================
|
||||
|
||||
// This module uses two TRAX HW registers and one Performance Monitor register 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.
|
||||
// Host writes zero to this field when it finishes reading exposed block;
|
||||
// 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.
|
||||
|
||||
// 3. Modes of operation
|
||||
// =====================
|
||||
|
||||
// This module supports two modes of operation:
|
||||
// - Post-mortem mode. This is the default mode. In this mode application tracing module does not check whether host has read all the data from block
|
||||
// exposed to it and switches block in any case. The mode does not need host interaction for operation and so can be useful when only the latest
|
||||
// trace data are necessary, e.g. for analyzing crashes. On panic the latest data from current input block are exposed to host and host can read them.
|
||||
// It can happen that system panic occurs when there are very small amount of data which are not exposed to host yet (e.g. crash just after the
|
||||
// TRAX block switch). In this case the previous 16KB of collected data will be dropped and host will see the latest, but very small piece of trace.
|
||||
// It can be insufficient to diagnose the problem. To avoid such situations there is menuconfig option
|
||||
// CONFIG_APPTRACE_POSTMORTEM_FLUSH_THRESH
|
||||
// which controls the threshold for flushing data in case of panic.
|
||||
// - Streaming mode. Tracing module enters this mode when host connects to target and sets respective bits in control registers (per core).
|
||||
// In this mode before switching the block tracing module waits for the host to read all the data from the previously exposed block.
|
||||
// On panic tracing module also waits (timeout is configured via menuconfig via CONFIG_APPTRACE_ONPANIC_HOST_FLUSH_TMO) for the host to read all data.
|
||||
|
||||
// 4. Communication Protocol
|
||||
// =========================
|
||||
|
||||
// 4.1 Trace Memory Blocks
|
||||
// -----------------------
|
||||
|
||||
// Communication is controlled via special register. Host periodically polls control register on each core to find out if there are any data available.
|
||||
// When current input memory block is filled it is exposed to host and 'block_len' and 'block_id' fields are updated in the control register.
|
||||
// Host reads new register value and according to it's value starts reading data from exposed block. Meanwhile target starts filling another trace block.
|
||||
// When host finishes reading the block it clears 'block_len' field in control register indicating to the target that it is ready to accept the next one.
|
||||
// If the host has some data to transfer to the target it writes them to trace memory block before clearing 'block_len' field. Then it sets
|
||||
// 'host_data_present' bit and clears 'block_len' field in control register. Upon every block switch target checks 'host_data_present' bit and if it is set
|
||||
// reads them to down buffer before writing any trace data to switched TRAX block.
|
||||
|
||||
// 4.2 User Data Chunks Level
|
||||
// --------------------------
|
||||
|
||||
// Since trace memory block is shared between user data chunks and data copying is performed on behalf of the API user (in its normal context) in
|
||||
// multithreading environment it can happen that task/ISR which copies data is preempted by another high prio task/ISR. So it is possible situation
|
||||
// that task/ISR will fail to complete filling its data chunk before the whole trace block is exposed to the host. To handle such conditions tracing
|
||||
// module prepends all user data chunks with header which contains allocated buffer size and actual data length within it. OpenOCD command
|
||||
// which reads application traces reports error when it reads incomplete user data block.
|
||||
// Data which are transffered from host to target are also prepended with a header. Down channel data header is simple and consists of one two bytes field
|
||||
// containing length of host data following the header.
|
||||
|
||||
// 4.3 Target Connection/Disconnection
|
||||
// -----------------------------------
|
||||
|
||||
// When host is going to start tracing in streaming mode it needs to put both ESP32 cores into initial state when 'host connected' bit is set
|
||||
// on both cores. To accomplish this host halts both cores and sets this bit in TRAX registers. But target code can be halted in state when it has read control
|
||||
// register but has not updated its value. To handle such situations target code indicates to the host that it is updating control register by writing
|
||||
// non-zero value to status register. Actually it writes address of the instruction which it will execute when it finishes with
|
||||
// the registers update. When target is halted during control register update host sets breakpoint at the address from status register and resumes CPU.
|
||||
// After target code finishes with register update it is halted on breakpoint, host detects it and safely sets 'host connected' bit. When both cores
|
||||
// are set up they are resumed. Tracing starts without further intrusion into CPUs work.
|
||||
// When host is going to stop tracing in streaming mode it needs to disconnect targets. Disconnection process is done using the same algorithm
|
||||
// as for connecting, but 'host connected' bits are cleared on ESP32 cores.
|
||||
|
||||
// 5. Module Access Synchronization
|
||||
// ================================
|
||||
|
||||
// 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
|
||||
// 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.
|
||||
// When low prio task takes mutex and enables local IRQs gets preempted by high prio task which in its turn can try to acquire mutex using infinite timeout.
|
||||
// So no local task switch occurs when mutex is locked. But this does not apply to tasks on another CPU.
|
||||
// WARNING: Priority inversion can happen when low prio task works on one CPU and medium and high prio tasks work on another.
|
||||
// WARNING: Care must be taken when selecting timeout values for trace calls from ISRs. Tracing module does not care about watchdogs when waiting
|
||||
// on internal locks and for host to complete previous block reading, so if timeout value exceeds watchdog's one it can lead to the system reboot.
|
||||
|
||||
// 6. Timeouts
|
||||
// ===========
|
||||
|
||||
// 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.
|
||||
// - 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
|
||||
// time exceeds specified timeout value operation is canceled and ESP_ERR_TIMEOUT code is returned.
|
||||
#include "sdkconfig.h"
|
||||
#include "soc/soc.h"
|
||||
#include "soc/dport_reg.h"
|
||||
#include "soc/tracemem_config.h"
|
||||
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
|
||||
#include "soc/sensitive_reg.h"
|
||||
#endif
|
||||
#include "eri.h"
|
||||
#include "esp_private/trax.h"
|
||||
#include "esp_cpu.h"
|
||||
#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)
|
||||
#define ESP_APPTRACE_TRAX_BLOCK_LEN_GET(_v_) ((_v_) & ESP_APPTRACE_TRAX_BLOCK_LEN_MSK)
|
||||
#define ESP_APPTRACE_TRAX_BLOCK_ID_MSK 0x7FUL
|
||||
#define ESP_APPTRACE_TRAX_BLOCK_ID(_id_) (((_id_) & ESP_APPTRACE_TRAX_BLOCK_ID_MSK) << 15)
|
||||
#define ESP_APPTRACE_TRAX_BLOCK_ID_GET(_v_) (((_v_) >> 15) & ESP_APPTRACE_TRAX_BLOCK_ID_MSK)
|
||||
#define ESP_APPTRACE_TRAX_HOST_DATA (1 << 22)
|
||||
#define ESP_APPTRACE_TRAX_HOST_CONNECT (1 << 23)
|
||||
|
||||
#define ESP_APPTRACE_TRAX_INITED(_hw_) ((_hw_)->inited & (1 << esp_cpu_get_core_id()))
|
||||
|
||||
#define ESP_APPTRACE_TRAX_BLOCK_SIZE (0x4000UL)
|
||||
|
||||
/** TRAX HW transport data */
|
||||
typedef struct {
|
||||
uint8_t inited;
|
||||
#if CONFIG_APPTRACE_LOCK_ENABLE
|
||||
esp_apptrace_lock_t lock; // sync lock
|
||||
#endif
|
||||
esp_apptrace_membufs_proto_data_t membufs;
|
||||
} esp_apptrace_trax_data_t;
|
||||
|
||||
const static char *TAG = "esp_apptrace";
|
||||
|
||||
static uint8_t * const s_trax_blocks[] = {
|
||||
(uint8_t *)TRACEMEM_BLK0_ADDR,
|
||||
(uint8_t *)TRACEMEM_BLK1_ADDR
|
||||
};
|
||||
|
||||
static esp_err_t esp_apptrace_trax_lock(void *hw_data, esp_apptrace_tmo_t *tmo)
|
||||
{
|
||||
#if CONFIG_APPTRACE_LOCK_ENABLE
|
||||
esp_apptrace_trax_data_t *trax_data = hw_data;
|
||||
esp_err_t ret = esp_apptrace_lock_take(&trax_data->lock, tmo);
|
||||
if (ret != ESP_OK) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
#endif
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t esp_apptrace_trax_unlock(void *hw_data)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
#if CONFIG_APPTRACE_LOCK_ENABLE
|
||||
esp_apptrace_trax_data_t *trax_data = hw_data;
|
||||
ret = esp_apptrace_lock_give(&trax_data->lock);
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline void esp_apptrace_trax_hw_init(void)
|
||||
{
|
||||
// Stop trace, if any (on the current CPU)
|
||||
eri_write(ERI_TRAX_TRAXCTRL, TRAXCTRL_TRSTP);
|
||||
eri_write(ERI_TRAX_TRAXCTRL, TRAXCTRL_TMEN);
|
||||
eri_write(ESP_APPTRACE_TRAX_CTRL_REG, ESP_APPTRACE_TRAX_BLOCK_ID(0));
|
||||
// this is for OpenOCD to let him know where stub entries vector is resided
|
||||
// must be read by host before any transfer using TRAX
|
||||
eri_write(ESP_APPTRACE_TRAX_STAT_REG, 0);
|
||||
|
||||
ESP_APPTRACE_LOGI("Initialized TRAX on CPU%d", esp_cpu_get_core_id());
|
||||
}
|
||||
|
||||
static inline void esp_apptrace_trax_select_memory_block(int block_num)
|
||||
{
|
||||
// select memory block to be exposed to the TRAX module (accessed by host)
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
DPORT_WRITE_PERI_REG(DPORT_TRACEMEM_MUX_MODE_REG, block_num ? TRACEMEM_MUX_BLK0_ONLY : TRACEMEM_MUX_BLK1_ONLY);
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||
WRITE_PERI_REG(DPORT_PMS_OCCUPY_3_REG, block_num ? BIT(TRACEMEM_MUX_BLK0_NUM - 4) : BIT(TRACEMEM_MUX_BLK1_NUM - 4));
|
||||
#elif CONFIG_IDF_TARGET_ESP32S3
|
||||
// select memory block to be exposed to the TRAX module (accessed by host)
|
||||
uint32_t block_bits = block_num ? TRACEMEM_CORE0_MUX_BLK_BITS(TRACEMEM_MUX_BLK0_NUM)
|
||||
: TRACEMEM_CORE0_MUX_BLK_BITS(TRACEMEM_MUX_BLK1_NUM);
|
||||
block_bits |= block_num ? TRACEMEM_CORE1_MUX_BLK_BITS(TRACEMEM_MUX_BLK0_NUM)
|
||||
: TRACEMEM_CORE1_MUX_BLK_BITS(TRACEMEM_MUX_BLK1_NUM);
|
||||
ESP_EARLY_LOGV(TAG, "Select block %d @ %p (bits 0x%" PRIx32 ")", block_num, s_trax_blocks[block_num], block_bits);
|
||||
DPORT_WRITE_PERI_REG(SENSITIVE_INTERNAL_SRAM_USAGE_2_REG, block_bits);
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void esp_apptrace_trax_memory_enable(void)
|
||||
{
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
/* Enable trace memory on PRO CPU */
|
||||
DPORT_WRITE_PERI_REG(DPORT_PRO_TRACEMEM_ENA_REG, DPORT_PRO_TRACEMEM_ENA_M);
|
||||
#if CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE == 0
|
||||
/* Enable trace memory on APP CPU */
|
||||
DPORT_WRITE_PERI_REG(DPORT_APP_TRACEMEM_ENA_REG, DPORT_APP_TRACEMEM_ENA_M);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
/*****************************************************************************************/
|
||||
/***************************** Apptrace HW iface *****************************************/
|
||||
/*****************************************************************************************/
|
||||
|
||||
static esp_err_t esp_apptrace_trax_init(void *hw_data, const esp_apptrace_config_t *config)
|
||||
{
|
||||
esp_apptrace_trax_data_t *trax_data = hw_data;
|
||||
|
||||
// 'esp_apptrace_trax_init()' is called on every core, so ensure to do main initialization only once
|
||||
int core_id = esp_cpu_get_core_id();
|
||||
if (core_id == 0) {
|
||||
esp_apptrace_mem_block_t mem_blocks_cfg[2] = {
|
||||
{
|
||||
.start = s_trax_blocks[0],
|
||||
.sz = ESP_APPTRACE_TRAX_BLOCK_SIZE
|
||||
},
|
||||
{
|
||||
.start = s_trax_blocks[1],
|
||||
.sz = ESP_APPTRACE_TRAX_BLOCK_SIZE
|
||||
},
|
||||
};
|
||||
trax_data->membufs.header_size = ESP_APPTRACE_HEADER_SIZE_32;
|
||||
esp_err_t res = esp_apptrace_membufs_init(&trax_data->membufs, mem_blocks_cfg);
|
||||
if (res != ESP_OK) {
|
||||
ESP_APPTRACE_LOGE("Failed to init membufs proto (%d)!", res);
|
||||
return res;
|
||||
}
|
||||
#if CONFIG_APPTRACE_LOCK_ENABLE
|
||||
esp_apptrace_lock_init(&trax_data->lock);
|
||||
#endif
|
||||
esp_apptrace_trax_memory_enable();
|
||||
esp_apptrace_trax_select_memory_block(0);
|
||||
}
|
||||
// init TRAX on this CPU
|
||||
esp_apptrace_trax_hw_init();
|
||||
trax_data->inited |= 1 << core_id;
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static uint8_t *esp_apptrace_trax_up_buffer_get(void *hw_data, uint32_t size, esp_apptrace_tmo_t *tmo)
|
||||
{
|
||||
esp_apptrace_trax_data_t *trax_data = hw_data;
|
||||
|
||||
if (!ESP_APPTRACE_TRAX_INITED(trax_data)) {
|
||||
return NULL;
|
||||
}
|
||||
esp_err_t res = esp_apptrace_trax_lock(trax_data, tmo);
|
||||
if (res != ESP_OK) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uint8_t *ptr = esp_apptrace_membufs_up_buffer_get(&trax_data->membufs, size, tmo);
|
||||
|
||||
// now we can safely unlock apptrace to allow other tasks/ISRs to get other buffers and write their data
|
||||
if (esp_apptrace_trax_unlock(trax_data) != ESP_OK) {
|
||||
assert(false && "Failed to unlock apptrace data!");
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
|
||||
static esp_err_t esp_apptrace_trax_up_buffer_put(void *hw_data, uint8_t *ptr, esp_apptrace_tmo_t *tmo)
|
||||
{
|
||||
esp_apptrace_trax_data_t *trax_data = hw_data;
|
||||
|
||||
if (!ESP_APPTRACE_TRAX_INITED(trax_data)) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
// Can avoid locking because esp_apptrace_membufs_up_buffer_put() just modifies buffer's header
|
||||
esp_err_t res = esp_apptrace_membufs_up_buffer_put(&trax_data->membufs, ptr, tmo);
|
||||
return res;
|
||||
}
|
||||
|
||||
static void esp_apptrace_trax_down_buffer_config(void *hw_data, uint8_t *buf, uint32_t size)
|
||||
{
|
||||
esp_apptrace_trax_data_t *trax_data = hw_data;
|
||||
|
||||
if (!ESP_APPTRACE_TRAX_INITED(trax_data)) {
|
||||
return;
|
||||
}
|
||||
esp_apptrace_membufs_down_buffer_config(&trax_data->membufs, buf, size);
|
||||
}
|
||||
|
||||
static uint8_t *esp_apptrace_trax_down_buffer_get(void *hw_data, uint32_t *size, esp_apptrace_tmo_t *tmo)
|
||||
{
|
||||
esp_apptrace_trax_data_t *trax_data = hw_data;
|
||||
|
||||
if (!ESP_APPTRACE_TRAX_INITED(trax_data)) {
|
||||
return NULL;
|
||||
}
|
||||
esp_err_t res = esp_apptrace_trax_lock(trax_data, tmo);
|
||||
if (res != ESP_OK) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uint8_t *ptr = esp_apptrace_membufs_down_buffer_get(&trax_data->membufs, size, tmo);
|
||||
|
||||
// now we can safely unlock apptrace to allow other tasks/ISRs to get other buffers and write their data
|
||||
if (esp_apptrace_trax_unlock(trax_data) != ESP_OK) {
|
||||
assert(false && "Failed to unlock apptrace data!");
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
|
||||
static esp_err_t esp_apptrace_trax_down_buffer_put(void *hw_data, uint8_t *ptr, esp_apptrace_tmo_t *tmo)
|
||||
{
|
||||
esp_apptrace_trax_data_t *trax_data = hw_data;
|
||||
|
||||
if (!ESP_APPTRACE_TRAX_INITED(trax_data)) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
// Can avoid locking because esp_apptrace_membufs_down_buffer_put() does nothing
|
||||
/*esp_err_t res = esp_apptrace_trax_lock(hw_data, tmo);
|
||||
if (res != ESP_OK) {
|
||||
return res;
|
||||
}*/
|
||||
|
||||
esp_err_t res = esp_apptrace_membufs_down_buffer_put(&trax_data->membufs, ptr, tmo);
|
||||
|
||||
// now we can safely unlock apptrace to allow other tasks/ISRs to get other buffers and write their data
|
||||
/*if (esp_apptrace_trax_unlock(hw_data) != ESP_OK) {
|
||||
assert(false && "Failed to unlock apptrace data!");
|
||||
}*/
|
||||
return res;
|
||||
}
|
||||
|
||||
static bool esp_apptrace_trax_host_is_connected(void *hw_data)
|
||||
{
|
||||
esp_apptrace_trax_data_t *trax_data = hw_data;
|
||||
|
||||
if (!ESP_APPTRACE_TRAX_INITED(trax_data)) {
|
||||
return false;
|
||||
}
|
||||
return eri_read(ESP_APPTRACE_TRAX_CTRL_REG) & ESP_APPTRACE_TRAX_HOST_CONNECT ? true : false;
|
||||
}
|
||||
|
||||
static esp_err_t esp_apptrace_trax_flush_nolock(void *hw_data, uint32_t min_sz, esp_apptrace_tmo_t *tmo)
|
||||
{
|
||||
esp_apptrace_trax_data_t *trax_data = hw_data;
|
||||
|
||||
if (!ESP_APPTRACE_TRAX_INITED(trax_data)) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
return esp_apptrace_membufs_flush_nolock(&trax_data->membufs, min_sz, tmo);
|
||||
}
|
||||
|
||||
static esp_err_t esp_apptrace_trax_flush(void *hw_data, esp_apptrace_tmo_t *tmo)
|
||||
{
|
||||
esp_apptrace_trax_data_t *trax_data = hw_data;
|
||||
|
||||
if (!ESP_APPTRACE_TRAX_INITED(trax_data)) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
esp_err_t res = esp_apptrace_trax_lock(trax_data, tmo);
|
||||
if (res != ESP_OK) {
|
||||
return res;
|
||||
}
|
||||
|
||||
res = esp_apptrace_membufs_flush_nolock(&trax_data->membufs, 0, tmo);
|
||||
|
||||
// now we can safely unlock apptrace to allow other tasks/ISRs to get other buffers and write their data
|
||||
if (esp_apptrace_trax_unlock(trax_data) != ESP_OK) {
|
||||
assert(false && "Failed to unlock apptrace data!");
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/*****************************************************************************************/
|
||||
/************************** Membufs proto HW iface ***************************************/
|
||||
/*****************************************************************************************/
|
||||
|
||||
static inline void esp_apptrace_trax_buffer_swap_lock(void)
|
||||
{
|
||||
extern uint32_t __esp_apptrace_trax_eri_updated;
|
||||
|
||||
// indicate to host that we are about to update.
|
||||
// this is used only to place CPU into streaming mode at tracing startup
|
||||
// before starting streaming host can halt us after we read ESP_APPTRACE_TRAX_CTRL_REG and before we updated it
|
||||
// HACK: in this case host will set breakpoint just after ESP_APPTRACE_TRAX_CTRL_REG update,
|
||||
// here we set address to set bp at
|
||||
// enter ERI update critical section
|
||||
eri_write(ESP_APPTRACE_TRAX_STAT_REG, (uint32_t)&__esp_apptrace_trax_eri_updated);
|
||||
}
|
||||
|
||||
static __attribute__((noinline)) void esp_apptrace_trax_buffer_swap_unlock(void)
|
||||
{
|
||||
// exit ERI update critical section
|
||||
eri_write(ESP_APPTRACE_TRAX_STAT_REG, 0x0);
|
||||
// TODO: currently host sets breakpoint, use break instruction to stop;
|
||||
// it will allow to use ESP_APPTRACE_TRAX_STAT_REG for other purposes
|
||||
asm volatile(
|
||||
" .global __esp_apptrace_trax_eri_updated\n"
|
||||
"__esp_apptrace_trax_eri_updated:\n"); // host will set bp here to resolve collision at streaming start
|
||||
}
|
||||
|
||||
static esp_err_t esp_apptrace_trax_buffer_swap_start(uint32_t curr_block_id)
|
||||
{
|
||||
esp_err_t res = ESP_OK;
|
||||
|
||||
esp_apptrace_trax_buffer_swap_lock();
|
||||
|
||||
uint32_t ctrl_reg = eri_read(ESP_APPTRACE_TRAX_CTRL_REG);
|
||||
uint32_t host_connected = ESP_APPTRACE_TRAX_HOST_CONNECT & ctrl_reg;
|
||||
if (host_connected) {
|
||||
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,
|
||||
curr_block_id & ESP_APPTRACE_TRAX_BLOCK_ID_MSK, curr_block_id);
|
||||
res = ESP_ERR_NO_MEM;
|
||||
goto _on_err;
|
||||
}
|
||||
}
|
||||
return ESP_OK;
|
||||
_on_err:
|
||||
esp_apptrace_trax_buffer_swap_unlock();
|
||||
return res;
|
||||
}
|
||||
|
||||
static esp_err_t esp_apptrace_trax_buffer_swap_end(uint32_t new_block_id, uint32_t prev_block_len)
|
||||
{
|
||||
uint32_t ctrl_reg = eri_read(ESP_APPTRACE_TRAX_CTRL_REG);
|
||||
uint32_t host_connected = ESP_APPTRACE_TRAX_HOST_CONNECT & ctrl_reg;
|
||||
|
||||
eri_write(ESP_APPTRACE_TRAX_CTRL_REG, ESP_APPTRACE_TRAX_BLOCK_ID(new_block_id) |
|
||||
host_connected | ESP_APPTRACE_TRAX_BLOCK_LEN(prev_block_len));
|
||||
esp_apptrace_trax_buffer_swap_unlock();
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t esp_apptrace_trax_buffer_swap(uint32_t new_block_id, uint32_t prev_block_len)
|
||||
{
|
||||
/* Before switching to the new block, calculate CRC16 of the current block */
|
||||
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;
|
||||
}
|
||||
|
||||
static bool esp_apptrace_trax_host_data_pending(void)
|
||||
{
|
||||
uint32_t ctrl_reg = eri_read(ESP_APPTRACE_TRAX_CTRL_REG);
|
||||
return (ctrl_reg & ESP_APPTRACE_TRAX_HOST_DATA) ? true : false;
|
||||
}
|
||||
|
||||
static void esp_apptrace_trax_set_header_size(void *hw_data, esp_apptrace_header_size_t header_size)
|
||||
{
|
||||
esp_apptrace_trax_data_t *trax_data = hw_data;
|
||||
trax_data->membufs.header_size = header_size;
|
||||
}
|
||||
|
||||
esp_apptrace_hw_t *esp_apptrace_jtag_hw_get(void **data)
|
||||
{
|
||||
static esp_apptrace_membufs_proto_hw_t s_trax_proto_hw = {
|
||||
.swap_start = esp_apptrace_trax_buffer_swap_start,
|
||||
.swap = esp_apptrace_trax_buffer_swap,
|
||||
.swap_end = esp_apptrace_trax_buffer_swap_end,
|
||||
.host_data_pending = esp_apptrace_trax_host_data_pending,
|
||||
};
|
||||
static esp_apptrace_trax_data_t s_trax_hw_data = {
|
||||
.membufs = {
|
||||
.hw = &s_trax_proto_hw,
|
||||
},
|
||||
};
|
||||
static esp_apptrace_hw_t s_trax_hw = {
|
||||
.init = esp_apptrace_trax_init,
|
||||
.get_up_buffer = esp_apptrace_trax_up_buffer_get,
|
||||
.put_up_buffer = esp_apptrace_trax_up_buffer_put,
|
||||
.flush_up_buffer_nolock = esp_apptrace_trax_flush_nolock,
|
||||
.flush_up_buffer = esp_apptrace_trax_flush,
|
||||
.down_buffer_config = esp_apptrace_trax_down_buffer_config,
|
||||
.get_down_buffer = esp_apptrace_trax_down_buffer_get,
|
||||
.put_down_buffer = esp_apptrace_trax_down_buffer_put,
|
||||
.host_is_connected = esp_apptrace_trax_host_is_connected,
|
||||
.set_header_size = esp_apptrace_trax_set_header_size,
|
||||
};
|
||||
*data = &s_trax_hw_data;
|
||||
return &s_trax_hw;
|
||||
}
|
||||
69
components/app_trace/private_include/dbg_stubs.h
Normal file
69
components/app_trace/private_include/dbg_stubs.h
Normal file
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2017-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef ESP_DBG_STUBS_H_
|
||||
#define ESP_DBG_STUBS_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "esp_err.h"
|
||||
|
||||
/**
|
||||
* Debug stubs entries IDs
|
||||
*/
|
||||
typedef enum {
|
||||
ESP_DBG_STUB_MAGIC_NUM,
|
||||
ESP_DBG_STUB_TABLE_SIZE,
|
||||
ESP_DBG_STUB_CONTROL_DATA, ///< stubs descriptor entry
|
||||
ESP_DBG_STUB_ENTRY_FIRST,
|
||||
ESP_DBG_STUB_ENTRY_GCOV ///< GCOV entry
|
||||
= ESP_DBG_STUB_ENTRY_FIRST,
|
||||
ESP_DBG_STUB_ENTRY_CAPABILITIES,
|
||||
ESP_DBG_STUB_ENTRY_MAX
|
||||
} esp_dbg_stub_id_t;
|
||||
|
||||
#define ESP_DBG_STUB_MAGIC_NUM_VAL 0xFEEDBEEF
|
||||
#define ESP_DBG_STUB_CAP_GCOV_TASK (1 << 0)
|
||||
|
||||
/**
|
||||
* @brief Initializes debug stubs.
|
||||
*
|
||||
* @note Must be called after esp_apptrace_init() if app tracing is enabled.
|
||||
*/
|
||||
void esp_dbg_stubs_init(void);
|
||||
|
||||
/**
|
||||
* @brief Initializes application tracing module.
|
||||
*
|
||||
* @note Should be called before any esp_apptrace_xxx call.
|
||||
*
|
||||
* @param id Stub ID.
|
||||
* @param entry Stub entry. Usually it is stub entry function address,
|
||||
* but can be any value meaningfull for OpenOCD command/code
|
||||
* such as capabilities
|
||||
* @return ESP_OK on success, otherwise see esp_err_t
|
||||
*/
|
||||
esp_err_t esp_dbg_stub_entry_set(esp_dbg_stub_id_t id, uint32_t entry);
|
||||
|
||||
/**
|
||||
* @brief Retrives the corresponding stub entry
|
||||
*
|
||||
* @param id Stub ID.
|
||||
* @param entry Stub entry. Usually it is stub entry function address,
|
||||
* but can be any value meaningfull for OpenOCD command/code
|
||||
* such as capabilities
|
||||
*
|
||||
* @return ESP_OK on success, otherwise see esp_err_t
|
||||
*/
|
||||
esp_err_t esp_dbg_stub_entry_get(esp_dbg_stub_id_t id, uint32_t *entry);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // ESP_DBG_STUBS_H_
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020-2025 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -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;
|
||||
@@ -38,9 +38,14 @@ typedef struct {
|
||||
esp_apptrace_membufs_proto_hw_t * hw;
|
||||
volatile esp_apptrace_membufs_state_t state; // state
|
||||
esp_apptrace_mem_block_t blocks[2]; // memory blocks
|
||||
#if CONFIG_APPTRACE_PENDING_DATA_SIZE_MAX > 0
|
||||
// ring buffer control struct for pending user blocks
|
||||
esp_apptrace_rb_t rb_pend;
|
||||
// storage for pending user blocks
|
||||
uint8_t pending_data[CONFIG_APPTRACE_PENDING_DATA_SIZE_MAX + 1];
|
||||
#endif
|
||||
// ring buffer control struct for data from host (down buffer)
|
||||
esp_apptrace_rb_t rb_down;
|
||||
int header_size; ///< Size of the trace header (2 or 4 bytes)
|
||||
} esp_apptrace_membufs_proto_data_t;
|
||||
|
||||
esp_err_t esp_apptrace_membufs_init(esp_apptrace_membufs_proto_data_t *proto, const esp_apptrace_mem_block_t blocks_cfg[2]);
|
||||
|
||||
41
components/app_trace/project_include.cmake
Normal file
41
components/app_trace/project_include.cmake
Normal file
@@ -0,0 +1,41 @@
|
||||
# idf_create_lcov_report
|
||||
#
|
||||
# Create coverage report.
|
||||
function(idf_create_coverage_report report_dir)
|
||||
set(gcov_tool ${_CMAKE_TOOLCHAIN_PREFIX}gcov)
|
||||
idf_build_get_property(project_name PROJECT_NAME)
|
||||
|
||||
file(TO_NATIVE_PATH "${report_dir}" _report_dir)
|
||||
file(TO_NATIVE_PATH "${project_dir}" _project_dir)
|
||||
file(TO_NATIVE_PATH "${report_dir}/html/index.html" _index_path)
|
||||
|
||||
add_custom_target(pre-cov-report
|
||||
COMMENT "Generating coverage report in: ${_report_dir}"
|
||||
COMMAND ${CMAKE_COMMAND} -E echo "Using gcov: ${gcov_tool}"
|
||||
COMMAND ${CMAKE_COMMAND} -E make_directory ${_report_dir}/html
|
||||
)
|
||||
|
||||
add_custom_target(lcov-report
|
||||
COMMENT "WARNING: lcov-report is deprecated. Please use gcovr-report instead."
|
||||
COMMAND lcov --gcov-tool ${gcov_tool} -c -d ${CMAKE_CURRENT_BINARY_DIR} -o ${_report_dir}/${project_name}.info
|
||||
COMMAND genhtml -o ${_report_dir}/html ${_report_dir}/${project_name}.info
|
||||
DEPENDS pre-cov-report
|
||||
)
|
||||
|
||||
add_custom_target(gcovr-report
|
||||
COMMAND gcovr -r ${_project_dir} --gcov-executable ${gcov_tool} -s --html-details ${_index_path}
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
|
||||
DEPENDS pre-cov-report
|
||||
)
|
||||
endfunction()
|
||||
|
||||
# idf_clean_coverage_report
|
||||
#
|
||||
# Clean coverage report.
|
||||
function(idf_clean_coverage_report report_dir)
|
||||
file(TO_CMAKE_PATH "${report_dir}" _report_dir)
|
||||
|
||||
add_custom_target(cov-data-clean
|
||||
COMMENT "Clean coverage report in: ${_report_dir}"
|
||||
COMMAND ${CMAKE_COMMAND} -E remove_directory ${_report_dir})
|
||||
endfunction()
|
||||
@@ -2,11 +2,31 @@
|
||||
# CONFIG_DEPRECATED_OPTION CONFIG_NEW_OPTION
|
||||
|
||||
CONFIG_ESP32_APPTRACE_DESTINATION CONFIG_APPTRACE_DESTINATION
|
||||
CONFIG_ESP32_APPTRACE_DEST_NONE CONFIG_APPTRACE_DEST_NONE
|
||||
CONFIG_ESP32_APPTRACE_DEST_TRAX CONFIG_APPTRACE_DEST_JTAG
|
||||
CONFIG_ESP32_APPTRACE_ENABLE CONFIG_ESP_TRACE_TRANSPORT_APPTRACE
|
||||
CONFIG_ESP32_APPTRACE_ENABLE CONFIG_APPTRACE_ENABLE
|
||||
CONFIG_ESP32_APPTRACE_LOCK_ENABLE CONFIG_APPTRACE_LOCK_ENABLE
|
||||
CONFIG_ESP32_APPTRACE_ONPANIC_HOST_FLUSH_TMO CONFIG_APPTRACE_ONPANIC_HOST_FLUSH_TMO
|
||||
CONFIG_ESP32_APPTRACE_POSTMORTEM_FLUSH_TRAX_THRESH CONFIG_APPTRACE_POSTMORTEM_FLUSH_THRESH
|
||||
CONFIG_ESP32_APPTRACE_PENDING_DATA_SIZE_MAX CONFIG_APPTRACE_PENDING_DATA_SIZE_MAX
|
||||
CONFIG_ESP32_GCOV_ENABLE CONFIG_APPTRACE_GCOV_ENABLE
|
||||
|
||||
CONFIG_SYSVIEW_TS_SOURCE_CCOUNT CONFIG_ESP_TRACE_TS_SOURCE_CCOUNT
|
||||
CONFIG_SYSVIEW_TS_SOURCE_ESP_TIMER CONFIG_ESP_TRACE_TS_SOURCE_ESP_TIMER
|
||||
CONFIG_SYSVIEW_ENABLE CONFIG_APPTRACE_SV_ENABLE
|
||||
CONFIG_SYSVIEW_TS_SOURCE CONFIG_APPTRACE_SV_TS_SOURCE
|
||||
CONFIG_SYSVIEW_TS_SOURCE_CCOUNT CONFIG_APPTRACE_SV_TS_SOURCE_CCOUNT
|
||||
CONFIG_SYSVIEW_TS_SOURCE_ESP_TIMER CONFIG_APPTRACE_SV_TS_SOURCE_ESP_TIMER
|
||||
CONFIG_SYSVIEW_MAX_TASKS CONFIG_APPTRACE_SV_MAX_TASKS
|
||||
CONFIG_SYSVIEW_BUF_WAIT_TMO CONFIG_APPTRACE_SV_BUF_WAIT_TMO
|
||||
CONFIG_SYSVIEW_EVT_OVERFLOW_ENABLE CONFIG_APPTRACE_SV_EVT_OVERFLOW_ENABLE
|
||||
CONFIG_SYSVIEW_EVT_ISR_ENTER_ENABLE CONFIG_APPTRACE_SV_EVT_ISR_ENTER_ENABLE
|
||||
CONFIG_SYSVIEW_EVT_ISR_EXIT_ENABLE CONFIG_APPTRACE_SV_EVT_ISR_EXIT_ENABLE
|
||||
CONFIG_SYSVIEW_EVT_ISR_TO_SCHEDULER_ENABLE CONFIG_APPTRACE_SV_EVT_ISR_TO_SCHED_ENABLE
|
||||
CONFIG_SYSVIEW_EVT_TASK_START_EXEC_ENABLE CONFIG_APPTRACE_SV_EVT_TASK_START_EXEC_ENABLE
|
||||
CONFIG_SYSVIEW_EVT_TASK_STOP_EXEC_ENABLE CONFIG_APPTRACE_SV_EVT_TASK_STOP_EXEC_ENABLE
|
||||
CONFIG_SYSVIEW_EVT_TASK_START_READY_ENABLE CONFIG_APPTRACE_SV_EVT_TASK_START_READY_ENABLE
|
||||
CONFIG_SYSVIEW_EVT_TASK_STOP_READY_ENABLE CONFIG_APPTRACE_SV_EVT_TASK_STOP_READY_ENABLE
|
||||
CONFIG_SYSVIEW_EVT_TASK_CREATE_ENABLE CONFIG_APPTRACE_SV_EVT_TASK_CREATE_ENABLE
|
||||
CONFIG_SYSVIEW_EVT_TASK_TERMINATE_ENABLE CONFIG_APPTRACE_SV_EVT_TASK_TERMINATE_ENABLE
|
||||
CONFIG_SYSVIEW_EVT_IDLE_ENABLE CONFIG_APPTRACE_SV_EVT_IDLE_ENABLE
|
||||
CONFIG_SYSVIEW_EVT_TIMER_ENTER_ENABLE CONFIG_APPTRACE_SV_EVT_TIMER_ENTER_ENABLE
|
||||
CONFIG_SYSVIEW_EVT_TIMER_EXIT_ENABLE CONFIG_APPTRACE_SV_EVT_TIMER_EXIT_ENABLE
|
||||
|
||||
118
components/app_trace/sys_view/Config/Global.h
Normal file
118
components/app_trace/sys_view/Config/Global.h
Normal file
@@ -0,0 +1,118 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 1995-2021 SEGGER Microcontroller GmbH
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-1-Clause
|
||||
*/
|
||||
/*********************************************************************
|
||||
* SEGGER Microcontroller GmbH *
|
||||
* The Embedded Experts *
|
||||
**********************************************************************
|
||||
* *
|
||||
* (c) 1995 - 2021 SEGGER Microcontroller GmbH *
|
||||
* *
|
||||
* www.segger.com Support: support@segger.com *
|
||||
* *
|
||||
**********************************************************************
|
||||
* *
|
||||
* SEGGER SystemView * Real-time application analysis *
|
||||
* *
|
||||
**********************************************************************
|
||||
* *
|
||||
* All rights reserved. *
|
||||
* *
|
||||
* SEGGER strongly recommends to not make any changes *
|
||||
* to or modify the source code of this software in order to stay *
|
||||
* compatible with the SystemView and RTT protocol, and J-Link. *
|
||||
* *
|
||||
* Redistribution and use in source and binary forms, with or *
|
||||
* without modification, are permitted provided that the following *
|
||||
* condition is met: *
|
||||
* *
|
||||
* o Redistributions of source code must retain the above copyright *
|
||||
* notice, this condition and the following disclaimer. *
|
||||
* *
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND *
|
||||
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, *
|
||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF *
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE *
|
||||
* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR *
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR *
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT *
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; *
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE *
|
||||
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH *
|
||||
* DAMAGE. *
|
||||
* *
|
||||
**********************************************************************
|
||||
* *
|
||||
* SystemView version: 3.42 *
|
||||
* *
|
||||
**********************************************************************
|
||||
----------------------------------------------------------------------
|
||||
File : Global.h
|
||||
Purpose : Global types
|
||||
In case your application already has a Global.h, you should
|
||||
merge the files. In order to use Segger code, the types
|
||||
U8, U16, U32, I8, I16, I32 need to be defined in Global.h;
|
||||
additional definitions do not hurt.
|
||||
Revision: $Rev: 12501 $
|
||||
---------------------------END-OF-HEADER------------------------------
|
||||
*/
|
||||
|
||||
#ifndef GLOBAL_H // Guard against multiple inclusion
|
||||
#define GLOBAL_H
|
||||
|
||||
#define U8 unsigned char
|
||||
#define I8 signed char
|
||||
#define U16 unsigned short
|
||||
#define I16 signed short
|
||||
#ifdef __x86_64__
|
||||
#define U32 unsigned
|
||||
#define I32 int
|
||||
#else
|
||||
#define U32 unsigned long
|
||||
#define I32 signed long
|
||||
#endif
|
||||
|
||||
//
|
||||
// CC_NO_LONG_SUPPORT can be defined to compile test
|
||||
// without long support for compilers that do not
|
||||
// support C99 and its long type.
|
||||
//
|
||||
#ifdef CC_NO_LONG_SUPPORT
|
||||
#define PTR_ADDR U32
|
||||
#else // Supports long type.
|
||||
#if defined(_WIN32) && !defined(__clang__) && !defined(__MINGW32__)
|
||||
//
|
||||
// Microsoft VC6 compiler related
|
||||
//
|
||||
#define U64 unsigned __int64
|
||||
#define U128 unsigned __int128
|
||||
#define I64 __int64
|
||||
#define I128 __int128
|
||||
#if _MSC_VER <= 1200
|
||||
#define U64_C(x) x##UI64
|
||||
#else
|
||||
#define U64_C(x) x##ULL
|
||||
#endif
|
||||
#else
|
||||
//
|
||||
// C99 compliant compiler
|
||||
//
|
||||
#define U64 unsigned long long
|
||||
#define I64 signed long long
|
||||
#define U64_C(x) x##ULL
|
||||
#endif
|
||||
|
||||
#if (defined(_WIN64) || defined(__LP64__)) // 64-bit symbols used by Visual Studio and GCC, maybe others as well.
|
||||
#define PTR_ADDR U64
|
||||
#else
|
||||
#define PTR_ADDR U32
|
||||
#endif
|
||||
#endif // Supports long type.
|
||||
|
||||
#endif // Avoid multiple inclusion
|
||||
|
||||
/*************************** End of file ****************************/
|
||||
433
components/app_trace/sys_view/Config/SEGGER_RTT_Conf.h
Normal file
433
components/app_trace/sys_view/Config/SEGGER_RTT_Conf.h
Normal file
@@ -0,0 +1,433 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 1995-2021 SEGGER Microcontroller GmbH
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-1-Clause
|
||||
*/
|
||||
/*********************************************************************
|
||||
* SEGGER Microcontroller GmbH *
|
||||
* The Embedded Experts *
|
||||
**********************************************************************
|
||||
* *
|
||||
* (c) 1995 - 2021 SEGGER Microcontroller GmbH *
|
||||
* *
|
||||
* www.segger.com Support: support@segger.com *
|
||||
* *
|
||||
**********************************************************************
|
||||
* *
|
||||
* SEGGER SystemView * Real-time application analysis *
|
||||
* *
|
||||
**********************************************************************
|
||||
* *
|
||||
* All rights reserved. *
|
||||
* *
|
||||
* SEGGER strongly recommends to not make any changes *
|
||||
* to or modify the source code of this software in order to stay *
|
||||
* compatible with the SystemView and RTT protocol, and J-Link. *
|
||||
* *
|
||||
* Redistribution and use in source and binary forms, with or *
|
||||
* without modification, are permitted provided that the following *
|
||||
* condition is met: *
|
||||
* *
|
||||
* o Redistributions of source code must retain the above copyright *
|
||||
* notice, this condition and the following disclaimer. *
|
||||
* *
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND *
|
||||
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, *
|
||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF *
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE *
|
||||
* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR *
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR *
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT *
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; *
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE *
|
||||
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH *
|
||||
* DAMAGE. *
|
||||
* *
|
||||
**********************************************************************
|
||||
* *
|
||||
* SystemView version: 3.42 *
|
||||
* *
|
||||
**********************************************************************
|
||||
---------------------------END-OF-HEADER------------------------------
|
||||
File : SEGGER_RTT_Conf.h
|
||||
Purpose : Implementation of SEGGER real-time transfer (RTT) which
|
||||
allows real-time communication on targets which support
|
||||
debugger memory accesses while the CPU is running.
|
||||
Revision: $Rev: 24316 $
|
||||
|
||||
*/
|
||||
|
||||
#ifndef SEGGER_RTT_CONF_H
|
||||
#define SEGGER_RTT_CONF_H
|
||||
|
||||
#ifdef __IAR_SYSTEMS_ICC__
|
||||
#include <intrinsics.h>
|
||||
#endif
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Defines, configurable
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
//
|
||||
// Take in and set to correct values for Cortex-A systems with CPU cache
|
||||
//
|
||||
//#define SEGGER_RTT_CPU_CACHE_LINE_SIZE (32) // Largest cache line size (in bytes) in the current system
|
||||
//#define SEGGER_RTT_UNCACHED_OFF (0xFB000000) // Address alias where RTT CB and buffers can be accessed uncached
|
||||
//
|
||||
// Most common case:
|
||||
// Up-channel 0: RTT
|
||||
// Up-channel 1: SystemView
|
||||
//
|
||||
#ifndef SEGGER_RTT_MAX_NUM_UP_BUFFERS
|
||||
#define SEGGER_RTT_MAX_NUM_UP_BUFFERS (3) // Max. number of up-buffers (T->H) available on this target (Default: 3)
|
||||
#endif
|
||||
//
|
||||
// Most common case:
|
||||
// Down-channel 0: RTT
|
||||
// Down-channel 1: SystemView
|
||||
//
|
||||
#ifndef SEGGER_RTT_MAX_NUM_DOWN_BUFFERS
|
||||
#define SEGGER_RTT_MAX_NUM_DOWN_BUFFERS (3) // Max. number of down-buffers (H->T) available on this target (Default: 3)
|
||||
#endif
|
||||
|
||||
#ifndef BUFFER_SIZE_UP
|
||||
#define BUFFER_SIZE_UP (1024) // Size of the buffer for terminal output of target, up to host (Default: 1k)
|
||||
#endif
|
||||
|
||||
#ifndef BUFFER_SIZE_DOWN
|
||||
#define BUFFER_SIZE_DOWN (16) // Size of the buffer for terminal input to target from host (Usually keyboard input) (Default: 16)
|
||||
#endif
|
||||
|
||||
#ifndef SEGGER_RTT_PRINTF_BUFFER_SIZE
|
||||
#define SEGGER_RTT_PRINTF_BUFFER_SIZE (64u) // Size of buffer for RTT printf to bulk-send chars via RTT (Default: 64)
|
||||
#endif
|
||||
|
||||
#ifndef SEGGER_RTT_MODE_DEFAULT
|
||||
#define SEGGER_RTT_MODE_DEFAULT SEGGER_RTT_MODE_NO_BLOCK_SKIP // Mode for pre-initialized terminal channel (buffer 0)
|
||||
#endif
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* RTT memcpy configuration
|
||||
*
|
||||
* memcpy() is good for large amounts of data,
|
||||
* but the overhead is big for small amounts, which are usually stored via RTT.
|
||||
* With SEGGER_RTT_MEMCPY_USE_BYTELOOP a simple byte loop can be used instead.
|
||||
*
|
||||
* SEGGER_RTT_MEMCPY() can be used to replace standard memcpy() in RTT functions.
|
||||
* This is may be required with memory access restrictions,
|
||||
* such as on Cortex-A devices with MMU.
|
||||
*/
|
||||
#ifndef SEGGER_RTT_MEMCPY_USE_BYTELOOP
|
||||
#define SEGGER_RTT_MEMCPY_USE_BYTELOOP 0 // 0: Use memcpy/SEGGER_RTT_MEMCPY, 1: Use a simple byte-loop
|
||||
#endif
|
||||
//
|
||||
// Example definition of SEGGER_RTT_MEMCPY to external memcpy with GCC toolchains and Cortex-A targets
|
||||
//
|
||||
//#if ((defined __SES_ARM) || (defined __CROSSWORKS_ARM) || (defined __GNUC__)) && (defined (__ARM_ARCH_7A__))
|
||||
// #define SEGGER_RTT_MEMCPY(pDest, pSrc, NumBytes) SEGGER_memcpy((pDest), (pSrc), (NumBytes))
|
||||
//#endif
|
||||
|
||||
//
|
||||
// Target is not allowed to perform other RTT operations while string still has not been stored completely.
|
||||
// Otherwise we would probably end up with a mixed string in the buffer.
|
||||
// If using RTT from within interrupts, multiple tasks or multi processors, define the SEGGER_RTT_LOCK() and SEGGER_RTT_UNLOCK() function here.
|
||||
//
|
||||
// SEGGER_RTT_MAX_INTERRUPT_PRIORITY can be used in the sample lock routines on Cortex-M3/4.
|
||||
// Make sure to mask all interrupts which can send RTT data, i.e. generate SystemView events, or cause task switches.
|
||||
// When high-priority interrupts must not be masked while sending RTT data, SEGGER_RTT_MAX_INTERRUPT_PRIORITY needs to be adjusted accordingly.
|
||||
// (Higher priority = lower priority number)
|
||||
// Default value for embOS: 128u
|
||||
// Default configuration in FreeRTOS: configMAX_SYSCALL_INTERRUPT_PRIORITY: ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
|
||||
// In case of doubt mask all interrupts: 1 << (8 - BASEPRI_PRIO_BITS) i.e. 1 << 5 when 3 bits are implemented in NVIC
|
||||
// or define SEGGER_RTT_LOCK() to completely disable interrupts.
|
||||
//
|
||||
#ifndef SEGGER_RTT_MAX_INTERRUPT_PRIORITY
|
||||
#define SEGGER_RTT_MAX_INTERRUPT_PRIORITY (0x20) // Interrupt priority to lock on SEGGER_RTT_LOCK on Cortex-M3/4 (Default: 0x20)
|
||||
#endif
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* RTT lock configuration for SEGGER Embedded Studio,
|
||||
* Rowley CrossStudio and GCC
|
||||
*/
|
||||
#if ((defined(__SES_ARM) || defined(__SES_RISCV) || defined(__CROSSWORKS_ARM) || defined(__GNUC__) || defined(__clang__)) && !defined (__CC_ARM) && !defined(WIN32))
|
||||
#if (defined(__ARM_ARCH_6M__) || defined(__ARM_ARCH_8M_BASE__))
|
||||
#define SEGGER_RTT_LOCK() { \
|
||||
unsigned int _SEGGER_RTT__LockState; \
|
||||
__asm volatile ("mrs %0, primask \n\t" \
|
||||
"movs r1, #1 \n\t" \
|
||||
"msr primask, r1 \n\t" \
|
||||
: "=r" (_SEGGER_RTT__LockState) \
|
||||
: \
|
||||
: "r1", "cc" \
|
||||
);
|
||||
|
||||
#define SEGGER_RTT_UNLOCK() __asm volatile ("msr primask, %0 \n\t" \
|
||||
: \
|
||||
: "r" (_SEGGER_RTT__LockState) \
|
||||
: \
|
||||
); \
|
||||
}
|
||||
#elif (defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__) || defined(__ARM_ARCH_8M_MAIN__))
|
||||
#ifndef SEGGER_RTT_MAX_INTERRUPT_PRIORITY
|
||||
#define SEGGER_RTT_MAX_INTERRUPT_PRIORITY (0x20)
|
||||
#endif
|
||||
#define SEGGER_RTT_LOCK() { \
|
||||
unsigned int _SEGGER_RTT__LockState; \
|
||||
__asm volatile ("mrs %0, basepri \n\t" \
|
||||
"mov r1, %1 \n\t" \
|
||||
"msr basepri, r1 \n\t" \
|
||||
: "=r" (_SEGGER_RTT__LockState) \
|
||||
: "i"(SEGGER_RTT_MAX_INTERRUPT_PRIORITY) \
|
||||
: "r1", "cc" \
|
||||
);
|
||||
|
||||
#define SEGGER_RTT_UNLOCK() __asm volatile ("msr basepri, %0 \n\t" \
|
||||
: \
|
||||
: "r" (_SEGGER_RTT__LockState) \
|
||||
: \
|
||||
); \
|
||||
}
|
||||
|
||||
#elif (defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7R__))
|
||||
#define SEGGER_RTT_LOCK() { \
|
||||
unsigned int _SEGGER_RTT__LockState; \
|
||||
__asm volatile ("mrs r1, CPSR \n\t" \
|
||||
"mov %0, r1 \n\t" \
|
||||
"orr r1, r1, #0xC0 \n\t" \
|
||||
"msr CPSR_c, r1 \n\t" \
|
||||
: "=r" (_SEGGER_RTT__LockState) \
|
||||
: \
|
||||
: "r1", "cc" \
|
||||
);
|
||||
|
||||
#define SEGGER_RTT_UNLOCK() __asm volatile ("mov r0, %0 \n\t" \
|
||||
"mrs r1, CPSR \n\t" \
|
||||
"bic r1, r1, #0xC0 \n\t" \
|
||||
"and r0, r0, #0xC0 \n\t" \
|
||||
"orr r1, r1, r0 \n\t" \
|
||||
"msr CPSR_c, r1 \n\t" \
|
||||
: \
|
||||
: "r" (_SEGGER_RTT__LockState) \
|
||||
: "r0", "r1", "cc" \
|
||||
); \
|
||||
}
|
||||
#elif defined(__riscv) || defined(__riscv_xlen)
|
||||
#define SEGGER_RTT_LOCK() { \
|
||||
unsigned int _SEGGER_RTT__LockState; \
|
||||
__asm volatile ("csrr %0, mstatus \n\t" \
|
||||
"csrci mstatus, 8 \n\t" \
|
||||
"andi %0, %0, 8 \n\t" \
|
||||
: "=r" (_SEGGER_RTT__LockState) \
|
||||
: \
|
||||
: \
|
||||
);
|
||||
|
||||
#define SEGGER_RTT_UNLOCK() __asm volatile ("csrr a1, mstatus \n\t" \
|
||||
"or %0, %0, a1 \n\t" \
|
||||
"csrs mstatus, %0 \n\t" \
|
||||
: \
|
||||
: "r" (_SEGGER_RTT__LockState) \
|
||||
: "a1" \
|
||||
); \
|
||||
}
|
||||
#else
|
||||
#define SEGGER_RTT_LOCK()
|
||||
#define SEGGER_RTT_UNLOCK()
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* RTT lock configuration for IAR EWARM
|
||||
*/
|
||||
#ifdef __ICCARM__
|
||||
#if (defined (__ARM6M__) && (__CORE__ == __ARM6M__)) || \
|
||||
(defined (__ARM8M_BASELINE__) && (__CORE__ == __ARM8M_BASELINE__))
|
||||
#define SEGGER_RTT_LOCK() { \
|
||||
unsigned int _SEGGER_RTT__LockState; \
|
||||
_SEGGER_RTT__LockState = __get_PRIMASK(); \
|
||||
__set_PRIMASK(1);
|
||||
|
||||
#define SEGGER_RTT_UNLOCK() __set_PRIMASK(_SEGGER_RTT__LockState); \
|
||||
}
|
||||
#elif (defined (__ARM7EM__) && (__CORE__ == __ARM7EM__)) || \
|
||||
(defined (__ARM7M__) && (__CORE__ == __ARM7M__)) || \
|
||||
(defined (__ARM8M_MAINLINE__) && (__CORE__ == __ARM8M_MAINLINE__)) || \
|
||||
(defined (__ARM8M_MAINLINE__) && (__CORE__ == __ARM8M_MAINLINE__))
|
||||
#ifndef SEGGER_RTT_MAX_INTERRUPT_PRIORITY
|
||||
#define SEGGER_RTT_MAX_INTERRUPT_PRIORITY (0x20)
|
||||
#endif
|
||||
#define SEGGER_RTT_LOCK() { \
|
||||
unsigned int _SEGGER_RTT__LockState; \
|
||||
_SEGGER_RTT__LockState = __get_BASEPRI(); \
|
||||
__set_BASEPRI(SEGGER_RTT_MAX_INTERRUPT_PRIORITY);
|
||||
|
||||
#define SEGGER_RTT_UNLOCK() __set_BASEPRI(_SEGGER_RTT__LockState); \
|
||||
}
|
||||
#elif (defined (__ARM7A__) && (__CORE__ == __ARM7A__)) || \
|
||||
(defined (__ARM7R__) && (__CORE__ == __ARM7R__))
|
||||
#define SEGGER_RTT_LOCK() { \
|
||||
unsigned int _SEGGER_RTT__LockState; \
|
||||
__asm volatile ("mrs r1, CPSR \n\t" \
|
||||
"mov %0, r1 \n\t" \
|
||||
"orr r1, r1, #0xC0 \n\t" \
|
||||
"msr CPSR_c, r1 \n\t" \
|
||||
: "=r" (_SEGGER_RTT__LockState) \
|
||||
: \
|
||||
: "r1", "cc" \
|
||||
);
|
||||
|
||||
#define SEGGER_RTT_UNLOCK() __asm volatile ("mov r0, %0 \n\t" \
|
||||
"mrs r1, CPSR \n\t" \
|
||||
"bic r1, r1, #0xC0 \n\t" \
|
||||
"and r0, r0, #0xC0 \n\t" \
|
||||
"orr r1, r1, r0 \n\t" \
|
||||
"msr CPSR_c, r1 \n\t" \
|
||||
: \
|
||||
: "r" (_SEGGER_RTT__LockState) \
|
||||
: "r0", "r1", "cc" \
|
||||
); \
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* RTT lock configuration for IAR RX
|
||||
*/
|
||||
#ifdef __ICCRX__
|
||||
#define SEGGER_RTT_LOCK() { \
|
||||
unsigned long _SEGGER_RTT__LockState; \
|
||||
_SEGGER_RTT__LockState = __get_interrupt_state(); \
|
||||
__disable_interrupt();
|
||||
|
||||
#define SEGGER_RTT_UNLOCK() __set_interrupt_state(_SEGGER_RTT__LockState); \
|
||||
}
|
||||
#endif
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* RTT lock configuration for IAR RL78
|
||||
*/
|
||||
#ifdef __ICCRL78__
|
||||
#define SEGGER_RTT_LOCK() { \
|
||||
__istate_t _SEGGER_RTT__LockState; \
|
||||
_SEGGER_RTT__LockState = __get_interrupt_state(); \
|
||||
__disable_interrupt();
|
||||
|
||||
#define SEGGER_RTT_UNLOCK() __set_interrupt_state(_SEGGER_RTT__LockState); \
|
||||
}
|
||||
#endif
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* RTT lock configuration for KEIL ARM
|
||||
*/
|
||||
#ifdef __CC_ARM
|
||||
#if (defined __TARGET_ARCH_6S_M)
|
||||
#define SEGGER_RTT_LOCK() { \
|
||||
unsigned int _SEGGER_RTT__LockState; \
|
||||
register unsigned char _SEGGER_RTT__PRIMASK __asm( "primask"); \
|
||||
_SEGGER_RTT__LockState = _SEGGER_RTT__PRIMASK; \
|
||||
_SEGGER_RTT__PRIMASK = 1u; \
|
||||
__schedule_barrier();
|
||||
|
||||
#define SEGGER_RTT_UNLOCK() _SEGGER_RTT__PRIMASK = _SEGGER_RTT__LockState; \
|
||||
__schedule_barrier(); \
|
||||
}
|
||||
#elif (defined(__TARGET_ARCH_7_M) || defined(__TARGET_ARCH_7E_M))
|
||||
#ifndef SEGGER_RTT_MAX_INTERRUPT_PRIORITY
|
||||
#define SEGGER_RTT_MAX_INTERRUPT_PRIORITY (0x20)
|
||||
#endif
|
||||
#define SEGGER_RTT_LOCK() { \
|
||||
unsigned int _SEGGER_RTT__LockState; \
|
||||
register unsigned char BASEPRI __asm( "basepri"); \
|
||||
_SEGGER_RTT__LockState = BASEPRI; \
|
||||
BASEPRI = SEGGER_RTT_MAX_INTERRUPT_PRIORITY; \
|
||||
__schedule_barrier();
|
||||
|
||||
#define SEGGER_RTT_UNLOCK() BASEPRI = _SEGGER_RTT__LockState; \
|
||||
__schedule_barrier(); \
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* RTT lock configuration for TI ARM
|
||||
*/
|
||||
#ifdef __TI_ARM__
|
||||
#if defined (__TI_ARM_V6M0__)
|
||||
#define SEGGER_RTT_LOCK() { \
|
||||
unsigned int _SEGGER_RTT__LockState; \
|
||||
_SEGGER_RTT__LockState = __get_PRIMASK(); \
|
||||
__set_PRIMASK(1);
|
||||
|
||||
#define SEGGER_RTT_UNLOCK() __set_PRIMASK(_SEGGER_RTT__LockState); \
|
||||
}
|
||||
#elif (defined (__TI_ARM_V7M3__) || defined (__TI_ARM_V7M4__))
|
||||
#ifndef SEGGER_RTT_MAX_INTERRUPT_PRIORITY
|
||||
#define SEGGER_RTT_MAX_INTERRUPT_PRIORITY (0x20)
|
||||
#endif
|
||||
#define SEGGER_RTT_LOCK() { \
|
||||
unsigned int _SEGGER_RTT__LockState; \
|
||||
_SEGGER_RTT__LockState = _set_interrupt_priority(SEGGER_RTT_MAX_INTERRUPT_PRIORITY);
|
||||
|
||||
#define SEGGER_RTT_UNLOCK() _set_interrupt_priority(_SEGGER_RTT__LockState); \
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* RTT lock configuration for CCRX
|
||||
*/
|
||||
#ifdef __RX
|
||||
#include <machine.h>
|
||||
#define SEGGER_RTT_LOCK() { \
|
||||
unsigned long _SEGGER_RTT__LockState; \
|
||||
_SEGGER_RTT__LockState = get_psw() & 0x010000; \
|
||||
clrpsw_i();
|
||||
|
||||
#define SEGGER_RTT_UNLOCK() set_psw(get_psw() | _SEGGER_RTT__LockState); \
|
||||
}
|
||||
#endif
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* RTT lock configuration for embOS Simulation on Windows
|
||||
* (Can also be used for generic RTT locking with embOS)
|
||||
*/
|
||||
#if defined(WIN32) || defined(SEGGER_RTT_LOCK_EMBOS)
|
||||
|
||||
void OS_SIM_EnterCriticalSection(void);
|
||||
void OS_SIM_LeaveCriticalSection(void);
|
||||
|
||||
#define SEGGER_RTT_LOCK() { \
|
||||
OS_SIM_EnterCriticalSection();
|
||||
|
||||
#define SEGGER_RTT_UNLOCK() OS_SIM_LeaveCriticalSection(); \
|
||||
}
|
||||
#endif
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* RTT lock configuration fallback
|
||||
*/
|
||||
#ifndef SEGGER_RTT_LOCK
|
||||
#define SEGGER_RTT_LOCK() // Lock RTT (nestable) (i.e. disable interrupts)
|
||||
#endif
|
||||
|
||||
#ifndef SEGGER_RTT_UNLOCK
|
||||
#define SEGGER_RTT_UNLOCK() // Unlock RTT (nestable) (i.e. enable previous interrupt lock state)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
/*************************** End of file ****************************/
|
||||
90
components/app_trace/sys_view/Config/SEGGER_SYSVIEW_Conf.h
Normal file
90
components/app_trace/sys_view/Config/SEGGER_SYSVIEW_Conf.h
Normal file
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 1995-2021 SEGGER Microcontroller GmbH
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-1-Clause
|
||||
*/
|
||||
/*********************************************************************
|
||||
* SEGGER Microcontroller GmbH *
|
||||
* The Embedded Experts *
|
||||
**********************************************************************
|
||||
* *
|
||||
* (c) 1995 - 2021 SEGGER Microcontroller GmbH *
|
||||
* *
|
||||
* www.segger.com Support: support@segger.com *
|
||||
* *
|
||||
**********************************************************************
|
||||
* *
|
||||
* SEGGER SystemView * Real-time application analysis *
|
||||
* *
|
||||
**********************************************************************
|
||||
* *
|
||||
* All rights reserved. *
|
||||
* *
|
||||
* SEGGER strongly recommends to not make any changes *
|
||||
* to or modify the source code of this software in order to stay *
|
||||
* compatible with the SystemView and RTT protocol, and J-Link. *
|
||||
* *
|
||||
* Redistribution and use in source and binary forms, with or *
|
||||
* without modification, are permitted provided that the following *
|
||||
* condition is met: *
|
||||
* *
|
||||
* o Redistributions of source code must retain the above copyright *
|
||||
* notice, this condition and the following disclaimer. *
|
||||
* *
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND *
|
||||
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, *
|
||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF *
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE *
|
||||
* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR *
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR *
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT *
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; *
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE *
|
||||
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH *
|
||||
* DAMAGE. *
|
||||
* *
|
||||
**********************************************************************
|
||||
* *
|
||||
* SystemView version: 3.42 *
|
||||
* *
|
||||
**********************************************************************
|
||||
-------------------------- END-OF-HEADER -----------------------------
|
||||
|
||||
File : SEGGER_SYSVIEW_Conf.h
|
||||
Purpose : SEGGER SystemView configuration file.
|
||||
Set defines which deviate from the defaults (see SEGGER_SYSVIEW_ConfDefaults.h) here.
|
||||
Revision: $Rev: 21292 $
|
||||
|
||||
Additional information:
|
||||
Required defines which must be set are:
|
||||
SEGGER_SYSVIEW_GET_TIMESTAMP
|
||||
SEGGER_SYSVIEW_GET_INTERRUPT_ID
|
||||
For known compilers and cores, these might be set to good defaults
|
||||
in SEGGER_SYSVIEW_ConfDefaults.h.
|
||||
|
||||
SystemView needs a (nestable) locking mechanism.
|
||||
If not defined, the RTT locking mechanism is used,
|
||||
which then needs to be properly configured.
|
||||
*/
|
||||
|
||||
#ifndef SEGGER_SYSVIEW_CONF_H
|
||||
#define SEGGER_SYSVIEW_CONF_H
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Defines, configurable
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
/*********************************************************************
|
||||
* TODO: Add your defines here. *
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
|
||||
#endif // SEGGER_SYSVIEW_CONF_H
|
||||
|
||||
/*************************** End of file ****************************/
|
||||
255
components/app_trace/sys_view/SEGGER/SEGGER.h
Normal file
255
components/app_trace/sys_view/SEGGER/SEGGER.h
Normal file
@@ -0,0 +1,255 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 1995-2021 SEGGER Microcontroller GmbH
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-1-Clause
|
||||
*
|
||||
* SPDX-FileContributor: 2023 Espressif Systems (Shanghai) CO LTD
|
||||
*/
|
||||
/*********************************************************************
|
||||
* SEGGER Microcontroller GmbH *
|
||||
* The Embedded Experts *
|
||||
**********************************************************************
|
||||
* *
|
||||
* (c) 1995 - 2024 SEGGER Microcontroller GmbH *
|
||||
* *
|
||||
* www.segger.com Support: support@segger.com *
|
||||
* *
|
||||
**********************************************************************
|
||||
* *
|
||||
* SEGGER SystemView * Real-time application analysis *
|
||||
* *
|
||||
**********************************************************************
|
||||
* *
|
||||
* All rights reserved. *
|
||||
* *
|
||||
* SEGGER strongly recommends to not make any changes *
|
||||
* to or modify the source code of this software in order to stay *
|
||||
* compatible with the SystemView and RTT protocol, and J-Link. *
|
||||
* *
|
||||
* Redistribution and use in source and binary forms, with or *
|
||||
* without modification, are permitted provided that the following *
|
||||
* condition is met: *
|
||||
* *
|
||||
* o Redistributions of source code must retain the above copyright *
|
||||
* notice, this condition and the following disclaimer. *
|
||||
* *
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND *
|
||||
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, *
|
||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF *
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE *
|
||||
* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR *
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR *
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT *
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; *
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE *
|
||||
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH *
|
||||
* DAMAGE. *
|
||||
* *
|
||||
**********************************************************************
|
||||
* *
|
||||
* SystemView version: 3.56 *
|
||||
* *
|
||||
**********************************************************************
|
||||
----------------------------------------------------------------------
|
||||
File : SEGGER.h
|
||||
Purpose : Global types etc & general purpose utility functions
|
||||
Revision: $Rev: 18102 $
|
||||
---------------------------END-OF-HEADER------------------------------
|
||||
*/
|
||||
|
||||
#ifndef SEGGER_H // Guard against multiple inclusion
|
||||
#define SEGGER_H
|
||||
|
||||
#include <stdarg.h> // For va_list.
|
||||
#include "Global.h" // Type definitions: U8, U16, U32, I8, I16, I32
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" { /* Make sure we have C-declarations in C++ programs */
|
||||
#endif
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Keywords/specifiers
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
#ifndef INLINE
|
||||
#if (defined(__ICCARM__) || defined(__RX) || defined(__ICCRX__))
|
||||
//
|
||||
// Other known compilers.
|
||||
//
|
||||
#define INLINE inline
|
||||
#else
|
||||
#if (defined(_WIN32) && !defined(__clang__))
|
||||
//
|
||||
// Microsoft VC6 and newer.
|
||||
// Force inlining without cost checking.
|
||||
//
|
||||
#define INLINE __forceinline
|
||||
#elif defined(__GNUC__) || defined(__clang__)
|
||||
//
|
||||
// Force inlining with GCC + clang
|
||||
//
|
||||
#define INLINE inline __attribute__((always_inline))
|
||||
#elif (defined(__CC_ARM))
|
||||
//
|
||||
// Force inlining with ARMCC (Keil)
|
||||
//
|
||||
#define INLINE __inline
|
||||
#else
|
||||
//
|
||||
// Unknown compilers.
|
||||
//
|
||||
#define INLINE
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Function-like macros
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
#define SEGGER_COUNTOF(a) (sizeof((a))/sizeof((a)[0]))
|
||||
#define SEGGER_MIN(a,b) (((a) < (b)) ? (a) : (b))
|
||||
#define SEGGER_MAX(a,b) (((a) > (b)) ? (a) : (b))
|
||||
|
||||
#ifndef SEGGER_USE_PARA // Some compiler complain about unused parameters.
|
||||
#define SEGGER_USE_PARA(Para) (void)Para // This works for most compilers.
|
||||
#endif
|
||||
|
||||
#define SEGGER_ADDR2PTR(Type, Addr) (/*lint -e(923) -e(9078)*/((Type*)((PTR_ADDR)(Addr)))) // Allow cast from address to pointer.
|
||||
#define SEGGER_PTR2ADDR(p) (/*lint -e(923) -e(9078)*/((PTR_ADDR)(p))) // Allow cast from pointer to address.
|
||||
#define SEGGER_PTR2PTR(Type, p) (/*lint -e(740) -e(826) -e(9079) -e(9087)*/((Type*)(p))) // Allow cast from one pointer type to another (ignore different size).
|
||||
#define SEGGER_PTR_DISTANCE(p0, p1) (SEGGER_PTR2ADDR(p0) - SEGGER_PTR2ADDR(p1))
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Defines
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
#define SEGGER_PRINTF_FLAG_ADJLEFT (1 << 0)
|
||||
#define SEGGER_PRINTF_FLAG_SIGNFORCE (1 << 1)
|
||||
#define SEGGER_PRINTF_FLAG_SIGNSPACE (1 << 2)
|
||||
#define SEGGER_PRINTF_FLAG_PRECEED (1 << 3)
|
||||
#define SEGGER_PRINTF_FLAG_ZEROPAD (1 << 4)
|
||||
#define SEGGER_PRINTF_FLAG_NEGATIVE (1 << 5)
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Types
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
char* pBuffer;
|
||||
int BufferSize;
|
||||
int Cnt;
|
||||
} SEGGER_BUFFER_DESC;
|
||||
|
||||
typedef struct {
|
||||
unsigned int CacheLineSize; // 0: No Cache. Most Systems such as ARM9 use a 32 bytes cache line size.
|
||||
void (*pfDMB) (void); // Optional DMB function for Data Memory Barrier to make sure all memory operations are completed.
|
||||
void (*pfClean) (void *p, unsigned long NumBytes); // Optional clean function for cached memory.
|
||||
void (*pfInvalidate)(void *p, unsigned long NumBytes); // Optional invalidate function for cached memory.
|
||||
} SEGGER_CACHE_CONFIG;
|
||||
|
||||
typedef struct SEGGER_SNPRINTF_CONTEXT_struct SEGGER_SNPRINTF_CONTEXT;
|
||||
|
||||
struct SEGGER_SNPRINTF_CONTEXT_struct {
|
||||
void* pContext; // Application specific context.
|
||||
SEGGER_BUFFER_DESC* pBufferDesc; // Buffer descriptor to use for output.
|
||||
void (*pfFlush)(SEGGER_SNPRINTF_CONTEXT* pContext); // Callback executed once the buffer is full. Callback decides if the buffer gets cleared to store more or not.
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
void (*pfStoreChar) (SEGGER_BUFFER_DESC* pBufferDesc, SEGGER_SNPRINTF_CONTEXT* pContext, char c);
|
||||
int (*pfPrintUnsigned) (SEGGER_BUFFER_DESC* pBufferDesc, SEGGER_SNPRINTF_CONTEXT* pContext, U32 v, unsigned Base, char Flags, int Width, int Precision);
|
||||
int (*pfPrintInt) (SEGGER_BUFFER_DESC* pBufferDesc, SEGGER_SNPRINTF_CONTEXT* pContext, I32 v, unsigned Base, char Flags, int Width, int Precision);
|
||||
} SEGGER_PRINTF_API;
|
||||
|
||||
typedef void (*SEGGER_pFormatter)(SEGGER_BUFFER_DESC* pBufferDesc, SEGGER_SNPRINTF_CONTEXT* pContext, const SEGGER_PRINTF_API* pApi, va_list* pParamList, char Lead, int Width, int Precision);
|
||||
|
||||
typedef struct SEGGER_PRINTF_FORMATTER {
|
||||
struct SEGGER_PRINTF_FORMATTER* pNext; // Pointer to next formatter.
|
||||
SEGGER_pFormatter pfFormatter; // Formatter function.
|
||||
char Specifier; // Format specifier.
|
||||
} SEGGER_PRINTF_FORMATTER;
|
||||
|
||||
typedef struct {
|
||||
U32 (*pfGetHPTimestamp)(void); // Mandatory, pfGetHPTimestamp
|
||||
int (*pfGetUID) (U8 abUID[16]); // Optional, pfGetUID
|
||||
} SEGGER_BSP_API;
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Utility functions
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
//
|
||||
// Memory operations.
|
||||
//
|
||||
void SEGGER_ARM_memcpy(void* pDest, const void* pSrc, int NumBytes);
|
||||
void SEGGER_memcpy (void* pDest, const void* pSrc, unsigned NumBytes);
|
||||
void SEGGER_memxor (void* pDest, const void* pSrc, unsigned NumBytes);
|
||||
|
||||
//
|
||||
// String functions.
|
||||
//
|
||||
int SEGGER_atoi (const char* s);
|
||||
int SEGGER_isalnum (int c);
|
||||
int SEGGER_isalpha (int c);
|
||||
unsigned SEGGER_strlen (const char* s);
|
||||
int SEGGER_tolower (int c);
|
||||
int SEGGER_strcasecmp (const char* sText1, const char* sText2);
|
||||
int SEGGER_strncasecmp(const char *sText1, const char *sText2, unsigned Count);
|
||||
|
||||
//
|
||||
// Buffer/printf related.
|
||||
//
|
||||
void SEGGER_StoreChar (SEGGER_BUFFER_DESC* pBufferDesc, char c);
|
||||
void SEGGER_PrintUnsigned(SEGGER_BUFFER_DESC* pBufferDesc, U32 v, unsigned Base, int Precision);
|
||||
void SEGGER_PrintInt (SEGGER_BUFFER_DESC* pBufferDesc, I32 v, unsigned Base, int Precision);
|
||||
int SEGGER_snprintf (char* pBuffer, int BufferSize, const char* sFormat, ...);
|
||||
int SEGGER_vsnprintf (char* pBuffer, int BufferSize, const char* sFormat, va_list ParamList);
|
||||
int SEGGER_vsnprintfEx (SEGGER_SNPRINTF_CONTEXT* pContext, const char* sFormat, va_list ParamList);
|
||||
|
||||
int SEGGER_PRINTF_AddFormatter (SEGGER_PRINTF_FORMATTER* pFormatter, SEGGER_pFormatter pfFormatter, char c);
|
||||
void SEGGER_PRINTF_AddDoubleFormatter (void);
|
||||
void SEGGER_PRINTF_AddIPFormatter (void);
|
||||
void SEGGER_PRINTF_AddBLUEFormatter (void);
|
||||
void SEGGER_PRINTF_AddCONNECTFormatter(void);
|
||||
void SEGGER_PRINTF_AddSSLFormatter (void);
|
||||
void SEGGER_PRINTF_AddSSHFormatter (void);
|
||||
void SEGGER_PRINTF_AddHTMLFormatter (void);
|
||||
|
||||
//
|
||||
// BSP abstraction API.
|
||||
//
|
||||
int SEGGER_BSP_GetUID (U8 abUID[16]);
|
||||
int SEGGER_BSP_GetUID32(U32* pUID);
|
||||
void SEGGER_BSP_SetAPI (const SEGGER_BSP_API* pAPI);
|
||||
void SEGGER_BSP_SeedUID (void);
|
||||
|
||||
//
|
||||
// Other API.
|
||||
//
|
||||
void SEGGER_VERSION_GetString(char acText[8], unsigned Version);
|
||||
|
||||
#if defined(__cplusplus)
|
||||
} /* Make sure we have C-declarations in C++ programs */
|
||||
#endif
|
||||
|
||||
#endif // Avoid multiple inclusion
|
||||
|
||||
/*************************** End of file ****************************/
|
||||
515
components/app_trace/sys_view/SEGGER/SEGGER_RTT.h
Normal file
515
components/app_trace/sys_view/SEGGER/SEGGER_RTT.h
Normal file
@@ -0,0 +1,515 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 1995-2021 SEGGER Microcontroller GmbH
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-1-Clause
|
||||
*/
|
||||
/*********************************************************************
|
||||
* SEGGER Microcontroller GmbH *
|
||||
* The Embedded Experts *
|
||||
**********************************************************************
|
||||
* *
|
||||
* (c) 1995 - 2024 SEGGER Microcontroller GmbH *
|
||||
* *
|
||||
* www.segger.com Support: support@segger.com *
|
||||
* *
|
||||
**********************************************************************
|
||||
* *
|
||||
* SEGGER SystemView * Real-time application analysis *
|
||||
* *
|
||||
**********************************************************************
|
||||
* *
|
||||
* All rights reserved. *
|
||||
* *
|
||||
* SEGGER strongly recommends to not make any changes *
|
||||
* to or modify the source code of this software in order to stay *
|
||||
* compatible with the SystemView and RTT protocol, and J-Link. *
|
||||
* *
|
||||
* Redistribution and use in source and binary forms, with or *
|
||||
* without modification, are permitted provided that the following *
|
||||
* condition is met: *
|
||||
* *
|
||||
* o Redistributions of source code must retain the above copyright *
|
||||
* notice, this condition and the following disclaimer. *
|
||||
* *
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND *
|
||||
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, *
|
||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF *
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE *
|
||||
* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR *
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR *
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT *
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; *
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE *
|
||||
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH *
|
||||
* DAMAGE. *
|
||||
* *
|
||||
**********************************************************************
|
||||
* *
|
||||
* SystemView version: 3.56 *
|
||||
* *
|
||||
**********************************************************************
|
||||
---------------------------END-OF-HEADER------------------------------
|
||||
File : SEGGER_RTT.h
|
||||
Purpose : Implementation of SEGGER real-time transfer which allows
|
||||
real-time communication on targets which support debugger
|
||||
memory accesses while the CPU is running.
|
||||
Revision: $Rev: 25842 $
|
||||
----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifndef SEGGER_RTT_H
|
||||
#define SEGGER_RTT_H
|
||||
|
||||
#include "../Config/SEGGER_RTT_Conf.h"
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Defines, defaults
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
#ifndef RTT_USE_ASM
|
||||
//
|
||||
// Some cores support out-of-order memory accesses (reordering of memory accesses in the core)
|
||||
// For such cores, we need to define a memory barrier to guarantee the order of certain accesses to the RTT ring buffers.
|
||||
// Needed for:
|
||||
// Cortex-M7 (ARMv7-M)
|
||||
// Cortex-M23 (ARM-v8M)
|
||||
// Cortex-M33 (ARM-v8M)
|
||||
// Cortex-A/R (ARM-v7A/R)
|
||||
//
|
||||
// We do not explicitly check for "Embedded Studio" as the compiler in use determines what we support.
|
||||
// You can use an external toolchain like IAR inside ES. So there is no point in checking for "Embedded Studio"
|
||||
//
|
||||
#if (defined __CROSSWORKS_ARM) // Rowley Crossworks
|
||||
#define _CC_HAS_RTT_ASM_SUPPORT 1
|
||||
#if (defined __ARM_ARCH_7M__) // Cortex-M3
|
||||
#define _CORE_HAS_RTT_ASM_SUPPORT 1
|
||||
#elif (defined __ARM_ARCH_7EM__) // Cortex-M4/M7
|
||||
#define _CORE_HAS_RTT_ASM_SUPPORT 1
|
||||
#define _CORE_NEEDS_DMB 1
|
||||
#define RTT__DMB() __asm volatile ("dmb\n" : : :);
|
||||
#elif (defined __ARM_ARCH_8M_BASE__) // Cortex-M23
|
||||
#define _CORE_HAS_RTT_ASM_SUPPORT 0
|
||||
#define _CORE_NEEDS_DMB 1
|
||||
#define RTT__DMB() __asm volatile ("dmb\n" : : :);
|
||||
#elif (defined __ARM_ARCH_8M_MAIN__) // Cortex-M33
|
||||
#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
|
||||
#elif (defined __ARMCC_VERSION)
|
||||
//
|
||||
// ARM compiler
|
||||
// ARM compiler V6.0 and later is clang based.
|
||||
// Our ASM part is compatible to clang.
|
||||
//
|
||||
#if (__ARMCC_VERSION >= 6000000)
|
||||
#define _CC_HAS_RTT_ASM_SUPPORT 1
|
||||
#else
|
||||
#define _CC_HAS_RTT_ASM_SUPPORT 0
|
||||
#endif
|
||||
#if (defined __ARM_ARCH_6M__) // Cortex-M0 / M1
|
||||
#define _CORE_HAS_RTT_ASM_SUPPORT 0 // No ASM support for this architecture
|
||||
#elif (defined __ARM_ARCH_7M__) // Cortex-M3
|
||||
#define _CORE_HAS_RTT_ASM_SUPPORT 1
|
||||
#elif (defined __ARM_ARCH_7EM__) // Cortex-M4/M7
|
||||
#define _CORE_HAS_RTT_ASM_SUPPORT 1
|
||||
#define _CORE_NEEDS_DMB 1
|
||||
#define RTT__DMB() __asm volatile ("dmb\n" : : :);
|
||||
#elif (defined __ARM_ARCH_8M_BASE__) // Cortex-M23
|
||||
#define _CORE_HAS_RTT_ASM_SUPPORT 0
|
||||
#define _CORE_NEEDS_DMB 1
|
||||
#define RTT__DMB() __asm volatile ("dmb\n" : : :);
|
||||
#elif (defined __ARM_ARCH_8M_MAIN__) // Cortex-M33
|
||||
#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" : : :);
|
||||
#else
|
||||
#define _CORE_HAS_RTT_ASM_SUPPORT 0
|
||||
#endif
|
||||
#elif ((defined __GNUC__) || (defined __clang__))
|
||||
//
|
||||
// GCC / Clang
|
||||
//
|
||||
#define _CC_HAS_RTT_ASM_SUPPORT 1
|
||||
// ARM 7/9: __ARM_ARCH_5__ / __ARM_ARCH_5E__ / __ARM_ARCH_5T__ / __ARM_ARCH_5T__ / __ARM_ARCH_5TE__
|
||||
#if (defined __ARM_ARCH_7M__) // Cortex-M3
|
||||
#define _CORE_HAS_RTT_ASM_SUPPORT 1
|
||||
#elif (defined __ARM_ARCH_7EM__) // Cortex-M4/M7
|
||||
#define _CORE_HAS_RTT_ASM_SUPPORT 1
|
||||
#define _CORE_NEEDS_DMB 1 // Only Cortex-M7 needs a DMB but we cannot distinguish M4 and M7 here...
|
||||
#define RTT__DMB() __asm volatile ("dmb\n" : : :);
|
||||
#elif (defined __ARM_ARCH_8M_BASE__) // Cortex-M23
|
||||
#define _CORE_HAS_RTT_ASM_SUPPORT 0
|
||||
#define _CORE_NEEDS_DMB 1
|
||||
#define RTT__DMB() __asm volatile ("dmb\n" : : :);
|
||||
#elif (defined __ARM_ARCH_8M_MAIN__) // Cortex-M33
|
||||
#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" : : :);
|
||||
#else
|
||||
#define _CORE_HAS_RTT_ASM_SUPPORT 0
|
||||
#endif
|
||||
#elif ((defined __IASMARM__) || (defined __ICCARM__))
|
||||
//
|
||||
// IAR assembler/compiler
|
||||
//
|
||||
#define _CC_HAS_RTT_ASM_SUPPORT 1
|
||||
#if (__VER__ < 6300000)
|
||||
#define VOLATILE
|
||||
#else
|
||||
#define VOLATILE volatile
|
||||
#endif
|
||||
#if (defined __ARM7M__) // Needed for old versions that do not know the define yet
|
||||
#if (__CORE__ == __ARM7M__) // Cortex-M3
|
||||
#define _CORE_HAS_RTT_ASM_SUPPORT 1
|
||||
#endif
|
||||
#endif
|
||||
#if (defined __ARM7EM__)
|
||||
#if (__CORE__ == __ARM7EM__) // Cortex-M4/M7
|
||||
#define _CORE_HAS_RTT_ASM_SUPPORT 1
|
||||
#define _CORE_NEEDS_DMB 1
|
||||
#define RTT__DMB() asm VOLATILE ("DMB");
|
||||
#endif
|
||||
#endif
|
||||
#if (defined __ARM8M_BASELINE__)
|
||||
#if (__CORE__ == __ARM8M_BASELINE__) // Cortex-M23
|
||||
#define _CORE_HAS_RTT_ASM_SUPPORT 0
|
||||
#define _CORE_NEEDS_DMB 1
|
||||
#define RTT__DMB() asm VOLATILE ("DMB");
|
||||
#endif
|
||||
#endif
|
||||
#if (defined __ARM8M_MAINLINE__)
|
||||
#if (__CORE__ == __ARM8M_MAINLINE__) // Cortex-M33
|
||||
#define _CORE_HAS_RTT_ASM_SUPPORT 1
|
||||
#define _CORE_NEEDS_DMB 1
|
||||
#define RTT__DMB() asm VOLATILE ("DMB");
|
||||
#endif
|
||||
#endif
|
||||
#if (defined __ARM8EM_MAINLINE__)
|
||||
#if (__CORE__ == __ARM8EM_MAINLINE__) // Cortex-???
|
||||
#define _CORE_HAS_RTT_ASM_SUPPORT 1
|
||||
#define _CORE_NEEDS_DMB 1
|
||||
#define RTT__DMB() asm VOLATILE ("DMB");
|
||||
#endif
|
||||
#endif
|
||||
#if (defined __ARM7A__)
|
||||
#if (__CORE__ == __ARM7A__) // Cortex-A 32-bit ARMv7-A
|
||||
#define _CORE_NEEDS_DMB 1
|
||||
#define RTT__DMB() asm VOLATILE ("DMB");
|
||||
#endif
|
||||
#endif
|
||||
#if (defined __ARM7R__)
|
||||
#if (__CORE__ == __ARM7R__) // Cortex-R 32-bit ARMv7-R
|
||||
#define _CORE_NEEDS_DMB 1
|
||||
#define RTT__DMB() asm VOLATILE ("DMB");
|
||||
#endif
|
||||
#endif
|
||||
// TBD: __ARM8A__ => Cortex-A 64-bit ARMv8-A
|
||||
// TBD: __ARM8R__ => Cortex-R 64-bit ARMv8-R
|
||||
#else
|
||||
//
|
||||
// Other compilers
|
||||
//
|
||||
#define _CC_HAS_RTT_ASM_SUPPORT 0
|
||||
#define _CORE_HAS_RTT_ASM_SUPPORT 0
|
||||
#endif
|
||||
//
|
||||
// If IDE and core support the ASM version, enable ASM version by default
|
||||
//
|
||||
#ifndef _CORE_HAS_RTT_ASM_SUPPORT
|
||||
#define _CORE_HAS_RTT_ASM_SUPPORT 0 // Default for unknown cores
|
||||
#endif
|
||||
#if (_CC_HAS_RTT_ASM_SUPPORT && _CORE_HAS_RTT_ASM_SUPPORT)
|
||||
#define RTT_USE_ASM (1)
|
||||
#else
|
||||
#define RTT_USE_ASM (0)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef _CORE_NEEDS_DMB
|
||||
#define _CORE_NEEDS_DMB 0
|
||||
#endif
|
||||
|
||||
#ifndef RTT__DMB
|
||||
#if _CORE_NEEDS_DMB
|
||||
#error "Don't know how to place inline assembly for DMB"
|
||||
#else
|
||||
#define RTT__DMB()
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef SEGGER_RTT_CPU_CACHE_LINE_SIZE
|
||||
#define SEGGER_RTT_CPU_CACHE_LINE_SIZE (0) // On most target systems where RTT is used, we do not have a CPU cache, therefore 0 is a good default here
|
||||
#endif
|
||||
|
||||
#ifndef SEGGER_RTT_UNCACHED_OFF
|
||||
#if SEGGER_RTT_CPU_CACHE_LINE_SIZE
|
||||
#error "SEGGER_RTT_UNCACHED_OFF must be defined when setting SEGGER_RTT_CPU_CACHE_LINE_SIZE != 0"
|
||||
#else
|
||||
#define SEGGER_RTT_UNCACHED_OFF (0)
|
||||
#endif
|
||||
#endif
|
||||
#if RTT_USE_ASM
|
||||
#if SEGGER_RTT_CPU_CACHE_LINE_SIZE
|
||||
#error "RTT_USE_ASM is not available if SEGGER_RTT_CPU_CACHE_LINE_SIZE != 0"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef SEGGER_RTT_ASM // defined when SEGGER_RTT.h is included from assembly file
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Defines, fixed
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
//
|
||||
// Determine how much we must pad the control block to make it a multiple of a cache line in size
|
||||
// Assuming: U8 = 1B
|
||||
// U16 = 2B
|
||||
// U32 = 4B
|
||||
// U8/U16/U32* = 4B
|
||||
//
|
||||
#if SEGGER_RTT_CPU_CACHE_LINE_SIZE // Avoid division by zero in case we do not have any cache
|
||||
#define SEGGER_RTT__ROUND_UP_2_CACHE_LINE_SIZE(NumBytes) (((NumBytes + SEGGER_RTT_CPU_CACHE_LINE_SIZE - 1) / SEGGER_RTT_CPU_CACHE_LINE_SIZE) * SEGGER_RTT_CPU_CACHE_LINE_SIZE)
|
||||
#else
|
||||
#define SEGGER_RTT__ROUND_UP_2_CACHE_LINE_SIZE(NumBytes) (NumBytes)
|
||||
#endif
|
||||
#define SEGGER_RTT__CB_SIZE (16 + 4 + 4 + (SEGGER_RTT_MAX_NUM_UP_BUFFERS * 24) + (SEGGER_RTT_MAX_NUM_DOWN_BUFFERS * 24))
|
||||
#define SEGGER_RTT__CB_PADDING (SEGGER_RTT__ROUND_UP_2_CACHE_LINE_SIZE(SEGGER_RTT__CB_SIZE) - SEGGER_RTT__CB_SIZE)
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Types
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
//
|
||||
// Description for a circular buffer (also called "ring buffer")
|
||||
// which is used as up-buffer (T->H)
|
||||
//
|
||||
typedef struct {
|
||||
const char* sName; // Optional name. Standard names so far are: "Terminal", "SysView", "J-Scope_t4i4"
|
||||
char* pBuffer; // Pointer to start of buffer
|
||||
unsigned SizeOfBuffer; // Buffer size in bytes. Note that one byte is lost, as this implementation does not fill up the buffer in order to avoid the problem of being unable to distinguish between full and empty.
|
||||
unsigned WrOff; // Position of next item to be written by either target.
|
||||
volatile unsigned RdOff; // Position of next item to be read by host. Must be volatile since it may be modified by host.
|
||||
unsigned Flags; // Contains configuration flags. Flags[31:24] are used for validity check and must be zero. Flags[23:2] are reserved for future use. Flags[1:0] = RTT operating mode.
|
||||
} SEGGER_RTT_BUFFER_UP;
|
||||
|
||||
//
|
||||
// Description for a circular buffer (also called "ring buffer")
|
||||
// which is used as down-buffer (H->T)
|
||||
//
|
||||
typedef struct {
|
||||
const char* sName; // Optional name. Standard names so far are: "Terminal", "SysView", "J-Scope_t4i4"
|
||||
char* pBuffer; // Pointer to start of buffer
|
||||
unsigned SizeOfBuffer; // Buffer size in bytes. Note that one byte is lost, as this implementation does not fill up the buffer in order to avoid the problem of being unable to distinguish between full and empty.
|
||||
volatile unsigned WrOff; // Position of next item to be written by host. Must be volatile since it may be modified by host.
|
||||
unsigned RdOff; // Position of next item to be read by target (down-buffer).
|
||||
unsigned Flags; // Contains configuration flags. Flags[31:24] are used for validity check and must be zero. Flags[23:2] are reserved for future use. Flags[1:0] = RTT operating mode.
|
||||
} SEGGER_RTT_BUFFER_DOWN;
|
||||
|
||||
//
|
||||
// RTT control block which describes the number of buffers available
|
||||
// as well as the configuration for each buffer
|
||||
//
|
||||
//
|
||||
typedef struct {
|
||||
char acID[16]; // Initialized to "SEGGER RTT"
|
||||
int MaxNumUpBuffers; // Initialized to SEGGER_RTT_MAX_NUM_UP_BUFFERS (type. 2)
|
||||
int MaxNumDownBuffers; // Initialized to SEGGER_RTT_MAX_NUM_DOWN_BUFFERS (type. 2)
|
||||
SEGGER_RTT_BUFFER_UP aUp[SEGGER_RTT_MAX_NUM_UP_BUFFERS]; // Up buffers, transferring information up from target via debug probe to host
|
||||
SEGGER_RTT_BUFFER_DOWN aDown[SEGGER_RTT_MAX_NUM_DOWN_BUFFERS]; // Down buffers, transferring information down from host via debug probe to target
|
||||
#if SEGGER_RTT__CB_PADDING
|
||||
unsigned char aDummy[SEGGER_RTT__CB_PADDING];
|
||||
#endif
|
||||
} SEGGER_RTT_CB;
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Global data
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
extern SEGGER_RTT_CB _SEGGER_RTT;
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* RTT API functions
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
int SEGGER_RTT_AllocDownBuffer (const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags);
|
||||
int SEGGER_RTT_AllocUpBuffer (const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags);
|
||||
int SEGGER_RTT_ConfigUpBuffer (unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags);
|
||||
int SEGGER_RTT_ConfigDownBuffer (unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags);
|
||||
int SEGGER_RTT_GetKey (void);
|
||||
unsigned SEGGER_RTT_HasData (unsigned BufferIndex);
|
||||
int SEGGER_RTT_HasKey (void);
|
||||
unsigned SEGGER_RTT_HasDataUp (unsigned BufferIndex);
|
||||
void SEGGER_RTT_Init (void);
|
||||
unsigned SEGGER_RTT_Read (unsigned BufferIndex, void* pBuffer, unsigned BufferSize);
|
||||
unsigned SEGGER_RTT_ReadNoLock (unsigned BufferIndex, void* pData, unsigned BufferSize);
|
||||
int SEGGER_RTT_SetNameDownBuffer (unsigned BufferIndex, const char* sName);
|
||||
int SEGGER_RTT_SetNameUpBuffer (unsigned BufferIndex, const char* sName);
|
||||
int SEGGER_RTT_SetFlagsDownBuffer (unsigned BufferIndex, unsigned Flags);
|
||||
int SEGGER_RTT_SetFlagsUpBuffer (unsigned BufferIndex, unsigned Flags);
|
||||
int SEGGER_RTT_WaitKey (void);
|
||||
unsigned SEGGER_RTT_Write (unsigned BufferIndex, const void* pBuffer, unsigned NumBytes);
|
||||
unsigned SEGGER_RTT_WriteNoLock (unsigned BufferIndex, const void* pBuffer, unsigned NumBytes);
|
||||
unsigned SEGGER_RTT_WriteSkipNoLock (unsigned BufferIndex, const void* pBuffer, unsigned NumBytes);
|
||||
unsigned SEGGER_RTT_ASM_WriteSkipNoLock (unsigned BufferIndex, const void* pBuffer, unsigned NumBytes);
|
||||
unsigned SEGGER_RTT_WriteString (unsigned BufferIndex, const char* s);
|
||||
void SEGGER_RTT_WriteWithOverwriteNoLock(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes);
|
||||
unsigned SEGGER_RTT_PutChar (unsigned BufferIndex, char c);
|
||||
unsigned SEGGER_RTT_PutCharSkip (unsigned BufferIndex, char c);
|
||||
unsigned SEGGER_RTT_PutCharSkipNoLock (unsigned BufferIndex, char c);
|
||||
unsigned SEGGER_RTT_GetAvailWriteSpace (unsigned BufferIndex);
|
||||
unsigned SEGGER_RTT_GetBytesInBuffer (unsigned BufferIndex);
|
||||
|
||||
void SEGGER_RTT_ESP_FlushNoLock (unsigned long min_sz, unsigned long tmo);
|
||||
void SEGGER_RTT_ESP_Flush (unsigned long min_sz, unsigned long tmo);
|
||||
//
|
||||
// Function macro for performance optimization
|
||||
//
|
||||
// @AGv: This macro is used inside SEGGER SystemView code.
|
||||
// For ESP32 we use our own implementation of RTT, so this macro should not check SEGGER's RTT buffer state.
|
||||
#define SEGGER_RTT_HASDATA(n) (1)
|
||||
|
||||
#if RTT_USE_ASM
|
||||
#define SEGGER_RTT_WriteSkipNoLock SEGGER_RTT_ASM_WriteSkipNoLock
|
||||
#endif
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* RTT transfer functions to send RTT data via other channels.
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
unsigned SEGGER_RTT_ReadUpBuffer (unsigned BufferIndex, void* pBuffer, unsigned BufferSize);
|
||||
unsigned SEGGER_RTT_ReadUpBufferNoLock (unsigned BufferIndex, void* pData, unsigned BufferSize);
|
||||
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
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* RTT "Terminal" API functions
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
int SEGGER_RTT_SetTerminal (unsigned char TerminalId);
|
||||
int SEGGER_RTT_TerminalOut (unsigned char TerminalId, const char* s);
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* RTT printf functions (require SEGGER_RTT_printf.c)
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
int SEGGER_RTT_printf(unsigned BufferIndex, const char * sFormat, ...);
|
||||
int SEGGER_RTT_vprintf(unsigned BufferIndex, const char * sFormat, va_list * pParamList);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // ifndef(SEGGER_RTT_ASM)
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Defines
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
//
|
||||
// Operating modes. Define behavior if buffer is full (not enough space for entire message)
|
||||
//
|
||||
#define SEGGER_RTT_MODE_NO_BLOCK_SKIP (0) // Skip. Do not block, output nothing. (Default)
|
||||
#define SEGGER_RTT_MODE_NO_BLOCK_TRIM (1) // Trim: Do not block, output as much as fits.
|
||||
#define SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL (2) // Block: Wait until there is space in the buffer.
|
||||
#define SEGGER_RTT_MODE_MASK (3)
|
||||
|
||||
//
|
||||
// Control sequences, based on ANSI.
|
||||
// Can be used to control color, and clear the screen
|
||||
//
|
||||
#define RTT_CTRL_RESET "\x1B[0m" // Reset to default colors
|
||||
#define RTT_CTRL_CLEAR "\x1B[2J" // Clear screen, reposition cursor to top left
|
||||
|
||||
#define RTT_CTRL_TEXT_BLACK "\x1B[2;30m"
|
||||
#define RTT_CTRL_TEXT_RED "\x1B[2;31m"
|
||||
#define RTT_CTRL_TEXT_GREEN "\x1B[2;32m"
|
||||
#define RTT_CTRL_TEXT_YELLOW "\x1B[2;33m"
|
||||
#define RTT_CTRL_TEXT_BLUE "\x1B[2;34m"
|
||||
#define RTT_CTRL_TEXT_MAGENTA "\x1B[2;35m"
|
||||
#define RTT_CTRL_TEXT_CYAN "\x1B[2;36m"
|
||||
#define RTT_CTRL_TEXT_WHITE "\x1B[2;37m"
|
||||
|
||||
#define RTT_CTRL_TEXT_BRIGHT_BLACK "\x1B[1;30m"
|
||||
#define RTT_CTRL_TEXT_BRIGHT_RED "\x1B[1;31m"
|
||||
#define RTT_CTRL_TEXT_BRIGHT_GREEN "\x1B[1;32m"
|
||||
#define RTT_CTRL_TEXT_BRIGHT_YELLOW "\x1B[1;33m"
|
||||
#define RTT_CTRL_TEXT_BRIGHT_BLUE "\x1B[1;34m"
|
||||
#define RTT_CTRL_TEXT_BRIGHT_MAGENTA "\x1B[1;35m"
|
||||
#define RTT_CTRL_TEXT_BRIGHT_CYAN "\x1B[1;36m"
|
||||
#define RTT_CTRL_TEXT_BRIGHT_WHITE "\x1B[1;37m"
|
||||
|
||||
#define RTT_CTRL_BG_BLACK "\x1B[24;40m"
|
||||
#define RTT_CTRL_BG_RED "\x1B[24;41m"
|
||||
#define RTT_CTRL_BG_GREEN "\x1B[24;42m"
|
||||
#define RTT_CTRL_BG_YELLOW "\x1B[24;43m"
|
||||
#define RTT_CTRL_BG_BLUE "\x1B[24;44m"
|
||||
#define RTT_CTRL_BG_MAGENTA "\x1B[24;45m"
|
||||
#define RTT_CTRL_BG_CYAN "\x1B[24;46m"
|
||||
#define RTT_CTRL_BG_WHITE "\x1B[24;47m"
|
||||
|
||||
#define RTT_CTRL_BG_BRIGHT_BLACK "\x1B[4;40m"
|
||||
#define RTT_CTRL_BG_BRIGHT_RED "\x1B[4;41m"
|
||||
#define RTT_CTRL_BG_BRIGHT_GREEN "\x1B[4;42m"
|
||||
#define RTT_CTRL_BG_BRIGHT_YELLOW "\x1B[4;43m"
|
||||
#define RTT_CTRL_BG_BRIGHT_BLUE "\x1B[4;44m"
|
||||
#define RTT_CTRL_BG_BRIGHT_MAGENTA "\x1B[4;45m"
|
||||
#define RTT_CTRL_BG_BRIGHT_CYAN "\x1B[4;46m"
|
||||
#define RTT_CTRL_BG_BRIGHT_WHITE "\x1B[4;47m"
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
/*************************** End of file ****************************/
|
||||
3645
components/app_trace/sys_view/SEGGER/SEGGER_SYSVIEW.c
Normal file
3645
components/app_trace/sys_view/SEGGER/SEGGER_SYSVIEW.c
Normal file
File diff suppressed because it is too large
Load Diff
436
components/app_trace/sys_view/SEGGER/SEGGER_SYSVIEW.h
Normal file
436
components/app_trace/sys_view/SEGGER/SEGGER_SYSVIEW.h
Normal file
@@ -0,0 +1,436 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 1995-2021 SEGGER Microcontroller GmbH
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-1-Clause
|
||||
*
|
||||
* SPDX-FileContributor: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*/
|
||||
/*********************************************************************
|
||||
* SEGGER Microcontroller GmbH *
|
||||
* The Embedded Experts *
|
||||
**********************************************************************
|
||||
* *
|
||||
* (c) 1995 - 2024 SEGGER Microcontroller GmbH *
|
||||
* *
|
||||
* www.segger.com Support: support@segger.com *
|
||||
* *
|
||||
**********************************************************************
|
||||
* *
|
||||
* SEGGER SystemView * Real-time application analysis *
|
||||
* *
|
||||
**********************************************************************
|
||||
* *
|
||||
* All rights reserved. *
|
||||
* *
|
||||
* SEGGER strongly recommends to not make any changes *
|
||||
* to or modify the source code of this software in order to stay *
|
||||
* compatible with the SystemView and RTT protocol, and J-Link. *
|
||||
* *
|
||||
* Redistribution and use in source and binary forms, with or *
|
||||
* without modification, are permitted provided that the following *
|
||||
* condition is met: *
|
||||
* *
|
||||
* o Redistributions of source code must retain the above copyright *
|
||||
* notice, this condition and the following disclaimer. *
|
||||
* *
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND *
|
||||
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, *
|
||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF *
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE *
|
||||
* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR *
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR *
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT *
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; *
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE *
|
||||
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH *
|
||||
* DAMAGE. *
|
||||
* *
|
||||
**********************************************************************
|
||||
* *
|
||||
* SystemView version: 3.56 *
|
||||
* *
|
||||
**********************************************************************
|
||||
-------------------------- END-OF-HEADER -----------------------------
|
||||
File : SEGGER_SYSVIEW.h
|
||||
Purpose : System visualization API.
|
||||
Revision: $Rev: 28768 $
|
||||
*/
|
||||
|
||||
#ifndef SEGGER_SYSVIEW_H
|
||||
#define SEGGER_SYSVIEW_H
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* #include Section
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
#include "SEGGER.h"
|
||||
#include "SEGGER_SYSVIEW_ConfDefaults.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Defines, fixed
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
#define SEGGER_SYSVIEW_MAJOR 3
|
||||
#define SEGGER_SYSVIEW_MINOR 32
|
||||
#define SEGGER_SYSVIEW_REV 0
|
||||
#define SEGGER_SYSVIEW_VERSION ((SEGGER_SYSVIEW_MAJOR * 10000) + (SEGGER_SYSVIEW_MINOR * 100) + SEGGER_SYSVIEW_REV)
|
||||
|
||||
#define SEGGER_SYSVIEW_INFO_SIZE 9 // Minimum size, which has to be reserved for a packet. 1-2 byte of message type, 0-2 byte of payload length, 1-5 bytes of timestamp.
|
||||
#define SEGGER_SYSVIEW_QUANTA_U32 5 // Maximum number of bytes to encode a U32, should be reserved for each 32-bit value in a packet.
|
||||
|
||||
#define SEGGER_SYSVIEW_LOG (0u)
|
||||
#define SEGGER_SYSVIEW_WARNING (1u)
|
||||
#define SEGGER_SYSVIEW_ERROR (2u)
|
||||
#define SEGGER_SYSVIEW_FLAG_APPEND (1u << 6)
|
||||
|
||||
#define SEGGER_SYSVIEW_PREPARE_PACKET(p) (p) + 4
|
||||
//
|
||||
// SystemView events. First 32 IDs from 0 .. 31 are reserved for these
|
||||
//
|
||||
#define SYSVIEW_EVTID_NOP 0 // Dummy packet.
|
||||
#define SYSVIEW_EVTID_OVERFLOW 1
|
||||
#define SYSVIEW_EVTID_ISR_ENTER 2
|
||||
#define SYSVIEW_EVTID_ISR_EXIT 3
|
||||
#define SYSVIEW_EVTID_TASK_START_EXEC 4
|
||||
#define SYSVIEW_EVTID_TASK_STOP_EXEC 5
|
||||
#define SYSVIEW_EVTID_TASK_START_READY 6
|
||||
#define SYSVIEW_EVTID_TASK_STOP_READY 7
|
||||
#define SYSVIEW_EVTID_TASK_CREATE 8
|
||||
#define SYSVIEW_EVTID_TASK_INFO 9
|
||||
#define SYSVIEW_EVTID_TRACE_START 10
|
||||
#define SYSVIEW_EVTID_TRACE_STOP 11
|
||||
#define SYSVIEW_EVTID_SYSTIME_CYCLES 12
|
||||
#define SYSVIEW_EVTID_SYSTIME_US 13
|
||||
#define SYSVIEW_EVTID_SYSDESC 14
|
||||
#define SYSVIEW_EVTID_MARK_START 15
|
||||
#define SYSVIEW_EVTID_MARK_STOP 16
|
||||
#define SYSVIEW_EVTID_IDLE 17
|
||||
#define SYSVIEW_EVTID_ISR_TO_SCHEDULER 18
|
||||
#define SYSVIEW_EVTID_TIMER_ENTER 19
|
||||
#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
|
||||
#define SYSVIEW_EVTID_NUMMODULES 27
|
||||
#define SYSVIEW_EVTID_END_CALL 28
|
||||
#define SYSVIEW_EVTID_TASK_TERMINATE 29
|
||||
|
||||
#define SYSVIEW_EVTID_EX 31
|
||||
//
|
||||
// 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
|
||||
//
|
||||
// Event masks to disable/enable events
|
||||
//
|
||||
#define SYSVIEW_EVTMASK_NOP (1 << SYSVIEW_EVTID_NOP)
|
||||
#define SYSVIEW_EVTMASK_OVERFLOW (1 << SYSVIEW_EVTID_OVERFLOW)
|
||||
#define SYSVIEW_EVTMASK_ISR_ENTER (1 << SYSVIEW_EVTID_ISR_ENTER)
|
||||
#define SYSVIEW_EVTMASK_ISR_EXIT (1 << SYSVIEW_EVTID_ISR_EXIT)
|
||||
#define SYSVIEW_EVTMASK_TASK_START_EXEC (1 << SYSVIEW_EVTID_TASK_START_EXEC)
|
||||
#define SYSVIEW_EVTMASK_TASK_STOP_EXEC (1 << SYSVIEW_EVTID_TASK_STOP_EXEC)
|
||||
#define SYSVIEW_EVTMASK_TASK_START_READY (1 << SYSVIEW_EVTID_TASK_START_READY)
|
||||
#define SYSVIEW_EVTMASK_TASK_STOP_READY (1 << SYSVIEW_EVTID_TASK_STOP_READY)
|
||||
#define SYSVIEW_EVTMASK_TASK_CREATE (1 << SYSVIEW_EVTID_TASK_CREATE)
|
||||
#define SYSVIEW_EVTMASK_TASK_INFO (1 << SYSVIEW_EVTID_TASK_INFO)
|
||||
#define SYSVIEW_EVTMASK_TRACE_START (1 << SYSVIEW_EVTID_TRACE_START)
|
||||
#define SYSVIEW_EVTMASK_TRACE_STOP (1 << SYSVIEW_EVTID_TRACE_STOP)
|
||||
#define SYSVIEW_EVTMASK_SYSTIME_CYCLES (1 << SYSVIEW_EVTID_SYSTIME_CYCLES)
|
||||
#define SYSVIEW_EVTMASK_SYSTIME_US (1 << SYSVIEW_EVTID_SYSTIME_US)
|
||||
#define SYSVIEW_EVTMASK_SYSDESC (1 << SYSVIEW_EVTID_SYSDESC)
|
||||
#define SYSVIEW_EVTMASK_USER_START (1 << SYSVIEW_EVTID_USER_START)
|
||||
#define SYSVIEW_EVTMASK_USER_STOP (1 << SYSVIEW_EVTID_USER_STOP)
|
||||
#define SYSVIEW_EVTMASK_IDLE (1 << SYSVIEW_EVTID_IDLE)
|
||||
#define SYSVIEW_EVTMASK_ISR_TO_SCHEDULER (1 << SYSVIEW_EVTID_ISR_TO_SCHEDULER)
|
||||
#define SYSVIEW_EVTMASK_TIMER_ENTER (1 << SYSVIEW_EVTID_TIMER_ENTER)
|
||||
#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)
|
||||
#define SYSVIEW_EVTMASK_NUMMODULES (1 << SYSVIEW_EVTID_NUMMODULES)
|
||||
#define SYSVIEW_EVTMASK_END_CALL (1 << SYSVIEW_EVTID_END_CALL)
|
||||
#define SYSVIEW_EVTMASK_TASK_TERMINATE (1 << SYSVIEW_EVTID_TASK_TERMINATE)
|
||||
|
||||
#define SYSVIEW_EVTMASK_EX (1 << SYSVIEW_EVTID_EX)
|
||||
|
||||
#define SYSVIEW_EVTMASK_ALL_INTERRUPTS ( SYSVIEW_EVTMASK_ISR_ENTER \
|
||||
| SYSVIEW_EVTMASK_ISR_EXIT \
|
||||
| SYSVIEW_EVTMASK_ISR_TO_SCHEDULER)
|
||||
#define SYSVIEW_EVTMASK_ALL_TASKS ( SYSVIEW_EVTMASK_TASK_START_EXEC \
|
||||
| SYSVIEW_EVTMASK_TASK_STOP_EXEC \
|
||||
| SYSVIEW_EVTMASK_TASK_START_READY \
|
||||
| SYSVIEW_EVTMASK_TASK_STOP_READY \
|
||||
| SYSVIEW_EVTMASK_TASK_CREATE \
|
||||
| SYSVIEW_EVTMASK_TASK_INFO \
|
||||
| SYSVIEW_EVTMASK_STACK_INFO \
|
||||
| SYSVIEW_EVTMASK_TASK_TERMINATE)
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Structures
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
U32 TaskID;
|
||||
const char* sName;
|
||||
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 {
|
||||
const char* sModule;
|
||||
U32 NumEvents;
|
||||
U32 EventOffset;
|
||||
void (*pfSendModuleDesc)(void);
|
||||
SEGGER_SYSVIEW_MODULE* pNext;
|
||||
};
|
||||
|
||||
typedef void (SEGGER_SYSVIEW_SEND_SYS_DESC_FUNC)(void);
|
||||
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Global data
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
#ifdef EXTERN
|
||||
#undef EXTERN
|
||||
#endif
|
||||
|
||||
#ifndef SEGGER_SYSVIEW_C // Defined in SEGGER_SYSVIEW.c which includes this header beside other C-files
|
||||
#define EXTERN extern
|
||||
#else
|
||||
#define EXTERN
|
||||
#endif
|
||||
|
||||
EXTERN unsigned int SEGGER_SYSVIEW_TickCnt;
|
||||
EXTERN unsigned int SEGGER_SYSVIEW_InterruptId;
|
||||
|
||||
#undef EXTERN
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* API functions
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
U64 (*pfGetTime) (void);
|
||||
void (*pfSendTaskList) (void);
|
||||
} SEGGER_SYSVIEW_OS_API;
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Control and initialization functions
|
||||
*/
|
||||
void SEGGER_SYSVIEW_Init (U32 SysFreq, U32 CPUFreq, const SEGGER_SYSVIEW_OS_API *pOSAPI, SEGGER_SYSVIEW_SEND_SYS_DESC_FUNC pfSendSysDesc);
|
||||
void SEGGER_SYSVIEW_SetRAMBase (U32 RAMBaseAddress);
|
||||
void SEGGER_SYSVIEW_Start (void);
|
||||
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);
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Event recording functions
|
||||
*/
|
||||
void SEGGER_SYSVIEW_RecordVoid (unsigned int EventId);
|
||||
void SEGGER_SYSVIEW_RecordU32 (unsigned int EventId, U32 Para0);
|
||||
void SEGGER_SYSVIEW_RecordU32x2 (unsigned int EventId, U32 Para0, U32 Para1);
|
||||
void SEGGER_SYSVIEW_RecordU32x3 (unsigned int EventId, U32 Para0, U32 Para1, U32 Para2);
|
||||
void SEGGER_SYSVIEW_RecordU32x4 (unsigned int EventId, U32 Para0, U32 Para1, U32 Para2, U32 Para3);
|
||||
void SEGGER_SYSVIEW_RecordU32x5 (unsigned int EventId, U32 Para0, U32 Para1, U32 Para2, U32 Para3, U32 Para4);
|
||||
void SEGGER_SYSVIEW_RecordU32x6 (unsigned int EventId, U32 Para0, U32 Para1, U32 Para2, U32 Para3, U32 Para4, U32 Para5);
|
||||
void SEGGER_SYSVIEW_RecordU32x7 (unsigned int EventId, U32 Para0, U32 Para1, U32 Para2, U32 Para3, U32 Para4, U32 Para5, U32 Para6);
|
||||
void SEGGER_SYSVIEW_RecordU32x8 (unsigned int EventId, U32 Para0, U32 Para1, U32 Para2, U32 Para3, U32 Para4, U32 Para5, U32 Para6, U32 Para7);
|
||||
void SEGGER_SYSVIEW_RecordU32x9 (unsigned int EventId, U32 Para0, U32 Para1, U32 Para2, U32 Para3, U32 Para4, U32 Para5, U32 Para6, U32 Para7, U32 Para8);
|
||||
void SEGGER_SYSVIEW_RecordU32x10 (unsigned int EventId, U32 Para0, U32 Para1, U32 Para2, U32 Para3, U32 Para4, U32 Para5, U32 Para6, U32 Para7, U32 Para8, U32 Para9);
|
||||
void SEGGER_SYSVIEW_RecordString (unsigned int EventId, const char* pString);
|
||||
void SEGGER_SYSVIEW_RecordSystime (void);
|
||||
void SEGGER_SYSVIEW_RecordEnterISR (U32 IrqId);
|
||||
void SEGGER_SYSVIEW_RecordExitISR (void);
|
||||
void SEGGER_SYSVIEW_RecordExitISRToScheduler (void);
|
||||
void SEGGER_SYSVIEW_RecordEnterTimer (U32 TimerId);
|
||||
void SEGGER_SYSVIEW_RecordExitTimer (void);
|
||||
void SEGGER_SYSVIEW_RecordEndCall (unsigned int EventID);
|
||||
void SEGGER_SYSVIEW_RecordEndCallU32 (unsigned int EventID, U32 Para0);
|
||||
|
||||
void SEGGER_SYSVIEW_OnIdle (void);
|
||||
void SEGGER_SYSVIEW_OnTaskCreate (U32 TaskId);
|
||||
void SEGGER_SYSVIEW_OnTaskTerminate (U32 TaskId);
|
||||
void SEGGER_SYSVIEW_OnTaskStartExec (U32 TaskId);
|
||||
void SEGGER_SYSVIEW_OnTaskStopExec (void);
|
||||
void SEGGER_SYSVIEW_OnTaskStartReady (U32 TaskId);
|
||||
void SEGGER_SYSVIEW_OnTaskStopReady (U32 TaskId, unsigned int Cause);
|
||||
void SEGGER_SYSVIEW_MarkStart (unsigned int MarkerId);
|
||||
void SEGGER_SYSVIEW_MarkStop (unsigned int MarkerId);
|
||||
void SEGGER_SYSVIEW_Mark (unsigned int MarkerId);
|
||||
void SEGGER_SYSVIEW_NameMarker (unsigned int MarkerId, const char* sName);
|
||||
|
||||
void SEGGER_SYSVIEW_HeapDefine (void* pHeap, void* pBase, unsigned int HeapSize, unsigned int MetadataSize);
|
||||
void SEGGER_SYSVIEW_HeapAlloc (void* pHeap, void* pUserData, unsigned int UserDataLen);
|
||||
void SEGGER_SYSVIEW_HeapAllocEx (void* pHeap, void* pUserData, unsigned int UserDataLen, unsigned int Tag);
|
||||
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);
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Event parameter encoding functions
|
||||
*/
|
||||
U8* SEGGER_SYSVIEW_EncodeU32 (U8* pPayload, U32 Value);
|
||||
U8* SEGGER_SYSVIEW_EncodeData (U8* pPayload, const char* pSrc, unsigned int Len);
|
||||
U8* SEGGER_SYSVIEW_EncodeString (U8* pPayload, const char* s, unsigned int MaxLen);
|
||||
U8* SEGGER_SYSVIEW_EncodeId (U8* pPayload, U32 Id);
|
||||
U32 SEGGER_SYSVIEW_ShrinkId (U32 Id);
|
||||
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Middleware module registration
|
||||
*/
|
||||
void SEGGER_SYSVIEW_RegisterModule (SEGGER_SYSVIEW_MODULE* pModule);
|
||||
void SEGGER_SYSVIEW_RecordModuleDescription (const SEGGER_SYSVIEW_MODULE* pModule, const char* sDescription);
|
||||
void SEGGER_SYSVIEW_SendModule (U8 ModuleId);
|
||||
void SEGGER_SYSVIEW_SendModuleDescription (void);
|
||||
void SEGGER_SYSVIEW_SendNumModules (void);
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* printf-Style functions
|
||||
*/
|
||||
#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);
|
||||
void SEGGER_SYSVIEW_Warn (const char* s);
|
||||
void SEGGER_SYSVIEW_Error (const char* s);
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Run-time configuration functions
|
||||
*/
|
||||
void SEGGER_SYSVIEW_EnableEvents (U32 EnableMask);
|
||||
void SEGGER_SYSVIEW_DisableEvents (U32 DisableMask);
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Application-provided functions
|
||||
*/
|
||||
void SEGGER_SYSVIEW_Conf (void);
|
||||
U32 SEGGER_SYSVIEW_X_GetTimestamp (void);
|
||||
U32 SEGGER_SYSVIEW_X_GetInterruptId (void);
|
||||
|
||||
void SEGGER_SYSVIEW_X_StartComm (void);
|
||||
void SEGGER_SYSVIEW_X_OnEventRecorded (unsigned NumBytes);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Compatibility API defines
|
||||
*/
|
||||
#define SEGGER_SYSVIEW_OnUserStart SEGGER_SYSVIEW_MarkStart
|
||||
#define SEGGER_SYSVIEW_OnUserStop SEGGER_SYSVIEW_MarkStop
|
||||
|
||||
#endif
|
||||
|
||||
/*************************** End of file ****************************/
|
||||
@@ -0,0 +1,592 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 1995-2021 SEGGER Microcontroller GmbH
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-1-Clause
|
||||
*
|
||||
* SPDX-FileContributor: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*/
|
||||
/*********************************************************************
|
||||
* SEGGER Microcontroller GmbH *
|
||||
* The Embedded Experts *
|
||||
**********************************************************************
|
||||
* *
|
||||
* (c) 1995 - 2024 SEGGER Microcontroller GmbH *
|
||||
* *
|
||||
* www.segger.com Support: support@segger.com *
|
||||
* *
|
||||
**********************************************************************
|
||||
* *
|
||||
* SEGGER SystemView * Real-time application analysis *
|
||||
* *
|
||||
**********************************************************************
|
||||
* *
|
||||
* All rights reserved. *
|
||||
* *
|
||||
* SEGGER strongly recommends to not make any changes *
|
||||
* to or modify the source code of this software in order to stay *
|
||||
* compatible with the SystemView and RTT protocol, and J-Link. *
|
||||
* *
|
||||
* Redistribution and use in source and binary forms, with or *
|
||||
* without modification, are permitted provided that the following *
|
||||
* condition is met: *
|
||||
* *
|
||||
* o Redistributions of source code must retain the above copyright *
|
||||
* notice, this condition and the following disclaimer. *
|
||||
* *
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND *
|
||||
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, *
|
||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF *
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE *
|
||||
* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR *
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR *
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT *
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; *
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE *
|
||||
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH *
|
||||
* DAMAGE. *
|
||||
* *
|
||||
**********************************************************************
|
||||
* *
|
||||
* SystemView version: 3.56 *
|
||||
* *
|
||||
**********************************************************************
|
||||
-------------------------- END-OF-HEADER -----------------------------
|
||||
File : SEGGER_SYSVIEW_ConfDefaults.h
|
||||
Purpose : Defines defaults for configurable defines used in
|
||||
SEGGER SystemView.
|
||||
Revision: $Rev: 26230 $
|
||||
*/
|
||||
|
||||
#ifndef SEGGER_SYSVIEW_CONFDEFAULTS_H
|
||||
#define SEGGER_SYSVIEW_CONFDEFAULTS_H
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* #include Section
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
#include "SEGGER_SYSVIEW_Conf.h"
|
||||
#include "SEGGER_RTT_Conf.h"
|
||||
|
||||
#include "esp_assert.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Defines, fixed
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
//
|
||||
// Use auto-detection for SEGGER_SYSVIEW_CORE define
|
||||
// based on compiler-/toolchain-specific defines
|
||||
// to define SEGGER_SYSVIEW_GET_INTERRUPT_ID and SEGGER_SYSVIEW_GET_TIMESTAMP
|
||||
//
|
||||
#define SEGGER_SYSVIEW_CORE_OTHER 0
|
||||
#define SEGGER_SYSVIEW_CORE_CM0 1 // Cortex-M0/M0+/M1
|
||||
#define SEGGER_SYSVIEW_CORE_CM3 2 // Cortex-M3/M4/M7
|
||||
#define SEGGER_SYSVIEW_CORE_RX 3 // Renesas RX
|
||||
#ifndef SEGGER_SYSVIEW_CORE
|
||||
#if (defined __SES_ARM) || (defined __CROSSWORKS_ARM) || (defined __SEGGER_CC__) || (defined __GNUC__) || (defined __clang__)
|
||||
#if (defined __ARM_ARCH_6M__) || (defined __ARM_ARCH_8M_BASE__)
|
||||
#define SEGGER_SYSVIEW_CORE SEGGER_SYSVIEW_CORE_CM0
|
||||
#elif (defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__) || defined(__ARM_ARCH_8M_MAIN__))
|
||||
#define SEGGER_SYSVIEW_CORE SEGGER_SYSVIEW_CORE_CM3
|
||||
#endif
|
||||
#elif defined(__ICCARM__)
|
||||
#if (defined (__ARM6M__) && (__CORE__ == __ARM6M__)) \
|
||||
|| (defined (__ARM8M_BASELINE__) && (__CORE__ == __ARM8M_BASELINE__))
|
||||
#define SEGGER_SYSVIEW_CORE SEGGER_SYSVIEW_CORE_CM0
|
||||
#elif (defined (__ARM7EM__) && (__CORE__ == __ARM7EM__)) \
|
||||
|| (defined (__ARM7M__) && (__CORE__ == __ARM7M__)) \
|
||||
|| (defined (__ARM8M_MAINLINE__) && (__CORE__ == __ARM8M_MAINLINE__)) \
|
||||
|| (defined (__ARM8M_MAINLINE__) && (__CORE__ == __ARM8M_MAINLINE__))
|
||||
#define SEGGER_SYSVIEW_CORE SEGGER_SYSVIEW_CORE_CM3
|
||||
#endif
|
||||
#elif defined(__CC_ARM)
|
||||
#if (defined(__TARGET_ARCH_6S_M))
|
||||
#define SEGGER_SYSVIEW_CORE SEGGER_SYSVIEW_CORE_CM0
|
||||
#elif (defined(__TARGET_ARCH_7_M) || defined(__TARGET_ARCH_7E_M))
|
||||
#define SEGGER_SYSVIEW_CORE SEGGER_SYSVIEW_CORE_CM3
|
||||
#endif
|
||||
#elif defined(__TI_ARM__)
|
||||
#ifdef __TI_ARM_V6M0__
|
||||
#define SEGGER_SYSVIEW_CORE SEGGER_SYSVIEW_CORE_CM0
|
||||
#elif (defined(__TI_ARM_V7M3__) || defined(__TI_ARM_V7M4__))
|
||||
#define SEGGER_SYSVIEW_CORE SEGGER_SYSVIEW_CORE_CM3
|
||||
#endif
|
||||
#elif defined(__ICCRX__)
|
||||
#define SEGGER_SYSVIEW_CORE SEGGER_SYSVIEW_CORE_RX
|
||||
#elif defined(__RX)
|
||||
#define SEGGER_SYSVIEW_CORE SEGGER_SYSVIEW_CORE_RX
|
||||
#endif
|
||||
|
||||
#ifndef SEGGER_SYSVIEW_CORE
|
||||
#define SEGGER_SYSVIEW_CORE SEGGER_SYSVIEW_CORE_OTHER
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Defines, defaults
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
/*********************************************************************
|
||||
*
|
||||
* Define: SEGGER_SYSVIEW_APP_NAME
|
||||
*
|
||||
* Description
|
||||
* The application name to be displayed in SystemView.
|
||||
* Default
|
||||
* "SystemView-enabled Application"
|
||||
* Notes
|
||||
* Convenience define to be used for SEGGER_SYSVIEW_SendSysDesc().
|
||||
*/
|
||||
#ifndef SEGGER_SYSVIEW_APP_NAME
|
||||
#define SEGGER_SYSVIEW_APP_NAME "SystemView-enabled Application"
|
||||
#endif
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Define: SEGGER_SYSVIEW_DEVICE_NAME
|
||||
*
|
||||
* Description
|
||||
* The target device name to be displayed in SystemView.
|
||||
* Default
|
||||
* "undefined device"
|
||||
* Notes
|
||||
* Convenience define to be used for SEGGER_SYSVIEW_SendSysDesc().
|
||||
*/
|
||||
#ifndef SEGGER_SYSVIEW_DEVICE_NAME
|
||||
#define SEGGER_SYSVIEW_DEVICE_NAME "undefined device"
|
||||
#endif
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Define: SEGGER_SYSVIEW_GET_INTERRUPT_ID()
|
||||
*
|
||||
* Description
|
||||
* Function macro to retrieve the Id of the currently active
|
||||
* interrupt.
|
||||
* Default
|
||||
* Call user-supplied function SEGGER_SYSVIEW_X_GetInterruptId().
|
||||
* Notes
|
||||
* For some known compilers and cores, a ready-to-use, core-specific
|
||||
* default is set.
|
||||
* ARMv7M: Read ICSR[8:0] (active vector)
|
||||
* ARMv6M: Read ICSR[5:0] (active vector)
|
||||
*/
|
||||
#ifndef SEGGER_SYSVIEW_GET_INTERRUPT_ID
|
||||
#if SEGGER_SYSVIEW_CORE == SEGGER_SYSVIEW_CORE_CM3
|
||||
#define SEGGER_SYSVIEW_GET_INTERRUPT_ID() ((*(U32*)(0xE000ED04)) & 0x1FF) // Get the currently active interrupt Id. (i.e. read Cortex-M ICSR[8:0] = active vector)
|
||||
#elif SEGGER_SYSVIEW_CORE == SEGGER_SYSVIEW_CORE_CM0
|
||||
#if defined(__ICCARM__)
|
||||
#if (__VER__ > 6010000)
|
||||
#define SEGGER_SYSVIEW_GET_INTERRUPT_ID() (__get_IPSR()) // Workaround for IAR, which might do a byte-access to 0xE000ED04. Read IPSR instead.
|
||||
#else
|
||||
#define SEGGER_SYSVIEW_GET_INTERRUPT_ID() ((*(U32*)(0xE000ED04)) & 0x3F) // Older versions of IAR do not include __get_IPSR, but might also not optimize to byte-access.
|
||||
#endif
|
||||
#else
|
||||
#define SEGGER_SYSVIEW_GET_INTERRUPT_ID() ((*(U32*)(0xE000ED04)) & 0x3F) // Get the currently active interrupt Id. (i.e. read Cortex-M ICSR[5:0] = active vector)
|
||||
#endif
|
||||
#else
|
||||
#define SEGGER_SYSVIEW_GET_INTERRUPT_ID() SEGGER_SYSVIEW_X_GetInterruptId() // Get the currently active interrupt Id from the user-provided function.
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Define: SEGGER_SYSVIEW_GET_TIMESTAMP()
|
||||
*
|
||||
* Description
|
||||
* Function macro to retrieve a system timestamp for SYSVIEW events.
|
||||
* Default
|
||||
* Call user-supplied function SEGGER_SYSVIEW_X_GetTimestamp().
|
||||
* Notes
|
||||
* For some known compilers and cores, a ready-to-use, core-specific
|
||||
* default is set.
|
||||
* ARMv7M: Read Cortex-M Cycle Count register.
|
||||
*
|
||||
* The system timestamp clock frequency has to be passed in
|
||||
* SEGGER_SYSVIEW_Init().
|
||||
*/
|
||||
#ifndef SEGGER_SYSVIEW_GET_TIMESTAMP
|
||||
#if defined (SEGGER_SYSVIEW_CORE) && (SEGGER_SYSVIEW_CORE == SEGGER_SYSVIEW_CORE_CM3)
|
||||
#define SEGGER_SYSVIEW_GET_TIMESTAMP() (*(U32 *)(0xE0001004)) // Retrieve a system timestamp. Cortex-M cycle counter.
|
||||
#else
|
||||
#define SEGGER_SYSVIEW_GET_TIMESTAMP() SEGGER_SYSVIEW_X_GetTimestamp() // Retrieve a system timestamp via user-defined function
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Define: SEGGER_SYSVIEW_TIMESTAMP_BITS
|
||||
*
|
||||
* Description
|
||||
* Number of valid (low-order) bits delivered in system timestamp.
|
||||
* Default
|
||||
* 32
|
||||
* Notes
|
||||
* Value has to match system timestamp clock source.
|
||||
*/
|
||||
// Define number of valid bits low-order delivered by clock source.
|
||||
#ifndef SEGGER_SYSVIEW_TIMESTAMP_BITS
|
||||
#define SEGGER_SYSVIEW_TIMESTAMP_BITS 32
|
||||
#endif
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Define: SEGGER_SYSVIEW_RTT_CHANNEL
|
||||
*
|
||||
* Description
|
||||
* The RTT channel that SystemView will use.
|
||||
* Default
|
||||
* 0: Auto selection.
|
||||
* Notes
|
||||
* Value has to be lower than SEGGER_RTT_MAX_NUM_UP_BUFFERS.
|
||||
*/
|
||||
#ifndef SEGGER_SYSVIEW_RTT_CHANNEL
|
||||
#define SEGGER_SYSVIEW_RTT_CHANNEL 1
|
||||
#endif
|
||||
// Sanity check of RTT channel
|
||||
#if (SEGGER_SYSVIEW_RTT_CHANNEL == 0) && (SEGGER_RTT_MAX_NUM_UP_BUFFERS < 2)
|
||||
#error "SEGGER_RTT_MAX_NUM_UP_BUFFERS in SEGGER_RTT_Conf.h has to be > 1!"
|
||||
#elif (SEGGER_SYSVIEW_RTT_CHANNEL >= SEGGER_RTT_MAX_NUM_UP_BUFFERS)
|
||||
#error "SEGGER_RTT_MAX_NUM_UP_BUFFERS in SEGGER_RTT_Conf.h has to be > SEGGER_SYSVIEW_RTT_CHANNEL!"
|
||||
#endif
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Define: SEGGER_SYSVIEW_RTT_BUFFER_SIZE
|
||||
*
|
||||
* Description
|
||||
* Number of bytes that SystemView uses for the RTT buffer.
|
||||
* Default
|
||||
* 1024
|
||||
*/
|
||||
#ifndef SEGGER_SYSVIEW_RTT_BUFFER_SIZE
|
||||
#define SEGGER_SYSVIEW_RTT_BUFFER_SIZE 1024
|
||||
#endif
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Define: SEGGER_SYSVIEW_SECTION
|
||||
*
|
||||
* Description
|
||||
* Section to place the SystemView RTT Buffer into.
|
||||
* Default
|
||||
* undefined: Do not place into a specific section.
|
||||
* Notes
|
||||
* If SEGGER_RTT_SECTION is defined, the default changes to use
|
||||
* this section for the SystemView RTT Buffer, too.
|
||||
*/
|
||||
#if !(defined SEGGER_SYSVIEW_SECTION) && (defined SEGGER_RTT_SECTION)
|
||||
#define SEGGER_SYSVIEW_SECTION SEGGER_RTT_SECTION
|
||||
#endif
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Define: SEGGER_SYSVIEW_CPU_CACHE_LINE_SIZE
|
||||
*
|
||||
* Description
|
||||
* Largest cache line size (in bytes) in the target system.
|
||||
* Default
|
||||
* 0
|
||||
* Notes
|
||||
* Required in systems with caches to make sure that the SystemView
|
||||
* RTT buffer can be aligned accordingly.
|
||||
*/
|
||||
#ifndef SEGGER_SYSVIEW_CPU_CACHE_LINE_SIZE
|
||||
#define SEGGER_SYSVIEW_CPU_CACHE_LINE_SIZE 0
|
||||
#endif
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Define: SEGGER_SYSVIEW_ID_BASE
|
||||
*
|
||||
* Description
|
||||
* Lowest Id reported by the application.
|
||||
* Default
|
||||
* 0
|
||||
* Notes
|
||||
* Value is usually subtracted from mailboxes, semaphores, tasks,
|
||||
* .... addresses, to compress event parameters.
|
||||
* Should be the lowest RAM address of the system.
|
||||
*/
|
||||
#ifndef SEGGER_SYSVIEW_ID_BASE
|
||||
#define SEGGER_SYSVIEW_ID_BASE 0
|
||||
#endif
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Define: SEGGER_SYSVIEW_ID_SHIFT
|
||||
*
|
||||
* Description
|
||||
* Number of bits to shift Ids.
|
||||
* Default
|
||||
* 0
|
||||
* Notes
|
||||
* Ids are shifted to compress event parameters.
|
||||
* Should match the alignment of Ids (addresses),
|
||||
* e.g. 2 when Ids are 4 byte aligned.
|
||||
*/
|
||||
#ifndef SEGGER_SYSVIEW_ID_SHIFT
|
||||
#define SEGGER_SYSVIEW_ID_SHIFT 0
|
||||
#endif
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Define: SEGGER_SYSVIEW_MAX_ARGUMENTS
|
||||
*
|
||||
* Description
|
||||
* Maximum number of arguments which are handled with SystemView
|
||||
* print routines or may be encoded in one recording function.
|
||||
* routines.
|
||||
* Default
|
||||
* 16
|
||||
*/
|
||||
#ifndef SEGGER_SYSVIEW_MAX_ARGUMENTS
|
||||
#define SEGGER_SYSVIEW_MAX_ARGUMENTS 16
|
||||
#endif
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Define: SEGGER_SYSVIEW_MAX_STRING_LEN
|
||||
*
|
||||
* Description
|
||||
* Maximum string length which can be used in SystemView print and
|
||||
* system description routines.
|
||||
* Default
|
||||
* 128
|
||||
*/
|
||||
#ifndef SEGGER_SYSVIEW_MAX_STRING_LEN
|
||||
#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.
|
||||
* Default
|
||||
* 1
|
||||
*/
|
||||
#ifndef SEGGER_SYSVIEW_SUPPORT_LONG_ID
|
||||
#define SEGGER_SYSVIEW_SUPPORT_LONG_ID 1
|
||||
#endif
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Define: SEGGER_SYSVIEW_SUPPORT_LONG_DATA
|
||||
*
|
||||
* Description
|
||||
* It set, support encoding event data longer than 14 bit.
|
||||
* Default
|
||||
* 0
|
||||
*/
|
||||
#ifndef SEGGER_SYSVIEW_SUPPORT_LONG_DATA
|
||||
#define SEGGER_SYSVIEW_SUPPORT_LONG_DATA 0
|
||||
#endif
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Define: SEGGER_SYSVIEW_PRINTF_IMPLICIT_FORMAT
|
||||
*
|
||||
* Description
|
||||
* If enabled, on SEGGER_SYSVIEW_PrintHost, check the format string
|
||||
* and if it includes unsupported formatters, use formatting on the
|
||||
* target instead.
|
||||
* Default
|
||||
* 0: Disabled.
|
||||
*/
|
||||
#ifndef SEGGER_SYSVIEW_PRINTF_IMPLICIT_FORMAT
|
||||
#define SEGGER_SYSVIEW_PRINTF_IMPLICIT_FORMAT 0
|
||||
#endif
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Define: SEGGER_SYSVIEW_USE_INTERNAL_RECORDER
|
||||
*
|
||||
* Description
|
||||
* If set, an internal recorder, such as UART or IP is used.
|
||||
* Default
|
||||
* 0: Disabled.
|
||||
* Notes
|
||||
* Convenience define to be used by SEGGER_SYSVIEW_Conf(),
|
||||
* such as in embOS configuration to enable Cortex-M cycle counter.
|
||||
*/
|
||||
#ifndef SEGGER_SYSVIEW_USE_INTERNAL_RECORDER
|
||||
#define SEGGER_SYSVIEW_USE_INTERNAL_RECORDER 0
|
||||
#endif
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Define: SEGGER_SYSVIEW_CAN_RESTART
|
||||
*
|
||||
* Description
|
||||
* If enabled, send the SystemView start sequence on every start
|
||||
* command, not just on the first one.
|
||||
* Enables restart when SystemView disconnected unexpectedly.
|
||||
* Default
|
||||
* 1: Enabled
|
||||
*/
|
||||
#ifndef SEGGER_SYSVIEW_CAN_RESTART
|
||||
#define SEGGER_SYSVIEW_CAN_RESTART 1
|
||||
#endif
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Define: SEGGER_SYSVIEW_START_ON_INIT
|
||||
*
|
||||
* Description
|
||||
* Enable calling SEGGER_SYSVIEW_Start() after initialization.
|
||||
* Default
|
||||
* 0: Disabled.
|
||||
* Notes
|
||||
* Convenience define to be used by SEGGER_SYSVIEW_Conf(),
|
||||
* such as in embOS configuration.
|
||||
*/
|
||||
#ifndef SEGGER_SYSVIEW_START_ON_INIT
|
||||
#define SEGGER_SYSVIEW_START_ON_INIT 0
|
||||
#endif
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Define: SEGGER_SYSVIEW_USE_STATIC_BUFFER
|
||||
*
|
||||
* Description
|
||||
* If enabled, use a static buffer instead of a buffer on the stack
|
||||
* for SystemView event packets.
|
||||
* Default
|
||||
* 1: Enabled.
|
||||
* Notes
|
||||
* If enabled, the static memory use by SystemView is increased by
|
||||
* the maximum packet size. SystemView is locked on entry of a
|
||||
* recording function.
|
||||
* If disabled, the stack usage by SystemView recording functions
|
||||
* might be increased by up to the maximum packet size. SystemView
|
||||
* is locked when writing the packet to the RTT buffer.
|
||||
*/
|
||||
#ifndef SEGGER_SYSVIEW_USE_STATIC_BUFFER
|
||||
#define SEGGER_SYSVIEW_USE_STATIC_BUFFER 1
|
||||
#endif
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Define: SEGGER_SYSVIEW_MAX_PACKET_SIZE
|
||||
*
|
||||
* Description
|
||||
* Maximum packet size for a SystemView event.
|
||||
* Default
|
||||
* Automatically calculated.
|
||||
* Notes
|
||||
* The maximum packet size is mainly defined by the maximum string
|
||||
* length and the maximum number of arguments.
|
||||
*/
|
||||
#ifndef SEGGER_SYSVIEW_MAX_PACKET_SIZE
|
||||
#define SEGGER_SYSVIEW_MAX_PACKET_SIZE (SEGGER_SYSVIEW_INFO_SIZE + SEGGER_SYSVIEW_MAX_STRING_LEN + 2 * SEGGER_SYSVIEW_QUANTA_U32 + SEGGER_SYSVIEW_MAX_ARGUMENTS * SEGGER_SYSVIEW_QUANTA_U32)
|
||||
#endif
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Define: SEGGER_SYSVIEW_POST_MORTEM_MODE
|
||||
*
|
||||
* Description
|
||||
* If enabled, SystemView records for post-mortem analysis instead
|
||||
* of real-time analysis.
|
||||
* Default
|
||||
* 0: Disabled.
|
||||
* Notes
|
||||
* For more information refer to
|
||||
* https://www.segger.com/products/development-tools/systemview/technology/post-mortem-mode
|
||||
*/
|
||||
#ifndef SEGGER_SYSVIEW_POST_MORTEM_MODE
|
||||
#define SEGGER_SYSVIEW_POST_MORTEM_MODE 0
|
||||
#endif
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Define: SEGGER_SYSVIEW_SYNC_PERIOD_SHIFT
|
||||
*
|
||||
* Description
|
||||
* Configure how frequently synchronization is sent in post-mortem
|
||||
* mode.
|
||||
* Default
|
||||
* 8: (1 << 8) = Every 256 Events.
|
||||
* Notes
|
||||
* In post-mortem mode, at least one sync has to be in the RTT buffer.
|
||||
* Recommended sync frequency: Buffer Size / 16
|
||||
* For more information refer to
|
||||
* https://www.segger.com/products/development-tools/systemview/technology/post-mortem-mode
|
||||
*/
|
||||
#ifndef SEGGER_SYSVIEW_SYNC_PERIOD_SHIFT
|
||||
#define SEGGER_SYSVIEW_SYNC_PERIOD_SHIFT 8
|
||||
#endif
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Define: SEGGER_SYSVIEW_ON_EVENT_RECORDED()
|
||||
*
|
||||
* Description
|
||||
* Function macro to notify recorder about a new event in buffer.
|
||||
* Default
|
||||
* undefined: Do not notify recorder.
|
||||
* Notes
|
||||
* Used for non-J-Link recorder,
|
||||
* such as to enable transmission via UART or notify IP task.
|
||||
*/
|
||||
#ifndef SEGGER_SYSVIEW_ON_EVENT_RECORDED
|
||||
#define SEGGER_SYSVIEW_ON_EVENT_RECORDED(NumBytes)
|
||||
#endif
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Define: SEGGER_SYSVIEW_LOCK()
|
||||
*
|
||||
* Description
|
||||
* Function macro to (nestable) lock SystemView recording.
|
||||
* Default
|
||||
* Use RTT Locking mechanism (defined by SEGGER_RTT_LOCK()).
|
||||
* Notes
|
||||
* If SystemView recording is not locked, recording events from
|
||||
* interrupts and tasks may lead to unpredictable, undefined, event
|
||||
* data.
|
||||
*/
|
||||
#ifndef SEGGER_SYSVIEW_LOCK
|
||||
unsigned SEGGER_SYSVIEW_X_SysView_Lock(void);
|
||||
#define SEGGER_SYSVIEW_LOCK() unsigned _SYSVIEW_int_state = SEGGER_SYSVIEW_X_SysView_Lock()
|
||||
#endif
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Define: SEGGER_SYSVIEW_UNLOCK
|
||||
*
|
||||
* Description
|
||||
* Function macro to unlock SystemView recording.
|
||||
* Default
|
||||
* Use RTT Unlocking mechanism (defined by SEGGER_RTT_UNLOCK()).
|
||||
*/
|
||||
#ifndef SEGGER_SYSVIEW_UNLOCK
|
||||
void SEGGER_SYSVIEW_X_SysView_Unlock(unsigned int_state);
|
||||
#define SEGGER_SYSVIEW_UNLOCK() SEGGER_SYSVIEW_X_SysView_Unlock(_SYSVIEW_int_state)
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/*************************** End of file ****************************/
|
||||
104
components/app_trace/sys_view/SEGGER/SEGGER_SYSVIEW_Int.h
Normal file
104
components/app_trace/sys_view/SEGGER/SEGGER_SYSVIEW_Int.h
Normal file
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 1995-2021 SEGGER Microcontroller GmbH
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-1-Clause
|
||||
*/
|
||||
/*********************************************************************
|
||||
* SEGGER Microcontroller GmbH *
|
||||
* The Embedded Experts *
|
||||
**********************************************************************
|
||||
* *
|
||||
* (c) 1995 - 2024 SEGGER Microcontroller GmbH *
|
||||
* *
|
||||
* www.segger.com Support: support@segger.com *
|
||||
* *
|
||||
**********************************************************************
|
||||
* *
|
||||
* SEGGER SystemView * Real-time application analysis *
|
||||
* *
|
||||
**********************************************************************
|
||||
* *
|
||||
* All rights reserved. *
|
||||
* *
|
||||
* SEGGER strongly recommends to not make any changes *
|
||||
* to or modify the source code of this software in order to stay *
|
||||
* compatible with the SystemView and RTT protocol, and J-Link. *
|
||||
* *
|
||||
* Redistribution and use in source and binary forms, with or *
|
||||
* without modification, are permitted provided that the following *
|
||||
* condition is met: *
|
||||
* *
|
||||
* o Redistributions of source code must retain the above copyright *
|
||||
* notice, this condition and the following disclaimer. *
|
||||
* *
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND *
|
||||
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, *
|
||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF *
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE *
|
||||
* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR *
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR *
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT *
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; *
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE *
|
||||
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH *
|
||||
* DAMAGE. *
|
||||
* *
|
||||
**********************************************************************
|
||||
* *
|
||||
* SystemView version: 3.56 *
|
||||
* *
|
||||
**********************************************************************
|
||||
-------------------------- END-OF-HEADER -----------------------------
|
||||
File : SEGGER_SYSVIEW_Int.h
|
||||
Purpose : SEGGER SystemView internal header.
|
||||
Revision: $Rev: 21281 $
|
||||
*/
|
||||
|
||||
#ifndef SEGGER_SYSVIEW_INT_H
|
||||
#define SEGGER_SYSVIEW_INT_H
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* #include Section
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
#include "SEGGER_SYSVIEW.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Private data types
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
//
|
||||
// Commands that Host can send to target
|
||||
//
|
||||
typedef enum {
|
||||
SEGGER_SYSVIEW_COMMAND_ID_START = 1,
|
||||
SEGGER_SYSVIEW_COMMAND_ID_STOP,
|
||||
SEGGER_SYSVIEW_COMMAND_ID_GET_SYSTIME,
|
||||
SEGGER_SYSVIEW_COMMAND_ID_GET_TASKLIST,
|
||||
SEGGER_SYSVIEW_COMMAND_ID_GET_SYSDESC,
|
||||
SEGGER_SYSVIEW_COMMAND_ID_GET_NUMMODULES,
|
||||
SEGGER_SYSVIEW_COMMAND_ID_GET_MODULEDESC,
|
||||
SEGGER_SYSVIEW_COMMAND_ID_HEARTBEAT = 127,
|
||||
// Extended commands: Commands >= 128 have a second parameter
|
||||
SEGGER_SYSVIEW_COMMAND_ID_GET_MODULE = 128
|
||||
} SEGGER_SYSVIEW_COMMAND_ID;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/*************************** End of file ****************************/
|
||||
6
components/app_trace/sys_view/SEGGER/sbom.yml
Normal file
6
components/app_trace/sys_view/SEGGER/sbom.yml
Normal file
@@ -0,0 +1,6 @@
|
||||
name: 'SystemView'
|
||||
version: '3.56'
|
||||
cpe: cpe:2.3:a:segger:systemview:{}:*:*:*:*:*:*:*
|
||||
supplier: 'Organization: Espressif Systems (Shanghai) CO LTD'
|
||||
originator: 'Organization: SEGGER Microcontroller GmbH'
|
||||
description: Real-time recording and visualization tool for embedded systems.
|
||||
@@ -0,0 +1,285 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 1995-2021 SEGGER Microcontroller GmbH
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-1-Clause
|
||||
*
|
||||
* SPDX-FileContributor: 2017-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*/
|
||||
/*********************************************************************
|
||||
* SEGGER Microcontroller GmbH *
|
||||
* The Embedded Experts *
|
||||
**********************************************************************
|
||||
* *
|
||||
* (c) 1995 - 2021 SEGGER Microcontroller GmbH *
|
||||
* *
|
||||
* www.segger.com Support: support@segger.com *
|
||||
* *
|
||||
**********************************************************************
|
||||
* *
|
||||
* SEGGER SystemView * Real-time application analysis *
|
||||
* *
|
||||
**********************************************************************
|
||||
* *
|
||||
* All rights reserved. *
|
||||
* *
|
||||
* SEGGER strongly recommends to not make any changes *
|
||||
* to or modify the source code of this software in order to stay *
|
||||
* compatible with the SystemView and RTT protocol, and J-Link. *
|
||||
* *
|
||||
* Redistribution and use in source and binary forms, with or *
|
||||
* without modification, are permitted provided that the following *
|
||||
* condition is met: *
|
||||
* *
|
||||
* o Redistributions of source code must retain the above copyright *
|
||||
* notice, this condition and the following disclaimer. *
|
||||
* *
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND *
|
||||
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, *
|
||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF *
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE *
|
||||
* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR *
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR *
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT *
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; *
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE *
|
||||
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH *
|
||||
* DAMAGE. *
|
||||
* *
|
||||
**********************************************************************
|
||||
* *
|
||||
* SystemView version: 3.42 *
|
||||
* *
|
||||
**********************************************************************
|
||||
-------------------------- END-OF-HEADER -----------------------------
|
||||
|
||||
File : SEGGER_SYSVIEW_Config_FreeRTOS.c
|
||||
Purpose : Sample setup configuration of SystemView with FreeRTOS.
|
||||
Revision: $Rev: 7745 $
|
||||
*/
|
||||
#include <string.h>
|
||||
#include "sdkconfig.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "SEGGER_SYSVIEW.h"
|
||||
#include "esp_app_trace.h"
|
||||
#include "esp_app_trace_util.h"
|
||||
#include "esp_intr_alloc.h"
|
||||
#include "esp_cpu.h"
|
||||
#include "soc/soc.h"
|
||||
#include "soc/interrupts.h"
|
||||
#include "esp_private/esp_clk.h"
|
||||
|
||||
extern const SEGGER_SYSVIEW_OS_API SYSVIEW_X_OS_TraceAPI;
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Defines, configurable
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
// The application name to be displayed in SystemViewer
|
||||
#define SYSVIEW_APP_NAME "FreeRTOS Application"
|
||||
|
||||
// The target device name
|
||||
#define SYSVIEW_DEVICE_NAME CONFIG_IDF_TARGET
|
||||
// The target core name
|
||||
#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
|
||||
#define TS_USE_CCOUNT 1
|
||||
#elif CONFIG_APPTRACE_SV_TS_SOURCE_ESP_TIMER
|
||||
#define TS_USE_ESP_TIMER 1
|
||||
#else
|
||||
#define TS_USE_TIMERGROUP 1
|
||||
#endif
|
||||
|
||||
#if TS_USE_TIMERGROUP
|
||||
#include "driver/gptimer.h"
|
||||
|
||||
// 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;
|
||||
|
||||
#endif // TS_USE_TIMERGROUP
|
||||
|
||||
#if TS_USE_ESP_TIMER
|
||||
// esp_timer provides 1us resolution
|
||||
#define SYSVIEW_TIMESTAMP_FREQ (1000000)
|
||||
#endif // TS_USE_ESP_TIMER
|
||||
|
||||
#if TS_USE_CCOUNT
|
||||
// CCOUNT is incremented at CPU frequency
|
||||
#define SYSVIEW_TIMESTAMP_FREQ (CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ * 1000000)
|
||||
#endif // TS_USE_CCOUNT
|
||||
|
||||
// System Frequency.
|
||||
#define SYSVIEW_CPU_FREQ (esp_clk_cpu_freq())
|
||||
|
||||
// The lowest RAM address used for IDs (pointers)
|
||||
#define SYSVIEW_RAM_BASE (SOC_DROM_LOW)
|
||||
|
||||
#ifdef CONFIG_FREERTOS_TICK_SUPPORT_CORETIMER
|
||||
#if CONFIG_FREERTOS_CORETIMER_0
|
||||
#define SYSTICK_INTR_ID (ETS_INTERNAL_TIMER0_INTR_SOURCE+ETS_INTERNAL_INTR_SOURCE_OFF)
|
||||
#endif
|
||||
#if CONFIG_FREERTOS_CORETIMER_1
|
||||
#define SYSTICK_INTR_ID (ETS_INTERNAL_TIMER1_INTR_SOURCE+ETS_INTERNAL_INTR_SOURCE_OFF)
|
||||
#endif
|
||||
|
||||
#elif CONFIG_FREERTOS_SYSTICK_USES_SYSTIMER
|
||||
#define SYSTICK_INTR_ID (ETS_SYSTIMER_TARGET0_INTR_SOURCE)
|
||||
#endif // CONFIG_FREERTOS_TICK_SUPPORT_CORETIMER
|
||||
|
||||
// SystemView is single core specific: it implies that SEGGER_SYSVIEW_LOCK()
|
||||
// disables IRQs (disables rescheduling globally). So we can not use finite timeouts for locks and return error
|
||||
// in case of expiration, because error will not be handled and SEGGER's code will go further implying that
|
||||
// everything is fine, so for multi-core env we have to wait on underlying lock forever
|
||||
#define SEGGER_LOCK_WAIT_TMO ESP_APPTRACE_TMO_INFINITE
|
||||
|
||||
static esp_apptrace_lock_t s_sys_view_lock = {.mux = portMUX_INITIALIZER_UNLOCKED, .int_state = 0};
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* _cbSendSystemDesc()
|
||||
*
|
||||
* Function description
|
||||
* Sends SystemView description strings.
|
||||
*/
|
||||
static void _cbSendSystemDesc(void) {
|
||||
char irq_str[32] = "I#";
|
||||
SEGGER_SYSVIEW_SendSysDesc("N="SYSVIEW_APP_NAME",D="SYSVIEW_DEVICE_NAME",C="SYSVIEW_CORE_NAME",O=FreeRTOS");
|
||||
strcat(itoa(SYSTICK_INTR_ID, irq_str + 2, 10), "=SysTick");
|
||||
SEGGER_SYSVIEW_SendSysDesc(irq_str);
|
||||
size_t isr_count = sizeof(esp_isr_names)/sizeof(esp_isr_names[0]);
|
||||
for (size_t i = 0; i < isr_count; ++i) {
|
||||
if (esp_isr_names[i] == NULL || (ETS_INTERNAL_INTR_SOURCE_OFF + i) == SYSTICK_INTR_ID)
|
||||
continue;
|
||||
strcat(itoa(ETS_INTERNAL_INTR_SOURCE_OFF + i, irq_str + 2, 10), "=");
|
||||
strncat(irq_str, esp_isr_names[i], sizeof(irq_str) - strlen(irq_str) - 1);
|
||||
SEGGER_SYSVIEW_SendSysDesc(irq_str);
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Global functions
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
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
|
||||
gptimer_config_t config = {
|
||||
.clk_src = GPTIMER_CLK_SRC_DEFAULT,
|
||||
.direction = GPTIMER_COUNT_UP,
|
||||
.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);
|
||||
#endif // TS_USE_TIMERGROUP
|
||||
}
|
||||
|
||||
void SEGGER_SYSVIEW_Conf(void) {
|
||||
U32 disable_evts = 0;
|
||||
|
||||
SEGGER_SYSVIEW_TS_Init();
|
||||
SEGGER_SYSVIEW_Init(SYSVIEW_TIMESTAMP_FREQ, SYSVIEW_CPU_FREQ,
|
||||
&SYSVIEW_X_OS_TraceAPI, _cbSendSystemDesc);
|
||||
SEGGER_SYSVIEW_SetRAMBase(SYSVIEW_RAM_BASE);
|
||||
|
||||
#if !CONFIG_APPTRACE_SV_EVT_OVERFLOW_ENABLE
|
||||
disable_evts |= SYSVIEW_EVTMASK_OVERFLOW;
|
||||
#endif
|
||||
#if !CONFIG_APPTRACE_SV_EVT_ISR_ENTER_ENABLE
|
||||
disable_evts |= SYSVIEW_EVTMASK_ISR_ENTER;
|
||||
#endif
|
||||
#if !CONFIG_APPTRACE_SV_EVT_ISR_EXIT_ENABLE
|
||||
disable_evts |= SYSVIEW_EVTMASK_ISR_EXIT;
|
||||
#endif
|
||||
#if !CONFIG_APPTRACE_SV_EVT_TASK_START_EXEC_ENABLE
|
||||
disable_evts |= SYSVIEW_EVTMASK_TASK_START_EXEC;
|
||||
#endif
|
||||
#if !CONFIG_APPTRACE_SV_EVT_TASK_STOP_EXEC_ENABLE
|
||||
disable_evts |= SYSVIEW_EVTMASK_TASK_STOP_EXEC;
|
||||
#endif
|
||||
#if !CONFIG_APPTRACE_SV_EVT_TASK_START_READY_ENABLE
|
||||
disable_evts |= SYSVIEW_EVTMASK_TASK_START_READY;
|
||||
#endif
|
||||
#if !CONFIG_APPTRACE_SV_EVT_TASK_STOP_READY_ENABLE
|
||||
disable_evts |= SYSVIEW_EVTMASK_TASK_STOP_READY;
|
||||
#endif
|
||||
#if !CONFIG_APPTRACE_SV_EVT_TASK_CREATE_ENABLE
|
||||
disable_evts |= SYSVIEW_EVTMASK_TASK_CREATE;
|
||||
#endif
|
||||
#if !CONFIG_APPTRACE_SV_EVT_TASK_TERMINATE_ENABLE
|
||||
disable_evts |= SYSVIEW_EVTMASK_TASK_TERMINATE;
|
||||
#endif
|
||||
#if !CONFIG_APPTRACE_SV_EVT_IDLE_ENABLE
|
||||
disable_evts |= SYSVIEW_EVTMASK_IDLE;
|
||||
#endif
|
||||
#if !CONFIG_APPTRACE_SV_EVT_ISR_TO_SCHED_ENABLE
|
||||
disable_evts |= SYSVIEW_EVTMASK_ISR_TO_SCHEDULER;
|
||||
#endif
|
||||
#if !CONFIG_APPTRACE_SV_EVT_TIMER_ENTER_ENABLE
|
||||
disable_evts |= SYSVIEW_EVTMASK_TIMER_ENTER;
|
||||
#endif
|
||||
#if !CONFIG_APPTRACE_SV_EVT_TIMER_EXIT_ENABLE
|
||||
disable_evts |= SYSVIEW_EVTMASK_TIMER_EXIT;
|
||||
#endif
|
||||
SEGGER_SYSVIEW_DisableEvents(disable_evts);
|
||||
}
|
||||
|
||||
U32 SEGGER_SYSVIEW_X_GetTimestamp(void)
|
||||
{
|
||||
#if TS_USE_TIMERGROUP
|
||||
uint64_t ts = 0;
|
||||
gptimer_get_raw_count(s_sv_gptimer, &ts);
|
||||
return (U32) ts; // return lower part of counter value
|
||||
#elif TS_USE_CCOUNT
|
||||
return esp_cpu_get_cycle_count();
|
||||
#elif TS_USE_ESP_TIMER
|
||||
return (U32) esp_timer_get_time(); // return lower part of counter value
|
||||
#endif
|
||||
}
|
||||
|
||||
void SEGGER_SYSVIEW_X_RTT_Lock(void)
|
||||
{
|
||||
}
|
||||
|
||||
void SEGGER_SYSVIEW_X_RTT_Unlock(void)
|
||||
{
|
||||
}
|
||||
|
||||
unsigned SEGGER_SYSVIEW_X_SysView_Lock(void)
|
||||
{
|
||||
esp_apptrace_tmo_t tmo;
|
||||
esp_apptrace_tmo_init(&tmo, SEGGER_LOCK_WAIT_TMO);
|
||||
esp_apptrace_lock_take(&s_sys_view_lock, &tmo);
|
||||
// to be recursive save IRQ status on the stack of the caller to keep it from overwriting
|
||||
return s_sys_view_lock.int_state;
|
||||
}
|
||||
|
||||
void SEGGER_SYSVIEW_X_SysView_Unlock(unsigned int_state)
|
||||
{
|
||||
s_sys_view_lock.int_state = int_state;
|
||||
esp_apptrace_lock_give(&s_sys_view_lock);
|
||||
}
|
||||
|
||||
/*************************** End of file ****************************/
|
||||
@@ -0,0 +1,270 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 1995-2021 SEGGER Microcontroller GmbH
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-1-Clause
|
||||
*
|
||||
* SPDX-FileContributor: 2023 Espressif Systems (Shanghai) CO LTD
|
||||
*/
|
||||
/*********************************************************************
|
||||
* SEGGER Microcontroller GmbH *
|
||||
* The Embedded Experts *
|
||||
**********************************************************************
|
||||
* *
|
||||
* (c) 1995 - 2021 SEGGER Microcontroller GmbH *
|
||||
* *
|
||||
* www.segger.com Support: support@segger.com *
|
||||
* *
|
||||
**********************************************************************
|
||||
* *
|
||||
* SEGGER SystemView * Real-time application analysis *
|
||||
* *
|
||||
**********************************************************************
|
||||
* *
|
||||
* All rights reserved. *
|
||||
* *
|
||||
* SEGGER strongly recommends to not make any changes *
|
||||
* to or modify the source code of this software in order to stay *
|
||||
* compatible with the SystemView and RTT protocol, and J-Link. *
|
||||
* *
|
||||
* Redistribution and use in source and binary forms, with or *
|
||||
* without modification, are permitted provided that the following *
|
||||
* condition is met: *
|
||||
* *
|
||||
* o Redistributions of source code must retain the above copyright *
|
||||
* notice, this condition and the following disclaimer. *
|
||||
* *
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND *
|
||||
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, *
|
||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF *
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE *
|
||||
* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR *
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR *
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT *
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; *
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE *
|
||||
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH *
|
||||
* DAMAGE. *
|
||||
* *
|
||||
**********************************************************************
|
||||
* *
|
||||
* SystemView version: 3.42 *
|
||||
* *
|
||||
**********************************************************************
|
||||
-------------------------- END-OF-HEADER -----------------------------
|
||||
|
||||
File : SEGGER_SYSVIEW_FreeRTOS.c
|
||||
Purpose : Interface between FreeRTOS and SystemView.
|
||||
Revision: $Rev: 7947 $
|
||||
*/
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "SEGGER_SYSVIEW.h"
|
||||
#include "SEGGER_SYSVIEW_FreeRTOS.h"
|
||||
#include "string.h" // Required for memset
|
||||
|
||||
|
||||
|
||||
typedef struct SYSVIEW_FREERTOS_TASK_STATUS SYSVIEW_FREERTOS_TASK_STATUS;
|
||||
|
||||
struct SYSVIEW_FREERTOS_TASK_STATUS {
|
||||
U32 xHandle;
|
||||
const char* pcTaskName;
|
||||
unsigned uxCurrentPriority;
|
||||
U32 pxStack;
|
||||
unsigned uStackHighWaterMark;
|
||||
};
|
||||
|
||||
static SYSVIEW_FREERTOS_TASK_STATUS _aTasks[SYSVIEW_FREERTOS_MAX_NOF_TASKS];
|
||||
static unsigned _NumTasks;
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* _cbSendTaskList()
|
||||
*
|
||||
* Function description
|
||||
* This function is part of the link between FreeRTOS and SYSVIEW.
|
||||
* Called from SystemView when asked by the host, it uses SYSVIEW
|
||||
* functions to send the entire task list to the host.
|
||||
*/
|
||||
static void _cbSendTaskList(void) {
|
||||
unsigned n;
|
||||
|
||||
for (n = 0; n < _NumTasks; n++) {
|
||||
#if INCLUDE_uxTaskGetStackHighWaterMark // Report Task Stack High Watermark
|
||||
_aTasks[n].uStackHighWaterMark = uxTaskGetStackHighWaterMark((TaskHandle_t)_aTasks[n].xHandle);
|
||||
#endif
|
||||
SYSVIEW_SendTaskInfo((U32)_aTasks[n].xHandle, _aTasks[n].pcTaskName, (unsigned)_aTasks[n].uxCurrentPriority, (U32)_aTasks[n].pxStack, (unsigned)_aTasks[n].uStackHighWaterMark);
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* _cbGetTime()
|
||||
*
|
||||
* Function description
|
||||
* This function is part of the link between FreeRTOS and SYSVIEW.
|
||||
* Called from SystemView when asked by the host, returns the
|
||||
* current system time in micro seconds.
|
||||
*/
|
||||
__attribute__((unused)) static U64 _cbGetTime(void) {
|
||||
U64 Time;
|
||||
|
||||
Time = xTaskGetTickCountFromISR();
|
||||
Time *= portTICK_PERIOD_MS;
|
||||
Time *= 1000;
|
||||
return Time;
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Global functions
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
/*********************************************************************
|
||||
*
|
||||
* SYSVIEW_AddTask()
|
||||
*
|
||||
* Function description
|
||||
* Add a task to the internal list and record its information.
|
||||
*/
|
||||
void SYSVIEW_AddTask(U32 xHandle, const char* pcTaskName, unsigned uxCurrentPriority, U32 pxStack, unsigned uStackHighWaterMark) {
|
||||
|
||||
/* On multi-core we have several idle tasks with 'IDLEx' names
|
||||
Not best solution, because we can filter out user tasks starting with 'IDLE'.
|
||||
But we can not use 'xTaskGetIdleTaskHandle' because at the moment when this
|
||||
function is called array of idle tasks handles are not initialized yet. */
|
||||
if (memcmp(pcTaskName, "IDLE", 4) == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (_NumTasks >= SYSVIEW_FREERTOS_MAX_NOF_TASKS) {
|
||||
SEGGER_SYSVIEW_Warn("SYSTEMVIEW: Could not record task information. Maximum number of tasks reached.");
|
||||
return;
|
||||
}
|
||||
|
||||
_aTasks[_NumTasks].xHandle = xHandle;
|
||||
_aTasks[_NumTasks].pcTaskName = pcTaskName;
|
||||
_aTasks[_NumTasks].uxCurrentPriority = uxCurrentPriority;
|
||||
_aTasks[_NumTasks].pxStack = pxStack;
|
||||
_aTasks[_NumTasks].uStackHighWaterMark = uStackHighWaterMark;
|
||||
|
||||
_NumTasks++;
|
||||
|
||||
SYSVIEW_SendTaskInfo(xHandle, pcTaskName,uxCurrentPriority, pxStack, uStackHighWaterMark);
|
||||
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* SYSVIEW_UpdateTask()
|
||||
*
|
||||
* Function description
|
||||
* Update a task in the internal list and record its information.
|
||||
*/
|
||||
void SYSVIEW_UpdateTask(U32 xHandle, const char* pcTaskName, unsigned uxCurrentPriority, U32 pxStack, unsigned uStackHighWaterMark) {
|
||||
unsigned n;
|
||||
|
||||
/* On multi-core we have several idle tasks with 'IDLEx' names
|
||||
Not best solution, because we can filter out user tasks starting with 'IDLE'.
|
||||
But we can not use 'xTaskGetIdleTaskHandle' because at the moment when this
|
||||
function is called array of idle tasks handles are not initialized yet. */
|
||||
if (memcmp(pcTaskName, "IDLE", 4) == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (n = 0; n < _NumTasks; n++) {
|
||||
if (_aTasks[n].xHandle == xHandle) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (n < _NumTasks) {
|
||||
_aTasks[n].pcTaskName = pcTaskName;
|
||||
_aTasks[n].uxCurrentPriority = uxCurrentPriority;
|
||||
_aTasks[n].pxStack = pxStack;
|
||||
_aTasks[n].uStackHighWaterMark = uStackHighWaterMark;
|
||||
|
||||
SYSVIEW_SendTaskInfo(xHandle, pcTaskName, uxCurrentPriority, pxStack, uStackHighWaterMark);
|
||||
} else {
|
||||
SYSVIEW_AddTask(xHandle, pcTaskName, uxCurrentPriority, pxStack, uStackHighWaterMark);
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* SYSVIEW_DeleteTask()
|
||||
*
|
||||
* Function description
|
||||
* Delete a task from the internal list.
|
||||
*/
|
||||
void SYSVIEW_DeleteTask(U32 xHandle) {
|
||||
unsigned n;
|
||||
|
||||
if (_NumTasks == 0) {
|
||||
return; // Early out
|
||||
}
|
||||
for (n = 0; n < _NumTasks; n++) {
|
||||
if (_aTasks[n].xHandle == xHandle) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (n == (_NumTasks - 1)) {
|
||||
//
|
||||
// Task is last item in list.
|
||||
// Simply zero the item and decrement number of tasks.
|
||||
//
|
||||
memset(&_aTasks[n], 0, sizeof(_aTasks[n]));
|
||||
_NumTasks--;
|
||||
} else if (n < _NumTasks) {
|
||||
//
|
||||
// Task is in the middle of the list.
|
||||
// Move last item to current position and decrement number of tasks.
|
||||
// Order of tasks does not really matter, so no need to move all following items.
|
||||
//
|
||||
_aTasks[n].xHandle = _aTasks[_NumTasks - 1].xHandle;
|
||||
_aTasks[n].pcTaskName = _aTasks[_NumTasks - 1].pcTaskName;
|
||||
_aTasks[n].uxCurrentPriority = _aTasks[_NumTasks - 1].uxCurrentPriority;
|
||||
_aTasks[n].pxStack = _aTasks[_NumTasks - 1].pxStack;
|
||||
_aTasks[n].uStackHighWaterMark = _aTasks[_NumTasks - 1].uStackHighWaterMark;
|
||||
memset(&_aTasks[_NumTasks - 1], 0, sizeof(_aTasks[_NumTasks - 1]));
|
||||
_NumTasks--;
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* SYSVIEW_SendTaskInfo()
|
||||
*
|
||||
* Function description
|
||||
* Record task information.
|
||||
*/
|
||||
void SYSVIEW_SendTaskInfo(U32 TaskID, const char* sName, unsigned Prio, U32 StackBase, unsigned StackSize) {
|
||||
SEGGER_SYSVIEW_TASKINFO TaskInfo;
|
||||
|
||||
memset(&TaskInfo, 0, sizeof(TaskInfo)); // Fill all elements with 0 to allow extending the structure in future version without breaking the code
|
||||
TaskInfo.TaskID = TaskID;
|
||||
TaskInfo.sName = sName;
|
||||
TaskInfo.Prio = Prio;
|
||||
TaskInfo.StackBase = StackBase;
|
||||
TaskInfo.StackSize = StackSize;
|
||||
SEGGER_SYSVIEW_SendTaskInfo(&TaskInfo);
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Public API structures
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
// 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,
|
||||
_cbSendTaskList,
|
||||
};
|
||||
|
||||
/*************************** End of file ****************************/
|
||||
@@ -0,0 +1,367 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 1995-2021 SEGGER Microcontroller GmbH
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-1-Clause
|
||||
*
|
||||
* SPDX-FileContributor: 2023 Espressif Systems (Shanghai) CO LTD
|
||||
*/
|
||||
/*********************************************************************
|
||||
* SEGGER Microcontroller GmbH *
|
||||
* The Embedded Experts *
|
||||
**********************************************************************
|
||||
* *
|
||||
* (c) 1995 - 2021 SEGGER Microcontroller GmbH *
|
||||
* *
|
||||
* www.segger.com Support: support@segger.com *
|
||||
* *
|
||||
**********************************************************************
|
||||
* *
|
||||
* SEGGER SystemView * Real-time application analysis *
|
||||
* *
|
||||
**********************************************************************
|
||||
* *
|
||||
* All rights reserved. *
|
||||
* *
|
||||
* SEGGER strongly recommends to not make any changes *
|
||||
* to or modify the source code of this software in order to stay *
|
||||
* compatible with the SystemView and RTT protocol, and J-Link. *
|
||||
* *
|
||||
* Redistribution and use in source and binary forms, with or *
|
||||
* without modification, are permitted provided that the following *
|
||||
* condition is met: *
|
||||
* *
|
||||
* o Redistributions of source code must retain the above copyright *
|
||||
* notice, this condition and the following disclaimer. *
|
||||
* *
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND *
|
||||
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, *
|
||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF *
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE *
|
||||
* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR *
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR *
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT *
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; *
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE *
|
||||
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH *
|
||||
* DAMAGE. *
|
||||
* *
|
||||
**********************************************************************
|
||||
* *
|
||||
* SystemView version: 3.42 *
|
||||
* *
|
||||
**********************************************************************
|
||||
-------------------------- END-OF-HEADER -----------------------------
|
||||
|
||||
File : SEGGER_SYSVIEW_FreeRTOS.h
|
||||
Purpose : Interface between FreeRTOS and SystemView.
|
||||
Tested with FreeRTOS V10.4.3
|
||||
Revision: $Rev: 7745 $
|
||||
|
||||
Notes:
|
||||
(1) Include this file at the end of FreeRTOSConfig.h
|
||||
*/
|
||||
|
||||
#ifndef SYSVIEW_FREERTOS_H
|
||||
#define SYSVIEW_FREERTOS_H
|
||||
|
||||
#include "SEGGER_SYSVIEW.h"
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Defines, configurable
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
#define SYSVIEW_FREERTOS_MAX_NOF_TASKS CONFIG_APPTRACE_SV_MAX_TASKS
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Defines, fixed
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
// for dual-core targets we use event ID to keep core ID bit (0 or 1)
|
||||
// use the highest - 1 bit of event ID to indicate core ID
|
||||
// the highest bit can not be used due to event ID encoding method
|
||||
// this reduces supported ID range to [0..63] (for 1 byte IDs) plus [128..16383] (for 2 bytes IDs)
|
||||
// so original continuous event IDs range is split into two sub-ranges for 1-bytes IDs and 2-bytes ones
|
||||
|
||||
// events which use apiFastID_OFFSET will have 1 byte ID,
|
||||
// so for the sake of bandwidth economy events which are generated more frequently should use this ID offset
|
||||
// currently all used events fall into this range
|
||||
#define apiFastID_OFFSET (32u)
|
||||
|
||||
#define apiID_VTASKDELETE (1u)
|
||||
#define apiID_VTASKDELAY (2u)
|
||||
#define apiID_VTASKDELAYUNTIL (3u)
|
||||
#define apiID_VTASKSUSPEND (4u)
|
||||
#define apiID_ULTASKNOTIFYTAKE (5u)
|
||||
#define apiID_VTASKNOTIFYGIVEFROMISR (6u)
|
||||
#define apiID_VTASKPRIORITYINHERIT (7u)
|
||||
#define apiID_VTASKRESUME (8u)
|
||||
#define apiID_VTASKSTEPTICK (9u)
|
||||
#define apiID_XTASKPRIORITYDISINHERIT (10u)
|
||||
#define apiID_XTASKRESUMEFROMISR (11u)
|
||||
#define apiID_XTASKGENERICNOTIFY (12u)
|
||||
#define apiID_XTASKGENERICNOTIFYFROMISR (13u)
|
||||
#define apiID_XTASKNOTIFYWAIT (14u)
|
||||
#define apiID_XQUEUEGENERICCREATE (15u)
|
||||
#define apiID_VQUEUEDELETE (16u)
|
||||
#define apiID_XQUEUEGENERICRECEIVE (17u)
|
||||
#define apiID_XQUEUEPEEKFROMISR (18u)
|
||||
#define apiID_XQUEUERECEIVEFROMISR (19u)
|
||||
#define apiID_VQUEUEADDTOREGISTRY (20u)
|
||||
#define apiID_XQUEUEGENERICSEND (21u)
|
||||
#define apiID_XQUEUEGENERICSENDFROMISR (22u)
|
||||
#define apiID_VTASKPRIORITYSET (23u)
|
||||
#define apiID_UXTASKPRIORITYGETFROMISR (24u)
|
||||
#define apiID_XTASKGETTICKCOUNTFROMISR (25u)
|
||||
#define apiID_XEVENTGROUPCLEARBITSFROMISR (26u)
|
||||
#define apiID_XEVENTGROUPSETBITSFROMISR (27u)
|
||||
#define apiID_XEVENTGROUPGETBITSFROMISR (28u)
|
||||
#define apiID_XQUEUEGIVEFROMISR (29u)
|
||||
#define apiID_XQUEUEISQUEUEEMPTYFROMISR (30u)
|
||||
#define apiID_XQUEUEISQUEUEFULLFROMISR (31u) // the maximum allowed apiID for the first ID range
|
||||
|
||||
// events which use apiSlowID_OFFSET will have 2-bytes ID
|
||||
#define apiSlowID_OFFSET (127u)
|
||||
|
||||
#define apiID_VTASKALLOCATEMPUREGIONS (1u)
|
||||
#define apiID_UXTASKPRIORITYGET (2u)
|
||||
#define apiID_ETASKGETSTATE (3u)
|
||||
#define apiID_VTASKSTARTSCHEDULER (4u)
|
||||
#define apiID_VTASKENDSCHEDULER (5u)
|
||||
#define apiID_VTASKSUSPENDALL (6u)
|
||||
#define apiID_XTASKRESUMEALL (7u)
|
||||
#define apiID_XTASKGETTICKCOUNT (8u)
|
||||
#define apiID_UXTASKGETNUMBEROFTASKS (9u)
|
||||
#define apiID_PCTASKGETTASKNAME (10u)
|
||||
#define apiID_UXTASKGETSTACKHIGHWATERMARK (11u)
|
||||
#define apiID_VTASKSETAPPLICATIONTASKTAG (12u)
|
||||
#define apiID_XTASKGETAPPLICATIONTASKTAG (13u)
|
||||
#define apiID_VTASKSETTHREADLOCALSTORAGEPOINTER (14u)
|
||||
#define apiID_PVTASKGETTHREADLOCALSTORAGEPOINTER (15u)
|
||||
#define apiID_XTASKCALLAPPLICATIONTASKHOOK (16u)
|
||||
#define apiID_XTASKGETIDLETASKHANDLE (17u)
|
||||
#define apiID_UXTASKGETSYSTEMSTATE (18u)
|
||||
#define apiID_VTASKLIST (19u)
|
||||
#define apiID_VTASKGETRUNTIMESTATS (20u)
|
||||
#define apiID_XTASKNOTIFYSTATECLEAR (21u)
|
||||
#define apiID_XTASKGETCURRENTTASKHANDLE (22u)
|
||||
#define apiID_VTASKSETTIMEOUTSTATE (23u)
|
||||
#define apiID_XTASKCHECKFORTIMEOUT (24u)
|
||||
#define apiID_VTASKMISSEDYIELD (25u)
|
||||
#define apiID_XTASKGETSCHEDULERSTATE (26u)
|
||||
#define apiID_XTASKGENERICCREATE (27u)
|
||||
#define apiID_UXTASKGETTASKNUMBER (28u)
|
||||
#define apiID_VTASKSETTASKNUMBER (29u)
|
||||
#define apiID_ETASKCONFIRMSLEEPMODESTATUS (30u)
|
||||
#define apiID_XTIMERCREATE (31u)
|
||||
#define apiID_PVTIMERGETTIMERID (32u)
|
||||
#define apiID_VTIMERSETTIMERID (33u)
|
||||
#define apiID_XTIMERISTIMERACTIVE (34u)
|
||||
#define apiID_XTIMERGETTIMERDAEMONTASKHANDLE (35u)
|
||||
#define apiID_XTIMERPENDFUNCTIONCALLFROMISR (36u)
|
||||
#define apiID_XTIMERPENDFUNCTIONCALL (37u)
|
||||
#define apiID_PCTIMERGETTIMERNAME (38u)
|
||||
#define apiID_XTIMERCREATETIMERTASK (39u)
|
||||
#define apiID_XTIMERGENERICCOMMAND (40u)
|
||||
#define apiID_UXQUEUEMESSAGESWAITING (41u)
|
||||
#define apiID_UXQUEUESPACESAVAILABLE (42u)
|
||||
#define apiID_UXQUEUEMESSAGESWAITINGFROMISR (43u)
|
||||
#define apiID_XQUEUEALTGENERICSEND (44u)
|
||||
#define apiID_XQUEUEALTGENERICRECEIVE (45u)
|
||||
#define apiID_XQUEUECRSENDFROMISR (46u)
|
||||
#define apiID_XQUEUECRRECEIVEFROMISR (47u)
|
||||
#define apiID_XQUEUECRSEND (48u)
|
||||
#define apiID_XQUEUECRRECEIVE (49u)
|
||||
#define apiID_XQUEUECREATEMUTEX (50u)
|
||||
#define apiID_XQUEUECREATECOUNTINGSEMAPHORE (51u)
|
||||
#define apiID_XQUEUEGETMUTEXHOLDER (52u)
|
||||
#define apiID_XQUEUETAKEMUTEXRECURSIVE (53u)
|
||||
#define apiID_XQUEUEGIVEMUTEXRECURSIVE (54u)
|
||||
#define apiID_VQUEUEUNREGISTERQUEUE (55u)
|
||||
#define apiID_XQUEUECREATESET (56u)
|
||||
#define apiID_XQUEUEADDTOSET (57u)
|
||||
#define apiID_XQUEUEREMOVEFROMSET (58u)
|
||||
#define apiID_XQUEUESELECTFROMSET (59u)
|
||||
#define apiID_XQUEUESELECTFROMSETFROMISR (60u)
|
||||
#define apiID_XQUEUEGENERICRESET (61u)
|
||||
#define apiID_VLISTINITIALISE (62u)
|
||||
#define apiID_VLISTINITIALISEITEM (63u)
|
||||
#define apiID_VLISTINSERT (64u)
|
||||
#define apiID_VLISTINSERTEND (65u)
|
||||
#define apiID_UXLISTREMOVE (66u)
|
||||
#define apiID_XEVENTGROUPCREATE (67u)
|
||||
#define apiID_XEVENTGROUPWAITBITS (68u)
|
||||
#define apiID_XEVENTGROUPCLEARBITS (69u)
|
||||
#define apiID_XEVENTGROUPSETBITS (70u)
|
||||
#define apiID_XEVENTGROUPSYNC (71u)
|
||||
#define apiID_VEVENTGROUPDELETE (72u)
|
||||
#define apiID_UXEVENTGROUPGETNUMBER (73u)
|
||||
#define apiID_XSTREAMBUFFERCREATE (74u)
|
||||
#define apiID_VSTREAMBUFFERDELETE (75u)
|
||||
#define apiID_XSTREAMBUFFERRESET (76u)
|
||||
#define apiID_XSTREAMBUFFERSEND (77u)
|
||||
#define apiID_XSTREAMBUFFERSENDFROMISR (78u)
|
||||
#define apiID_XSTREAMBUFFERRECEIVE (79u)
|
||||
#define apiID_XSTREAMBUFFERRECEIVEFROMISR (80u)
|
||||
|
||||
#ifdef CONFIG_FREERTOS_SMP
|
||||
|
||||
#define traceQUEUE_SEND( pxQueue ) SEGGER_SYSVIEW_RecordU32x4(apiFastID_OFFSET + apiID_XQUEUEGENERICSEND, SEGGER_SYSVIEW_ShrinkId((U32)pxQueue), 0u, 0u, 0u)
|
||||
|
||||
#else // CONFIG_FREERTOS_SMP
|
||||
|
||||
#if ( configUSE_QUEUE_SETS != 1 )
|
||||
#define traceQUEUE_SEND( pxQueue ) SEGGER_SYSVIEW_RecordU32x4(apiFastID_OFFSET + apiID_XQUEUEGENERICSEND, SEGGER_SYSVIEW_ShrinkId((U32)pxQueue), (U32)pvItemToQueue, xTicksToWait, xCopyPosition)
|
||||
#else
|
||||
#define traceQUEUE_SEND( pxQueue ) SEGGER_SYSVIEW_RecordU32x4(apiFastID_OFFSET + apiID_XQUEUEGENERICSEND, SEGGER_SYSVIEW_ShrinkId((U32)pxQueue), 0u, 0u, 0u)
|
||||
#endif
|
||||
|
||||
#endif // CONFIG_FREERTOS_SMP
|
||||
|
||||
|
||||
#define traceSTART() SEGGER_SYSVIEW_Conf()
|
||||
|
||||
#define traceTASK_NOTIFY_TAKE(uxIndexToWait) SEGGER_SYSVIEW_RecordU32x2(apiFastID_OFFSET + apiID_ULTASKNOTIFYTAKE, xClearCountOnExit, xTicksToWait)
|
||||
#define traceTASK_DELAY() SEGGER_SYSVIEW_RecordU32 (apiFastID_OFFSET + apiID_VTASKDELAY, xTicksToDelay)
|
||||
#define traceTASK_DELAY_UNTIL(xTimeToWake) SEGGER_SYSVIEW_RecordVoid (apiFastID_OFFSET + apiID_VTASKDELAYUNTIL)
|
||||
#define traceTASK_NOTIFY_GIVE_FROM_ISR(uxIndexToNotify) SEGGER_SYSVIEW_RecordU32x2(apiFastID_OFFSET + apiID_VTASKNOTIFYGIVEFROMISR, SEGGER_SYSVIEW_ShrinkId((U32)pxTCB), (U32)pxHigherPriorityTaskWoken)
|
||||
|
||||
#define traceTASK_PRIORITY_INHERIT( pxTCB, uxPriority ) SEGGER_SYSVIEW_RecordU32 (apiFastID_OFFSET + apiID_VTASKPRIORITYINHERIT, (U32)pxMutexHolder)
|
||||
#define traceTASK_RESUME( pxTCB ) SEGGER_SYSVIEW_RecordU32 (apiFastID_OFFSET + apiID_VTASKRESUME, SEGGER_SYSVIEW_ShrinkId((U32)pxTCB))
|
||||
#define traceINCREASE_TICK_COUNT( xTicksToJump ) SEGGER_SYSVIEW_RecordU32 (apiFastID_OFFSET + apiID_VTASKSTEPTICK, xTicksToJump)
|
||||
#define traceTASK_SUSPEND( pxTCB ) SEGGER_SYSVIEW_RecordU32 (apiFastID_OFFSET + apiID_VTASKSUSPEND, SEGGER_SYSVIEW_ShrinkId((U32)pxTCB))
|
||||
#define traceTASK_PRIORITY_DISINHERIT( pxTCB, uxBasePriority ) SEGGER_SYSVIEW_RecordU32 (apiFastID_OFFSET + apiID_XTASKPRIORITYDISINHERIT, (U32)pxMutexHolder)
|
||||
#define traceTASK_RESUME_FROM_ISR( pxTCB ) SEGGER_SYSVIEW_RecordU32 (apiFastID_OFFSET + apiID_XTASKRESUMEFROMISR, SEGGER_SYSVIEW_ShrinkId((U32)pxTCB))
|
||||
#define traceTASK_NOTIFY(uxIndexToNotify) SEGGER_SYSVIEW_RecordU32x4(apiFastID_OFFSET + apiID_XTASKGENERICNOTIFY, SEGGER_SYSVIEW_ShrinkId((U32)pxTCB), ulValue, eAction, (U32)pulPreviousNotificationValue)
|
||||
#define traceTASK_NOTIFY_FROM_ISR(uxIndexToWait) SEGGER_SYSVIEW_RecordU32x5(apiFastID_OFFSET + apiID_XTASKGENERICNOTIFYFROMISR, SEGGER_SYSVIEW_ShrinkId((U32)pxTCB), ulValue, eAction, (U32)pulPreviousNotificationValue, (U32)pxHigherPriorityTaskWoken)
|
||||
#define traceTASK_NOTIFY_WAIT(uxIndexToWait) SEGGER_SYSVIEW_RecordU32x4(apiFastID_OFFSET + apiID_XTASKNOTIFYWAIT, ulBitsToClearOnEntry, ulBitsToClearOnExit, (U32)pulNotificationValue, xTicksToWait)
|
||||
|
||||
#define traceQUEUE_CREATE( pxNewQueue ) SEGGER_SYSVIEW_RecordU32x3(apiFastID_OFFSET + apiID_XQUEUEGENERICCREATE, uxQueueLength, uxItemSize, ucQueueType)
|
||||
#define traceQUEUE_DELETE( pxQueue ) SEGGER_SYSVIEW_RecordU32 (apiFastID_OFFSET + apiID_VQUEUEDELETE, SEGGER_SYSVIEW_ShrinkId((U32)pxQueue))
|
||||
#define traceQUEUE_PEEK( pxQueue ) SEGGER_SYSVIEW_RecordU32x4(apiFastID_OFFSET + apiID_XQUEUEGENERICRECEIVE, SEGGER_SYSVIEW_ShrinkId((U32)pxQueue), SEGGER_SYSVIEW_ShrinkId((U32)pvBuffer), xTicksToWait, 1)
|
||||
#define traceQUEUE_PEEK_FROM_ISR( pxQueue ) SEGGER_SYSVIEW_RecordU32x2(apiFastID_OFFSET + apiID_XQUEUEPEEKFROMISR, SEGGER_SYSVIEW_ShrinkId((U32)pxQueue), SEGGER_SYSVIEW_ShrinkId((U32)pvBuffer))
|
||||
#define traceQUEUE_PEEK_FROM_ISR_FAILED( pxQueue ) SEGGER_SYSVIEW_RecordU32x2(apiFastID_OFFSET + apiID_XQUEUEPEEKFROMISR, SEGGER_SYSVIEW_ShrinkId((U32)pxQueue), SEGGER_SYSVIEW_ShrinkId((U32)pvBuffer))
|
||||
#define traceQUEUE_RECEIVE( pxQueue ) SEGGER_SYSVIEW_RecordU32x4(apiFastID_OFFSET + apiID_XQUEUEGENERICRECEIVE, SEGGER_SYSVIEW_ShrinkId((U32)pxQueue), SEGGER_SYSVIEW_ShrinkId((U32)0), xTicksToWait, 1)
|
||||
#define traceQUEUE_RECEIVE_FAILED( pxQueue ) SEGGER_SYSVIEW_RecordU32x4(apiFastID_OFFSET + apiID_XQUEUEGENERICRECEIVE, SEGGER_SYSVIEW_ShrinkId((U32)pxQueue), SEGGER_SYSVIEW_ShrinkId((U32)0), xTicksToWait, 1)
|
||||
#define traceQUEUE_SEMAPHORE_RECEIVE( pxQueue ) SEGGER_SYSVIEW_RecordU32x4(apiFastID_OFFSET + apiID_XQUEUEGENERICRECEIVE, SEGGER_SYSVIEW_ShrinkId((U32)pxQueue), SEGGER_SYSVIEW_ShrinkId((U32)0), xTicksToWait, 0)
|
||||
#define traceQUEUE_RECEIVE_FROM_ISR( pxQueue ) SEGGER_SYSVIEW_RecordU32x3(apiFastID_OFFSET + apiID_XQUEUERECEIVEFROMISR, SEGGER_SYSVIEW_ShrinkId((U32)pxQueue), SEGGER_SYSVIEW_ShrinkId((U32)pvBuffer), (U32)pxHigherPriorityTaskWoken)
|
||||
#define traceQUEUE_RECEIVE_FROM_ISR_FAILED( pxQueue ) SEGGER_SYSVIEW_RecordU32x3(apiFastID_OFFSET + apiID_XQUEUERECEIVEFROMISR, SEGGER_SYSVIEW_ShrinkId((U32)pxQueue), SEGGER_SYSVIEW_ShrinkId((U32)pvBuffer), (U32)pxHigherPriorityTaskWoken)
|
||||
#define traceQUEUE_REGISTRY_ADD( xQueue, pcQueueName ) SEGGER_SYSVIEW_RecordU32x2(apiFastID_OFFSET + apiID_VQUEUEADDTOREGISTRY, SEGGER_SYSVIEW_ShrinkId((U32)xQueue), (U32)pcQueueName)
|
||||
#define traceQUEUE_SEND_FAILED( pxQueue ) SEGGER_SYSVIEW_RecordU32x4(apiFastID_OFFSET + apiID_XQUEUEGENERICSEND, SEGGER_SYSVIEW_ShrinkId((U32)pxQueue), (U32)pvItemToQueue, xTicksToWait, xCopyPosition)
|
||||
#define traceQUEUE_SEND_FROM_ISR( pxQueue ) SEGGER_SYSVIEW_RecordU32x4(apiFastID_OFFSET + apiID_XQUEUEGENERICSENDFROMISR, SEGGER_SYSVIEW_ShrinkId((U32)pxQueue), (U32)pvItemToQueue, (U32)pxHigherPriorityTaskWoken, xCopyPosition)
|
||||
#define traceQUEUE_SEND_FROM_ISR_FAILED( pxQueue ) SEGGER_SYSVIEW_RecordU32x4(apiFastID_OFFSET + apiID_XQUEUEGENERICSENDFROMISR, SEGGER_SYSVIEW_ShrinkId((U32)pxQueue), (U32)pvItemToQueue, (U32)pxHigherPriorityTaskWoken, xCopyPosition)
|
||||
#define traceQUEUE_GIVE_FROM_ISR( pxQueue ) SEGGER_SYSVIEW_RecordU32x2(apiFastID_OFFSET + apiID_XQUEUEGIVEFROMISR, SEGGER_SYSVIEW_ShrinkId((U32)pxQueue), (U32)pxHigherPriorityTaskWoken)
|
||||
#define traceQUEUE_GIVE_FROM_ISR_FAILED( pxQueue ) SEGGER_SYSVIEW_RecordU32x2(apiFastID_OFFSET + apiID_XQUEUEGIVEFROMISR, SEGGER_SYSVIEW_ShrinkId((U32)pxQueue), (U32)pxHigherPriorityTaskWoken)
|
||||
#define traceSTREAM_BUFFER_CREATE( pxStreamBuffer, xIsMessageBuffer ) SEGGER_SYSVIEW_RecordU32x2(apiSlowID_OFFSET + apiID_XSTREAMBUFFERCREATE, (U32)xIsMessageBuffer, (U32)pxStreamBuffer)
|
||||
#define traceSTREAM_BUFFER_CREATE_FAILED( xIsMessageBuffer ) SEGGER_SYSVIEW_RecordU32x2(apiSlowID_OFFSET + apiID_XSTREAMBUFFERCREATE, (U32)xIsMessageBuffer, 0u)
|
||||
#define traceSTREAM_BUFFER_DELETE( xStreamBuffer ) SEGGER_SYSVIEW_RecordU32 (apiSlowID_OFFSET + apiID_VSTREAMBUFFERDELETE, (U32)xStreamBuffer)
|
||||
#define traceSTREAM_BUFFER_RESET( xStreamBuffer ) SEGGER_SYSVIEW_RecordU32 (apiSlowID_OFFSET + apiID_XSTREAMBUFFERRESET, (U32)xStreamBuffer)
|
||||
#define traceSTREAM_BUFFER_SEND( xStreamBuffer, xBytesSent ) SEGGER_SYSVIEW_RecordU32x2(apiSlowID_OFFSET + apiID_XSTREAMBUFFERSEND, (U32)xStreamBuffer, (U32)xBytesSent)
|
||||
#define traceSTREAM_BUFFER_SEND_FAILED( xStreamBuffer ) SEGGER_SYSVIEW_RecordU32x2(apiSlowID_OFFSET + apiID_XSTREAMBUFFERSEND, (U32)xStreamBuffer, 0u)
|
||||
#define traceSTREAM_BUFFER_SEND_FROM_ISR( xStreamBuffer, xBytesSent ) SEGGER_SYSVIEW_RecordU32x2(apiSlowID_OFFSET + apiID_XSTREAMBUFFERSENDFROMISR, (U32)xStreamBuffer, (U32)xBytesSent)
|
||||
#define traceSTREAM_BUFFER_RECEIVE( xStreamBuffer, xReceivedLength ) SEGGER_SYSVIEW_RecordU32x2(apiSlowID_OFFSET + apiID_XSTREAMBUFFERRECEIVE, (U32)xStreamBuffer, (U32)xReceivedLength)
|
||||
#define traceSTREAM_BUFFER_RECEIVE_FAILED( xStreamBuffer ) SEGGER_SYSVIEW_RecordU32x2(apiSlowID_OFFSET + apiID_XSTREAMBUFFERRECEIVE, (U32)xStreamBuffer, 0u)
|
||||
#define traceSTREAM_BUFFER_RECEIVE_FROM_ISR( xStreamBuffer, xReceivedLength ) SEGGER_SYSVIEW_RecordU32x2(apiSlowID_OFFSET + apiID_XSTREAMBUFFERRECEIVEFROMISR, (U32)xStreamBuffer, (U32)xReceivedLength)
|
||||
|
||||
#define traceTASK_DELETE( pxTCB ) do { \
|
||||
SEGGER_SYSVIEW_RecordU32(apiFastID_OFFSET + apiID_VTASKDELETE, SEGGER_SYSVIEW_ShrinkId((U32)pxTCB)); \
|
||||
SYSVIEW_DeleteTask((U32)pxTCB); \
|
||||
} while(0)
|
||||
|
||||
|
||||
#if( portSTACK_GROWTH < 0 )
|
||||
#define traceTASK_CREATE(pxNewTCB) if (pxNewTCB != NULL) { \
|
||||
SEGGER_SYSVIEW_OnTaskCreate((U32)pxNewTCB); \
|
||||
SYSVIEW_AddTask((U32)pxNewTCB, \
|
||||
&(pxNewTCB->pcTaskName[0]), \
|
||||
pxNewTCB->uxPriority, \
|
||||
(U32)pxNewTCB->pxStack, \
|
||||
((U32)pxNewTCB->pxTopOfStack - (U32)pxNewTCB->pxStack) \
|
||||
); \
|
||||
}
|
||||
#else
|
||||
#define traceTASK_CREATE(pxNewTCB) if (pxNewTCB != NULL) { \
|
||||
SEGGER_SYSVIEW_OnTaskCreate((U32)pxNewTCB); \
|
||||
SYSVIEW_AddTask((U32)pxNewTCB, \
|
||||
&(pxNewTCB->pcTaskName[0]), \
|
||||
pxNewTCB->uxPriority, \
|
||||
(U32)pxNewTCB->pxStack, \
|
||||
(U32)(pxNewTCB->pxStack-pxNewTCB->pxTopOfStack) \
|
||||
); \
|
||||
}
|
||||
#endif
|
||||
#define traceTASK_PRIORITY_SET(pxTask, uxNewPriority) { \
|
||||
SEGGER_SYSVIEW_RecordU32x2(apiFastID_OFFSET+apiID_VTASKPRIORITYSET, \
|
||||
SEGGER_SYSVIEW_ShrinkId((U32)pxTCB), \
|
||||
uxNewPriority \
|
||||
); \
|
||||
SYSVIEW_UpdateTask((U32)pxTask, \
|
||||
&(pxTask->pcTaskName[0]), \
|
||||
uxNewPriority, \
|
||||
(U32)pxTask->pxStack, \
|
||||
0 \
|
||||
); \
|
||||
}
|
||||
//
|
||||
// Define INCLUDE_xTaskGetIdleTaskHandle as 1 in FreeRTOSConfig.h to allow identification of Idle state.
|
||||
//
|
||||
// SMP FreeRTOS uses unpinned IDLE tasks, so sometimes IDEL0 runs on CPU1, IDLE1 runs on CPU0 and so on.
|
||||
// So IDLE state detection based on 'xTaskGetIdleTaskHandle' does not work for SMP kernel.
|
||||
// We could compare current task handle with every element of the array returned by 'xTaskGetIdleTaskHandle',
|
||||
// but it deos not seem to be efficient enough to be worth of making code more complex and less readabl.
|
||||
// So always use task name comparison mechanism for SMP kernel.
|
||||
#if ( INCLUDE_xTaskGetIdleTaskHandle == 1 && !defined(CONFIG_FREERTOS_SMP))
|
||||
#define traceTASK_SWITCHED_IN() if(prvGetTCBFromHandle(NULL) == xTaskGetIdleTaskHandle()) { \
|
||||
SEGGER_SYSVIEW_OnIdle(); \
|
||||
} else { \
|
||||
SEGGER_SYSVIEW_OnTaskStartExec((U32)prvGetTCBFromHandle(NULL)); \
|
||||
}
|
||||
#else
|
||||
#define traceTASK_SWITCHED_IN() { \
|
||||
if (memcmp(prvGetTCBFromHandle(NULL)->pcTaskName, "IDLE", 4) != 0) { \
|
||||
SEGGER_SYSVIEW_OnTaskStartExec((U32)prvGetTCBFromHandle(NULL)); \
|
||||
} else { \
|
||||
SEGGER_SYSVIEW_OnIdle(); \
|
||||
} \
|
||||
}
|
||||
#endif
|
||||
|
||||
#define traceMOVED_TASK_TO_READY_STATE(pxTCB) SEGGER_SYSVIEW_OnTaskStartReady((U32)pxTCB)
|
||||
#define traceREADDED_TASK_TO_READY_STATE(pxTCB)
|
||||
|
||||
#define traceMOVED_TASK_TO_DELAYED_LIST() SEGGER_SYSVIEW_OnTaskStopReady((U32)prvGetTCBFromHandle(NULL), (1u << 2))
|
||||
#define traceMOVED_TASK_TO_OVERFLOW_DELAYED_LIST() SEGGER_SYSVIEW_OnTaskStopReady((U32)prvGetTCBFromHandle(NULL), (1u << 2))
|
||||
#define traceMOVED_TASK_TO_SUSPENDED_LIST(pxTCB) SEGGER_SYSVIEW_OnTaskStopReady((U32)pxTCB, ((3u << 3) | 3))
|
||||
|
||||
|
||||
#define traceISR_EXIT_TO_SCHEDULER() SEGGER_SYSVIEW_RecordExitISRToScheduler()
|
||||
#define traceISR_EXIT() SEGGER_SYSVIEW_RecordExitISR()
|
||||
#define traceISR_ENTER(n) SEGGER_SYSVIEW_RecordEnterISR(n)
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* API functions
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
void SYSVIEW_AddTask (U32 xHandle, const char* pcTaskName, unsigned uxCurrentPriority, U32 pxStack, unsigned uStackHighWaterMark);
|
||||
void SYSVIEW_UpdateTask (U32 xHandle, const char* pcTaskName, unsigned uxCurrentPriority, U32 pxStack, unsigned uStackHighWaterMark);
|
||||
void SYSVIEW_DeleteTask (U32 xHandle);
|
||||
void SYSVIEW_SendTaskInfo (U32 TaskID, const char* sName, unsigned Prio, U32 StackBase, unsigned StackSize);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/*************************** End of file ****************************/
|
||||
306
components/app_trace/sys_view/esp/SEGGER_RTT_esp.c
Normal file
306
components/app_trace/sys_view/esp/SEGGER_RTT_esp.c
Normal file
@@ -0,0 +1,306 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2017-2021 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "string.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "SEGGER_RTT.h"
|
||||
#include "SEGGER_SYSVIEW.h"
|
||||
#include "SEGGER_SYSVIEW_Conf.h"
|
||||
|
||||
#include "esp_app_trace.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_cpu.h"
|
||||
#include "esp_private/startup_internal.h"
|
||||
|
||||
const static char *TAG = "segger_rtt";
|
||||
|
||||
#define SYSVIEW_EVENTS_BUF_SZ 255U
|
||||
|
||||
// size of down channel data buf
|
||||
#define SYSVIEW_DOWN_BUF_SIZE 32
|
||||
#define SEGGER_STOP_WAIT_TMO 1000000 //us
|
||||
#if CONFIG_APPTRACE_SV_BUF_WAIT_TMO == -1
|
||||
#define SEGGER_HOST_WAIT_TMO ESP_APPTRACE_TMO_INFINITE
|
||||
#else
|
||||
#define SEGGER_HOST_WAIT_TMO CONFIG_APPTRACE_SV_BUF_WAIT_TMO
|
||||
#endif
|
||||
|
||||
static uint8_t s_events_buf[SYSVIEW_EVENTS_BUF_SZ];
|
||||
static uint16_t s_events_buf_filled;
|
||||
static uint8_t s_down_buf[SYSVIEW_DOWN_BUF_SIZE];
|
||||
|
||||
#if CONFIG_APPTRACE_SV_DEST_UART
|
||||
|
||||
#define ESP_APPTRACE_DEST_SYSVIEW ESP_APPTRACE_DEST_UART
|
||||
#if CONFIG_APPTRACE_SV_DEST_CPU_0 || CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE
|
||||
#define APPTRACE_SV_DEST_CPU 0
|
||||
#else
|
||||
#define APPTRACE_SV_DEST_CPU 1
|
||||
#endif // CONFIG_APPTRACE_SV_DEST_CPU_0
|
||||
|
||||
#elif CONFIG_APPTRACE_SV_DEST_JTAG || (CONFIG_APPTRACE_ENABLE && CONFIG_APPTRACE_DEST_UART_NONE)
|
||||
#define ESP_APPTRACE_DEST_SYSVIEW ESP_APPTRACE_DEST_TRAX
|
||||
#endif
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Public code
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* SEGGER_RTT_ESP_FlushNoLock()
|
||||
*
|
||||
* Function description
|
||||
* Flushes buffered events.
|
||||
*
|
||||
* Parameters
|
||||
* min_sz Threshold for flushing data. If current filling level is above this value, data will be flushed. TRAX destinations only.
|
||||
* tmo Timeout for operation (in us). Use ESP_APPTRACE_TMO_INFINITE to wait indefinetly.
|
||||
*
|
||||
* Return value
|
||||
* None.
|
||||
*/
|
||||
void SEGGER_RTT_ESP_FlushNoLock(unsigned long min_sz, unsigned long tmo)
|
||||
{
|
||||
esp_err_t res;
|
||||
if (s_events_buf_filled > 0) {
|
||||
res = esp_apptrace_write(ESP_APPTRACE_DEST_SYSVIEW, s_events_buf, s_events_buf_filled, tmo);
|
||||
if (res != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to flush buffered events (%d)!", res);
|
||||
}
|
||||
}
|
||||
// flush even if we failed to write buffered events, because no new events will be sent after STOP
|
||||
res = esp_apptrace_flush_nolock(ESP_APPTRACE_DEST_SYSVIEW, min_sz, tmo);
|
||||
if (res != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to flush apptrace data (%d)!", res);
|
||||
}
|
||||
s_events_buf_filled = 0;
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* SEGGER_RTT_ESP_Flush()
|
||||
*
|
||||
* Function description
|
||||
* Flushes buffered events.
|
||||
*
|
||||
* Parameters
|
||||
* min_sz Threshold for flushing data. If current filling level is above this value, data will be flushed. TRAX destinations only.
|
||||
* tmo Timeout for operation (in us). Use ESP_APPTRACE_TMO_INFINITE to wait indefinetly.
|
||||
*
|
||||
* Return value
|
||||
* None.
|
||||
*/
|
||||
void SEGGER_RTT_ESP_Flush(unsigned long min_sz, unsigned long tmo)
|
||||
{
|
||||
SEGGER_SYSVIEW_LOCK();
|
||||
SEGGER_RTT_ESP_FlushNoLock(min_sz, tmo);
|
||||
SEGGER_SYSVIEW_UNLOCK();
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* SEGGER_RTT_ReadNoLock()
|
||||
*
|
||||
* Function description
|
||||
* Reads characters from SEGGER real-time-terminal control block
|
||||
* which have been previously stored by the host.
|
||||
* Do not lock against interrupts and multiple access.
|
||||
*
|
||||
* Parameters
|
||||
* BufferIndex Index of Down-buffer to be used (e.g. 0 for "Terminal").
|
||||
* pBuffer Pointer to buffer provided by target application, to copy characters from RTT-down-buffer to.
|
||||
* BufferSize Size of the target application buffer.
|
||||
*
|
||||
* Return value
|
||||
* Number of bytes that have been read.
|
||||
*/
|
||||
unsigned SEGGER_RTT_ReadNoLock(unsigned BufferIndex, void* pData, unsigned BufferSize) {
|
||||
uint32_t size = BufferSize;
|
||||
esp_err_t res = esp_apptrace_read(ESP_APPTRACE_DEST_SYSVIEW, pData, &size, 0);
|
||||
if (res != ESP_OK) {
|
||||
return 0;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* SEGGER_RTT_WriteSkipNoLock
|
||||
*
|
||||
* Function description
|
||||
* Stores a specified number of characters in SEGGER RTT
|
||||
* control block which is then read by the host.
|
||||
* SEGGER_RTT_WriteSkipNoLock does not lock the application and
|
||||
* skips all data, if the data does not fit into the buffer.
|
||||
*
|
||||
* Parameters
|
||||
* BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal").
|
||||
* pBuffer Pointer to character array. Does not need to point to a \0 terminated string.
|
||||
* NumBytes Number of bytes to be stored in the SEGGER RTT control block.
|
||||
*
|
||||
* Return value
|
||||
* Number of bytes which have been stored in the "Up"-buffer.
|
||||
*
|
||||
* Notes
|
||||
* (1) If there is not enough space in the "Up"-buffer, all data is dropped.
|
||||
* (2) For performance reasons this function does not call Init()
|
||||
* and may only be called after RTT has been initialized.
|
||||
* Either by calling SEGGER_RTT_Init() or calling another RTT API function first.
|
||||
*/
|
||||
unsigned SEGGER_RTT_WriteSkipNoLock(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) {
|
||||
uint8_t *pbuf = (uint8_t *)pBuffer;
|
||||
uint8_t event_id = *pbuf;
|
||||
#if CONFIG_APPTRACE_SV_DEST_UART
|
||||
if (
|
||||
(APPTRACE_SV_DEST_CPU != esp_cpu_get_core_id()) &&
|
||||
(
|
||||
(event_id == SYSVIEW_EVTID_ISR_ENTER) ||
|
||||
(event_id == SYSVIEW_EVTID_ISR_EXIT) ||
|
||||
(event_id == SYSVIEW_EVTID_TASK_START_EXEC) ||
|
||||
(event_id == SYSVIEW_EVTID_TASK_STOP_EXEC) ||
|
||||
(event_id == SYSVIEW_EVTID_TASK_START_READY) ||
|
||||
(event_id == SYSVIEW_EVTID_TASK_STOP_READY) ||
|
||||
(event_id == SYSVIEW_EVTID_MARK_START) ||
|
||||
(event_id == SYSVIEW_EVTID_MARK_STOP) ||
|
||||
(event_id == SYSVIEW_EVTID_TIMER_ENTER) ||
|
||||
(event_id == SYSVIEW_EVTID_TIMER_EXIT) ||
|
||||
(event_id == SYSVIEW_EVTID_STACK_INFO) ||
|
||||
(event_id == SYSVIEW_EVTID_MODULEDESC)
|
||||
)
|
||||
){
|
||||
return NumBytes;
|
||||
}
|
||||
|
||||
// This is workaround for SystemView!
|
||||
// Without this line SystemView will hangs on when heap tracing enabled.
|
||||
if(event_id == SYSVIEW_EVTID_MODULEDESC){
|
||||
return NumBytes;
|
||||
}
|
||||
#endif // CONFIG_APPTRACE_SV_DEST_UART
|
||||
|
||||
if (NumBytes > SYSVIEW_EVENTS_BUF_SZ) {
|
||||
ESP_LOGE(TAG, "Too large event %u bytes!", NumBytes);
|
||||
return 0;
|
||||
}
|
||||
#if CONFIG_APPTRACE_SV_DEST_JTAG
|
||||
if (esp_cpu_get_core_id()) { // dual core specific code
|
||||
// use the highest - 1 bit of event ID to indicate core ID
|
||||
// the highest bit can not be used due to event ID encoding method
|
||||
// this reduces supported ID range to [0..63] (for 1 byte IDs) plus [128..16383] (for 2 bytes IDs)
|
||||
if (*pbuf & 0x80) { // 2 bytes ID
|
||||
*(pbuf + 1) |= (1 << 6);
|
||||
} else if (NumBytes != 10 || *pbuf != 0) { // ignore sync sequence
|
||||
*pbuf |= (1 << 6);
|
||||
}
|
||||
}
|
||||
#endif // CONFIG_APPTRACE_SV_DEST_JTAG
|
||||
#if CONFIG_APPTRACE_SV_DEST_JTAG
|
||||
if (s_events_buf_filled + NumBytes > SYSVIEW_EVENTS_BUF_SZ) {
|
||||
|
||||
esp_err_t res = esp_apptrace_write(ESP_APPTRACE_DEST_SYSVIEW, s_events_buf, s_events_buf_filled, SEGGER_HOST_WAIT_TMO);
|
||||
if (res != ESP_OK) {
|
||||
return 0; // skip current data buffer only, accumulated events are kept
|
||||
}
|
||||
s_events_buf_filled = 0;
|
||||
}
|
||||
#endif
|
||||
memcpy(&s_events_buf[s_events_buf_filled], pBuffer, NumBytes);
|
||||
s_events_buf_filled += NumBytes;
|
||||
|
||||
#if CONFIG_APPTRACE_SV_DEST_UART
|
||||
esp_err_t res = esp_apptrace_write(ESP_APPTRACE_DEST_SYSVIEW, pBuffer, NumBytes, SEGGER_HOST_WAIT_TMO);
|
||||
if (res != ESP_OK)
|
||||
{
|
||||
return 0; // skip current data buffer only, accumulated events are kept
|
||||
}
|
||||
s_events_buf_filled = 0;
|
||||
#endif
|
||||
|
||||
if (event_id == SYSVIEW_EVTID_TRACE_STOP)
|
||||
{
|
||||
SEGGER_RTT_ESP_FlushNoLock(0, SEGGER_STOP_WAIT_TMO);
|
||||
}
|
||||
return NumBytes;
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* SEGGER_RTT_ConfigUpBuffer
|
||||
*
|
||||
* Function description
|
||||
* Run-time configuration of a specific up-buffer (T->H).
|
||||
* Buffer to be configured is specified by index.
|
||||
* This includes: Buffer address, size, name, flags, ...
|
||||
*
|
||||
* Parameters
|
||||
* BufferIndex Index of the buffer to configure.
|
||||
* sName Pointer to a constant name string.
|
||||
* pBuffer Pointer to a buffer to be used.
|
||||
* BufferSize Size of the buffer.
|
||||
* Flags Operating modes. Define behavior if buffer is full (not enough space for entire message).
|
||||
*
|
||||
* Return value
|
||||
* >= 0 - O.K.
|
||||
* < 0 - Error
|
||||
*
|
||||
* Additional information
|
||||
* Buffer 0 is configured on compile-time.
|
||||
* May only be called once per buffer.
|
||||
* Buffer name and flags can be reconfigured using the appropriate functions.
|
||||
*/
|
||||
int SEGGER_RTT_ConfigUpBuffer(unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) {
|
||||
s_events_buf_filled = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* SEGGER_RTT_ConfigDownBuffer
|
||||
*
|
||||
* Function description
|
||||
* Run-time configuration of a specific down-buffer (H->T).
|
||||
* Buffer to be configured is specified by index.
|
||||
* This includes: Buffer address, size, name, flags, ...
|
||||
*
|
||||
* Parameters
|
||||
* BufferIndex Index of the buffer to configure.
|
||||
* sName Pointer to a constant name string.
|
||||
* pBuffer Pointer to a buffer to be used.
|
||||
* BufferSize Size of the buffer.
|
||||
* Flags Operating modes. Define behavior if buffer is full (not enough space for entire message).
|
||||
*
|
||||
* Return value
|
||||
* >= 0 O.K.
|
||||
* < 0 Error
|
||||
*
|
||||
* Additional information
|
||||
* Buffer 0 is configured on compile-time.
|
||||
* May only be called once per buffer.
|
||||
* Buffer name and flags can be reconfigured using the appropriate functions.
|
||||
*/
|
||||
int SEGGER_RTT_ConfigDownBuffer(unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) {
|
||||
esp_apptrace_down_buffer_config(s_down_buf, sizeof(s_down_buf));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*************************** Init hook ****************************
|
||||
*
|
||||
* This init function is placed here because this port file will be
|
||||
* linked whenever SystemView is used.
|
||||
*/
|
||||
|
||||
ESP_SYSTEM_INIT_FN(sysview_init, SECONDARY, BIT(0), 120)
|
||||
{
|
||||
SEGGER_SYSVIEW_Conf();
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
|
||||
/*************************** End of file ****************************/
|
||||
92
components/app_trace/sys_view/ext/heap_trace_module.c
Normal file
92
components/app_trace/sys_view/ext/heap_trace_module.c
Normal file
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2018-2021 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include <stdint.h>
|
||||
#include <sdkconfig.h>
|
||||
#include "SEGGER_SYSVIEW.h"
|
||||
#include "SEGGER_RTT.h"
|
||||
#include "esp_app_trace.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
|
||||
#include "esp_log.h"
|
||||
const static char *TAG = "sysview_heap_trace";
|
||||
|
||||
#ifdef CONFIG_HEAP_TRACING_STACK_DEPTH
|
||||
#define CALLSTACK_SIZE CONFIG_HEAP_TRACING_STACK_DEPTH
|
||||
#else
|
||||
#define CALLSTACK_SIZE 0
|
||||
#endif
|
||||
|
||||
static SEGGER_SYSVIEW_MODULE s_esp_sysview_heap_module = {
|
||||
.sModule = "M=ESP32 SystemView Heap Tracing Module",
|
||||
.NumEvents = 2,
|
||||
};
|
||||
|
||||
static bool s_mod_registered;
|
||||
|
||||
|
||||
esp_err_t esp_sysview_heap_trace_start(uint32_t tmo)
|
||||
{
|
||||
uint32_t tmo_ticks = tmo/(1000*portTICK_PERIOD_MS);
|
||||
|
||||
ESP_EARLY_LOGV(TAG, "%s", __func__);
|
||||
do {
|
||||
if (tmo != (uint32_t)-1) {
|
||||
// Currently timeout implementation is simple and has granularity of 1 OS tick,
|
||||
// so just count down the number of times to call vTaskDelay
|
||||
if (tmo_ticks-- == 0) {
|
||||
return ESP_ERR_TIMEOUT;
|
||||
}
|
||||
}
|
||||
vTaskDelay(1);
|
||||
} while(!SEGGER_SYSVIEW_Started());
|
||||
|
||||
SEGGER_SYSVIEW_RegisterModule(&s_esp_sysview_heap_module);
|
||||
s_mod_registered = true;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_sysview_heap_trace_stop(void)
|
||||
{
|
||||
ESP_EARLY_LOGV(TAG, "%s", __func__);
|
||||
SEGGER_RTT_ESP_Flush(0, ESP_APPTRACE_TMO_INFINITE);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
void esp_sysview_heap_trace_alloc(const void *addr, uint32_t size, const void *callers)
|
||||
{
|
||||
U8 aPacket[SEGGER_SYSVIEW_INFO_SIZE + (2+CALLSTACK_SIZE)*SEGGER_SYSVIEW_QUANTA_U32];
|
||||
U8* pPayload = SEGGER_SYSVIEW_PREPARE_PACKET(aPacket);
|
||||
U32 *calls = (U32 *)callers;
|
||||
|
||||
if (!s_mod_registered) {
|
||||
return;
|
||||
}
|
||||
ESP_EARLY_LOGV(TAG, "%s %p %lu", __func__, addr, size);
|
||||
pPayload = SEGGER_SYSVIEW_EncodeU32(pPayload, (U32)addr);
|
||||
pPayload = SEGGER_SYSVIEW_EncodeU32(pPayload, size);
|
||||
for (int i = 0; i < CALLSTACK_SIZE; i++) {
|
||||
pPayload = SEGGER_SYSVIEW_EncodeU32(pPayload, calls[i]);
|
||||
}
|
||||
SEGGER_SYSVIEW_SendPacket(&aPacket[0], pPayload, s_esp_sysview_heap_module.EventOffset + 0);
|
||||
}
|
||||
|
||||
void esp_sysview_heap_trace_free(const void *addr, const void *callers)
|
||||
{
|
||||
U8 aPacket[SEGGER_SYSVIEW_INFO_SIZE + (1+CALLSTACK_SIZE)*SEGGER_SYSVIEW_QUANTA_U32];
|
||||
U8* pPayload = SEGGER_SYSVIEW_PREPARE_PACKET(aPacket);
|
||||
U32 *calls = (U32 *)callers;
|
||||
|
||||
if (!s_mod_registered) {
|
||||
return;
|
||||
}
|
||||
ESP_EARLY_LOGV(TAG, "%s %p", __func__, addr);
|
||||
pPayload = SEGGER_SYSVIEW_EncodeU32(pPayload, (U32)addr);
|
||||
for (int i = 0; i < CALLSTACK_SIZE; i++) {
|
||||
pPayload = SEGGER_SYSVIEW_EncodeU32(pPayload, calls[i]);
|
||||
}
|
||||
SEGGER_SYSVIEW_SendPacket(&aPacket[0], pPayload, s_esp_sysview_heap_module.EventOffset + 1);
|
||||
}
|
||||
26
components/app_trace/sys_view/ext/logging.c
Normal file
26
components/app_trace/sys_view/ext/logging.c
Normal file
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2018-2021 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <sdkconfig.h>
|
||||
#include "SEGGER_SYSVIEW_Int.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
|
||||
static portMUX_TYPE s_log_mutex = portMUX_INITIALIZER_UNLOCKED;
|
||||
|
||||
int esp_sysview_vprintf(const char * format, va_list args)
|
||||
{
|
||||
static char log_buffer[SEGGER_SYSVIEW_MAX_STRING_LEN];
|
||||
|
||||
portENTER_CRITICAL(&s_log_mutex);
|
||||
size_t len = vsnprintf(log_buffer, sizeof(log_buffer), format, args);
|
||||
if (len > sizeof(log_buffer) - 1) {
|
||||
log_buffer[sizeof(log_buffer) - 1] = 0;
|
||||
}
|
||||
SEGGER_SYSVIEW_Print(log_buffer);
|
||||
portEXIT_CRITICAL(&s_log_mutex);
|
||||
return len;
|
||||
}
|
||||
@@ -2,9 +2,12 @@
|
||||
|
||||
components/app_trace/test_apps:
|
||||
depends_components:
|
||||
- esp_trace
|
||||
- esp_driver_gptimer
|
||||
- app_trace
|
||||
- esp_timer
|
||||
- soc
|
||||
- driver
|
||||
- esp_hw_support
|
||||
disable:
|
||||
- if: IDF_TARGET in ["esp32h21", "esp32h4"]
|
||||
- if: IDF_TARGET in ["esp32c5", "esp32c61", "esp32h21", "esp32h4"]
|
||||
temporary: true
|
||||
reason: not support yet # TODO: [ESP32H21] IDF-11539 [ESP32H4] IDF-12325
|
||||
reason: not support yet # TODO: [ESP32C5] IDF-8705, [ESP32C61] IDF-9306, [ESP32H21] IDF-11539 [ESP32H4] IDF-12325
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
cmake_minimum_required(VERSION 3.22)
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||
set(COMPONENTS main)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-P4 | ESP32-S2 | ESP32-S3 |
|
||||
| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | -------- |
|
||||
| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-P4 | ESP32-S2 | ESP32-S3 |
|
||||
| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- | -------- |
|
||||
|
||||
# app_trace test
|
||||
|
||||
@@ -8,4 +8,9 @@ To build and run this test app for app_trace related tests:
|
||||
IDF_TARGET=esp32 idf.py @app_trace build flash monitor
|
||||
```
|
||||
|
||||
`@app_trace` argument apply additional `idf.py` options, from [app_trace](app_trace) and file.
|
||||
To build and run this test app for SystemView related tests:
|
||||
```bash
|
||||
IDF_TARGET=esp32 idf.py @sysview build flash monitor
|
||||
```
|
||||
|
||||
`@app_trace` and `@sysview` arguments apply additional `idf.py` options, from [app_trace](app_trace) and [sysview](sysview) files.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
idf_component_register(SRCS "test_app_trace_main.c" "test_trace.c"
|
||||
INCLUDE_DIRS "."
|
||||
PRIV_REQUIRES esp_trace unity esp_driver_gptimer
|
||||
PRIV_REQUIRES app_trace unity esp_driver_gptimer
|
||||
WHOLE_ARCHIVE)
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
@@ -16,16 +16,17 @@
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/semphr.h"
|
||||
#include "freertos/task.h"
|
||||
#include "esp_app_trace.h"
|
||||
|
||||
#define LOG_LOCAL_LEVEL ESP_LOG_VERBOSE
|
||||
#include "esp_log.h"
|
||||
#include "esp_app_trace.h"
|
||||
#include "esp_app_trace_util.h"
|
||||
|
||||
#define ESP_APPTRACE_TEST_USE_PRINT_LOCK 0
|
||||
#define ESP_APPTRACE_TEST_PRN_WRERR_MAX 5
|
||||
#define ESP_APPTRACE_TEST_BLOCKS_BEFORE_CRASH 100
|
||||
#define ESP_APPTRACE_TEST_BLOCK_SIZE 1024
|
||||
|
||||
#define LOG_LOCAL_LEVEL ESP_LOG_VERBOSE
|
||||
#include "esp_log.h"
|
||||
const static char *TAG = "esp_apptrace_test";
|
||||
|
||||
#if ESP_APPTRACE_TEST_USE_PRINT_LOCK == 1
|
||||
@@ -65,9 +66,10 @@ const static char *TAG = "esp_apptrace_test";
|
||||
#define ESP_APPTRACE_TEST_LOGV( format, ... ) ESP_APPTRACE_TEST_LOG_LEVEL(V, ESP_LOG_VERBOSE, format, ##__VA_ARGS__)
|
||||
#define ESP_APPTRACE_TEST_LOGO( format, ... ) ESP_APPTRACE_TEST_LOG_LEVEL(E, ESP_LOG_NONE, format, ##__VA_ARGS__)
|
||||
|
||||
#define ESP_APPTRACE_TEST_WRITE(_b_, _s_) esp_apptrace_write(_b_, _s_, ESP_APPTRACE_TMO_INFINITE)
|
||||
#define ESP_APPTRACE_TEST_WRITE_FROM_ISR(_b_, _s_) esp_apptrace_write(_b_, _s_, 0UL)
|
||||
#define ESP_APPTRACE_TEST_WRITE_NOWAIT(_b_, _s_) esp_apptrace_write(_b_, _s_, 0)
|
||||
#if CONFIG_APPTRACE_SV_ENABLE == 0
|
||||
#define ESP_APPTRACE_TEST_WRITE(_b_, _s_) esp_apptrace_write(ESP_APPTRACE_DEST_TRAX, _b_, _s_, ESP_APPTRACE_TMO_INFINITE)
|
||||
#define ESP_APPTRACE_TEST_WRITE_FROM_ISR(_b_, _s_) esp_apptrace_write(ESP_APPTRACE_DEST_TRAX, _b_, _s_, 0UL)
|
||||
#define ESP_APPTRACE_TEST_WRITE_NOWAIT(_b_, _s_) esp_apptrace_write(ESP_APPTRACE_DEST_TRAX, _b_, _s_, 0)
|
||||
|
||||
typedef struct {
|
||||
uint8_t *buf;
|
||||
@@ -623,7 +625,7 @@ static int esp_logtrace_printf(const char *fmt, ...)
|
||||
|
||||
va_start(ap, fmt);
|
||||
|
||||
int ret = esp_apptrace_vprintf_to(ESP_APPTRACE_TMO_INFINITE, fmt, ap);
|
||||
int ret = esp_apptrace_vprintf_to(ESP_APPTRACE_DEST_TRAX, ESP_APPTRACE_TMO_INFINITE, fmt, ap);
|
||||
|
||||
va_end(ap);
|
||||
|
||||
@@ -655,7 +657,7 @@ static void esp_logtrace_task(void *p)
|
||||
break;
|
||||
}
|
||||
}
|
||||
esp_err_t ret = esp_apptrace_flush(ESP_APPTRACE_TMO_INFINITE);
|
||||
esp_err_t ret = esp_apptrace_flush(ESP_APPTRACE_DEST_TRAX, ESP_APPTRACE_TMO_INFINITE);
|
||||
if (ret != ESP_OK) {
|
||||
ESP_APPTRACE_TEST_LOGE("Failed to flush printf buf (%d)!", ret);
|
||||
}
|
||||
@@ -692,3 +694,233 @@ TEST_CASE("Log trace test (2 tasks)", "[trace][ignore]")
|
||||
xSemaphoreTake(arg2.done, portMAX_DELAY);
|
||||
vSemaphoreDelete(arg2.done);
|
||||
}
|
||||
|
||||
#else // #if CONFIG_APPTRACE_SV_ENABLE == 0
|
||||
|
||||
typedef struct {
|
||||
gptimer_handle_t gptimer;
|
||||
uint32_t period;
|
||||
int flags;
|
||||
uint32_t id;
|
||||
} esp_sysviewtrace_timer_arg_t;
|
||||
|
||||
typedef struct {
|
||||
SemaphoreHandle_t done;
|
||||
SemaphoreHandle_t *sync;
|
||||
esp_sysviewtrace_timer_arg_t *timer;
|
||||
uint32_t work_count;
|
||||
uint32_t sleep_tmo;
|
||||
uint32_t id;
|
||||
} esp_sysviewtrace_task_arg_t;
|
||||
|
||||
static bool esp_sysview_test_timer_isr(gptimer_handle_t timer, const gptimer_alarm_event_data_t *edata, void *user_ctx)
|
||||
{
|
||||
esp_sysviewtrace_timer_arg_t *tim_arg = (esp_sysviewtrace_timer_arg_t *)user_ctx;
|
||||
(void) tim_arg;
|
||||
return false;
|
||||
}
|
||||
|
||||
static void esp_sysviewtrace_test_task(void *p)
|
||||
{
|
||||
esp_sysviewtrace_task_arg_t *arg = (esp_sysviewtrace_task_arg_t *) p;
|
||||
volatile uint32_t tmp = 0;
|
||||
printf("%p: run sysview task\n", xTaskGetCurrentTaskHandle());
|
||||
|
||||
if (arg->timer) {
|
||||
gptimer_alarm_config_t alarm_config = {
|
||||
.reload_count = 0,
|
||||
.alarm_count = arg->timer->period,
|
||||
.flags.auto_reload_on_alarm = true,
|
||||
};
|
||||
gptimer_event_callbacks_t cbs = {
|
||||
.on_alarm = esp_sysview_test_timer_isr,
|
||||
};
|
||||
TEST_ESP_OK(gptimer_register_event_callbacks(arg->timer->gptimer, &cbs, arg->timer));
|
||||
TEST_ESP_OK(gptimer_enable(arg->timer->gptimer));
|
||||
TEST_ESP_OK(gptimer_set_alarm_action(arg->timer->gptimer, &alarm_config));
|
||||
TEST_ESP_OK(gptimer_start(arg->timer->gptimer));
|
||||
}
|
||||
|
||||
int i = 0;
|
||||
while (1) {
|
||||
static uint32_t count;
|
||||
printf("%" PRIu32, arg->id);
|
||||
if ((++count % 80) == 0) {
|
||||
printf("\n");
|
||||
}
|
||||
if (arg->sync) {
|
||||
xSemaphoreTake(*arg->sync, portMAX_DELAY);
|
||||
}
|
||||
for (uint32_t k = 0; k < arg->work_count; k++) {
|
||||
tmp++;
|
||||
}
|
||||
vTaskDelay(arg->sleep_tmo / portTICK_PERIOD_MS);
|
||||
i++;
|
||||
if (arg->sync) {
|
||||
xSemaphoreGive(*arg->sync);
|
||||
}
|
||||
}
|
||||
ESP_APPTRACE_TEST_LOGI("%p: finished", xTaskGetCurrentTaskHandle());
|
||||
|
||||
xSemaphoreGive(arg->done);
|
||||
vTaskDelay(1);
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
TEST_CASE("SysView trace test 1", "[trace][ignore]")
|
||||
{
|
||||
TaskHandle_t thnd;
|
||||
|
||||
esp_sysviewtrace_timer_arg_t tim_arg1 = {
|
||||
.flags = ESP_INTR_FLAG_SHARED,
|
||||
.id = 0,
|
||||
.period = 500,
|
||||
};
|
||||
esp_sysviewtrace_task_arg_t arg1 = {
|
||||
.done = xSemaphoreCreateBinary(),
|
||||
.sync = NULL,
|
||||
.work_count = 10000,
|
||||
.sleep_tmo = 1,
|
||||
.timer = &tim_arg1,
|
||||
.id = 0,
|
||||
};
|
||||
esp_sysviewtrace_timer_arg_t tim_arg2 = {
|
||||
.flags = 0,
|
||||
.id = 1,
|
||||
.period = 100,
|
||||
};
|
||||
esp_sysviewtrace_task_arg_t arg2 = {
|
||||
.done = xSemaphoreCreateBinary(),
|
||||
.sync = NULL,
|
||||
.work_count = 10000,
|
||||
.sleep_tmo = 1,
|
||||
.timer = &tim_arg2,
|
||||
.id = 1,
|
||||
};
|
||||
|
||||
gptimer_config_t timer_config = {
|
||||
.clk_src = GPTIMER_CLK_SRC_DEFAULT,
|
||||
.direction = GPTIMER_COUNT_UP,
|
||||
.resolution_hz = 1000000,
|
||||
};
|
||||
timer_config.flags.intr_shared = (tim_arg1.flags & ESP_INTR_FLAG_SHARED) == ESP_INTR_FLAG_SHARED;
|
||||
TEST_ESP_OK(gptimer_new_timer(&timer_config, &tim_arg1.gptimer));
|
||||
timer_config.flags.intr_shared = (tim_arg2.flags & ESP_INTR_FLAG_SHARED) == ESP_INTR_FLAG_SHARED;
|
||||
TEST_ESP_OK(gptimer_new_timer(&timer_config, &tim_arg2.gptimer));
|
||||
|
||||
xTaskCreatePinnedToCore(esp_sysviewtrace_test_task, "svtrace0", 2048, &arg1, 3, &thnd, 0);
|
||||
ESP_APPTRACE_TEST_LOGI("Created task %p", thnd);
|
||||
#if CONFIG_FREERTOS_UNICORE == 0
|
||||
xTaskCreatePinnedToCore(esp_sysviewtrace_test_task, "svtrace1", 2048, &arg2, 5, &thnd, 1);
|
||||
#else
|
||||
xTaskCreatePinnedToCore(esp_sysviewtrace_test_task, "svtrace1", 2048, &arg2, 5, &thnd, 0);
|
||||
#endif
|
||||
ESP_APPTRACE_TEST_LOGI("Created task %p", thnd);
|
||||
|
||||
xSemaphoreTake(arg1.done, portMAX_DELAY);
|
||||
vSemaphoreDelete(arg1.done);
|
||||
xSemaphoreTake(arg2.done, portMAX_DELAY);
|
||||
vSemaphoreDelete(arg2.done);
|
||||
TEST_ESP_OK(gptimer_stop(tim_arg1.gptimer));
|
||||
TEST_ESP_OK(gptimer_disable(tim_arg1.gptimer));
|
||||
TEST_ESP_OK(gptimer_del_timer(tim_arg1.gptimer));
|
||||
TEST_ESP_OK(gptimer_stop(tim_arg2.gptimer));
|
||||
TEST_ESP_OK(gptimer_disable(tim_arg2.gptimer));
|
||||
TEST_ESP_OK(gptimer_del_timer(tim_arg2.gptimer));
|
||||
}
|
||||
|
||||
TEST_CASE("SysView trace test 2", "[trace][ignore]")
|
||||
{
|
||||
TaskHandle_t thnd;
|
||||
|
||||
esp_sysviewtrace_timer_arg_t tim_arg1 = {
|
||||
.flags = ESP_INTR_FLAG_SHARED,
|
||||
.id = 0,
|
||||
.period = 500,
|
||||
};
|
||||
esp_sysviewtrace_task_arg_t arg1 = {
|
||||
.done = xSemaphoreCreateBinary(),
|
||||
.sync = NULL,
|
||||
.work_count = 10000,
|
||||
.sleep_tmo = 1,
|
||||
.timer = &tim_arg1,
|
||||
.id = 0,
|
||||
};
|
||||
esp_sysviewtrace_timer_arg_t tim_arg2 = {
|
||||
.flags = 0,
|
||||
.id = 1,
|
||||
.period = 100,
|
||||
};
|
||||
esp_sysviewtrace_task_arg_t arg2 = {
|
||||
.done = xSemaphoreCreateBinary(),
|
||||
.sync = NULL,
|
||||
.work_count = 10000,
|
||||
.sleep_tmo = 1,
|
||||
.timer = &tim_arg2,
|
||||
.id = 1,
|
||||
};
|
||||
|
||||
SemaphoreHandle_t test_sync = xSemaphoreCreateBinary();
|
||||
xSemaphoreGive(test_sync);
|
||||
esp_sysviewtrace_task_arg_t arg3 = {
|
||||
.done = xSemaphoreCreateBinary(),
|
||||
.sync = &test_sync,
|
||||
.work_count = 1000,
|
||||
.sleep_tmo = 1,
|
||||
.timer = NULL,
|
||||
.id = 2,
|
||||
};
|
||||
esp_sysviewtrace_task_arg_t arg4 = {
|
||||
.done = xSemaphoreCreateBinary(),
|
||||
.sync = &test_sync,
|
||||
.work_count = 10000,
|
||||
.sleep_tmo = 1,
|
||||
.timer = NULL,
|
||||
.id = 3,
|
||||
};
|
||||
|
||||
gptimer_config_t timer_config = {
|
||||
.clk_src = GPTIMER_CLK_SRC_DEFAULT,
|
||||
.direction = GPTIMER_COUNT_UP,
|
||||
.resolution_hz = 1000000,
|
||||
};
|
||||
timer_config.flags.intr_shared = (tim_arg1.flags & ESP_INTR_FLAG_SHARED) == ESP_INTR_FLAG_SHARED;
|
||||
TEST_ESP_OK(gptimer_new_timer(&timer_config, &tim_arg1.gptimer));
|
||||
timer_config.flags.intr_shared = (tim_arg2.flags & ESP_INTR_FLAG_SHARED) == ESP_INTR_FLAG_SHARED;
|
||||
TEST_ESP_OK(gptimer_new_timer(&timer_config, &tim_arg2.gptimer));
|
||||
|
||||
xTaskCreatePinnedToCore(esp_sysviewtrace_test_task, "svtrace0", 2048, &arg1, 3, &thnd, 0);
|
||||
printf("Created task %p\n", thnd);
|
||||
#if CONFIG_FREERTOS_UNICORE == 0
|
||||
xTaskCreatePinnedToCore(esp_sysviewtrace_test_task, "svtrace1", 2048, &arg2, 4, &thnd, 1);
|
||||
#else
|
||||
xTaskCreatePinnedToCore(esp_sysviewtrace_test_task, "svtrace1", 2048, &arg2, 4, &thnd, 0);
|
||||
#endif
|
||||
printf("Created task %p\n", thnd);
|
||||
|
||||
xTaskCreatePinnedToCore(esp_sysviewtrace_test_task, "svsync0", 2048, &arg3, 3, &thnd, 0);
|
||||
printf("Created task %p\n", thnd);
|
||||
#if CONFIG_FREERTOS_UNICORE == 0
|
||||
xTaskCreatePinnedToCore(esp_sysviewtrace_test_task, "svsync1", 2048, &arg4, 5, &thnd, 1);
|
||||
#else
|
||||
xTaskCreatePinnedToCore(esp_sysviewtrace_test_task, "svsync1", 2048, &arg4, 5, &thnd, 0);
|
||||
#endif
|
||||
printf("Created task %p\n", thnd);
|
||||
|
||||
xSemaphoreTake(arg1.done, portMAX_DELAY);
|
||||
vSemaphoreDelete(arg1.done);
|
||||
xSemaphoreTake(arg2.done, portMAX_DELAY);
|
||||
vSemaphoreDelete(arg2.done);
|
||||
xSemaphoreTake(arg3.done, portMAX_DELAY);
|
||||
vSemaphoreDelete(arg3.done);
|
||||
xSemaphoreTake(arg4.done, portMAX_DELAY);
|
||||
vSemaphoreDelete(arg4.done);
|
||||
vSemaphoreDelete(test_sync);
|
||||
TEST_ESP_OK(gptimer_stop(tim_arg1.gptimer));
|
||||
TEST_ESP_OK(gptimer_disable(tim_arg1.gptimer));
|
||||
TEST_ESP_OK(gptimer_del_timer(tim_arg1.gptimer));
|
||||
TEST_ESP_OK(gptimer_stop(tim_arg2.gptimer));
|
||||
TEST_ESP_OK(gptimer_disable(tim_arg2.gptimer));
|
||||
TEST_ESP_OK(gptimer_del_timer(tim_arg2.gptimer));
|
||||
}
|
||||
#endif // #if CONFIG_APPTRACE_SV_ENABLE == 0
|
||||
|
||||
@@ -1,3 +1 @@
|
||||
CONFIG_ESP_TRACE_LIB_NONE=y
|
||||
CONFIG_ESP_TRACE_TRANSPORT_APPTRACE=y
|
||||
CONFIG_APPTRACE_DEST_JTAG=y
|
||||
# app_trace is already enabled by sdkconfig.defaults, so no options are needed here
|
||||
|
||||
1
components/app_trace/test_apps/sdkconfig.ci.sysview
Normal file
1
components/app_trace/test_apps/sdkconfig.ci.sysview
Normal file
@@ -0,0 +1 @@
|
||||
CONFIG_APPTRACE_SV_ENABLE=y
|
||||
@@ -1,2 +1,2 @@
|
||||
CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU0=n
|
||||
CONFIG_ESP_TRACE_ENABLE=y
|
||||
CONFIG_APPTRACE_DEST_JTAG=y
|
||||
|
||||
1
components/app_trace/test_apps/sysview
Normal file
1
components/app_trace/test_apps/sysview
Normal file
@@ -0,0 +1 @@
|
||||
-DSDKCONFIG_DEFAULTS="sdkconfig.defaults;sdkconfig.ci.sysview" -B build/sysview -DSDKCONFIG=build/sysview/sdkconfig
|
||||
@@ -4,7 +4,7 @@ if(${target} STREQUAL "linux")
|
||||
return() # This component is not supported by the POSIX/Linux simulator
|
||||
endif()
|
||||
|
||||
idf_component_register(SRCS "esp_ota_ops.c"
|
||||
idf_component_register(SRCS "esp_ota_ops.c" "esp_ota_app_desc.c"
|
||||
INCLUDE_DIRS "include"
|
||||
REQUIRES partition_table bootloader_support esp_app_format esp_bootloader_format esp_partition
|
||||
PRIV_REQUIRES esptool_py efuse spi_flash)
|
||||
@@ -29,9 +29,7 @@ if(NOT BOOTLOADER_BUILD)
|
||||
|
||||
add_custom_target(blank_ota_data ALL DEPENDS ${blank_otadata_file})
|
||||
add_dependencies(flash blank_ota_data)
|
||||
if(CONFIG_SECURE_FLASH_ENCRYPTION_MODE_DEVELOPMENT)
|
||||
add_dependencies(encrypted-flash blank_ota_data)
|
||||
endif()
|
||||
add_dependencies(encrypted-flash blank_ota_data)
|
||||
|
||||
set(otatool_py "${python}" "${COMPONENT_DIR}/otatool.py")
|
||||
|
||||
|
||||
21
components/app_update/esp_ota_app_desc.c
Normal file
21
components/app_update/esp_ota_app_desc.c
Normal file
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2017-2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <sys/param.h>
|
||||
#include "esp_ota_ops.h"
|
||||
#include "esp_attr.h"
|
||||
#include "sdkconfig.h"
|
||||
|
||||
const esp_app_desc_t *esp_ota_get_app_description(void)
|
||||
{
|
||||
return esp_app_get_description();
|
||||
}
|
||||
|
||||
int esp_ota_get_app_elf_sha256(char* dst, size_t size)
|
||||
{
|
||||
return esp_app_get_elf_sha256(dst, size);
|
||||
}
|
||||
@@ -33,7 +33,7 @@
|
||||
#include "esp_flash.h"
|
||||
#include "esp_flash_internal.h"
|
||||
|
||||
#define OTA_SLOT(i) (i & 0x0F)
|
||||
#define SUB_TYPE_ID(i) (i & 0x0F)
|
||||
#define ALIGN_UP(num, align) (((num) + ((align) - 1)) & ~((align) - 1))
|
||||
|
||||
/* Partial_data is word aligned so no reallocation is necessary for encrypted flash write */
|
||||
@@ -539,69 +539,6 @@ static esp_err_t rewrite_ota_seq(esp_ota_select_entry_t *two_otadata, uint32_t s
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Calculate the next OTA sequence number that will boot the given OTA slot.
|
||||
*
|
||||
* Based on the ESP-IDF OTA boot scheme, the system selects the OTA slot to boot by:
|
||||
* boot_slot = (seq - 1) % ota_app_count
|
||||
*
|
||||
* This function determines the required seq value that would cause the given ota_slot_idx
|
||||
* to be selected on next boot.
|
||||
*
|
||||
* @param current_seq Current active OTA sequence number
|
||||
* @param ota_slot_idx Target OTA slot index (0-based)
|
||||
* @param ota_app_count Total number of OTA slots
|
||||
*
|
||||
* @return New sequence number that will result in booting ota_slot_idx
|
||||
*/
|
||||
static uint32_t compute_ota_seq_for_target_slot(uint32_t current_seq, uint32_t ota_slot_idx, uint8_t ota_app_count)
|
||||
{
|
||||
if (ota_app_count == 0) {
|
||||
return 0;
|
||||
}
|
||||
/* ESP-IDF stores OTA boot information in the OTA data partition, which consists of two sectors.
|
||||
* Each sector holds an esp_ota_select_entry_t structure: otadata[0] and otadata[1].
|
||||
* These structures record the OTA sequence number (ota_seq) used to determine the current boot partition.
|
||||
*
|
||||
* Boot selection logic:
|
||||
* - If both otadata[0].ota_seq and otadata[1].ota_seq are 0xFFFFFFFF (invalid), it is the initial state:
|
||||
* → Boot the factory app, if it exists.
|
||||
* → Otherwise, fall back to booting ota[0].
|
||||
*
|
||||
* - If both otadata entries have valid sequence numbers and CRCs:
|
||||
* → Choose the higher sequence number (max_seq).
|
||||
* → Determine the OTA partition for boot (or running partition) using:
|
||||
* running_ota_slot = (max_seq - 1) % ota_app_count
|
||||
* where ota_app_count is the total number of OTA app partitions.
|
||||
*
|
||||
* Example:
|
||||
* otadata[0].ota_seq = 4
|
||||
* otadata[1].ota_seq = 5
|
||||
* ota_app_count = 8 (available OTA slots: ota_0 to ota_7)
|
||||
* → max_seq = 5
|
||||
* → running slot = (5 - 1) % 8 = 4
|
||||
* → So ota_4 is currently running
|
||||
*
|
||||
* If you want to switch to boot a different OTA slot (e.g., ota_7):
|
||||
* → You need to compute a new sequence number such that:
|
||||
* (new_seq - 1) % ota_app_count == 7
|
||||
* while ensuring new_seq > current_seq.
|
||||
*
|
||||
* General formula:
|
||||
* x = current OTA slot ID
|
||||
* ota_slot_idx = desired OTA slot ID
|
||||
* seq = current ota_seq
|
||||
*
|
||||
* To find the next ota_seq that will boot ota_y, use:
|
||||
* new_seq = ((ota_slot_idx + 1) % ota_app_count) + ota_app_count * i;
|
||||
* // where i is the smallest non-negative integer such that new_seq > seq
|
||||
*/
|
||||
uint32_t i = 0;
|
||||
uint32_t base = (ota_slot_idx + 1) % ota_app_count;
|
||||
while (current_seq > (base + i * ota_app_count)) { i++; };
|
||||
return base + i * ota_app_count;
|
||||
}
|
||||
|
||||
uint8_t esp_ota_get_app_partition_count(void)
|
||||
{
|
||||
uint16_t ota_app_count = 0;
|
||||
@@ -612,30 +549,6 @@ uint8_t esp_ota_get_app_partition_count(void)
|
||||
return ota_app_count;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Update the OTA data partition to set the given OTA app subtype as the next boot target.
|
||||
*
|
||||
* ESP-IDF uses the OTA data partition to track which OTA app should boot.
|
||||
* This partition contains two entries (otadata[0] and otadata[1]), each storing an esp_ota_select_entry_t struct,
|
||||
* which includes the OTA sequence number (ota_seq).
|
||||
*
|
||||
* On boot, the chip determines the current running OTA slot using:
|
||||
* current_slot = (max(ota_seq) - 1) % ota_app_count
|
||||
*
|
||||
* This function updates the OTA data to switch the next boot to the partition with the given subtype.
|
||||
*
|
||||
* Behavior:
|
||||
* - If the currently selected OTA slot already matches the requested subtype,
|
||||
* only the state field is updated (e.g., to mark the app as newly downloaded).
|
||||
* - Otherwise, it calculates the next valid ota_seq that will cause the bootloader to select
|
||||
* the requested OTA slot on reboot, and writes it to the inactive OTA data sector.
|
||||
*
|
||||
* @param subtype The OTA partition subtype (e.g., ESP_PARTITION_SUBTYPE_APP_OTA_0, ..._OTA_1, ...)
|
||||
* @return
|
||||
* - ESP_OK if update was successful
|
||||
* - ESP_ERR_NOT_FOUND if OTA data partition not found
|
||||
* - ESP_ERR_INVALID_ARG if subtype is out of range
|
||||
*/
|
||||
static esp_err_t esp_rewrite_ota_data(esp_partition_subtype_t subtype)
|
||||
{
|
||||
esp_ota_select_entry_t otadata[2];
|
||||
@@ -645,31 +558,42 @@ static esp_err_t esp_rewrite_ota_data(esp_partition_subtype_t subtype)
|
||||
}
|
||||
|
||||
uint8_t ota_app_count = esp_ota_get_app_partition_count();
|
||||
if (OTA_SLOT(subtype) >= ota_app_count) {
|
||||
if (SUB_TYPE_ID(subtype) >= ota_app_count) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
//esp32_idf use two sector for store information about which partition is running
|
||||
//it defined the two sector as ota data partition,two structure esp_ota_select_entry_t is saved in the two sector
|
||||
//named data in first sector as otadata[0], second sector data as otadata[1]
|
||||
//e.g.
|
||||
//if otadata[0].ota_seq == otadata[1].ota_seq == 0xFFFFFFFF,means ota info partition is in init status
|
||||
//so it will boot factory application(if there is),if there's no factory application,it will boot ota[0] application
|
||||
//if otadata[0].ota_seq != 0 and otadata[1].ota_seq != 0,it will choose a max seq ,and get value of max_seq%max_ota_app_number
|
||||
//and boot a subtype (mask 0x0F) value is (max_seq - 1)%max_ota_app_number,so if want switch to run ota[x],can use next formulas.
|
||||
//for example, if otadata[0].ota_seq = 4, otadata[1].ota_seq = 5, and there are 8 ota application,
|
||||
//current running is (5-1)%8 = 4,running ota[4],so if we want to switch to run ota[7],
|
||||
//we should add otadata[0].ota_seq (is 4) to 4 ,(8-1)%8=7,then it will boot ota[7]
|
||||
//if A=(B - C)%D
|
||||
//then B=(A + C)%D + D*n ,n= (0,1,2...)
|
||||
//so current ota app sub type id is x , dest bin subtype is y,total ota app count is n
|
||||
//seq will add (x + n*1 + 1 - seq)%n
|
||||
|
||||
int active_otadata = bootloader_common_get_active_otadata(otadata);
|
||||
int next_otadata;
|
||||
uint32_t new_seq;
|
||||
if (active_otadata != -1) {
|
||||
uint32_t ota_slot = (otadata[active_otadata].ota_seq - 1) % ota_app_count;
|
||||
if (ota_slot == OTA_SLOT(subtype)) {
|
||||
// ota_data is already valid and points to the correct OTA slot.
|
||||
// So after reboot the requested partition will be selected for boot.
|
||||
// Only update the ota_state of the requested partition.
|
||||
next_otadata = active_otadata;
|
||||
new_seq = otadata[active_otadata].ota_seq;
|
||||
} else {
|
||||
next_otadata = (~active_otadata) & 1; // if 0 -> will be next 1. and if 1 -> will be next 0.
|
||||
new_seq = compute_ota_seq_for_target_slot(otadata[active_otadata].ota_seq, OTA_SLOT(subtype), ota_app_count);
|
||||
uint32_t seq = otadata[active_otadata].ota_seq;
|
||||
uint32_t i = 0;
|
||||
while (seq > (SUB_TYPE_ID(subtype) + 1) % ota_app_count + i * ota_app_count) {
|
||||
i++;
|
||||
}
|
||||
int next_otadata = (~active_otadata)&1; // if 0 -> will be next 1. and if 1 -> will be next 0.
|
||||
otadata[next_otadata].ota_state = set_new_state_otadata();
|
||||
return rewrite_ota_seq(otadata, (SUB_TYPE_ID(subtype) + 1) % ota_app_count + i * ota_app_count, next_otadata, otadata_partition);
|
||||
} else {
|
||||
/* Both OTA slots are invalid, probably because unformatted... */
|
||||
next_otadata = 0;
|
||||
new_seq = OTA_SLOT(subtype) + 1;
|
||||
int next_otadata = 0;
|
||||
otadata[next_otadata].ota_state = set_new_state_otadata();
|
||||
return rewrite_ota_seq(otadata, SUB_TYPE_ID(subtype) + 1, next_otadata, otadata_partition);
|
||||
}
|
||||
otadata[next_otadata].ota_state = set_new_state_otadata();
|
||||
return rewrite_ota_seq(otadata, new_seq, next_otadata, otadata_partition);
|
||||
}
|
||||
|
||||
esp_err_t esp_ota_set_boot_partition(const esp_partition_t *partition)
|
||||
|
||||
@@ -42,6 +42,30 @@ extern "C"
|
||||
*/
|
||||
typedef uint32_t esp_ota_handle_t;
|
||||
|
||||
/**
|
||||
* @brief Return esp_app_desc structure. This structure includes app version.
|
||||
*
|
||||
* @note This API is present for backward compatibility reasons. Alternative function
|
||||
* with the same functionality is `esp_app_get_description`
|
||||
*
|
||||
* Return description for running app.
|
||||
* @return Pointer to esp_app_desc structure.
|
||||
*/
|
||||
const esp_app_desc_t *esp_ota_get_app_description(void) __attribute__((deprecated("Please use esp_app_get_description instead")));
|
||||
|
||||
/**
|
||||
* @brief Fill the provided buffer with SHA256 of the ELF file, formatted as hexadecimal, null-terminated.
|
||||
* If the buffer size is not sufficient to fit the entire SHA256 in hex plus a null terminator,
|
||||
* the largest possible number of bytes will be written followed by a null.
|
||||
*
|
||||
* @note This API is present for backward compatibility reasons. Alternative function
|
||||
* with the same functionality is `esp_app_get_elf_sha256`
|
||||
*
|
||||
* @param dst Destination buffer
|
||||
* @param size Size of the buffer
|
||||
* @return Number of bytes written to dst (including null terminator)
|
||||
*/
|
||||
int esp_ota_get_app_elf_sha256(char* dst, size_t size) __attribute__((deprecated("Please use esp_app_get_elf_sha256 instead")));
|
||||
|
||||
/**
|
||||
* @brief Commence an OTA update writing to the specified partition.
|
||||
@@ -89,10 +113,6 @@ esp_err_t esp_ota_begin(const esp_partition_t* partition, size_t image_size, esp
|
||||
* 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 When flash encryption is enabled, data writes must be 16-byte aligned.
|
||||
* Any leftover (non-aligned) data is temporarily cached and may be lost after reboot.
|
||||
* Therefore, during resumption, ensure that image offset is always 16-byte aligned.
|
||||
*
|
||||
* @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.
|
||||
|
||||
@@ -3,8 +3,10 @@
|
||||
# otatool is used to perform ota-level operations - flashing ota partition
|
||||
# erasing ota partition and switching ota partition
|
||||
#
|
||||
# SPDX-FileCopyrightText: 2018-2025 Espressif Systems (Shanghai) CO LTD
|
||||
# SPDX-FileCopyrightText: 2018-2021 Espressif Systems (Shanghai) CO LTD
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
from __future__ import division, print_function
|
||||
|
||||
import argparse
|
||||
import binascii
|
||||
import collections
|
||||
@@ -14,18 +16,12 @@ import sys
|
||||
import tempfile
|
||||
|
||||
try:
|
||||
from parttool import PARTITION_TABLE_OFFSET
|
||||
from parttool import PartitionName
|
||||
from parttool import PartitionType
|
||||
from parttool import ParttoolTarget
|
||||
from parttool import PARTITION_TABLE_OFFSET, PartitionName, PartitionType, ParttoolTarget
|
||||
except ImportError:
|
||||
COMPONENTS_PATH = os.path.expandvars(os.path.join('$IDF_PATH', 'components'))
|
||||
PARTTOOL_DIR = os.path.join(COMPONENTS_PATH, 'partition_table')
|
||||
sys.path.append(PARTTOOL_DIR)
|
||||
from parttool import PARTITION_TABLE_OFFSET
|
||||
from parttool import PartitionName
|
||||
from parttool import PartitionType
|
||||
from parttool import ParttoolTarget
|
||||
from parttool import PARTITION_TABLE_OFFSET, PartitionName, PartitionType, ParttoolTarget
|
||||
|
||||
__version__ = '2.0'
|
||||
|
||||
@@ -39,31 +35,15 @@ def status(msg):
|
||||
print(msg)
|
||||
|
||||
|
||||
class OtatoolTarget:
|
||||
class OtatoolTarget():
|
||||
|
||||
OTADATA_PARTITION = PartitionType('data', 'ota')
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
port=None,
|
||||
baud=None,
|
||||
partition_table_offset=PARTITION_TABLE_OFFSET,
|
||||
partition_table_file=None,
|
||||
spi_flash_sec_size=SPI_FLASH_SEC_SIZE,
|
||||
esptool_args=[],
|
||||
esptool_write_args=[],
|
||||
esptool_read_args=[],
|
||||
esptool_erase_args=[],
|
||||
):
|
||||
self.target = ParttoolTarget(
|
||||
port,
|
||||
baud,
|
||||
partition_table_offset,
|
||||
partition_table_file,
|
||||
esptool_args,
|
||||
esptool_write_args,
|
||||
esptool_read_args,
|
||||
esptool_erase_args,
|
||||
)
|
||||
def __init__(self, port=None, baud=None, partition_table_offset=PARTITION_TABLE_OFFSET, partition_table_file=None,
|
||||
spi_flash_sec_size=SPI_FLASH_SEC_SIZE, esptool_args=[], esptool_write_args=[],
|
||||
esptool_read_args=[], esptool_erase_args=[]):
|
||||
self.target = ParttoolTarget(port, baud, partition_table_offset, partition_table_file, esptool_args,
|
||||
esptool_write_args, esptool_read_args, esptool_erase_args)
|
||||
self.spi_flash_sec_size = spi_flash_sec_size
|
||||
|
||||
temp_file = tempfile.NamedTemporaryFile(delete=False)
|
||||
@@ -91,8 +71,8 @@ class OtatoolTarget:
|
||||
for i in range(2):
|
||||
start = i * (self.spi_flash_sec_size >> 1)
|
||||
|
||||
seq = bytearray(self.otadata[start : start + 4])
|
||||
crc = bytearray(self.otadata[start + 28 : start + 32])
|
||||
seq = bytearray(self.otadata[start:start + 4])
|
||||
crc = bytearray(self.otadata[start + 28:start + 32])
|
||||
|
||||
seq = struct.unpack('I', seq)
|
||||
crc = struct.unpack('I', crc)
|
||||
@@ -138,9 +118,7 @@ class OtatoolTarget:
|
||||
|
||||
try:
|
||||
if isinstance(ota_id, int):
|
||||
ota_partition_next = filter(
|
||||
lambda p: p.subtype - gen.MIN_PARTITION_SUBTYPE_APP_OTA == ota_id, ota_partitions
|
||||
)
|
||||
ota_partition_next = filter(lambda p: p.subtype - gen.MIN_PARTITION_SUBTYPE_APP_OTA == ota_id, ota_partitions)
|
||||
else:
|
||||
ota_partition_next = filter(lambda p: p.name == ota_id, ota_partitions)
|
||||
|
||||
@@ -214,8 +192,8 @@ class OtatoolTarget:
|
||||
def read_ota_partition(self, ota_id, output):
|
||||
self.target.read_partition(self._get_partition_id_from_ota_id(ota_id), output)
|
||||
|
||||
def write_ota_partition(self, ota_id, input_file):
|
||||
self.target.write_partition(self._get_partition_id_from_ota_id(ota_id), input_file)
|
||||
def write_ota_partition(self, ota_id, input):
|
||||
self.target.write_partition(self._get_partition_id_from_ota_id(ota_id), input)
|
||||
|
||||
def erase_ota_partition(self, ota_id):
|
||||
self.target.erase_partition(self._get_partition_id_from_ota_id(ota_id))
|
||||
@@ -227,10 +205,8 @@ def _read_otadata(target):
|
||||
otadata_info = target._get_otadata_info()
|
||||
|
||||
print(' {:8s} \t {:8s} | \t {:8s} \t {:8s}'.format('OTA_SEQ', 'CRC', 'OTA_SEQ', 'CRC'))
|
||||
print(
|
||||
f'Firmware: {otadata_info[0].seq:#08x} \t{otadata_info[0].crc:#08x} | '
|
||||
f'\t{otadata_info[1].seq:#08x} \t {otadata_info[1].crc:#08x}'
|
||||
)
|
||||
print('Firmware: 0x{:08x} \t0x{:08x} | \t0x{:08x} \t 0x{:08x}'.format(otadata_info[0].seq, otadata_info[0].crc,
|
||||
otadata_info[1].seq, otadata_info[1].crc))
|
||||
|
||||
|
||||
def _erase_otadata(target):
|
||||
@@ -244,12 +220,12 @@ def _switch_ota_partition(target, ota_id):
|
||||
|
||||
def _read_ota_partition(target, ota_id, output):
|
||||
target.read_ota_partition(ota_id, output)
|
||||
status(f'Read ota partition contents to file {output}')
|
||||
status('Read ota partition contents to file {}'.format(output))
|
||||
|
||||
|
||||
def _write_ota_partition(target, ota_id, input_file):
|
||||
target.write_ota_partition(ota_id, input_file)
|
||||
status(f'Written contents of file {input_file} to ota partition')
|
||||
def _write_ota_partition(target, ota_id, input):
|
||||
target.write_ota_partition(ota_id, input)
|
||||
status('Written contents of file {} to ota partition'.format(input))
|
||||
|
||||
|
||||
def _erase_ota_partition(target, ota_id):
|
||||
@@ -264,13 +240,9 @@ def main():
|
||||
|
||||
parser.add_argument('--quiet', '-q', help='suppress stderr messages', action='store_true')
|
||||
parser.add_argument('--esptool-args', help='additional main arguments for esptool', nargs='+')
|
||||
parser.add_argument(
|
||||
'--esptool-write-args', help='additional subcommand arguments for esptool write-flash', nargs='+'
|
||||
)
|
||||
parser.add_argument('--esptool-read-args', help='additional subcommand arguments for esptool read-flash', nargs='+')
|
||||
parser.add_argument(
|
||||
'--esptool-erase-args', help='additional subcommand arguments for esptool erase-region', nargs='+'
|
||||
)
|
||||
parser.add_argument('--esptool-write-args', help='additional subcommand arguments for esptool write_flash', nargs='+')
|
||||
parser.add_argument('--esptool-read-args', help='additional subcommand arguments for esptool read_flash', nargs='+')
|
||||
parser.add_argument('--esptool-erase-args', help='additional subcommand arguments for esptool erase_region', nargs='+')
|
||||
|
||||
# There are two possible sources for the partition table: a device attached to the host
|
||||
# or a partition table CSV/binary file. These sources are mutually exclusive.
|
||||
@@ -278,14 +250,10 @@ def main():
|
||||
|
||||
parser.add_argument('--baud', '-b', help='baudrate to use', type=int)
|
||||
|
||||
parser.add_argument('--partition-table-offset', '-o', help='offset to read the partition table from', type=str)
|
||||
parser.add_argument('--partition-table-offset', '-o', help='offset to read the partition table from', type=str)
|
||||
|
||||
parser.add_argument(
|
||||
'--partition-table-file',
|
||||
'-f',
|
||||
help='file (CSV/binary) to read the partition table from; '
|
||||
'overrides device attached to specified port as the partition table source when defined',
|
||||
)
|
||||
parser.add_argument('--partition-table-file', '-f', help='file (CSV/binary) to read the partition table from; \
|
||||
overrides device attached to specified port as the partition table source when defined')
|
||||
|
||||
subparsers = parser.add_subparsers(dest='operation', help='run otatool -h for additional help')
|
||||
|
||||
@@ -301,25 +269,15 @@ def main():
|
||||
slot_or_name_parser_args.add_argument('--slot', help='slot number of the ota partition', type=int)
|
||||
slot_or_name_parser_args.add_argument('--name', help='name of the ota partition')
|
||||
|
||||
subparsers.add_parser(
|
||||
'switch_ota_partition', help='switch otadata partition', parents=[slot_or_name_parser, spi_flash_sec_size]
|
||||
)
|
||||
subparsers.add_parser('switch_ota_partition', help='switch otadata partition', parents=[slot_or_name_parser, spi_flash_sec_size])
|
||||
|
||||
read_ota_partition_subparser = subparsers.add_parser(
|
||||
'read_ota_partition', help='read contents of an ota partition', parents=[slot_or_name_parser]
|
||||
)
|
||||
read_ota_partition_subparser.add_argument(
|
||||
'--output', help='file to write the contents of the ota partition to', required=True
|
||||
)
|
||||
read_ota_partition_subparser = subparsers.add_parser('read_ota_partition', help='read contents of an ota partition', parents=[slot_or_name_parser])
|
||||
read_ota_partition_subparser.add_argument('--output', help='file to write the contents of the ota partition to', required=True)
|
||||
|
||||
write_ota_partition_subparser = subparsers.add_parser(
|
||||
'write_ota_partition', help='write contents to an ota partition', parents=[slot_or_name_parser]
|
||||
)
|
||||
write_ota_partition_subparser = subparsers.add_parser('write_ota_partition', help='write contents to an ota partition', parents=[slot_or_name_parser])
|
||||
write_ota_partition_subparser.add_argument('--input', help='file whose contents to write to the ota partition')
|
||||
|
||||
subparsers.add_parser(
|
||||
'erase_ota_partition', help='erase contents of an ota partition', parents=[slot_or_name_parser]
|
||||
)
|
||||
subparsers.add_parser('erase_ota_partition', help='erase contents of an ota partition', parents=[slot_or_name_parser])
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
@@ -366,7 +324,7 @@ def main():
|
||||
target = OtatoolTarget(**target_args)
|
||||
|
||||
# Create the operation table and execute the operation
|
||||
common_args = {'target': target}
|
||||
common_args = {'target':target}
|
||||
|
||||
ota_id = []
|
||||
|
||||
@@ -380,18 +338,18 @@ def main():
|
||||
pass
|
||||
|
||||
otatool_ops = {
|
||||
'read_otadata': (_read_otadata, []),
|
||||
'erase_otadata': (_erase_otadata, []),
|
||||
'switch_ota_partition': (_switch_ota_partition, ota_id),
|
||||
'read_ota_partition': (_read_ota_partition, ['output'] + ota_id),
|
||||
'write_ota_partition': (_write_ota_partition, ['input'] + ota_id),
|
||||
'erase_ota_partition': (_erase_ota_partition, ota_id),
|
||||
'read_otadata':(_read_otadata, []),
|
||||
'erase_otadata':(_erase_otadata, []),
|
||||
'switch_ota_partition':(_switch_ota_partition, ota_id),
|
||||
'read_ota_partition':(_read_ota_partition, ['output'] + ota_id),
|
||||
'write_ota_partition':(_write_ota_partition, ['input'] + ota_id),
|
||||
'erase_ota_partition':(_erase_ota_partition, ota_id)
|
||||
}
|
||||
|
||||
(op, op_args) = otatool_ops[args.operation]
|
||||
|
||||
for op_arg in op_args:
|
||||
common_args.update({op_arg: vars(args)[op_arg]})
|
||||
common_args.update({op_arg:vars(args)[op_arg]})
|
||||
|
||||
try:
|
||||
common_args['ota_id'] = common_args.pop('name')
|
||||
|
||||
@@ -7,7 +7,6 @@ components/app_update/test_apps:
|
||||
- if: CONFIG_NAME == "xip_psram" and SOC_SPIRAM_XIP_SUPPORTED == 1
|
||||
# S2 doesn't have ROM for flash
|
||||
- if: CONFIG_NAME == "xip_psram_with_rom_impl" and (SOC_SPIRAM_XIP_SUPPORTED == 1 and IDF_TARGET != "esp32s2")
|
||||
- if: CONFIG_NAME == "recovery_bootloader" and SOC_RECOVERY_BOOTLOADER_SUPPORTED == 1
|
||||
disable:
|
||||
- if: IDF_TARGET in ["esp32h21", "esp32h4"]
|
||||
temporary: true
|
||||
@@ -15,10 +14,3 @@ components/app_update/test_apps:
|
||||
- if: IDF_TARGET == "esp32c61" and CONFIG_NAME == "xip_psram_with_rom_impl"
|
||||
temporary: true
|
||||
reason: not supported yet # TODO: [ESP32C61] IDF-12784
|
||||
- if: IDF_TARGET == "esp32p4"
|
||||
temporary: true
|
||||
reason: p4 rev3 migration # TODO: IDF-14401
|
||||
disable_test:
|
||||
- if: CONFIG_NAME == "recovery_bootloader" and SOC_RECOVERY_BOOTLOADER_SUPPORTED == 1 and IDF_TARGET == "esp32c61"
|
||||
temporary: true
|
||||
reason: lack of runners # TODO: [ESP32C61] IDF-13165
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user