Compare commits

..

52 Commits
v4.0.4 ... v2.1

Author SHA1 Message Date
Ivan Grokhotkov
27574a31e7 Merge branch 'feature/tw12244_add_more_comments_for_wifi_api_v2.1' into 'release/v2.1'
docs: add wifi doc

See merge request !1046
2017-07-24 19:42:36 +08:00
Liu Zhi Fu
8134140acd docs: add wifi doc
Add more comments about WiFi API usage
2017-07-24 14:52:00 +08:00
Ivan Grokhotkov
efdbc63b5f Merge branch 'cherry-pick-292c2abd' into 'release/v2.1'
Merge branch 'bugfix/init_nvs_in_bluetooth' into 'master'

See merge request !1031
2017-07-23 14:35:33 +08:00
Ivan Grokhotkov
1891382db6 examples: add missing nvs_flash.h include 2017-07-20 17:53:39 +08:00
Ivan Grokhotkov
16cd517410 Merge branch 'bugfix/tw14046_scan_assert_in_non_sleep_mode' into 'release/v2.1'
Fix the bug that scan assert in non sleep mode.

See merge request !1023
2017-07-20 14:57:04 +08:00
Ivan Grokhotkov
8fc78a958a Merge branch 'bugfix/init_nvs_in_bluetooth' into 'master'
bt: call nvs_flash_init in examples, show error if NVS is not initialized

See merge request !1003
2017-07-20 14:26:14 +08:00
Ivan Grokhotkov
3cbaf98d29 Merge branch 'bugfix/btdm_rx_losing' into 'release/v2.1'
component/bt : update libbtadm_app.a (easing syncerr to fix RX packet losing bug)

See merge request !1029
2017-07-20 14:19:49 +08:00
Tian Hao
b2d41a3506 component/bt : update libbtadm_app.a (easing syncerr to fix RX packet losing bug) 2017-07-20 11:51:28 +08:00
XiaXiaotian
5d1ec0da02 Fix the bug that scan assert in non sleep mode. 2017-07-19 14:12:14 +08:00
Jiang Jiang Jian
6a9e9759ea Merge branch 'bugfix/l2cap_disc_tmo' into 'release/v2.1'
component/bt: fix a bug for L2CAP state machine to access lcb after it is released

See merge request !1015
2017-07-18 19:49:05 +08:00
wangmengyang
0de622e4f6 component/bt: fix a bug for L2CAP state machine to access lcb after it is released
cherry-pick commit 6da84eff
2017-07-17 21:30:40 +08:00
Ivan Grokhotkov
fc67a8b1b9 Merge branch 'cherry-pick-5d736f7eca' into 'release/v2.1'
mbedtls: Fix memory leak in initial ECDH exchange if OOM/failure occurs

See merge request !995
2017-07-17 21:18:32 +08:00
Jiang Jiang Jian
41f43164e2 Merge branch 'cherry-pick-0c28b3bc' into 'release/v2.1'
Merge branch 'bugfix/btdm_update_connect_params_for_gattc' into 'master'

See merge request !996
2017-07-17 21:10:54 +08:00
Jiang Jiang Jian
2236ab7bd4 Merge branch 'cherry-pick-5ac0503c' into 'release/v2.1'
Merge branch 'bugfix/btdm_modify_BTA_GATTC_KNOWN_SR_MAX_for_Multi-connection' into 'master'

See merge request !999
2017-07-17 21:10:30 +08:00
Jiang Jiang Jian
a281359db0 Merge branch 'cherry-pick-4ec2abbf' into 'release/v2.1'
Merge branch 'feature/some_refactor_for_tcpip_adapter' into 'master'

See merge request !1000
2017-07-17 21:10:04 +08:00
Jiang Jiang Jian
1fb777cc49 Merge branch 'feature/some_refactor_for_tcpip_adapter' into 'master'
tcpip_adapter: not remove netif when tcpip adapter is stopped

See merge request !943
2017-07-13 22:16:58 +08:00
Jiang Jiang Jian
92facb6884 Merge branch 'bugfix/btdm_modify_BTA_GATTC_KNOWN_SR_MAX_for_Multi-connection' into 'master'
component/bt: modify BTA_GATTC_KNOWN_SR_MAX for Multi-connection bug

See merge request !992
2017-07-13 21:55:36 +08:00
Ivan Grokhotkov
eb38883217 Merge branch 'bugfix/btdm_update_connect_params_for_gattc' into 'master'
component/bt: bugfix update connect params for gattc

See merge request !991
2017-07-13 16:08:02 +08:00
Angus Gratton
5d736f7eca mbedtls: Fix memory leak in initial ECDH exchange if OOM/failure occurs
In ecp_mul_comb(), if (!p_eq_g && grp->T == NULL) and ecp_precompute_comb() fails (which can happen due to OOM), then the new array of points T was leaked.
2017-07-13 15:55:57 +08:00
Ivan Grokhotkov
bdc499aea7 Merge branch 'cherry-pick-94877972' into 'release/v2.1'
freertos: Bump idle stack size to 1KB, min stack to 768 bytes, make configurable

See merge request !981
2017-07-12 22:39:12 +08:00
Angus Gratton
99dbfb3539 Merge branch 'bugfix/minimal_stack_size' into 'master'
freertos: Bump idle stack size to 1KB, min stack to 768 bytes, make configurable

See merge request !979
2017-07-12 04:24:18 +08:00
Jiang Jiang Jian
8d3e1a2a79 Merge branch 'bugfix/btdm_blufi_aes_cfb128_for_v2.1' into 'release/v2.1'
component/bt : comment out set_key_dec for res cfb128(software crypt)

See merge request !972
2017-07-09 11:52:23 +08:00
Jiang Jiang Jian
f33b0fd4c9 Merge branch 'bugfix/btdm_update_lib_for_v2.1' into 'release/v2.1'
component/bt : update lib for fix register reg(follow V2.1 RC)

See merge request !973
2017-07-08 23:29:37 +08:00
Tian Hao
b99551b48f component/bt : update lib for fix register reg(follow V2.1 RC) 2017-07-08 22:48:26 +08:00
Tian Hao
6c04e3ee6a component/bt : comment out set_key_dec for res cfb128(software crypt) 2017-07-08 22:46:02 +08:00
Jiang Jiang Jian
6878c4e329 Merge branch 'cherry-pick-7a79d31d' into 'release/v2.1'
fix reg operation missing

See merge request !966
2017-07-08 15:46:58 +08:00
Jiang Jiang Jian
f54a656932 Merge branch 'bugfix/make_low_rate_work' into 'release/v2.1'
esp32: udpate wifi lib to make low rate work

See merge request !967
2017-07-08 01:11:26 +08:00
Liu Zhi Fu
305564cd59 esp32: udpate wifi lib to make low rate work
Make low rate feature work
2017-07-07 22:47:39 +08:00
Tian Hao
6bceb41bf7 fix reg operation missing 2017-07-07 22:44:05 +08:00
Ivan Grokhotkov
2e9db99921 Merge branch 'cherry-pick-6d03d42d' into 'release/v2.1'
Merge branch 'bugfix/btdm_error_length_unit' into 'master'

See merge request !960
2017-07-07 11:14:03 +08:00
Ivan Grokhotkov
fa7d3f38fc Merge branch 'cherry_pick_to_release_v2.1' into 'release/v2.1'
Update release/v2.1 with some bug fixes

See merge request !952
2017-07-07 11:13:43 +08:00
Angus Gratton
602e223c9c mbedtls unit tests: Allow for longer timeout using software SHA
Hardware SHA runs SHA operations faster than software...
2017-07-06 18:09:59 +08:00
Jiang Jiang Jian
baa743c7b9 Merge branch 'bugfix/btdm_error_length_unit' into 'master'
Component/bt: fix bug for  error length unit

See merge request !950
2017-07-06 14:49:09 +08:00
Ivan Grokhotkov
6db29f0766 soc: fix typo in register name 2017-07-06 14:29:37 +08:00
Ivan Grokhotkov
abec2392c7 esp_chip_info: populate ‘model’ field 2017-07-06 14:29:30 +08:00
Ivan Grokhotkov
8a54ebe02e docs: update general notes section on IRAM/ISRs
- Remove outdated note that all ISRs should be in IRAM
- Replace “ISR handler” with “ISR” or “interrupt handler”
2017-07-06 14:29:23 +08:00
Ivan Grokhotkov
0a1c68d7b6 docs: fix flash encryption key storage block, use same names as in TRM 2017-07-06 14:29:15 +08:00
Ivan Grokhotkov
494641c481 phy_init: fix log level for "PHY data partition validated" message 2017-07-06 14:29:08 +08:00
Angus Gratton
3ab2436b11 mbedtls: Temporarily disable hardware acceleration in dual-core mode
Temporary fix, until DPORT bugs in crypto accelerators are completely fixed.
2017-07-06 14:28:43 +08:00
Ivan Grokhotkov
ee86c15ab8 Merge branch 'cherry-pick-55b3ea9c' into 'release/v2.1'
Merge branch 'bugfix/btdm_cherry-pick_ble_smp_bonding_issues' into 'master'

See merge request !949
2017-07-04 17:28:30 +08:00
Ivan Grokhotkov
9deaa6ab60 Merge branch 'cherry-pick-3c082b47' into 'release/v2.1'
Merge branch 'bugfix/bt_avdt_state_machine' into 'master'

See merge request !948
2017-07-04 17:28:17 +08:00
Ivan Grokhotkov
8a5c1e9209 Merge branch 'cherry-pick-176107f8' into 'release/v2.1'
update expiration date of wpa2 enterprise certificates to 2027/06/05.

See merge request !945
2017-07-04 17:28:00 +08:00
Simon Werner
3d3994632b ESP_ERR_NVS_VALUE_TOO_LONG had conflicting value.
`ESP_ERR_NVS_VALUE_TOO_LONG` had conflicting value, its original value was `0x0c`, which is the same as `ESP_ERR_NVS_INVALID_LENGTH`
2017-07-04 15:31:33 +08:00
Ivan Grokhotkov
17dd3e9ca0 nvs: add test for ESP_ERR_NVS_INVALID_LENGTH 2017-07-04 15:31:10 +08:00
Angus Gratton
c40bbc5c42 ipc task: Allow configuration of IPC task stack size
Fixes regression in 3fe0022ef
2017-07-04 15:30:04 +08:00
Angus Gratton
1b3120615b stack sizes: Revert stack size increases added in 8d43859
Set min stack size to 2048 if AppTrace support is enabled, 512 bytes otherwise.
2017-07-04 15:29:33 +08:00
Angus Gratton
3365b9322b dport_access: Fix spurious warning in unicore mode, refactor 2017-07-04 15:27:31 +08:00
Wangjialin
852e94d73a bugfix(uart): fix bugs reported from github
1. uart_set_line_inverse API issue, https://github.com/espressif/esp-idf/issues/673
2. tx buffer length issue, https://github.com/espressif/esp-idf/issues/710
2017-07-04 15:24:02 +08:00
Angus Gratton
09bb7a7650 newlib locks: Fix _lock_init() & _lock_init_recursive() failing to initialise a lock
If scheduler was running, and lock was an automatic variable (ie stack-allocated) to be initialised by _lock_init*,
initialisation could be skipped if the lock variable was non-zero (and lock would be left invalid).

In other cases the lock is statically initialised to zero by __LOCK_INIT*
2017-07-04 15:23:10 +08:00
Jiang Jiang Jian
4f4fb7b453 Merge branch 'bugfix/btdm_cherry-pick_ble_smp_bonding_issues' into 'master'
component/bt: Fixed the bug crash of disconnet BLE when close the SMP module in the menuconfig.

See merge request !941
2017-07-03 19:49:30 +08:00
Jiang Jiang Jian
663129abce Merge branch 'bugfix/bt_avdt_state_machine' into 'master'
component/bt: bugfix for AVDTP state machine function on disconnection to handle NULL pointer condition

See merge request !946
2017-07-03 19:48:40 +08:00
XiaXiaotian
9cf81f754b update expiration date of wpa2 enterprise certificates to 2027/06/05. 2017-07-03 15:41:11 +08:00
5993 changed files with 377298 additions and 752652 deletions

View File

@@ -1,39 +0,0 @@
# EditorConfig helps developers define and maintain consistent
# coding styles between different editors and IDEs
# http://editorconfig.org
root = true
[*]
indent_style = space
indent_size = 4
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[{*.md,*.rst}]
trim_trailing_whitespace = false
[{Makefile,*.mk,*.bat}]
indent_style = tab
indent_size = 2
[*/freertos/**]
indent_style = tab
indent_size = 4
[{*/freertos/**.S,**/FreeRTOSConfig.h}]
indent_style = space
indent_size = 4
[*.pem]
insert_final_newline = false
[*.py]
max_line_length = 119
[{*.cmake,CMakeLists.txt}]
indent_style = space
indent_size = 4
max_line_length = 120

164
.flake8
View File

@@ -1,164 +0,0 @@
[flake8]
select =
# Full lists are given in order to suppress all errors from other plugins
# Full list of pyflakes error codes:
F401, # module imported but unused
F402, # import module from line N shadowed by loop variable
F403, # 'from module import *' used; unable to detect undefined names
F404, # future import(s) name after other statements
F405, # name may be undefined, or defined from star imports: module
F406, # 'from module import *' only allowed at module level
F407, # an undefined __future__ feature name was imported
F601, # dictionary key name repeated with different values
F602, # dictionary key variable name repeated with different values
F621, # too many expressions in an assignment with star-unpacking
F622, # two or more starred expressions in an assignment (a, *b, *c = d)
F631, # assertion test is a tuple, which are always True
F701, # a break statement outside of a while or for loop
F702, # a continue statement outside of a while or for loop
F703, # a continue statement in a finally block in a loop
F704, # a yield or yield from statement outside of a function
F705, # a return statement with arguments inside a generator
F706, # a return statement outside of a function/method
F707, # an except: block as not the last exception handler
F721, F722, # doctest syntax error syntax error in forward type annotation
F811, # redefinition of unused name from line N
F812, # list comprehension redefines name from line N
F821, # undefined name name
F822, # undefined name name in __all__
F823, # local variable name referenced before assignment
F831, # duplicate argument name in function definition
F841, # local variable name is assigned to but never used
F901, # raise NotImplemented should be raise NotImplementedError
# Full list of pycodestyle violations:
E101, # indentation contains mixed spaces and tabs
E111, # indentation is not a multiple of four
E112, # expected an indented block
E113, # unexpected indentation
E114, # indentation is not a multiple of four (comment)
E115, # expected an indented block (comment)
E116, # unexpected indentation (comment)
E121, # continuation line under-indented for hanging indent
E122, # continuation line missing indentation or outdented
E123, # closing bracket does not match indentation of opening bracket's line
E124, # closing bracket does not match visual indentation
E125, # continuation line with same indent as next logical line
E126, # continuation line over-indented for hanging indent
E127, # continuation line over-indented for visual indent
E128, # continuation line under-indented for visual indent
E129, # visually indented line with same indent as next logical line
E131, # continuation line unaligned for hanging indent
E133, # closing bracket is missing indentation
E201, # whitespace after '('
E202, # whitespace before ')'
E203, # whitespace before ':'
E211, # whitespace before '('
E221, # multiple spaces before operator
E222, # multiple spaces after operator
E223, # tab before operator
E224, # tab after operator
E225, # missing whitespace around operator
E226, # missing whitespace around arithmetic operator
E227, # missing whitespace around bitwise or shift operator
E228, # missing whitespace around modulo operator
E231, # missing whitespace after ',', ';', or ':'
E241, # multiple spaces after ','
E242, # tab after ','
E251, # unexpected spaces around keyword / parameter equals
E261, # at least two spaces before inline comment
E262, # inline comment should start with '# '
E265, # block comment should start with '# '
E266, # too many leading '#' for block comment
E271, # multiple spaces after keyword
E272, # multiple spaces before keyword
E273, # tab after keyword
E274, # tab before keyword
E275, # missing whitespace after keyword
E301, # expected 1 blank line, found 0
E302, # expected 2 blank lines, found 0
E303, # too many blank lines
E304, # blank lines found after function decorator
E305, # expected 2 blank lines after end of function or class
E306, # expected 1 blank line before a nested definition
E401, # multiple imports on one line
E402, # module level import not at top of file
E501, # line too long (82 > 79 characters)
E502, # the backslash is redundant between brackets
E701, # multiple statements on one line (colon)
E702, # multiple statements on one line (semicolon)
E703, # statement ends with a semicolon
E704, # multiple statements on one line (def)
E711, # comparison to None should be 'if cond is None:'
E712, # comparison to True should be 'if cond is True:' or 'if cond:'
E713, # test for membership should be 'not in'
E714, # test for object identity should be 'is not'
E721, # do not compare types, use 'isinstance()'
E722, # do not use bare except, specify exception instead
E731, # do not assign a lambda expression, use a def
E741, # do not use variables named 'l', 'O', or 'I'
E742, # do not define classes named 'l', 'O', or 'I'
E743, # do not define functions named 'l', 'O', or 'I'
E901, # SyntaxError or IndentationError
E902, # IOError
W191, # indentation contains tabs
W291, # trailing whitespace
W292, # no newline at end of file
W293, # blank line contains whitespace
W391, # blank line at end of file
W503, # line break before binary operator
W504, # line break after binary operator
W505, # doc line too long (82 > 79 characters)
W601, # .has_key() is deprecated, use 'in'
W602, # deprecated form of raising exception
W603, # '<>' is deprecated, use '!='
W604, # backticks are deprecated, use 'repr()'
W605, # invalid escape sequence 'x'
W606, # 'async' and 'await' are reserved keywords starting with Python 3.7
# Full list of flake8 violations
E999, # failed to compile a file into an Abstract Syntax Tree for the plugins that require it
# Full list of mccabe violations
C901 # complexity value provided by the user
ignore =
E221, # multiple spaces before operator
E231, # missing whitespace after ',', ';', or ':'
E241, # multiple spaces after ','
W503, # line break before binary operator
W504 # line break after binary operator
max-line-length = 160
show_source = True
statistics = True
exclude =
.git,
__pycache__,
# submodules
components/bootloader/subproject/components/micro-ecc/micro-ecc,
components/esptool_py/esptool,
components/expat/expat,
components/json/cJSON,
components/libsodium/libsodium,
components/mbedtls/mbedtls,
components/nghttp/nghttp2,
components/bt/host/nimble/nimble,
components/unity/unity,
examples/build_system/cmake/import_lib/main/lib/tinyxml2,
# other third-party libraries
tools/kconfig_new/kconfiglib.py,
# autogenerated scripts
components/protocomm/python/constants_pb2.py,
components/protocomm/python/sec0_pb2.py,
components/protocomm/python/sec1_pb2.py,
components/protocomm/python/session_pb2.py,
components/wifi_provisioning/python/wifi_scan_pb2.py,
components/wifi_provisioning/python/wifi_config_pb2.py,
components/wifi_provisioning/python/wifi_constants_pb2.py,
components/esp_local_ctrl/python/esp_local_ctrl_pb2.py,
examples/provisioning/custom_config/components/custom_provisioning/python/custom_config_pb2.py,

22
.github/main.workflow vendored
View File

@@ -1,22 +0,0 @@
workflow "Sync issues to JIRA" {
on = "issues"
resolves = ["Sync to JIRA"]
}
workflow "Sync issue and PR comments to JIRA" {
on = "issue_comment"
resolves = ["Sync to JIRA"]
}
workflow "Sync PRs to JIRA" {
on = "pull_request"
resolves = ["Sync to JIRA"]
}
action "Sync to JIRA" {
uses = "espressif/github-actions/sync_issues_to_jira@master"
secrets = ["GITHUB_TOKEN", "JIRA_URL", "JIRA_USER", "JIRA_PASS"]
env = {
JIRA_PROJECT = "IDFGH"
}
}

View File

@@ -1,17 +0,0 @@
name: Create zip file with recursive source clone for release
on:
push:
tags:
- v*
jobs:
release_zips:
name: Create release zip file
runs-on: ubuntu-20.04
steps:
- name: Create a recursive clone source zip
uses: espressif/github-actions/release_zips@master
env:
RELEASE_PROJECT_NAME: ESP-IDF
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

46
.gitignore vendored
View File

@@ -18,53 +18,23 @@ GPATH
# eclipse setting
.settings
# MacOS directory files
.DS_Store
# Example project files
examples/**/sdkconfig
examples/**/sdkconfig.old
examples/**/build
# Doc build artifacts
docs/*/_build/
docs/*/doxygen-warning-log.txt
docs/*/sphinx-warning-log.txt
docs/*/sphinx-warning-log-sanitized.txt
docs/*/xml/
docs/*/xml_in/
docs/*/man/
docs/doxygen_sqlite3.db
# Downloaded font files
docs/_static/DejaVuSans.ttf
docs/_static/NotoSansSC-Regular.otf
#Doc build artifacts
docs/_build/
docs/doxygen-warning-log.txt
docs/sphinx-warning-log.txt
docs/xml/
docs/man/
# Unit test app files
tools/unit-test-app/sdkconfig
tools/unit-test-app/sdkconfig.old
tools/unit-test-app/build
tools/unit-test-app/builds
tools/unit-test-app/output
# IDF monitor test
tools/test_idf_monitor/outputs
# AWS IoT Examples require device-specific certs/keys
examples/protocols/aws_iot/*/main/certs/*.pem.*
TEST_LOGS
# gcov coverage reports
*.gcda
*.gcno
coverage.info
coverage_report/
test_multi_heap_host
# VS Code Settings
.vscode/
# Results for the checking of the Python coding style
flake8_output.txt
# ESP-IDF library
build

View File

@@ -1,23 +1,10 @@
stages:
- build
- assign_test
- host_test
- target_test
- check
- unit_test
- test
- test_report
- deploy
- post_check
# pipelines will not be created in such two cases:
# 1. MR push
# 2. push not on "master/release" branches, and not tagged
# This behavior could be changed after the `rules: changes` feature is implemented
workflow:
rules:
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
when: never
- if: '$CI_COMMIT_REF_NAME != "master" && $CI_COMMIT_BRANCH !~ /^release\/v/ && $CI_COMMIT_TAG !~ /^v\d+\.\d+(\.\d+)?($|-)/ && $CI_PIPELINE_SOURCE == "push"'
when: never
- when: always
variables:
# System environment
@@ -27,60 +14,15 @@ variables:
# GitLab-CI environment
# XXX_ATTEMPTS variables (https://docs.gitlab.com/ce/ci/yaml/README.html#job-stages-attempts) are not defined here.
# Use values from "CI / CD Settings" - "Variables".
# more attempts for more robust
GET_SOURCES_ATTEMPTS: "10"
ARTIFACT_DOWNLOAD_ATTEMPTS: "10"
# GIT_STRATEGY is not defined here.
# Use an option from "CI / CD Settings" - "General pipelines".
# IDF environment
# 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
SUBMODULE_FETCH_TOOL: "tools/ci/ci_fetch_submodule.py"
# by default we will fetch all submodules
# jobs can overwrite this variable to only fetch submodules they required
# set to "none" if don't need to fetch submodules
SUBMODULES_TO_FETCH: "all"
# tell build system do not check submodule update as we download archive instead of clone
IDF_SKIP_CHECK_SUBMODULES: 1
UNIT_TEST_BUILD_SYSTEM: cmake
IDF_PATH: "$CI_PROJECT_DIR"
BATCH_BUILD: "1"
V: "0"
APPLY_BOT_FILTER_SCRIPT: "$CI_PROJECT_DIR/tools/ci/apply_bot_filter.py"
CHECKOUT_REF_SCRIPT: "$CI_PROJECT_DIR/tools/ci/checkout_project_ref.py"
# Docker images
BOT_DOCKER_IMAGE_TAG: ":latest"
# target test config file, used by assign test job
CI_TARGET_TEST_CONFIG_FILE: "$CI_PROJECT_DIR/tools/ci/config/target-test.yml"
# target test repo parameters
TEST_ENV_CONFIG_REPO: "https://gitlab-ci-token:${BOT_TOKEN}@${CI_SERVER_HOST}:${CI_SERVER_PORT}/qa/ci-test-runner-configs.git"
CI_AUTO_TEST_SCRIPT_REPO_URL: "https://gitlab-ci-token:${BOT_TOKEN}@${CI_SERVER_HOST}:${CI_SERVER_PORT}/qa/auto_test_script.git"
CI_AUTO_TEST_SCRIPT_REPO_BRANCH: "ci/v3.1"
# Versioned esp-idf-doc env image to use for all document building jobs
ESP_IDF_DOC_ENV_IMAGE: "$CI_DOCKER_REGISTRY/esp-idf-doc-env:v7"
# before each job, we need to check if this job is filtered by bot stage/job filter
.apply_bot_filter: &apply_bot_filter
python $APPLY_BOT_FILTER_SCRIPT || exit 0
.setup_tools_unless_target_test: &setup_tools_unless_target_test |
if [ "$CI_JOB_STAGE" != "target_test" ]; then
tools/idf_tools.py --non-interactive install && eval "$(tools/idf_tools.py --non-interactive export)" || exit 1
fi
.fetch_submodules: &fetch_submodules |
python $SUBMODULE_FETCH_TOOL -s $SUBMODULES_TO_FETCH
before_script:
- source tools/ci/setup_python.sh
# apply bot filter in before script
- *apply_bot_filter
# add gitlab ssh key
- mkdir -p ~/.ssh
- chmod 700 ~/.ssh
@@ -88,58 +30,649 @@ before_script:
- base64 --decode --ignore-garbage ~/.ssh/id_rsa_base64 > ~/.ssh/id_rsa
- chmod 600 ~/.ssh/id_rsa
- echo -e "Host gitlab.espressif.cn\n\tStrictHostKeyChecking no\n" >> ~/.ssh/config
# Set some options and environment for CI
- source tools/ci/configure_ci_environment.sh
- *setup_tools_unless_target_test
- *fetch_submodules
# Set IS_PRIVATE or IS_PUBLIC depending on if our branch is public or not
#
# (the same regular expressions are used to set these are used in 'only:' sections below
- source make/configure_ci_environment.sh
# used for check scripts which we want to run unconditionally
.before_script_lesser_nofilter:
# fetch all submodules
- git submodule update --init --recursive
build_template_app:
stage: build
image: $CI_DOCKER_REGISTRY/esp32-ci-env
tags:
- build
variables:
GIT_SUBMODULE_STRATEGY: none
before_script:
- echo "Not setting up GitLab key, not fetching submodules, not applying bot filter"
- source tools/ci/setup_python.sh
- source tools/ci/configure_ci_environment.sh
GIT_STRATEGY: clone
BATCH_BUILD: "1"
IDF_CI_BUILD: "1"
script:
- git clone https://github.com/espressif/esp-idf-template.git
- cd esp-idf-template
# Try to use the same branch name for esp-idf-template that we're
# using on esp-idf. If it doesn't exist then just stick to the default
# branch
- git checkout ${CI_COMMIT_REF_NAME} || echo "Using esp-idf-template default branch..."
# Test debug build (default)
- make all V=1
# Now test release build
- make clean
- sed -i.bak -e's/CONFIG_OPTIMIZATION_LEVEL_DEBUG\=y/CONFIG_OPTIMIZATION_LEVEL_RELEASE=y/' sdkconfig
- make all V=1
# Check if there are any stray printf/ets_printf references in WiFi libs
- cd ../components/esp32/lib
- test $(xtensa-esp32-elf-nm *.a | grep -w printf | wc -l) -eq 0
- test $(xtensa-esp32-elf-nm *.a | grep -w ets_printf | wc -l) -eq 0
# used for everything else where we want to do no prep, except for bot filter
.before_script_lesser:
.build_template: &build_template
stage: build
image: $CI_DOCKER_REGISTRY/esp32-ci-env
tags:
- build
variables:
GIT_SUBMODULE_STRATEGY: none
GIT_STRATEGY: clone
BATCH_BUILD: "1"
V: "0"
build_ssc:
<<: *build_template
artifacts:
paths:
- SSC/ssc_bin
expire_in: 6 mos
script:
- git clone $SSC_REPOSITORY
- cd SSC
- git checkout ${CI_COMMIT_REF_NAME} || echo "Using SSC default branch..."
- MAKEFLAGS= ./gen_misc_ng.sh
build_at:
<<: *build_template
script:
- git clone $GITLAB_SSH_SERVER/application/esp-at.git
- cd esp-at
- git checkout ${CI_COMMIT_REF_NAME} || echo "Using esp-at default branch..."
- make defconfig
- make
build_esp_idf_tests:
<<: *build_template
artifacts:
paths:
- tools/unit-test-app/build/*.bin
- tools/unit-test-app/build/*.elf
- tools/unit-test-app/build/*.map
- tools/unit-test-app/build/download.config
- tools/unit-test-app/build/bootloader/*.bin
- components/idf_test/unit_test/TestCaseAll.yml
- components/idf_test/unit_test/CIConfigs/*.yml
expire_in: 6 mos
script:
- cd tools/unit-test-app
- make TESTS_ALL=1
# cut last line in case make V=0/1 is set by default
- make print_flash_cmd | tail -n 1 > build/download.config
- python tools/UnitTestParser.py
.build_examples_template: &build_examples_template
<<: *build_template
artifacts:
paths:
- build_examples/*/*/*/build/*.bin
- build_examples/*/*/*/build/*.elf
- build_examples/*/*/*/build/*.map
- build_examples/*/*/*/build/bootloader/*.bin
expire_in: 1 week
variables:
IDF_CI_BUILD: "1"
GIT_STRATEGY: fetch
script:
# it's not possible to build 100% out-of-tree and have the "artifacts"
# mechanism work, but this is the next best thing
- mkdir build_examples
- cd build_examples
# build some of examples
- ${IDF_PATH}/make/build_examples.sh "${CI_JOB_NAME}"
build_examples_00:
<<: *build_examples_template
build_examples_01:
<<: *build_examples_template
build_examples_02:
<<: *build_examples_template
build_examples_03:
<<: *build_examples_template
build_examples_04:
<<: *build_examples_template
build_docs:
stage: build
image: $CI_DOCKER_REGISTRY/esp32-ci-env
tags:
- build_docs
artifacts:
paths:
- docs/_build/html
expire_in: 1 mos
script:
- cd docs
- doxygen
# If not building master branch, and there are Doxygen warnings, print them and bail out
- test -n $IS_PRIVATE && test $(cat doxygen-warning-log.txt | wc -l) -eq 0 || ( echo "Doxygen pass had some warnings:" && cat doxygen-warning-log.txt && false )
- make gh-linkcheck
- make html
test_nvs_on_host:
stage: test
image: $CI_DOCKER_REGISTRY/esp32-ci-env
tags:
- nvs_host_test
dependencies: []
script:
- cd components/nvs_flash/test_nvs_host
- make test
test_partition_table_on_host:
stage: test
image: $CI_DOCKER_REGISTRY/esp32-ci-env
tags:
- build
dependencies: []
script:
- cd components/partition_table/test_gen_esp32part_host
- ./gen_esp32part_tests.py
test_wl_on_host:
stage: test
image: $CI_DOCKER_REGISTRY/esp32-ci-env
tags:
- wl_host_test
artifacts:
paths:
- components/wear_levelling/test_wl_host/coverage_report.zip
dependencies: []
script:
- cd components/wear_levelling/test_wl_host
- make test
test_build_system:
stage: test
image: $CI_DOCKER_REGISTRY/esp32-ci-env
tags:
- build_test
dependencies: []
script:
- ./make/test_configure_ci_environment.sh
- ./make/test_build_system.sh
test_report:
stage: test_report
image: $CI_DOCKER_REGISTRY/esp32-ci-env
tags:
- report
only:
- master
- triggers
- /^release\/v/
- /^v\d+\.\d+(\.\d+)?($|-)/
variables:
LOG_PATH: "$CI_PROJECT_DIR/$CI_COMMIT_SHA"
TEST_CASE_FILE_PATH: "$CI_PROJECT_DIR/components/idf_test"
REPORT_PATH: "$CI_PROJECT_DIR/CI_Test_Report"
MODULE_UPDATE_FILE: "$CI_PROJECT_DIR/tools/unit-test-app/tools/ModuleDefinition.yml"
#dependencies:
#We need all UT* and IT* artifacts except for only a few other
artifacts:
when: always
paths:
- $REPORT_PATH
- $LOG_PATH
expire_in: 12 mos
script:
# calc log path
- VER_NUM=`git rev-list HEAD | wc -l | awk '{print $1}'`
- SHA_ID=`echo $CI_COMMIT_SHA | cut -c 1-7`
- REVISION="${VER_NUM}_${SHA_ID}"
# replace / to _ in branch name
- ESCAPED_BRANCH_NAME=`echo $CI_COMMIT_REF_NAME | sed 's/\//___/g'`
# result path and artifacts path
- RESULT_PATH="$CI_PROJECT_NAME/$ESCAPED_BRANCH_NAME/$REVISION"
- ARTIFACTS_PATH="$GITLAB_HTTP_SERVER/idf/esp-idf/builds/$CI_JOB_ID/artifacts/browse/$CI_COMMIT_SHA"
# clone test bench
- git clone $GITLAB_SSH_SERVER/yinling/auto_test_script.git
- cd auto_test_script
# generate report
- TEST_RESULT=Pass
- python CITestReport.py -l $LOG_PATH -t $TEST_CASE_FILE_PATH -p $REPORT_PATH -r $RESULT_PATH -a $ARTIFACTS_PATH -m $MODULE_UPDATE_FILE || TEST_RESULT=Fail
# commit to CI-test-result project
- git clone $GITLAB_SSH_SERVER/qa/CI-test-result.git
- rm -rf "CI-test-result/RawData/$RESULT_PATH"
- cp -R $CI_PROJECT_NAME CI-test-result/RawData
- cd CI-test-result
# config git user
- git config --global user.email "ci-test-result@espressif.com"
- git config --global user.name "ci-test-result"
# commit test result
- git add .
- git commit . -m "update test result for $CI_PROJECT_NAME/$CI_COMMIT_REF_NAME/$CI_COMMIT_SHA, pipeline ID $CI_PIPELINE_ID" || exit 0
- git push origin master
- test "${TEST_RESULT}" = "Pass" || exit 1
push_master_to_github:
before_script:
- echo "Not setting up GitLab key, not fetching submodules"
- source tools/ci/setup_python.sh
# apply bot filter in before script
- *apply_bot_filter
- source tools/ci/configure_ci_environment.sh
.check_job_template:
stage: check
image: $CI_DOCKER_REGISTRY/esp32-ci-env$BOT_DOCKER_IMAGE_TAG
stage: deploy
image: $CI_DOCKER_REGISTRY/esp32-ci-env
tags:
- host_test
- deploy
only:
- master
- /^release\/v/
- /^v\d+\.\d+(\.\d+)?($|-)/
when: on_success
dependencies: []
extends: .before_script_lesser_nofilter
variables:
GIT_STRATEGY: clone
GITHUB_PUSH_REFS: refs/remotes/origin/release refs/remotes/origin/master
script:
- mkdir -p ~/.ssh
- chmod 700 ~/.ssh
- echo -n $GH_PUSH_KEY > ~/.ssh/id_rsa_base64
- base64 --decode --ignore-garbage ~/.ssh/id_rsa_base64 > ~/.ssh/id_rsa
- chmod 600 ~/.ssh/id_rsa
- echo -e "Host github.com\n\tStrictHostKeyChecking no\n" >> ~/.ssh/config
- git remote add github git@github.com:espressif/esp-idf.git
# What the next line of script does: goes through the list of refs for all branches we push to github,
# generates a snippet of shell which is evaluated. The snippet checks CI_COMMIT_SHA against the SHA
# (aka objectname) at tip of each branch, and if any SHAs match then it checks out the local branch
# and then pushes that ref to a corresponding github branch
- eval $(git for-each-ref --shell bash --format 'if [ $CI_COMMIT_SHA == %(objectname) ]; then git checkout -B %(refname:strip=3); git push --follow-tags github %(refname:strip=3); fi;' $GITHUB_PUSH_REFS)
.check_job_template_with_filter:
stage: check
image: $CI_DOCKER_REGISTRY/esp32-ci-env$BOT_DOCKER_IMAGE_TAG
deploy_docs:
before_script:
- echo "Not setting up GitLab key, not fetching submodules"
stage: deploy
image: $CI_DOCKER_REGISTRY/esp32-ci-env
tags:
- host_test
- deploy
only:
- master
- /^release\/v/
- /^v\d+\.\d+(\.\d+)?($|-)/
- triggers
dependencies:
- build_docs
script:
- mkdir -p ~/.ssh
- chmod 700 ~/.ssh
- echo -n $DOCS_DEPLOY_KEY > ~/.ssh/id_rsa_base64
- base64 --decode --ignore-garbage ~/.ssh/id_rsa_base64 > ~/.ssh/id_rsa
- chmod 600 ~/.ssh/id_rsa
- echo -e "Host $DOCS_SERVER\n\tStrictHostKeyChecking no\n\tUser $DOCS_SERVER_USER\n" >> ~/.ssh/config
- export GIT_VER=$(git describe --always)
- cd docs/_build/
- mv html $GIT_VER
- tar czvf $GIT_VER.tar.gz $GIT_VER
- scp $GIT_VER.tar.gz $DOCS_SERVER:$DOCS_PATH
- ssh $DOCS_SERVER -x "cd $DOCS_PATH && tar xzvf $GIT_VER.tar.gz && rm -f latest && ln -s $GIT_VER latest"
check_doc_links:
stage: test
image: $CI_DOCKER_REGISTRY/esp32-ci-env
tags:
- check_doc_links
only:
# can only be triggered
- triggers
artifacts:
paths:
- docs/_build/linkcheck
expire_in: 1 mos
script:
# must be triggered with CHECK_LINKS=Yes, otherwise exit without test
- test "$CHECK_LINKS" = "Yes" || exit 0
# can only run on master branch (otherwise the commit is not on Github yet)
- test "${CI_COMMIT_REF_NAME}" = "master" || exit 0
- cd docs
- make linkcheck
check_commit_msg:
stage: deploy
image: $CI_DOCKER_REGISTRY/esp32-ci-env
tags:
- build
except:
- master
- /^release\/v/
- /^v\d+\.\d+(\.\d+)?($|-)/
dependencies: []
extends: .before_script_lesser_nofilter
before_script:
- echo "skip update submodule"
script:
- git checkout ${CI_COMMIT_REF_NAME}
# commit start with "WIP: " need to be squashed before merge
- 'git log --pretty=%s master..${CI_COMMIT_REF_NAME} | grep "^WIP: " || exit 0 && exit 1'
default:
retry:
max: 2
# In case of a runner failure we could hop to another one, or a network error could go away.
when: runner_system_failure
check_submodule_sync:
stage: deploy
image: $CI_DOCKER_REGISTRY/esp32-ci-env
tags:
- build
except:
- master
- /^release\/v/
- /^v\d+\.\d+(\.\d+)?($|-)/
dependencies: []
before_script:
- echo "do not use gitlab submodule repository"
script:
# check if all submodules are correctly synced to public repostory
- git submodule update --init --recursive
include:
- '/tools/ci/config/build.yml'
- '/tools/ci/config/assign-test.yml'
- '/tools/ci/config/host-test.yml'
- '/tools/ci/config/target-test.yml'
- '/tools/ci/config/check.yml'
- '/tools/ci/config/deploy.yml'
assign_test:
<<: *build_template
stage: assign_test
dependencies:
- build_esp_idf_tests
- build_ssc
artifacts:
paths:
- test_bins
- components/idf_test/*/CIConfigs
- components/idf_test/*/TC.sqlite
expire_in: 1 mos
script:
# first move test bins together: test_bins/CHIP_SDK/TestApp/bin_files
- mkdir -p test_bins/ESP32_IDF/UT
- cp -r tools/unit-test-app/build/* test_bins/ESP32_IDF/UT
- cp -r SSC/ssc_bin/* test_bins/ESP32_IDF
# clone test script to assign tests
- git clone $TEST_SCRIPT_REPOSITORY
- cd auto_test_script
- git checkout ${CI_COMMIT_REF_NAME} || echo "Using default branch..."
# assign unit test cases
- python CIAssignTestCases.py -t $IDF_PATH/components/idf_test/unit_test -c $IDF_PATH/.gitlab-ci.yml -b $IDF_PATH/test_bins
# assgin integration test cases
- python CIAssignTestCases.py -t $IDF_PATH/components/idf_test/integration_test -c $IDF_PATH/.gitlab-ci.yml -b $IDF_PATH/test_bins
.test_template: &test_template
before_script:
- echo "Skip cloning submodule here"
stage: test
when: on_success
only:
- master
- /^release\/v/
- /^v\d+\.\d+(\.\d+)?($|-)/
- triggers
allow_failure: true
dependencies:
- assign_test
artifacts:
when: always
paths:
- $LOG_PATH
expire_in: 6 mos
variables:
# set git strategy to fetch so we can get esptool without update submodule
GIT_STRATEGY: fetch
LOCAL_ENV_CONFIG_PATH: "$CI_PROJECT_DIR/ci-test-runner-configs/$CI_RUNNER_DESCRIPTION/ESP32_IDF"
LOG_PATH: "$CI_PROJECT_DIR/$CI_COMMIT_SHA"
TEST_CASE_FILE_PATH: "$CI_PROJECT_DIR/components/idf_test/integration_test"
MODULE_UPDATE_FILE: "$CI_PROJECT_DIR/components/idf_test/ModuleDefinition.yml"
CONFIG_FILE: "$CI_PROJECT_DIR/components/idf_test/integration_test/CIConfigs/$CI_JOB_NAME.yml"
script:
# first test if config file exists, if not exist, exit 0
- test -e $CONFIG_FILE || exit 0
# remove artifacts from the 'unit_test' stage
- rm -rf "$LOG_PATH"
# add gitlab ssh key
- mkdir -p ~/.ssh
- chmod 700 ~/.ssh
- echo -n $GITLAB_KEY > ~/.ssh/id_rsa_base64
- base64 --decode --ignore-garbage ~/.ssh/id_rsa_base64 > ~/.ssh/id_rsa
- chmod 600 ~/.ssh/id_rsa
- echo -e "Host gitlab.espressif.cn\n\tStrictHostKeyChecking no\n" >> ~/.ssh/config
# clone local test env configs
- git clone $TEST_ENV_CONFIG_REPOSITORY
# clone test bench
- git clone $TEST_SCRIPT_REPOSITORY
- cd auto_test_script
- git checkout ${CI_COMMIT_REF_NAME} || echo "Using default branch..."
# run test
- python CIRunner.py -l "$LOG_PATH/$CI_JOB_NAME" -c $CONFIG_FILE -e $LOCAL_ENV_CONFIG_PATH -t $TEST_CASE_FILE_PATH -m $MODULE_UPDATE_FILE
# template for unit test jobs
.unit_test_template: &unit_test_template
<<: *test_template
allow_failure: false
stage: unit_test
variables:
GIT_STRATEGY: fetch
LOCAL_ENV_CONFIG_PATH: "$CI_PROJECT_DIR/ci-test-runner-configs/$CI_RUNNER_DESCRIPTION/ESP32_IDF"
LOG_PATH: "$CI_PROJECT_DIR/$CI_COMMIT_SHA"
TEST_CASE_FILE_PATH: "$CI_PROJECT_DIR/components/idf_test/unit_test"
MODULE_UPDATE_FILE: "$CI_PROJECT_DIR/components/idf_test/ModuleDefinition.yml"
CONFIG_FILE: "$CI_PROJECT_DIR/components/idf_test/unit_test/CIConfigs/$CI_JOB_NAME.yml"
nvs_compatible_test:
<<: *test_template
artifacts:
when: always
paths:
- $LOG_PATH
- nvs_wifi.bin
expire_in: 6 mos
tags:
- ESP32_IDF
- NVS_Compatible
script:
# remove artifacts from the 'unit_test' stage
- rm -rf "$LOG_PATH"
# add gitlab ssh key
- mkdir -p ~/.ssh
- chmod 700 ~/.ssh
- echo -n $GITLAB_KEY > ~/.ssh/id_rsa_base64
- base64 --decode --ignore-garbage ~/.ssh/id_rsa_base64 > ~/.ssh/id_rsa
- chmod 600 ~/.ssh/id_rsa
- echo -e "Host gitlab.espressif.cn\n\tStrictHostKeyChecking no\n" >> ~/.ssh/config
# clone local test env configs
- git clone $TEST_ENV_CONFIG_REPOSITORY
# clone test bench
- git clone $TEST_SCRIPT_REPOSITORY
- cd auto_test_script
- git checkout ${CI_COMMIT_REF_NAME} || echo "Using default branch..."
# prepare nvs bins
- ./Tools/prepare_nvs_bin.sh
# run test
- python CIRunner.py -l "$LOG_PATH/$CI_JOB_NAME" -c $CONFIG_FILE -e $LOCAL_ENV_CONFIG_PATH -t $TEST_CASE_FILE_PATH -m $MODULE_UPDATE_FILE
UT_001_01:
<<: *unit_test_template
tags:
- ESP32_IDF
- UT_T1_1
UT_001_02:
<<: *unit_test_template
tags:
- ESP32_IDF
- UT_T1_1
UT_001_03:
<<: *unit_test_template
tags:
- ESP32_IDF
- UT_T1_1
UT_001_04:
<<: *unit_test_template
tags:
- ESP32_IDF
- UT_T1_1
IT_001_01:
<<: *test_template
tags:
- ESP32_IDF
- SSC_T1_1
IT_001_02:
<<: *test_template
tags:
- ESP32_IDF
- SSC_T1_1
IT_001_03:
<<: *test_template
tags:
- ESP32_IDF
- SSC_T1_1
IT_001_04:
<<: *test_template
tags:
- ESP32_IDF
- SSC_T1_1
IT_001_05:
<<: *test_template
tags:
- ESP32_IDF
- SSC_T1_1
IT_001_06:
<<: *test_template
tags:
- ESP32_IDF
- SSC_T1_1
IT_001_07:
<<: *test_template
tags:
- ESP32_IDF
- SSC_T1_1
IT_001_08:
<<: *test_template
tags:
- ESP32_IDF
- SSC_T1_1
IT_002_01:
<<: *test_template
tags:
- ESP32_IDF
- SSC_T1_2
IT_003_01:
<<: *test_template
tags:
- ESP32_IDF
- SSC_T2_1
IT_003_02:
<<: *test_template
tags:
- ESP32_IDF
- SSC_T2_1
IT_003_03:
<<: *test_template
tags:
- ESP32_IDF
- SSC_T2_1
IT_004_01:
<<: *test_template
tags:
- ESP32_IDF
- SSC_T1_APC
IT_005_01:
<<: *test_template
tags:
- ESP32_IDF
- SSC_T1_WEP
IT_006_01:
<<: *test_template
tags:
- ESP32_IDF
- SSC_T3_PhyMode
IT_007_01:
<<: *test_template
tags:
- ESP32_IDF
- SSC_T2_PhyMode
IT_008_01:
<<: *test_template
tags:
- ESP32_IDF
- SSC_T2_PhyMode
IT_501_01:
<<: *test_template
tags:
- ESP32_IDF
- SSC_T1_1
- stress_test
IT_501_02:
<<: *test_template
tags:
- ESP32_IDF
- SSC_T1_1
- stress_test
IT_501_03:
<<: *test_template
tags:
- ESP32_IDF
- SSC_T1_1
- stress_test
IT_502_01:
<<: *test_template
tags:
- ESP32_IDF
- SSC_T2_1
- stress_test
IT_502_02:
<<: *test_template
tags:
- ESP32_IDF
- SSC_T2_1
- stress_test
IT_503_01:
<<: *test_template
tags:
- ESP32_IDF
- SSC_T5_1
- stress_test
IT_503_02:
<<: *test_template
tags:
- ESP32_IDF
- SSC_T5_1
- stress_test
IT_503_03:
<<: *test_template
tags:
- ESP32_IDF
- SSC_T5_1
- stress_test

View File

@@ -1,6 +0,0 @@
# For the syntax of this file, see:
#
# https://docs.gitlab.com/ee/user/project/code_owners.html#the-syntax-of-code-owners-files
#
* @esp-idf-codeowners/all-maintainers

79
.gitmodules vendored
View File

@@ -1,76 +1,31 @@
#
# All the relative URL paths are intended to be GitHub ones
# For Espressif's public projects please use '../../espressif/proj', not a '../proj'
#
[submodule "components/esp32/lib"]
path = components/esp32/lib
url = https://github.com/espressif/esp32-wifi-lib.git
[submodule "components/esptool_py/esptool"]
path = components/esptool_py/esptool
url = ../../espressif/esptool.git
url = https://github.com/espressif/esptool.git
[submodule "components/bt/controller/lib"]
path = components/bt/controller/lib
url = ../../espressif/esp32-bt-lib.git
[submodule "components/bt/lib"]
path = components/bt/lib
url = https://github.com/espressif/esp32-bt-lib.git
[submodule "components/bootloader/subproject/components/micro-ecc/micro-ecc"]
path = components/bootloader/subproject/components/micro-ecc/micro-ecc
url = ../../kmackay/micro-ecc.git
[submodule "components/micro-ecc/micro-ecc"]
path = components/micro-ecc/micro-ecc
url = https://github.com/kmackay/micro-ecc.git
[submodule "components/coap/libcoap"]
path = components/coap/libcoap
url = ../../obgm/libcoap.git
url = https://github.com/obgm/libcoap.git
[submodule "components/aws_iot/aws-iot-device-sdk-embedded-C"]
path = components/aws_iot/aws-iot-device-sdk-embedded-C
url = https://github.com/espressif/aws-iot-device-sdk-embedded-C.git
[submodule "components/nghttp/nghttp2"]
path = components/nghttp/nghttp2
url = ../../nghttp2/nghttp2.git
url = https://github.com/nghttp2/nghttp2.git
[submodule "components/libsodium/libsodium"]
path = components/libsodium/libsodium
url = ../../jedisct1/libsodium.git
[submodule "components/spiffs/spiffs"]
path = components/spiffs/spiffs
url = ../../pellepl/spiffs.git
[submodule "components/json/cJSON"]
path = components/json/cJSON
url = ../../DaveGamble/cJSON.git
[submodule "components/mbedtls/mbedtls"]
path = components/mbedtls/mbedtls
url = ../../espressif/mbedtls.git
[submodule "components/asio/asio"]
path = components/asio/asio
url = ../../espressif/asio.git
[submodule "components/expat/expat"]
path = components/expat/expat
url = ../../libexpat/libexpat.git
[submodule "components/lwip/lwip"]
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
[submodule "components/unity/unity"]
path = components/unity/unity
url = ../../ThrowTheSwitch/Unity.git
[submodule "examples/build_system/cmake/import_lib/main/lib/tinyxml2"]
path = examples/build_system/cmake/import_lib/main/lib/tinyxml2
url = ../../leethomason/tinyxml2.git
[submodule "components/esp_wifi/lib_esp32"]
path = components/esp_wifi/lib_esp32
url = ../../espressif/esp32-wifi-lib.git
[submodule "components/bt/host/nimble/nimble"]
path = components/bt/host/nimble/nimble
url = ../../espressif/esp-nimble.git
url = https://github.com/jedisct1/libsodium.git

View File

@@ -1,21 +0,0 @@
# .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 documenation build by DOxygen
submodules:
include:
- components/mqtt/esp-mqtt

View File

@@ -1,7 +0,0 @@
language: python
sudo: false
python:
- "3.4"
script:
- pip install flake8
- travis_wait 20 python -m flake8 --config=.flake8 .

View File

@@ -1,99 +0,0 @@
cmake_minimum_required(VERSION 3.5)
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.")
endif()
unset(compile_options)
unset(c_compile_options)
unset(cxx_compile_options)
unset(compile_definitions)
unset(link_options)
# Add the following build specifications here, since these seem to be dependent
# on config values on the root Kconfig.
if(CONFIG_COMPILER_OPTIMIZATION_LEVEL_RELEASE)
list(APPEND compile_options "-Os")
list(APPEND compile_options "-freorder-blocks")
else()
list(APPEND compile_options "-Og")
endif()
if(CONFIG_COMPILER_CXX_EXCEPTIONS)
list(APPEND cxx_compile_options "-fexceptions")
else()
list(APPEND cxx_compile_options "-fno-exceptions")
endif()
if(CONFIG_COMPILER_CXX_RTTI)
list(APPEND cxx_compile_options "-frtti")
else()
list(APPEND cxx_compile_options "-fno-rtti")
list(APPEND link_options "-fno-rtti") # used to invoke correct multilib variant (no-rtti) during linking
endif()
if(CONFIG_COMPILER_DISABLE_GCC8_WARNINGS)
list(APPEND compile_options "-Wno-parentheses"
"-Wno-sizeof-pointer-memaccess"
"-Wno-clobbered")
# doesn't use GCC_NOT_5_2_0 because idf_set_global_variables was not called before
if(GCC_NOT_5_2_0)
list(APPEND compile_options "-Wno-format-overflow"
"-Wno-stringop-truncation"
"-Wno-misleading-indentation"
"-Wno-cast-function-type"
"-Wno-implicit-fallthrough"
"-Wno-unused-const-variable"
"-Wno-switch-unreachable"
"-Wno-format-truncation"
"-Wno-memset-elt-size"
"-Wno-int-in-bool-context")
endif()
endif()
if(CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_DISABLE)
list(APPEND compile_definitions "-DNDEBUG")
endif()
if(CONFIG_COMPILER_STACK_CHECK_MODE_NORM)
list(APPEND compile_options "-fstack-protector")
elseif(CONFIG_COMPILER_STACK_CHECK_MODE_STRONG)
list(APPEND compile_options "-fstack-protector-strong")
elseif(CONFIG_COMPILER_STACK_CHECK_MODE_ALL)
list(APPEND compile_options "-fstack-protector-all")
endif()
list(APPEND link_options "-fno-lto")
idf_build_set_property(COMPILE_OPTIONS "${compile_options}" APPEND)
idf_build_set_property(C_COMPILE_OPTIONS "${c_compile_options}" APPEND)
idf_build_set_property(CXX_COMPILE_OPTIONS "${cxx_compile_options}" APPEND)
idf_build_set_property(COMPILE_DEFINITIONS "${compile_definitions}" APPEND)
idf_build_set_property(LINK_OPTIONS "${link_options}" APPEND)
idf_build_get_property(build_component_targets __BUILD_COMPONENT_TARGETS)
# Add each component as a subdirectory, processing each component's CMakeLists.txt
foreach(component_target ${build_component_targets})
__component_get_property(dir ${component_target} COMPONENT_DIR)
__component_get_property(_name ${component_target} COMPONENT_NAME)
__component_get_property(prefix ${component_target} __PREFIX)
__component_get_property(alias ${component_target} COMPONENT_ALIAS)
set(COMPONENT_NAME ${_name})
set(COMPONENT_DIR ${dir})
set(COMPONENT_ALIAS ${alias})
set(COMPONENT_PATH ${dir}) # for backward compatibility only, COMPONENT_DIR is preferred
idf_build_get_property(build_prefix __PREFIX)
set(__idf_component_context 1)
if(NOT prefix STREQUAL build_prefix)
add_subdirectory(${dir} ${prefix}_${_name})
else()
add_subdirectory(${dir} ${_name})
endif()
set(__idf_component_context 0)
endforeach()

View File

@@ -25,8 +25,6 @@ Before sending us a Pull Request, please consider this list of points:
* Are comments and documentation written in clear English, with no spelling or grammar errors?
* Example contributions are also welcome. Please check the :doc:`creating-examples` guide for these.
* If the contribution contains multiple commits, are they grouped together into logical changes (one major change per pull request)? Are any commits with names like "fixed typo" `squashed into previous commits <http://eli.thegreenplace.net/2014/02/19/squashing-github-pull-requests-into-a-single-commit/>`_?
* If you're unsure about any of these points, please open the Pull Request anyhow and then ask us for feedback.
@@ -53,7 +51,5 @@ Related Documents
style-guide
documenting-code
add-ons-reference
creating-examples
../api-reference/template
contributor-agreement
contributor-agreement

277
Kconfig
View File

@@ -4,243 +4,48 @@
#
mainmenu "Espressif IoT Development Framework Configuration"
# Hidden option to support checking for this specific target in C code and Kconfig files
config IDF_TARGET_ESP32
bool
default "y" if IDF_TARGET="esp32"
default "n"
config IDF_CMAKE
bool
option env="IDF_CMAKE"
menu "SDK tool configuration"
config TOOLPREFIX
string "Compiler toolchain path/prefix"
default "xtensa-esp32-elf-"
help
The prefix/path that is used to call the toolchain. The default setting assumes
a crosstool-ng gcc setup that is in your PATH.
config PYTHON
string "Python 2 interpreter"
default "python"
help
The executable name/path that is used to run python. On some systems Python 2.x
may need to be invoked as python2.
endmenu
source "$COMPONENT_KCONFIGS_PROJBUILD"
choice OPTIMIZATION_LEVEL
prompt "Optimization level"
default OPTIMIZATION_LEVEL_DEBUG
help
This option sets optimization level.
- for "Release" setting, -Os flag is added to CFLAGS,
and -DNDEBUG flag is added to CPPFLAGS.
- for "Debug" setting, -Og flag is added to CFLAGS.
To override any of these settings, set CFLAGS and/or CPPFLAGS
in project makefile, before including $(IDF_PATH)/make/project.mk.
config OPTIMIZATION_LEVEL_DEBUG
bool "Debug"
config OPTIMIZATION_LEVEL_RELEASE
bool "Release"
endchoice
menu "Component config"
source "$COMPONENT_KCONFIGS"
endmenu
config IDF_TARGET_ENV
# A proxy to get environment variable $IDF_TARGET
string
option env="IDF_TARGET"
config IDF_TARGET
# This option records the IDF target when sdkconfig is generated the first time.
# It is not updated if environment variable $IDF_TARGET changes later, and
# the build system is responsible for detecting the mismatch between
# CONFIG_IDF_TARGET and $IDF_TARGET.
string
default "IDF_TARGET_NOT_SET" if IDF_TARGET_ENV=""
default IDF_TARGET_ENV
config IDF_FIRMWARE_CHIP_ID
hex
default 0x0000 if IDF_TARGET="esp32"
default 0xFFFF
menu "SDK tool configuration"
config SDK_TOOLPREFIX
string "Compiler toolchain path/prefix"
default "xtensa-esp32-elf-"
help
The prefix/path that is used to call the toolchain. The default setting assumes
a crosstool-ng gcc setup that is in your PATH.
config SDK_PYTHON
string "Python interpreter"
depends on !IDF_CMAKE
default "python"
help
The executable name/path that is used to run python.
(Note: This option is used with the legacy GNU Make build system only.)
config SDK_MAKE_WARN_UNDEFINED_VARIABLES
bool "'make' warns on undefined variables"
depends on !IDF_CMAKE
default "y"
help
Adds --warn-undefined-variables to MAKEFLAGS. This causes make to
print a warning any time an undefined variable is referenced.
This option helps find places where a variable reference is misspelled
or otherwise missing, but it can be unwanted if you have Makefiles which
depend on undefined variables expanding to an empty string.
(Note: this option is used with the legacy GNU Make build system only.)
endmenu # SDK tool configuration
source "$COMPONENT_KCONFIGS_PROJBUILD"
menu "Compiler options"
choice COMPILER_OPTIMIZATION
prompt "Optimization Level"
default COMPILER_OPTIMIZATION_LEVEL_DEBUG
help
This option sets compiler optimization level (gcc -O argument).
- for "Release" setting, -Os flag is added to CFLAGS.
- for "Debug" setting, -Og flag is added to CFLAGS.
"Release" with -Os produces smaller & faster compiled code but it
may be harder to correlated code addresses to source files when debugging.
To add custom optimization settings, set CFLAGS and/or CPPFLAGS
in project makefile, before including $(IDF_PATH)/make/project.mk. Note that
custom optimization levels may be unsupported.
config COMPILER_OPTIMIZATION_LEVEL_DEBUG
bool "Debug (-Og)"
config COMPILER_OPTIMIZATION_LEVEL_RELEASE
bool "Release (-Os)"
endchoice
choice COMPILER_OPTIMIZATION_ASSERTION_LEVEL
prompt "Assertion level"
default COMPILER_OPTIMIZATION_ASSERTIONS_ENABLE
help
Assertions can be:
- Enabled. Failure will print verbose assertion details. This is the default.
- Set to "silent" to save code size (failed assertions will abort() but user
needs to use the aborting address to find the line number with the failed assertion.)
- Disabled entirely (not recommended for most configurations.) -DNDEBUG is added
to CPPFLAGS in this case.
config COMPILER_OPTIMIZATION_ASSERTIONS_ENABLE
prompt "Enabled"
bool
help
Enable assertions. Assertion content and line number will be printed on failure.
config COMPILER_OPTIMIZATION_ASSERTIONS_SILENT
prompt "Silent (saves code size)"
bool
help
Enable silent assertions. Failed assertions will abort(), user needs to
use the aborting address to find the line number with the failed assertion.
config COMPILER_OPTIMIZATION_ASSERTIONS_DISABLE
prompt "Disabled (sets -DNDEBUG)"
bool
help
If assertions are disabled, -DNDEBUG is added to CPPFLAGS.
endchoice # assertions
menuconfig COMPILER_CXX_EXCEPTIONS
bool "Enable C++ exceptions"
default n
help
Enabling this option compiles all IDF C++ files with exception support enabled.
Disabling this option disables C++ exception support in all compiled files, and any libstdc++ code
which throws an exception will abort instead.
Enabling this option currently adds an additional ~500 bytes of heap overhead
when an exception is thrown in user code for the first time.
config COMPILER_CXX_EXCEPTIONS_EMG_POOL_SIZE
int "Emergency Pool Size"
default 0
depends on COMPILER_CXX_EXCEPTIONS
help
Size (in bytes) of the emergency memory pool for C++ exceptions. This pool will be used to allocate
memory for thrown exceptions when there is not enough memory on the heap.
config COMPILER_CXX_RTTI
# Invisible option, until the toolchain with RTTI support is released.
# Use prompt "Enable C++ run-time type info (RTTI)" when updating.
bool
help
Enabling this option compiles all C++ files with RTTI support enabled.
This increases binary size (typically by tens of kB) but allows using
dynamic_cast conversion and typeid operator.
choice COMPILER_STACK_CHECK_MODE
prompt "Stack smashing protection mode"
default COMPILER_STACK_CHECK_MODE_NONE
help
Stack smashing protection mode. Emit extra code to check for buffer overflows, such as stack
smashing attacks. This is done by adding a guard variable to functions with vulnerable objects.
The guards are initialized when a function is entered and then checked when the function exits.
If a guard check fails, program is halted. Protection has the following modes:
- In NORMAL mode (GCC flag: -fstack-protector) only functions that call alloca, and functions with
buffers larger than 8 bytes are protected.
- STRONG mode (GCC flag: -fstack-protector-strong) is like NORMAL, but includes additional functions
to be protected -- those that have local array definitions, or have references to local frame
addresses.
- In OVERALL mode (GCC flag: -fstack-protector-all) all functions are protected.
Modes have the following impact on code performance and coverage:
- performance: NORMAL > STRONG > OVERALL
- coverage: NORMAL < STRONG < OVERALL
config COMPILER_STACK_CHECK_MODE_NONE
bool "None"
config COMPILER_STACK_CHECK_MODE_NORM
bool "Normal"
config COMPILER_STACK_CHECK_MODE_STRONG
bool "Strong"
config COMPILER_STACK_CHECK_MODE_ALL
bool "Overall"
endchoice
config COMPILER_STACK_CHECK
bool
default !COMPILER_STACK_CHECK_MODE_NONE
help
Stack smashing protection.
config COMPILER_WARN_WRITE_STRINGS
bool "Enable -Wwrite-strings warning flag"
default "n"
help
Adds -Wwrite-strings flag for the C/C++ compilers.
For C, this gives string constants the type ``const char[]`` so that
copying the address of one into a non-const ``char *`` pointer
produces a warning. This warning helps to find at compile time code
that tries to write into a string constant.
For C++, this warns about the deprecated conversion from string
literals to ``char *``.
config COMPILER_DISABLE_GCC8_WARNINGS
bool "Disable new warnings introduced in GCC 6 - 8"
default "n"
help
Enable this option if using GCC 6 or newer, and wanting to disable warnings which don't appear with
GCC 5.
endmenu # Compiler Options
menu "Component config"
source "$COMPONENT_KCONFIGS"
endmenu
menu "Compatibility options"
config LEGACY_INCLUDE_COMMON_HEADERS
bool "Include headers accross components as before IDF v4.0"
default n
help
Soc, esp32, and driver components, the most common
components. Some header of these components are included
implicitly by headers of other components before IDF v4.0.
It's not required for high-level components, but still
included through long header chain everywhere.
This is harmful to the modularity. So it's changed in IDF
v4.0.
You can still include these headers in a legacy way until it
is totally deprecated by enable this option.
endmenu #Compatibility options

111
README.md
View File

@@ -1,101 +1,116 @@
# Espressif IoT Development Framework
ESP-IDF is the official development framework for the [ESP32](https://espressif.com/en/products/hardware/esp32/overview) chip provided for Windows, Linux and macOS.
[![alt text](https://readthedocs.org/projects/docs/badge/?version=latest "Documentation Status")](http://esp-idf.readthedocs.io/en/latest/?badge=latest)
# Developing With ESP-IDF
ESP-IDF is the official development framework for the [ESP32](https://espressif.com/en/products/hardware/esp32/overview) chip.
# Developing With the ESP-IDF
## Setting Up ESP-IDF
See setup guides for detailed instructions to set up the ESP-IDF:
* [Getting Started Guide for the stable ESP-IDF version](https://docs.espressif.com/projects/esp-idf/en/stable/get-started/)
* [Getting Started Guide for the latest (master branch) ESP-IDF version](https://docs.espressif.com/projects/esp-idf/en/latest/get-started/)
### Non-GitHub forks
ESP-IDF uses relative locations as its submodules URLs ([.gitmodules](.gitmodules)). So they link to GitHub.
If ESP-IDF is forked to a Git repository which is not on GitHub, you will need to run the script
[tools/set-submodules-to-github.sh](tools/set-submodules-to-github.sh) after git clone.
The script sets absolute URLs for all submodules, allowing `git submodule update --init --recursive` to complete.
If cloning ESP-IDF from GitHub, this step is not needed.
* [Windows Setup Guide](http://esp-idf.readthedocs.io/en/latest/get-started/windows-setup.html)
* [Mac OS Setup Guide](http://esp-idf.readthedocs.io/en/latest/get-started/macos-setup.html)
* [Linux Setup Guide](http://esp-idf.readthedocs.io/en/latest/get-started/linux-setup.html)
## Finding a Project
As well as the [esp-idf-template](https://github.com/espressif/esp-idf-template) project mentioned in Getting Started, ESP-IDF comes with some example projects in the [examples](examples) directory.
As well as the [esp-idf-template](https://github.com/espressif/esp-idf-template) project mentioned in the setup guide, ESP-IDF comes with some example projects in the [examples](examples) directory.
Once you've found the project you want to work with, change to its directory and you can configure and build it.
To start your own project based on an example, copy the example project directory outside of the ESP-IDF directory.
# Quick Reference
See the Getting Started guide links above for a detailed setup guide. This is a quick reference for common commands when working with ESP-IDF projects:
## Setup Build Environment
(See the Getting Started guide listed above for a full list of required steps with more details.)
* Install host build dependencies mentioned in the Getting Started guide.
* Run the install script to set up the build environment. The options include `install.bat` for Windows, and `install.sh` for Unix shells.
* Run the export script on Windows (`export.bat`) or source it on Unix (`source export.sh`) in every shell environment before using ESP-IDF.
## Configuring the Project
`idf.py menuconfig` opens a text-based configuration menu where you can configure the project.
`make menuconfig`
* Opens a text-based configuration menu for the project.
* Use up & down arrow keys to navigate the menu.
* Use Enter key to go into a submenu, Escape key to go out or to exit.
* Type `?` to see a help screen. Enter key exits the help screen.
* Use Space key, or `Y` and `N` keys to enable (Yes) and disable (No) configuration items with checkboxes "`[*]`"
* Pressing `?` while highlighting a configuration item displays help about that item.
* Type `/` to search the configuration items.
Once done configuring, press Escape multiple times to exit and say "Yes" to save the new configuration when prompted.
## Compiling the Project
`idf.py build`
`make all`
... will compile app, bootloader and generate a partition table based on the config.
## Flashing the Project
When the build finishes, it will print a command line to use esptool.py to flash the chip. However you can also do this automatically by running:
When `make all` finishes, it will print a command line to use esptool.py to flash the chip. However you can also do this from make by running:
`idf.py -p PORT flash`
`make flash`
Replace PORT with the name of your serial port (like `COM3` on Windows, `/dev/ttyUSB0` on Linux, or `/dev/cu.usbserial-X` on MacOS. If the `-p` option is left out, `idf.py flash` will try to flash the first available serial port.
This will flash the entire project (app, bootloader and partition table) to a new chip. The settings for serial port flashing can be configured with `make menuconfig`.
This will flash the entire project (app, bootloader and partition table) to a new chip. The settings for serial port flashing can be configured with `idf.py menuconfig`.
You don't need to run `idf.py build` before running `idf.py flash`, `idf.py flash` will automatically rebuild anything which needs it.
You don't need to run `make all` before running `make flash`, `make flash` will automatically rebuild anything which needs it.
## Viewing Serial Output
The `idf.py monitor` target uses the [idf_monitor tool](https://docs.espressif.com/projects/esp-idf/en/latest/get-started/idf-monitor.html) to display serial output from the ESP32. idf_monitor also has a range of features to decode crash output and interact with the device. [Check the documentation page for details](https://docs.espressif.com/projects/esp-idf/en/latest/get-started/idf-monitor.html).
The `make monitor` target uses the [idf_monitor tool](http://esp-idf.readthedocs.io/en/latest/get-started/idf-monitor.html) to display serial output from the ESP32. idf_monitor also has a range of features to decode crash output and interact with the device. [Check the documentation page for details](http://esp-idf.readthedocs.io/en/latest/get-started/idf-monitor.html).
Exit the monitor by typing Ctrl-].
To build, flash and monitor output in one pass, you can run:
To flash and monitor output in one pass, you can run:
`idf.py flash monitor`
`make flash monitor`
## Compiling & Flashing Only the App
## Compiling & Flashing Just the App
After the initial flash, you may just want to build and flash just your app, not the bootloader and partition table:
* `idf.py app` - build just the app.
* `idf.py app-flash` - flash just the app.
* `make app` - build just the app.
* `make app-flash` - flash just the app.
`idf.py app-flash` will automatically rebuild the app if any source files have changed.
`make app-flash` will automatically rebuild the app if it needs it.
(In normal development there's no downside to reflashing the bootloader and partition table each time, if they haven't changed.)
## Parallel Builds
ESP-IDF supports compiling multiple files in parallel, so all of the above commands can be run as `make -jN` where `N` is the number of parallel make processes to run (generally N should be equal to or one more than the number of CPU cores in your system.)
Multiple make functions can be combined into one. For example: to build the app & bootloader using 5 jobs in parallel, then flash everything, and then display serial output from the ESP32 run:
```
make -j5 flash monitor
```
## The Partition Table
Once you've compiled your project, the "build" directory will contain a binary file with a name like "my_app.bin". This is an ESP32 image binary that can be loaded by the bootloader.
A single ESP32's flash can contain multiple apps, as well as many different kinds of data (calibration data, filesystems, parameter storage, etc). For this reason a partition table is flashed to offset 0x8000 in the flash.
Each entry in the partition table has a name (label), type (app, data, or something else), subtype and the offset in flash where the partition is loaded.
The simplest way to use the partition table is to `make menuconfig` and choose one of the simple predefined partition tables:
* "Single factory app, no OTA"
* "Factory app, two OTA definitions"
In both cases the factory app is flashed at offset 0x10000. If you `make partition_table` then it will print a summary of the partition table.
For more details about partition tables and how to create custom variations, view the `docs/partition-tables.rst` file.
## Erasing Flash
The `idf.py flash` target does not erase the entire flash contents. However it is sometimes useful to set the device back to a totally erased state, particularly when making partition table changes or OTA app updates. To erase the entire flash, run `idf.py erase_flash`.
The `make flash` target does not erase the entire flash contents. However it is sometimes useful to set the device back to a totally erased state, particularly when making partition table changes or OTA app updates. To erase the entire flash, run `make erase_flash`.
This can be combined with other targets, ie `idf.py -p PORT erase_flash flash` will erase everything and then re-flash the new app, bootloader and partition table.
This can be combined with other targets, ie `make erase_flash flash` will erase everything and then re-flash the new app, bootloader and partition table.
# Resources
* Documentation for the latest version: https://docs.espressif.com/projects/esp-idf/. This documentation is built from the [docs directory](docs) of this repository.
* Documentation for the latest version: http://esp-idf.readthedocs.io/. This documentation is built from the [docs directory](docs) of this repository.
* The [esp32.com forum](https://esp32.com/) is a place to ask questions and find community resources.
* The [esp32.com forum](http://esp32.com/) is a place to ask questions and find community resources.
* [Check the Issues section on github](https://github.com/espressif/esp-idf/issues) if you find a bug or have a feature request. Please check existing Issues before opening a new one.
* If you're interested in contributing to ESP-IDF, please check the [Contributions Guide](https://docs.espressif.com/projects/esp-idf/en/latest/contribute/index.html).
* If you're interested in contributing to ESP-IDF, please check the [Contributions Guide](http://esp-idf.readthedocs.io/en/latest/contribute/index.html).

View File

@@ -1,66 +0,0 @@
The latest support policy for ESP-IDF can be found at [https://github.com/espressif/esp-idf/blob/master/SUPPORT_POLICY.md](https://github.com/espressif/esp-idf/blob/master/SUPPORT_POLICY.md)
Support Period Policy
=====================
Each ESP-IDF major and minor release (V4.0, V4.1, etc) is supported for
18 months after the initial stable release date.
Supported means that the ESP-IDF team will continue to apply bug fixes,
security fixes, etc to the release branch on GitHub, and periodically
make new bugfix releases as needed.
Users are encouraged to upgrade to a newer ESP-IDF release before the
support period finishes and the release becomes End of Life (EOL). It is
our policy to not continue fixing bugs in End of Life releases.
Pre-release versions (betas, previews, `-rc` and `-dev` versions, etc)
are not covered by any support period. Sometimes a particular feature is
marked as \"Preview\" in a release, which means it is also not covered
by the support period.
The ESP-IDF Programming Guide has information about the
[different versions of ESP-IDF](https://docs.espressif.com/projects/esp-idf/en/latest/versions.html)
(major, minor, bugfix, etc).
Long Term Support releases
--------------------------
Some releases (starting with ESP-IDF V3.3) are designated Long Term
Support (LTS). LTS releases are supported for 30 months (2.5 years)
after the initial stable release date.
A new LTS release will be made at least every 18 months. This means
there will always be a period of at least 12 months to upgrade from the
previous LTS release to the following LTS release.
Example
-------
ESP-IDF V3.3 was released in September 2019 and is a Long Term Support
(LTS) release, meaning it will be supported for 30 months until February
2022.
- The first V3.3 release was `v3.3` in September 2019.
- The ESP-IDF team continues to backport bug fixes, security fixes,
etc to the release branch `release/v3.3`.
- Periodically stable bugfix releases are created from the release
branch. For example `v3.3.1`, `v3.3.2`, etc. Users are encouraged to
always update to the latest bugfix release.
- V3.3 bugfix releases continue until February 2022, when all V3.3.x
releases become End of Life.
Existing Releases
-----------------
ESP-IDF release V3.3 and all newer releases will follow this support
period policy. The support period for each release will be announced
when the release is made.
For releases made before the support period policy was announced,
the following support periods apply:
- ESP-IDF V3.1.x and V3.2.x will both be supported until October 2020.
- ESP-IDF V3.0.9 (planned for October 2019) will be the last V3.0
bugfix release. ESP-IDF V3.0.x is End of Life from October 2019.
- ESP-IDF versions before V3.0 are already End of Life.

View File

@@ -9,11 +9,8 @@
if [ -z ${IDF_PATH} ]; then
echo "IDF_PATH must be set before including this script."
else
IDF_ADD_PATHS_EXTRAS="${IDF_PATH}/components/esptool_py/esptool"
IDF_ADD_PATHS_EXTRAS="${IDF_ADD_PATHS_EXTRAS}:${IDF_PATH}/components/espcoredump"
IDF_ADD_PATHS_EXTRAS="${IDF_ADD_PATHS_EXTRAS}:${IDF_PATH}/components/partition_table/"
IDF_ADD_PATHS_EXTRAS="${IDF_ADD_PATHS_EXTRAS}:${IDF_PATH}/tools/"
export PATH="${IDF_ADD_PATHS_EXTRAS}:${PATH}"
IDF_ADD_PATHS_EXTRAS="${IDF_PATH}/components/esptool_py/esptool:${IDF_PATH}/components/espcoredump:${IDF_PATH}/components/partition_table/"
export PATH="${PATH}:${IDF_ADD_PATHS_EXTRAS}"
echo "Added to PATH: ${IDF_ADD_PATHS_EXTRAS}"
fi

View File

@@ -1,43 +0,0 @@
set(srcs
"app_trace.c"
"app_trace_util.c"
"host_file_io.c"
"gcov/gcov_rtio.c")
set(include_dirs "include")
if(CONFIG_SYSVIEW_ENABLE)
list(APPEND include_dirs
sys_view/Config
sys_view/SEGGER
sys_view/Sample/OS)
list(APPEND srcs
"sys_view/SEGGER/SEGGER_SYSVIEW.c"
"sys_view/Sample/Config/SEGGER_SYSVIEW_Config_FreeRTOS.c"
"sys_view/Sample/OS/SEGGER_SYSVIEW_FreeRTOS.c"
"sys_view/esp32/SEGGER_RTT_esp32.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")
endif()
idf_component_register(SRCS "${srcs}"
INCLUDE_DIRS "${include_dirs}"
PRIV_REQUIRES soc
LDFRAGMENTS linker.lf)
if(CONFIG_ESP32_GCOV_ENABLE)
# 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")
# Force app_trace to also appear later than gcov in link line
idf_component_get_property(app_trace app_trace COMPONENT_LIB)
target_link_libraries(${COMPONENT_LIB} INTERFACE
"-Wl,--undefined=gcov_rtio_atexit" $<TARGET_FILE:${app_trace}> gcov $<TARGET_FILE:${app_trace}> c)
endif()

View File

@@ -1,218 +0,0 @@
menu "Application Level Tracing"
choice ESP32_APPTRACE_DESTINATION
prompt "Data Destination"
default ESP32_APPTRACE_DEST_NONE
help
Select destination for application trace: trace memory or none (to disable).
config ESP32_APPTRACE_DEST_TRAX
bool "Trace memory"
select ESP32_APPTRACE_ENABLE
config ESP32_APPTRACE_DEST_NONE
bool "None"
endchoice
config ESP32_APPTRACE_ENABLE
bool
depends on !ESP32_TRAX
select ESP32_MEMMAP_TRACEMEM
select ESP32_MEMMAP_TRACEMEM_TWOBANKS
default n
help
Enables/disable application tracing module.
config ESP32_APPTRACE_LOCK_ENABLE
bool
default !SYSVIEW_ENABLE
help
Enables/disable application tracing module internal sync lock.
config ESP32_APPTRACE_ONPANIC_HOST_FLUSH_TMO
int "Timeout for flushing last trace data to host on panic"
depends on ESP32_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 ESP32_APPTRACE_POSTMORTEM_FLUSH_THRESH
int "Threshold for flushing last trace data to host on panic"
depends on ESP32_APPTRACE_DEST_TRAX
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 ESP32_APPTRACE_PENDING_DATA_SIZE_MAX
int "Size of the pending data buffer"
depends on ESP32_APPTRACE_DEST_TRAX
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 ESP32_APPTRACE_ENABLE
config SYSVIEW_ENABLE
bool "SystemView Tracing Enable"
depends on ESP32_APPTRACE_ENABLE
default n
help
Enables supporrt for SEGGER SystemView tracing functionality.
choice SYSVIEW_TS_SOURCE
prompt "Timer to use as timestamp source"
depends on SYSVIEW_ENABLE
default SYSVIEW_TS_SOURCE_CCOUNT if FREERTOS_UNICORE && !PM_ENABLE
default SYSVIEW_TS_SOURCE_TIMER_00 if !FREERTOS_UNICORE && !PM_ENABLE
default SYSVIEW_TS_SOURCE_ESP_TIMER if PM_ENABLE
help
SystemView needs to use a hardware timer as the source of timestamps
when tracing. This option selects the timer for it.
config SYSVIEW_TS_SOURCE_CCOUNT
bool "CPU cycle counter (CCOUNT)"
depends on FREERTOS_UNICORE && !PM_ENABLE
config SYSVIEW_TS_SOURCE_TIMER_00
bool "Timer 0, Group 0"
depends on !PM_ENABLE
config SYSVIEW_TS_SOURCE_TIMER_01
bool "Timer 1, Group 0"
depends on !PM_ENABLE
config SYSVIEW_TS_SOURCE_TIMER_10
bool "Timer 0, Group 1"
depends on !PM_ENABLE
config SYSVIEW_TS_SOURCE_TIMER_11
bool "Timer 1, Group 1"
depends on !PM_ENABLE
config SYSVIEW_TS_SOURCE_ESP_TIMER
bool "esp_timer high resolution timer"
endchoice
config SYSVIEW_MAX_TASKS
int "Maximum supported tasks"
depends on SYSVIEW_ENABLE
range 1 64
default 16
help
Configures maximum supported tasks in sysview debug
config SYSVIEW_BUF_WAIT_TMO
int "Trace buffer wait timeout"
depends on SYSVIEW_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 SYSVIEW_EVT_OVERFLOW_ENABLE
bool "Trace Buffer Overflow Event"
depends on SYSVIEW_ENABLE
default y
help
Enables "Trace Buffer Overflow" event.
config SYSVIEW_EVT_ISR_ENTER_ENABLE
bool "ISR Enter Event"
depends on SYSVIEW_ENABLE
default y
help
Enables "ISR Enter" event.
config SYSVIEW_EVT_ISR_EXIT_ENABLE
bool "ISR Exit Event"
depends on SYSVIEW_ENABLE
default y
help
Enables "ISR Exit" event.
config SYSVIEW_EVT_ISR_TO_SCHEDULER_ENABLE
bool "ISR Exit to Scheduler Event"
depends on SYSVIEW_ENABLE
default y
help
Enables "ISR to Scheduler" event.
config SYSVIEW_EVT_TASK_START_EXEC_ENABLE
bool "Task Start Execution Event"
depends on SYSVIEW_ENABLE
default y
help
Enables "Task Start Execution" event.
config SYSVIEW_EVT_TASK_STOP_EXEC_ENABLE
bool "Task Stop Execution Event"
depends on SYSVIEW_ENABLE
default y
help
Enables "Task Stop Execution" event.
config SYSVIEW_EVT_TASK_START_READY_ENABLE
bool "Task Start Ready State Event"
depends on SYSVIEW_ENABLE
default y
help
Enables "Task Start Ready State" event.
config SYSVIEW_EVT_TASK_STOP_READY_ENABLE
bool "Task Stop Ready State Event"
depends on SYSVIEW_ENABLE
default y
help
Enables "Task Stop Ready State" event.
config SYSVIEW_EVT_TASK_CREATE_ENABLE
bool "Task Create Event"
depends on SYSVIEW_ENABLE
default y
help
Enables "Task Create" event.
config SYSVIEW_EVT_TASK_TERMINATE_ENABLE
bool "Task Terminate Event"
depends on SYSVIEW_ENABLE
default y
help
Enables "Task Terminate" event.
config SYSVIEW_EVT_IDLE_ENABLE
bool "System Idle Event"
depends on SYSVIEW_ENABLE
default y
help
Enables "System Idle" event.
config SYSVIEW_EVT_TIMER_ENTER_ENABLE
bool "Timer Enter Event"
depends on SYSVIEW_ENABLE
default y
help
Enables "Timer Enter" event.
config SYSVIEW_EVT_TIMER_EXIT_ENABLE
bool "Timer Exit Event"
depends on SYSVIEW_ENABLE
default y
help
Enables "Timer Exit" event.
endmenu
config ESP32_GCOV_ENABLE
bool "GCOV to Host Enable"
depends on ESP32_DEBUG_STUBS_ENABLE && ESP32_APPTRACE_ENABLE && !SYSVIEW_ENABLE
default y
help
Enables support for GCOV data transfer to host.
endmenu

File diff suppressed because it is too large Load Diff

View File

@@ -1,191 +0,0 @@
// Copyright 2017 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_app_trace_util.h"
#include "esp32/clk.h"
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////// TIMEOUT /////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
#define ESP_APPTRACE_CPUTICKS2US(_t_, _cpu_freq_) ((_t_)/(_cpu_freq_/1000000))
#define ESP_APPTRACE_US2CPUTICKS(_t_, _cpu_freq_) ((_t_)*(_cpu_freq_/1000000))
esp_err_t esp_apptrace_tmo_check(esp_apptrace_tmo_t *tmo)
{
int cpu_freq = esp_clk_cpu_freq();
if (tmo->tmo != ESP_APPTRACE_TMO_INFINITE) {
unsigned cur = portGET_RUN_TIME_COUNTER_VALUE();
if (tmo->start <= cur) {
tmo->elapsed = ESP_APPTRACE_CPUTICKS2US(cur - tmo->start, cpu_freq);
} else {
tmo->elapsed = ESP_APPTRACE_CPUTICKS2US(0xFFFFFFFF - tmo->start + cur, cpu_freq);
}
if (tmo->elapsed >= tmo->tmo) {
return ESP_ERR_TIMEOUT;
}
}
return ESP_OK;
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////// LOCK ////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
esp_err_t esp_apptrace_lock_take(esp_apptrace_lock_t *lock, esp_apptrace_tmo_t *tmo)
{
int res;
while (1) {
// do not overwrite lock->int_state before we actually acquired the mux
unsigned int_state = portENTER_CRITICAL_NESTED();
// FIXME: if mux is busy it is not good idea to loop during the whole tmo with disabled IRQs.
// So we check mux state using zero tmo, restore IRQs and let others tasks/IRQs to run on this CPU
// while we are doing our own tmo check.
#ifdef CONFIG_FREERTOS_PORTMUX_DEBUG
bool success = vPortCPUAcquireMutexTimeout(&lock->mux, 0, __FUNCTION__, __LINE__);
#else
bool success = vPortCPUAcquireMutexTimeout(&lock->mux, 0);
#endif
if (success) {
lock->int_state = int_state;
return ESP_OK;
}
portEXIT_CRITICAL_NESTED(int_state);
// we can be preempted from this place till the next call (above) to portENTER_CRITICAL_NESTED()
res = esp_apptrace_tmo_check(tmo);
if (res != ESP_OK) {
break;
}
}
return res;
}
esp_err_t esp_apptrace_lock_give(esp_apptrace_lock_t *lock)
{
// save lock's irq state value for this CPU
unsigned int_state = lock->int_state;
// after call to the following func we can not be sure that lock->int_state
// is not overwritten by other CPU who has acquired the mux just after we released it. See esp_apptrace_lock_take().
#ifdef CONFIG_FREERTOS_PORTMUX_DEBUG
vPortCPUReleaseMutex(&lock->mux, __FUNCTION__, __LINE__);
#else
vPortCPUReleaseMutex(&lock->mux);
#endif
portEXIT_CRITICAL_NESTED(int_state);
return ESP_OK;
}
///////////////////////////////////////////////////////////////////////////////
////////////////////////////// RING BUFFER ////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
uint8_t *esp_apptrace_rb_produce(esp_apptrace_rb_t *rb, uint32_t size)
{
uint8_t *ptr = rb->data + rb->wr;
// check for avalable space
if (rb->rd <= rb->wr) {
// |?R......W??|
if (rb->wr + size >= rb->size) {
if (rb->rd == 0) {
return NULL; // cannot wrap wr
}
if (rb->wr + size == rb->size) {
rb->wr = 0;
} else {
// check if we can wrap wr earlier to get space for requested size
if (size > rb->rd - 1) {
return NULL; // cannot wrap wr
}
// shrink buffer a bit, full size will be restored at rd wrapping
rb->cur_size = rb->wr;
rb->wr = 0;
ptr = rb->data;
if (rb->rd == rb->cur_size) {
rb->rd = 0;
if (rb->cur_size < rb->size) {
rb->cur_size = rb->size;
}
}
rb->wr += size;
}
} else {
rb->wr += size;
}
} else {
// |?W......R??|
if (size > rb->rd - rb->wr - 1) {
return NULL;
}
rb->wr += size;
}
return ptr;
}
uint8_t *esp_apptrace_rb_consume(esp_apptrace_rb_t *rb, uint32_t size)
{
uint8_t *ptr = rb->data + rb->rd;
if (rb->rd <= rb->wr) {
// |?R......W??|
if (rb->rd + size > rb->wr) {
return NULL;
}
rb->rd += size;
} else {
// |?W......R??|
if (rb->rd + size > rb->cur_size) {
return NULL;
} else if (rb->rd + size == rb->cur_size) {
// restore full size usage
if (rb->cur_size < rb->size) {
rb->cur_size = rb->size;
}
rb->rd = 0;
} else {
rb->rd += size;
}
}
return ptr;
}
uint32_t esp_apptrace_rb_read_size_get(esp_apptrace_rb_t *rb)
{
uint32_t size = 0;
if (rb->rd <= rb->wr) {
// |?R......W??|
size = rb->wr - rb->rd;
} else {
// |?W......R??|
size = rb->cur_size - rb->rd;
}
return size;
}
uint32_t esp_apptrace_rb_write_size_get(esp_apptrace_rb_t *rb)
{
uint32_t size = 0;
if (rb->rd <= rb->wr) {
// |?R......W??|
size = rb->size - rb->wr;
if (size && rb->rd == 0) {
size--;
}
} else {
// |?W......R??|
size = rb->rd - rb->wr - 1;
}
return size;
}

View File

@@ -1,33 +0,0 @@
#
# Component Makefile
#
COMPONENT_SRCDIRS := .
COMPONENT_ADD_INCLUDEDIRS = include
COMPONENT_ADD_LDFLAGS = -lapp_trace
ifdef CONFIG_SYSVIEW_ENABLE
COMPONENT_ADD_INCLUDEDIRS += \
sys_view/Config \
sys_view/SEGGER \
sys_view/Sample/OS
COMPONENT_SRCDIRS += \
gcov \
sys_view/SEGGER \
sys_view/Sample/OS \
sys_view/Sample/Config \
sys_view/esp32 \
sys_view/ext
else
ifdef CONFIG_ESP32_GCOV_ENABLE
# do not produce gcov info for this module, it is used as transport for gcov
CFLAGS := $(subst --coverage,,$(CFLAGS))
COMPONENT_ADD_LDFLAGS += -Wl,--undefined=gcov_rtio_atexit
COMPONENT_SRCDIRS += gcov
endif
endif
COMPONENT_ADD_LDFRAGMENTS += linker.lf

View File

@@ -1,194 +0,0 @@
// Copyright 2017 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// This module implements runtime file I/O API for GCOV.
#include "esp_task_wdt.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "soc/cpu.h"
#include "soc/timer_periph.h"
#include "esp_app_trace.h"
#include "esp_private/dbg_stubs.h"
#if CONFIG_ESP32_GCOV_ENABLE
#define ESP_GCOV_DOWN_BUF_SIZE 4200
#define LOG_LOCAL_LEVEL CONFIG_LOG_DEFAULT_LEVEL
#include "esp_log.h"
const static char *TAG = "esp_gcov_rtio";
#if GCC_NOT_5_2_0
void __gcov_dump(void);
void __gcov_reset(void);
#else
/* The next code for old GCC */
static void (*s_gcov_exit)(void);
/* Root of a program/shared-object state */
struct gcov_root
{
void *list;
unsigned dumped : 1; /* counts have been dumped. */
unsigned run_counted : 1; /* run has been accounted for. */
struct gcov_root *next;
struct gcov_root *prev;
};
/* Per-dynamic-object gcov state. */
extern struct gcov_root __gcov_root;
static void esp_gcov_reset_status(void)
{
__gcov_root.dumped = 0;
__gcov_root.run_counted = 0;
}
#endif
static int esp_dbg_stub_gcov_dump_do(void)
{
int ret = ESP_OK;
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");
return ESP_ERR_NO_MEM;
}
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...");
#if GCC_NOT_5_2_0
__gcov_dump();
// reset dump status to allow incremental data accumulation
__gcov_reset();
#else
ESP_EARLY_LOGV(TAG, "Check for dump handler %p", s_gcov_exit);
if (s_gcov_exit) {
s_gcov_exit();
// reset dump status to allow incremental data accumulation
esp_gcov_reset_status();
}
#endif
ESP_EARLY_LOGV(TAG, "Free apptrace down buf");
free(down_buf);
ESP_EARLY_LOGV(TAG, "Finish file transfer session");
ret = esp_apptrace_fstop(ESP_APPTRACE_DEST_TRAX);
if (ret != ESP_OK) {
ESP_EARLY_LOGE(TAG, "Failed to send files transfer stop cmd (%d)!", ret);
}
return ret;
}
/**
* @brief Triggers gcov info dump.
* 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)
{
#if GCC_NOT_5_2_0
return esp_dbg_stub_gcov_dump_do();
#else
int ret = ESP_OK;
// disable IRQs on this CPU, other CPU is halted by OpenOCD
unsigned irq_state = portENTER_CRITICAL_NESTED();
ret = esp_dbg_stub_gcov_dump_do();
portEXIT_CRITICAL_NESTED(irq_state);
return ret;
#endif
}
void esp_gcov_dump()
{
// disable IRQs on this CPU, other CPU is halted by OpenOCD
unsigned irq_state = portENTER_CRITICAL_NESTED();
#if !CONFIG_FREERTOS_UNICORE
int other_core = xPortGetCoreID() ? 0 : 1;
esp_cpu_stall(other_core);
#endif
while (!esp_apptrace_host_is_connected(ESP_APPTRACE_DEST_TRAX)) {
// to avoid complains that task watchdog got triggered for other tasks
TIMERG0.wdt_wprotect=TIMG_WDT_WKEY_VALUE;
TIMERG0.wdt_feed=1;
TIMERG0.wdt_wprotect=0;
// to avoid reboot on INT_WDT
TIMERG1.wdt_wprotect=TIMG_WDT_WKEY_VALUE;
TIMERG1.wdt_feed=1;
TIMERG1.wdt_wprotect=0;
}
esp_dbg_stub_gcov_dump_do();
#if !CONFIG_FREERTOS_UNICORE
esp_cpu_unstall(other_core);
#endif
portEXIT_CRITICAL_NESTED(irq_state);
}
int gcov_rtio_atexit(void (*function)(void) __attribute__ ((unused)))
{
#if GCC_NOT_5_2_0
ESP_EARLY_LOGV(TAG, "%s", __FUNCTION__);
#else
ESP_EARLY_LOGV(TAG, "%s %p", __FUNCTION__, function);
s_gcov_exit = function;
#endif
esp_dbg_stub_entry_set(ESP_DBG_STUB_ENTRY_GCOV, (uint32_t)&esp_dbg_stub_gcov_entry);
return 0;
}
void *gcov_rtio_fopen(const char *path, const char *mode)
{
ESP_EARLY_LOGV(TAG, "%s '%s' '%s'", __FUNCTION__, path, mode);
return esp_apptrace_fopen(ESP_APPTRACE_DEST_TRAX, path, mode);
}
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;
}
#endif

View File

@@ -1,114 +0,0 @@
// Copyright 2018 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <sdkconfig.h>
#define HEAP_TRACE_SRCFILE /* don't warn on inclusion here */
#include "esp_heap_trace.h"
#undef HEAP_TRACE_SRCFILE
#if CONFIG_SYSVIEW_ENABLE
#include "esp_app_trace.h"
#include "esp_sysview_trace.h"
#endif
#define STACK_DEPTH CONFIG_HEAP_TRACING_STACK_DEPTH
#ifdef CONFIG_HEAP_TRACING_TOHOST
#if !CONFIG_SYSVIEW_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()
{
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_SYSVIEW_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_SYSVIEW_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;
}
void heap_trace_dump(void)
{
return;
}
/* Add a new allocation to the heap trace records */
static IRAM_ATTR void record_allocation(const heap_trace_record_t *record)
{
if (!s_tracing) {
return;
}
#if CONFIG_SYSVIEW_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 IRAM_ATTR void record_free(void *p, void **callers)
{
if (!s_tracing) {
return;
}
#if CONFIG_SYSVIEW_ENABLE
esp_sysview_heap_trace_free(p, callers);
#endif
}
#include "heap_trace.inc"
#endif /*CONFIG_HEAP_TRACING_TOHOST*/

View File

@@ -1,364 +0,0 @@
// Copyright 2017 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Hot It Works
// ************
//
// This module implements host file I/O protocol on top of apptrace module.
// The protocol is enough simple. It sends command with arguments to the host and receives response from it.
// Responses contains return values of respective file I/O API. This value is returned to the caller.
// Commands has the following format:
// * Header. See esp_apptrace_fcmd_hdr_t.
// * Operation arguments. See file operation helper structures below.
#include <string.h>
#include "esp_app_trace.h"
#if CONFIG_ESP32_APPTRACE_ENABLE
#define LOG_LOCAL_LEVEL CONFIG_LOG_DEFAULT_LEVEL
#include "esp_log.h"
const static char *TAG = "esp_host_file_io";
#define ESP_APPTRACE_FILE_CMD_FOPEN 0x0
#define ESP_APPTRACE_FILE_CMD_FCLOSE 0x1
#define ESP_APPTRACE_FILE_CMD_FWRITE 0x2
#define ESP_APPTRACE_FILE_CMD_FREAD 0x3
#define ESP_APPTRACE_FILE_CMD_FSEEK 0x4
#define ESP_APPTRACE_FILE_CMD_FTELL 0x5
#define ESP_APPTRACE_FILE_CMD_STOP 0x6 // indicates that there is no files to transfer
/** File operation header */
typedef struct {
uint8_t cmd; ///< Command ID
} esp_apptrace_fcmd_hdr_t;
/** Helper structure for fopen */
typedef struct {
const char *path;
uint16_t path_len;
const char *mode;
uint16_t mode_len;
} esp_apptrace_fopen_args_t;
/** Helper structure for fclose */
typedef struct {
void *file;
} esp_apptrace_fclose_args_t;
/** Helper structure for fwrite */
typedef struct {
void * buf;
size_t size;
void * file;
} esp_apptrace_fwrite_args_t;
/** Helper structure for fread */
typedef struct {
size_t size;
void * file;
} esp_apptrace_fread_args_t;
/** Helper structure for fseek */
typedef struct {
long offset;
int whence;
void * file;
} esp_apptrace_fseek_args_t;
/** Helper structure for ftell */
typedef struct {
void *file;
} esp_apptrace_ftell_args_t;
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(dest, sizeof(*hdr) + args_len, ESP_APPTRACE_TMO_INFINITE); //TODO: finite tmo
if (ptr == NULL) {
return ESP_ERR_NO_MEM;
}
hdr = (esp_apptrace_fcmd_hdr_t *)ptr;
hdr->cmd = cmd;
if (prep_args) {
prep_args(ptr + sizeof(hdr->cmd), args);
}
// now indicate that this buffer is ready to be sent off to host
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(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;
}
return ESP_OK;
}
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(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;
}
ESP_EARLY_LOGV(TAG, "%s read %d bytes", __FUNCTION__, rd_size);
tot_rd += rd_size;
}
return ESP_OK;
}
static void esp_apptrace_fopen_args_prepare(uint8_t *buf, void *priv)
{
esp_apptrace_fopen_args_t *args = priv;
memcpy(buf, args->path, args->path_len);
memcpy(buf + args->path_len, args->mode, args->mode_len);
}
void *esp_apptrace_fopen(esp_apptrace_dest_t dest, const char *path, const char *mode)
{
esp_apptrace_fopen_args_t cmd_args;
ESP_EARLY_LOGV(TAG, "esp_apptrace_fopen '%s' '%s'", path, mode);
if (path == NULL || mode == NULL) {
return 0;
}
cmd_args.path = path;
cmd_args.path_len = strlen(path) + 1;
cmd_args.mode = mode;
cmd_args.mode_len = strlen(mode) + 1;
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;
}
// now read the answer
void *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;
}
return resp;
}
static void esp_apptrace_fclose_args_prepare(uint8_t *buf, void *priv)
{
esp_apptrace_fclose_args_t *args = priv;
memcpy(buf, &args->file, sizeof(args->file));
}
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(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;
}
// now read the answer
int 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;
}
return resp;
}
static void esp_apptrace_fwrite_args_prepare(uint8_t *buf, void *priv)
{
esp_apptrace_fwrite_args_t *args = priv;
memcpy(buf, &args->file, sizeof(args->file));
memcpy(buf + sizeof(args->file), args->buf, args->size);
}
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);
if (ptr == NULL) {
return 0;
}
cmd_args.buf = (void *)ptr;
cmd_args.size = size * nmemb;
cmd_args.file = stream;
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;
}
// now read the answer
size_t 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;
}
return resp;
}
static void esp_apptrace_fread_args_prepare(uint8_t *buf, void *priv)
{
esp_apptrace_fread_args_t *args = priv;
memcpy(buf, &args->file, sizeof(args->file));
memcpy(buf + sizeof(args->file), &args->size, sizeof(args->size));
}
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);
if (ptr == NULL) {
return 0;
}
cmd_args.size = size * nmemb;
cmd_args.file = stream;
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;
}
// now read the answer
size_t 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;
}
if (resp > 0) {
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;
}
}
return resp;
}
static void esp_apptrace_fseek_args_prepare(uint8_t *buf, void *priv)
{
esp_apptrace_fseek_args_t *args = priv;
memcpy(buf, &args->file, sizeof(args->file));
memcpy(buf + sizeof(args->file), &args->offset, sizeof(args->offset));
memcpy(buf + sizeof(args->file) + sizeof(args->offset), &args->whence, sizeof(args->whence));
}
int esp_apptrace_fseek(esp_apptrace_dest_t dest, void *stream, long offset, int whence)
{
esp_apptrace_fseek_args_t cmd_args;
ESP_EARLY_LOGV(TAG, "esp_apptrace_fseek f %p o 0x%lx w %d", stream, offset, whence);
cmd_args.file = stream;
cmd_args.offset = offset;
cmd_args.whence = whence;
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;
}
// now read the answer
int 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;
}
return resp;
}
static void esp_apptrace_ftell_args_prepare(uint8_t *buf, void *priv)
{
esp_apptrace_ftell_args_t *args = priv;
memcpy(buf, &args->file, sizeof(args->file));
}
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(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;
}
// now read the answer
int 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;
}
return resp;
}
int esp_apptrace_fstop(esp_apptrace_dest_t dest)
{
ESP_EARLY_LOGV(TAG, "%s", __func__);
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);
}
return ret;
}
#endif

View File

@@ -1,265 +0,0 @@
// Copyright 2017 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef ESP_APP_TRACE_H_
#define ESP_APP_TRACE_H_
#include <stdarg.h>
#include "esp_err.h"
#include "esp_app_trace_util.h" // ESP_APPTRACE_TMO_INFINITE
/**
* Application trace data destinations bits.
*/
typedef enum {
ESP_APPTRACE_DEST_TRAX = 0x1, ///< JTAG destination
ESP_APPTRACE_DEST_UART0 = 0x2, ///< UART destination
} 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();
/**
* @brief Configures down buffer.
* @note Needs to be called before initiating any data transfer using esp_apptrace_buffer_get and esp_apptrace_write.
* 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.
*/
void esp_apptrace_down_buffer_config(uint8_t *buf, uint32_t size);
/**
* @brief Allocates buffer for trace data.
* After data in buffer are ready to be sent off 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(esp_apptrace_dest_t dest, uint32_t size, uint32_t tmo);
/**
* @brief Indicates that the data in buffer are ready to be sent off.
* This function is a counterpart of and must be preceeded 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(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(esp_apptrace_dest_t dest, const void *data, uint32_t size, uint32_t tmo);
/**
* @brief vprintf-like function to sent 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(esp_apptrace_dest_t dest, uint32_t tmo, const char *fmt, va_list ap);
/**
* @brief vprintf-like function to sent log messages to host.
*
* @param fmt Address of format string.
* @param ap List of arguments.
*
* @return Number of bytes written.
*/
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(esp_apptrace_dest_t dest, uint32_t tmo);
/**
* @brief Flushes remaining data in trace buffer to host without locking internal data.
* This is special version of esp_apptrace_flush which should be called from panic handler.
*
* @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(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(esp_apptrace_dest_t dest, void *data, uint32_t *size, uint32_t tmo);
/**
* @brief Retrieves incoming data buffer if any.
* After data in buffer are 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(esp_apptrace_dest_t dest, uint32_t *size, uint32_t tmo);
/**
* @brief Indicates that the data in down buffer are processed.
* This function is a counterpart of and must be preceeded 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(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(esp_apptrace_dest_t dest);
/**
* @brief Opens file on host.
* 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(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.
*
* @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(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.
*
* @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(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.
*
* @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(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.
*
* @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(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.
*
* @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(esp_apptrace_dest_t dest, void *stream);
/**
* @brief Indicates to the host that all file operations are completed.
* 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(esp_apptrace_dest_t dest);
/**
* @brief Triggers gcov info dump.
* This function waits for the host to connect to target before dumping data.
*/
void esp_gcov_dump(void);
#endif

View File

@@ -1,167 +0,0 @@
// Copyright 2017 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef ESP_APP_TRACE_UTIL_H_
#define ESP_APP_TRACE_UTIL_H_
#include "freertos/FreeRTOS.h"
#include "esp_err.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 {
uint32_t start; ///< time interval start (in CPU ticks)
uint32_t tmo; ///< timeout value (in us)
uint32_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 indefinetly.
*/
static inline void esp_apptrace_tmo_init(esp_apptrace_tmo_t *tmo, uint32_t user_tmo)
{
tmo->start = portGET_RUN_TIME_COUNTER_VALUE();
tmo->tmo = user_tmo;
tmo->elapsed = 0;
}
/**
* @brief Checks timeout for expiration.
*
* @param tmo Pointer to timeout structure to be initialized.
*
* @return ESP_OK on success, otherwise \see esp_err_t
*/
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 != ESP_APPTRACE_TMO_INFINITE ? (tmo->elapsed - tmo->tmo) : ESP_APPTRACE_TMO_INFINITE;
}
/** Tracing module synchronization lock */
typedef struct {
portMUX_TYPE mux;
unsigned int_state;
} esp_apptrace_lock_t;
/**
* @brief Initializes lock structure.
*
* @param lock Pointer to lock structure to be initialized.
*/
static inline void esp_apptrace_lock_init(esp_apptrace_lock_t *lock)
{
vPortCPUInitializeMutex(&lock->mux);
lock->int_state = 0;
}
/**
* @brief Tries to acquire lock in specified time period.
*
* @param lock Pointer to lock structure.
* @param tmo Pointer to timeout struct.
*
* @return ESP_OK on success, otherwise \see esp_err_t
*/
esp_err_t esp_apptrace_lock_take(esp_apptrace_lock_t *lock, esp_apptrace_tmo_t *tmo);
/**
* @brief Releases lock.
*
* @param lock Pointer to lock structure.
*
* @return ESP_OK on success, otherwise \see esp_err_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.
*
* @param rb Pointer to ring buffer structure to be initialized.
* @param data Pointer to buffer to be used as ring buffer's data storage.
* @param size Size of buffer to be used as ring buffer's data storage.
*/
static inline void esp_apptrace_rb_init(esp_apptrace_rb_t *rb, uint8_t *data, uint32_t size)
{
rb->data = data;
rb->size = rb->cur_size = size;
rb->rd = 0;
rb->wr = 0;
}
/**
* @brief Allocates memory chunk in ring buffer.
*
* @param rb Pointer to ring buffer structure.
* @param size Size of the memory to allocate.
*
* @return Pointer to the allocated memory or NULL in case of failure.
*/
uint8_t *esp_apptrace_rb_produce(esp_apptrace_rb_t *rb, uint32_t size);
/**
* @brief Consumes memory chunk in ring buffer.
*
* @param rb Pointer to ring buffer structure.
* @param size Size of the memory to consume.
*
* @return Pointer to consumed memory chunk or NULL in case of failure.
*/
uint8_t *esp_apptrace_rb_consume(esp_apptrace_rb_t *rb, uint32_t size);
/**
* @brief Gets size of memory which can consumed with single call to esp_apptrace_rb_consume().
*
* @param rb Pointer to ring buffer structure.
*
* @return Size of memory which can consumed.
*
* @note Due to read pointer wrapping returned size can be less then the total size of available data.
*/
uint32_t esp_apptrace_rb_read_size_get(esp_apptrace_rb_t *rb);
/**
* @brief Gets size of memory which can produced with single call to esp_apptrace_rb_produce().
*
* @param rb Pointer to ring buffer structure.
*
* @return Size of memory which can produced.
*
* @note Due to write pointer wrapping returned size can be less then the total size of available data.
*/
uint32_t esp_apptrace_rb_write_size_get(esp_apptrace_rb_t *rb);
#endif //ESP_APP_TRACE_UTIL_H_

View File

@@ -1,80 +0,0 @@
// Copyright 2018 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef ESP_SYSVIEW_TRACE_H_
#define ESP_SYSVIEW_TRACE_H_
#include <stdarg.h>
#include "esp_err.h"
#include "SEGGER_RTT.h" // SEGGER_RTT_ESP32_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_ESP32_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);
#endif //ESP_SYSVIEW_TRACE_H_

View File

@@ -1,19 +0,0 @@
[mapping:app_trace]
archive: libapp_trace.a
entries:
app_trace (noflash)
app_trace_util (noflash)
if SYSVIEW_ENABLE = y:
SEGGER_SYSVIEW (noflash)
SEGGER_RTT_esp32 (noflash)
SEGGER_SYSVIEW_Config_FreeRTOS (noflash)
SEGGER_SYSVIEW_FreeRTOS (noflash)
[mapping:driver]
archive: libdriver.a
entries:
if SYSVIEW_TS_SOURCE_TIMER_00 = y || SYSVIEW_TS_SOURCE_TIMER_01 = y
|| SYSVIEW_TS_SOURCE_TIMER_10 = y || SYSVIEW_TS_SOURCE_TIMER_11 = y:
timer (noflash)
else:
* (default)

View File

@@ -1,23 +0,0 @@
# idf_create_lcov_report
#
# Create coverage report.
function(idf_create_coverage_report report_dir)
set(gcov_tool ${CONFIG_SDK_TOOLPREFIX}gcov)
idf_build_get_property(project_name PROJECT_NAME)
add_custom_target(lcov-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
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)
endfunction()
# idf_clean_coverage_report
#
# Clean coverage report.
function(idf_clean_coverage_report report_dir)
add_custom_target(cov-data-clean
COMMENT "Clean coverage report in: ${report_dir}"
COMMAND ${CMAKE_COMMAND} -E remove_directory ${report_dir})
endfunction()

View File

@@ -1,4 +0,0 @@
# sdkconfig replacement configurations for deprecated options formatted as
# CONFIG_DEPRECATED_OPTION CONFIG_NEW_OPTION
CONFIG_ESP32_APPTRACE_POSTMORTEM_FLUSH_TRAX_THRESH CONFIG_ESP32_APPTRACE_POSTMORTEM_FLUSH_THRESH

View File

@@ -1,102 +0,0 @@
/*********************************************************************
* SEGGER Microcontroller GmbH & Co. KG *
* The Embedded Experts *
**********************************************************************
* *
* (c) 2015 - 2017 SEGGER Microcontroller GmbH & Co. KG *
* *
* 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 RTT protocol and J-Link. *
* *
* Redistribution and use in source and binary forms, with or *
* without modification, are permitted provided that the following *
* conditions are met: *
* *
* o Redistributions of source code must retain the above copyright *
* notice, this list of conditions and the following disclaimer. *
* *
* o Redistributions in binary form must reproduce the above *
* copyright notice, this list of conditions and the following *
* disclaimer in the documentation and/or other materials provided *
* with the distribution. *
* *
* o Neither the name of SEGGER Microcontroller GmbH & Co. KG *
* nor the names of its contributors may be used to endorse or *
* promote products derived from this software without specific *
* prior written permission. *
* *
* 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: V2.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.
---------------------------END-OF-HEADER------------------------------
*/
#ifndef GLOBAL_H // Guard against multiple inclusion
#define GLOBAL_H
#define U8 unsigned char
#define U16 unsigned short
#define U32 unsigned long
#define I8 signed char
#define I16 signed short
#define I32 signed long
#ifdef _WIN32
//
// 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
#endif // Avoid multiple inclusion
/*************************** End of file ****************************/

View File

@@ -1,298 +0,0 @@
/*********************************************************************
* SEGGER Microcontroller GmbH & Co. KG *
* The Embedded Experts *
**********************************************************************
* *
* (c) 2015 - 2017 SEGGER Microcontroller GmbH & Co. KG *
* *
* 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 RTT protocol and J-Link. *
* *
* Redistribution and use in source and binary forms, with or *
* without modification, are permitted provided that the following *
* conditions are met: *
* *
* o Redistributions of source code must retain the above copyright *
* notice, this list of conditions and the following disclaimer. *
* *
* o Redistributions in binary form must reproduce the above *
* copyright notice, this list of conditions and the following *
* disclaimer in the documentation and/or other materials provided *
* with the distribution. *
* *
* o Neither the name of SEGGER Microcontroller GmbH & Co. KG *
* nor the names of its contributors may be used to endorse or *
* promote products derived from this software without specific *
* prior written permission. *
* *
* 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: V2.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: 5626 $
*/
#ifndef SEGGER_RTT_CONF_H
#define SEGGER_RTT_CONF_H
#ifdef __IAR_SYSTEMS_ICC__
#include <intrinsics.h>
#endif
/*********************************************************************
*
* Defines, configurable
*
**********************************************************************
*/
#define SEGGER_RTT_MAX_NUM_UP_BUFFERS (3) // Max. number of up-buffers (T->H) available on this target (Default: 3)
#define SEGGER_RTT_MAX_NUM_DOWN_BUFFERS (3) // Max. number of down-buffers (H->T) available on this target (Default: 3)
#define BUFFER_SIZE_UP (1024) // Size of the buffer for terminal output of target, up to host (Default: 1k)
#define BUFFER_SIZE_DOWN (16) // Size of the buffer for terminal input to target from host (Usually keyboard input) (Default: 16)
#define SEGGER_RTT_PRINTF_BUFFER_SIZE (64u) // Size of buffer for RTT printf to bulk-send chars via RTT (Default: 64)
#define SEGGER_RTT_MODE_DEFAULT SEGGER_RTT_MODE_NO_BLOCK_SKIP // Mode for pre-initialized terminal channel (buffer 0)
//
// 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.
//
#define SEGGER_RTT_MAX_INTERRUPT_PRIORITY (0x20) // Interrupt priority to lock on SEGGER_RTT_LOCK on Cortex-M3/4 (Default: 0x20)
/*********************************************************************
*
* RTT lock configuration for SEGGER Embedded Studio,
* Rowley CrossStudio and GCC
*/
#if (defined __SES_ARM) || (defined __CROSSWORKS_ARM) || (defined __GNUC__)
#ifdef __ARM_ARCH_6M__
#define SEGGER_RTT_LOCK() { \
unsigned int LockState; \
__asm volatile ("mrs %0, primask \n\t" \
"mov r1, $1 \n\t" \
"msr primask, r1 \n\t" \
: "=r" (LockState) \
: \
: "r1" \
);
#define SEGGER_RTT_UNLOCK() __asm volatile ("msr primask, %0 \n\t" \
: \
: "r" (LockState) \
: \
); \
}
#elif (defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__))
#ifndef SEGGER_RTT_MAX_INTERRUPT_PRIORITY
#define SEGGER_RTT_MAX_INTERRUPT_PRIORITY (0x20)
#endif
#define SEGGER_RTT_LOCK() { \
unsigned int LockState; \
__asm volatile ("mrs %0, basepri \n\t" \
"mov r1, %1 \n\t" \
"msr basepri, r1 \n\t" \
: "=r" (LockState) \
: "i"(SEGGER_RTT_MAX_INTERRUPT_PRIORITY) \
: "r1" \
);
#define SEGGER_RTT_UNLOCK() __asm volatile ("msr basepri, %0 \n\t" \
: \
: "r" (LockState) \
: \
); \
}
#elif defined(__ARM_ARCH_7A__)
#define SEGGER_RTT_LOCK() { \
unsigned int 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" (LockState) \
: \
: "r1" \
);
#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" (LockState) \
: "r0", "r1" \
); \
}
#else
#define SEGGER_RTT_LOCK()
#define SEGGER_RTT_UNLOCK()
#endif
#endif
/*********************************************************************
*
* RTT lock configuration for IAR EWARM
*/
#ifdef __ICCARM__
#if (defined (__ARM6M__) && (__CORE__ == __ARM6M__))
#define SEGGER_RTT_LOCK() { \
unsigned int LockState; \
LockState = __get_PRIMASK(); \
__set_PRIMASK(1);
#define SEGGER_RTT_UNLOCK() __set_PRIMASK(LockState); \
}
#elif ((defined (__ARM7EM__) && (__CORE__ == __ARM7EM__)) || (defined (__ARM7M__) && (__CORE__ == __ARM7M__)))
#ifndef SEGGER_RTT_MAX_INTERRUPT_PRIORITY
#define SEGGER_RTT_MAX_INTERRUPT_PRIORITY (0x20)
#endif
#define SEGGER_RTT_LOCK() { \
unsigned int LockState; \
LockState = __get_BASEPRI(); \
__set_BASEPRI(SEGGER_RTT_MAX_INTERRUPT_PRIORITY);
#define SEGGER_RTT_UNLOCK() __set_BASEPRI(LockState); \
}
#endif
#endif
/*********************************************************************
*
* RTT lock configuration for IAR RX
*/
#ifdef __ICCRX__
#define SEGGER_RTT_LOCK() { \
unsigned long LockState; \
LockState = __get_interrupt_state(); \
__disable_interrupt();
#define SEGGER_RTT_UNLOCK() __set_interrupt_state(LockState); \
}
#endif
/*********************************************************************
*
* RTT lock configuration for KEIL ARM
*/
#ifdef __CC_ARM
#if (defined __TARGET_ARCH_6S_M)
#define SEGGER_RTT_LOCK() { \
unsigned int LockState; \
register unsigned char PRIMASK __asm( "primask"); \
LockState = PRIMASK; \
PRIMASK = 1u; \
__schedule_barrier();
#define SEGGER_RTT_UNLOCK() PRIMASK = 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 LockState; \
register unsigned char BASEPRI __asm( "basepri"); \
LockState = BASEPRI; \
BASEPRI = SEGGER_RTT_MAX_INTERRUPT_PRIORITY; \
__schedule_barrier();
#define SEGGER_RTT_UNLOCK() BASEPRI = 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 LockState; \
LockState = __get_PRIMASK(); \
__set_PRIMASK(1);
#define SEGGER_RTT_UNLOCK() __set_PRIMASK(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 LockState; \
LockState = OS_GetBASEPRI(); \
OS_SetBASEPRI(SEGGER_RTT_MAX_INTERRUPT_PRIORITY);
#define SEGGER_RTT_UNLOCK() OS_SetBASEPRI(LockState); \
}
#endif
#endif
/*********************************************************************
*
* RTT lock configuration fallback
*/
#ifndef SEGGER_RTT_LOCK
void SEGGER_SYSVIEW_X_RTT_Lock();
#define SEGGER_RTT_LOCK() SEGGER_SYSVIEW_X_RTT_Lock() // Lock RTT (nestable) (i.e. disable interrupts)
#endif
#ifndef SEGGER_RTT_UNLOCK
void SEGGER_SYSVIEW_X_RTT_Unlock();
#define SEGGER_RTT_UNLOCK() SEGGER_SYSVIEW_X_RTT_Unlock() // Unlock RTT (nestable) (i.e. enable previous interrupt lock state)
#endif
#endif
/*************************** End of file ****************************/

View File

@@ -1,177 +0,0 @@
/*********************************************************************
* SEGGER Microcontroller GmbH & Co. KG *
* The Embedded Experts *
**********************************************************************
* *
* (c) 2015 - 2017 SEGGER Microcontroller GmbH & Co. KG *
* *
* 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 RTT protocol and J-Link. *
* *
* Redistribution and use in source and binary forms, with or *
* without modification, are permitted provided that the following *
* conditions are met: *
* *
* o Redistributions of source code must retain the above copyright *
* notice, this list of conditions and the following disclaimer. *
* *
* o Redistributions in binary form must reproduce the above *
* copyright notice, this list of conditions and the following *
* disclaimer in the documentation and/or other materials provided *
* with the distribution. *
* *
* o Neither the name of SEGGER Microcontroller GmbH & Co. KG *
* nor the names of its contributors may be used to endorse or *
* promote products derived from this software without specific *
* prior written permission. *
* *
* 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: V2.42 *
* *
**********************************************************************
-------------------------- END-OF-HEADER -----------------------------
File : SEGGER_SYSVIEW_Conf.h
Purpose : SEGGER SystemView configuration.
Revision: $Rev: 5927 $
*/
#ifndef SEGGER_SYSVIEW_CONF_H
#define SEGGER_SYSVIEW_CONF_H
/*********************************************************************
*
* Defines, fixed
*
**********************************************************************
*/
//
// Constants for known core configuration
//
#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
#if (defined __SES_ARM) || (defined __CROSSWORKS_ARM) || (defined __GNUC__)
#ifdef __ARM_ARCH_6M__
#define SEGGER_SYSVIEW_CORE SEGGER_SYSVIEW_CORE_CM0
#elif (defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__))
#define SEGGER_SYSVIEW_CORE SEGGER_SYSVIEW_CORE_CM3
#endif
#elif defined(__ICCARM__)
#if (defined (__ARM6M__) && (__CORE__ == __ARM6M__))
#define SEGGER_SYSVIEW_CORE SEGGER_SYSVIEW_CORE_CM0
#elif ((defined (__ARM7M__) && (__CORE__ == __ARM7M__)) || (defined (__ARM7EM__) && (__CORE__ == __ARM7EM__)))
#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
/*********************************************************************
*
* Defines, configurable
*
**********************************************************************
*/
/*********************************************************************
*
* SystemView buffer configuration
*/
#define SEGGER_SYSVIEW_RTT_BUFFER_SIZE 1024 // Number of bytes that SystemView uses for the buffer.
#define SEGGER_SYSVIEW_RTT_CHANNEL 1 // The RTT channel that SystemView will use. 0: Auto selection
#define SEGGER_SYSVIEW_USE_STATIC_BUFFER 1 // Use a static buffer to generate events instead of a buffer on the stack
#define SEGGER_SYSVIEW_POST_MORTEM_MODE 0 // 1: Enable post mortem analysis mode
/*********************************************************************
*
* SystemView timestamp configuration
*/
#if SEGGER_SYSVIEW_CORE == SEGGER_SYSVIEW_CORE_CM3
#define SEGGER_SYSVIEW_GET_TIMESTAMP() (*(U32 *)(0xE0001004)) // Retrieve a system timestamp. Cortex-M cycle counter.
#define SEGGER_SYSVIEW_TIMESTAMP_BITS 32 // Define number of valid bits low-order delivered by clock source
#else
#define SEGGER_SYSVIEW_GET_TIMESTAMP() SEGGER_SYSVIEW_X_GetTimestamp() // Retrieve a system timestamp via user-defined function
#define SEGGER_SYSVIEW_TIMESTAMP_BITS 32 // Define number of valid bits low-order delivered by SEGGER_SYSVIEW_X_GetTimestamp()
#endif
/*********************************************************************
*
* SystemView Id configuration
*/
//TODO: optimise it
#define SEGGER_SYSVIEW_ID_BASE 0x3F400000 // Default value for the lowest Id reported by the application. Can be overridden by the application via SEGGER_SYSVIEW_SetRAMBase(). (i.e. 0x20000000 when all Ids are an address in this RAM)
#define SEGGER_SYSVIEW_ID_SHIFT 0 // Number of bits to shift the Id to save bandwidth. (i.e. 2 when Ids are 4 byte aligned)
/*********************************************************************
*
* SystemView interrupt configuration
*/
#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__)
#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) // 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
unsigned SEGGER_SYSVIEW_X_SysView_Lock();
void SEGGER_SYSVIEW_X_SysView_Unlock(unsigned int_state);
// to be recursive save IRQ status on the stack of the caller
#define SEGGER_SYSVIEW_LOCK() unsigned _SYSVIEW_int_state = SEGGER_SYSVIEW_X_SysView_Lock()
#define SEGGER_SYSVIEW_UNLOCK() SEGGER_SYSVIEW_X_SysView_Unlock(_SYSVIEW_int_state)
#endif // SEGGER_SYSVIEW_CONF_H
/*************************** End of file ****************************/

View File

@@ -1,155 +0,0 @@
/*********************************************************************
* SEGGER Microcontroller GmbH & Co. KG *
* The Embedded Experts *
**********************************************************************
* *
* (c) 2015 - 2017 SEGGER Microcontroller GmbH & Co. KG *
* *
* 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 RTT protocol and J-Link. *
* *
* Redistribution and use in source and binary forms, with or *
* without modification, are permitted provided that the following *
* conditions are met: *
* *
* o Redistributions of source code must retain the above copyright *
* notice, this list of conditions and the following disclaimer. *
* *
* o Redistributions in binary form must reproduce the above *
* copyright notice, this list of conditions and the following *
* disclaimer in the documentation and/or other materials provided *
* with the distribution. *
* *
* o Neither the name of SEGGER Microcontroller GmbH & Co. KG *
* nor the names of its contributors may be used to endorse or *
* promote products derived from this software without specific *
* prior written permission. *
* *
* 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: V2.42 *
* *
**********************************************************************
----------------------------------------------------------------------
File : SEGGER.h
Purpose : Global types etc & general purpose utility functions
---------------------------END-OF-HEADER------------------------------
*/
#ifndef SEGGER_H // Guard against multiple inclusion
#define SEGGER_H
#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
#ifdef _WIN32
//
// Microsoft VC6 and newer.
// Force inlining without cost checking.
//
#define INLINE __forceinline
#else
#if (defined(__ICCARM__) || defined(__CC_ARM) || defined(__GNUC__) || defined(__RX) || defined(__ICCRX__))
//
// Other known compilers.
//
#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))
/*********************************************************************
*
* Types
*
**********************************************************************
*/
typedef struct {
char *pBuffer;
int BufferSize;
int Cnt;
} SEGGER_BUFFER_DESC;
typedef struct {
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 NumBytes); // Optional clean function for cached memory.
void (*pfInvalidate)(void *p, unsigned NumBytes); // Optional invalidate function for cached memory.
} SEGGER_CACHE_CONFIG;
/*********************************************************************
*
* Utility functions
*
**********************************************************************
*/
void SEGGER_ARM_memcpy (void *pDest, const void *pSrc, int NumBytes);
void SEGGER_memcpy (void *pDest, const void *pSrc, int NumBytes);
void SEGGER_memxor (void *pDest, const void *pSrc, unsigned NumBytes);
void SEGGER_StoreChar (SEGGER_BUFFER_DESC *p, char c);
void SEGGER_PrintUnsigned(SEGGER_BUFFER_DESC *pBufferDesc, U32 v, unsigned Base, int NumDigits);
void SEGGER_PrintInt (SEGGER_BUFFER_DESC *pBufferDesc, I32 v, unsigned Base, unsigned NumDigits);
int SEGGER_snprintf (char *pBuffer, int BufferSize, const char *sFormat, ...);
#if defined(__cplusplus)
} /* Make sure we have C-declarations in C++ programs */
#endif
#endif // Avoid multiple inclusion
/*************************** End of file ****************************/

View File

@@ -1,252 +0,0 @@
/*********************************************************************
* SEGGER Microcontroller GmbH & Co. KG *
* The Embedded Experts *
**********************************************************************
* *
* (c) 2015 - 2017 SEGGER Microcontroller GmbH & Co. KG *
* *
* 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 RTT protocol and J-Link. *
* *
* Redistribution and use in source and binary forms, with or *
* without modification, are permitted provided that the following *
* conditions are met: *
* *
* o Redistributions of source code must retain the above copyright *
* notice, this list of conditions and the following disclaimer. *
* *
* o Redistributions in binary form must reproduce the above *
* copyright notice, this list of conditions and the following *
* disclaimer in the documentation and/or other materials provided *
* with the distribution. *
* *
* o Neither the name of SEGGER Microcontroller GmbH & Co. KG *
* nor the names of its contributors may be used to endorse or *
* promote products derived from this software without specific *
* prior written permission. *
* *
* 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: V2.42 *
* *
**********************************************************************
---------------------------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: 5626 $
----------------------------------------------------------------------
*/
#ifndef SEGGER_RTT_H
#define SEGGER_RTT_H
#include "SEGGER_RTT_Conf.h"
/*********************************************************************
*
* Defines, fixed
*
**********************************************************************
*/
/*********************************************************************
*
* 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
} 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
} 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
} 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);
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_WriteString (unsigned BufferIndex, const char* s);
void SEGGER_RTT_WriteWithOverwriteNoLock(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes);
void SEGGER_RTT_ESP32_FlushNoLock (unsigned long min_sz, unsigned long tmo);
void SEGGER_RTT_ESP32_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)
/*********************************************************************
*
* RTT "Terminal" API functions
*
**********************************************************************
*/
int SEGGER_RTT_SetTerminal (char TerminalId);
int SEGGER_RTT_TerminalOut (char TerminalId, const char* s);
/*********************************************************************
*
* RTT printf functions (require SEGGER_RTT_printf.c)
*
**********************************************************************
*/
int SEGGER_RTT_printf(unsigned BufferIndex, const char * sFormat, ...);
#ifdef __cplusplus
}
#endif
/*********************************************************************
*
* Defines
*
**********************************************************************
*/
//
// Operating modes. Define behavior if buffer is full (not enough space for entire message)
//
#define SEGGER_RTT_MODE_NO_BLOCK_SKIP (0U) // Skip. Do not block, output nothing. (Default)
#define SEGGER_RTT_MODE_NO_BLOCK_TRIM (1U) // Trim: Do not block, output as much as fits.
#define SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL (2U) // Block: Wait until there is space in the buffer.
#define SEGGER_RTT_MODE_MASK (3U)
//
// Control sequences, based on ANSI.
// Can be used to control color, and clear the screen
//
#define RTT_CTRL_RESET "" // Reset to default colors
#define RTT_CTRL_CLEAR "" // Clear screen, reposition cursor to top left
#define RTT_CTRL_TEXT_BLACK ""
#define RTT_CTRL_TEXT_RED ""
#define RTT_CTRL_TEXT_GREEN ""
#define RTT_CTRL_TEXT_YELLOW ""
#define RTT_CTRL_TEXT_BLUE ""
#define RTT_CTRL_TEXT_MAGENTA ""
#define RTT_CTRL_TEXT_CYAN ""
#define RTT_CTRL_TEXT_WHITE ""
#define RTT_CTRL_TEXT_BRIGHT_BLACK ""
#define RTT_CTRL_TEXT_BRIGHT_RED ""
#define RTT_CTRL_TEXT_BRIGHT_GREEN ""
#define RTT_CTRL_TEXT_BRIGHT_YELLOW ""
#define RTT_CTRL_TEXT_BRIGHT_BLUE ""
#define RTT_CTRL_TEXT_BRIGHT_MAGENTA ""
#define RTT_CTRL_TEXT_BRIGHT_CYAN ""
#define RTT_CTRL_TEXT_BRIGHT_WHITE ""
#define RTT_CTRL_BG_BLACK ""
#define RTT_CTRL_BG_RED ""
#define RTT_CTRL_BG_GREEN ""
#define RTT_CTRL_BG_YELLOW ""
#define RTT_CTRL_BG_BLUE ""
#define RTT_CTRL_BG_MAGENTA ""
#define RTT_CTRL_BG_CYAN ""
#define RTT_CTRL_BG_WHITE ""
#define RTT_CTRL_BG_BRIGHT_BLACK ""
#define RTT_CTRL_BG_BRIGHT_RED ""
#define RTT_CTRL_BG_BRIGHT_GREEN ""
#define RTT_CTRL_BG_BRIGHT_YELLOW ""
#define RTT_CTRL_BG_BRIGHT_BLUE ""
#define RTT_CTRL_BG_BRIGHT_MAGENTA ""
#define RTT_CTRL_BG_BRIGHT_CYAN ""
#define RTT_CTRL_BG_BRIGHT_WHITE ""
#endif
/*************************** End of file ****************************/

File diff suppressed because it is too large Load Diff

View File

@@ -1,336 +0,0 @@
/*********************************************************************
* SEGGER Microcontroller GmbH & Co. KG *
* The Embedded Experts *
**********************************************************************
* *
* (c) 2015 - 2017 SEGGER Microcontroller GmbH & Co. KG *
* *
* 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 RTT protocol and J-Link. *
* *
* Redistribution and use in source and binary forms, with or *
* without modification, are permitted provided that the following *
* conditions are met: *
* *
* o Redistributions of source code must retain the above copyright *
* notice, this list of conditions and the following disclaimer. *
* *
* o Redistributions in binary form must reproduce the above *
* copyright notice, this list of conditions and the following *
* disclaimer in the documentation and/or other materials provided *
* with the distribution. *
* *
* o Neither the name of SEGGER Microcontroller GmbH & Co. KG *
* nor the names of its contributors may be used to endorse or *
* promote products derived from this software without specific *
* prior written permission. *
* *
* 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: V2.42 *
* *
**********************************************************************
-------------------------- END-OF-HEADER -----------------------------
File : SEGGER_SYSVIEW.h
Purpose : System visualization API.
Revision: $Rev: 5626 $
*/
#ifndef SEGGER_SYSVIEW_H
#define SEGGER_SYSVIEW_H
/*********************************************************************
*
* #include Section
*
**********************************************************************
*/
#include "SEGGER.h"
#ifdef __cplusplus
extern "C" {
#endif
/*********************************************************************
*
* Defines, fixed
*
**********************************************************************
*/
#define SEGGER_SYSVIEW_VERSION 21000
#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_USER_START 15
#define SYSVIEW_EVTID_USER_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_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
//
// 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_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;
} SEGGER_SYSVIEW_TASKINFO;
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);
/*********************************************************************
*
* 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_SendSysDesc (const char* sSysDesc);
// 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_OnUserStart (unsigned int UserId); // Start of user defined event (such as a subroutine to profile)
void SEGGER_SYSVIEW_OnUserStop (unsigned int UserId); // Start of user defined event
void SEGGER_SYSVIEW_NameResource (U32 ResourceId, const char* sName);
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_PrintfTargetEx (const char* s, U32 Options, ...);
void SEGGER_SYSVIEW_PrintfHost (const char* s, ...);
void SEGGER_SYSVIEW_PrintfTarget (const char* s, ...);
void SEGGER_SYSVIEW_WarnfHost (const char* s, ...);
void SEGGER_SYSVIEW_WarnfTarget (const char* s, ...);
void SEGGER_SYSVIEW_ErrorfHost (const char* s, ...);
void SEGGER_SYSVIEW_ErrorfTarget (const char* s, ...);
#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);
#ifdef __cplusplus
}
#endif
#endif
/*************************** End of file ****************************/

View File

@@ -1,178 +0,0 @@
/*********************************************************************
* SEGGER Microcontroller GmbH & Co. KG *
* The Embedded Experts *
**********************************************************************
* *
* (c) 2015 - 2017 SEGGER Microcontroller GmbH & Co. KG *
* *
* 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 RTT protocol and J-Link. *
* *
* Redistribution and use in source and binary forms, with or *
* without modification, are permitted provided that the following *
* conditions are met: *
* *
* o Redistributions of source code must retain the above copyright *
* notice, this list of conditions and the following disclaimer. *
* *
* o Redistributions in binary form must reproduce the above *
* copyright notice, this list of conditions and the following *
* disclaimer in the documentation and/or other materials provided *
* with the distribution. *
* *
* o Neither the name of SEGGER Microcontroller GmbH & Co. KG *
* nor the names of its contributors may be used to endorse or *
* promote products derived from this software without specific *
* prior written permission. *
* *
* 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: V2.42 *
* *
**********************************************************************
-------------------------- END-OF-HEADER -----------------------------
File : SEGGER_SYSVIEW_ConfDefaults.h
Purpose : Defines defaults for configurable defines used in
SEGGER SystemView.
Revision: $Rev: 3734 $
*/
#ifndef SEGGER_SYSVIEW_CONFDEFAULTS_H
#define SEGGER_SYSVIEW_CONFDEFAULTS_H
/*********************************************************************
*
* #include Section
*
**********************************************************************
*/
#include "SEGGER_SYSVIEW_Conf.h"
#include "SEGGER_RTT_Conf.h"
#ifdef __cplusplus
extern "C" {
#endif
/*********************************************************************
*
* Configuration defaults
*
**********************************************************************
*/
// Number of bytes that SystemView uses for a buffer.
#ifndef SEGGER_SYSVIEW_RTT_BUFFER_SIZE
#define SEGGER_SYSVIEW_RTT_BUFFER_SIZE 1024
#endif
// The RTT channel that SystemView will use.
#ifndef SEGGER_SYSVIEW_RTT_CHANNEL
#define SEGGER_SYSVIEW_RTT_CHANNEL 0
#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
// Place the SystemView buffer into its own/the RTT section
#if !(defined SEGGER_SYSVIEW_BUFFER_SECTION) && (defined SEGGER_RTT_SECTION)
#define SEGGER_SYSVIEW_BUFFER_SECTION SEGGER_RTT_SECTION
#endif
// Retrieve a system timestamp. This gets the Cortex-M cycle counter.
#ifndef SEGGER_SYSVIEW_GET_TIMESTAMP
#error "SEGGER_SYSVIEW_GET_TIMESTAMP has to be defined in SEGGER_SYSVIEW_Conf.h!"
#endif
// Define number of valid bits low-order delivered by clock source.
#ifndef SEGGER_SYSVIEW_TIMESTAMP_BITS
#define SEGGER_SYSVIEW_TIMESTAMP_BITS 32
#endif
// Lowest Id reported by the Application.
#ifndef SEGGER_SYSVIEW_ID_BASE
#define SEGGER_SYSVIEW_ID_BASE 0
#endif
// Number of bits to shift Ids to save bandwidth
#ifndef SEGGER_SYSVIEW_ID_SHIFT
#define SEGGER_SYSVIEW_ID_SHIFT 0
#endif
#ifndef SEGGER_SYSVIEW_GET_INTERRUPT_ID
#error "SEGGER_SYSVIEW_GET_INTERRUPT_ID has to be defined in SEGGER_SYSVIEW_Conf.h!"
#endif
#ifndef SEGGER_SYSVIEW_MAX_ARGUMENTS
#define SEGGER_SYSVIEW_MAX_ARGUMENTS 16
#endif
#ifndef SEGGER_SYSVIEW_MAX_STRING_LEN
#define SEGGER_SYSVIEW_MAX_STRING_LEN 128
#endif
// Use a static buffer instead of a buffer on the stack for packets
#ifndef SEGGER_SYSVIEW_USE_STATIC_BUFFER
#define SEGGER_SYSVIEW_USE_STATIC_BUFFER 1
#endif
// Maximum packet size used by SystemView for the static buffer
#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
// Use post-mortem analysis instead of real-time analysis
#ifndef SEGGER_SYSVIEW_POST_MORTEM_MODE
#define SEGGER_SYSVIEW_POST_MORTEM_MODE 0
#endif
// Configure how frequently syncronization is sent
#ifndef SEGGER_SYSVIEW_SYNC_PERIOD_SHIFT
#define SEGGER_SYSVIEW_SYNC_PERIOD_SHIFT 8
#endif
// Lock SystemView (nestable)
#ifndef SEGGER_SYSVIEW_LOCK
#define SEGGER_SYSVIEW_LOCK() SEGGER_RTT_LOCK()
#endif
// Unlock SystemView (nestable)
#ifndef SEGGER_SYSVIEW_UNLOCK
#define SEGGER_SYSVIEW_UNLOCK() SEGGER_RTT_UNLOCK()
#endif
#ifdef __cplusplus
}
#endif
#endif
/*************************** End of file ****************************/

View File

@@ -1,110 +0,0 @@
/*********************************************************************
* SEGGER Microcontroller GmbH & Co. KG *
* The Embedded Experts *
**********************************************************************
* *
* (c) 2015 - 2017 SEGGER Microcontroller GmbH & Co. KG *
* *
* 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 RTT protocol and J-Link. *
* *
* Redistribution and use in source and binary forms, with or *
* without modification, are permitted provided that the following *
* conditions are met: *
* *
* o Redistributions of source code must retain the above copyright *
* notice, this list of conditions and the following disclaimer. *
* *
* o Redistributions in binary form must reproduce the above *
* copyright notice, this list of conditions and the following *
* disclaimer in the documentation and/or other materials provided *
* with the distribution. *
* *
* o Neither the name of SEGGER Microcontroller GmbH & Co. KG *
* nor the names of its contributors may be used to endorse or *
* promote products derived from this software without specific *
* prior written permission. *
* *
* 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: V2.42 *
* *
**********************************************************************
-------------------------- END-OF-HEADER -----------------------------
File : SEGGER_SYSVIEW_Int.h
Purpose : SEGGER SystemView internal header.
Revision: $Rev: 5626 $
*/
#ifndef SEGGER_SYSVIEW_INT_H
#define SEGGER_SYSVIEW_INT_H
/*********************************************************************
*
* #include Section
*
**********************************************************************
*/
#include "SEGGER_SYSVIEW.h"
#include "SEGGER_SYSVIEW_Conf.h"
#include "SEGGER_SYSVIEW_ConfDefaults.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,
// 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 ****************************/

View File

@@ -1,355 +0,0 @@
/*********************************************************************
* SEGGER Microcontroller GmbH & Co. KG *
* The Embedded Experts *
**********************************************************************
* *
* (c) 2015 - 2017 SEGGER Microcontroller GmbH & Co. KG *
* *
* 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 RTT protocol and J-Link. *
* *
* Redistribution and use in source and binary forms, with or *
* without modification, are permitted provided that the following *
* conditions are met: *
* *
* o Redistributions of source code must retain the above copyright *
* notice, this list of conditions and the following disclaimer. *
* *
* o Redistributions in binary form must reproduce the above *
* copyright notice, this list of conditions and the following *
* disclaimer in the documentation and/or other materials provided *
* with the distribution. *
* *
* o Neither the name of SEGGER Microcontroller GmbH & Co. KG *
* nor the names of its contributors may be used to endorse or *
* promote products derived from this software without specific *
* prior written permission. *
* *
* 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: V2.42 *
* *
**********************************************************************
-------------------------- END-OF-HEADER -----------------------------
File : SEGGER_SYSVIEW_Config_FreeRTOS.c
Purpose : Sample setup configuration of SystemView with FreeRTOS.
Revision: $Rev: 3734 $
*/
#include "freertos/FreeRTOS.h"
#include "SEGGER_SYSVIEW.h"
#include "esp32/rom/ets_sys.h"
#include "esp_app_trace.h"
#include "esp_app_trace_util.h"
#include "esp_intr_alloc.h"
#include "esp32/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 "ESP32"
// Determine which timer to use as timestamp source
#if CONFIG_SYSVIEW_TS_SOURCE_CCOUNT
#define TS_USE_CCOUNT 1
#elif CONFIG_SYSVIEW_TS_SOURCE_ESP_TIMER
#define TS_USE_ESP_TIMER 1
#else
#define TS_USE_TIMERGROUP 1
#endif
#if TS_USE_TIMERGROUP
#include "driver/timer.h"
// Timer group timer divisor
#define SYSVIEW_TIMER_DIV 2
// Frequency of the timestamp.
#define SYSVIEW_TIMESTAMP_FREQ (esp_clk_apb_freq() / SYSVIEW_TIMER_DIV)
// Timer ID and group ID
#if defined(CONFIG_SYSVIEW_TS_SOURCE_TIMER_00) || defined(CONFIG_SYSVIEW_TS_SOURCE_TIMER_01)
#define TS_TIMER_ID 0
#else
#define TS_TIMER_ID 1
#endif // TIMER_00 || TIMER_01
#if defined(CONFIG_SYSVIEW_TS_SOURCE_TIMER_00) || defined(CONFIG_SYSVIEW_TS_SOURCE_TIMER_10)
#define TS_TIMER_GROUP 0
#else
#define TS_TIMER_GROUP 1
#endif // TIMER_00 || TIMER_10
#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_ESP32_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 (0x3F400000)
#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
// 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};
static const char * const s_isr_names[] = {
[0] = "WIFI_MAC",
[1] = "WIFI_NMI",
[2] = "WIFI_BB",
[3] = "BT_MAC",
[4] = "BT_BB",
[5] = "BT_BB_NMI",
[6] = "RWBT",
[7] = "RWBLE",
[8] = "RWBT_NMI",
[9] = "RWBLE_NMI",
[10] = "SLC0",
[11] = "SLC1",
[12] = "UHCI0",
[13] = "UHCI1",
[14] = "TG0_T0_LEVEL",
[15] = "TG0_T1_LEVEL",
[16] = "TG0_WDT_LEVEL",
[17] = "TG0_LACT_LEVEL",
[18] = "TG1_T0_LEVEL",
[19] = "TG1_T1_LEVEL",
[20] = "TG1_WDT_LEVEL",
[21] = "TG1_LACT_LEVEL",
[22] = "GPIO",
[23] = "GPIO_NMI",
[24] = "FROM_CPU0",
[25] = "FROM_CPU1",
[26] = "FROM_CPU2",
[27] = "FROM_CPU3",
[28] = "SPI0",
[29] = "SPI1",
[30] = "SPI2",
[31] = "SPI3",
[32] = "I2S0",
[33] = "I2S1",
[34] = "UART0",
[35] = "UART1",
[36] = "UART2",
[37] = "SDIO_HOST",
[38] = "ETH_MAC",
[39] = "PWM0",
[40] = "PWM1",
[41] = "PWM2",
[42] = "PWM3",
[43] = "LEDC",
[44] = "EFUSE",
[45] = "CAN",
[46] = "RTC_CORE",
[47] = "RMT",
[48] = "PCNT",
[49] = "I2C_EXT0",
[50] = "I2C_EXT1",
[51] = "RSA",
[52] = "SPI1_DMA",
[53] = "SPI2_DMA",
[54] = "SPI3_DMA",
[55] = "WDT",
[56] = "TIMER1",
[57] = "TIMER2",
[58] = "TG0_T0_EDGE",
[59] = "TG0_T1_EDGE",
[60] = "TG0_WDT_EDGE",
[61] = "TG0_LACT_EDGE",
[62] = "TG1_T0_EDGE",
[63] = "TG1_T1_EDGE",
[64] = "TG1_WDT_EDGE",
[65] = "TG1_LACT_EDGE",
[66] = "MMU_IA",
[67] = "MPU_IA",
[68] = "CACHE_IA",
};
/*********************************************************************
*
* _cbSendSystemDesc()
*
* Function description
* Sends SystemView description strings.
*/
static void _cbSendSystemDesc(void) {
char irq_str[32];
SEGGER_SYSVIEW_SendSysDesc("N="SYSVIEW_APP_NAME",D="SYSVIEW_DEVICE_NAME",C=Xtensa,O=FreeRTOS");
snprintf(irq_str, sizeof(irq_str), "I#%d=SysTick", SYSTICK_INTR_ID);
SEGGER_SYSVIEW_SendSysDesc(irq_str);
size_t isr_count = sizeof(s_isr_names)/sizeof(s_isr_names[0]);
for (size_t i = 0; i < isr_count; ++i) {
snprintf(irq_str, sizeof(irq_str), "I#%d=%s", ETS_INTERNAL_INTR_SOURCE_OFF + i, s_isr_names[i]);
SEGGER_SYSVIEW_SendSysDesc(irq_str);
}
}
/*********************************************************************
*
* Global functions
*
**********************************************************************
*/
static void SEGGER_SYSVIEW_TS_Init()
{
/* We only need to initialize something if we use Timer Group.
* esp_timer and ccount can be used as is.
*/
#if TS_USE_TIMERGROUP
timer_config_t config = {
.alarm_en = 0,
.auto_reload = 0,
.counter_dir = TIMER_COUNT_UP,
.divider = SYSVIEW_TIMER_DIV,
.counter_en = 0
};
/* Configure timer */
timer_init(TS_TIMER_GROUP, TS_TIMER_ID, &config);
/* Load counter value */
timer_set_counter_value(TS_TIMER_GROUP, TS_TIMER_ID, 0x00000000ULL);
/* Start counting */
timer_start(TS_TIMER_GROUP, TS_TIMER_ID);
#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_SYSVIEW_EVT_OVERFLOW_ENABLE
disable_evts |= SYSVIEW_EVTMASK_OVERFLOW;
#endif
#if !CONFIG_SYSVIEW_EVT_ISR_ENTER_ENABLE
disable_evts |= SYSVIEW_EVTMASK_ISR_ENTER;
#endif
#if !CONFIG_SYSVIEW_EVT_ISR_EXIT_ENABLE
disable_evts |= SYSVIEW_EVTMASK_ISR_EXIT;
#endif
#if !CONFIG_SYSVIEW_EVT_TASK_START_EXEC_ENABLE
disable_evts |= SYSVIEW_EVTMASK_TASK_START_EXEC;
#endif
#if !CONFIG_SYSVIEW_EVT_TASK_STOP_EXEC_ENABLE
disable_evts |= SYSVIEW_EVTMASK_TASK_STOP_EXEC;
#endif
#if !CONFIG_SYSVIEW_EVT_TASK_START_READY_ENABLE
disable_evts |= SYSVIEW_EVTMASK_TASK_START_READY;
#endif
#if !CONFIG_SYSVIEW_EVT_TASK_STOP_READY_ENABLE
disable_evts |= SYSVIEW_EVTMASK_TASK_STOP_READY;
#endif
#if !CONFIG_SYSVIEW_EVT_TASK_CREATE_ENABLE
disable_evts |= SYSVIEW_EVTMASK_TASK_CREATE;
#endif
#if !CONFIG_SYSVIEW_EVT_TASK_TERMINATE_ENABLE
disable_evts |= SYSVIEW_EVTMASK_TASK_TERMINATE;
#endif
#if !CONFIG_SYSVIEW_EVT_IDLE_ENABLE
disable_evts |= SYSVIEW_EVTMASK_IDLE;
#endif
#if !CONFIG_SYSVIEW_EVT_ISR_TO_SCHEDULER_ENABLE
disable_evts |= SYSVIEW_EVTMASK_ISR_TO_SCHEDULER;
#endif
#if !CONFIG_SYSVIEW_EVT_TIMER_ENTER_ENABLE
disable_evts |= SYSVIEW_EVTMASK_TIMER_ENTER;
#endif
#if !CONFIG_SYSVIEW_EVT_TIMER_EXIT_ENABLE
disable_evts |= SYSVIEW_EVTMASK_TIMER_EXIT;
#endif
SEGGER_SYSVIEW_DisableEvents(disable_evts);
}
U32 SEGGER_SYSVIEW_X_GetTimestamp()
{
#if TS_USE_TIMERGROUP
uint64_t ts = 0;
timer_get_counter_value(TS_TIMER_GROUP, TS_TIMER_ID, &ts);
return (U32) ts; // return lower part of counter value
#elif TS_USE_CCOUNT
return portGET_RUN_TIME_COUNTER_VALUE();
#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 SEGGER_SYSVIEW_X_RTT_Unlock()
{
}
unsigned SEGGER_SYSVIEW_X_SysView_Lock()
{
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 ****************************/

View File

@@ -1,290 +0,0 @@
/*********************************************************************
* SEGGER Microcontroller GmbH & Co. KG *
* The Embedded Experts *
**********************************************************************
* *
* (c) 2015 - 2017 SEGGER Microcontroller GmbH & Co. KG *
* *
* 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 RTT protocol and J-Link. *
* *
* Redistribution and use in source and binary forms, with or *
* without modification, are permitted provided that the following *
* conditions are met: *
* *
* o Redistributions of source code must retain the above copyright *
* notice, this list of conditions and the following disclaimer. *
* *
* o Redistributions in binary form must reproduce the above *
* copyright notice, this list of conditions and the following *
* disclaimer in the documentation and/or other materials provided *
* with the distribution. *
* *
* o Neither the name of SEGGER Microcontroller GmbH & Co. KG *
* nor the names of its contributors may be used to endorse or *
* promote products derived from this software without specific *
* prior written permission. *
* *
* 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: V2.42 *
* *
**********************************************************************
-------------------------- END-OF-HEADER -----------------------------
File : SEGGER_SYSVIEW_FreeRTOS.c
Purpose : Interface between FreeRTOS and SystemView.
Revision: $Rev: 3734 $
*/
#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];
/*********************************************************************
*
* _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 < SYSVIEW_FREERTOS_MAX_NOF_TASKS; n++) {
if (_aTasks[n].xHandle) {
#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.
*/
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) {
unsigned n;
if (memcmp(pcTaskName, "IDLE", 5) == 0) {
return;
}
for (n = 0; n < SYSVIEW_FREERTOS_MAX_NOF_TASKS; n++) {
if (_aTasks[n].xHandle == 0) {
break;
}
}
if (n == SYSVIEW_FREERTOS_MAX_NOF_TASKS) {
SEGGER_SYSVIEW_Warn("SYSTEMVIEW: Could not record task information. Maximum number of tasks reached.");
return;
}
_aTasks[n].xHandle = xHandle;
_aTasks[n].pcTaskName = pcTaskName;
_aTasks[n].uxCurrentPriority = uxCurrentPriority;
_aTasks[n].pxStack = pxStack;
_aTasks[n].uStackHighWaterMark = uStackHighWaterMark;
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;
if (memcmp(pcTaskName, "IDLE", 5) == 0) {
return;
}
for (n = 0; n < SYSVIEW_FREERTOS_MAX_NOF_TASKS; n++) {
if (_aTasks[n].xHandle == xHandle) {
break;
}
}
if (n < SYSVIEW_FREERTOS_MAX_NOF_TASKS) {
_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;
for (n = 0; n < SYSVIEW_FREERTOS_MAX_NOF_TASKS; n++) {
if (_aTasks[n].xHandle == xHandle) {
break;
}
}
if (n == SYSVIEW_FREERTOS_MAX_NOF_TASKS) {
SEGGER_SYSVIEW_Warn("SYSTEMVIEW: Could not find task information. Cannot delete task.");
return;
}
_aTasks[n].xHandle = 0;
}
/*********************************************************************
*
* 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);
}
/*********************************************************************
*
* SYSVIEW_RecordU32x4()
*
* Function description
* Record an event with 4 parameters
*/
void SYSVIEW_RecordU32x4(unsigned Id, U32 Para0, U32 Para1, U32 Para2, U32 Para3) {
U8 aPacket[SEGGER_SYSVIEW_INFO_SIZE + 4 * SEGGER_SYSVIEW_QUANTA_U32];
U8* pPayload;
//
pPayload = SEGGER_SYSVIEW_PREPARE_PACKET(aPacket); // Prepare the packet for SystemView
pPayload = SEGGER_SYSVIEW_EncodeU32(pPayload, Para0); // Add the first parameter to the packet
pPayload = SEGGER_SYSVIEW_EncodeU32(pPayload, Para1); // Add the second parameter to the packet
pPayload = SEGGER_SYSVIEW_EncodeU32(pPayload, Para2); // Add the third parameter to the packet
pPayload = SEGGER_SYSVIEW_EncodeU32(pPayload, Para3); // Add the fourth parameter to the packet
//
SEGGER_SYSVIEW_SendPacket(&aPacket[0], pPayload, Id); // Send the packet
}
/*********************************************************************
*
* SYSVIEW_RecordU32x5()
*
* Function description
* Record an event with 5 parameters
*/
void SYSVIEW_RecordU32x5(unsigned Id, U32 Para0, U32 Para1, U32 Para2, U32 Para3, U32 Para4) {
U8 aPacket[SEGGER_SYSVIEW_INFO_SIZE + 5 * SEGGER_SYSVIEW_QUANTA_U32];
U8* pPayload;
//
pPayload = SEGGER_SYSVIEW_PREPARE_PACKET(aPacket); // Prepare the packet for SystemView
pPayload = SEGGER_SYSVIEW_EncodeU32(pPayload, Para0); // Add the first parameter to the packet
pPayload = SEGGER_SYSVIEW_EncodeU32(pPayload, Para1); // Add the second parameter to the packet
pPayload = SEGGER_SYSVIEW_EncodeU32(pPayload, Para2); // Add the third parameter to the packet
pPayload = SEGGER_SYSVIEW_EncodeU32(pPayload, Para3); // Add the fourth parameter to the packet
pPayload = SEGGER_SYSVIEW_EncodeU32(pPayload, Para4); // Add the fifth parameter to the packet
//
SEGGER_SYSVIEW_SendPacket(&aPacket[0], pPayload, Id); // Send the packet
}
/*********************************************************************
*
* Public API structures
*
**********************************************************************
*/
// Callbacks provided to SYSTEMVIEW by FreeRTOS
const SEGGER_SYSVIEW_OS_API SYSVIEW_X_OS_TraceAPI = {
_cbGetTime,
_cbSendTaskList,
};
/*************************** End of file ****************************/

View File

@@ -1,337 +0,0 @@
/*********************************************************************
* SEGGER Microcontroller GmbH & Co. KG *
* The Embedded Experts *
**********************************************************************
* *
* (c) 2015 - 2017 SEGGER Microcontroller GmbH & Co. KG *
* *
* 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 RTT protocol and J-Link. *
* *
* Redistribution and use in source and binary forms, with or *
* without modification, are permitted provided that the following *
* conditions are met: *
* *
* o Redistributions of source code must retain the above copyright *
* notice, this list of conditions and the following disclaimer. *
* *
* o Redistributions in binary form must reproduce the above *
* copyright notice, this list of conditions and the following *
* disclaimer in the documentation and/or other materials provided *
* with the distribution. *
* *
* o Neither the name of SEGGER Microcontroller GmbH & Co. KG *
* nor the names of its contributors may be used to endorse or *
* promote products derived from this software without specific *
* prior written permission. *
* *
* 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: V2.42 *
* *
**********************************************************************
-------------------------- END-OF-HEADER -----------------------------
File : SEGGER_SYSVIEW_FreeRTOS.h
Purpose : Interface between FreeRTOS and SystemView.
Revision: $Rev: 3734 $
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
*
**********************************************************************
*/
#ifndef portSTACK_GROWTH
#define portSTACK_GROWTH ( -1 )
#endif
#define SYSVIEW_FREERTOS_MAX_NOF_TASKS CONFIG_SYSVIEW_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 traceTASK_NOTIFY_TAKE() SEGGER_SYSVIEW_RecordU32x2(apiFastID_OFFSET + apiID_ULTASKNOTIFYTAKE, xClearCountOnExit, xTicksToWait)
#define traceTASK_DELAY() SEGGER_SYSVIEW_RecordU32(apiFastID_OFFSET + apiID_VTASKDELAY, xTicksToDelay)
#define traceTASK_DELAY_UNTIL() SEGGER_SYSVIEW_RecordVoid(apiFastID_OFFSET + apiID_VTASKDELAYUNTIL)
#define traceTASK_DELETE( pxTCB ) if (pxTCB != NULL) { \
SEGGER_SYSVIEW_RecordU32(apiFastID_OFFSET + apiID_VTASKDELETE, \
SEGGER_SYSVIEW_ShrinkId((U32)pxTCB)); \
SYSVIEW_DeleteTask((U32)pxTCB); \
}
#define traceTASK_NOTIFY_GIVE_FROM_ISR() 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() SYSVIEW_RecordU32x4(apiFastID_OFFSET + apiID_XTASKGENERICNOTIFY, SEGGER_SYSVIEW_ShrinkId((U32)pxTCB), ulValue, eAction, (U32)pulPreviousNotificationValue)
#define traceTASK_NOTIFY_FROM_ISR() SYSVIEW_RecordU32x5(apiFastID_OFFSET + apiID_XTASKGENERICNOTIFYFROMISR, SEGGER_SYSVIEW_ShrinkId((U32)pxTCB), ulValue, eAction, (U32)pulPreviousNotificationValue, (U32)pxHigherPriorityTaskWoken)
#define traceTASK_NOTIFY_WAIT() 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 ) SYSVIEW_RecordU32x4(apiFastID_OFFSET + apiID_XQUEUEGENERICRECEIVE, SEGGER_SYSVIEW_ShrinkId((U32)pxQueue), SEGGER_SYSVIEW_ShrinkId((U32)pvBuffer), xTicksToWait, xJustPeeking)
#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 ) SYSVIEW_RecordU32x4(apiFastID_OFFSET + apiID_XQUEUEGENERICRECEIVE, SEGGER_SYSVIEW_ShrinkId((U32)pxQueue), SEGGER_SYSVIEW_ShrinkId((U32)pvBuffer), xTicksToWait, xJustPeeking)
#define traceQUEUE_RECEIVE_FAILED( pxQueue ) SYSVIEW_RecordU32x4(apiFastID_OFFSET + apiID_XQUEUEGENERICRECEIVE, SEGGER_SYSVIEW_ShrinkId((U32)pxQueue), SEGGER_SYSVIEW_ShrinkId((U32)pvBuffer), xTicksToWait, xJustPeeking)
#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)
#if ( configUSE_QUEUE_SETS != 1 )
#define traceQUEUE_SEND( pxQueue ) SYSVIEW_RecordU32x4(apiFastID_OFFSET + apiID_XQUEUEGENERICSEND, SEGGER_SYSVIEW_ShrinkId((U32)pxQueue), (U32)pvItemToQueue, xTicksToWait, xCopyPosition)
#else
#define traceQUEUE_SEND( pxQueue ) SYSVIEW_RecordU32x4(apiFastID_OFFSET + apiID_XQUEUEGENERICSEND, SEGGER_SYSVIEW_ShrinkId((U32)pxQueue), 0, 0, xCopyPosition)
#endif
#define traceQUEUE_SEND_FAILED( pxQueue ) 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)
#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.
//
#if ( INCLUDE_xTaskGetIdleTaskHandle == 1 )
#define traceTASK_SWITCHED_IN() if(prvGetTCBFromHandle(NULL) == xTaskGetIdleTaskHandle()) { \
SEGGER_SYSVIEW_OnIdle(); \
} else { \
SEGGER_SYSVIEW_OnTaskStartExec((U32)pxCurrentTCB[xPortGetCoreID()]); \
}
#else
#define traceTASK_SWITCHED_IN() { \
if (memcmp(pxCurrentTCB[xPortGetCoreID()]->pcTaskName, "IDLE", 5) != 0) { \
SEGGER_SYSVIEW_OnTaskStartExec((U32)pxCurrentTCB[xPortGetCoreID()]); \
} 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)pxCurrentTCB[xPortGetCoreID()], (1u << 2))
#define traceMOVED_TASK_TO_OVERFLOW_DELAYED_LIST() SEGGER_SYSVIEW_OnTaskStopReady((U32)pxCurrentTCB[xPortGetCoreID()], (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);
void SYSVIEW_RecordU32x4 (unsigned Id, U32 Para0, U32 Para1, U32 Para2, U32 Para3);
void SYSVIEW_RecordU32x5 (unsigned Id, U32 Para0, U32 Para1, U32 Para2, U32 Para3, U32 Para4);
#ifdef __cplusplus
}
#endif
#endif
/*************************** End of file ****************************/

View File

@@ -1,244 +0,0 @@
// Copyright 2017 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "string.h"
#include "freertos/FreeRTOS.h"
#include "SEGGER_RTT.h"
#include "SEGGER_SYSVIEW.h"
#include "SEGGER_SYSVIEW_Conf.h"
#include "esp32/rom/ets_sys.h"
#include "esp_app_trace.h"
#include "esp_log.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_SYSVIEW_BUF_WAIT_TMO == -1
#define SEGGER_HOST_WAIT_TMO ESP_APPTRACE_TMO_INFINITE
#else
#define SEGGER_HOST_WAIT_TMO CONFIG_SYSVIEW_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];
/*********************************************************************
*
* Public code
*
**********************************************************************
*/
/*********************************************************************
*
* SEGGER_RTT_ESP32_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_ESP32_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_TRAX, s_events_buf, s_events_buf_filled, tmo);
if (res != ESP_OK) {
ESP_LOGE(TAG, "Failed to flush buffered events (%d)!\n", 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_TRAX, min_sz, tmo);
if (res != ESP_OK) {
ESP_LOGE(TAG, "Failed to flush apptrace data (%d)!\n", res);
}
s_events_buf_filled = 0;
}
/*********************************************************************
*
* SEGGER_RTT_ESP32_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_ESP32_Flush(unsigned long min_sz, unsigned long tmo)
{
SEGGER_SYSVIEW_LOCK();
SEGGER_RTT_ESP32_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_TRAX, 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 (NumBytes > SYSVIEW_EVENTS_BUF_SZ) {
ESP_LOGE(TAG, "Too large event %u bytes!", NumBytes);
return 0;
}
if (xPortGetCoreID()) { // 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);
}
}
if (s_events_buf_filled + NumBytes > SYSVIEW_EVENTS_BUF_SZ) {
esp_err_t res = esp_apptrace_write(ESP_APPTRACE_DEST_TRAX, 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;
}
memcpy(&s_events_buf[s_events_buf_filled], pBuffer, NumBytes);
s_events_buf_filled += NumBytes;
if (event_id == SYSVIEW_EVTID_TRACE_STOP) {
SEGGER_RTT_ESP32_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;
}
/*************************** End of file ****************************/

View File

@@ -1,100 +0,0 @@
// Copyright 2018 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <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 = "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_ESP32_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);
}

View File

@@ -1,34 +0,0 @@
// Copyright 2018 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <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;
}

View File

@@ -1,3 +0,0 @@
idf_component_register(SRC_DIRS "."
INCLUDE_DIRS "."
REQUIRES unity)

View File

@@ -1,5 +0,0 @@
#
#Component Makefile
#
COMPONENT_ADD_LDFLAGS = -Wl,--whole-archive -l$(COMPONENT_NAME) -Wl,--no-whole-archive

View File

@@ -1,57 +0,0 @@
idf_component_register(SRCS "esp_ota_ops.c"
"esp_app_desc.c"
INCLUDE_DIRS "include"
REQUIRES spi_flash partition_table bootloader_support)
# esp_app_desc structure is added as an undefined symbol because otherwise the
# linker will ignore this structure as it has no other files depending on it.
target_link_libraries(${COMPONENT_LIB} INTERFACE "-u esp_app_desc")
# cut PROJECT_VER and PROJECT_NAME to required 32 characters.
idf_build_get_property(project_ver PROJECT_VER)
idf_build_get_property(project_name PROJECT_NAME)
string(SUBSTRING "${project_ver}" 0 31 PROJECT_VER_CUT)
string(SUBSTRING "${project_name}" 0 31 PROJECT_NAME_CUT)
set_source_files_properties(
SOURCE "esp_app_desc.c"
PROPERTIES COMPILE_DEFINITIONS
"PROJECT_VER=\"${PROJECT_VER_CUT}\"; PROJECT_NAME=\"${PROJECT_NAME_CUT}\"")
if(NOT BOOTLOADER_BUILD)
partition_table_get_partition_info(otadata_offset "--partition-type data --partition-subtype ota" "offset")
partition_table_get_partition_info(otadata_size "--partition-type data --partition-subtype ota" "size")
# Add custom target for generating empty otadata partition for flashing
if(otadata_size AND otadata_offset)
idf_build_get_property(build_dir BUILD_DIR)
set(blank_otadata_file ${build_dir}/ota_data_initial.bin)
idf_build_get_property(idf_path IDF_PATH)
idf_build_get_property(python PYTHON)
add_custom_command(OUTPUT ${blank_otadata_file}
COMMAND ${python} ${idf_path}/components/partition_table/gen_empty_partition.py
${otadata_size} ${blank_otadata_file})
add_custom_target(blank_ota_data ALL DEPENDS ${blank_otadata_file})
add_dependencies(flash blank_ota_data)
set(otatool_py ${python} ${COMPONENT_DIR}/otatool.py)
set(esptool_args --esptool-args before=${CONFIG_ESPTOOLPY_BEFORE} after=${CONFIG_ESPTOOLPY_AFTER})
add_custom_target(read_otadata DEPENDS "${PARTITION_CSV_PATH}"
COMMAND ${otatool_py} ${esptool_args}
--partition-table-file ${PARTITION_CSV_PATH}
--partition-table-offset ${PARTITION_TABLE_OFFSET}
read_otadata)
add_custom_target(erase_otadata DEPENDS "${PARTITION_CSV_PATH}"
COMMAND ${otatool_py} ${esptool_args}
--partition-table-file ${PARTITION_CSV_PATH}
--partition-table-offset ${PARTITION_TABLE_OFFSET}
erase_otadata)
esptool_py_flash_project_args(otadata ${otadata_offset} "${blank_otadata_file}" FLASH_IN_PROJECT)
endif()
endif()

View File

@@ -1,35 +0,0 @@
menu "Application manager"
config APP_COMPILE_TIME_DATE
bool "Use time/date stamp for app"
default y
help
If set, then the app will be built with the current time/date stamp. It is stored in the app description
structure. If not set, time/date stamp will be excluded from app image. This can be useful for getting the
same binary image files made from the same source, but at different times.
config APP_EXCLUDE_PROJECT_VER_VAR
bool "Exclude PROJECT_VER from firmware image"
default n
help
The PROJECT_VER variable from the build system will not affect the firmware image.
This value will not be contained in the esp_app_desc structure.
config APP_EXCLUDE_PROJECT_NAME_VAR
bool "Exclude PROJECT_NAME from firmware image"
default n
help
The PROJECT_NAME variable from the build system will not affect the firmware image.
This value will not be contained in the esp_app_desc structure.
config APP_RETRIEVE_LEN_ELF_SHA
int "The length of APP ELF SHA is stored in RAM(chars)"
default 16
range 8 64
help
At startup, the app will read this many hex characters from the embedded APP ELF SHA-256 hash value
and store it in static RAM. This ensures the app ELF SHA-256 value is always available
if it needs to be printed by the panic handler code.
Changing this value will change the size of a static buffer, in bytes.
endmenu # "Application manager"

View File

@@ -1,54 +0,0 @@
# Generate partition binary
#
.PHONY: blank_ota_data erase_otadata read_otadata
OTATOOL_PY := $(PYTHON) $(COMPONENT_PATH)/otatool.py
PARTTOOL_PY := $(PYTHON) $(IDF_PATH)/components/partition_table/parttool.py
# Generate blank partition file
BLANK_OTA_DATA_FILE = $(BUILD_DIR_BASE)/ota_data_initial.bin
# Copy PARTITION_TABLE_CSV_PATH definition here from $IDF_PATH/components/partition_table/Makefile.projbuild
# to avoid undefined variables warning for PARTITION_TABLE_CSV_PATH
ifndef PARTITION_TABLE_CSV_PATH
PARTITION_TABLE_ROOT := $(call dequote,$(if $(CONFIG_PARTITION_TABLE_CUSTOM),$(PROJECT_PATH),$(IDF_PATH)/components/partition_table))
PARTITION_TABLE_CSV_PATH := $(call dequote,$(abspath $(PARTITION_TABLE_ROOT)/$(call dequote,$(CONFIG_PARTITION_TABLE_FILENAME))))
endif
$(BLANK_OTA_DATA_FILE): partition_table_get_info $(PARTITION_TABLE_CSV_PATH) | check_python_dependencies
$(shell if [ "$(OTA_DATA_OFFSET)" != "" ] && [ "$(OTA_DATA_SIZE)" != "" ]; then \
$(PYTHON) $(IDF_PATH)/components/partition_table/gen_empty_partition.py $(OTA_DATA_SIZE) $(BLANK_OTA_DATA_FILE); \
fi; )
$(eval BLANK_OTA_DATA_FILE = $(shell if [ "$(OTA_DATA_OFFSET)" != "" ] && [ "$(OTA_DATA_SIZE)" != "" ]; then \
echo $(BLANK_OTA_DATA_FILE); else echo " "; fi) )
blank_ota_data: $(BLANK_OTA_DATA_FILE)
# If there is no otadata partition, both OTA_DATA_OFFSET and BLANK_OTA_DATA_FILE
# expand to empty values.
ESPTOOL_ALL_FLASH_ARGS += $(OTA_DATA_OFFSET) $(BLANK_OTA_DATA_FILE)
ESPTOOL_ARGS := --esptool-args port=$(CONFIG_ESPTOOLPY_PORT) baud=$(CONFIG_ESPTOOLPY_BAUD) before=$(CONFIG_ESPTOOLPY_BEFORE) after=$(CONFIG_ESPTOOLPY_AFTER)
erase_otadata: $(PARTITION_TABLE_CSV_PATH) partition_table_get_info | check_python_dependencies
$(OTATOOL_PY) $(ESPTOOL_ARGS) --partition-table-file $(PARTITION_TABLE_CSV_PATH) \
--partition-table-offset $(PARTITION_TABLE_OFFSET) \
erase_otadata
read_otadata: $(PARTITION_TABLE_CSV_PATH) partition_table_get_info | check_python_dependencies
$(OTATOOL_PY) $(ESPTOOL_ARGS) --partition-table-file $(PARTITION_TABLE_CSV_PATH) \
--partition-table-offset $(partition_table_offset) \
read_otadata
all: blank_ota_data
flash: blank_ota_data
ifdef CONFIG_SECURE_FLASH_ENCRYPTION_MODE_DEVELOPMENT
encrypted-flash: blank_ota_data
endif
TMP_DEFINES := $(BUILD_DIR_BASE)/app_update/tmp_cppflags.txt
export TMP_DEFINES
clean:
rm -f $(BLANK_OTA_DATA_FILE)
rm -f $(TMP_DEFINES)

51
components/app_update/component.mk Normal file → Executable file
View File

@@ -3,54 +3,3 @@
#
# (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.)
# esp_app_desc structure is added as an undefined symbol because otherwise the
# linker will ignore this structure as it has no other files depending on it.
COMPONENT_ADD_LDFLAGS += -u esp_app_desc
ifndef IS_BOOTLOADER_BUILD
GET_PROJECT_VER ?=
ifeq ("${PROJECT_VER}", "")
ifeq ("$(wildcard ${PROJECT_PATH}/version.txt)","")
GET_PROJECT_VER := $(shell cd ${PROJECT_PATH} && git describe --always --tags --dirty 2> /dev/null)
ifeq ("${GET_PROJECT_VER}", "")
GET_PROJECT_VER := "1"
$(info Project is not inside a git repository, will not use 'git describe' to determine PROJECT_VER.)
endif
else
# read from version.txt
GET_PROJECT_VER := $(shell cat ${PROJECT_PATH}/version.txt)
endif
endif
# If ``PROJECT_VER`` variable set in project Makefile file, its value will be used.
# Else, if the ``$PROJECT_PATH/version.txt`` exists, its contents will be used as ``PROJECT_VER``.
# Else, if the project is located inside a Git repository, the output of git describe will be used.
# Otherwise, ``PROJECT_VER`` will be "1".
ifeq ("${PROJECT_VER}", "")
PROJECT_VER:= $(GET_PROJECT_VER)
else
PROJECT_VER:= $(PROJECT_VER)
endif
# cut PROJECT_VER and PROJECT_NAME to required 32 characters.
PROJECT_VER_CUT := $(shell echo "$(PROJECT_VER)" | cut -c 1-31)
PROJECT_NAME_CUT := $(shell echo "$(PROJECT_NAME)" | cut -c 1-31)
$(info App "$(PROJECT_NAME_CUT)" version: $(PROJECT_VER_CUT))
NEW_DEFINES:= "$(PROJECT_VER_CUT) $(PROJECT_NAME_CUT) $(IDF_VER)"
ifeq ("$(wildcard ${TMP_DEFINES})","")
OLD_DEFINES:= ""
else
OLD_DEFINES:= "$(shell cat $(TMP_DEFINES))"
endif
# If NEW_DEFINES (PROJECT_VER, PROJECT_NAME) were changed then rebuild only esp_app_desc.
ifneq (${NEW_DEFINES}, ${OLD_DEFINES})
$(shell echo $(NEW_DEFINES) > $(TMP_DEFINES); rm -f esp_app_desc.o;)
endif
esp_app_desc.o: CPPFLAGS += -D PROJECT_VER=\""$(PROJECT_VER_CUT)"\" -D PROJECT_NAME=\""$(PROJECT_NAME_CUT)"\"
endif

View File

@@ -1,107 +0,0 @@
// Copyright 2017-2018 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <assert.h>
#include <sys/param.h>
#include "esp_ota_ops.h"
#include "esp_attr.h"
#include "sdkconfig.h"
// Application version info
const __attribute__((section(".rodata_desc"))) esp_app_desc_t esp_app_desc = {
.magic_word = ESP_APP_DESC_MAGIC_WORD,
#ifdef CONFIG_APP_EXCLUDE_PROJECT_VER_VAR
.version = "",
#else
.version = PROJECT_VER,
#endif
#ifdef CONFIG_APP_EXCLUDE_PROJECT_NAME_VAR
.project_name = "",
#else
.project_name = PROJECT_NAME,
#endif
.idf_ver = IDF_VER,
#ifdef CONFIG_BOOTLOADER_APP_SECURE_VERSION
.secure_version = CONFIG_BOOTLOADER_APP_SECURE_VERSION,
#else
.secure_version = 0,
#endif
#ifdef CONFIG_APP_COMPILE_TIME_DATE
.time = __TIME__,
.date = __DATE__,
#else
.time = "",
.date = "",
#endif
};
#ifndef CONFIG_APP_EXCLUDE_PROJECT_VER_VAR
_Static_assert(sizeof(PROJECT_VER) <= sizeof(esp_app_desc.version), "PROJECT_VER is longer than version field in structure");
#endif
_Static_assert(sizeof(IDF_VER) <= sizeof(esp_app_desc.idf_ver), "IDF_VER is longer than idf_ver field in structure");
#ifndef CONFIG_APP_EXCLUDE_PROJECT_NAME_VAR
_Static_assert(sizeof(PROJECT_NAME) <= sizeof(esp_app_desc.project_name), "PROJECT_NAME is longer than project_name field in structure");
#endif
const esp_app_desc_t *esp_ota_get_app_description(void)
{
return &esp_app_desc;
}
/* The following two functions may be called from the panic handler
* or core dump, hence IRAM_ATTR.
*/
static inline char IRAM_ATTR to_hex_digit(unsigned val)
{
return (val < 10) ? ('0' + val) : ('a' + val - 10);
}
__attribute__((constructor)) void esp_ota_init_app_elf_sha256(void)
{
esp_ota_get_app_elf_sha256(NULL, 0);
}
/* The esp_app_desc.app_elf_sha256 should be possible to print in panic handler during cache is disabled.
* But because the cache is disabled the reading esp_app_desc.app_elf_sha256 is not right and
* can lead to a complete lock-up of the CPU.
* For this reason we do a reading of esp_app_desc.app_elf_sha256 while start up in esp_ota_init_app_elf_sha256()
* and keep it in the static s_app_elf_sha256 value.
*/
int IRAM_ATTR esp_ota_get_app_elf_sha256(char* dst, size_t size)
{
static char s_app_elf_sha256[CONFIG_APP_RETRIEVE_LEN_ELF_SHA / 2];
static bool first_call = true;
if (first_call) {
first_call = false;
const uint8_t* src = esp_app_desc.app_elf_sha256;
for (size_t i = 0; i < sizeof(s_app_elf_sha256); ++i) {
s_app_elf_sha256[i] = src[i];
}
}
if (dst == NULL || size == 0) {
return 0;
}
size_t n = MIN((size - 1) / 2, sizeof(s_app_elf_sha256));
for (size_t i = 0; i < n; ++i) {
dst[2*i] = to_hex_digit(s_app_elf_sha256[i] >> 4);
dst[2*i + 1] = to_hex_digit(s_app_elf_sha256[i] & 0xf);
}
dst[2*n] = 0;
return 2*n + 1;
}

View File

@@ -28,21 +28,18 @@
#include "esp_image_format.h"
#include "esp_secure_boot.h"
#include "esp_flash_encrypt.h"
#include "esp_spi_flash.h"
#include "sdkconfig.h"
#include "esp_ota_ops.h"
#include "sys/queue.h"
#include "esp32/rom/crc.h"
#include "rom/queue.h"
#include "rom/crc.h"
#include "soc/dport_reg.h"
#include "esp_log.h"
#include "esp_flash_partitions.h"
#include "bootloader_common.h"
#include "sys/param.h"
#include "esp_system.h"
#include "esp_efuse.h"
#define SUB_TYPE_ID(i) (i & 0x0F)
#define OTA_MAX(a,b) ((a) >= (b) ? (a) : (b))
#define OTA_MIN(a,b) ((a) <= (b) ? (a) : (b))
#define SUB_TYPE_ID(i) (i & 0x0F)
typedef struct ota_ops_entry_ {
uint32_t handle;
@@ -54,10 +51,19 @@ typedef struct ota_ops_entry_ {
LIST_ENTRY(ota_ops_entry_) entries;
} ota_ops_entry_t;
/* OTA selection structure (two copies in the OTA data partition.)
Size of 32 bytes is friendly to flash encryption */
typedef struct {
uint32_t ota_seq;
uint8_t seq_label[24];
uint32_t crc; /* CRC32 of ota_seq field only */
} ota_select;
static LIST_HEAD(ota_ops_entries_head, ota_ops_entry_) s_ota_ops_entries_head =
LIST_HEAD_INITIALIZER(s_ota_ops_entries_head);
static uint32_t s_ota_ops_last_handle = 0;
static ota_select s_ota_select[2];
const static char *TAG = "esp_ota_ops";
@@ -70,56 +76,6 @@ static bool is_ota_partition(const esp_partition_t *p)
&& p->subtype < ESP_PARTITION_SUBTYPE_APP_OTA_MAX);
}
// Read otadata partition and fill array from two otadata structures.
// Also return pointer to otadata info partition.
static const esp_partition_t *read_otadata(esp_ota_select_entry_t *two_otadata)
{
const esp_partition_t *otadata_partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_OTA, NULL);
if (otadata_partition == NULL) {
ESP_LOGE(TAG, "not found otadata");
return NULL;
}
spi_flash_mmap_handle_t ota_data_map;
const void *result = NULL;
esp_err_t err = esp_partition_mmap(otadata_partition, 0, otadata_partition->size, SPI_FLASH_MMAP_DATA, &result, &ota_data_map);
if (err != ESP_OK) {
ESP_LOGE(TAG, "mmap otadata filed. Err=0x%8x", err);
return NULL;
} else {
memcpy(&two_otadata[0], result, sizeof(esp_ota_select_entry_t));
memcpy(&two_otadata[1], result + SPI_FLASH_SEC_SIZE, sizeof(esp_ota_select_entry_t));
spi_flash_munmap(ota_data_map);
}
return otadata_partition;
}
static esp_err_t image_validate(const esp_partition_t *partition, esp_image_load_mode_t load_mode)
{
esp_image_metadata_t data;
const esp_partition_pos_t part_pos = {
.offset = partition->address,
.size = partition->size,
};
if (esp_image_verify(load_mode, &part_pos, &data) != ESP_OK) {
return ESP_ERR_OTA_VALIDATE_FAILED;
}
return ESP_OK;
}
static esp_ota_img_states_t set_new_state_otadata(void)
{
#ifdef CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE
ESP_LOGD(TAG, "Monitoring the first boot of the app is enabled.");
return ESP_OTA_IMG_NEW;
#else
return ESP_OTA_IMG_UNDEFINED;
#endif
}
esp_err_t esp_ota_begin(const esp_partition_t *partition, size_t image_size, esp_ota_handle_t *out_handle)
{
ota_ops_entry_t *new_entry;
@@ -138,27 +94,15 @@ esp_err_t esp_ota_begin(const esp_partition_t *partition, size_t image_size, esp
return ESP_ERR_INVALID_ARG;
}
const esp_partition_t* running_partition = esp_ota_get_running_partition();
if (partition == running_partition) {
if (partition == esp_ota_get_running_partition()) {
return ESP_ERR_OTA_PARTITION_CONFLICT;
}
#ifdef CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE
esp_ota_img_states_t ota_state_running_part;
if (esp_ota_get_state_partition(running_partition, &ota_state_running_part) == ESP_OK) {
if (ota_state_running_part == ESP_OTA_IMG_PENDING_VERIFY) {
ESP_LOGE(TAG, "Running app has not confirmed state (ESP_OTA_IMG_PENDING_VERIFY)");
return ESP_ERR_OTA_ROLLBACK_INVALID_STATE;
}
}
#endif
// If input image size is 0 or OTA_SIZE_UNKNOWN, erase entire partition
if ((image_size == 0) || (image_size == OTA_SIZE_UNKNOWN)) {
ret = esp_partition_erase_range(partition, 0, partition->size);
} else {
const int aligned_erase_size = (image_size + SPI_FLASH_SEC_SIZE - 1) & ~(SPI_FLASH_SEC_SIZE - 1);
ret = esp_partition_erase_range(partition, 0, aligned_erase_size);
ret = esp_partition_erase_range(partition, 0, (image_size / SPI_FLASH_SEC_SIZE + 1) * SPI_FLASH_SEC_SIZE);
}
if (ret != ESP_OK) {
@@ -200,8 +144,9 @@ esp_err_t esp_ota_write(esp_ota_handle_t handle, const void *data, size_t size)
if (it->handle == handle) {
// must erase the partition before writing to it
assert(it->erased_size > 0 && "must erase the partition before writing to it");
if (it->wrote_size == 0 && it->partial_bytes == 0 && size > 0 && data_bytes[0] != ESP_IMAGE_HEADER_MAGIC) {
ESP_LOGE(TAG, "OTA image has invalid magic byte (expected 0xE9, saw 0x%02x)", data_bytes[0]);
if(it->wrote_size == 0 && size > 0 && data_bytes[0] != 0xE9) {
ESP_LOGE(TAG, "OTA image has invalid magic byte (expected 0xE9, saw 0x%02x", data_bytes[0]);
return ESP_ERR_OTA_VALIDATE_FAILED;
}
@@ -211,7 +156,7 @@ esp_err_t esp_ota_write(esp_ota_handle_t handle, const void *data, size_t size)
/* check if we have partially written data from earlier */
if (it->partial_bytes != 0) {
copy_len = MIN(16 - it->partial_bytes, size);
copy_len = OTA_MIN(16 - it->partial_bytes, size);
memcpy(it->partial_data + it->partial_bytes, data_bytes, copy_len);
it->partial_bytes += copy_len;
if (it->partial_bytes != 16) {
@@ -246,13 +191,14 @@ esp_err_t esp_ota_write(esp_ota_handle_t handle, const void *data, size_t size)
}
//if go to here ,means don't find the handle
ESP_LOGE(TAG,"not found the handle");
ESP_LOGE(TAG,"not found the handle")
return ESP_ERR_INVALID_ARG;
}
esp_err_t esp_ota_end(esp_ota_handle_t handle)
{
ota_ops_entry_t *it;
size_t image_size;
esp_err_t ret = ESP_OK;
for (it = LIST_FIRST(&s_ota_ops_entries_head); it != NULL; it = LIST_NEXT(it, entries)) {
@@ -284,36 +230,50 @@ esp_err_t esp_ota_end(esp_ota_handle_t handle)
it->partial_bytes = 0;
}
esp_image_metadata_t data;
const esp_partition_pos_t part_pos = {
.offset = it->part->address,
.size = it->part->size,
};
if (esp_image_verify(ESP_IMAGE_VERIFY, &part_pos, &data) != ESP_OK) {
if (esp_image_basic_verify(it->part->address, true, &image_size) != ESP_OK) {
ret = ESP_ERR_OTA_VALIDATE_FAILED;
goto cleanup;
}
#ifdef CONFIG_SECURE_BOOT_ENABLED
ret = esp_secure_boot_verify_signature(it->part->address, image_size);
if (ret != ESP_OK) {
ret = ESP_ERR_OTA_VALIDATE_FAILED;
goto cleanup;
}
#endif
cleanup:
LIST_REMOVE(it, entries);
free(it);
return ret;
}
static esp_err_t rewrite_ota_seq(esp_ota_select_entry_t *two_otadata, uint32_t seq, uint8_t sec_id, const esp_partition_t *ota_data_partition)
static uint32_t ota_select_crc(const ota_select *s)
{
if (two_otadata == NULL || sec_id > 1) {
return ESP_ERR_INVALID_ARG;
}
return crc32_le(UINT32_MAX, (uint8_t *)&s->ota_seq, 4);
}
two_otadata[sec_id].ota_seq = seq;
two_otadata[sec_id].crc = bootloader_common_ota_select_crc(&two_otadata[sec_id]);
esp_err_t ret = esp_partition_erase_range(ota_data_partition, sec_id * SPI_FLASH_SEC_SIZE, SPI_FLASH_SEC_SIZE);
if (ret != ESP_OK) {
return ret;
static bool ota_select_valid(const ota_select *s)
{
return s->ota_seq != UINT32_MAX && s->crc == ota_select_crc(s);
}
static esp_err_t rewrite_ota_seq(uint32_t seq, uint8_t sec_id, const esp_partition_t *ota_data_partition)
{
esp_err_t ret;
if (sec_id == 0 || sec_id == 1) {
s_ota_select[sec_id].ota_seq = seq;
s_ota_select[sec_id].crc = ota_select_crc(&s_ota_select[sec_id]);
ret = esp_partition_erase_range(ota_data_partition, sec_id * SPI_FLASH_SEC_SIZE, SPI_FLASH_SEC_SIZE);
if (ret != ESP_OK) {
return ret;
} else {
return esp_partition_write(ota_data_partition, SPI_FLASH_SEC_SIZE * sec_id, &s_ota_select[sec_id].ota_seq, sizeof(ota_select));
}
} else {
return esp_partition_write(ota_data_partition, SPI_FLASH_SEC_SIZE * sec_id, &two_otadata[sec_id], sizeof(esp_ota_select_entry_t));
return ESP_ERR_INVALID_ARG;
}
}
@@ -329,166 +289,185 @@ static uint8_t get_ota_partition_count(void)
static esp_err_t esp_rewrite_ota_data(esp_partition_subtype_t subtype)
{
esp_ota_select_entry_t otadata[2];
const esp_partition_t *otadata_partition = read_otadata(otadata);
if (otadata_partition == NULL) {
return ESP_ERR_NOT_FOUND;
}
esp_err_t ret;
const esp_partition_t *find_partition = NULL;
uint16_t ota_app_count = 0;
uint32_t i = 0;
uint32_t seq;
static spi_flash_mmap_memory_t ota_data_map;
const void *result = NULL;
int ota_app_count = get_ota_partition_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);
if (active_otadata != -1) {
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++;
find_partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_OTA, NULL);
if (find_partition != NULL) {
ota_app_count = get_ota_partition_count();
//esp32_idf use two sector for store information about which partition is running
//it defined the two sector as ota data partition,two structure ota_select is saved in the two sector
//named data in first sector as s_ota_select[0], second sector data as s_ota_select[1]
//e.g.
//if s_ota_select[0].ota_seq == s_ota_select[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 s_ota_select[0].ota_seq != 0 and s_ota_select[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 s_ota_select[0].ota_seq = 4, s_ota_select[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 s_ota_select[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
if (SUB_TYPE_ID(subtype) >= ota_app_count) {
return ESP_ERR_INVALID_ARG;
}
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);
ret = esp_partition_mmap(find_partition, 0, find_partition->size, SPI_FLASH_MMAP_DATA, &result, &ota_data_map);
if (ret != ESP_OK) {
result = NULL;
return ret;
} else {
memcpy(&s_ota_select[0], result, sizeof(ota_select));
memcpy(&s_ota_select[1], result + SPI_FLASH_SEC_SIZE, sizeof(ota_select));
spi_flash_munmap(ota_data_map);
}
if (ota_select_valid(&s_ota_select[0]) && ota_select_valid(&s_ota_select[1])) {
seq = OTA_MAX(s_ota_select[0].ota_seq, s_ota_select[1].ota_seq);
while (seq > (SUB_TYPE_ID(subtype) + 1) % ota_app_count + i * ota_app_count) {
i++;
}
if (s_ota_select[0].ota_seq >= s_ota_select[1].ota_seq) {
return rewrite_ota_seq((SUB_TYPE_ID(subtype) + 1) % ota_app_count + i * ota_app_count, 1, find_partition);
} else {
return rewrite_ota_seq((SUB_TYPE_ID(subtype) + 1) % ota_app_count + i * ota_app_count, 0, find_partition);
}
} else if (ota_select_valid(&s_ota_select[0])) {
while (s_ota_select[0].ota_seq > (SUB_TYPE_ID(subtype) + 1) % ota_app_count + i * ota_app_count) {
i++;
}
return rewrite_ota_seq((SUB_TYPE_ID(subtype) + 1) % ota_app_count + i * ota_app_count, 1, find_partition);
} else if (ota_select_valid(&s_ota_select[1])) {
while (s_ota_select[1].ota_seq > (SUB_TYPE_ID(subtype) + 1) % ota_app_count + i * ota_app_count) {
i++;
}
return rewrite_ota_seq((SUB_TYPE_ID(subtype) + 1) % ota_app_count + i * ota_app_count, 0, find_partition);
} else {
/* Both OTA slots are invalid, probably because unformatted... */
return rewrite_ota_seq(SUB_TYPE_ID(subtype) + 1, 0, find_partition);
}
} else {
/* Both OTA slots are invalid, probably because unformatted... */
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);
return ESP_ERR_NOT_FOUND;
}
}
esp_err_t esp_ota_set_boot_partition(const esp_partition_t *partition)
{
size_t image_size;
const esp_partition_t *find_partition = NULL;
if (partition == NULL) {
return ESP_ERR_INVALID_ARG;
}
if (image_validate(partition, ESP_IMAGE_VERIFY) != ESP_OK) {
if (esp_image_basic_verify(partition->address, true, &image_size) != ESP_OK) {
return ESP_ERR_OTA_VALIDATE_FAILED;
}
#ifdef CONFIG_SECURE_BOOT_ENABLED
esp_err_t ret = esp_secure_boot_verify_signature(partition->address, image_size);
if (ret != ESP_OK) {
return ESP_ERR_OTA_VALIDATE_FAILED;
}
#endif
// if set boot partition to factory bin ,just format ota info partition
if (partition->type == ESP_PARTITION_TYPE_APP) {
if (partition->subtype == ESP_PARTITION_SUBTYPE_APP_FACTORY) {
const esp_partition_t *find_partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_OTA, NULL);
find_partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_OTA, NULL);
if (find_partition != NULL) {
return esp_partition_erase_range(find_partition, 0, find_partition->size);
} else {
return ESP_ERR_NOT_FOUND;
}
} else {
#ifdef CONFIG_BOOTLOADER_APP_ANTI_ROLLBACK
esp_app_desc_t partition_app_desc;
esp_err_t err = esp_ota_get_partition_description(partition, &partition_app_desc);
if (err != ESP_OK) {
return err;
// try to find this partition in flash,if not find it ,return error
find_partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_OTA, NULL);
if (find_partition != NULL) {
return esp_rewrite_ota_data(partition->subtype);
} else {
return ESP_ERR_NOT_FOUND;
}
if (esp_efuse_check_secure_version(partition_app_desc.secure_version) == false) {
ESP_LOGE(TAG, "This a new partition can not be booted due to a secure version is lower than stored in efuse. Partition will be erased.");
esp_err_t err = esp_partition_erase_range(partition, 0, partition->size);
if (err != ESP_OK) {
return err;
}
return ESP_ERR_OTA_SMALL_SEC_VER;
}
#endif
return esp_rewrite_ota_data(partition->subtype);
}
} else {
return ESP_ERR_INVALID_ARG;
}
}
static const esp_partition_t *find_default_boot_partition(void)
{
// This logic matches the logic of bootloader get_selected_boot_partition() & load_boot_image().
// Default to factory if present
const esp_partition_t *result = esp_partition_find_first(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_APP_FACTORY, NULL);
if (result != NULL) {
return result;
}
// Try first OTA slot if no factory partition
for (esp_partition_subtype_t s = ESP_PARTITION_SUBTYPE_APP_OTA_MIN; s != ESP_PARTITION_SUBTYPE_APP_OTA_MAX; s++) {
result = esp_partition_find_first(ESP_PARTITION_TYPE_APP, s, NULL);
if (result != NULL) {
return result;
}
}
// Test app slot if present
result = esp_partition_find_first(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_APP_TEST, NULL);
if (result != NULL) {
return result;
}
ESP_LOGE(TAG, "invalid partition table, no app partitions");
return NULL;
}
const esp_partition_t *esp_ota_get_boot_partition(void)
{
esp_ota_select_entry_t otadata[2];
const esp_partition_t *otadata_partition = read_otadata(otadata);
if (otadata_partition == NULL) {
esp_err_t ret;
const esp_partition_t *find_partition = NULL;
static spi_flash_mmap_memory_t ota_data_map;
const void *result = NULL;
uint16_t ota_app_count = 0;
find_partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_OTA, NULL);
if (find_partition == NULL) {
ESP_LOGE(TAG, "not found ota data");
return NULL;
}
int ota_app_count = get_ota_partition_count();
ret = esp_partition_mmap(find_partition, 0, find_partition->size, SPI_FLASH_MMAP_DATA, &result, &ota_data_map);
if (ret != ESP_OK) {
spi_flash_munmap(ota_data_map);
ESP_LOGE(TAG, "mmap ota data filed");
return NULL;
} else {
memcpy(&s_ota_select[0], result, sizeof(ota_select));
memcpy(&s_ota_select[1], result + 0x1000, sizeof(ota_select));
spi_flash_munmap(ota_data_map);
}
ota_app_count = get_ota_partition_count();
ESP_LOGD(TAG, "found ota app max = %d", ota_app_count);
if ((bootloader_common_ota_select_invalid(&otadata[0]) &&
bootloader_common_ota_select_invalid(&otadata[1])) ||
ota_app_count == 0) {
ESP_LOGD(TAG, "finding factory app...");
return find_default_boot_partition();
if (s_ota_select[0].ota_seq == 0xFFFFFFFF && s_ota_select[1].ota_seq == 0xFFFFFFFF) {
ESP_LOGD(TAG, "finding factory app......");
return esp_partition_find_first(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_APP_FACTORY, NULL);
} else if (ota_select_valid(&s_ota_select[0]) && ota_select_valid(&s_ota_select[1])) {
ESP_LOGD(TAG, "finding ota_%d app......", \
ESP_PARTITION_SUBTYPE_APP_OTA_MIN + ((OTA_MAX(s_ota_select[0].ota_seq, s_ota_select[1].ota_seq) - 1) % ota_app_count));
return esp_partition_find_first(ESP_PARTITION_TYPE_APP, \
ESP_PARTITION_SUBTYPE_APP_OTA_MIN + ((OTA_MAX(s_ota_select[0].ota_seq, s_ota_select[1].ota_seq) - 1) % ota_app_count), NULL);
} else if (ota_select_valid(&s_ota_select[0])) {
ESP_LOGD(TAG, "finding ota_%d app......", \
ESP_PARTITION_SUBTYPE_APP_OTA_MIN + (s_ota_select[0].ota_seq - 1) % ota_app_count);
return esp_partition_find_first(ESP_PARTITION_TYPE_APP, \
ESP_PARTITION_SUBTYPE_APP_OTA_MIN + (s_ota_select[0].ota_seq - 1) % ota_app_count, NULL);
} else if (ota_select_valid(&s_ota_select[1])) {
ESP_LOGD(TAG, "finding ota_%d app......", \
ESP_PARTITION_SUBTYPE_APP_OTA_MIN + (s_ota_select[1].ota_seq - 1) % ota_app_count);
return esp_partition_find_first(ESP_PARTITION_TYPE_APP, \
ESP_PARTITION_SUBTYPE_APP_OTA_MIN + (s_ota_select[1].ota_seq - 1) % ota_app_count, NULL);
} else {
int active_otadata = bootloader_common_get_active_otadata(otadata);
if (active_otadata != -1) {
int ota_slot = (otadata[active_otadata].ota_seq - 1) % ota_app_count; // Actual OTA partition selection
ESP_LOGD(TAG, "finding ota_%d app...", ESP_PARTITION_SUBTYPE_APP_OTA_MIN + ota_slot);
return esp_partition_find_first(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_APP_OTA_MIN + ota_slot, NULL);
} else {
ESP_LOGE(TAG, "ota data invalid, no current app. Assuming factory");
return find_default_boot_partition();
}
ESP_LOGE(TAG, "ota data invalid, no current app. Assuming factory");
return esp_partition_find_first(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_APP_FACTORY, NULL);
}
}
const esp_partition_t* esp_ota_get_running_partition(void)
{
static const esp_partition_t *curr_partition = NULL;
/*
* Currently running partition is unlikely to change across reset cycle,
* so it can be cached here, and avoid lookup on every flash write operation.
*/
if (curr_partition != NULL) {
return curr_partition;
}
/* Find the flash address of this exact function. By definition that is part
of the currently running firmware. Then find the enclosing partition. */
size_t phys_offs = spi_flash_cache2phys(esp_ota_get_running_partition);
assert (phys_offs != SPI_FLASH_CACHE2PHYS_FAIL); /* indicates cache2phys lookup is buggy */
@@ -502,7 +481,6 @@ const esp_partition_t* esp_ota_get_running_partition(void)
const esp_partition_t *p = esp_partition_get(it);
if (p->address <= phys_offs && p->address + p->size > phys_offs) {
esp_partition_iterator_release(it);
curr_partition = p;
return p;
}
it = esp_partition_next(it);
@@ -559,265 +537,3 @@ const esp_partition_t* esp_ota_get_next_update_partition(const esp_partition_t *
return default_ota;
}
esp_err_t esp_ota_get_partition_description(const esp_partition_t *partition, esp_app_desc_t *app_desc)
{
if (partition == NULL || app_desc == NULL) {
return ESP_ERR_INVALID_ARG;
}
if(partition->type != ESP_PARTITION_TYPE_APP) {
return ESP_ERR_NOT_SUPPORTED;
}
esp_err_t err = esp_partition_read(partition, sizeof(esp_image_header_t) + sizeof(esp_image_segment_header_t), app_desc, sizeof(esp_app_desc_t));
if (err != ESP_OK) {
return err;
}
if (app_desc->magic_word != ESP_APP_DESC_MAGIC_WORD) {
return ESP_ERR_NOT_FOUND;
}
return ESP_OK;
}
#ifdef CONFIG_BOOTLOADER_APP_ANTI_ROLLBACK
static esp_err_t esp_ota_set_anti_rollback(void) {
const esp_app_desc_t *app_desc = esp_ota_get_app_description();
return esp_efuse_update_secure_version(app_desc->secure_version);
}
#endif
// Checks applications on the slots which can be booted in case of rollback.
// Returns true if the slots have at least one app (except the running app).
bool esp_ota_check_rollback_is_possible(void)
{
esp_ota_select_entry_t otadata[2];
if (read_otadata(otadata) == NULL) {
return false;
}
int ota_app_count = get_ota_partition_count();
if (ota_app_count == 0) {
return false;
}
bool valid_otadata[2];
valid_otadata[0] = bootloader_common_ota_select_valid(&otadata[0]);
valid_otadata[1] = bootloader_common_ota_select_valid(&otadata[1]);
int active_ota = bootloader_common_select_otadata(otadata, valid_otadata, true);
if (active_ota == -1) {
return false;
}
int last_active_ota = (~active_ota)&1;
const esp_partition_t *partition = NULL;
#ifndef CONFIG_BOOTLOADER_APP_ANTI_ROLLBACK
if (valid_otadata[last_active_ota] == false) {
partition = esp_partition_find_first(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_APP_FACTORY, NULL);
if (partition != NULL) {
if(image_validate(partition, ESP_IMAGE_VERIFY_SILENT) == ESP_OK) {
return true;
}
}
}
#endif
if (valid_otadata[last_active_ota] == true) {
int slot = (otadata[last_active_ota].ota_seq - 1) % ota_app_count;
partition = esp_partition_find_first(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_APP_OTA_MIN + slot, NULL);
if (partition != NULL) {
if(image_validate(partition, ESP_IMAGE_VERIFY_SILENT) == ESP_OK) {
#ifdef CONFIG_BOOTLOADER_APP_ANTI_ROLLBACK
esp_app_desc_t app_desc;
if (esp_ota_get_partition_description(partition, &app_desc) == ESP_OK &&
esp_efuse_check_secure_version(app_desc.secure_version) == true) {
return true;
}
#else
return true;
#endif
}
}
}
return false;
}
// if valid == false - will done rollback with reboot. After reboot will boot previous OTA[x] or Factory partition.
// if valid == true - it confirm that current OTA[x] is workable. Reboot will not happen.
static esp_err_t esp_ota_current_ota_is_workable(bool valid)
{
esp_ota_select_entry_t otadata[2];
const esp_partition_t *otadata_partition = read_otadata(otadata);
if (otadata_partition == NULL) {
return ESP_ERR_NOT_FOUND;
}
int active_otadata = bootloader_common_get_active_otadata(otadata);
if (active_otadata != -1 && get_ota_partition_count() != 0) {
if (valid == true && otadata[active_otadata].ota_state != ESP_OTA_IMG_VALID) {
otadata[active_otadata].ota_state = ESP_OTA_IMG_VALID;
ESP_LOGD(TAG, "OTA[current] partition is marked as VALID");
esp_err_t err = rewrite_ota_seq(otadata, otadata[active_otadata].ota_seq, active_otadata, otadata_partition);
#ifdef CONFIG_BOOTLOADER_APP_ANTI_ROLLBACK
if (err == ESP_OK) {
return esp_ota_set_anti_rollback();
}
#endif
return err;
} else if (valid == false) {
if (esp_ota_check_rollback_is_possible() == false) {
ESP_LOGE(TAG, "Rollback is not possible, do not have any suitable apps in slots");
return ESP_ERR_OTA_ROLLBACK_FAILED;
}
ESP_LOGD(TAG, "OTA[current] partition is marked as INVALID");
otadata[active_otadata].ota_state = ESP_OTA_IMG_INVALID;
esp_err_t err = rewrite_ota_seq(otadata, otadata[active_otadata].ota_seq, active_otadata, otadata_partition);
if (err != ESP_OK) {
return err;
}
ESP_LOGI(TAG, "Rollback to previously worked partition. Restart.");
esp_restart();
}
} else {
ESP_LOGE(TAG, "Running firmware is factory");
return ESP_FAIL;
}
return ESP_OK;
}
esp_err_t esp_ota_mark_app_valid_cancel_rollback()
{
return esp_ota_current_ota_is_workable(true);
}
esp_err_t esp_ota_mark_app_invalid_rollback_and_reboot()
{
return esp_ota_current_ota_is_workable(false);
}
static bool check_invalid_otadata (const esp_ota_select_entry_t *s) {
return s->ota_seq != UINT32_MAX &&
s->crc == bootloader_common_ota_select_crc(s) &&
(s->ota_state == ESP_OTA_IMG_INVALID ||
s->ota_state == ESP_OTA_IMG_ABORTED);
}
static int get_last_invalid_otadata(const esp_ota_select_entry_t *two_otadata)
{
bool invalid_otadata[2];
invalid_otadata[0] = check_invalid_otadata(&two_otadata[0]);
invalid_otadata[1] = check_invalid_otadata(&two_otadata[1]);
int num_invalid_otadata = bootloader_common_select_otadata(two_otadata, invalid_otadata, false);
ESP_LOGD(TAG, "Invalid otadata[%d]", num_invalid_otadata);
return num_invalid_otadata;
}
const esp_partition_t* esp_ota_get_last_invalid_partition()
{
esp_ota_select_entry_t otadata[2];
if (read_otadata(otadata) == NULL) {
return NULL;
}
int invalid_otadata = get_last_invalid_otadata(otadata);
int ota_app_count = get_ota_partition_count();
if (invalid_otadata != -1 && ota_app_count != 0) {
int ota_slot = (otadata[invalid_otadata].ota_seq - 1) % ota_app_count;
ESP_LOGD(TAG, "Find invalid ota_%d app", ESP_PARTITION_SUBTYPE_APP_OTA_MIN + ota_slot);
const esp_partition_t* invalid_partition = esp_partition_find_first(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_APP_OTA_MIN + ota_slot, NULL);
if (invalid_partition != NULL) {
if (image_validate(invalid_partition, ESP_IMAGE_VERIFY_SILENT) != ESP_OK) {
ESP_LOGD(TAG, "Last invalid partition has corrupted app");
return NULL;
}
}
return invalid_partition;
}
return NULL;
}
esp_err_t esp_ota_get_state_partition(const esp_partition_t *partition, esp_ota_img_states_t *ota_state)
{
if (partition == NULL || ota_state == NULL) {
return ESP_ERR_INVALID_ARG;
}
if (!is_ota_partition(partition)) {
return ESP_ERR_NOT_SUPPORTED;
}
esp_ota_select_entry_t otadata[2];
int ota_app_count = get_ota_partition_count();
if (read_otadata(otadata) == NULL || ota_app_count == 0) {
return ESP_ERR_NOT_FOUND;
}
int req_ota_slot = partition->subtype - ESP_PARTITION_SUBTYPE_APP_OTA_MIN;
bool not_found = true;
for (int i = 0; i < 2; ++i) {
int ota_slot = (otadata[i].ota_seq - 1) % ota_app_count;
if (ota_slot == req_ota_slot && otadata[i].crc == bootloader_common_ota_select_crc(&otadata[i])) {
*ota_state = otadata[i].ota_state;
not_found = false;
break;
}
}
if (not_found) {
return ESP_ERR_NOT_FOUND;
}
return ESP_OK;
}
esp_err_t esp_ota_erase_last_boot_app_partition(void)
{
esp_ota_select_entry_t otadata[2];
const esp_partition_t* ota_data_partition = read_otadata(otadata);
if (ota_data_partition == NULL) {
return ESP_FAIL;
}
int active_otadata = bootloader_common_get_active_otadata(otadata);
int ota_app_count = get_ota_partition_count();
if (active_otadata == -1 || ota_app_count == 0) {
return ESP_FAIL;
}
int inactive_otadata = (~active_otadata)&1;
if (otadata[inactive_otadata].ota_seq == UINT32_MAX || otadata[inactive_otadata].crc != bootloader_common_ota_select_crc(&otadata[inactive_otadata])) {
return ESP_FAIL;
}
int ota_slot = (otadata[inactive_otadata].ota_seq - 1) % ota_app_count; // Actual OTA partition selection
ESP_LOGD(TAG, "finding last_boot_app_partition ota_%d app...", ESP_PARTITION_SUBTYPE_APP_OTA_MIN + ota_slot);
const esp_partition_t* last_boot_app_partition_from_otadata = esp_partition_find_first(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_APP_OTA_MIN + ota_slot, NULL);
if (last_boot_app_partition_from_otadata == NULL) {
return ESP_FAIL;
}
const esp_partition_t* running_partition = esp_ota_get_running_partition();
if (running_partition == NULL || last_boot_app_partition_from_otadata == running_partition) {
return ESP_FAIL;
}
esp_err_t err = esp_partition_erase_range(last_boot_app_partition_from_otadata, 0, last_boot_app_partition_from_otadata->size);
if (err != ESP_OK) {
return err;
}
int sec_id = inactive_otadata;
err = esp_partition_erase_range(ota_data_partition, sec_id * SPI_FLASH_SEC_SIZE, SPI_FLASH_SEC_SIZE);
if (err != ESP_OK) {
return err;
}
return ESP_OK;
}

123
components/app_update/include/esp_ota_ops.h Normal file → Executable file
View File

@@ -20,8 +20,7 @@
#include <stddef.h>
#include "esp_err.h"
#include "esp_partition.h"
#include "esp_image_format.h"
#include "esp_flash_partitions.h"
#include "esp_spi_flash.h"
#ifdef __cplusplus
extern "C"
@@ -34,10 +33,6 @@ extern "C"
#define ESP_ERR_OTA_PARTITION_CONFLICT (ESP_ERR_OTA_BASE + 0x01) /*!< Error if request was to write or erase the current running partition */
#define ESP_ERR_OTA_SELECT_INFO_INVALID (ESP_ERR_OTA_BASE + 0x02) /*!< Error if OTA data partition contains invalid content */
#define ESP_ERR_OTA_VALIDATE_FAILED (ESP_ERR_OTA_BASE + 0x03) /*!< Error if OTA app image is invalid */
#define ESP_ERR_OTA_SMALL_SEC_VER (ESP_ERR_OTA_BASE + 0x04) /*!< Error if the firmware has a secure version less than the running firmware. */
#define ESP_ERR_OTA_ROLLBACK_FAILED (ESP_ERR_OTA_BASE + 0x05) /*!< Error if flash does not have valid firmware in passive partition and hence rollback is not possible */
#define ESP_ERR_OTA_ROLLBACK_INVALID_STATE (ESP_ERR_OTA_BASE + 0x06) /*!< Error if current active firmware is still marked in pending validation state (ESP_OTA_IMG_PENDING_VERIFY), essentially first boot of firmware image post upgrade and hence firmware upgrade is not possible */
/**
* @brief Opaque handle for an application OTA update
@@ -47,24 +42,6 @@ extern "C"
*/
typedef uint32_t esp_ota_handle_t;
/**
* @brief Return esp_app_desc structure. This structure includes app version.
*
* Return description for running app.
* @return Pointer to esp_app_desc structure.
*/
const esp_app_desc_t *esp_ota_get_app_description(void);
/**
* @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.
* @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);
/**
* @brief Commence an OTA update writing to the specified partition.
@@ -76,10 +53,6 @@ int esp_ota_get_app_elf_sha256(char* dst, size_t size);
* On success, this function allocates memory that remains in use
* until esp_ota_end() is called with the returned handle.
*
* Note: If the rollback option is enabled and the running application has the ESP_OTA_IMG_PENDING_VERIFY state then
* it will lead to the ESP_ERR_OTA_ROLLBACK_INVALID_STATE error. Confirm the running app before to run download a new app,
* use esp_ota_mark_app_valid_cancel_rollback() function for it (this should be done as early as possible when you first download a new application).
*
* @param partition Pointer to info for partition which will receive the OTA update. Required.
* @param image_size Size of new OTA app image. Partition will be erased in order to receive this size of image. If 0 or OTA_SIZE_UNKNOWN, the entire partition is erased.
* @param out_handle On success, returns a handle which should be used for subsequent esp_ota_write() and esp_ota_end() calls.
@@ -93,7 +66,6 @@ int esp_ota_get_app_elf_sha256(char* dst, size_t size);
* - ESP_ERR_OTA_SELECT_INFO_INVALID: The OTA data partition contains invalid data.
* - ESP_ERR_INVALID_SIZE: Partition doesn't fit in configured flash size.
* - ESP_ERR_FLASH_OP_TIMEOUT or ESP_ERR_FLASH_OP_FAIL: Flash write failed.
* - ESP_ERR_OTA_ROLLBACK_INVALID_STATE: If the running app has not confirmed state. Before performing an update, the application must be valid.
*/
esp_err_t esp_ota_begin(const esp_partition_t* partition, size_t image_size, esp_ota_handle_t* out_handle);
@@ -154,17 +126,10 @@ esp_err_t esp_ota_set_boot_partition(const esp_partition_t* partition);
*
* If esp_ota_set_boot_partition() has been called, the partition which was set by that function will be returned.
*
* If esp_ota_set_boot_partition() has not been called, the result is usually the same as esp_ota_get_running_partition().
* The two results are not equal if the configured boot partition does not contain a valid app (meaning that the running partition
* will be an app that the bootloader chose via fallback).
* If esp_ota_set_boot_partition() has not been called, the result is
* equivalent to esp_ota_get_running_partition().
*
* If the OTA data partition is not present or not valid then the result is the first app partition found in the
* partition table. In priority order, this means: the factory app, the first OTA app slot, or the test app partition.
*
* Note that there is no guarantee the returned partition is a valid app. Use esp_image_verify(ESP_IMAGE_VERIFY, ...) to verify if the
* returned partition contains a bootable image.
*
* @return Pointer to info for partition structure, or NULL if partition table is invalid or a flash read operation failed. Any returned pointer is valid for the lifetime of the application.
* @return Pointer to info for partition structure, or NULL if no partition is found or flash read operation failed. Returned pointer is valid for the lifetime of the application.
*/
const esp_partition_t* esp_ota_get_boot_partition(void);
@@ -177,9 +142,6 @@ const esp_partition_t* esp_ota_get_boot_partition(void);
* esp_ota_set_boot_partition(). Only the app whose code is currently
* running will have its partition information returned.
*
* The partition returned by this function may also differ from esp_ota_get_boot_partition() if the configured boot
* partition is somehow invalid, and the bootloader fell back to a different app partition at boot.
*
* @return Pointer to info for partition structure, or NULL if no partition is found or flash read operation failed. Returned pointer is valid for the lifetime of the application.
*/
const esp_partition_t* esp_ota_get_running_partition(void);
@@ -199,83 +161,6 @@ const esp_partition_t* esp_ota_get_running_partition(void);
*/
const esp_partition_t* esp_ota_get_next_update_partition(const esp_partition_t *start_from);
/**
* @brief Returns esp_app_desc structure for app partition. This structure includes app version.
*
* Returns a description for the requested app partition.
* @param[in] partition Pointer to app partition. (only app partition)
* @param[out] app_desc Structure of info about app.
* @return
* - ESP_OK Successful.
* - ESP_ERR_NOT_FOUND app_desc structure is not found. Magic word is incorrect.
* - ESP_ERR_NOT_SUPPORTED Partition is not application.
* - ESP_ERR_INVALID_ARG Arguments is NULL or if partition's offset exceeds partition size.
* - ESP_ERR_INVALID_SIZE Read would go out of bounds of the partition.
* - or one of error codes from lower-level flash driver.
*/
esp_err_t esp_ota_get_partition_description(const esp_partition_t *partition, esp_app_desc_t *app_desc);
/**
* @brief This function is called to indicate that the running app is working well.
*
* @return
* - ESP_OK: if successful.
*/
esp_err_t esp_ota_mark_app_valid_cancel_rollback();
/**
* @brief This function is called to roll back to the previously workable app with reboot.
*
* If rollback is successful then device will reset else API will return with error code.
* Checks applications on a flash drive that can be booted in case of rollback.
* If the flash does not have at least one app (except the running app) then rollback is not possible.
* @return
* - ESP_FAIL: if not successful.
* - ESP_ERR_OTA_ROLLBACK_FAILED: The rollback is not possible due to flash does not have any apps.
*/
esp_err_t esp_ota_mark_app_invalid_rollback_and_reboot();
/**
* @brief Returns last partition with invalid state (ESP_OTA_IMG_INVALID or ESP_OTA_IMG_ABORTED).
*
* @return partition.
*/
const esp_partition_t* esp_ota_get_last_invalid_partition();
/**
* @brief Returns state for given partition.
*
* @param[in] partition Pointer to partition.
* @param[out] ota_state state of partition (if this partition has a record in otadata).
* @return
* - ESP_OK: Successful.
* - ESP_ERR_INVALID_ARG: partition or ota_state arguments were NULL.
* - ESP_ERR_NOT_SUPPORTED: partition is not ota.
* - ESP_ERR_NOT_FOUND: Partition table does not have otadata or state was not found for given partition.
*/
esp_err_t esp_ota_get_state_partition(const esp_partition_t *partition, esp_ota_img_states_t *ota_state);
/**
* @brief Erase previous boot app partition and corresponding otadata select for this partition.
*
* When current app is marked to as valid then you can erase previous app partition.
* @return
* - ESP_OK: Successful, otherwise ESP_ERR.
*/
esp_err_t esp_ota_erase_last_boot_app_partition(void);
/**
* @brief Checks applications on the slots which can be booted in case of rollback.
*
* These applications should be valid (marked in otadata as not UNDEFINED, INVALID or ABORTED and crc is good) and be able booted,
* and secure_version of app >= secure_version of efuse (if anti-rollback is enabled).
*
* @return
* - True: Returns true if the slots have at least one app (except the running app).
* - False: The rollback is not possible.
*/
bool esp_ota_check_rollback_is_possible(void);
#ifdef __cplusplus
}
#endif

View File

@@ -1,392 +0,0 @@
#!/usr/bin/env python
#
# otatool is used to perform ota-level operations - flashing ota partition
# erasing ota partition and switching ota partition
#
# Copyright 2018 Espressif Systems (Shanghai) PTE LTD
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http:#www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from __future__ import print_function, division
import argparse
import os
import sys
import binascii
import tempfile
import collections
import struct
try:
from parttool import PartitionName, PartitionType, ParttoolTarget, PARTITION_TABLE_OFFSET
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 PartitionName, PartitionType, ParttoolTarget, PARTITION_TABLE_OFFSET
__version__ = '2.0'
SPI_FLASH_SEC_SIZE = 0x2000
quiet = False
def status(msg):
if not quiet:
print(msg)
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)
self.spi_flash_sec_size = spi_flash_sec_size
temp_file = tempfile.NamedTemporaryFile(delete=False)
temp_file.close()
try:
self.target.read_partition(OtatoolTarget.OTADATA_PARTITION, temp_file.name)
with open(temp_file.name, "rb") as f:
self.otadata = f.read()
except Exception:
self.otadata = None
finally:
os.unlink(temp_file.name)
def _check_otadata_partition(self):
if not self.otadata:
raise Exception("No otadata partition found")
def erase_otadata(self):
self._check_otadata_partition()
self.target.erase_partition(OtatoolTarget.OTADATA_PARTITION)
def _get_otadata_info(self):
info = []
otadata_info = collections.namedtuple("otadata_info", "seq crc")
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 = struct.unpack('>I', seq)
crc = struct.unpack('>I', crc)
info.append(otadata_info(seq[0], crc[0]))
return info
def _get_partition_id_from_ota_id(self, ota_id):
if isinstance(ota_id, int):
return PartitionType("app", "ota_" + str(ota_id))
else:
return PartitionName(ota_id)
def switch_ota_partition(self, ota_id):
self._check_otadata_partition()
sys.path.append(PARTTOOL_DIR)
import gen_esp32part as gen
def is_otadata_info_valid(status):
seq = status.seq % (1 << 32)
crc = hex(binascii.crc32(struct.pack("I", seq), 0xFFFFFFFF) % (1 << 32))
return seq < (int('0xFFFFFFFF', 16) % (1 << 32)) and status.crc == crc
partition_table = self.target.partition_table
ota_partitions = list()
for i in range(gen.NUM_PARTITION_SUBTYPE_APP_OTA):
ota_partition = filter(lambda p: p.subtype == (gen.MIN_PARTITION_SUBTYPE_APP_OTA + i), partition_table)
try:
ota_partitions.append(list(ota_partition)[0])
except IndexError:
break
ota_partitions = sorted(ota_partitions, key=lambda p: p.subtype)
if not ota_partitions:
raise Exception("No ota app partitions found")
# Look for the app partition to switch to
ota_partition_next = None
try:
if isinstance(ota_id, int):
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)
ota_partition_next = list(ota_partition_next)[0]
except IndexError:
raise Exception("Partition to switch to not found")
otadata_info = self._get_otadata_info()
# Find the copy to base the computation for ota sequence number on
otadata_compute_base = -1
# Both are valid, take the max as computation base
if is_otadata_info_valid(otadata_info[0]) and is_otadata_info_valid(otadata_info[1]):
if otadata_info[0].seq >= otadata_info[1].seq:
otadata_compute_base = 0
else:
otadata_compute_base = 1
# Only one copy is valid, use that
elif is_otadata_info_valid(otadata_info[0]):
otadata_compute_base = 0
elif is_otadata_info_valid(otadata_info[1]):
otadata_compute_base = 1
# Both are invalid (could be initial state - all 0xFF's)
else:
pass
ota_seq_next = 0
ota_partitions_num = len(ota_partitions)
target_seq = (ota_partition_next.subtype & 0x0F) + 1
# Find the next ota sequence number
if otadata_compute_base == 0 or otadata_compute_base == 1:
base_seq = otadata_info[otadata_compute_base].seq % (1 << 32)
i = 0
while base_seq > target_seq % ota_partitions_num + i * ota_partitions_num:
i += 1
ota_seq_next = target_seq % ota_partitions_num + i * ota_partitions_num
else:
ota_seq_next = target_seq
# Create binary data from computed values
ota_seq_next = struct.pack("I", ota_seq_next)
ota_seq_crc_next = binascii.crc32(ota_seq_next, 0xFFFFFFFF) % (1 << 32)
ota_seq_crc_next = struct.pack("I", ota_seq_crc_next)
temp_file = tempfile.NamedTemporaryFile(delete=False)
temp_file.close()
try:
with open(temp_file.name, "wb") as otadata_next_file:
start = (1 if otadata_compute_base == 0 else 0) * (self.spi_flash_sec_size >> 1)
otadata_next_file.write(self.otadata)
otadata_next_file.seek(start)
otadata_next_file.write(ota_seq_next)
otadata_next_file.seek(start + 28)
otadata_next_file.write(ota_seq_crc_next)
otadata_next_file.flush()
self.target.write_partition(OtatoolTarget.OTADATA_PARTITION, temp_file.name)
finally:
os.unlink(temp_file.name)
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):
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))
def _read_otadata(target):
target._check_otadata_partition()
otadata_info = target._get_otadata_info()
print(" {:8s} \t {:8s} | \t {:8s} \t {:8s}".format("OTA_SEQ", "CRC", "OTA_SEQ", "CRC"))
print("Firmware: 0x{:8x} \t0x{:8x} | \t0x{:8x} \t 0x{:8x}".format(otadata_info[0].seq, otadata_info[0].crc,
otadata_info[1].seq, otadata_info[1].crc))
def _erase_otadata(target):
target.erase_otadata()
status("Erased ota_data partition contents")
def _switch_ota_partition(target, ota_id):
target.switch_ota_partition(ota_id)
def _read_ota_partition(target, ota_id, output):
target.read_ota_partition(ota_id, output)
status("Read ota partition contents to file {}".format(output))
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):
target.erase_ota_partition(ota_id)
status("Erased contents of ota partition")
def main():
if sys.version_info[0] < 3:
print("WARNING: Support for Python 2 is deprecated and will be removed in future versions.", file=sys.stderr)
elif sys.version_info[0] == 3 and sys.version_info[1] < 6:
print("WARNING: Python 3 versions older than 3.6 are not supported.", file=sys.stderr)
global quiet
parser = argparse.ArgumentParser("ESP-IDF OTA Partitions Tool")
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="+")
# 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.
parser.add_argument("--port", "-p", help="port where the device to read the partition table from is attached")
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-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")
spi_flash_sec_size = argparse.ArgumentParser(add_help=False)
spi_flash_sec_size.add_argument("--spi-flash-sec-size", help="value of SPI_FLASH_SEC_SIZE macro", type=str)
# Specify the supported operations
subparsers.add_parser("read_otadata", help="read otadata partition", parents=[spi_flash_sec_size])
subparsers.add_parser("erase_otadata", help="erase otadata partition")
slot_or_name_parser = argparse.ArgumentParser(add_help=False)
slot_or_name_parser_args = slot_or_name_parser.add_mutually_exclusive_group()
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])
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")
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])
args = parser.parse_args()
quiet = args.quiet
# No operation specified, display help and exit
if args.operation is None:
if not quiet:
parser.print_help()
sys.exit(1)
target_args = {}
if args.port:
target_args["port"] = args.port
if args.partition_table_file:
target_args["partition_table_file"] = args.partition_table_file
if args.partition_table_offset:
target_args["partition_table_offset"] = int(args.partition_table_offset, 0)
try:
if args.spi_flash_sec_size:
target_args["spi_flash_sec_size"] = int(args.spi_flash_sec_size, 0)
except AttributeError:
pass
if args.esptool_args:
target_args["esptool_args"] = args.esptool_args
if args.esptool_write_args:
target_args["esptool_write_args"] = args.esptool_write_args
if args.esptool_read_args:
target_args["esptool_read_args"] = args.esptool_read_args
if args.esptool_erase_args:
target_args["esptool_erase_args"] = args.esptool_erase_args
if args.baud:
target_args["baud"] = args.baud
target = OtatoolTarget(**target_args)
# Create the operation table and execute the operation
common_args = {'target':target}
ota_id = []
try:
if args.name is not None:
ota_id = ["name"]
else:
if args.slot is not None:
ota_id = ["slot"]
except AttributeError:
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)
}
(op, op_args) = otatool_ops[args.operation]
for op_arg in op_args:
common_args.update({op_arg:vars(args)[op_arg]})
try:
common_args['ota_id'] = common_args.pop('name')
except KeyError:
try:
common_args['ota_id'] = common_args.pop('slot')
except KeyError:
pass
if quiet:
# If exceptions occur, suppress and exit quietly
try:
op(**common_args)
except Exception:
sys.exit(2)
else:
op(**common_args)
if __name__ == '__main__':
main()

View File

@@ -1,3 +0,0 @@
idf_component_register(SRC_DIRS "."
INCLUDE_DIRS "."
REQUIRES unity test_utils app_update bootloader_support nvs_flash)

View File

@@ -1,50 +0,0 @@
#include <string.h>
#include "esp_ota_ops.h"
#include "unity.h"
TEST_CASE("esp_ota_get_app_elf_sha256 test", "[esp_app_desc]")
{
const int sha256_hex_len = CONFIG_APP_RETRIEVE_LEN_ELF_SHA;
char dst[sha256_hex_len + 2];
const char fill = 0xcc;
int res;
size_t len;
char ref_sha256[sha256_hex_len + 1];
const esp_app_desc_t* desc = esp_ota_get_app_description();
for (int i = 0; i < sizeof(ref_sha256) / 2; ++i) {
snprintf(ref_sha256 + 2*i, 3, "%02x", desc->app_elf_sha256[i]);
}
ref_sha256[sha256_hex_len] = 0;
printf("Ref: %s\n", ref_sha256);
memset(dst, fill, sizeof(dst));
len = sizeof(dst);
res = esp_ota_get_app_elf_sha256(dst, len);
printf("%d: %s (%d)\n", len, dst, res);
TEST_ASSERT_EQUAL(sha256_hex_len + 1, res);
TEST_ASSERT_EQUAL(0, memcmp(dst, ref_sha256, res - 1));
TEST_ASSERT_EQUAL_HEX(0, dst[sha256_hex_len]);
TEST_ASSERT_EQUAL_HEX(fill, dst[sha256_hex_len + 1]);
memset(dst, fill, sizeof(dst));
len = 9;
res = esp_ota_get_app_elf_sha256(dst, len);
printf("%d: %s (%d)\n", len, dst, res);
TEST_ASSERT_EQUAL(9, res);
TEST_ASSERT_EQUAL(0, memcmp(dst, ref_sha256, res - 1));
TEST_ASSERT_EQUAL_HEX(0, dst[8]);
TEST_ASSERT_EQUAL_HEX(fill, dst[9]);
memset(dst, fill, sizeof(dst));
len = 8;
res = esp_ota_get_app_elf_sha256(dst, len);
printf("%d: %s (%d)\n", len, dst, res);
// should output even number of characters plus '\0'
TEST_ASSERT_EQUAL(7, res);
TEST_ASSERT_EQUAL(0, memcmp(dst, ref_sha256, res - 1));
TEST_ASSERT_EQUAL_HEX(0, dst[6]);
TEST_ASSERT_EQUAL_HEX(fill, dst[7]);
TEST_ASSERT_EQUAL_HEX(fill, dst[8]);
}

View File

@@ -8,7 +8,7 @@
#include <unity.h>
#include <test_utils.h>
#include <esp_ota_ops.h>
#include "bootloader_common.h"
/* These OTA tests currently don't assume an OTA partition exists
on the device, so they're a bit limited
@@ -84,26 +84,3 @@ TEST_CASE("esp_ota_get_next_update_partition logic", "[ota]")
TEST_ASSERT_EQUAL_PTR(ota_0, p);
}
TEST_CASE("esp_ota_get_partition_description ", "[ota]")
{
const esp_partition_t *running = esp_ota_get_running_partition();
TEST_ASSERT_NOT_NULL(running);
esp_app_desc_t app_desc1, app_desc2;
TEST_ESP_OK(esp_ota_get_partition_description(running, &app_desc1));
const esp_partition_pos_t running_pos = {
.offset = running->address,
.size = running->size
};
TEST_ESP_OK(bootloader_common_get_partition_description(&running_pos, &app_desc2));
TEST_ASSERT_EQUAL_MEMORY_MESSAGE((uint8_t *)&app_desc1, (uint8_t *)&app_desc2, sizeof(app_desc1), "must be the same");
const esp_partition_t *not_app = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_OTA, NULL);
TEST_ASSERT_NOT_NULL(not_app);
TEST_ESP_ERR(ESP_ERR_NOT_SUPPORTED, esp_ota_get_partition_description(not_app, &app_desc1));
const esp_partition_pos_t not_app_pos = {
.offset = not_app->address,
.size = not_app->size
};
TEST_ESP_ERR(ESP_ERR_NOT_FOUND, bootloader_common_get_partition_description(&not_app_pos, &app_desc1));
}

View File

@@ -1,733 +0,0 @@
/*
* Tests for switching between partitions: factory, OTAx, test.
*/
#include <esp_types.h>
#include <stdio.h>
#include "string.h"
#include "sdkconfig.h"
#include "esp32/rom/spi_flash.h"
#include "esp32/rom/rtc.h"
#include "esp32/rom/ets_sys.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"
#include "freertos/queue.h"
#include "freertos/xtensa_api.h"
#include "unity.h"
#include "bootloader_common.h"
#include "../include_bootloader/bootloader_flash.h"
#include "esp_log.h"
#include "esp_ota_ops.h"
#include "esp_partition.h"
#include "esp_flash_partitions.h"
#include "esp_image_format.h"
#include "nvs_flash.h"
#include "driver/gpio.h"
#include "esp_sleep.h"
RTC_DATA_ATTR static int boot_count = 0;
static const char *TAG = "ota_test";
/* @brief Copies a current app to next partition using handle.
*
* @param[in] update_handle - Handle of API ota.
* @param[in] cur_app - Current app.
*/
static void copy_app_partition(esp_ota_handle_t update_handle, const esp_partition_t *curr_app)
{
const void *partition_bin = NULL;
spi_flash_mmap_handle_t data_map;
TEST_ESP_OK(esp_partition_mmap(curr_app, 0, curr_app->size, SPI_FLASH_MMAP_DATA, &partition_bin, &data_map));
TEST_ESP_OK(esp_ota_write(update_handle, (const void *)partition_bin, curr_app->size));
spi_flash_munmap(data_map);
}
#if defined(CONFIG_BOOTLOADER_FACTORY_RESET) || defined(CONFIG_BOOTLOADER_APP_TEST)
/* @brief Copies partition from source partition to destination partition.
*
* Partitions can be of any types and subtypes.
* @param[in] dst_partition - Destination partition
* @param[in] src_partition - Source partition
*/
static void copy_partition(const esp_partition_t *dst_partition, const esp_partition_t *src_partition)
{
const void *partition_bin = NULL;
spi_flash_mmap_handle_t data_map;
TEST_ESP_OK(esp_partition_mmap(src_partition, 0, src_partition->size, SPI_FLASH_MMAP_DATA, &partition_bin, &data_map));
TEST_ESP_OK(esp_partition_erase_range(dst_partition, 0, dst_partition->size));
TEST_ESP_OK(esp_partition_write(dst_partition, 0, (const void *)partition_bin, dst_partition->size));
spi_flash_munmap(data_map);
}
#endif
/* @brief Get the next partition of OTA for the update.
*
* @return The next partition of OTA(OTA0-15).
*/
static const esp_partition_t * get_next_update_partition(void)
{
const esp_partition_t *update_partition = esp_ota_get_next_update_partition(NULL);
TEST_ASSERT_NOT_EQUAL(NULL, update_partition);
ESP_LOGI(TAG, "Writing to partition subtype %d at offset 0x%x", update_partition->subtype, update_partition->address);
return update_partition;
}
/* @brief Copies a current app to next partition (OTA0-15) and then configure OTA data for a new boot partition.
*
* @param[in] cur_app_partition - Current app.
* @param[in] next_app_partition - Next app for boot.
*/
static void copy_current_app_to_next_part(const esp_partition_t *cur_app_partition, const esp_partition_t *next_app_partition)
{
esp_ota_get_next_update_partition(NULL);
TEST_ASSERT_NOT_EQUAL(NULL, next_app_partition);
ESP_LOGI(TAG, "Writing to partition subtype %d at offset 0x%x", next_app_partition->subtype, next_app_partition->address);
esp_ota_handle_t update_handle = 0;
TEST_ESP_OK(esp_ota_begin(next_app_partition, OTA_SIZE_UNKNOWN, &update_handle));
copy_app_partition(update_handle, cur_app_partition);
TEST_ESP_OK(esp_ota_end(update_handle));
TEST_ESP_OK(esp_ota_set_boot_partition(next_app_partition));
}
/* @brief Erase otadata partition
*/
static void erase_ota_data(void)
{
const esp_partition_t *data_partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_OTA, NULL);
TEST_ASSERT_NOT_EQUAL(NULL, data_partition);
TEST_ESP_OK(esp_partition_erase_range(data_partition, 0, 2 * SPI_FLASH_SEC_SIZE));
}
/* @brief Reboots ESP using mode deep sleep. This mode guaranty that RTC_DATA_ATTR variables is not reset.
*/
static void reboot_as_deep_sleep(void)
{
esp_sleep_enable_timer_wakeup(2000);
esp_deep_sleep_start();
}
/* @brief Copies a current app to next partition (OTA0-15), after that ESP is rebooting and run this (the next) OTAx.
*/
static void copy_current_app_to_next_part_and_reboot()
{
const esp_partition_t *cur_app = esp_ota_get_running_partition();
copy_current_app_to_next_part(cur_app, get_next_update_partition());
reboot_as_deep_sleep();
}
/* @brief Get running app.
*
* @return The next partition of OTA(OTA0-15).
*/
static const esp_partition_t* get_running_firmware(void)
{
const esp_partition_t *configured = esp_ota_get_boot_partition();
const esp_partition_t *running = esp_ota_get_running_partition();
ESP_LOGI(TAG, "Running partition type %d subtype %d (offset 0x%08x)",
running->type, running->subtype, running->address);
ESP_LOGI(TAG, "Configured partition type %d subtype %d (offset 0x%08x)",
configured->type, configured->subtype, configured->address);
TEST_ASSERT_NOT_EQUAL(NULL, configured);
TEST_ASSERT_NOT_EQUAL(NULL, running);
if (running->subtype != ESP_PARTITION_SUBTYPE_APP_TEST) {
TEST_ASSERT_EQUAL_PTR(running, configured);
}
return running;
}
// type of a corrupt ota_data
typedef enum {
CORR_CRC_1_SECTOR_OTA_DATA = (1 << 0), /*!< Corrupt CRC only 1 sector of ota_data */
CORR_CRC_2_SECTOR_OTA_DATA = (1 << 1), /*!< Corrupt CRC only 2 sector of ota_data */
} corrupt_ota_data_t;
/* @brief Get two copies ota_data from otadata partition.
*
* @param[in] otadata_partition - otadata partition.
* @param[out] ota_data_0 - First copy from otadata_partition.
* @param[out] ota_data_1 - Second copy from otadata_partition.
*/
static void get_ota_data(const esp_partition_t *otadata_partition, esp_ota_select_entry_t *ota_data_0, esp_ota_select_entry_t *ota_data_1)
{
uint32_t offset = otadata_partition->address;
uint32_t size = otadata_partition->size;
if (offset != 0) {
const esp_ota_select_entry_t *ota_select_map;
ota_select_map = bootloader_mmap(offset, size);
TEST_ASSERT_NOT_EQUAL(NULL, ota_select_map);
memcpy(ota_data_0, ota_select_map, sizeof(esp_ota_select_entry_t));
memcpy(ota_data_1, (uint8_t *)ota_select_map + SPI_FLASH_SEC_SIZE, sizeof(esp_ota_select_entry_t));
bootloader_munmap(ota_select_map);
}
}
/* @brief Writes a ota_data into required sector of otadata_partition.
*
* @param[in] otadata_partition - Partition information otadata.
* @param[in] ota_data - otadata structure.
* @param[in] sec_id - Sector number 0 or 1.
*/
static void write_ota_data(const esp_partition_t *otadata_partition, esp_ota_select_entry_t *ota_data, int sec_id)
{
esp_partition_write(otadata_partition, SPI_FLASH_SEC_SIZE * sec_id, &ota_data[sec_id], sizeof(esp_ota_select_entry_t));
}
/* @brief Makes a corrupt of ota_data.
* @param[in] err - type error
*/
static void corrupt_ota_data(corrupt_ota_data_t err)
{
esp_ota_select_entry_t ota_data[2];
const esp_partition_t *otadata_partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_OTA, NULL);
TEST_ASSERT_NOT_EQUAL(NULL, otadata_partition);
get_ota_data(otadata_partition, &ota_data[0], &ota_data[1]);
if (err & CORR_CRC_1_SECTOR_OTA_DATA) {
ota_data[0].crc = 0;
}
if (err & CORR_CRC_2_SECTOR_OTA_DATA) {
ota_data[1].crc = 0;
}
TEST_ESP_OK(esp_partition_erase_range(otadata_partition, 0, otadata_partition->size));
write_ota_data(otadata_partition, &ota_data[0], 0);
write_ota_data(otadata_partition, &ota_data[1], 1);
}
#if defined(CONFIG_BOOTLOADER_FACTORY_RESET) || defined(CONFIG_BOOTLOADER_APP_TEST)
/* @brief Sets the pin number to output and sets output level as low. After reboot (deep sleep) this pin keep the same level.
*
* The output level of the pad will be force locked and can not be changed.
* Power down or call gpio_hold_dis will disable this function.
*
* @param[in] num_pin - Pin number
*/
static void set_output_pin(uint32_t num_pin)
{
TEST_ESP_OK(gpio_hold_dis(num_pin));
gpio_config_t io_conf;
io_conf.intr_type = GPIO_PIN_INTR_DISABLE;
io_conf.mode = GPIO_MODE_OUTPUT;
io_conf.pin_bit_mask = (1ULL << num_pin);
io_conf.pull_down_en = 0;
io_conf.pull_up_en = 0;
TEST_ESP_OK(gpio_config(&io_conf));
TEST_ESP_OK(gpio_set_level(num_pin, 0));
TEST_ESP_OK(gpio_hold_en(num_pin));
}
/* @brief Unset the pin number hold function.
*/
static void reset_output_pin(uint32_t num_pin)
{
TEST_ESP_OK(gpio_hold_dis(num_pin));
TEST_ESP_OK(gpio_reset_pin(num_pin));
}
#endif
static void mark_app_valid(void)
{
#ifdef CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE
TEST_ESP_OK(esp_ota_mark_app_valid_cancel_rollback());
#endif
}
/* @brief Checks and prepares the partition so that the factory app is launched after that.
*/
static void start_test(void)
{
ESP_LOGI(TAG, "boot count 1 - reset");
boot_count = 1;
erase_ota_data();
reboot_as_deep_sleep();
}
static void test_flow1(void)
{
boot_count++;
ESP_LOGI(TAG, "boot count %d", boot_count);
const esp_partition_t *cur_app = get_running_firmware();
switch (boot_count) {
case 2:
ESP_LOGI(TAG, "Factory");
TEST_ASSERT_EQUAL(ESP_PARTITION_SUBTYPE_APP_FACTORY, cur_app->subtype);
copy_current_app_to_next_part_and_reboot(cur_app);
break;
case 3:
ESP_LOGI(TAG, "OTA0");
TEST_ASSERT_EQUAL(ESP_PARTITION_SUBTYPE_APP_OTA_0, cur_app->subtype);
mark_app_valid();
copy_current_app_to_next_part_and_reboot(cur_app);
break;
case 4:
ESP_LOGI(TAG, "OTA1");
TEST_ASSERT_EQUAL(ESP_PARTITION_SUBTYPE_APP_OTA_1, cur_app->subtype);
mark_app_valid();
copy_current_app_to_next_part_and_reboot(cur_app);
break;
case 5:
ESP_LOGI(TAG, "OTA0");
mark_app_valid();
TEST_ASSERT_EQUAL(ESP_PARTITION_SUBTYPE_APP_OTA_0, cur_app->subtype);
erase_ota_data();
break;
default:
erase_ota_data();
TEST_FAIL_MESSAGE("Unexpected stage");
break;
}
}
// 1 Stage: After POWER_RESET erase OTA_DATA for this test -> reboot through deep sleep.
// 2 Stage: run factory -> check it -> copy factory to OTA0 -> reboot --//--
// 3 Stage: run OTA0 -> check it -> copy OTA0 to OTA1 -> reboot --//--
// 4 Stage: run OTA1 -> check it -> copy OTA1 to OTA0 -> reboot --//--
// 5 Stage: run OTA0 -> check it -> erase OTA_DATA for next tests -> PASS
TEST_CASE_MULTIPLE_STAGES("Switching between factory, OTA0, OTA1, OTA0", "[app_update][timeout=90][reset=DEEPSLEEP_RESET, DEEPSLEEP_RESET, DEEPSLEEP_RESET, DEEPSLEEP_RESET]", start_test, test_flow1, test_flow1, test_flow1, test_flow1);
static void test_flow2(void)
{
boot_count++;
ESP_LOGI(TAG, "boot count %d", boot_count);
const esp_partition_t *cur_app = get_running_firmware();
switch (boot_count) {
case 2:
ESP_LOGI(TAG, "Factory");
TEST_ASSERT_EQUAL(ESP_PARTITION_SUBTYPE_APP_FACTORY, cur_app->subtype);
copy_current_app_to_next_part_and_reboot(cur_app);
break;
case 3:
ESP_LOGI(TAG, "OTA0");
TEST_ASSERT_EQUAL(ESP_PARTITION_SUBTYPE_APP_OTA_0, cur_app->subtype);
mark_app_valid();
copy_current_app_to_next_part(cur_app, get_next_update_partition());
corrupt_ota_data(CORR_CRC_1_SECTOR_OTA_DATA);
reboot_as_deep_sleep();
break;
case 4:
ESP_LOGI(TAG, "Factory");
TEST_ASSERT_EQUAL(ESP_PARTITION_SUBTYPE_APP_FACTORY, cur_app->subtype);
erase_ota_data();
break;
default:
erase_ota_data();
TEST_FAIL_MESSAGE("Unexpected stage");
break;
}
}
// 1 Stage: After POWER_RESET erase OTA_DATA for this test -> reboot through deep sleep.
// 2 Stage: run factory -> check it -> copy factory to OTA0 -> reboot --//--
// 3 Stage: run OTA0 -> check it -> corrupt ota data -> reboot --//--
// 4 Stage: run factory -> check it -> erase OTA_DATA for next tests -> PASS
TEST_CASE_MULTIPLE_STAGES("Switching between factory, OTA0, corrupt ota_sec1, factory", "[app_update][timeout=90][reset=DEEPSLEEP_RESET, DEEPSLEEP_RESET, DEEPSLEEP_RESET]", start_test, test_flow2, test_flow2, test_flow2);
static void test_flow3(void)
{
boot_count++;
ESP_LOGI(TAG, "boot count %d", boot_count);
const esp_partition_t *cur_app = get_running_firmware();
switch (boot_count) {
case 2:
ESP_LOGI(TAG, "Factory");
TEST_ASSERT_EQUAL(ESP_PARTITION_SUBTYPE_APP_FACTORY, cur_app->subtype);
copy_current_app_to_next_part_and_reboot(cur_app);
break;
case 3:
ESP_LOGI(TAG, "OTA0");
TEST_ASSERT_EQUAL(ESP_PARTITION_SUBTYPE_APP_OTA_0, cur_app->subtype);
mark_app_valid();
copy_current_app_to_next_part_and_reboot(cur_app);
break;
case 4:
ESP_LOGI(TAG, "OTA1");
TEST_ASSERT_EQUAL(ESP_PARTITION_SUBTYPE_APP_OTA_1, cur_app->subtype);
mark_app_valid();
copy_current_app_to_next_part(cur_app, get_next_update_partition());
corrupt_ota_data(CORR_CRC_2_SECTOR_OTA_DATA);
reboot_as_deep_sleep();
break;
case 5:
ESP_LOGI(TAG, "OTA0");
TEST_ASSERT_EQUAL(ESP_PARTITION_SUBTYPE_APP_OTA_0, cur_app->subtype);
erase_ota_data();
break;
default:
erase_ota_data();
TEST_FAIL_MESSAGE("Unexpected stage");
break;
}
}
// 1 Stage: After POWER_RESET erase OTA_DATA for this test -> reboot through deep sleep.
// 2 Stage: run factory -> check it -> copy factory to OTA0 -> reboot --//--
// 3 Stage: run OTA0 -> check it -> copy OTA0 to OTA1 -> reboot --//--
// 3 Stage: run OTA1 -> check it -> corrupt ota sector2 -> reboot --//--
// 4 Stage: run OTA0 -> check it -> erase OTA_DATA for next tests -> PASS
TEST_CASE_MULTIPLE_STAGES("Switching between factory, OTA0, OTA1, currupt ota_sec2, OTA0", "[app_update][timeout=90][reset=DEEPSLEEP_RESET, DEEPSLEEP_RESET, DEEPSLEEP_RESET, DEEPSLEEP_RESET]", start_test, test_flow3, test_flow3, test_flow3, test_flow3);
#ifdef CONFIG_BOOTLOADER_FACTORY_RESET
#define STORAGE_NAMESPACE "update_ota"
static void test_flow4(void)
{
boot_count++;
ESP_LOGI(TAG, "boot count %d", boot_count);
const esp_partition_t *cur_app = get_running_firmware();
nvs_handle_t handle = 0;
int boot_count_nvs = 0;
switch (boot_count) {
case 2:
ESP_LOGI(TAG, "Factory");
TEST_ASSERT_EQUAL(ESP_PARTITION_SUBTYPE_APP_FACTORY, cur_app->subtype);
TEST_ESP_OK(nvs_flash_erase());
TEST_ESP_OK(nvs_flash_init());
TEST_ESP_OK(nvs_open(STORAGE_NAMESPACE, NVS_READWRITE, &handle));
TEST_ESP_OK(nvs_set_i32(handle, "boot_count", boot_count));
TEST_ESP_OK(nvs_commit(handle));
nvs_close(handle);
nvs_flash_deinit();
copy_current_app_to_next_part_and_reboot(cur_app);
break;
case 3:
ESP_LOGI(TAG, "OTA0");
TEST_ASSERT_EQUAL(ESP_PARTITION_SUBTYPE_APP_OTA_0, cur_app->subtype);
mark_app_valid();
TEST_ESP_OK(nvs_flash_init());
TEST_ESP_OK(nvs_open(STORAGE_NAMESPACE, NVS_READWRITE, &handle));
TEST_ESP_OK(nvs_get_i32(handle, "boot_count", &boot_count_nvs));
TEST_ASSERT_EQUAL(boot_count_nvs + 1, boot_count);
nvs_close(handle);
nvs_flash_deinit();
set_output_pin(CONFIG_BOOTLOADER_NUM_PIN_FACTORY_RESET);
reboot_as_deep_sleep();
break;
case 4:
reset_output_pin(CONFIG_BOOTLOADER_NUM_PIN_FACTORY_RESET);
ESP_LOGI(TAG, "Factory");
TEST_ASSERT_EQUAL(ESP_PARTITION_SUBTYPE_APP_FACTORY, cur_app->subtype);
int boot_count_nvs;
TEST_ESP_OK(nvs_flash_init());
TEST_ESP_OK(nvs_open(STORAGE_NAMESPACE, NVS_READWRITE, &handle));
TEST_ESP_ERR(ESP_ERR_NVS_NOT_FOUND, nvs_get_i32(handle, "boot_count", &boot_count_nvs));
nvs_close(handle);
nvs_flash_deinit();
erase_ota_data();
break;
default:
reset_output_pin(CONFIG_BOOTLOADER_NUM_PIN_FACTORY_RESET);
erase_ota_data();
TEST_FAIL_MESSAGE("Unexpected stage");
break;
}
}
// 1 Stage: After POWER_RESET erase OTA_DATA for this test -> reboot through deep sleep.
// 2 Stage: run factory -> check it -> copy factory to OTA0 -> reboot --//--
// 3 Stage: run OTA0 -> check it -> set_pin_factory_reset -> reboot --//--
// 4 Stage: run factory -> check it -> erase OTA_DATA for next tests -> PASS
TEST_CASE_MULTIPLE_STAGES("Switching between factory, OTA0, sets pin_factory_reset, factory", "[app_update][timeout=90][ignore][reset=DEEPSLEEP_RESET, DEEPSLEEP_RESET, DEEPSLEEP_RESET]", start_test, test_flow4, test_flow4, test_flow4);
#endif
#ifdef CONFIG_BOOTLOADER_APP_TEST
static void test_flow5(void)
{
boot_count++;
ESP_LOGI(TAG, "boot count %d", boot_count);
const esp_partition_t *cur_app = get_running_firmware();
switch (boot_count) {
case 2:
ESP_LOGI(TAG, "Factory");
TEST_ASSERT_EQUAL(ESP_PARTITION_SUBTYPE_APP_FACTORY, cur_app->subtype);
set_output_pin(CONFIG_BOOTLOADER_NUM_PIN_APP_TEST);
copy_partition(esp_partition_find_first(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_APP_TEST, NULL), cur_app);
esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_OTA, NULL);
reboot_as_deep_sleep();
break;
case 3:
reset_output_pin(CONFIG_BOOTLOADER_NUM_PIN_APP_TEST);
ESP_LOGI(TAG, "Test");
TEST_ASSERT_EQUAL(ESP_PARTITION_SUBTYPE_APP_TEST, cur_app->subtype);
reboot_as_deep_sleep();
break;
case 4:
ESP_LOGI(TAG, "Factory");
TEST_ASSERT_EQUAL(ESP_PARTITION_SUBTYPE_APP_FACTORY, cur_app->subtype);
erase_ota_data();
break;
default:
reset_output_pin(CONFIG_BOOTLOADER_NUM_PIN_APP_TEST);
erase_ota_data();
TEST_FAIL_MESSAGE("Unexpected stage");
break;
}
}
// 1 Stage: After POWER_RESET erase OTA_DATA for this test -> reboot through deep sleep.
// 2 Stage: run factory -> check it -> copy factory to Test and set pin_test_app -> reboot --//--
// 3 Stage: run test -> check it -> reset pin_test_app -> reboot --//--
// 4 Stage: run factory -> check it -> erase OTA_DATA for next tests -> PASS
TEST_CASE_MULTIPLE_STAGES("Switching between factory, test, factory", "[app_update][timeout=90][ignore][reset=DEEPSLEEP_RESET, DEEPSLEEP_RESET, DEEPSLEEP_RESET]", start_test, test_flow5, test_flow5, test_flow5);
#endif
static const esp_partition_t* app_update(void)
{
const esp_partition_t *cur_app = get_running_firmware();
const esp_partition_t* update_partition = esp_ota_get_next_update_partition(NULL);
TEST_ASSERT_NOT_NULL(update_partition);
esp_ota_handle_t update_handle = 0;
TEST_ESP_OK(esp_ota_begin(update_partition, OTA_SIZE_UNKNOWN, &update_handle));
copy_app_partition(update_handle, cur_app);
TEST_ESP_OK(esp_ota_end(update_handle));
TEST_ESP_OK(esp_ota_set_boot_partition(update_partition));
return update_partition;
}
static void test_rollback1(void)
{
boot_count++;
ESP_LOGI(TAG, "boot count %d", boot_count);
const esp_partition_t *cur_app = get_running_firmware();
esp_ota_img_states_t ota_state = 0x5555AAAA;
const esp_partition_t* update_partition = NULL;
switch (boot_count) {
case 2:
ESP_LOGI(TAG, "Factory");
TEST_ASSERT_EQUAL(ESP_PARTITION_SUBTYPE_APP_FACTORY, cur_app->subtype);
TEST_ASSERT_NULL(esp_ota_get_last_invalid_partition());
TEST_ESP_ERR(ESP_ERR_NOT_SUPPORTED, esp_ota_get_state_partition(cur_app, &ota_state));
update_partition = app_update();
TEST_ESP_OK(esp_ota_get_state_partition(update_partition, &ota_state));
#ifndef CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE
TEST_ASSERT_EQUAL(ESP_OTA_IMG_UNDEFINED, ota_state);
#else
TEST_ASSERT_EQUAL(ESP_OTA_IMG_NEW, ota_state);
#endif
reboot_as_deep_sleep();
break;
case 3:
ESP_LOGI(TAG, "OTA0");
TEST_ASSERT_EQUAL(ESP_PARTITION_SUBTYPE_APP_OTA_0, cur_app->subtype);
TEST_ASSERT_NULL(esp_ota_get_last_invalid_partition());
TEST_ESP_OK(esp_ota_get_state_partition(cur_app, &ota_state));
#ifndef CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE
TEST_ASSERT_EQUAL(ESP_OTA_IMG_UNDEFINED, ota_state);
#else
TEST_ASSERT_EQUAL(ESP_OTA_IMG_PENDING_VERIFY, ota_state);
#endif
TEST_ESP_OK(esp_ota_mark_app_valid_cancel_rollback());
TEST_ESP_OK(esp_ota_get_state_partition(cur_app, &ota_state));
TEST_ASSERT_EQUAL(ESP_OTA_IMG_VALID, ota_state);
reboot_as_deep_sleep();
break;
case 4:
ESP_LOGI(TAG, "OTA0");
TEST_ASSERT_EQUAL(ESP_PARTITION_SUBTYPE_APP_OTA_0, cur_app->subtype);
TEST_ESP_OK(esp_ota_get_state_partition(cur_app, &ota_state));
TEST_ASSERT_EQUAL(ESP_OTA_IMG_VALID, ota_state);
TEST_ESP_OK(esp_ota_mark_app_invalid_rollback_and_reboot());
break;
default:
erase_ota_data();
TEST_FAIL_MESSAGE("Unexpected stage");
break;
}
}
static void test_rollback1_1(void)
{
boot_count = 5;
esp_ota_img_states_t ota_state = 0x5555AAAA;
ESP_LOGI(TAG, "boot count %d", boot_count);
const esp_partition_t *cur_app = get_running_firmware();
ESP_LOGI(TAG, "Factory");
TEST_ASSERT_EQUAL(ESP_PARTITION_SUBTYPE_APP_FACTORY, cur_app->subtype);
const esp_partition_t *invalid_partition = esp_ota_get_last_invalid_partition();
const esp_partition_t* next_update_partition = esp_ota_get_next_update_partition(NULL);
TEST_ASSERT_NOT_NULL(invalid_partition);
TEST_ASSERT_NOT_NULL(next_update_partition);
TEST_ASSERT_EQUAL_PTR(invalid_partition, next_update_partition);
TEST_ESP_ERR(ESP_ERR_NOT_SUPPORTED, esp_ota_get_state_partition(cur_app, &ota_state));
TEST_ESP_OK(esp_ota_get_state_partition(invalid_partition, &ota_state));
TEST_ASSERT_EQUAL(ESP_OTA_IMG_INVALID, ota_state);
erase_ota_data();
}
// 1 Stage: After POWER_RESET erase OTA_DATA for this test -> reboot through deep sleep.
// 2 Stage: run factory -> check it -> copy factory to next app slot -> reboot --//--
// 3 Stage: run OTA0 -> check it -> esp_ota_mark_app_valid_cancel_rollback() -> reboot --//--
// 4 Stage: run OTA0 -> check it -> esp_ota_mark_app_invalid_rollback_and_reboot() -> reboot
// 5 Stage: run factory -> check it -> erase OTA_DATA for next tests -> PASS
TEST_CASE_MULTIPLE_STAGES("Test rollback. factory, OTA0, OTA0, rollback -> factory", "[app_update][timeout=90][reset=DEEPSLEEP_RESET, DEEPSLEEP_RESET, DEEPSLEEP_RESET, SW_CPU_RESET]", start_test, test_rollback1, test_rollback1, test_rollback1, test_rollback1_1);
static void test_rollback2(void)
{
boot_count++;
ESP_LOGI(TAG, "boot count %d", boot_count);
const esp_partition_t *cur_app = get_running_firmware();
esp_ota_img_states_t ota_state = 0x5555AAAA;
const esp_partition_t* update_partition = NULL;
switch (boot_count) {
case 2:
ESP_LOGI(TAG, "Factory");
TEST_ASSERT_EQUAL(ESP_PARTITION_SUBTYPE_APP_FACTORY, cur_app->subtype);
TEST_ASSERT_NULL(esp_ota_get_last_invalid_partition());
TEST_ESP_ERR(ESP_ERR_NOT_SUPPORTED, esp_ota_get_state_partition(cur_app, &ota_state));
update_partition = app_update();
TEST_ESP_OK(esp_ota_get_state_partition(update_partition, &ota_state));
#ifndef CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE
TEST_ASSERT_EQUAL(ESP_OTA_IMG_UNDEFINED, ota_state);
#else
TEST_ASSERT_EQUAL(ESP_OTA_IMG_NEW, ota_state);
#endif
reboot_as_deep_sleep();
break;
case 3:
ESP_LOGI(TAG, "OTA0");
TEST_ASSERT_EQUAL(ESP_PARTITION_SUBTYPE_APP_OTA_0, cur_app->subtype);
TEST_ASSERT_NULL(esp_ota_get_last_invalid_partition());
TEST_ESP_OK(esp_ota_get_state_partition(cur_app, &ota_state));
#ifndef CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE
TEST_ASSERT_EQUAL(ESP_OTA_IMG_UNDEFINED, ota_state);
#else
TEST_ASSERT_EQUAL(ESP_OTA_IMG_PENDING_VERIFY, ota_state);
#endif
TEST_ESP_OK(esp_ota_mark_app_valid_cancel_rollback());
TEST_ASSERT_NULL(esp_ota_get_last_invalid_partition());
TEST_ESP_OK(esp_ota_get_state_partition(cur_app, &ota_state));
TEST_ASSERT_EQUAL(ESP_OTA_IMG_VALID, ota_state);
update_partition = app_update();
TEST_ESP_OK(esp_ota_get_state_partition(update_partition, &ota_state));
#ifndef CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE
TEST_ASSERT_EQUAL(ESP_OTA_IMG_UNDEFINED, ota_state);
#else
TEST_ASSERT_EQUAL(ESP_OTA_IMG_NEW, ota_state);
#endif
reboot_as_deep_sleep();
break;
case 4:
ESP_LOGI(TAG, "OTA1");
TEST_ASSERT_EQUAL(ESP_PARTITION_SUBTYPE_APP_OTA_1, cur_app->subtype);
TEST_ASSERT_NULL(esp_ota_get_last_invalid_partition());
TEST_ESP_OK(esp_ota_get_state_partition(cur_app, &ota_state));
#ifndef CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE
TEST_ASSERT_EQUAL(ESP_OTA_IMG_UNDEFINED, ota_state);
TEST_ESP_OK(esp_ota_mark_app_invalid_rollback_and_reboot());
#else
TEST_ASSERT_EQUAL(ESP_OTA_IMG_PENDING_VERIFY, ota_state);
reboot_as_deep_sleep();
#endif
break;
default:
erase_ota_data();
TEST_FAIL_MESSAGE("Unexpected stage");
break;
}
}
static void test_rollback2_1(void)
{
boot_count = 5;
esp_ota_img_states_t ota_state = 0x5555AAAA;
ESP_LOGI(TAG, "boot count %d", boot_count);
const esp_partition_t *cur_app = get_running_firmware();
ESP_LOGI(TAG, "OTA0");
TEST_ASSERT_EQUAL(ESP_PARTITION_SUBTYPE_APP_OTA_0, cur_app->subtype);
const esp_partition_t *invalid_partition = esp_ota_get_last_invalid_partition();
TEST_ASSERT_EQUAL(ESP_PARTITION_SUBTYPE_APP_OTA_1, invalid_partition->subtype);
const esp_partition_t* next_update_partition = esp_ota_get_next_update_partition(NULL);
TEST_ASSERT_NOT_NULL(invalid_partition);
TEST_ASSERT_NOT_NULL(next_update_partition);
TEST_ASSERT_EQUAL_PTR(invalid_partition, next_update_partition);
TEST_ESP_OK(esp_ota_get_state_partition(cur_app, &ota_state));
TEST_ASSERT_EQUAL(ESP_OTA_IMG_VALID, ota_state);
TEST_ESP_OK(esp_ota_get_state_partition(invalid_partition, &ota_state));
#ifndef CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE
TEST_ASSERT_EQUAL(ESP_OTA_IMG_INVALID, ota_state);
#else
TEST_ASSERT_EQUAL(ESP_OTA_IMG_ABORTED, ota_state);
#endif
erase_ota_data();
}
// 1 Stage: After POWER_RESET erase OTA_DATA for this test -> reboot through deep sleep.
// 2 Stage: run factory -> check it -> copy factory to next app slot -> reboot --//--
// 3 Stage: run OTA0 -> check it -> esp_ota_mark_app_valid_cancel_rollback(), copy to next app slot -> reboot --//--
// 4 Stage: run OTA1 -> check it -> PENDING_VERIFY/esp_ota_mark_app_invalid_rollback_and_reboot() -> reboot
// 5 Stage: run OTA0(rollback) -> check it -> erase OTA_DATA for next tests -> PASS
TEST_CASE_MULTIPLE_STAGES("Test rollback. factory, OTA0, OTA1, rollback -> OTA0", "[app_update][timeout=90][reset=DEEPSLEEP_RESET, DEEPSLEEP_RESET, DEEPSLEEP_RESET, SW_CPU_RESET]", start_test, test_rollback2, test_rollback2, test_rollback2, test_rollback2_1);
static void test_erase_last_app_flow(void)
{
boot_count++;
ESP_LOGI(TAG, "boot count %d", boot_count);
const esp_partition_t *cur_app = get_running_firmware();
switch (boot_count) {
case 2:
ESP_LOGI(TAG, "Factory");
TEST_ASSERT_EQUAL(ESP_PARTITION_SUBTYPE_APP_FACTORY, cur_app->subtype);
app_update();
reboot_as_deep_sleep();
break;
case 3:
ESP_LOGI(TAG, "OTA0");
TEST_ASSERT_EQUAL(ESP_PARTITION_SUBTYPE_APP_OTA_0, cur_app->subtype);
mark_app_valid();
app_update();
reboot_as_deep_sleep();
break;
case 4:
ESP_LOGI(TAG, "OTA1");
TEST_ASSERT_EQUAL(ESP_PARTITION_SUBTYPE_APP_OTA_1, cur_app->subtype);
TEST_ESP_OK(esp_ota_erase_last_boot_app_partition());
TEST_ESP_OK(esp_ota_mark_app_invalid_rollback_and_reboot());
reboot_as_deep_sleep();
break;
default:
erase_ota_data();
TEST_FAIL_MESSAGE("Unexpected stage");
break;
}
}
static void test_erase_last_app_rollback(void)
{
boot_count = 5;
ESP_LOGI(TAG, "boot count %d", boot_count);
const esp_partition_t *cur_app = get_running_firmware();
ESP_LOGI(TAG, "erase_last_app");
TEST_ASSERT_EQUAL(ESP_PARTITION_SUBTYPE_APP_FACTORY, cur_app->subtype);
TEST_ESP_ERR(ESP_FAIL, esp_ota_erase_last_boot_app_partition());
erase_ota_data();
}
// 1 Stage: After POWER_RESET erase OTA_DATA for this test -> reboot through deep sleep.
// 2 Stage: run factory -> check it -> copy factory to OTA0 -> reboot --//--
// 3 Stage: run OTA0 -> check it -> copy factory to OTA1 -> reboot --//--
// 4 Stage: run OTA1 -> check it -> erase OTA0 and rollback -> reboot
// 5 Stage: run factory -> check it -> erase OTA_DATA for next tests -> PASS
TEST_CASE_MULTIPLE_STAGES("Test erase_last_boot_app_partition. factory, OTA1, OTA0, factory", "[app_update][timeout=90][reset=DEEPSLEEP_RESET, DEEPSLEEP_RESET, DEEPSLEEP_RESET, SW_CPU_RESET]", start_test, test_erase_last_app_flow, test_erase_last_app_flow, test_erase_last_app_flow, test_erase_last_app_rollback);

View File

@@ -1,3 +0,0 @@
idf_component_register(SRCS "asio/asio/src/asio.cpp"
INCLUDE_DIRS "asio/asio/include" "port/include"
REQUIRES lwip)

View File

@@ -1,6 +0,0 @@
COMPONENT_ADD_INCLUDEDIRS := asio/asio/include port/include
COMPONENT_PRIV_INCLUDEDIRS := private_include
COMPONENT_SRCDIRS := asio/asio/src
COMPONENT_OBJEXCLUDE := asio/asio/src/asio_ssl.o
COMPONENT_SUBMODULES += asio

View File

@@ -1,45 +0,0 @@
// Copyright 2018 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef _ESP_ASIO_CONFIG_H_
#define _ESP_ASIO_CONFIG_H_
//
// Enabling exceptions only when they are enabled in menuconfig
//
# include <sdkconfig.h>
# ifndef CONFIG_COMPILER_CXX_EXCEPTIONS
# define ASIO_NO_EXCEPTIONS
# endif // CONFIG_COMPILER_CXX_EXCEPTIONS
//
// LWIP compatifility inet and address macros/functions
//
# define LWIP_COMPAT_SOCKET_INET 1
# define LWIP_COMPAT_SOCKET_ADDR 1
//
// Specific ASIO feature flags
//
# define ASIO_DISABLE_SERIAL_PORT
# define ASIO_SEPARATE_COMPILATION
# define ASIO_STANDALONE
# define ASIO_NO_TYPEID
# define ASIO_DISABLE_SIGNAL
# define ASIO_HAS_PTHREADS
# define ASIO_DISABLE_EPOLL
# define ASIO_DISABLE_EVENTFD
# define ASIO_DISABLE_SIGNAL
# define ASIO_DISABLE_SIGACTION
#endif // _ESP_ASIO_CONFIG_H_

View File

@@ -1,39 +0,0 @@
// Copyright 2018 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef _ESP_EXCEPTION_H_
#define _ESP_EXCEPTION_H_
//
// This exception stub is enabled only if exceptions are disabled in menuconfig
//
#if !defined(CONFIG_COMPILER_CXX_EXCEPTIONS) && defined (ASIO_NO_EXCEPTIONS)
#include "esp_log.h"
//
// asio exception stub
//
namespace asio {
namespace detail {
template <typename Exception>
void throw_exception(const Exception& e)
{
ESP_LOGE("esp32_asio_exception", "Caught exception: %s!", e.what());
abort();
}
}}
#endif // CONFIG_COMPILER_CXX_EXCEPTIONS==1 && defined (ASIO_NO_EXCEPTIONS)
#endif // _ESP_EXCEPTION_H_

View File

@@ -0,0 +1,32 @@
menuconfig AWS_IOT_SDK
bool "Amazon Web Services IoT Platform"
help
Select this option to enable support for the AWS IoT platform,
via the esp-idf component for the AWS IoT Device C SDK.
config AWS_IOT_MQTT_HOST
string "AWS IoT Endpoint Hostname"
depends on AWS_IOT_SDK
default ""
help
Default endpoint host name to connect to AWS IoT MQTT/S gateway
This is the custom endpoint hostname and is specific to an AWS
IoT account. You can find it by logging into your AWS IoT
Console and clicking the Settings button. The endpoint hostname
is shown under the "Custom Endpoint" heading on this page.
If you need per-device hostnames for different regions or
accounts, you can override the default hostname in your app.
config AWS_IOT_MQTT_PORT
int "AWS IoT MQTT Port"
depends on AWS_IOT_SDK
default 8883
range 0 65535
help
Default port number to connect to AWS IoT MQTT/S gateway
If you need per-device port numbers for different regions, you can
override the default port number in your app.

View File

@@ -0,0 +1,20 @@
#
# Component Makefile
#
ifdef CONFIG_AWS_IOT_SDK
COMPONENT_ADD_INCLUDEDIRS := include aws-iot-device-sdk-embedded-C/include
COMPONENT_SRCDIRS := aws-iot-device-sdk-embedded-C/src port
# Check the submodule is initialised
COMPONENT_SUBMODULES := aws-iot-device-sdk-embedded-C
else
# Disable AWS IoT support
COMPONENT_ADD_INCLUDEDIRS :=
COMPONENT_ADD_LDFLAGS :=
COMPONENT_SRCDIRS :=
endif

View File

@@ -0,0 +1,60 @@
/*
* Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
/**
* @file aws_iot_config.h
* @brief AWS IoT specific configuration file
*/
#ifndef _AWS_IOT_CONFIG_H_
#define _AWS_IOT_CONFIG_H_
#include "aws_iot_log.h"
// This configuration macro needs to be available globally to enable threading
#define _ENABLE_THREAD_SUPPORT_
// These values are defined in the menuconfig of the AWS IoT component.
// However, you can override these constants from your own code.
#define AWS_IOT_MQTT_HOST CONFIG_AWS_IOT_MQTT_HOST ///< Customer specific MQTT HOST. The same will be used for Thing Shadow
#define AWS_IOT_MQTT_PORT CONFIG_AWS_IOT_MQTT_PORT ///< default port for MQTT/S
// These values are defaults and are used for ShadowConnectParametersDefault.
// You should override them from your own code.
#define AWS_IOT_MQTT_CLIENT_ID "ESP32" ///< MQTT client ID should be unique for every device
#define AWS_IOT_MY_THING_NAME "ESP32" ///< Thing Name of the Shadow this device is associated with
// MQTT PubSub
#define AWS_IOT_MQTT_TX_BUF_LEN 512 ///< Any time a message is sent out through the MQTT layer. The message is copied into this buffer anytime a publish is done. This will also be used in the case of Thing Shadow
#define AWS_IOT_MQTT_RX_BUF_LEN 512 ///< Any message that comes into the device should be less than this buffer size. If a received message is bigger than this buffer size the message will be dropped.
#define AWS_IOT_MQTT_NUM_SUBSCRIBE_HANDLERS 5 ///< Maximum number of topic filters the MQTT client can handle at any given time. This should be increased appropriately when using Thing Shadow
// Thing Shadow specific configs
#define SHADOW_MAX_SIZE_OF_RX_BUFFER (AWS_IOT_MQTT_RX_BUF_LEN + 1) ///< Maximum size of the SHADOW buffer to store the received Shadow message
#define MAX_SIZE_OF_UNIQUE_CLIENT_ID_BYTES 80 ///< Maximum size of the Unique Client Id. For More info on the Client Id refer \ref response "Acknowledgments"
#define MAX_SIZE_CLIENT_ID_WITH_SEQUENCE (MAX_SIZE_OF_UNIQUE_CLIENT_ID_BYTES + 10) ///< This is size of the extra sequence number that will be appended to the Unique client Id
#define MAX_SIZE_CLIENT_TOKEN_CLIENT_SEQUENCE (MAX_SIZE_CLIENT_ID_WITH_SEQUENCE + 20) ///< This is size of the the total clientToken key and value pair in the JSON
#define MAX_ACKS_TO_COMEIN_AT_ANY_GIVEN_TIME 10 ///< At Any given time we will wait for this many responses. This will correlate to the rate at which the shadow actions are requested
#define MAX_THINGNAME_HANDLED_AT_ANY_GIVEN_TIME 10 ///< We could perform shadow action on any thing Name and this is maximum Thing Names we can act on at any given time
#define MAX_JSON_TOKEN_EXPECTED 120 ///< These are the max tokens that is expected to be in the Shadow JSON document. Include the metadata that gets published
#define MAX_SHADOW_TOPIC_LENGTH_WITHOUT_THINGNAME 60 ///< All shadow actions have to be published or subscribed to a topic which is of the formablogt $aws/things/{thingName}/shadow/update/accepted. This refers to the size of the topic without the Thing Name
#define MAX_SIZE_OF_THING_NAME 20 ///< The Thing Name should not be bigger than this value. Modify this if the Thing Name needs to be bigger
#define MAX_SHADOW_TOPIC_LENGTH_BYTES (MAX_SHADOW_TOPIC_LENGTH_WITHOUT_THINGNAME + MAX_SIZE_OF_THING_NAME) ///< This size includes the length of topic with Thing Name
// Auto Reconnect specific config
#define AWS_IOT_MQTT_MIN_RECONNECT_WAIT_INTERVAL 1000 ///< Minimum time before the First reconnect attempt is made as part of the exponential back-off algorithm
#define AWS_IOT_MQTT_MAX_RECONNECT_WAIT_INTERVAL 128000 ///< Maximum time interval after which exponential back-off will stop attempting to reconnect.
#endif /* _AWS_IOT_CONFIG_H_ */

View File

@@ -0,0 +1,44 @@
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#pragma once
/* (these two headers aren't used here, but AWS IoT SDK code relies on them
being included from here...) */
#include <stdio.h>
#include <stdlib.h>
#include "esp_log.h"
/* This is a stub replacement for the aws_iot_log.h header in the AWS IoT SDK,
which redirects their logging framework into the esp-idf logging framework.
The current (2.1.1) upstream AWS IoT SDK doesn't allow this as some of its
headers include aws_iot_log.h, but our modified fork does.
*/
// redefine the AWS IoT log functions to call into the IDF log layer
#define IOT_DEBUG(format, ...) ESP_LOGD("aws_iot", format, ##__VA_ARGS__)
#define IOT_INFO(format, ...) ESP_LOGI("aws_iot", format, ##__VA_ARGS__)
#define IOT_WARN(format, ...) ESP_LOGW("aws_iot", format, ##__VA_ARGS__)
#define IOT_ERROR(format, ...) ESP_LOGE("aws_iot", format, ##__VA_ARGS__)
/* Function tracing macros used in AWS IoT SDK,
mapped to "verbose" level output
*/
#define FUNC_ENTRY ESP_LOGV("aws_iot", "FUNC_ENTRY: %s L#%d \n", __func__, __LINE__)
#define FUNC_EXIT_RC(x) \
do { \
ESP_LOGV("aws_iot", "FUNC_EXIT: %s L#%d Return Code : %d \n", __func__, __LINE__, x); \
return x; \
} while(0)

View File

@@ -0,0 +1,64 @@
/*
* Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* Additions Copyright 2016 Espressif Systems (Shanghai) PTE LTD
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
#ifndef IOTSDKC_NETWORK_MBEDTLS_PLATFORM_H_H
#if !defined(MBEDTLS_CONFIG_FILE)
#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
#include "mbedtls/platform.h"
#include "mbedtls/net.h"
#include "mbedtls/ssl.h"
#include "mbedtls/entropy.h"
#include "mbedtls/ctr_drbg.h"
#include "mbedtls/certs.h"
#include "mbedtls/x509.h"
#include "mbedtls/error.h"
#include "mbedtls/debug.h"
#include "mbedtls/timing.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief TLS Connection Parameters
*
* Defines a type containing TLS specific parameters to be passed down to the
* TLS networking layer to create a TLS secured socket.
*/
typedef struct _TLSDataParams {
mbedtls_entropy_context entropy;
mbedtls_ctr_drbg_context ctr_drbg;
mbedtls_ssl_context ssl;
mbedtls_ssl_config conf;
uint32_t flags;
mbedtls_x509_crt cacert;
mbedtls_x509_crt clicert;
mbedtls_pk_context pkey;
mbedtls_net_context server_fd;
}TLSDataParams;
#define IOTSDKC_NETWORK_MBEDTLS_PLATFORM_H_H
#ifdef __cplusplus
}
#endif
#endif //IOTSDKC_NETWORK_MBEDTLS_PLATFORM_H_H

View File

@@ -0,0 +1,45 @@
/*
* Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* Additions Copyright 2016 Espressif Systems (Shanghai) PTE LTD
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
#include "threads_interface.h"
#ifndef AWS_IOTSDK_THREADS_PLATFORM_H
#define AWS_IOTSDK_THREADS_PLATFORM_H
#ifdef __cplusplus
extern "C" {
#endif
#include "freertos/FreeRTOS.h"
#include "freertos/semphr.h"
/**
* @brief Mutex Type
*
* definition of the Mutex struct. Platform specific
*
*/
struct _IoT_Mutex_t {
SemaphoreHandle_t mutex;
};
#ifdef __cplusplus
}
#endif
#endif /* AWS_IOTSDK_THREADS_PLATFORM_H */

View File

@@ -0,0 +1,40 @@
/*
* Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* Additions Copyright 2016 Espressif Systems (Shanghai) PTE LTD
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
#ifndef AWS_IOT_PLATFORM_H
#define AWS_IOT_PLATFORM_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
#include "timer_interface.h"
/**
* definition of the Timer struct. Platform specific
*/
struct Timer {
uint32_t start_ticks;
uint32_t timeout_ticks;
uint32_t last_polled_ticks;
};
#ifdef __cplusplus
}
#endif
#endif /* AWS_IOT_PLATFORM_H */

View File

@@ -0,0 +1,408 @@
/*
* Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* Additions Copyright 2016 Espressif Systems (Shanghai) PTE LTD
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
#include <sys/param.h>
#include <stdbool.h>
#include <string.h>
#include <timer_platform.h>
#include <network_interface.h>
#include "aws_iot_config.h"
#include "aws_iot_error.h"
#include "network_interface.h"
#include "network_platform.h"
#include "mbedtls/esp_debug.h"
#include "esp_log.h"
#include "esp_vfs.h"
static const char *TAG = "aws_iot";
/* This is the value used for ssl read timeout */
#define IOT_SSL_READ_TIMEOUT 10
/*
* This is a function to do further verification if needed on the cert received.
*
* Currently used to print debug-level information about each cert.
*/
static int _iot_tls_verify_cert(void *data, mbedtls_x509_crt *crt, int depth, uint32_t *flags) {
char buf[256];
((void) data);
if (LOG_LOCAL_LEVEL >= ESP_LOG_DEBUG) {
ESP_LOGD(TAG, "Verify requested for (Depth %d):", depth);
mbedtls_x509_crt_info(buf, sizeof(buf) - 1, "", crt);
ESP_LOGD(TAG, "%s", buf);
if((*flags) == 0) {
ESP_LOGD(TAG, " This certificate has no flags");
} else {
ESP_LOGD(TAG, "Verify result:%s", buf);
}
}
return 0;
}
static void _iot_tls_set_connect_params(Network *pNetwork, const char *pRootCALocation, const char *pDeviceCertLocation,
const char *pDevicePrivateKeyLocation, const char *pDestinationURL,
uint16_t destinationPort, uint32_t timeout_ms, bool ServerVerificationFlag) {
pNetwork->tlsConnectParams.DestinationPort = destinationPort;
pNetwork->tlsConnectParams.pDestinationURL = pDestinationURL;
pNetwork->tlsConnectParams.pDeviceCertLocation = pDeviceCertLocation;
pNetwork->tlsConnectParams.pDevicePrivateKeyLocation = pDevicePrivateKeyLocation;
pNetwork->tlsConnectParams.pRootCALocation = pRootCALocation;
pNetwork->tlsConnectParams.timeout_ms = timeout_ms;
pNetwork->tlsConnectParams.ServerVerificationFlag = ServerVerificationFlag;
}
IoT_Error_t iot_tls_init(Network *pNetwork, const char *pRootCALocation, const char *pDeviceCertLocation,
const char *pDevicePrivateKeyLocation, const char *pDestinationURL,
uint16_t destinationPort, uint32_t timeout_ms, bool ServerVerificationFlag) {
_iot_tls_set_connect_params(pNetwork, pRootCALocation, pDeviceCertLocation, pDevicePrivateKeyLocation,
pDestinationURL, destinationPort, timeout_ms, ServerVerificationFlag);
pNetwork->connect = iot_tls_connect;
pNetwork->read = iot_tls_read;
pNetwork->write = iot_tls_write;
pNetwork->disconnect = iot_tls_disconnect;
pNetwork->isConnected = iot_tls_is_connected;
pNetwork->destroy = iot_tls_destroy;
pNetwork->tlsDataParams.flags = 0;
return SUCCESS;
}
IoT_Error_t iot_tls_is_connected(Network *pNetwork) {
/* Use this to add implementation which can check for physical layer disconnect */
return NETWORK_PHYSICAL_LAYER_CONNECTED;
}
IoT_Error_t iot_tls_connect(Network *pNetwork, TLSConnectParams *params) {
int ret = SUCCESS;
TLSDataParams *tlsDataParams = NULL;
char portBuffer[6];
char info_buf[256];
if(NULL == pNetwork) {
return NULL_VALUE_ERROR;
}
if(NULL != params) {
_iot_tls_set_connect_params(pNetwork, params->pRootCALocation, params->pDeviceCertLocation,
params->pDevicePrivateKeyLocation, params->pDestinationURL,
params->DestinationPort, params->timeout_ms, params->ServerVerificationFlag);
}
tlsDataParams = &(pNetwork->tlsDataParams);
mbedtls_net_init(&(tlsDataParams->server_fd));
mbedtls_ssl_init(&(tlsDataParams->ssl));
mbedtls_ssl_config_init(&(tlsDataParams->conf));
#ifdef CONFIG_MBEDTLS_DEBUG
mbedtls_esp_enable_debug_log(&(tlsDataParams->conf), 4);
#endif
mbedtls_ctr_drbg_init(&(tlsDataParams->ctr_drbg));
mbedtls_x509_crt_init(&(tlsDataParams->cacert));
mbedtls_x509_crt_init(&(tlsDataParams->clicert));
mbedtls_pk_init(&(tlsDataParams->pkey));
ESP_LOGD(TAG, "Seeding the random number generator...");
mbedtls_entropy_init(&(tlsDataParams->entropy));
if((ret = mbedtls_ctr_drbg_seed(&(tlsDataParams->ctr_drbg), mbedtls_entropy_func, &(tlsDataParams->entropy),
(const unsigned char *) TAG, strlen(TAG))) != 0) {
ESP_LOGE(TAG, "failed! mbedtls_ctr_drbg_seed returned -0x%x", -ret);
return NETWORK_MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED;
}
/* Load root CA...
Certs/keys can be paths or they can be raw data. These use a
very basic heuristic: if the cert starts with '/' then it's a
path, if it's longer than this then it's raw cert data (PEM or DER,
neither of which can start with a slash. */
if (pNetwork->tlsConnectParams.pRootCALocation[0] == '/') {
ESP_LOGD(TAG, "Loading CA root certificate from file ...");
ret = mbedtls_x509_crt_parse_file(&(tlsDataParams->cacert), pNetwork->tlsConnectParams.pRootCALocation);
} else {
ESP_LOGD(TAG, "Loading embedded CA root certificate ...");
ret = mbedtls_x509_crt_parse(&(tlsDataParams->cacert), (const unsigned char *)pNetwork->tlsConnectParams.pRootCALocation,
strlen(pNetwork->tlsConnectParams.pRootCALocation)+1);
}
if(ret < 0) {
ESP_LOGE(TAG, "failed! mbedtls_x509_crt_parse returned -0x%x while parsing root cert", -ret);
return NETWORK_X509_ROOT_CRT_PARSE_ERROR;
}
ESP_LOGD(TAG, "ok (%d skipped)", ret);
/* Load client certificate... */
if (pNetwork->tlsConnectParams.pDeviceCertLocation[0] == '/') {
ESP_LOGD(TAG, "Loading client cert from file...");
ret = mbedtls_x509_crt_parse_file(&(tlsDataParams->clicert),
pNetwork->tlsConnectParams.pDeviceCertLocation);
} else {
ESP_LOGD(TAG, "Loading embedded client certificate...");
ret = mbedtls_x509_crt_parse(&(tlsDataParams->clicert),
(const unsigned char *)pNetwork->tlsConnectParams.pDeviceCertLocation,
strlen(pNetwork->tlsConnectParams.pDeviceCertLocation)+1);
}
if(ret != 0) {
ESP_LOGE(TAG, "failed! mbedtls_x509_crt_parse returned -0x%x while parsing device cert", -ret);
return NETWORK_X509_DEVICE_CRT_PARSE_ERROR;
}
/* Parse client private key... */
if (pNetwork->tlsConnectParams.pDevicePrivateKeyLocation[0] == '/') {
ESP_LOGD(TAG, "Loading client private key from file...");
ret = mbedtls_pk_parse_keyfile(&(tlsDataParams->pkey),
pNetwork->tlsConnectParams.pDevicePrivateKeyLocation,
"");
} else {
ESP_LOGD(TAG, "Loading embedded client private key...");
ret = mbedtls_pk_parse_key(&(tlsDataParams->pkey),
(const unsigned char *)pNetwork->tlsConnectParams.pDevicePrivateKeyLocation,
strlen(pNetwork->tlsConnectParams.pDevicePrivateKeyLocation)+1,
(const unsigned char *)"", 0);
}
if(ret != 0) {
ESP_LOGE(TAG, "failed! mbedtls_pk_parse_key returned -0x%x while parsing private key", -ret);
return NETWORK_PK_PRIVATE_KEY_PARSE_ERROR;
}
/* Done parsing certs */
ESP_LOGD(TAG, "ok");
snprintf(portBuffer, 6, "%d", pNetwork->tlsConnectParams.DestinationPort);
ESP_LOGD(TAG, "Connecting to %s/%s...", pNetwork->tlsConnectParams.pDestinationURL, portBuffer);
if((ret = mbedtls_net_connect(&(tlsDataParams->server_fd), pNetwork->tlsConnectParams.pDestinationURL,
portBuffer, MBEDTLS_NET_PROTO_TCP)) != 0) {
ESP_LOGE(TAG, "failed! mbedtls_net_connect returned -0x%x", -ret);
switch(ret) {
case MBEDTLS_ERR_NET_SOCKET_FAILED:
return NETWORK_ERR_NET_SOCKET_FAILED;
case MBEDTLS_ERR_NET_UNKNOWN_HOST:
return NETWORK_ERR_NET_UNKNOWN_HOST;
case MBEDTLS_ERR_NET_CONNECT_FAILED:
default:
return NETWORK_ERR_NET_CONNECT_FAILED;
};
}
ret = mbedtls_net_set_block(&(tlsDataParams->server_fd));
if(ret != 0) {
ESP_LOGE(TAG, "failed! net_set_(non)block() returned -0x%x", -ret);
return SSL_CONNECTION_ERROR;
} ESP_LOGD(TAG, "ok");
ESP_LOGD(TAG, "Setting up the SSL/TLS structure...");
if((ret = mbedtls_ssl_config_defaults(&(tlsDataParams->conf), MBEDTLS_SSL_IS_CLIENT, MBEDTLS_SSL_TRANSPORT_STREAM,
MBEDTLS_SSL_PRESET_DEFAULT)) != 0) {
ESP_LOGE(TAG, "failed! mbedtls_ssl_config_defaults returned -0x%x", -ret);
return SSL_CONNECTION_ERROR;
}
mbedtls_ssl_conf_verify(&(tlsDataParams->conf), _iot_tls_verify_cert, NULL);
if(pNetwork->tlsConnectParams.ServerVerificationFlag == true) {
mbedtls_ssl_conf_authmode(&(tlsDataParams->conf), MBEDTLS_SSL_VERIFY_REQUIRED);
} else {
mbedtls_ssl_conf_authmode(&(tlsDataParams->conf), MBEDTLS_SSL_VERIFY_OPTIONAL);
}
mbedtls_ssl_conf_rng(&(tlsDataParams->conf), mbedtls_ctr_drbg_random, &(tlsDataParams->ctr_drbg));
mbedtls_ssl_conf_ca_chain(&(tlsDataParams->conf), &(tlsDataParams->cacert), NULL);
ret = mbedtls_ssl_conf_own_cert(&(tlsDataParams->conf), &(tlsDataParams->clicert), &(tlsDataParams->pkey));
if(ret != 0) {
ESP_LOGE(TAG, "failed! mbedtls_ssl_conf_own_cert returned %d", ret);
return SSL_CONNECTION_ERROR;
}
mbedtls_ssl_conf_read_timeout(&(tlsDataParams->conf), pNetwork->tlsConnectParams.timeout_ms);
if((ret = mbedtls_ssl_setup(&(tlsDataParams->ssl), &(tlsDataParams->conf))) != 0) {
ESP_LOGE(TAG, "failed! mbedtls_ssl_setup returned -0x%x", -ret);
return SSL_CONNECTION_ERROR;
}
if((ret = mbedtls_ssl_set_hostname(&(tlsDataParams->ssl), pNetwork->tlsConnectParams.pDestinationURL)) != 0) {
ESP_LOGE(TAG, "failed! mbedtls_ssl_set_hostname returned %d", ret);
return SSL_CONNECTION_ERROR;
}
ESP_LOGD(TAG, "SSL state connect : %d ", tlsDataParams->ssl.state);
mbedtls_ssl_set_bio(&(tlsDataParams->ssl), &(tlsDataParams->server_fd), mbedtls_net_send, NULL,
mbedtls_net_recv_timeout);
ESP_LOGD(TAG, "ok");
ESP_LOGD(TAG, "SSL state connect : %d ", tlsDataParams->ssl.state);
ESP_LOGD(TAG, "Performing the SSL/TLS handshake...");
while((ret = mbedtls_ssl_handshake(&(tlsDataParams->ssl))) != 0) {
if(ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) {
ESP_LOGE(TAG, "failed! mbedtls_ssl_handshake returned -0x%x", -ret);
if(ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED) {
ESP_LOGE(TAG, " Unable to verify the server's certificate. ");
}
return SSL_CONNECTION_ERROR;
}
}
ESP_LOGD(TAG, "ok [ Protocol is %s ] [ Ciphersuite is %s ]", mbedtls_ssl_get_version(&(tlsDataParams->ssl)),
mbedtls_ssl_get_ciphersuite(&(tlsDataParams->ssl)));
if((ret = mbedtls_ssl_get_record_expansion(&(tlsDataParams->ssl))) >= 0) {
ESP_LOGD(TAG, " [ Record expansion is %d ]", ret);
} else {
ESP_LOGD(TAG, " [ Record expansion is unknown (compression) ]");
}
ESP_LOGD(TAG, "Verifying peer X.509 certificate...");
if(pNetwork->tlsConnectParams.ServerVerificationFlag == true) {
if((tlsDataParams->flags = mbedtls_ssl_get_verify_result(&(tlsDataParams->ssl))) != 0) {
ESP_LOGE(TAG, "failed");
mbedtls_x509_crt_verify_info(info_buf, sizeof(info_buf), " ! ", tlsDataParams->flags);
ESP_LOGE(TAG, "%s", info_buf);
ret = SSL_CONNECTION_ERROR;
} else {
ESP_LOGD(TAG, "ok");
ret = SUCCESS;
}
} else {
ESP_LOGW(TAG, " Server Verification skipped");
ret = SUCCESS;
}
if(LOG_LOCAL_LEVEL >= ESP_LOG_DEBUG) {
if (mbedtls_ssl_get_peer_cert(&(tlsDataParams->ssl)) != NULL) {
ESP_LOGD(TAG, "Peer certificate information:");
mbedtls_x509_crt_info((char *) info_buf, sizeof(info_buf) - 1, " ", mbedtls_ssl_get_peer_cert(&(tlsDataParams->ssl)));
ESP_LOGD(TAG, "%s", info_buf);
}
}
return (IoT_Error_t) ret;
}
IoT_Error_t iot_tls_write(Network *pNetwork, unsigned char *pMsg, size_t len, Timer *timer, size_t *written_len) {
size_t written_so_far;
bool isErrorFlag = false;
int frags, ret = 0;
TLSDataParams *tlsDataParams = &(pNetwork->tlsDataParams);
for(written_so_far = 0, frags = 0;
written_so_far < len && !has_timer_expired(timer); written_so_far += ret, frags++) {
while(!has_timer_expired(timer) &&
(ret = mbedtls_ssl_write(&(tlsDataParams->ssl), pMsg + written_so_far, len - written_so_far)) <= 0) {
if(ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) {
ESP_LOGE(TAG, "failed! mbedtls_ssl_write returned -0x%x", -ret);
/* All other negative return values indicate connection needs to be reset.
* Will be caught in ping request so ignored here */
isErrorFlag = true;
break;
}
}
if(isErrorFlag) {
break;
}
}
*written_len = written_so_far;
if(isErrorFlag) {
return NETWORK_SSL_WRITE_ERROR;
} else if(has_timer_expired(timer) && written_so_far != len) {
return NETWORK_SSL_WRITE_TIMEOUT_ERROR;
}
return SUCCESS;
}
IoT_Error_t iot_tls_read(Network *pNetwork, unsigned char *pMsg, size_t len, Timer *timer, size_t *read_len) {
TLSDataParams *tlsDataParams = &(pNetwork->tlsDataParams);
mbedtls_ssl_context *ssl = &(tlsDataParams->ssl);
mbedtls_ssl_config *ssl_conf = &(tlsDataParams->conf);
uint32_t read_timeout;
size_t rxLen = 0;
int ret;
read_timeout = ssl_conf->read_timeout;
while (len > 0) {
/* Make sure we never block on read for longer than timer has left,
but also that we don't block indefinitely (ie read_timeout > 0) */
mbedtls_ssl_conf_read_timeout(ssl_conf, MAX(1, MIN(read_timeout, left_ms(timer))));
ret = mbedtls_ssl_read(ssl, pMsg, len);
/* Restore the old timeout */
mbedtls_ssl_conf_read_timeout(ssl_conf, read_timeout);
if (ret > 0) {
rxLen += ret;
pMsg += ret;
len -= ret;
} else if (ret == 0 || (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE && ret != MBEDTLS_ERR_SSL_TIMEOUT)) {
return NETWORK_SSL_READ_ERROR;
}
// Evaluate timeout after the read to make sure read is done at least once
if (has_timer_expired(timer)) {
break;
}
}
if (len == 0) {
*read_len = rxLen;
return SUCCESS;
}
if (rxLen == 0) {
return NETWORK_SSL_NOTHING_TO_READ;
} else {
return NETWORK_SSL_READ_TIMEOUT_ERROR;
}
}
IoT_Error_t iot_tls_disconnect(Network *pNetwork) {
mbedtls_ssl_context *ssl = &(pNetwork->tlsDataParams.ssl);
int ret = 0;
do {
ret = mbedtls_ssl_close_notify(ssl);
} while(ret == MBEDTLS_ERR_SSL_WANT_WRITE);
/* All other negative return values indicate connection needs to be reset.
* No further action required since this is disconnect call */
return SUCCESS;
}
IoT_Error_t iot_tls_destroy(Network *pNetwork) {
TLSDataParams *tlsDataParams = &(pNetwork->tlsDataParams);
mbedtls_net_free(&(tlsDataParams->server_fd));
mbedtls_x509_crt_free(&(tlsDataParams->clicert));
mbedtls_x509_crt_free(&(tlsDataParams->cacert));
mbedtls_pk_free(&(tlsDataParams->pkey));
mbedtls_ssl_free(&(tlsDataParams->ssl));
mbedtls_ssl_config_free(&(tlsDataParams->conf));
mbedtls_ctr_drbg_free(&(tlsDataParams->ctr_drbg));
mbedtls_entropy_free(&(tlsDataParams->entropy));
return SUCCESS;
}

View File

@@ -0,0 +1,104 @@
/*
* Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* Additions Copyright 2016 Espressif Systems (Shanghai) PTE LTD
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "threads_platform.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Initialize the provided mutex
*
* Call this function to initialize the mutex
*
* @param IoT_Mutex_t - pointer to the mutex to be initialized
* @return IoT_Error_t - error code indicating result of operation
*/
IoT_Error_t aws_iot_thread_mutex_init(IoT_Mutex_t *pMutex) {
pMutex->mutex = xSemaphoreCreateRecursiveMutex();
return pMutex->mutex ? SUCCESS : MUTEX_INIT_ERROR;
}
/**
* @brief Lock the provided mutex
*
* Call this function to lock the mutex before performing a state change
* Blocking, thread will block until lock request fails
*
* @param IoT_Mutex_t - pointer to the mutex to be locked
* @return IoT_Error_t - error code indicating result of operation
*/
IoT_Error_t aws_iot_thread_mutex_lock(IoT_Mutex_t *pMutex) {
xSemaphoreTakeRecursive(pMutex->mutex, portMAX_DELAY);
return SUCCESS;
}
/**
* @brief Try to lock the provided mutex
*
* Call this function to attempt to lock the mutex before performing a state change
* Non-Blocking, immediately returns with failure if lock attempt fails
*
* @param IoT_Mutex_t - pointer to the mutex to be locked
* @return IoT_Error_t - error code indicating result of operation
*/
IoT_Error_t aws_iot_thread_mutex_trylock(IoT_Mutex_t *pMutex) {
if (xSemaphoreTakeRecursive(pMutex->mutex, 0)) {
return SUCCESS;
} else {
return MUTEX_LOCK_ERROR;
}
}
/**
* @brief Unlock the provided mutex
*
* Call this function to unlock the mutex before performing a state change
*
* @param IoT_Mutex_t - pointer to the mutex to be unlocked
* @return IoT_Error_t - error code indicating result of operation
*/
IoT_Error_t aws_iot_thread_mutex_unlock(IoT_Mutex_t *pMutex) {
if (xSemaphoreGiveRecursive(pMutex->mutex)) {
return SUCCESS;
} else {
return MUTEX_UNLOCK_ERROR;
}
}
/**
* @brief Destroy the provided mutex
*
* Call this function to destroy the mutex
*
* @param IoT_Mutex_t - pointer to the mutex to be destroyed
* @return IoT_Error_t - error code indicating result of operation
*/
IoT_Error_t aws_iot_thread_mutex_destroy(IoT_Mutex_t *pMutex) {
vSemaphoreDelete(pMutex->mutex);
return SUCCESS;
}
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,83 @@
/*
* Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* Additions Copyright 2016 Espressif Systems (Shanghai) PTE LTD
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
/**
* @file timer.c
* @brief FreeRTOS implementation of the timer interface uses ticks.
*/
#ifdef __cplusplus
extern "C" {
#endif
#include <limits.h>
#include "timer_platform.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_log.h"
const static char *TAG = "aws_timer";
bool has_timer_expired(Timer *timer) {
uint32_t now = xTaskGetTickCount();
bool expired = (now - timer->start_ticks) >= timer->timeout_ticks;
/* AWS IoT SDK isn't very RTOS friendly because it polls for "done
timers" a lot without ever sleeping on them. So we hack in some
amount of sleeping here: if it seems like the caller is polling
an unexpired timer in a tight loop then we delay a tick to let
things progress elsewhere.
*/
if(!expired && now == timer->last_polled_ticks) {
vTaskDelay(1);
}
timer->last_polled_ticks = now;
return expired;
}
void countdown_ms(Timer *timer, uint32_t timeout) {
timer->start_ticks = xTaskGetTickCount();
timer->timeout_ticks = timeout / portTICK_PERIOD_MS;
timer->last_polled_ticks = 0;
}
uint32_t left_ms(Timer *timer) {
uint32_t now = xTaskGetTickCount();
uint32_t elapsed = now - timer->start_ticks;
if (elapsed < timer->timeout_ticks) {
return (timer->timeout_ticks - elapsed) * portTICK_PERIOD_MS;
} else {
return 0;
}
}
void countdown_sec(Timer *timer, uint32_t timeout) {
if (timeout > UINT32_MAX / 1000) {
ESP_LOGE(TAG, "timeout is out of range: %ds", timeout);
}
countdown_ms(timer, timeout * 1000);
}
void init_timer(Timer *timer) {
timer->start_ticks = 0;
timer->timeout_ticks = 0;
timer->last_polled_ticks = 0;
}
#ifdef __cplusplus
}
#endif

View File

@@ -1,21 +0,0 @@
idf_component_register(PRIV_REQUIRES partition_table)
# Do not generate flash file when building bootloader or is in early expansion of the build
if(BOOTLOADER_BUILD)
return()
endif()
# When secure boot is enabled, do not flash bootloader along with invocation of `idf.py flash`
if(NOT CONFIG_SECURE_BOOT_ENABLED)
set(flash_bootloader FLASH_IN_PROJECT)
endif()
# Set values used in flash_bootloader_args.in and generate flash file
# for bootloader
esptool_py_flash_project_args(bootloader 0x1000
${BOOTLOADER_BUILD_DIR}/bootloader.bin
${flash_bootloader}
FLASH_FILE_TEMPLATE flash_bootloader_args.in)
esptool_py_custom_target(bootloader-flash bootloader "bootloader")
add_dependencies(bootloader partition_table)

View File

@@ -1,566 +1,217 @@
menu "Bootloader config"
choice BOOTLOADER_LOG_LEVEL
bool "Bootloader log verbosity"
default BOOTLOADER_LOG_LEVEL_INFO
help
Specify how much output to see in bootloader logs.
choice LOG_BOOTLOADER_LEVEL
bool "Bootloader log verbosity"
default LOG_BOOTLOADER_LEVEL_INFO
help
Specify how much output to see in bootloader logs.
config BOOTLOADER_LOG_LEVEL_NONE
bool "No output"
config BOOTLOADER_LOG_LEVEL_ERROR
bool "Error"
config BOOTLOADER_LOG_LEVEL_WARN
bool "Warning"
config BOOTLOADER_LOG_LEVEL_INFO
bool "Info"
config BOOTLOADER_LOG_LEVEL_DEBUG
bool "Debug"
config BOOTLOADER_LOG_LEVEL_VERBOSE
bool "Verbose"
endchoice
config LOG_BOOTLOADER_LEVEL_NONE
bool "No output"
config LOG_BOOTLOADER_LEVEL_ERROR
bool "Error"
config LOG_BOOTLOADER_LEVEL_WARN
bool "Warning"
config LOG_BOOTLOADER_LEVEL_INFO
bool "Info"
config LOG_BOOTLOADER_LEVEL_DEBUG
bool "Debug"
config LOG_BOOTLOADER_LEVEL_VERBOSE
bool "Verbose"
endchoice
config BOOTLOADER_LOG_LEVEL
int
default 0 if BOOTLOADER_LOG_LEVEL_NONE
default 1 if BOOTLOADER_LOG_LEVEL_ERROR
default 2 if BOOTLOADER_LOG_LEVEL_WARN
default 3 if BOOTLOADER_LOG_LEVEL_INFO
default 4 if BOOTLOADER_LOG_LEVEL_DEBUG
default 5 if BOOTLOADER_LOG_LEVEL_VERBOSE
config LOG_BOOTLOADER_LEVEL
int
default 0 if LOG_BOOTLOADER_LEVEL_NONE
default 1 if LOG_BOOTLOADER_LEVEL_ERROR
default 2 if LOG_BOOTLOADER_LEVEL_WARN
default 3 if LOG_BOOTLOADER_LEVEL_INFO
default 4 if LOG_BOOTLOADER_LEVEL_DEBUG
default 5 if LOG_BOOTLOADER_LEVEL_VERBOSE
config BOOTLOADER_SPI_WP_PIN
int "SPI Flash WP Pin when customising pins via eFuse (read help)"
range 0 33
default 7
depends on ESPTOOLPY_FLASHMODE_QIO || ESPTOOLPY_FLASHMODE_QOUT
help
This value is ignored unless flash mode is set to QIO or QOUT *and* the SPI flash pins have been
overriden by setting the eFuses SPI_PAD_CONFIG_xxx.
endmenu
When this is the case, the eFuse config only defines 3 of the 4 Quad I/O data pins. The WP pin (aka ESP32
pin "SD_DATA_3" or SPI flash pin "IO2") is not specified in eFuse. That pin number is compiled into the
bootloader instead.
The default value (GPIO 7) is correct for WP pin on ESP32-D2WD integrated flash.
choice BOOTLOADER_VDDSDIO_BOOST
bool "VDDSDIO LDO voltage"
default BOOTLOADER_VDDSDIO_BOOST_1_9V
help
If this option is enabled, and VDDSDIO LDO is set to 1.8V (using eFuse
or MTDI bootstrapping pin), bootloader will change LDO settings to
output 1.9V instead. This helps prevent flash chip from browning out
during flash programming operations.
This option has no effect if VDDSDIO is set to 3.3V, or if the internal
VDDSDIO regulator is disabled via eFuse.
config BOOTLOADER_VDDSDIO_BOOST_1_8V
bool "1.8V"
depends on !ESPTOOLPY_FLASHFREQ_80M
config BOOTLOADER_VDDSDIO_BOOST_1_9V
bool "1.9V"
endchoice
config BOOTLOADER_FACTORY_RESET
bool "GPIO triggers factory reset"
default N
help
Allows to reset the device to factory settings:
- clear one or more data partitions;
- boot from "factory" partition.
The factory reset will occur if there is a GPIO input pulled low while device starts up.
See settings below.
config BOOTLOADER_NUM_PIN_FACTORY_RESET
int "Number of the GPIO input for factory reset"
depends on BOOTLOADER_FACTORY_RESET
range 0 39
default 4
help
The selected GPIO will be configured as an input with internal pull-up enabled.
To trigger a factory reset, this GPIO must be pulled low on reset.
Note that GPIO34-39 do not have an internal pullup and an external one must be provided.
config BOOTLOADER_OTA_DATA_ERASE
bool "Clear OTA data on factory reset (select factory partition)"
depends on BOOTLOADER_FACTORY_RESET
help
The device will boot from "factory" partition (or OTA slot 0 if no factory partition is present) after a
factory reset.
config BOOTLOADER_DATA_FACTORY_RESET
string "Comma-separated names of partitions to clear on factory reset"
depends on BOOTLOADER_FACTORY_RESET
default "nvs"
help
Allows customers to select which data partitions will be erased while factory reset.
Specify the names of partitions as a comma-delimited with optional spaces for readability. (Like this:
"nvs, phy_init, ...")
Make sure that the name specified in the partition table and here are the same.
Partitions of type "app" cannot be specified here.
config BOOTLOADER_APP_TEST
bool "GPIO triggers boot from test app partition"
default N
help
Allows to run the test app from "TEST" partition.
A boot from "test" partition will occur if there is a GPIO input pulled low while device starts up.
See settings below.
config BOOTLOADER_NUM_PIN_APP_TEST
int "Number of the GPIO input to boot TEST partition"
depends on BOOTLOADER_APP_TEST
range 0 39
default 18
help
The selected GPIO will be configured as an input with internal pull-up enabled.
To trigger a test app, this GPIO must be pulled low on reset.
After the GPIO input is deactivated and the device reboots, the old application will boot.
(factory or OTA[x]).
Note that GPIO34-39 do not have an internal pullup and an external one must be provided.
config BOOTLOADER_HOLD_TIME_GPIO
int "Hold time of GPIO for reset/test mode (seconds)"
depends on BOOTLOADER_FACTORY_RESET || BOOTLOADER_APP_TEST
default 5
help
The GPIO must be held low continuously for this period of time after reset
before a factory reset or test partition boot (as applicable) is performed.
config BOOTLOADER_WDT_ENABLE
bool "Use RTC watchdog in start code"
default y
help
Tracks the execution time of startup code.
If the execution time is exceeded, the RTC_WDT will restart system.
It is also useful to prevent a lock up in start code caused by an unstable power source.
NOTE: Tracks the execution time starts from the bootloader code - re-set timeout, while selecting the
source for slow_clk - and ends calling app_main.
Re-set timeout is needed due to WDT uses a SLOW_CLK clock source. After changing a frequency slow_clk a
time of WDT needs to re-set for new frequency.
slow_clk depends on ESP32_RTC_CLK_SRC (INTERNAL_RC or EXTERNAL_CRYSTAL).
config BOOTLOADER_WDT_DISABLE_IN_USER_CODE
bool "Allows RTC watchdog disable in user code"
depends on BOOTLOADER_WDT_ENABLE
default n
help
If it is set, the client must itself reset or disable rtc_wdt in their code (app_main()).
Otherwise rtc_wdt will be disabled before calling app_main function.
Use function rtc_wdt_feed() for resetting counter of rtc_wdt.
Use function rtc_wdt_disable() for disabling rtc_wdt.
config BOOTLOADER_WDT_TIME_MS
int "Timeout for RTC watchdog (ms)"
depends on BOOTLOADER_WDT_ENABLE
default 9000
range 0 120000
help
Verify that this parameter is correct and more then the execution time.
Pay attention to options such as reset to factory, trigger test partition and encryption on boot
- these options can increase the execution time.
Note: RTC_WDT will reset while encryption operations will be performed.
config BOOTLOADER_APP_ROLLBACK_ENABLE
bool "Enable app rollback support"
default n
help
After updating the app, the bootloader runs a new app with the "ESP_OTA_IMG_PENDING_VERIFY" state set.
This state prevents the re-run of this app. After the first boot of the new app in the user code, the
function should be called to confirm the operability of the app or vice versa about its non-operability.
If the app is working, then it is marked as valid. Otherwise, it is marked as not valid and rolls back to
the previous working app. A reboot is performed, and the app is booted before the software update.
Note: If during the first boot a new app the power goes out or the WDT works, then roll back will happen.
Rollback is possible only between the apps with the same security versions.
config BOOTLOADER_APP_ANTI_ROLLBACK
bool "Enable app anti-rollback support"
depends on BOOTLOADER_APP_ROLLBACK_ENABLE
default n
help
This option prevents rollback to previous firmware/application image with lower security version.
config BOOTLOADER_APP_SECURE_VERSION
int "eFuse secure version of app"
depends on BOOTLOADER_APP_ANTI_ROLLBACK
default 0
help
The secure version is the sequence number stored in the header of each firmware.
The security version is set in the bootloader, version is recorded in the eFuse field
as the number of set ones. The allocated number of bits in the efuse field
for storing the security version is limited (see BOOTLOADER_APP_SEC_VER_SIZE_EFUSE_FIELD option).
Bootloader: When bootloader selects an app to boot, an app is selected that has
a security version greater or equal that recorded in eFuse field.
The app is booted with a higher (or equal) secure version.
The security version is worth increasing if in previous versions there is
a significant vulnerability and their use is not acceptable.
Your partition table should has a scheme with ota_0 + ota_1 (without factory).
config BOOTLOADER_APP_SEC_VER_SIZE_EFUSE_FIELD
int "Size of the efuse secure version field"
depends on BOOTLOADER_APP_ANTI_ROLLBACK
range 1 32
default 32
help
The size of the efuse secure version field. Its length is limited to 32 bits.
This determines how many times the security version can be increased.
config BOOTLOADER_EFUSE_SECURE_VERSION_EMULATE
bool "Emulate operations with efuse secure version(only test)"
default n
depends on BOOTLOADER_APP_ANTI_ROLLBACK
help
This option allow emulate read/write operations with efuse secure version.
It allow to test anti-rollback implemention without permanent write eFuse bits.
In partition table should be exist this partition `emul_efuse, data, 5, , 0x2000`.
config BOOTLOADER_FLASH_XMC_SUPPORT
bool "Enable the support for flash chips of XMC (READ HELP FIRST)"
default y
help
Perform the startup flow recommended by XMC. Please consult XMC for the details of this flow.
XMC chips will be forbidden to be used, when this option is disabled.
DON'T DISABLE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.
endmenu # Bootloader
menu "Security features"
# These three are the actual options to check in code,
# selected by the displayed options
config SECURE_SIGNED_ON_BOOT
bool
default y
depends on SECURE_BOOT_ENABLED || SECURE_SIGNED_ON_BOOT_NO_SECURE_BOOT
config SECURE_SIGNED_ON_UPDATE
bool
default y
depends on SECURE_BOOT_ENABLED || SECURE_SIGNED_ON_UPDATE_NO_SECURE_BOOT
config SECURE_SIGNED_APPS
bool
default y
select MBEDTLS_ECP_DP_SECP256R1_ENABLED
select MBEDTLS_ECP_C
select MBEDTLS_ECDH_C
select MBEDTLS_ECDSA_C
depends on SECURE_SIGNED_ON_BOOT || SECURE_SIGNED_ON_UPDATE
config SECURE_SIGNED_APPS_NO_SECURE_BOOT
bool "Require signed app images"
default n
depends on !SECURE_BOOT_ENABLED
help
Require apps to be signed to verify their integrity.
This option uses the same app signature scheme as hardware secure boot, but unlike hardware secure boot it
does not prevent the bootloader from being physically updated. This means that the device can be secured
against remote network access, but not physical access. Compared to using hardware Secure Boot this option
is much simpler to implement.
config SECURE_SIGNED_ON_BOOT_NO_SECURE_BOOT
bool "Bootloader verifies app signatures"
default n
depends on SECURE_SIGNED_APPS_NO_SECURE_BOOT
help
If this option is set, the bootloader will be compiled with code to verify that an app is signed before
booting it.
If hardware secure boot is enabled, this option is always enabled and cannot be disabled.
If hardware secure boot is not enabled, this option doesn't add significant security by itself so most
users will want to leave it disabled.
config SECURE_SIGNED_ON_UPDATE_NO_SECURE_BOOT
bool "Verify app signature on update"
default y
depends on SECURE_SIGNED_APPS_NO_SECURE_BOOT
help
If this option is set, any OTA updated apps will have the signature verified before being considered valid.
When enabled, the signature is automatically checked whenever the esp_ota_ops.h APIs are used for OTA
updates, or esp_image_format.h APIs are used to verify apps.
If hardware secure boot is enabled, this option is always enabled and cannot be disabled.
If hardware secure boot is not enabled, this option still adds significant security against network-based
attackers by preventing spoofing of OTA updates.
config SECURE_BOOT_ENABLED
bool "Enable hardware secure boot in bootloader (READ DOCS FIRST)"
default n
help
Build a bootloader which enables secure boot on first boot.
Once enabled, secure boot will not boot a modified bootloader. The bootloader will only load a partition
table or boot an app if the data has a verified digital signature. There are implications for reflashing
updated apps once secure boot is enabled.
When enabling secure boot, JTAG and ROM BASIC Interpreter are permanently disabled by default.
Refer to https://docs.espressif.com/projects/esp-idf/en/latest/security/secure-boot.html before enabling.
choice SECURE_BOOTLOADER_MODE
bool "Secure bootloader mode"
depends on SECURE_BOOT_ENABLED
default SECURE_BOOTLOADER_ONE_TIME_FLASH
config SECURE_BOOTLOADER_ONE_TIME_FLASH
bool "One-time flash"
help
On first boot, the bootloader will generate a key which is not readable externally or by software. A
digest is generated from the bootloader image itself. This digest will be verified on each subsequent
boot.
Enabling this option means that the bootloader cannot be changed after the first time it is booted.
config SECURE_BOOTLOADER_REFLASHABLE
bool "Reflashable"
help
Generate a reusable secure bootloader key, derived (via SHA-256) from the secure boot signing key.
This allows the secure bootloader to be re-flashed by anyone with access to the secure boot signing
key.
This option is less secure than one-time flash, because a leak of the digest key from one device
allows reflashing of any device that uses it.
endchoice
config SECURE_BOOT_BUILD_SIGNED_BINARIES
bool "Sign binaries during build"
depends on SECURE_SIGNED_APPS
default y
help
Once secure boot or signed app requirement is enabled, app images are required to be signed.
If enabled (default), these binary files are signed as part of the build process. The file named in
"Secure boot private signing key" will be used to sign the image.
If disabled, unsigned app/partition data will be built. They must be signed manually using espsecure.py
(for example, on a remote signing server.)
config SECURE_BOOT_SIGNING_KEY
string "Secure boot private signing key"
depends on SECURE_BOOT_BUILD_SIGNED_BINARIES
default "secure_boot_signing_key.pem"
help
Path to the key file used to sign app images.
config SECURE_BOOT_ENABLED
bool "Enable secure boot in bootloader (READ DOCS FIRST)"
default N
help
Build a bootloader which enables secure boot on first boot.
Key file is an ECDSA private key (NIST256p curve) in PEM format.
Path is evaluated relative to the project directory.
Once enabled, secure boot will not boot a modified bootloader. The bootloader will only load a partition table or boot an app if the data has a verified digital signature. There are implications for reflashing updated apps once secure boot is enabled.
You can generate a new signing key by running the following command:
espsecure.py generate_signing_key secure_boot_signing_key.pem
When enabling secure boot, JTAG and ROM BASIC Interpreter are permanently disabled by default.
See https://docs.espressif.com/projects/esp-idf/en/latest/security/secure-boot.html for details.
config SECURE_BOOT_VERIFICATION_KEY
string "Secure boot public signature verification key"
depends on SECURE_SIGNED_APPS && !SECURE_BOOT_BUILD_SIGNED_BINARIES
default "signature_verification_key.bin"
help
Path to a public key file used to verify signed images. This key is compiled into the bootloader and/or
app, to verify app images.
Refer to http://esp-idf.readthedocs.io/en/latest/security/secure-boot.html before enabling.
Key file is in raw binary format, and can be extracted from a
PEM formatted private key using the espsecure.py
extract_public_key command.
choice SECURE_BOOTLOADER_MODE
bool "Secure bootloader mode"
depends on SECURE_BOOT_ENABLED
default SECURE_BOOTLOADER_ONE_TIME_FLASH
Refer to https://docs.espressif.com/projects/esp-idf/en/latest/security/secure-boot.html before enabling.
config SECURE_BOOTLOADER_ONE_TIME_FLASH
bool "One-time flash"
help
On first boot, the bootloader will generate a key which is not readable externally or by software. A digest is generated from the bootloader image itself. This digest will be verified on each subsequent boot.
choice SECURE_BOOTLOADER_KEY_ENCODING
bool "Hardware Key Encoding"
depends on SECURE_BOOTLOADER_REFLASHABLE
default SECURE_BOOTLOADER_KEY_ENCODING_256BIT
help
Enabling this option means that the bootloader cannot be changed after the first time it is booted.
In reflashable secure bootloader mode, a hardware key is derived from the signing key (with SHA-256) and
can be written to eFuse with espefuse.py.
config SECURE_BOOTLOADER_REFLASHABLE
bool "Reflashable"
help
Generate a reusable secure bootloader key, derived (via SHA-256) from the secure boot signing key.
Normally this is a 256-bit key, but if 3/4 Coding Scheme is used on the device then the eFuse key is
truncated to 192 bits.
This allows the secure bootloader to be re-flashed by anyone with access to the secure boot signing key.
This configuration item doesn't change any firmware code, it only changes the size of key binary which is
generated at build time.
This option is less secure than one-time flash, because a leak of the digest key from one device allows reflashing of any device that uses it.
config SECURE_BOOTLOADER_KEY_ENCODING_256BIT
bool "No encoding (256 bit key)"
endchoice
config SECURE_BOOTLOADER_KEY_ENCODING_192BIT
bool "3/4 encoding (192 bit key)"
config SECURE_BOOT_BUILD_SIGNED_BINARIES
bool "Sign binaries during build"
depends on SECURE_BOOT_ENABLED
default y
help
Once secure boot is enabled, bootloader will only boot if partition table and app image are signed.
endchoice
If enabled, these binary files are signed as part of the build process. The file named in "Secure boot private signing key" will be used to sign the image.
config SECURE_BOOT_INSECURE
bool "Allow potentially insecure options"
depends on SECURE_BOOT_ENABLED
default N
help
You can disable some of the default protections offered by secure boot, in order to enable testing or a
custom combination of security features.
Only enable these options if you are very sure.
Refer to https://docs.espressif.com/projects/esp-idf/en/latest/security/secure-boot.html before enabling.
config SECURE_FLASH_ENC_ENABLED
bool "Enable flash encryption on boot (READ DOCS FIRST)"
default N
select SPI_FLASH_ENABLE_ENCRYPTED_READ_WRITE
help
If this option is set, flash contents will be encrypted by the bootloader on first boot.
If disabled, unsigned app/partition data will be built. They must be signed manually using espsecure.py (for example, on a remote signing server.)
Note: After first boot, the system will be permanently encrypted. Re-flashing an encrypted
system is complicated and not always possible.
Read https://docs.espressif.com/projects/esp-idf/en/latest/security/flash-encryption.html
before enabling.
choice SECURE_FLASH_ENCRYPTION_MODE
bool "Enable usage mode"
depends on SECURE_FLASH_ENC_ENABLED
default SECURE_FLASH_ENCRYPTION_MODE_DEVELOPMENT
help
By default Development mode is enabled which allows UART bootloader to perform flash encryption operations
Select Release mode only for production or manufacturing. Once enabled you can not reflash using UART
bootloader
Refer to https://docs.espressif.com/projects/esp-idf/en/latest/security/secure-boot.html and
https://docs.espressif.com/projects/esp-idf/en/latest/security/flash-encryption.html for details.
config SECURE_FLASH_ENCRYPTION_MODE_DEVELOPMENT
bool "Development(NOT SECURE)"
select SECURE_FLASH_UART_BOOTLOADER_ALLOW_ENC
config SECURE_FLASH_ENCRYPTION_MODE_RELEASE
bool "Release"
select PARTITION_TABLE_MD5 if !ESP32_COMPATIBLE_PRE_V3_1_BOOTLOADERS
endchoice
menu "Potentially insecure options"
visible if SECURE_FLASH_ENCRYPTION_MODE_DEVELOPMENT || SECURE_BOOT_INSECURE
# NOTE: Options in this menu NEED to have SECURE_BOOT_INSECURE
# and/or SECURE_FLASH_ENCRYPTION_MODE_DEVELOPMENT in "depends on", as the menu
# itself doesn't enable/disable its children (if it's not set,
# it's possible for the insecure menu to be disabled but the insecure option
# to remain on which is very bad.)
config SECURE_BOOT_ALLOW_ROM_BASIC
bool "Leave ROM BASIC Interpreter available on reset"
depends on SECURE_BOOT_INSECURE || SECURE_FLASH_ENCRYPTION_MODE_DEVELOPMENT
default N
help
By default, the BASIC ROM Console starts on reset if no valid bootloader is
read from the flash.
When either flash encryption or secure boot are enabled, the default is to
disable this BASIC fallback mode permanently via eFuse.
If this option is set, this eFuse is not burned and the BASIC ROM Console may
remain accessible. Only set this option in testing environments.
config SECURE_BOOT_ALLOW_JTAG
bool "Allow JTAG Debugging"
depends on SECURE_BOOT_INSECURE || SECURE_FLASH_ENCRYPTION_MODE_DEVELOPMENT
default N
help
If not set (default), the bootloader will permanently disable JTAG (across entire chip) on first boot
when either secure boot or flash encryption is enabled.
Setting this option leaves JTAG on for debugging, which negates all protections of flash encryption
and some of the protections of secure boot.
Only set this option in testing environments.
config SECURE_BOOT_ALLOW_SHORT_APP_PARTITION
bool "Allow app partition length not 64KB aligned"
depends on SECURE_BOOT_INSECURE
help
If not set (default), app partition size must be a multiple of 64KB. App images are padded to 64KB
length, and the bootloader checks any trailing bytes after the signature (before the next 64KB
boundary) have not been written. This is because flash cache maps entire 64KB pages into the address
space. This prevents an attacker from appending unverified data after the app image in the flash,
causing it to be mapped into the address space.
Setting this option allows the app partition length to be unaligned, and disables padding of the app
image to this length. It is generally not recommended to set this option, unless you have a legacy
partitioning scheme which doesn't support 64KB aligned partition lengths.
config SECURE_FLASH_UART_BOOTLOADER_ALLOW_ENC
bool "Leave UART bootloader encryption enabled"
depends on SECURE_FLASH_ENCRYPTION_MODE_DEVELOPMENT
default N
help
If not set (default), the bootloader will permanently disable UART bootloader encryption access on
first boot. If set, the UART bootloader will still be able to access hardware encryption.
It is recommended to only set this option in testing environments.
config SECURE_FLASH_UART_BOOTLOADER_ALLOW_DEC
bool "Leave UART bootloader decryption enabled"
depends on SECURE_FLASH_ENCRYPTION_MODE_DEVELOPMENT
default N
help
If not set (default), the bootloader will permanently disable UART bootloader decryption access on
first boot. If set, the UART bootloader will still be able to access hardware decryption.
Only set this option in testing environments. Setting this option allows complete bypass of flash
encryption.
config SECURE_FLASH_UART_BOOTLOADER_ALLOW_CACHE
bool "Leave UART bootloader flash cache enabled"
depends on SECURE_FLASH_ENCRYPTION_MODE_DEVELOPMENT
default N
help
If not set (default), the bootloader will permanently disable UART bootloader flash cache access on
first boot. If set, the UART bootloader will still be able to access the flash cache.
Only set this option in testing environments.
config SECURE_FLASH_REQUIRE_ALREADY_ENABLED
bool "Require flash encryption to be already enabled"
depends on SECURE_FLASH_ENCRYPTION_MODE_DEVELOPMENT
default N
help
If not set (default), and flash encryption is not yet enabled in eFuses, the 2nd stage bootloader
will enable flash encryption: generate the flash encryption key and program eFuses.
If this option is set, and flash encryption is not yet enabled, the bootloader will error out and
reboot.
If flash encryption is enabled in eFuses, this option does not change the bootloader behavior.
Only use this option in testing environments, to avoid accidentally enabling flash encryption on
the wrong device. The device needs to have flash encryption already enabled using espefuse.py.
endmenu # Potentially Insecure
config SECURE_DISABLE_ROM_DL_MODE
bool "Permanently disable ROM Download Mode"
depends on ESP32_REV_MIN_3
default n
help
If set, during startup the app will burn an eFuse bit to permanently disable the UART ROM
Download Mode. This prevents any future use of esptool.py, espefuse.py and similar tools.
Once disabled, if the SoC is booted with strapping pins set for ROM Download Mode
then an error is printed instead.
It is recommended to enable this option in any production application where Flash
Encryption and/or Secure Boot is enabled and access to Download Mode is not required.
It is also possible to permanently disable Download Mode by calling
esp_efuse_disable_rom_download_mode() at runtime.
endmenu # Security features
config SECURE_BOOT_SIGNING_KEY
string "Secure boot private signing key"
depends on SECURE_BOOT_BUILD_SIGNED_BINARIES
default secure_boot_signing_key.pem
help
Path to the key file used to sign partition tables and app images for secure boot. Once secure boot is enabled, bootloader will only boot if partition table and app image are signed.
Key file is an ECDSA private key (NIST256p curve) in PEM format.
Path is evaluated relative to the project directory.
You can generate a new signing key by running the following command:
espsecure.py generate_signing_key secure_boot_signing_key.pem
See docs/security/secure-boot.rst for details.
config SECURE_BOOT_VERIFICATION_KEY
string "Secure boot public signature verification key"
depends on SECURE_BOOT_ENABLED && !SECURE_BOOT_BUILD_SIGNED_BINARIES
default signature_verification_key.bin
help
Path to a public key file used to verify signed images. This key is compiled into the bootloader,
and may also be used to verify signatures on OTA images after download.
Key file is in raw binary format, and can be extracted from a
PEM formatted private key using the espsecure.py
extract_public_key command.
Refer to http://esp-idf.readthedocs.io/en/latest/security/secure-boot.html before enabling.
config SECURE_BOOT_INSECURE
bool "Allow potentially insecure options"
depends on SECURE_BOOT_ENABLED
default N
help
You can disable some of the default protections offered by secure boot, in order to enable testing or a custom combination of security features.
Only enable these options if you are very sure.
Refer to http://esp-idf.readthedocs.io/en/latest/security/secure-boot.html before enabling.
config FLASH_ENCRYPTION_ENABLED
bool "Enable flash encryption on boot (READ DOCS FIRST)"
default N
help
If this option is set, flash contents will be encrypted by the bootloader on first boot.
Note: After first boot, the system will be permanently encrypted. Re-flashing an encrypted
system is complicated and not always possible.
Read http://esp-idf.readthedocs.io/en/latest/security/flash-encryption.html before enabling.
config FLASH_ENCRYPTION_INSECURE
bool "Allow potentially insecure options"
depends on FLASH_ENCRYPTION_ENABLED
default N
help
You can disable some of the default protections offered by flash encryption, in order to enable testing or a custom combination of security features.
Only enable these options if you are very sure.
Refer to docs/security/secure-boot.rst and docs/security/flash-encryption.rst for details.
menu "Potentially insecure options"
visible if FLASH_ENCRYPTION_INSECURE || SECURE_BOOT_INSECURE
# NOTE: Options in this menu NEED to have SECURE_BOOT_INSECURE
# and/or FLASH_ENCRYPTION_INSECURE in "depends on", as the menu
# itself doesn't enable/disable its children (if it's not set,
# it's possible for the insecure menu to be disabled but the insecure option
# to remain on which is very bad.)
config SECURE_BOOT_ALLOW_ROM_BASIC
bool "Leave ROM BASIC Interpreter available on reset"
depends on SECURE_BOOT_INSECURE
default N
help
If not set (default), bootloader permanently disables ROM BASIC (on UART console) as a fallback if the bootloader image becomes invalid. This happens on first boot.
Only set this option in testing environments.
config SECURE_BOOT_ALLOW_JTAG
bool "Allow JTAG Debugging"
depends on SECURE_BOOT_INSECURE || FLASH_ENCRYPTION_INSECURE
default N
help
If not set (default), the bootloader will permanently disable JTAG (across entire chip) on first boot when either secure boot or flash encryption is enabled.
Setting this option leaves JTAG on for debugging, which negates all protections of flash encryption and some of the protections of secure boot.
Only set this option in testing environments.
config FLASH_ENCRYPTION_UART_BOOTLOADER_ALLOW_ENCRYPT
bool "Leave UART bootloader encryption enabled"
depends on FLASH_ENCRYPTION_INSECURE
default N
help
If not set (default), the bootloader will permanently disable UART bootloader encryption access on first boot. If set, the UART bootloader will still be able to access hardware encryption.
It is recommended to only set this option in testing environments.
config FLASH_ENCRYPTION_UART_BOOTLOADER_ALLOW_DECRYPT
bool "Leave UART bootloader decryption enabled"
depends on FLASH_ENCRYPTION_INSECURE
default N
help
If not set (default), the bootloader will permanently disable UART bootloader decryption access on first boot. If set, the UART bootloader will still be able to access hardware decryption.
Only set this option in testing environments. Setting this option allows complete bypass of flash encryption.
config FLASH_ENCRYPTION_UART_BOOTLOADER_ALLOW_CACHE
bool "Leave UART bootloader flash cache enabled"
depends on FLASH_ENCRYPTION_INSECURE
default N
help
If not set (default), the bootloader will permanently disable UART bootloader flash cache access on first boot. If set, the UART bootloader will still be able to access the flash cache.
Only set this option in testing environments.
config SECURE_BOOT_TEST_MODE
bool "Secure boot test mode: don't permanently set any efuses"
depends on SECURE_BOOT_INSECURE
default N
help
If this option is set, all permanent secure boot changes (via Efuse) are disabled.
Log output will state changes which would be applied, but they will not be.
This option is for testing purposes only - it completely disables secure boot protection.
endmenu # potentially insecure
endmenu

View File

@@ -1,19 +1,20 @@
# Bootloader component (top-level project parts)
#
# Bootloader component
#
# The bootloader is not a real component that gets linked into the project.
# Instead it is an entire standalone project (in subproject/) that gets
# built in the upper project's build directory. This Makefile.projbuild provides
# the glue to build the bootloader project from the original project. It
# basically runs Make in the subproject/ directory but it needs to
# zero some variables the ESP-IDF project.mk makefile exports first, to not
# let them interfere.
# Instead it is an entire standalone project ( in src/) that gets built in
# the upper projects build directory. This Makefile.projbuild provides the
# glue to build the bootloader project from the original project. It
# basically runs Make in the src/ directory but it needs to zero some variables
# the ESP-IDF project.mk makefile exports first, to not let them interfere.
#
ifndef IS_BOOTLOADER_BUILD
BOOTLOADER_COMPONENT_PATH := $(COMPONENT_PATH)
BOOTLOADER_BUILD_DIR=$(abspath $(BUILD_DIR_BASE)/bootloader)
BOOTLOADER_BIN=$(BOOTLOADER_BUILD_DIR)/bootloader.bin
# signing key path is resolved relative to the project directory
CONFIG_SECURE_BOOT_SIGNING_KEY ?=
SECURE_BOOT_SIGNING_KEY=$(abspath $(call dequote,$(CONFIG_SECURE_BOOT_SIGNING_KEY)))
export SECURE_BOOT_SIGNING_KEY # used by bootloader_support component
@@ -21,42 +22,28 @@ export SECURE_BOOT_SIGNING_KEY # used by bootloader_support component
BOOTLOADER_OFFSET := 0x1000
# Custom recursive make for bootloader sub-project
#
# NB: Some variables are cleared in the environment, not
# overriden, because they need to be re-defined in the child
# project.
BOOTLOADER_MAKE= +\
PROJECT_PATH= \
COMPONENT_DIRS= \
$(MAKE) -C $(BOOTLOADER_COMPONENT_PATH)/subproject \
V=$(V) \
BUILD_DIR_BASE=$(BOOTLOADER_BUILD_DIR) \
TEST_COMPONENTS= \
TESTS_ALL= \
EXCLUDE_COMPONENTS=
BOOTLOADER_MAKE=+$(MAKE) -C $(BOOTLOADER_COMPONENT_PATH)/src \
V=$(V) BUILD_DIR_BASE=$(BOOTLOADER_BUILD_DIR) TEST_COMPONENTS= TESTS_ALL=
.PHONY: bootloader-clean bootloader-flash bootloader-list-components bootloader $(BOOTLOADER_BIN)
.PHONY: bootloader-clean bootloader-flash bootloader $(BOOTLOADER_BIN)
$(BOOTLOADER_BIN): $(SDKCONFIG_MAKEFILE)
$(BOOTLOADER_MAKE) $@
clean: bootloader-clean
bootloader-list-components:
$(BOOTLOADER_MAKE) list-components
ifndef CONFIG_SECURE_BOOT_ENABLED
# If secure boot disabled, bootloader flashing is integrated
# with 'make flash' and no warnings are printed.
bootloader: $(BOOTLOADER_BIN) | check_python_dependencies
bootloader: $(BOOTLOADER_BIN)
@echo $(SEPARATOR)
@echo "Bootloader built. Default flash command is:"
@echo "$(ESPTOOLPY_WRITE_FLASH) $(BOOTLOADER_OFFSET) $^"
ESPTOOL_ALL_FLASH_ARGS += $(BOOTLOADER_OFFSET) $(BOOTLOADER_BIN)
bootloader-flash: $(BOOTLOADER_BIN) $(call prereq_if_explicit,erase_flash) | check_python_dependencies
bootloader-flash: $(BOOTLOADER_BIN) $(call prereq_if_explicit,erase_flash)
$(ESPTOOLPY_WRITE_FLASH) 0x1000 $^
else ifdef CONFIG_SECURE_BOOTLOADER_ONE_TIME_FLASH
@@ -67,7 +54,7 @@ else ifdef CONFIG_SECURE_BOOTLOADER_ONE_TIME_FLASH
# The flashing command is deliberately printed without an auto-reset
# step, so the device doesn't immediately reset to flash itself.
bootloader: $(BOOTLOADER_BIN) | check_python_dependencies
bootloader: $(BOOTLOADER_BIN)
@echo $(SEPARATOR)
@echo "Bootloader built. One-time flash command is:"
@echo "$(subst hard_reset,no_reset,$(ESPTOOLPY_WRITE_FLASH)) $(BOOTLOADER_OFFSET) $(BOOTLOADER_BIN)"
@@ -78,18 +65,12 @@ else ifdef CONFIG_SECURE_BOOTLOADER_REFLASHABLE
# Reflashable secure bootloader
# generates a digest binary (bootloader + digest)
ifdef CONFIG_SECURE_BOOTLOADER_KEY_ENCODING_192BIT
KEY_DIGEST_LEN=192
else
KEY_DIGEST_LEN=256
endif
BOOTLOADER_DIGEST_BIN := $(BOOTLOADER_BUILD_DIR)/bootloader-reflash-digest.bin
SECURE_BOOTLOADER_KEY := $(BOOTLOADER_BUILD_DIR)/secure-bootloader-key-$(KEY_DIGEST_LEN).bin
SECURE_BOOTLOADER_KEY := $(BOOTLOADER_BUILD_DIR)/secure-bootloader-key.bin
ifdef CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES
$(SECURE_BOOTLOADER_KEY): $(SECURE_BOOT_SIGNING_KEY) | check_python_dependencies
$(ESPSECUREPY) digest_private_key --keylen $(KEY_DIGEST_LEN) -k $< $@
$(SECURE_BOOTLOADER_KEY): $(SECURE_BOOT_SIGNING_KEY)
$(ESPSECUREPY) digest_private_key -k $< $@
else
$(SECURE_BOOTLOADER_KEY):
@echo "No pre-generated key for a reflashable secure bootloader is available, due to signing configuration."
@@ -111,23 +92,29 @@ bootloader: $(BOOTLOADER_DIGEST_BIN)
@echo "* After first boot, only re-flashes of this kind (with same key) will be accepted."
@echo "* Not recommended to re-use the same secure boot keyfile on multiple production devices."
$(BOOTLOADER_DIGEST_BIN): $(BOOTLOADER_BIN) $(SECURE_BOOTLOADER_KEY) | check_python_dependencies
$(BOOTLOADER_DIGEST_BIN): $(BOOTLOADER_BIN) $(SECURE_BOOTLOADER_KEY)
@echo "DIGEST $(notdir $@)"
$(ESPSECUREPY) digest_secure_bootloader -k $(SECURE_BOOTLOADER_KEY) -o $@ $<
$(Q) $(ESPSECUREPY) digest_secure_bootloader -k $(SECURE_BOOTLOADER_KEY) -o $@ $<
else # CONFIG_SECURE_BOOT_ENABLED && !CONFIG_SECURE_BOOTLOADER_REFLASHABLE && !CONFIG_SECURE_BOOTLOADER_ONE_TIME_FLASH
else
bootloader:
@echo "Invalid bootloader target: bad sdkconfig?"
@exit 1
endif
ifndef CONFIG_SECURE_BOOT_ENABLED
# don't build bootloader by default if secure boot is enabled
# don't build bootloader by default is secure boot is enabled
all_binaries: $(BOOTLOADER_BIN)
endif
bootloader-clean: $(SDKCONFIG_MAKEFILE)
bootloader-clean:
$(BOOTLOADER_MAKE) app-clean
ifdef CONFIG_SECURE_BOOTLOADER_REFLASHABLE
rm -f $(SECURE_BOOTLOADER_KEY) $(BOOTLOADER_DIGEST_BIN)
$(BOOTLOADER_BUILD_DIR):
mkdir -p $@
else
CFLAGS += -D BOOTLOADER_BUILD=1 -I $(IDF_PATH)/components/esp32/include
endif

View File

@@ -1,7 +0,0 @@
# bootloader component is special, as bootloader is also a project.
#
# This top-level component is only configuration files for the IDF project.
#
# See Makefile.projbuild for the targets which actually build the bootloader.
COMPONENT_CONFIG_ONLY := 1

View File

@@ -1,4 +0,0 @@
--flash_mode ${ESPFLASHMODE}
--flash_size ${ESPFLASHSIZE}
--flash_freq ${ESPFLASHFREQ}
${OFFSET} ${IMAGE}

View File

@@ -1,130 +0,0 @@
set(BOOTLOADER_OFFSET 0x1000)
# Do not generate flash file when building bootloader
if(BOOTLOADER_BUILD)
return()
endif()
# Glue to build the bootloader subproject binary as an external
# cmake project under this one
#
#
idf_build_get_property(build_dir BUILD_DIR)
set(BOOTLOADER_BUILD_DIR "${build_dir}/bootloader")
set(bootloader_binary_files
"${BOOTLOADER_BUILD_DIR}/bootloader.elf"
"${BOOTLOADER_BUILD_DIR}/bootloader.bin"
"${BOOTLOADER_BUILD_DIR}/bootloader.map"
)
idf_build_get_property(project_dir PROJECT_DIR)
# There are some additional processing when CONFIG_CONFIG_SECURE_SIGNED_APPS. This happens
# when either CONFIG_SECURE_BOOT_ENABLED or SECURE_BOOT_BUILD_SIGNED_BINARIES.
# For both cases, the user either sets binaries to be signed during build or not
# using CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES.
#
# Regardless, pass the main project's keys (signing/verification) to the bootloader subproject
# via config.
if(CONFIG_SECURE_SIGNED_APPS)
add_custom_target(gen_secure_boot_keys)
if(CONFIG_SECURE_BOOT_ENABLED)
# Check that the configuration is sane
if((CONFIG_SECURE_BOOTLOADER_REFLASHABLE AND CONFIG_SECURE_BOOTLOADER_ONE_TIME_FLASH) OR
(NOT CONFIG_SECURE_BOOTLOADER_REFLASHABLE AND NOT CONFIG_SECURE_BOOTLOADER_ONE_TIME_FLASH))
fail_at_build_time(bootloader "Invalid bootloader target: bad sdkconfig?")
endif()
if(CONFIG_SECURE_BOOTLOADER_REFLASHABLE)
set(bootloader_binary_files
${bootloader_binary_files}
"${BOOTLOADER_BUILD_DIR}/bootloader-reflash-digest.bin"
"${BOOTLOADER_BUILD_DIR}/secure-bootloader-key-192.bin"
"${BOOTLOADER_BUILD_DIR}/secure-bootloader-key-256.bin"
)
endif()
endif()
# Since keys are usually given relative to main project dir, get the absolute paths to the keys
# for use by the bootloader subproject. Replace the values in config with these absolute paths,
# so that bootloader subproject does not need to assume main project dir to obtain path to the keys.
if(CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES)
get_filename_component(secure_boot_signing_key
"${CONFIG_SECURE_BOOT_SIGNING_KEY}"
ABSOLUTE BASE_DIR "${project_dir}")
if(NOT EXISTS ${secure_boot_signing_key})
# If the signing key is not found, create a phony gen_secure_boot_signing_key target that
# fails the build. fail_at_build_time causes a cmake run next time
# (to pick up a new signing key if one exists, etc.)
fail_at_build_time(gen_secure_boot_signing_key
"Secure Boot Signing Key ${CONFIG_SECURE_BOOT_SIGNING_KEY} does not exist. Generate using:"
"\tespsecure.py generate_signing_key ${CONFIG_SECURE_BOOT_SIGNING_KEY}")
else()
add_custom_target(gen_secure_boot_signing_key)
endif()
set(SECURE_BOOT_SIGNING_KEY ${secure_boot_signing_key}) # needed by some other components
set(sign_key_arg "-DSECURE_BOOT_SIGNING_KEY=${secure_boot_signing_key}")
add_dependencies(gen_secure_boot_keys gen_secure_boot_signing_key)
else()
get_filename_component(secure_boot_verification_key
${CONFIG_SECURE_BOOT_VERIFICATION_KEY}
ABSOLUTE BASE_DIR "${project_dir}")
if(NOT EXISTS ${secure_boot_verification_key})
# If the verification key is not found, create a phony gen_secure_boot_verification_key target that
# fails the build. fail_at_build_time causes a cmake run next time
# (to pick up a new verification key if one exists, etc.)
fail_at_build_time(gen_secure_boot_verification_key
"Secure Boot Verification Public Key ${CONFIG_SECURE_BOOT_VERIFICATION_KEY} does not exist."
"\tThis can be extracted from the private signing key."
"\tSee docs/security/secure-boot.rst for details.")
else()
add_custom_target(gen_secure_boot_verification_key)
endif()
set(ver_key_arg "-DSECURE_BOOT_VERIFICATION_KEY=${secure_boot_verification_key}")
add_dependencies(gen_secure_boot_keys gen_secure_boot_verification_key)
endif()
endif()
idf_build_get_property(idf_path IDF_PATH)
idf_build_get_property(idf_target IDF_TARGET)
idf_build_get_property(sdkconfig SDKCONFIG)
idf_build_get_property(python PYTHON)
idf_build_get_property(extra_cmake_args EXTRA_CMAKE_ARGS)
externalproject_add(bootloader
SOURCE_DIR "${CMAKE_CURRENT_LIST_DIR}/subproject"
BINARY_DIR "${BOOTLOADER_BUILD_DIR}"
CMAKE_ARGS -DSDKCONFIG=${sdkconfig} -DIDF_PATH=${idf_path} -DIDF_TARGET=${idf_target} -DPYTHON=${python}
-DPYTHON_DEPS_CHECKED=1
-DEXTRA_COMPONENT_DIRS=${CMAKE_CURRENT_LIST_DIR}
${sign_key_arg} ${ver_key_arg}
# LEGACY_INCLUDE_COMMON_HEADERS has to be passed in via cache variable since
# the bootloader common component requirements depends on this and
# config variables are not available before project() call.
-DLEGACY_INCLUDE_COMMON_HEADERS=${CONFIG_LEGACY_INCLUDE_COMMON_HEADERS}
${extra_cmake_args}
INSTALL_COMMAND ""
BUILD_ALWAYS 1 # no easy way around this...
BUILD_BYPRODUCTS ${bootloader_binary_files}
)
if(CONFIG_SECURE_SIGNED_APPS)
add_dependencies(bootloader gen_secure_boot_keys)
endif()
# this is a hack due to an (annoying) shortcoming in cmake, it can't
# extend the 'clean' target to the external project
# see thread: https://cmake.org/pipermail/cmake/2016-December/064660.html
#
# So for now we just have the top-level build remove the final build products...
set_property(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" APPEND PROPERTY
ADDITIONAL_MAKE_CLEAN_FILES
${bootloader_binary_files})

View File

@@ -1,22 +0,0 @@
# sdkconfig replacement configurations for deprecated options formatted as
# CONFIG_DEPRECATED_OPTION CONFIG_NEW_OPTION
CONFIG_LOG_BOOTLOADER_LEVEL CONFIG_BOOTLOADER_LOG_LEVEL
CONFIG_LOG_BOOTLOADER_LEVEL_NONE CONFIG_BOOTLOADER_LOG_LEVEL_NONE
CONFIG_LOG_BOOTLOADER_LEVEL_ERROR CONFIG_BOOTLOADER_LOG_LEVEL_ERROR
CONFIG_LOG_BOOTLOADER_LEVEL_WARN CONFIG_BOOTLOADER_LOG_LEVEL_WARN
CONFIG_LOG_BOOTLOADER_LEVEL_INFO CONFIG_BOOTLOADER_LOG_LEVEL_INFO
CONFIG_LOG_BOOTLOADER_LEVEL_DEBUG CONFIG_BOOTLOADER_LOG_LEVEL_DEBUG
CONFIG_LOG_BOOTLOADER_LEVEL_VERBOSE CONFIG_BOOTLOADER_LOG_LEVEL_VERBOSE
CONFIG_APP_ROLLBACK_ENABLE CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE
CONFIG_APP_ANTI_ROLLBACK CONFIG_BOOTLOADER_APP_ANTI_ROLLBACK
CONFIG_APP_SECURE_VERSION CONFIG_BOOTLOADER_APP_SECURE_VERSION
CONFIG_APP_SECURE_VERSION_SIZE_EFUSE_FIELD CONFIG_BOOTLOADER_APP_SEC_VER_SIZE_EFUSE_FIELD
CONFIG_EFUSE_SECURE_VERSION_EMULATE CONFIG_BOOTLOADER_EFUSE_SECURE_VERSION_EMULATE
CONFIG_FLASH_ENCRYPTION_ENABLED CONFIG_SECURE_FLASH_ENC_ENABLED
CONFIG_FLASH_ENCRYPTION_INSECURE CONFIG_SECURE_FLASH_ENCRYPTION_MODE_DEVELOPMENT
CONFIG_FLASH_ENCRYPTION_UART_BOOTLOADER_ALLOW_ENCRYPT CONFIG_SECURE_FLASH_UART_BOOTLOADER_ALLOW_ENC
CONFIG_FLASH_ENCRYPTION_UART_BOOTLOADER_ALLOW_DECRYPT CONFIG_SECURE_FLASH_UART_BOOTLOADER_ALLOW_DEC
CONFIG_FLASH_ENCRYPTION_UART_BOOTLOADER_ALLOW_CACHE CONFIG_SECURE_FLASH_UART_BOOTLOADER_ALLOW_CACHE

View File

@@ -0,0 +1,21 @@
#
# This is a project Makefile. It is assumed the directory this Makefile resides in is a
# project subdirectory.
#
PROJECT_NAME := bootloader
#We cannot include the esp32 component directly but we need its includes.
#This is fixed by adding CFLAGS from Makefile.projbuild
COMPONENTS := esptool_py bootloader bootloader_support log spi_flash micro-ecc soc
# The bootloader pseudo-component is also included in this build, for its Kconfig.projbuild to be included.
#
# IS_BOOTLOADER_BUILD tells the component Makefile.projbuild to be a no-op
IS_BOOTLOADER_BUILD := 1
export IS_BOOTLOADER_BUILD
# include the top-level "project" include directory, for sdkconfig.h
CFLAGS += -I$(BUILD_DIR_BASE)/../include
include $(IDF_PATH)/make/project.mk

View File

@@ -0,0 +1,4 @@
# Submodules normally added in component.mk, but fully qualified
# paths can be added at this level (we need binary librtc to be
# available to link bootloader).
COMPONENT_SUBMODULES += $(IDF_PATH)/components/esp32/lib

View File

@@ -21,32 +21,24 @@ extern "C"
{
#endif
#include "esp_flash_partitions.h"
#include "esp_flash_data_types.h"
#include "soc/soc.h"
#define SPI_SEC_SIZE 0x1000
#define SPI_ERROR_LOG "spi flash error"
#define MAX_OTA_SLOTS 16
typedef struct {
esp_partition_pos_t ota_info;
esp_partition_pos_t factory;
esp_partition_pos_t test;
esp_partition_pos_t ota[MAX_OTA_SLOTS];
esp_partition_pos_t ota[16];
uint32_t app_count;
uint32_t selected_subtype;
} bootloader_state_t;
bool flash_encrypt(bootloader_state_t *bs);
/* Indices used by index_to_partition are the OTA index
number, or these special constants */
#define FACTORY_INDEX (-1)
#define TEST_APP_INDEX (-2)
#define INVALID_INDEX (-99)
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,857 @@
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <string.h>
#include <stdint.h>
#include <limits.h>
#include <sys/param.h>
#include "esp_attr.h"
#include "esp_log.h"
#include "rom/cache.h"
#include "rom/efuse.h"
#include "rom/ets_sys.h"
#include "rom/spi_flash.h"
#include "rom/crc.h"
#include "rom/rtc.h"
#include "rom/uart.h"
#include "rom/gpio.h"
#include "rom/secure_boot.h"
#include "soc/soc.h"
#include "soc/cpu.h"
#include "soc/rtc.h"
#include "soc/dport_reg.h"
#include "soc/io_mux_reg.h"
#include "soc/efuse_reg.h"
#include "soc/rtc_cntl_reg.h"
#include "soc/timer_group_reg.h"
#include "soc/gpio_reg.h"
#include "soc/gpio_sig_map.h"
#include "sdkconfig.h"
#include "esp_image_format.h"
#include "esp_secure_boot.h"
#include "esp_flash_encrypt.h"
#include "esp_flash_partitions.h"
#include "bootloader_flash.h"
#include "bootloader_random.h"
#include "bootloader_config.h"
#include "flash_qio_mode.h"
extern int _bss_start;
extern int _bss_end;
static const char* TAG = "boot";
/*
We arrive here after the bootloader finished loading the program from flash. The hardware is mostly uninitialized,
flash cache is down and the app CPU is in reset. We do have a stack, so we can do the initialization in C.
*/
void bootloader_main();
static void unpack_load_app(const esp_partition_pos_t *app_node);
void print_flash_info(const esp_image_header_t* pfhdr);
static void set_cache_and_start_app(uint32_t drom_addr,
uint32_t drom_load_addr,
uint32_t drom_size,
uint32_t irom_addr,
uint32_t irom_load_addr,
uint32_t irom_size,
uint32_t entry_addr);
static void update_flash_config(const esp_image_header_t* pfhdr);
static void clock_configure(void);
static void uart_console_configure(void);
static void wdt_reset_check(void);
void IRAM_ATTR call_start_cpu0()
{
cpu_configure_region_protection();
//Clear bss
memset(&_bss_start, 0, (&_bss_end - &_bss_start) * sizeof(_bss_start));
/* completely reset MMU for both CPUs
(in case serial bootloader was running) */
Cache_Read_Disable(0);
Cache_Read_Disable(1);
Cache_Flush(0);
Cache_Flush(1);
mmu_init(0);
DPORT_REG_SET_BIT(DPORT_APP_CACHE_CTRL1_REG, DPORT_APP_CACHE_MMU_IA_CLR);
mmu_init(1);
DPORT_REG_CLR_BIT(DPORT_APP_CACHE_CTRL1_REG, DPORT_APP_CACHE_MMU_IA_CLR);
/* (above steps probably unnecessary for most serial bootloader
usage, all that's absolutely needed is that we unmask DROM0
cache on the following two lines - normal ROM boot exits with
DROM0 cache unmasked, but serial bootloader exits with it
masked. However can't hurt to be thorough and reset
everything.)
The lines which manipulate DPORT_APP_CACHE_MMU_IA_CLR bit are
necessary to work around a hardware bug.
*/
DPORT_REG_CLR_BIT(DPORT_PRO_CACHE_CTRL1_REG, DPORT_PRO_CACHE_MASK_DROM0);
DPORT_REG_CLR_BIT(DPORT_APP_CACHE_CTRL1_REG, DPORT_APP_CACHE_MASK_DROM0);
bootloader_main();
}
/** @brief Load partition table
*
* Parse partition table, get useful data such as location of
* OTA data partition, factory app partition, and test app partition.
*
* @param bs bootloader state structure used to save read data
* @return return true if the partition table was succesfully loaded and MD5 checksum is valid.
*/
bool load_partition_table(bootloader_state_t* bs)
{
const esp_partition_info_t *partitions;
const int ESP_PARTITION_TABLE_DATA_LEN = 0xC00; /* length of actual data (signature is appended to this) */
char *partition_usage;
esp_err_t err;
int num_partitions;
#ifdef CONFIG_SECURE_BOOT_ENABLED
if(esp_secure_boot_enabled()) {
ESP_LOGI(TAG, "Verifying partition table signature...");
err = esp_secure_boot_verify_signature(ESP_PARTITION_TABLE_ADDR, ESP_PARTITION_TABLE_DATA_LEN);
if (err != ESP_OK) {
ESP_LOGE(TAG, "Failed to verify partition table signature.");
return false;
}
ESP_LOGD(TAG, "Partition table signature verified");
}
#endif
partitions = bootloader_mmap(ESP_PARTITION_TABLE_ADDR, ESP_PARTITION_TABLE_DATA_LEN);
if (!partitions) {
ESP_LOGE(TAG, "bootloader_mmap(0x%x, 0x%x) failed", ESP_PARTITION_TABLE_ADDR, ESP_PARTITION_TABLE_DATA_LEN);
return false;
}
ESP_LOGD(TAG, "mapped partition table 0x%x at 0x%x", ESP_PARTITION_TABLE_ADDR, (intptr_t)partitions);
err = esp_partition_table_basic_verify(partitions, true, &num_partitions);
if (err != ESP_OK) {
ESP_LOGE(TAG, "Failed to verify partition table");
return false;
}
ESP_LOGI(TAG, "Partition Table:");
ESP_LOGI(TAG, "## Label Usage Type ST Offset Length");
for(int i = 0; i < num_partitions; i++) {
const esp_partition_info_t *partition = &partitions[i];
ESP_LOGD(TAG, "load partition table entry 0x%x", (intptr_t)partition);
ESP_LOGD(TAG, "type=%x subtype=%x", partition->type, partition->subtype);
partition_usage = "unknown";
/* valid partition table */
switch(partition->type) {
case PART_TYPE_APP: /* app partition */
switch(partition->subtype) {
case PART_SUBTYPE_FACTORY: /* factory binary */
bs->factory = partition->pos;
partition_usage = "factory app";
break;
case PART_SUBTYPE_TEST: /* test binary */
bs->test = partition->pos;
partition_usage = "test app";
break;
default:
/* OTA binary */
if ((partition->subtype & ~PART_SUBTYPE_OTA_MASK) == PART_SUBTYPE_OTA_FLAG) {
bs->ota[partition->subtype & PART_SUBTYPE_OTA_MASK] = partition->pos;
++bs->app_count;
partition_usage = "OTA app";
}
else {
partition_usage = "Unknown app";
}
break;
}
break; /* PART_TYPE_APP */
case PART_TYPE_DATA: /* data partition */
switch(partition->subtype) {
case PART_SUBTYPE_DATA_OTA: /* ota data */
bs->ota_info = partition->pos;
partition_usage = "OTA data";
break;
case PART_SUBTYPE_DATA_RF:
partition_usage = "RF data";
break;
case PART_SUBTYPE_DATA_WIFI:
partition_usage = "WiFi data";
break;
default:
partition_usage = "Unknown data";
break;
}
break; /* PARTITION_USAGE_DATA */
default: /* other partition type */
break;
}
/* print partition type info */
ESP_LOGI(TAG, "%2d %-16s %-16s %02x %02x %08x %08x", i, partition->label, partition_usage,
partition->type, partition->subtype,
partition->pos.offset, partition->pos.size);
}
bootloader_munmap(partitions);
ESP_LOGI(TAG,"End of partition table");
return true;
}
static uint32_t ota_select_crc(const esp_ota_select_entry_t *s)
{
return crc32_le(UINT32_MAX, (uint8_t*)&s->ota_seq, 4);
}
static bool ota_select_valid(const esp_ota_select_entry_t *s)
{
return s->ota_seq != UINT32_MAX && s->crc == ota_select_crc(s);
}
/**
* @function : bootloader_main
* @description: entry function of 2nd bootloader
*
* @inputs: void
*/
void bootloader_main()
{
clock_configure();
uart_console_configure();
wdt_reset_check();
ESP_LOGI(TAG, "ESP-IDF %s 2nd stage bootloader", IDF_VER);
#if defined(CONFIG_SECURE_BOOT_ENABLED) || defined(CONFIG_FLASH_ENCRYPTION_ENABLED)
esp_err_t err;
#endif
esp_image_header_t fhdr;
bootloader_state_t bs;
esp_rom_spiflash_result_t spiRet1,spiRet2;
esp_ota_select_entry_t sa,sb;
const esp_ota_select_entry_t *ota_select_map;
memset(&bs, 0, sizeof(bs));
ESP_LOGI(TAG, "compile time " __TIME__ );
ets_set_appcpu_boot_addr(0);
/* disable watch dog here */
REG_CLR_BIT( RTC_CNTL_WDTCONFIG0_REG, RTC_CNTL_WDT_FLASHBOOT_MOD_EN );
REG_CLR_BIT( TIMG_WDTCONFIG0_REG(0), TIMG_WDT_FLASHBOOT_MOD_EN );
#ifndef CONFIG_SPI_FLASH_ROM_DRIVER_PATCH
const uint32_t spiconfig = ets_efuse_get_spiconfig();
if(spiconfig != EFUSE_SPICONFIG_SPI_DEFAULTS && spiconfig != EFUSE_SPICONFIG_HSPI_DEFAULTS) {
ESP_LOGE(TAG, "SPI flash pins are overridden. \"Enable SPI flash ROM driver patched functions\" must be enabled in menuconfig");
return;
}
#endif
esp_rom_spiflash_unlock();
ESP_LOGI(TAG, "Enabling RNG early entropy source...");
bootloader_random_enable();
#if CONFIG_FLASHMODE_QIO || CONFIG_FLASHMODE_QOUT
bootloader_enable_qio_mode();
#endif
if(esp_image_load_header(0x1000, true, &fhdr) != ESP_OK) {
ESP_LOGE(TAG, "failed to load bootloader header!");
return;
}
print_flash_info(&fhdr);
update_flash_config(&fhdr);
if (!load_partition_table(&bs)) {
ESP_LOGE(TAG, "load partition table error!");
return;
}
esp_partition_pos_t load_part_pos;
if (bs.ota_info.offset != 0) { // check if partition table has OTA info partition
//ESP_LOGE("OTA info sector handling is not implemented");
if (bs.ota_info.size < 2 * SPI_SEC_SIZE) {
ESP_LOGE(TAG, "ERROR: ota_info partition size %d is too small (minimum %d bytes)", bs.ota_info.size, sizeof(esp_ota_select_entry_t));
return;
}
ota_select_map = bootloader_mmap(bs.ota_info.offset, bs.ota_info.size);
if (!ota_select_map) {
ESP_LOGE(TAG, "bootloader_mmap(0x%x, 0x%x) failed", bs.ota_info.offset, bs.ota_info.size);
return;
}
memcpy(&sa, ota_select_map, sizeof(esp_ota_select_entry_t));
memcpy(&sb, (uint8_t *)ota_select_map + SPI_SEC_SIZE, sizeof(esp_ota_select_entry_t));
bootloader_munmap(ota_select_map);
ESP_LOGD(TAG, "OTA sequence values A 0x%08x B 0x%08x", sa.ota_seq, sb.ota_seq);
if(sa.ota_seq == 0xFFFFFFFF && sb.ota_seq == 0xFFFFFFFF) {
ESP_LOGD(TAG, "OTA sequence numbers both empty (all-0xFF");
// init status flash
if (bs.factory.offset != 0) { // if have factory bin,boot factory bin
ESP_LOGD(TAG, "Defaulting to factory image");
load_part_pos = bs.factory;
} else {
ESP_LOGD(TAG, "No factory image, defaulting to OTA 0");
load_part_pos = bs.ota[0];
sa.ota_seq = 0x01;
sa.crc = ota_select_crc(&sa);
sb.ota_seq = 0x00;
sb.crc = ota_select_crc(&sb);
Cache_Read_Disable(0);
spiRet1 = esp_rom_spiflash_erase_sector(bs.ota_info.offset/0x1000);
spiRet2 = esp_rom_spiflash_erase_sector(bs.ota_info.offset/0x1000+1);
if (spiRet1 != ESP_ROM_SPIFLASH_RESULT_OK || spiRet2 != ESP_ROM_SPIFLASH_RESULT_OK ) {
ESP_LOGE(TAG, SPI_ERROR_LOG);
return;
}
spiRet1 = esp_rom_spiflash_write(bs.ota_info.offset,(uint32_t *)&sa,sizeof(esp_ota_select_entry_t));
spiRet2 = esp_rom_spiflash_write(bs.ota_info.offset + 0x1000,(uint32_t *)&sb,sizeof(esp_ota_select_entry_t));
if (spiRet1 != ESP_ROM_SPIFLASH_RESULT_OK || spiRet2 != ESP_ROM_SPIFLASH_RESULT_OK ) {
ESP_LOGE(TAG, SPI_ERROR_LOG);
return;
}
Cache_Read_Enable(0);
}
//TODO:write data in ota info
} else {
if(ota_select_valid(&sa) && ota_select_valid(&sb)) {
ESP_LOGD(TAG, "Both OTA sequence valid, using OTA slot %d", MAX(sa.ota_seq, sb.ota_seq)-1);
load_part_pos = bs.ota[(MAX(sa.ota_seq, sb.ota_seq) - 1)%bs.app_count];
} else if(ota_select_valid(&sa)) {
ESP_LOGD(TAG, "Only OTA sequence A is valid, using OTA slot %d", sa.ota_seq - 1);
load_part_pos = bs.ota[(sa.ota_seq - 1) % bs.app_count];
} else if(ota_select_valid(&sb)) {
ESP_LOGD(TAG, "Only OTA sequence B is valid, using OTA slot %d", sa.ota_seq - 1);
load_part_pos = bs.ota[(sb.ota_seq - 1) % bs.app_count];
} else if (bs.factory.offset != 0) {
ESP_LOGE(TAG, "ota data partition invalid, falling back to factory");
load_part_pos = bs.factory;
} else {
ESP_LOGE(TAG, "ota data partition invalid and no factory, can't boot");
return;
}
}
} else if (bs.factory.offset != 0) { // otherwise, look for factory app partition
load_part_pos = bs.factory;
} else if (bs.test.offset != 0) { // otherwise, look for test app parition
load_part_pos = bs.test;
} else { // nothing to load, bail out
ESP_LOGE(TAG, "nothing to load");
return;
}
#ifdef CONFIG_SECURE_BOOT_ENABLED
/* Generate secure digest from this bootloader to protect future
modifications */
ESP_LOGI(TAG, "Checking secure boot...");
err = esp_secure_boot_permanently_enable();
if (err != ESP_OK) {
ESP_LOGE(TAG, "Bootloader digest generation failed (%d). SECURE BOOT IS NOT ENABLED.", err);
/* Allow booting to continue, as the failure is probably
due to user-configured EFUSEs for testing...
*/
}
#endif
#ifdef CONFIG_FLASH_ENCRYPTION_ENABLED
/* encrypt flash */
ESP_LOGI(TAG, "Checking flash encryption...");
bool flash_encryption_enabled = esp_flash_encryption_enabled();
err = esp_flash_encrypt_check_and_update();
if (err != ESP_OK) {
ESP_LOGE(TAG, "Flash encryption check failed (%d).", err);
return;
}
if (!flash_encryption_enabled && esp_flash_encryption_enabled()) {
/* Flash encryption was just enabled for the first time,
so issue a system reset to ensure flash encryption
cache resets properly */
ESP_LOGI(TAG, "Resetting with flash encryption enabled...");
REG_WRITE(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_SW_SYS_RST);
return;
}
#endif
ESP_LOGI(TAG, "Disabling RNG early entropy source...");
bootloader_random_disable();
// copy loaded segments to RAM, set up caches for mapped segments, and start application
ESP_LOGI(TAG, "Loading app partition at offset %08x", load_part_pos);
unpack_load_app(&load_part_pos);
}
static void unpack_load_app(const esp_partition_pos_t* partition)
{
esp_err_t err;
esp_image_header_t image_header;
uint32_t image_length;
/* TODO: verify the app image as part of OTA boot decision, so can have fallbacks */
err = esp_image_basic_verify(partition->offset, true, &image_length);
if (err != ESP_OK) {
ESP_LOGE(TAG, "Failed to verify app image @ 0x%x (%d)", partition->offset, err);
return;
}
#ifdef CONFIG_SECURE_BOOT_ENABLED
if (esp_secure_boot_enabled()) {
ESP_LOGI(TAG, "Verifying app signature @ 0x%x (length 0x%x)", partition->offset, image_length);
err = esp_secure_boot_verify_signature(partition->offset, image_length);
if (err != ESP_OK) {
ESP_LOGE(TAG, "App image @ 0x%x failed signature verification (%d)", partition->offset, err);
return;
}
ESP_LOGD(TAG, "App signature is valid");
}
#endif
if (esp_image_load_header(partition->offset, true, &image_header) != ESP_OK) {
ESP_LOGE(TAG, "Failed to load app image header @ 0x%x", partition->offset);
return;
}
uint32_t drom_addr = 0;
uint32_t drom_load_addr = 0;
uint32_t drom_size = 0;
uint32_t irom_addr = 0;
uint32_t irom_load_addr = 0;
uint32_t irom_size = 0;
/* Reload the RTC memory segments whenever a non-deepsleep reset
is occurring */
bool load_rtc_memory = rtc_get_reset_reason(0) != DEEPSLEEP_RESET;
ESP_LOGD(TAG, "bin_header: %u %u %u %u %08x", image_header.magic,
image_header.segment_count,
image_header.spi_mode,
image_header.spi_size,
(unsigned)image_header.entry_addr);
/* Important: From here on this function cannot access any global data (bss/data segments),
as loading the app image may overwrite these.
*/
for (int segment = 0; segment < image_header.segment_count; segment++) {
esp_image_segment_header_t segment_header;
uint32_t data_offs;
if(esp_image_load_segment_header(segment, partition->offset,
&image_header, true,
&segment_header, &data_offs) != ESP_OK) {
ESP_LOGE(TAG, "failed to load segment header #%d", segment);
return;
}
const uint32_t address = segment_header.load_addr;
bool load = true;
bool map = false;
if (address == 0x00000000) { // padding, ignore block
load = false;
}
if (address == 0x00000004) {
load = false; // md5 checksum block
// TODO: actually check md5
}
if (address >= SOC_DROM_LOW && address < SOC_DROM_HIGH) {
ESP_LOGD(TAG, "found drom segment, map from %08x to %08x", data_offs,
segment_header.load_addr);
drom_addr = data_offs;
drom_load_addr = segment_header.load_addr;
drom_size = segment_header.data_len + sizeof(segment_header);
load = false;
map = true;
}
if (address >= SOC_IROM_LOW && address < SOC_IROM_HIGH) {
ESP_LOGD(TAG, "found irom segment, map from %08x to %08x", data_offs,
segment_header.load_addr);
irom_addr = data_offs;
irom_load_addr = segment_header.load_addr;
irom_size = segment_header.data_len + sizeof(segment_header);
load = false;
map = true;
}
if (!load_rtc_memory && address >= SOC_RTC_IRAM_LOW && address < SOC_RTC_IRAM_HIGH) {
ESP_LOGD(TAG, "Skipping RTC code segment at %08x\n", data_offs);
load = false;
}
if (!load_rtc_memory && address >= SOC_RTC_DATA_LOW && address < SOC_RTC_DATA_HIGH) {
ESP_LOGD(TAG, "Skipping RTC data segment at %08x\n", data_offs);
load = false;
}
ESP_LOGI(TAG, "segment %d: paddr=0x%08x vaddr=0x%08x size=0x%05x (%6d) %s", segment, data_offs - sizeof(esp_image_segment_header_t),
segment_header.load_addr, segment_header.data_len, segment_header.data_len, (load)?"load":(map)?"map":"");
if (load) {
intptr_t sp, start_addr, end_addr;
ESP_LOGV(TAG, "bootloader_mmap data_offs=%08x data_len=%08x", data_offs, segment_header.data_len);
start_addr = segment_header.load_addr;
end_addr = start_addr + segment_header.data_len;
/* Before loading segment, check it doesn't clobber
bootloader RAM... */
if (end_addr < 0x40000000) {
sp = (intptr_t)get_sp();
if (end_addr > sp) {
ESP_LOGE(TAG, "Segment %d end address %08x overlaps bootloader stack %08x - can't load",
segment, end_addr, sp);
return;
}
if (end_addr > sp - 256) {
/* We don't know for sure this is the stack high water mark, so warn if
it seems like we may overflow.
*/
ESP_LOGW(TAG, "Segment %d end address %08x close to stack pointer %08x",
segment, end_addr, sp);
}
}
const void *data = bootloader_mmap(data_offs, segment_header.data_len);
if(!data) {
ESP_LOGE(TAG, "bootloader_mmap(0x%xc, 0x%x) failed",
data_offs, segment_header.data_len);
return;
}
memcpy((void *)segment_header.load_addr, data, segment_header.data_len);
bootloader_munmap(data);
}
}
set_cache_and_start_app(drom_addr,
drom_load_addr,
drom_size,
irom_addr,
irom_load_addr,
irom_size,
image_header.entry_addr);
}
static void set_cache_and_start_app(
uint32_t drom_addr,
uint32_t drom_load_addr,
uint32_t drom_size,
uint32_t irom_addr,
uint32_t irom_load_addr,
uint32_t irom_size,
uint32_t entry_addr)
{
ESP_LOGD(TAG, "configure drom and irom and start");
Cache_Read_Disable( 0 );
Cache_Flush( 0 );
uint32_t drom_page_count = (drom_size + 64*1024 - 1) / (64*1024); // round up to 64k
ESP_LOGV(TAG, "d mmu set paddr=%08x vaddr=%08x size=%d n=%d", drom_addr & 0xffff0000, drom_load_addr & 0xffff0000, drom_size, drom_page_count );
int rc = cache_flash_mmu_set( 0, 0, drom_load_addr & 0xffff0000, drom_addr & 0xffff0000, 64, drom_page_count );
ESP_LOGV(TAG, "rc=%d", rc );
rc = cache_flash_mmu_set( 1, 0, drom_load_addr & 0xffff0000, drom_addr & 0xffff0000, 64, drom_page_count );
ESP_LOGV(TAG, "rc=%d", rc );
uint32_t irom_page_count = (irom_size + 64*1024 - 1) / (64*1024); // round up to 64k
ESP_LOGV(TAG, "i mmu set paddr=%08x vaddr=%08x size=%d n=%d", irom_addr & 0xffff0000, irom_load_addr & 0xffff0000, irom_size, irom_page_count );
rc = cache_flash_mmu_set( 0, 0, irom_load_addr & 0xffff0000, irom_addr & 0xffff0000, 64, irom_page_count );
ESP_LOGV(TAG, "rc=%d", rc );
rc = cache_flash_mmu_set( 1, 0, irom_load_addr & 0xffff0000, irom_addr & 0xffff0000, 64, irom_page_count );
ESP_LOGV(TAG, "rc=%d", rc );
DPORT_REG_CLR_BIT( DPORT_PRO_CACHE_CTRL1_REG, (DPORT_PRO_CACHE_MASK_IRAM0) | (DPORT_PRO_CACHE_MASK_IRAM1 & 0) | (DPORT_PRO_CACHE_MASK_IROM0 & 0) | DPORT_PRO_CACHE_MASK_DROM0 | DPORT_PRO_CACHE_MASK_DRAM1 );
DPORT_REG_CLR_BIT( DPORT_APP_CACHE_CTRL1_REG, (DPORT_APP_CACHE_MASK_IRAM0) | (DPORT_APP_CACHE_MASK_IRAM1 & 0) | (DPORT_APP_CACHE_MASK_IROM0 & 0) | DPORT_APP_CACHE_MASK_DROM0 | DPORT_APP_CACHE_MASK_DRAM1 );
Cache_Read_Enable( 0 );
// Application will need to do Cache_Flush(1) and Cache_Read_Enable(1)
ESP_LOGD(TAG, "start: 0x%08x", entry_addr);
typedef void (*entry_t)(void);
entry_t entry = ((entry_t) entry_addr);
// TODO: we have used quite a bit of stack at this point.
// use "movsp" instruction to reset stack back to where ROM stack starts.
(*entry)();
}
static void update_flash_config(const esp_image_header_t* pfhdr)
{
uint32_t size;
switch(pfhdr->spi_size) {
case ESP_IMAGE_FLASH_SIZE_1MB:
size = 1;
break;
case ESP_IMAGE_FLASH_SIZE_2MB:
size = 2;
break;
case ESP_IMAGE_FLASH_SIZE_4MB:
size = 4;
break;
case ESP_IMAGE_FLASH_SIZE_8MB:
size = 8;
break;
case ESP_IMAGE_FLASH_SIZE_16MB:
size = 16;
break;
default:
size = 2;
}
Cache_Read_Disable( 0 );
// Set flash chip size
esp_rom_spiflash_config_param(g_rom_flashchip.device_id, size * 0x100000, 0x10000, 0x1000, 0x100, 0xffff);
// TODO: set mode
// TODO: set frequency
Cache_Flush(0);
Cache_Read_Enable( 0 );
}
void print_flash_info(const esp_image_header_t* phdr)
{
#if (BOOT_LOG_LEVEL >= BOOT_LOG_LEVEL_NOTICE)
ESP_LOGD(TAG, "magic %02x", phdr->magic );
ESP_LOGD(TAG, "segments %02x", phdr->segment_count );
ESP_LOGD(TAG, "spi_mode %02x", phdr->spi_mode );
ESP_LOGD(TAG, "spi_speed %02x", phdr->spi_speed );
ESP_LOGD(TAG, "spi_size %02x", phdr->spi_size );
const char* str;
switch ( phdr->spi_speed ) {
case ESP_IMAGE_SPI_SPEED_40M:
str = "40MHz";
break;
case ESP_IMAGE_SPI_SPEED_26M:
str = "26.7MHz";
break;
case ESP_IMAGE_SPI_SPEED_20M:
str = "20MHz";
break;
case ESP_IMAGE_SPI_SPEED_80M:
str = "80MHz";
break;
default:
str = "20MHz";
break;
}
ESP_LOGI(TAG, "SPI Speed : %s", str );
/* SPI mode could have been set to QIO during boot already,
so test the SPI registers not the flash header */
uint32_t spi_ctrl = REG_READ(SPI_CTRL_REG(0));
if (spi_ctrl & SPI_FREAD_QIO) {
str = "QIO";
} else if (spi_ctrl & SPI_FREAD_QUAD) {
str = "QOUT";
} else if (spi_ctrl & SPI_FREAD_DIO) {
str = "DIO";
} else if (spi_ctrl & SPI_FREAD_DUAL) {
str = "DOUT";
} else if (spi_ctrl & SPI_FASTRD_MODE) {
str = "FAST READ";
} else {
str = "SLOW READ";
}
ESP_LOGI(TAG, "SPI Mode : %s", str );
switch ( phdr->spi_size ) {
case ESP_IMAGE_FLASH_SIZE_1MB:
str = "1MB";
break;
case ESP_IMAGE_FLASH_SIZE_2MB:
str = "2MB";
break;
case ESP_IMAGE_FLASH_SIZE_4MB:
str = "4MB";
break;
case ESP_IMAGE_FLASH_SIZE_8MB:
str = "8MB";
break;
case ESP_IMAGE_FLASH_SIZE_16MB:
str = "16MB";
break;
default:
str = "2MB";
break;
}
ESP_LOGI(TAG, "SPI Flash Size : %s", str );
#endif
}
static void clock_configure(void)
{
/* Set CPU to 80MHz. Keep other clocks unmodified. */
rtc_cpu_freq_t cpu_freq = RTC_CPU_FREQ_80M;
/* On ESP32 rev 0, switching to 80MHz if clock was previously set to
* 240 MHz may cause the chip to lock up (see section 3.5 of the errata
* document). For rev. 0, switch to 240 instead if it was chosen in
* menuconfig.
*/
uint32_t chip_ver_reg = REG_READ(EFUSE_BLK0_RDATA3_REG);
if ((chip_ver_reg & EFUSE_RD_CHIP_VER_REV1_M) == 0 &&
CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ == 240) {
cpu_freq = RTC_CPU_FREQ_240M;
}
uart_tx_wait_idle(0);
rtc_clk_config_t clk_cfg = RTC_CLK_CONFIG_DEFAULT();
clk_cfg.xtal_freq = CONFIG_ESP32_XTAL_FREQ;
clk_cfg.cpu_freq = cpu_freq;
clk_cfg.slow_freq = rtc_clk_slow_freq_get();
clk_cfg.fast_freq = rtc_clk_fast_freq_get();
rtc_clk_init(clk_cfg);
/* As a slight optimization, if 32k XTAL was enabled in sdkconfig, we enable
* it here. Usually it needs some time to start up, so we amortize at least
* part of the start up time by enabling 32k XTAL early.
* App startup code will wait until the oscillator has started up.
*/
#ifdef CONFIG_ESP32_RTC_CLOCK_SOURCE_EXTERNAL_CRYSTAL
if (!rtc_clk_32k_enabled()) {
rtc_clk_32k_bootstrap();
}
#endif
}
static void uart_console_configure(void)
{
#if CONFIG_CONSOLE_UART_NONE
ets_install_putc1(NULL);
ets_install_putc2(NULL);
#else // CONFIG_CONSOLE_UART_NONE
const int uart_num = CONFIG_CONSOLE_UART_NUM;
uartAttach();
ets_install_uart_printf();
// ROM bootloader may have put a lot of text into UART0 FIFO.
// Wait for it to be printed.
uart_tx_wait_idle(0);
#if CONFIG_CONSOLE_UART_CUSTOM
// Some constants to make the following code less upper-case
const int uart_tx_gpio = CONFIG_CONSOLE_UART_TX_GPIO;
const int uart_rx_gpio = CONFIG_CONSOLE_UART_RX_GPIO;
// Switch to the new UART (this just changes UART number used for
// ets_printf in ROM code).
uart_tx_switch(uart_num);
// If console is attached to UART1 or if non-default pins are used,
// need to reconfigure pins using GPIO matrix
if (uart_num != 0 || uart_tx_gpio != 1 || uart_rx_gpio != 3) {
// Change pin mode for GPIO1/3 from UART to GPIO
PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0RXD_U, FUNC_U0RXD_GPIO3);
PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0TXD_U, FUNC_U0TXD_GPIO1);
// Route GPIO signals to/from pins
// (arrays should be optimized away by the compiler)
const uint32_t tx_idx_list[3] = { U0TXD_OUT_IDX, U1TXD_OUT_IDX, U2TXD_OUT_IDX };
const uint32_t rx_idx_list[3] = { U0RXD_IN_IDX, U1RXD_IN_IDX, U2RXD_IN_IDX };
const uint32_t tx_idx = tx_idx_list[uart_num];
const uint32_t rx_idx = rx_idx_list[uart_num];
gpio_matrix_out(uart_tx_gpio, tx_idx, 0, 0);
gpio_matrix_in(uart_rx_gpio, rx_idx, 0);
}
#endif // CONFIG_CONSOLE_UART_CUSTOM
// Set configured UART console baud rate
const int uart_baud = CONFIG_CONSOLE_UART_BAUDRATE;
uart_div_modify(uart_num, (rtc_clk_apb_freq_get() << 4) / uart_baud);
#endif // CONFIG_CONSOLE_UART_NONE
}
static void wdt_reset_cpu0_info_enable(void)
{
//We do not reset core1 info here because it didn't work before cpu1 was up. So we put it into call_start_cpu1.
DPORT_REG_SET_BIT(DPORT_PRO_CPU_RECORD_CTRL_REG, DPORT_PRO_CPU_PDEBUG_ENABLE | DPORT_PRO_CPU_RECORD_ENABLE);
DPORT_REG_CLR_BIT(DPORT_PRO_CPU_RECORD_CTRL_REG, DPORT_PRO_CPU_RECORD_ENABLE);
}
static void wdt_reset_info_dump(int cpu)
{
uint32_t inst = 0, pid = 0, stat = 0, data = 0, pc = 0,
lsstat = 0, lsaddr = 0, lsdata = 0, dstat = 0;
char *cpu_name = cpu ? "APP" : "PRO";
if (cpu == 0) {
stat = DPORT_REG_READ(DPORT_PRO_CPU_RECORD_STATUS_REG);
pid = DPORT_REG_READ(DPORT_PRO_CPU_RECORD_PID_REG);
inst = DPORT_REG_READ(DPORT_PRO_CPU_RECORD_PDEBUGINST_REG);
dstat = DPORT_REG_READ(DPORT_PRO_CPU_RECORD_PDEBUGSTATUS_REG);
data = DPORT_REG_READ(DPORT_PRO_CPU_RECORD_PDEBUGDATA_REG);
pc = DPORT_REG_READ(DPORT_PRO_CPU_RECORD_PDEBUGPC_REG);
lsstat = DPORT_REG_READ(DPORT_PRO_CPU_RECORD_PDEBUGLS0STAT_REG);
lsaddr = DPORT_REG_READ(DPORT_PRO_CPU_RECORD_PDEBUGLS0ADDR_REG);
lsdata = DPORT_REG_READ(DPORT_PRO_CPU_RECORD_PDEBUGLS0DATA_REG);
} else {
stat = DPORT_REG_READ(DPORT_APP_CPU_RECORD_STATUS_REG);
pid = DPORT_REG_READ(DPORT_APP_CPU_RECORD_PID_REG);
inst = DPORT_REG_READ(DPORT_APP_CPU_RECORD_PDEBUGINST_REG);
dstat = DPORT_REG_READ(DPORT_APP_CPU_RECORD_PDEBUGSTATUS_REG);
data = DPORT_REG_READ(DPORT_APP_CPU_RECORD_PDEBUGDATA_REG);
pc = DPORT_REG_READ(DPORT_APP_CPU_RECORD_PDEBUGPC_REG);
lsstat = DPORT_REG_READ(DPORT_APP_CPU_RECORD_PDEBUGLS0STAT_REG);
lsaddr = DPORT_REG_READ(DPORT_APP_CPU_RECORD_PDEBUGLS0ADDR_REG);
lsdata = DPORT_REG_READ(DPORT_APP_CPU_RECORD_PDEBUGLS0DATA_REG);
}
if (DPORT_RECORD_PDEBUGINST_SZ(inst) == 0 &&
DPORT_RECORD_PDEBUGSTATUS_BBCAUSE(dstat) == DPORT_RECORD_PDEBUGSTATUS_BBCAUSE_WAITI) {
ESP_LOGW(TAG, "WDT reset info: %s CPU PC=0x%x (waiti mode)", cpu_name, pc);
} else {
ESP_LOGW(TAG, "WDT reset info: %s CPU PC=0x%x", cpu_name, pc);
}
ESP_LOGD(TAG, "WDT reset info: %s CPU STATUS 0x%08x", cpu_name, stat);
ESP_LOGD(TAG, "WDT reset info: %s CPU PID 0x%08x", cpu_name, pid);
ESP_LOGD(TAG, "WDT reset info: %s CPU PDEBUGINST 0x%08x", cpu_name, inst);
ESP_LOGD(TAG, "WDT reset info: %s CPU PDEBUGSTATUS 0x%08x", cpu_name, dstat);
ESP_LOGD(TAG, "WDT reset info: %s CPU PDEBUGDATA 0x%08x", cpu_name, data);
ESP_LOGD(TAG, "WDT reset info: %s CPU PDEBUGPC 0x%08x", cpu_name, pc);
ESP_LOGD(TAG, "WDT reset info: %s CPU PDEBUGLS0STAT 0x%08x", cpu_name, lsstat);
ESP_LOGD(TAG, "WDT reset info: %s CPU PDEBUGLS0ADDR 0x%08x", cpu_name, lsaddr);
ESP_LOGD(TAG, "WDT reset info: %s CPU PDEBUGLS0DATA 0x%08x", cpu_name, lsdata);
}
static void wdt_reset_check(void)
{
int wdt_rst = 0;
RESET_REASON rst_reas[2];
rst_reas[0] = rtc_get_reset_reason(0);
rst_reas[1] = rtc_get_reset_reason(1);
if (rst_reas[0] == RTCWDT_SYS_RESET || rst_reas[0] == TG0WDT_SYS_RESET || rst_reas[0] == TG1WDT_SYS_RESET ||
rst_reas[0] == TGWDT_CPU_RESET || rst_reas[0] == RTCWDT_CPU_RESET) {
ESP_LOGW(TAG, "PRO CPU has been reset by WDT.");
wdt_rst = 1;
}
if (rst_reas[1] == RTCWDT_SYS_RESET || rst_reas[1] == TG0WDT_SYS_RESET || rst_reas[1] == TG1WDT_SYS_RESET ||
rst_reas[1] == TGWDT_CPU_RESET || rst_reas[1] == RTCWDT_CPU_RESET) {
ESP_LOGW(TAG, "APP CPU has been reset by WDT.");
wdt_rst = 1;
}
if (wdt_rst) {
// if reset by WDT dump info from trace port
wdt_reset_info_dump(0);
wdt_reset_info_dump(1);
}
wdt_reset_cpu0_info_enable();
}

View File

@@ -0,0 +1,20 @@
#
# Main bootloader Makefile.
#
# This is basically the same as a component makefile, but in the case of the bootloader
# we pull in bootloader-specific linker arguments.
#
LINKER_SCRIPTS := \
esp32.bootloader.ld \
$(IDF_PATH)/components/esp32/ld/esp32.rom.ld \
$(IDF_PATH)/components/esp32/ld/esp32.peripherals.ld \
esp32.bootloader.rom.ld
ifndef CONFIG_SPI_FLASH_ROM_DRIVER_PATCH
LINKER_SCRIPTS += $(IDF_PATH)/components/esp32/ld/esp32.rom.spiflash.ld
endif
COMPONENT_ADD_LDFLAGS := -L $(COMPONENT_PATH) -lmain $(addprefix -T ,$(LINKER_SCRIPTS))
COMPONENT_ADD_LINKER_DEPS := $(LINKER_SCRIPTS)

View File

@@ -0,0 +1,148 @@
/*
Linker file used to link the bootloader.
*WARNING* For now this linker dumps everything into IRAM/DRAM. ToDo: move
some/most stuff to DROM/IROM.
*/
/* THESE ARE THE VIRTUAL RUNTIME ADDRESSES */
/* The load addresses are defined later using the AT statements. */
MEMORY
{
/* All these values assume the flash cache is on, and have the blocks this uses subtracted from the length
of the various regions. The 'data access port' dram/drom regions map to the same iram/irom regions but
are connected to the data port of the CPU and eg allow bytewise access. */
dport0_seg (RW) : org = 0x3FF00000, len = 0x10 /* IO */
iram_seg (RWX) : org = 0x40080000, len = 0x400 /* 1k of IRAM used by bootloader functions which need to flush/enable APP CPU cache */
iram_pool_1_seg (RWX) : org = 0x40078000, len = 0x8000 /* IRAM POOL1, used for APP CPU cache. We can abuse it in bootloader because APP CPU is still held in reset, until we enable APP CPU cache */
dram_seg (RW) : org = 0x3FFF0000, len = 0x10000 /* 64k at the end of DRAM, after ROM bootloader stack */
}
/* Default entry point: */
ENTRY(call_start_cpu0);
SECTIONS
{
.iram1.text :
{
_init_start = ABSOLUTE(.);
*(.UserEnter.literal);
*(.UserEnter.text);
. = ALIGN (16);
*(.entry.text)
*(.init.literal)
*(.init)
_init_end = ABSOLUTE(.);
/* Code marked as runnning out of IRAM */
_iram_text_start = ABSOLUTE(.);
*(.iram1 .iram1.*)
_iram_text_end = ABSOLUTE(.);
} > iram_seg
/* Shared RAM */
.dram0.bss (NOLOAD) :
{
. = ALIGN (8);
_bss_start = ABSOLUTE(.);
*(.dynsbss)
*(.sbss)
*(.sbss.*)
*(.gnu.linkonce.sb.*)
*(.scommon)
*(.sbss2)
*(.sbss2.*)
*(.gnu.linkonce.sb2.*)
*(.dynbss)
KEEP(*(.bss))
*(.bss.*)
*(.gnu.linkonce.b.*)
*(COMMON)
. = ALIGN (8);
_bss_end = ABSOLUTE(.);
} >dram_seg
.dram0.data :
{
_data_start = ABSOLUTE(.);
KEEP(*(.data))
KEEP(*(.data.*))
KEEP(*(.gnu.linkonce.d.*))
KEEP(*(.data1))
KEEP(*(.sdata))
KEEP(*(.sdata.*))
KEEP(*(.gnu.linkonce.s.*))
KEEP(*(.sdata2))
KEEP(*(.sdata2.*))
KEEP(*(.gnu.linkonce.s2.*))
KEEP(*(.jcr))
_data_end = ABSOLUTE(.);
} >dram_seg
.dram0.rodata :
{
_rodata_start = ABSOLUTE(.);
*(.rodata)
*(.rodata.*)
*(.irom1.text) /* catch stray ICACHE_RODATA_ATTR */
*(.gnu.linkonce.r.*)
*(.rodata1)
__XT_EXCEPTION_TABLE_ = ABSOLUTE(.);
*(.xt_except_table)
*(.gcc_except_table)
*(.gnu.linkonce.e.*)
*(.gnu.version_r)
*(.eh_frame)
. = (. + 3) & ~ 3;
/* C++ constructor and destructor tables, properly ordered: */
__init_array_start = ABSOLUTE(.);
KEEP (*crtbegin.o(.ctors))
KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))
KEEP (*(SORT(.ctors.*)))
KEEP (*(.ctors))
__init_array_end = ABSOLUTE(.);
KEEP (*crtbegin.o(.dtors))
KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))
KEEP (*(SORT(.dtors.*)))
KEEP (*(.dtors))
/* C++ exception handlers table: */
__XT_EXCEPTION_DESCS_ = ABSOLUTE(.);
*(.xt_except_desc)
*(.gnu.linkonce.h.*)
__XT_EXCEPTION_DESCS_END__ = ABSOLUTE(.);
*(.xt_except_desc_end)
*(.dynamic)
*(.gnu.version_d)
_rodata_end = ABSOLUTE(.);
/* Literals are also RO data. */
_lit4_start = ABSOLUTE(.);
*(*.lit4)
*(.lit4.*)
*(.gnu.linkonce.lit4.*)
_lit4_end = ABSOLUTE(.);
. = ALIGN(4);
_heap_start = ABSOLUTE(.);
} >dram_seg
.iram_pool_1.text :
{
_stext = .;
_text_start = ABSOLUTE(.);
*(.literal .text .literal.* .text.* .stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*)
*(.irom0.text) /* catch stray ICACHE_RODATA_ATTR */
*(.fini.literal)
*(.fini)
*(.gnu.version)
_text_end = ABSOLUTE(.);
_etext = .;
} >iram_pool_1_seg
}

View File

@@ -0,0 +1 @@
PROVIDE ( ets_update_cpu_frequency = 0x40008550 ); /* Updates g_ticks_per_us on the current CPU only; not on the other core */

View File

@@ -0,0 +1,266 @@
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <stddef.h>
#include <stdint.h>
#include "flash_qio_mode.h"
#include "esp_log.h"
#include "rom/spi_flash.h"
#include "rom/efuse.h"
#include "soc/spi_struct.h"
#include "soc/efuse_reg.h"
#include "sdkconfig.h"
/* SPI flash controller */
#define SPIFLASH SPI1
/* SPI commands (actual on-wire commands not SPI controller bitmasks)
Suitable for use with the execute_flash_command static function.
*/
#define CMD_RDID 0x9F
#define CMD_WRSR 0x01
#define CMD_WRSR2 0x31 /* Not all SPI flash uses this command */
#define CMD_WREN 0x06
#define CMD_WRDI 0x04
#define CMD_RDSR 0x05
#define CMD_RDSR2 0x35 /* Not all SPI flash uses this command */
#define ESP32_D2WD_WP_GPIO 7 /* ESP32-D2WD has this GPIO wired to WP pin of flash */
static const char *TAG = "qio_mode";
typedef unsigned (*read_status_fn_t)();
typedef void (*write_status_fn_t)(unsigned);
typedef struct __attribute__((packed)) {
const char *manufacturer;
uint8_t mfg_id; /* 8-bit JEDEC manufacturer ID */
uint16_t flash_id; /* 16-bit JEDEC flash chip ID */
uint16_t id_mask; /* Bits to match on in flash chip ID */
read_status_fn_t read_status_fn;
write_status_fn_t write_status_fn;
uint8_t status_qio_bit;
} qio_info_t;
/* Read 8 bit status using RDSR command */
static unsigned read_status_8b_rdsr();
/* Read 8 bit status (second byte) using RDSR2 command */
static unsigned read_status_8b_rdsr2();
/* read 16 bit status using RDSR & RDSR2 (low and high bytes) */
static unsigned read_status_16b_rdsr_rdsr2();
/* Write 8 bit status using WRSR */
static void write_status_8b_wrsr(unsigned new_status);
/* Write 8 bit status (second byte) using WRSR2 */
static void write_status_8b_wrsr2(unsigned new_status);
/* Write 16 bit status using WRSR */
static void write_status_16b_wrsr(unsigned new_status);
/* Array of known flash chips and data to enable Quad I/O mode
Manufacturer & flash ID can be tested by running "esptool.py
flash_id"
If manufacturer ID matches, and flash ID ORed with flash ID mask
matches, enable_qio_mode() will execute "Read Cmd", test if bit
number "QIE Bit" is set, and if not set it will call "Write Cmd"
with this bit set.
Searching of this table stops when the first match is found.
*/
const static qio_info_t chip_data[] = {
/* Manufacturer, mfg_id, flash_id, id mask, Read Status, Write Status, QIE Bit */
{ "MXIC", 0xC2, 0x2000, 0xFF00, read_status_8b_rdsr, write_status_8b_wrsr, 6 },
{ "ISSI", 0x9D, 0x4000, 0xCF00, read_status_8b_rdsr, write_status_8b_wrsr, 6 }, /* IDs 0x40xx, 0x70xx */
{ "WinBond", 0xEF, 0x4000, 0xFF00, read_status_16b_rdsr_rdsr2, write_status_16b_wrsr, 9 },
/* Final entry is default entry, if no other IDs have matched.
This approach works for chips including:
GigaDevice (mfg ID 0xC8, flash IDs including 4016),
FM25Q32 (QOUT mode only, mfg ID 0xA1, flash IDs including 4016)
*/
{ NULL, 0xFF, 0xFFFF, 0xFFFF, read_status_8b_rdsr2, write_status_8b_wrsr2, 1 },
};
#define NUM_CHIPS (sizeof(chip_data) / sizeof(qio_info_t))
static void enable_qio_mode(read_status_fn_t read_status_fn,
write_status_fn_t write_status_fn,
uint8_t status_qio_bit);
/* Generic function to use the "user command" SPI controller functionality
to send commands to the SPI flash and read the respopnse.
The command passed here is always the on-the-wire command given to the SPI flash unit.
*/
static uint32_t execute_flash_command(uint8_t command, uint32_t mosi_data, uint8_t mosi_len, uint8_t miso_len);
/* dummy_len_plus values defined in ROM for SPI flash configuration */
extern uint8_t g_rom_spiflash_dummy_len_plus[];
void bootloader_enable_qio_mode(void)
{
uint32_t raw_flash_id;
uint8_t mfg_id;
uint16_t flash_id;
int i;
ESP_LOGD(TAG, "Probing for QIO mode enable...");
esp_rom_spiflash_wait_idle(&g_rom_flashchip);
/* Set up some of the SPIFLASH user/ctrl variables which don't change
while we're probing using execute_flash_command() */
SPIFLASH.ctrl.val = 0;
SPIFLASH.user.usr_dummy = 0;
SPIFLASH.user.usr_addr = 0;
SPIFLASH.user.usr_command = 1;
SPIFLASH.user2.usr_command_bitlen = 7;
raw_flash_id = execute_flash_command(CMD_RDID, 0, 0, 24);
ESP_LOGD(TAG, "Raw SPI flash chip id 0x%x", raw_flash_id);
mfg_id = raw_flash_id & 0xFF;
flash_id = (raw_flash_id >> 16) | (raw_flash_id & 0xFF00);
ESP_LOGD(TAG, "Manufacturer ID 0x%02x chip ID 0x%04x", mfg_id, flash_id);
for (i = 0; i < NUM_CHIPS-1; i++) {
const qio_info_t *chip = &chip_data[i];
if (mfg_id == chip->mfg_id && (flash_id & chip->id_mask) == (chip->flash_id & chip->id_mask)) {
ESP_LOGI(TAG, "Enabling QIO for flash chip %s", chip_data[i].manufacturer);
break;
}
}
if (i == NUM_CHIPS - 1) {
ESP_LOGI(TAG, "Enabling default flash chip QIO");
}
enable_qio_mode(chip_data[i].read_status_fn,
chip_data[i].write_status_fn,
chip_data[i].status_qio_bit);
}
static void enable_qio_mode(read_status_fn_t read_status_fn,
write_status_fn_t write_status_fn,
uint8_t status_qio_bit)
{
uint32_t status;
const uint32_t spiconfig = ets_efuse_get_spiconfig();
if (spiconfig != EFUSE_SPICONFIG_SPI_DEFAULTS && spiconfig != EFUSE_SPICONFIG_HSPI_DEFAULTS) {
// spiconfig specifies a custom efuse pin configuration. This config defines all pins -except- WP.
//
// For now, in this situation we only support Quad I/O mode for ESP32-D2WD where WP pin is known.
uint32_t chip_ver = REG_GET_FIELD(EFUSE_BLK0_RDATA3_REG, EFUSE_RD_CHIP_VER_RESERVE);
uint32_t pkg_ver = chip_ver & 0x7;
const uint32_t PKG_VER_ESP32_D2WD = 2; // TODO: use chip detection API once available
if (pkg_ver != PKG_VER_ESP32_D2WD) {
ESP_LOGE(TAG, "Quad I/O is only supported for standard pin numbers or ESP32-D2WD. Falling back to Dual I/O.");
return;
}
}
esp_rom_spiflash_wait_idle(&g_rom_flashchip);
status = read_status_fn();
ESP_LOGD(TAG, "Initial flash chip status 0x%x", status);
if ((status & (1<<status_qio_bit)) == 0) {
execute_flash_command(CMD_WREN, 0, 0, 0);
write_status_fn(status | (1<<status_qio_bit));
esp_rom_spiflash_wait_idle(&g_rom_flashchip);
status = read_status_fn();
ESP_LOGD(TAG, "Updated flash chip status 0x%x", status);
if ((status & (1<<status_qio_bit)) == 0) {
ESP_LOGE(TAG, "Failed to set QIE bit, not enabling QIO mode");
return;
}
} else {
ESP_LOGD(TAG, "QIO mode already enabled in flash");
}
ESP_LOGD(TAG, "Enabling QIO mode...");
esp_rom_spiflash_read_mode_t mode;
#if CONFIG_FLASHMODE_QOUT
mode = ESP_ROM_SPIFLASH_QOUT_MODE;
#else
mode = ESP_ROM_SPIFLASH_QIO_MODE;
#endif
esp_rom_spiflash_config_readmode(mode);
esp_rom_spiflash_select_qio_pins(ESP32_D2WD_WP_GPIO, spiconfig);
}
static unsigned read_status_8b_rdsr()
{
return execute_flash_command(CMD_RDSR, 0, 0, 8);
}
static unsigned read_status_8b_rdsr2()
{
return execute_flash_command(CMD_RDSR2, 0, 0, 8);
}
static unsigned read_status_16b_rdsr_rdsr2()
{
return execute_flash_command(CMD_RDSR, 0, 0, 8) | (execute_flash_command(CMD_RDSR2, 0, 0, 8) << 8);
}
static void write_status_8b_wrsr(unsigned new_status)
{
execute_flash_command(CMD_WRSR, new_status, 8, 0);
}
static void write_status_8b_wrsr2(unsigned new_status)
{
execute_flash_command(CMD_WRSR2, new_status, 8, 0);
}
static void write_status_16b_wrsr(unsigned new_status)
{
execute_flash_command(CMD_WRSR, new_status, 16, 0);
}
static uint32_t execute_flash_command(uint8_t command, uint32_t mosi_data, uint8_t mosi_len, uint8_t miso_len)
{
SPIFLASH.user2.usr_command_value = command;
SPIFLASH.user.usr_miso = miso_len > 0;
SPIFLASH.miso_dlen.usr_miso_dbitlen = miso_len ? (miso_len - 1) : 0;
SPIFLASH.user.usr_mosi = mosi_len > 0;
SPIFLASH.mosi_dlen.usr_mosi_dbitlen = mosi_len ? (mosi_len - 1) : 0;
SPIFLASH.data_buf[0] = mosi_data;
if (g_rom_spiflash_dummy_len_plus[1]) {
/* When flash pins are mapped via GPIO matrix, need a dummy cycle before reading via MISO */
if (miso_len > 0) {
SPIFLASH.user.usr_dummy = 1;
SPIFLASH.user1.usr_dummy_cyclelen = g_rom_spiflash_dummy_len_plus[1] - 1;
} else {
SPIFLASH.user.usr_dummy = 0;
SPIFLASH.user1.usr_dummy_cyclelen = 0;
}
}
SPIFLASH.cmd.usr = 1;
while(SPIFLASH.cmd.usr != 0)
{ }
return SPIFLASH.data_buf[0];
}

View File

@@ -0,0 +1,29 @@
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
/** @brief Enable Quad I/O mode in bootloader (if configured)
*
* Queries attached SPI flash ID and sends correct SPI flash
* commands to enable QIO or QOUT mode, then enables this mode.
*/
void bootloader_enable_qio_mode(void);
#ifdef __cplusplus
}
#endif

View File

@@ -1,129 +0,0 @@
cmake_minimum_required(VERSION 3.5)
if(NOT SDKCONFIG)
message(FATAL_ERROR "Bootloader subproject expects the SDKCONFIG variable to be passed "
"in by the parent build process.")
endif()
if(NOT IDF_PATH)
message(FATAL_ERROR "Bootloader subproject expects the IDF_PATH variable to be passed "
"in by the parent build process.")
endif()
if(NOT IDF_TARGET)
message(FATAL_ERROR "Bootloader subproject expects the IDF_TARGET variable to be passed "
"in by the parent build process.")
endif()
set(COMPONENTS bootloader esptool_py partition_table soc bootloader_support log spi_flash micro-ecc main efuse)
set(BOOTLOADER_BUILD 1)
include("${IDF_PATH}/tools/cmake/project.cmake")
set(common_req log esp_rom esp_common xtensa)
if(LEGACY_INCLUDE_COMMON_HEADERS)
list(APPEND common_req soc)
endif()
idf_build_set_property(__COMPONENT_REQUIRES_COMMON "${common_req}")
idf_build_set_property(__OUTPUT_SDKCONFIG 0)
project(bootloader)
idf_build_set_property(COMPILE_DEFINITIONS "-DBOOTLOADER_BUILD=1" APPEND)
idf_build_set_property(COMPILE_OPTIONS "-fno-stack-protector" APPEND)
string(REPLACE ";" " " espsecurepy "${ESPSECUREPY}")
string(REPLACE ";" " " espefusepy "${ESPEFUSEPY}")
set(esptoolpy_write_flash "${ESPTOOLPY_WRITE_FLASH_STR}")
if(CONFIG_SECURE_BOOTLOADER_REFLASHABLE)
if(CONFIG_SECURE_BOOTLOADER_KEY_ENCODING_192BIT)
set(key_digest_len 192)
else()
set(key_digest_len 256)
endif()
get_filename_component(bootloader_digest_bin
"bootloader-reflash-digest.bin"
ABSOLUTE BASE_DIR "${CMAKE_BINARY_DIR}")
get_filename_component(secure_bootloader_key
"secure-bootloader-key-${key_digest_len}.bin"
ABSOLUTE BASE_DIR "${CMAKE_BINARY_DIR}")
add_custom_command(OUTPUT "${secure_bootloader_key}"
COMMAND ${ESPSECUREPY} digest_private_key
--keylen "${key_digest_len}"
--keyfile "${SECURE_BOOT_SIGNING_KEY}"
"${secure_bootloader_key}"
VERBATIM)
if(CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES)
add_custom_target(gen_secure_bootloader_key ALL DEPENDS "${secure_bootloader_key}")
else()
if(NOT EXISTS "${secure_bootloader_key}")
message(FATAL_ERROR
"No pre-generated key for a reflashable secure bootloader is available, "
"due to signing configuration."
"\nTo generate one, you can use this command:"
"\n\t${espsecurepy} generate_flash_encryption_key ${secure_bootloader_key}"
"\nIf a signing key is present, then instead use:"
"\n\t${espsecurepy} digest_private_key "
"--keylen (192/256) --keyfile KEYFILE "
"${secure_bootloader_key}")
endif()
add_custom_target(gen_secure_bootloader_key)
endif()
add_custom_command(OUTPUT "${bootloader_digest_bin}"
COMMAND ${CMAKE_COMMAND} -E echo "DIGEST ${bootloader_digest_bin}"
COMMAND ${ESPSECUREPY} digest_secure_bootloader --keyfile "${secure_bootloader_key}"
-o "${bootloader_digest_bin}" "${CMAKE_BINARY_DIR}/bootloader.bin"
MAIN_DEPENDENCY "${CMAKE_BINARY_DIR}/.bin_timestamp"
DEPENDS gen_secure_bootloader_key gen_project_binary
VERBATIM)
add_custom_target (gen_bootloader_digest_bin ALL DEPENDS "${bootloader_digest_bin}")
endif()
if(CONFIG_SECURE_BOOTLOADER_ONE_TIME_FLASH)
add_custom_command(TARGET bootloader.elf POST_BUILD
COMMAND ${CMAKE_COMMAND} -E echo
"=============================================================================="
COMMAND ${CMAKE_COMMAND} -E echo
"Bootloader built. Secure boot enabled, so bootloader not flashed automatically."
COMMAND ${CMAKE_COMMAND} -E echo
"One-time flash command is:"
COMMAND ${CMAKE_COMMAND} -E echo
"\t${esptoolpy_write_flash} ${BOOTLOADER_OFFSET} ${CMAKE_BINARY_DIR}/bootloader.bin"
COMMAND ${CMAKE_COMMAND} -E echo
"* IMPORTANT: After first boot, BOOTLOADER CANNOT BE RE-FLASHED on same device"
VERBATIM)
elseif(CONFIG_SECURE_BOOTLOADER_REFLASHABLE)
add_custom_command(TARGET bootloader.elf POST_BUILD
COMMAND ${CMAKE_COMMAND} -E echo
"=============================================================================="
COMMAND ${CMAKE_COMMAND} -E echo
"Bootloader built and secure digest generated."
COMMAND ${CMAKE_COMMAND} -E echo
"Secure boot enabled, so bootloader not flashed automatically."
COMMAND ${CMAKE_COMMAND} -E echo
"Burn secure boot key to efuse using:"
COMMAND ${CMAKE_COMMAND} -E echo
"\t${espefusepy} burn_key secure_boot ${secure_bootloader_key}"
COMMAND ${CMAKE_COMMAND} -E echo
"First time flash command is:"
COMMAND ${CMAKE_COMMAND} -E echo
"\t${esptoolpy_write_flash} ${BOOTLOADER_OFFSET} ${CMAKE_BINARY_DIR}/bootloader.bin"
COMMAND ${CMAKE_COMMAND} -E echo
"=============================================================================="
COMMAND ${CMAKE_COMMAND} -E echo
"To reflash the bootloader after initial flash:"
COMMAND ${CMAKE_COMMAND} -E echo
"\t${esptoolpy_write_flash} 0x0 ${bootloader_digest_bin}"
COMMAND ${CMAKE_COMMAND} -E echo
"=============================================================================="
COMMAND ${CMAKE_COMMAND} -E echo
"* After first boot, only re-flashes of this kind (with same key) will be accepted."
COMMAND ${CMAKE_COMMAND} -E echo
"* Not recommended to re-use the same secure boot keyfile on multiple production devices."
DEPENDS gen_secure_bootloader_key gen_bootloader_digest_bin
VERBATIM)
endif()

View File

@@ -1,37 +0,0 @@
#
# This is a project Makefile. It is assumed the directory this Makefile resides in is a
# project subdirectory.
#
ifeq ("$(MAKELEVEL)","0")
$(error Bootloader makefile expects to be run as part of 'make bootloader' from a top-level project.)
endif
PROJECT_NAME := bootloader
COMPONENTS := esptool_py bootloader_support log spi_flash micro-ecc soc main efuse
# Clear C and CXX from top level project
CFLAGS =
CXXFLAGS =
#We cannot include the idf_target, esp_rom, esp_common component directly but we need their includes.
CFLAGS += -I $(IDF_PATH)/components/$(IDF_TARGET)/include
CFLAGS += -I $(IDF_PATH)/components/esp_rom/include
CFLAGS += -I $(IDF_PATH)/components/esp_common/include
CFLAGS += -I $(IDF_PATH)/components/xtensa/include -I $(IDF_PATH)/components/xtensa/$(IDF_TARGET)/include
# The bootloader pseudo-component is also included in this build, for its Kconfig.projbuild to be included.
#
# IS_BOOTLOADER_BUILD tells the component Makefile.projbuild to be a no-op
IS_BOOTLOADER_BUILD := 1
export IS_BOOTLOADER_BUILD
# BOOTLOADER_BUILD macro is the same, for source file changes
CFLAGS += -D BOOTLOADER_BUILD=1
# include the top-level "project" include directory, for sdkconfig.h
CFLAGS += -I$(BUILD_DIR_BASE)/../include
COMPONENT_ADD_LDFLAGS += -l$(COMPONENT_NAME) -Wl,--wrap=longjmp \
include $(IDF_PATH)/make/project.mk

View File

@@ -1,3 +0,0 @@
# only compile the "micro-ecc/uECC.c" source file
idf_component_register(SRCS "micro-ecc/uECC.c"
INCLUDE_DIRS micro-ecc)

View File

@@ -1,8 +0,0 @@
idf_component_register(SRCS "bootloader_start.c"
REQUIRES bootloader bootloader_support)
idf_build_get_property(target IDF_TARGET)
set(scripts "${target}.bootloader.ld"
"${target}.bootloader.rom.ld")
target_linker_script(${COMPONENT_LIB} INTERFACE "${scripts}")

View File

@@ -1,4 +0,0 @@
# Submodules normally added in component.mk, but fully qualified
# paths can be added at this level (we need binary librtc to be
# available to link bootloader).
COMPONENT_SUBMODULES += $(IDF_PATH)/components/esp_wifi/lib_esp32

View File

@@ -1,121 +0,0 @@
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <string.h>
#include <stdint.h>
#include <stdbool.h>
#include "esp_log.h"
#include "esp32/rom/gpio.h"
#include "esp32/rom/spi_flash.h"
#include "bootloader_config.h"
#include "bootloader_init.h"
#include "bootloader_utility.h"
#include "bootloader_common.h"
#include "sdkconfig.h"
#include "esp_image_format.h"
#include "esp32/rom/rtc.h"
static const char* TAG = "boot";
static int select_partition_number (bootloader_state_t *bs);
static int selected_boot_partition(const bootloader_state_t *bs);
/*
* We arrive here after the ROM bootloader finished loading this second stage bootloader from flash.
* The hardware is mostly uninitialized, flash cache is down and the app CPU is in reset.
* We do have a stack, so we can do the initialization in C.
*/
void __attribute__((noreturn)) call_start_cpu0()
{
// 1. Hardware initialization
if (bootloader_init() != ESP_OK) {
bootloader_reset();
}
// 2. Select the number of boot partition
bootloader_state_t bs = { 0 };
int boot_index = select_partition_number(&bs);
if (boot_index == INVALID_INDEX) {
bootloader_reset();
}
// 3. Load the app image for booting
bootloader_utility_load_boot_image(&bs, boot_index);
}
// Select the number of boot partition
static int select_partition_number (bootloader_state_t *bs)
{
// 1. Load partition table
if (!bootloader_utility_load_partition_table(bs)) {
ESP_LOGE(TAG, "load partition table error!");
return INVALID_INDEX;
}
// 2. Select the number of boot partition
return selected_boot_partition(bs);
}
/*
* Selects a boot partition.
* The conditions for switching to another firmware are checked.
*/
static int selected_boot_partition(const bootloader_state_t *bs)
{
int boot_index = bootloader_utility_get_selected_boot_partition(bs);
if (boot_index == INVALID_INDEX) {
return boot_index; // Unrecoverable failure (not due to corrupt ota data or bad partition contents)
}
if (rtc_get_reset_reason(0) != DEEPSLEEP_RESET) {
// Factory firmware.
#ifdef CONFIG_BOOTLOADER_FACTORY_RESET
if (bootloader_common_check_long_hold_gpio(CONFIG_BOOTLOADER_NUM_PIN_FACTORY_RESET, CONFIG_BOOTLOADER_HOLD_TIME_GPIO) == 1) {
ESP_LOGI(TAG, "Detect a condition of the factory reset");
bool ota_data_erase = false;
#ifdef CONFIG_BOOTLOADER_OTA_DATA_ERASE
ota_data_erase = true;
#endif
const char *list_erase = CONFIG_BOOTLOADER_DATA_FACTORY_RESET;
ESP_LOGI(TAG, "Data partitions to erase: %s", list_erase);
if (bootloader_common_erase_part_type_data(list_erase, ota_data_erase) == false) {
ESP_LOGE(TAG, "Not all partitions were erased");
}
return bootloader_utility_get_selected_boot_partition(bs);
}
#endif
// TEST firmware.
#ifdef CONFIG_BOOTLOADER_APP_TEST
if (bootloader_common_check_long_hold_gpio(CONFIG_BOOTLOADER_NUM_PIN_APP_TEST, CONFIG_BOOTLOADER_HOLD_TIME_GPIO) == 1) {
ESP_LOGI(TAG, "Detect a boot condition of the test firmware");
if (bs->test.offset != 0) {
boot_index = TEST_APP_INDEX;
return boot_index;
} else {
ESP_LOGE(TAG, "Test firmware is not found in partition table");
return INVALID_INDEX;
}
}
#endif
// Customer implementation.
// if (gpio_pin_1 == true && ...){
// boot_index = required_boot_partition;
// } ...
}
return boot_index;
}
// Return global reent struct if any newlib functions are linked to bootloader
struct _reent* __getreent() {
return _GLOBAL_REENT;
}

View File

@@ -1,21 +0,0 @@
#
# Main bootloader Makefile.
#
# This is basically the same as a component makefile, but in the case of the bootloader
# we pull in bootloader-specific linker arguments.
#
LINKER_SCRIPTS := \
$(IDF_TARGET).bootloader.ld \
$(IDF_TARGET).bootloader.rom.ld \
$(IDF_PATH)/components/esp_rom/$(IDF_TARGET)/ld/$(IDF_TARGET).rom.ld \
$(IDF_PATH)/components/esp_rom/$(IDF_TARGET)/ld/$(IDF_TARGET).rom.newlib-funcs.ld \
$(IDF_PATH)/components/$(IDF_TARGET)/ld/$(IDF_TARGET).peripherals.ld
ifndef CONFIG_SPI_FLASH_ROM_DRIVER_PATCH
LINKER_SCRIPTS += $(IDF_PATH)/components/esp_rom/$(IDF_TARGET)/ld/$(IDF_TARGET).rom.spiflash.ld
endif
COMPONENT_ADD_LDFLAGS += -L $(COMPONENT_PATH) $(addprefix -T ,$(LINKER_SCRIPTS))
COMPONENT_ADD_LINKER_DEPS := $(LINKER_SCRIPTS)

Some files were not shown because too many files have changed in this diff Show More