forked from espressif/esp-idf
Compare commits
203 Commits
v2.0-rc1
...
release/v2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bef9896305 | ||
|
|
18dbdd46f4 | ||
|
|
4184968469 | ||
|
|
024ef51d1a | ||
|
|
4d9778e208 | ||
|
|
6181af2a0b | ||
|
|
abf0cd8421 | ||
|
|
7a83c87c44 | ||
|
|
6ad86f0d67 | ||
|
|
fddebe4bcc | ||
|
|
2102acf266 | ||
|
|
a4ac9bf80b | ||
|
|
6e2601f389 | ||
|
|
ea48f43f87 | ||
|
|
1b0b34247a | ||
|
|
4aaa453b31 | ||
|
|
fe69377782 | ||
|
|
1c9d8744ab | ||
|
|
7db3370e20 | ||
|
|
eece22d075 | ||
|
|
2cc668bbb1 | ||
|
|
ad4a1b600a | ||
|
|
877b407c8c | ||
|
|
5850f423d5 | ||
|
|
ea74033d1e | ||
|
|
7cd1e0ef4b | ||
|
|
f72888544e | ||
|
|
a513ac4dec | ||
|
|
b337b20270 | ||
|
|
8ab96b13af | ||
|
|
50f414f54c | ||
|
|
0dfef8c16c | ||
|
|
6bb1367fe5 | ||
|
|
a286846095 | ||
|
|
2b2dd845ae | ||
|
|
b9f9e681ba | ||
|
|
3429241e1a | ||
|
|
455a7784a9 | ||
|
|
7d9a20e714 | ||
|
|
a6980fce4c | ||
|
|
4bd41d4082 | ||
|
|
3302a38432 | ||
|
|
82ef2b9485 | ||
|
|
de461671aa | ||
|
|
aa2f5e4ae5 | ||
|
|
c01dff8263 | ||
|
|
06274ff5a5 | ||
|
|
c62ae777c2 | ||
|
|
abdd8feebb | ||
|
|
3b8c9a407f | ||
|
|
6451c57e52 | ||
|
|
432b25f755 | ||
|
|
6739d5b99f | ||
|
|
d3eede2110 | ||
|
|
ecbe5a66f2 | ||
|
|
4e5e154603 | ||
|
|
6d061ec903 | ||
|
|
fabe0493c2 | ||
|
|
66199b1efe | ||
|
|
23f933a78d | ||
|
|
3b3c3210a6 | ||
|
|
ae09a46cb8 | ||
|
|
4d67a2ba8b | ||
|
|
98f8594151 | ||
|
|
c025dfbfa7 | ||
|
|
f3687f7177 | ||
|
|
8f43567a68 | ||
|
|
f36c909528 | ||
|
|
cd83bfb31c | ||
|
|
c6420792f2 | ||
|
|
290c40a4ab | ||
|
|
13dfb5568d | ||
|
|
d9c649d26e | ||
|
|
75115e1d83 | ||
|
|
c17e05040a | ||
|
|
63e0140ae6 | ||
|
|
1671879b7a | ||
|
|
ff81e17504 | ||
|
|
708539c559 | ||
|
|
36b3963efb | ||
|
|
b582697889 | ||
|
|
7dfb1c2e97 | ||
|
|
c057f067c7 | ||
|
|
ce7d0a7015 | ||
|
|
d772e1489b | ||
|
|
dca0377e19 | ||
|
|
cbb71baca9 | ||
|
|
045307ea0f | ||
|
|
f29768c404 | ||
|
|
c0f155f6ff | ||
|
|
8dede8f8a4 | ||
|
|
d28ee9a25e | ||
|
|
c3544dc090 | ||
|
|
3c90032369 | ||
|
|
e91d436e45 | ||
|
|
de28d3a655 | ||
|
|
e76c187efb | ||
|
|
e35ebbf813 | ||
|
|
04f7d96623 | ||
|
|
55693b1168 | ||
|
|
26dec992eb | ||
|
|
d3fde5188e | ||
|
|
3b583c150f | ||
|
|
1405fd1fef | ||
|
|
adfb289e81 | ||
|
|
a51f378ecc | ||
|
|
b5d1eb42b4 | ||
|
|
678ec0bd04 | ||
|
|
12a7293b31 | ||
|
|
bb0298bc71 | ||
|
|
abf87b000d | ||
|
|
7eaf1c76dc | ||
|
|
770c2ade05 | ||
|
|
95b62ef980 | ||
|
|
4db4e28b6e | ||
|
|
bfdfcbfaef | ||
|
|
21964a42fb | ||
|
|
4bd5b0c91a | ||
|
|
8f3d1d3184 | ||
|
|
4494e15ecf | ||
|
|
ad890aa5ea | ||
|
|
cd13c9e95d | ||
|
|
eb14284c92 | ||
|
|
61c7bd3c3a | ||
|
|
6c139c8ffb | ||
|
|
997fbf9e18 | ||
|
|
2fc4413dae | ||
|
|
6648ff427c | ||
|
|
5023e30a33 | ||
|
|
9cea5ea075 | ||
|
|
34d0b0086e | ||
|
|
39c546d63f | ||
|
|
413f05ce09 | ||
|
|
578e93803a | ||
|
|
fe44bc9e79 | ||
|
|
174c313d3d | ||
|
|
dd5401749d | ||
|
|
01c4a980ee | ||
|
|
25f05bef71 | ||
|
|
24cfe78962 | ||
|
|
4c9fdb7c52 | ||
|
|
0eb5c06ad4 | ||
|
|
7c7edab328 | ||
|
|
22c3877183 | ||
|
|
57af0d70d3 | ||
|
|
10c2e984dc | ||
|
|
dcd5c5bb73 | ||
|
|
473f2cff51 | ||
|
|
a65944a8cb | ||
|
|
97eef61184 | ||
|
|
2664291ba5 | ||
|
|
483411fd1a | ||
|
|
554237bf5e | ||
|
|
5fd7bd14db | ||
|
|
3aa2b571ae | ||
|
|
e8b7670db3 | ||
|
|
9893b71096 | ||
|
|
cf917567e9 | ||
|
|
2c334b46e0 | ||
|
|
0017e75bda | ||
|
|
7093c59a74 | ||
|
|
02460ff864 | ||
|
|
c61fdff729 | ||
|
|
777816cb99 | ||
|
|
89fea85a45 | ||
|
|
b748a63a43 | ||
|
|
d07a149e2c | ||
|
|
c78aa138b0 | ||
|
|
e8adb5ab57 | ||
|
|
627bc23b1c | ||
|
|
96e6839745 | ||
|
|
2d5162dc3c | ||
|
|
732a5fd0b2 | ||
|
|
04acc88023 | ||
|
|
b8e2edc99f | ||
|
|
f21275b910 | ||
|
|
0a678ebe8c | ||
|
|
21c7fc624a | ||
|
|
aaa891ada9 | ||
|
|
a4c76671c2 | ||
|
|
f512923791 | ||
|
|
e6f8837152 | ||
|
|
5e3b30da3a | ||
|
|
b6a2329f0f | ||
|
|
eea2788f5a | ||
|
|
385c61e183 | ||
|
|
39fe51924e | ||
|
|
d8aae55eeb | ||
|
|
67336672bd | ||
|
|
813395adcb | ||
|
|
2173ad3b45 | ||
|
|
4dd81fddd8 | ||
|
|
93395a3370 | ||
|
|
4f7e4dd0f5 | ||
|
|
33500f2561 | ||
|
|
32ad1e676d | ||
|
|
8e467801bc | ||
|
|
c6bb239f0c | ||
|
|
74f78540ae | ||
|
|
1d0c909daf | ||
|
|
d193424ae8 | ||
|
|
03e3b137bf | ||
|
|
905180667c |
@@ -14,10 +14,11 @@ before_script:
|
||||
- chmod 600 ~/.ssh/id_rsa
|
||||
- echo -e "Host gitlab.espressif.cn\n\tStrictHostKeyChecking no\n" >> ~/.ssh/config
|
||||
|
||||
# if testing master branch, use github wifi and bt libs.
|
||||
# if testing other branches, use gitlab wifi and bt libs (as maybe changes aren't merged to master yet)
|
||||
- test "${CI_BUILD_REF_NAME}" = "master" || sed -i "s%https://github.com/espressif/esp32-wifi-lib%${GITLAB_SSH_SERVER}/idf/esp32-wifi-lib%" .gitmodules
|
||||
- test "${CI_BUILD_REF_NAME}" = "master" || sed -i "s%https://github.com/espressif/esp32-bt-lib%${GITLAB_SSH_SERVER}/idf/esp32-bt-lib%" .gitmodules
|
||||
# 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
|
||||
|
||||
# fetch all submodules
|
||||
- git submodule update --init --recursive
|
||||
|
||||
@@ -31,6 +32,7 @@ build_template_app:
|
||||
SDK_PATH: "$CI_PROJECT_DIR"
|
||||
IDF_PATH: "$CI_PROJECT_DIR"
|
||||
GIT_STRATEGY: clone
|
||||
BATCH_BUILD: "1"
|
||||
|
||||
script:
|
||||
- git clone https://github.com/espressif/esp-idf-template.git
|
||||
@@ -39,13 +41,11 @@ build_template_app:
|
||||
# using on esp-idf. If it doesn't exist then just stick to the default
|
||||
# branch
|
||||
- git checkout ${CI_BUILD_REF_NAME} || echo "Using esp-idf-template default branch..."
|
||||
- make defconfig
|
||||
# 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 defconfig
|
||||
- make all V=1
|
||||
# Check if there are any stray printf/ets_printf references in WiFi libs
|
||||
- cd ../components/esp32/lib
|
||||
@@ -63,6 +63,8 @@ build_template_app:
|
||||
SDK_PATH: "$CI_PROJECT_DIR"
|
||||
IDF_PATH: "$CI_PROJECT_DIR"
|
||||
GIT_STRATEGY: clone
|
||||
BATCH_BUILD: "1"
|
||||
|
||||
|
||||
build_ssc:
|
||||
<<: *build_template
|
||||
@@ -79,6 +81,15 @@ build_ssc:
|
||||
- chmod +x gen_misc_ng.sh
|
||||
- ./gen_misc_ng.sh
|
||||
|
||||
build_at:
|
||||
<<: *build_template
|
||||
script:
|
||||
- git clone $GITLAB_SSH_SERVER/application/esp-at.git
|
||||
- cd esp-at
|
||||
- git checkout ${CI_BUILD_REF_NAME} || echo "Using esp-at default branch..."
|
||||
- make defconfig
|
||||
- make
|
||||
|
||||
build_esp_idf_tests:
|
||||
<<: *build_template
|
||||
artifacts:
|
||||
@@ -94,7 +105,6 @@ build_esp_idf_tests:
|
||||
script:
|
||||
- cd tools/unit-test-app
|
||||
- git checkout ${CI_BUILD_REF_NAME} || echo "Using default branch..."
|
||||
- make defconfig
|
||||
- make TESTS_ALL=1
|
||||
- python UnitTestParser.py
|
||||
|
||||
@@ -124,7 +134,7 @@ build_docs:
|
||||
- cd docs
|
||||
- doxygen
|
||||
# If not building master branch, and there are Doxygen warnings, print them and bail out
|
||||
- test "${CI_BUILD_REF_NAME}" = "master" || test $(cat doxygen-warning-log.txt | wc -l) -eq 0 || ( echo "Doxygen pass had some warnings:" && cat doxygen-warning-log.txt && false )
|
||||
- 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
|
||||
artifacts:
|
||||
@@ -150,6 +160,7 @@ test_build_system:
|
||||
variables:
|
||||
IDF_PATH: "$CI_PROJECT_DIR"
|
||||
script:
|
||||
- ./make/test_configure_ci_environment.sh
|
||||
- ./make/test_build_system.sh
|
||||
|
||||
test_report:
|
||||
@@ -158,6 +169,8 @@ test_report:
|
||||
only:
|
||||
- master
|
||||
- triggers
|
||||
- /^release\/v/
|
||||
- /^v\d+\.\d+(\.\d+)?($|-)/
|
||||
tags:
|
||||
- report
|
||||
variables:
|
||||
@@ -207,13 +220,15 @@ push_master_to_github:
|
||||
stage: deploy
|
||||
only:
|
||||
- master
|
||||
- /^release\/v.*$/
|
||||
- /^release\/v/
|
||||
- /^v\d+\.\d+(\.\d+)?($|-)/
|
||||
tags:
|
||||
- deploy
|
||||
when: on_success
|
||||
image: espressif/esp32-ci-env
|
||||
variables:
|
||||
GIT_STRATEGY: clone
|
||||
GITHUB_PUSH_REFS: refs/remotes/origin/release refs/remotes/origin/master
|
||||
script:
|
||||
- mkdir -p ~/.ssh
|
||||
- chmod 700 ~/.ssh
|
||||
@@ -222,7 +237,14 @@ push_master_to_github:
|
||||
- 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
|
||||
- git push --follow-tags github HEAD:master
|
||||
# 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_BUILD_REF 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
|
||||
#
|
||||
# NB: In gitlab 9.x, CI_BUILD_REF was deprecated. New name is CI_COMMIT_REF. If below command suddenly
|
||||
# generates bash syntax errors, this is probably why.
|
||||
- eval $(git for-each-ref --shell bash --format 'if [ $CI_BUILD_REF == %(objectname) ]; then git checkout -B %(refname:strip=3); git push --follow-tags github %(refname:strip=3); fi;' $GITHUB_PUSH_REFS)
|
||||
|
||||
|
||||
deploy_docs:
|
||||
@@ -231,7 +253,8 @@ deploy_docs:
|
||||
stage: deploy
|
||||
only:
|
||||
- master
|
||||
- /^release\/v.*$/
|
||||
- /^release\/v/
|
||||
- /^v\d+\.\d+(\.\d+)?($|-)/
|
||||
- triggers
|
||||
tags:
|
||||
- deploy
|
||||
@@ -278,12 +301,13 @@ check_doc_links:
|
||||
when: on_success
|
||||
only:
|
||||
- master
|
||||
- /^release\/v/
|
||||
- /^v\d+\.\d+(\.\d+)?($|-)/
|
||||
- triggers
|
||||
allow_failure: true
|
||||
|
||||
variables:
|
||||
# LOCAL_ENV_CONFIG_PATH: define in template and jobs can overwrite if required
|
||||
LOCAL_ENV_CONFIG_PATH: /home/gitlab-runner/LocalConfig/ESP32_IDF
|
||||
LOCAL_ENV_CONFIG_PATH: $CI_PROJECT_DIR/ci-test-runner-configs/$CI_RUNNER_DESCRIPTION/ESP32_IDF
|
||||
BIN_PATH: "$CI_PROJECT_DIR/SSC/ssc_bin/SSC"
|
||||
APP_NAME: "ssc"
|
||||
LOG_PATH: "$CI_PROJECT_DIR/$CI_BUILD_REF"
|
||||
@@ -308,9 +332,12 @@ check_doc_links:
|
||||
- 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 $GITLAB_SSH_SERVER/qa/ci-test-runner-configs.git
|
||||
# clone test bench
|
||||
- git clone $GITLAB_SSH_SERVER/yinling/auto_test_script.git
|
||||
- cd auto_test_script
|
||||
- git checkout ${CI_COMMIT_REF_NAME} || echo "Using default branch..."
|
||||
# run test
|
||||
- python CIRunner.py -l $LOG_PATH -c $CONFIG_FILE -e $LOCAL_ENV_CONFIG_PATH -t $TEST_CASE_FILE_PATH -m $MODULE_UPDATE_FILE bin_path $APP_NAME $BIN_PATH
|
||||
|
||||
@@ -333,9 +360,12 @@ check_doc_links:
|
||||
- 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 $GITLAB_SSH_SERVER/qa/ci-test-runner-configs.git
|
||||
# clone test bench
|
||||
- git clone $GITLAB_SSH_SERVER/yinling/auto_test_script.git
|
||||
- cd auto_test_script
|
||||
- git checkout ${CI_COMMIT_REF_NAME} || echo "Using default branch..."
|
||||
# run test
|
||||
- python CIRunner.py -l $LOG_PATH -c $CONFIG_FILE -e $LOCAL_ENV_CONFIG_PATH -t $TEST_CASE_FILE_PATH -m $MODULE_UPDATE_FILE bin_path $APP_NAME $BIN_PATH
|
||||
|
||||
@@ -346,14 +376,13 @@ check_doc_links:
|
||||
stage: unit_test
|
||||
|
||||
variables:
|
||||
# jobs MUST set CONFIG_FILE in before_script, and overwrite the variables above if necessary
|
||||
LOCAL_ENV_CONFIG_PATH: /home/gitlab-runner/LocalConfig/ESP32_IDF
|
||||
LOCAL_ENV_CONFIG_PATH: $CI_PROJECT_DIR/ci-test-runner-configs/$CI_RUNNER_DESCRIPTION/ESP32_IDF
|
||||
BIN_PATH: "$CI_PROJECT_DIR/tools/unit-test-app/build/"
|
||||
LOG_PATH: "$CI_PROJECT_DIR/$CI_BUILD_REF"
|
||||
APP_NAME: "ut"
|
||||
TEST_CASE_FILE_PATH: "$CI_PROJECT_DIR/components/idf_test/unit_test"
|
||||
MODULE_UPDATE_FILE: "$CI_PROJECT_DIR/tools/unit-test-app/ModuleDefinition.yml"
|
||||
|
||||
|
||||
dependencies:
|
||||
- build_esp_idf_tests
|
||||
|
||||
|
||||
12
README.md
12
README.md
@@ -24,6 +24,16 @@ Once you've found the project you want to work with, change to its directory and
|
||||
|
||||
`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
|
||||
|
||||
`make all`
|
||||
@@ -59,7 +69,7 @@ After the initial flash, you may just want to build and flash just your app, not
|
||||
|
||||
`make app-flash` will automatically rebuild the app if it needs it.
|
||||
|
||||
(There's no downside to reflashing the bootloader and partition table each time, if they haven't changed.)
|
||||
(In normal development there's no downside to reflashing the bootloader and partition table each time, if they haven't changed.)
|
||||
|
||||
## Parallel Builds
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
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_PATH}/components/partition_table/"
|
||||
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
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include "esp_spi_flash.h"
|
||||
#include "esp_image_format.h"
|
||||
#include "esp_secure_boot.h"
|
||||
#include "esp_flash_encrypt.h"
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#include "esp_ota_ops.h"
|
||||
@@ -44,6 +45,10 @@ typedef struct ota_ops_entry_ {
|
||||
esp_partition_t part;
|
||||
uint32_t erased_size;
|
||||
uint32_t wrote_size;
|
||||
#ifdef CONFIG_FLASH_ENCRYPTION_ENABLED
|
||||
uint8_t partial_bytes;
|
||||
uint8_t partial_data[16];
|
||||
#endif
|
||||
LIST_ENTRY(ota_ops_entry_) entries;
|
||||
} ota_ops_entry_t;
|
||||
|
||||
@@ -106,6 +111,7 @@ esp_err_t esp_ota_begin(const esp_partition_t *partition, size_t image_size, esp
|
||||
|
||||
esp_err_t esp_ota_write(esp_ota_handle_t handle, const void *data, size_t size)
|
||||
{
|
||||
const uint8_t *data_bytes = (const uint8_t *)data;
|
||||
esp_err_t ret;
|
||||
ota_ops_entry_t *it;
|
||||
|
||||
@@ -119,7 +125,47 @@ 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");
|
||||
ret = esp_partition_write(&it->part, it->wrote_size, data, size);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_FLASH_ENCRYPTION_ENABLED
|
||||
if (esp_flash_encryption_enabled()) {
|
||||
/* Can only write 16 byte blocks to flash, so need to cache anything else */
|
||||
size_t copy_len;
|
||||
|
||||
/* check if we have partially written data from earlier */
|
||||
if (it->partial_bytes != 0) {
|
||||
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) {
|
||||
return ESP_OK; /* nothing to write yet, just filling buffer */
|
||||
}
|
||||
/* write 16 byte to partition */
|
||||
ret = esp_partition_write(&it->part, it->wrote_size, it->partial_data, 16);
|
||||
if (ret != ESP_OK) {
|
||||
return ret;
|
||||
}
|
||||
it->partial_bytes = 0;
|
||||
memset(it->partial_data, 0xFF, 16);
|
||||
it->wrote_size += 16;
|
||||
data_bytes += copy_len;
|
||||
size -= copy_len;
|
||||
}
|
||||
|
||||
/* check if we need to save trailing data that we're about to write */
|
||||
it->partial_bytes = size % 16;
|
||||
if (it->partial_bytes != 0) {
|
||||
size -= it->partial_bytes;
|
||||
memcpy(it->partial_data, data_bytes + size, it->partial_bytes);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
ret = esp_partition_write(&it->part, it->wrote_size, data_bytes, size);
|
||||
if(ret == ESP_OK){
|
||||
it->wrote_size += size;
|
||||
}
|
||||
@@ -135,26 +181,11 @@ esp_err_t esp_ota_write(esp_ota_handle_t handle, const void *data, size_t size)
|
||||
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)) {
|
||||
if (it->handle == handle) {
|
||||
// an ota handle need to be ended after erased and wrote data in it
|
||||
if ((it->erased_size == 0) || (it->wrote_size == 0)) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SECUREBOOTLOADER
|
||||
esp_err_t ret;
|
||||
size_t image_size;
|
||||
if (esp_image_basic_verify(it->part.address, &image_size) != ESP_OK) {
|
||||
return ESP_ERR_OTA_VALIDATE_FAILED;
|
||||
}
|
||||
ret = esp_secure_boot_verify_signature(it->part.address, image_size);
|
||||
if (ret != ESP_OK) {
|
||||
return ESP_ERR_OTA_VALIDATE_FAILED;
|
||||
}
|
||||
#endif
|
||||
|
||||
LIST_REMOVE(it, entries);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -163,8 +194,44 @@ esp_err_t esp_ota_end(esp_ota_handle_t handle)
|
||||
return ESP_ERR_NOT_FOUND;
|
||||
}
|
||||
|
||||
/* 'it' holds the ota_ops_entry_t for 'handle' */
|
||||
|
||||
// esp_ota_end() is only valid if some data was written to this handle
|
||||
if ((it->erased_size == 0) || (it->wrote_size == 0)) {
|
||||
ret = ESP_ERR_INVALID_ARG;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_FLASH_ENCRYPTION_ENABLED
|
||||
if (it->partial_bytes > 0 && esp_flash_encryption_enabled()) {
|
||||
/* Write out last 16 bytes, if necessary */
|
||||
ret = esp_partition_write(&it->part, it->wrote_size, it->partial_data, 16);
|
||||
if (ret != ESP_OK) {
|
||||
ret = ESP_ERR_INVALID_STATE;
|
||||
goto cleanup;
|
||||
}
|
||||
it->wrote_size += 16;
|
||||
it->partial_bytes = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
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 ESP_OK;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static uint32_t ota_select_crc(const ota_select *s)
|
||||
@@ -271,11 +338,9 @@ static esp_err_t esp_rewrite_ota_data(esp_partition_subtype_t subtype)
|
||||
}
|
||||
return rewrite_ota_seq((SUB_TYPE_ID(subtype) + 1) % ota_app_count + i * ota_app_count, 0, find_partition);
|
||||
|
||||
} else if (s_ota_select[0].ota_seq == 0xFFFFFFFF && s_ota_select[1].ota_seq == 0xFFFFFFFF) {
|
||||
return rewrite_ota_seq(SUB_TYPE_ID(subtype) + 1, 0, find_partition);
|
||||
|
||||
} else {
|
||||
return ESP_ERR_OTA_SELECT_INFO_INVALID;
|
||||
/* Both OTA slots are invalid, probably because unformatted... */
|
||||
return rewrite_ota_seq(SUB_TYPE_ID(subtype) + 1, 0, find_partition);
|
||||
}
|
||||
|
||||
} else {
|
||||
@@ -285,17 +350,18 @@ static esp_err_t esp_rewrite_ota_data(esp_partition_subtype_t subtype)
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SECUREBOOTLOADER
|
||||
size_t image_size;
|
||||
if (esp_image_basic_verify(partition->address, &image_size) != ESP_OK) {
|
||||
if (esp_image_basic_verify(partition->address, true, &image_size) != ESP_OK) {
|
||||
return ESP_ERR_OTA_VALIDATE_FAILED;
|
||||
}
|
||||
ret = esp_secure_boot_verify_signature(partition->address, image_size);
|
||||
|
||||
#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;
|
||||
}
|
||||
@@ -349,33 +415,34 @@ const esp_partition_t *esp_ota_get_boot_partition(void)
|
||||
}
|
||||
ota_app_count = get_ota_partition_count();
|
||||
|
||||
ESP_LOGD(TAG, "found ota bin max = %d", ota_app_count);
|
||||
ESP_LOGD(TAG, "found ota app max = %d", ota_app_count);
|
||||
|
||||
if (s_ota_select[0].ota_seq == 0xFFFFFFFF && s_ota_select[1].ota_seq == 0xFFFFFFFF) {
|
||||
ESP_LOGD(TAG, "finding factory bin......");
|
||||
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 bin......", \
|
||||
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 bin......", \
|
||||
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 bin......", \
|
||||
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 {
|
||||
ESP_LOGE(TAG, "not found current bin");
|
||||
return NULL;
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,11 +73,16 @@ esp_err_t esp_ota_write(esp_ota_handle_t handle, const void* data, size_t size);
|
||||
/**
|
||||
* @brief Finish the update and validate written data
|
||||
*
|
||||
* @param handle Handle obtained from esp_ota_begin
|
||||
* @param handle Handle obtained from esp_ota_begin.
|
||||
*
|
||||
* @return:
|
||||
* - ESP_OK: if validate ota image pass
|
||||
* - ESP_ERR_OTA_VALIDATE_FAILED: validate the ota image is invalid
|
||||
* @note After calling esp_ota_end(), the handle is no longer valid and any memory associated with it is freed (regardless of result).
|
||||
*
|
||||
* @return:
|
||||
* - ESP_OK: Newly written OTA app image is valid.
|
||||
* - ESP_ERR_NOT_FOUND: OTA handle was not found.
|
||||
* - ESP_ERR_INVALID_ARG: Handle was never written to.
|
||||
* - ESP_ERR_OTA_VALIDATE_FAILED: OTA image is invalid (either not a valid app image, or - if secure boot is enabled - signature failed to verify.)
|
||||
* - ESP_ERR_INVALID_STATE: If flash encryption is enabled, this result indicates an internal error writing the final encrypted bytes to flash.
|
||||
*/
|
||||
esp_err_t esp_ota_end(esp_ota_handle_t handle);
|
||||
|
||||
|
||||
@@ -35,16 +35,16 @@ endmenu
|
||||
menu "Security features"
|
||||
|
||||
config SECURE_BOOT_ENABLED
|
||||
bool "Enable secure boot in bootloader"
|
||||
bool "Enable 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.
|
||||
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.
|
||||
|
||||
See docs/security/secure-boot.rst for details.
|
||||
Refer to http://esp-idf.readthedocs.io/en/latest/security/secure-boot.html before enabling.
|
||||
|
||||
choice SECURE_BOOTLOADER_MODE
|
||||
bool "Secure bootloader mode"
|
||||
@@ -108,7 +108,7 @@ config SECURE_BOOT_VERIFICATION_KEY
|
||||
PEM formatted private key using the espsecure.py
|
||||
extract_public_key command.
|
||||
|
||||
See docs/security/secure-boot.rst for details.
|
||||
Refer to http://esp-idf.readthedocs.io/en/latest/security/secure-boot.html before enabling.
|
||||
|
||||
config SECURE_BOOT_INSECURE
|
||||
bool "Allow potentially insecure options"
|
||||
@@ -119,16 +119,18 @@ config SECURE_BOOT_INSECURE
|
||||
|
||||
Only enable these options if you are very sure.
|
||||
|
||||
Refer to docs/security/secure-boot.rst and docs/security/flash-encryption.rst for details.
|
||||
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"
|
||||
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.
|
||||
See docs/securityflash-encryption.rst for details.
|
||||
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"
|
||||
|
||||
4
components/bootloader/src/main/Makefile.projbuild
Normal file
4
components/bootloader/src/main/Makefile.projbuild
Normal 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
|
||||
@@ -323,12 +323,15 @@ void bootloader_main()
|
||||
} else {
|
||||
if(ota_select_valid(&sa) && ota_select_valid(&sb)) {
|
||||
load_part_pos = bs.ota[(((sa.ota_seq > sb.ota_seq)?sa.ota_seq:sb.ota_seq) - 1)%bs.app_count];
|
||||
}else if(ota_select_valid(&sa)) {
|
||||
} else if(ota_select_valid(&sa)) {
|
||||
load_part_pos = bs.ota[(sa.ota_seq - 1) % bs.app_count];
|
||||
}else if(ota_select_valid(&sb)) {
|
||||
} else if(ota_select_valid(&sb)) {
|
||||
load_part_pos = bs.ota[(sb.ota_seq - 1) % bs.app_count];
|
||||
}else {
|
||||
ESP_LOGE(TAG, "ota data partition info error");
|
||||
} 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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,10 +14,10 @@ COMPONENT_ADD_LDFLAGS := -L $(COMPONENT_PATH) -lmain $(addprefix -T ,$(LINKER_SC
|
||||
|
||||
COMPONENT_ADD_LINKER_DEPS := $(LINKER_SCRIPTS)
|
||||
|
||||
ifdef IS_BOOTLOADER_BUILD
|
||||
# following lines are a workaround to link librtc into the
|
||||
# bootloader, until clock setting code is in a source-based esp-idf
|
||||
# component. See also rtc_printf() in bootloader_start.c
|
||||
COMPONENT_ADD_LDFLAGS += -L $(IDF_PATH)/components/esp32/lib/ -lrtc
|
||||
#
|
||||
# See also matching COMPONENT_SUBMODULES line in Makefile.projbuild
|
||||
COMPONENT_ADD_LDFLAGS += -L $(IDF_PATH)/components/esp32/lib/ -lrtc_clk -lrtc
|
||||
COMPONENT_EXTRA_INCLUDES += $(IDF_PATH)/components/esp32/
|
||||
endif
|
||||
|
||||
@@ -15,14 +15,17 @@
|
||||
#define __ESP32_FLASH_ENCRYPT_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <esp_err.h>
|
||||
#include "esp_attr.h"
|
||||
#include "esp_err.h"
|
||||
#include "esp_spi_flash.h"
|
||||
#include "soc/efuse_reg.h"
|
||||
|
||||
/* Support functions for flash encryption features.
|
||||
|
||||
Can be compiled as part of app or bootloader code.
|
||||
*/
|
||||
/**
|
||||
* @file esp_partition.h
|
||||
* @brief Support functions for flash encryption features
|
||||
*
|
||||
* Can be compiled as part of app or bootloader code.
|
||||
*/
|
||||
|
||||
/** @brief Is flash encryption currently enabled in hardware?
|
||||
*
|
||||
@@ -30,9 +33,17 @@
|
||||
*
|
||||
* @return true if flash encryption is enabled.
|
||||
*/
|
||||
static inline bool esp_flash_encryption_enabled(void) {
|
||||
static inline IRAM_ATTR bool esp_flash_encryption_enabled(void) {
|
||||
uint32_t flash_crypt_cnt = REG_GET_FIELD(EFUSE_BLK0_RDATA0_REG, EFUSE_RD_FLASH_CRYPT_CNT);
|
||||
return __builtin_parity(flash_crypt_cnt) == 1;
|
||||
/* __builtin_parity is in flash, so we calculate parity inline */
|
||||
bool enabled = false;
|
||||
while(flash_crypt_cnt) {
|
||||
if (flash_crypt_cnt & 1) {
|
||||
enabled = !enabled;
|
||||
}
|
||||
flash_crypt_cnt >>= 1;
|
||||
}
|
||||
return enabled;
|
||||
}
|
||||
|
||||
/* @brief Update on-device flash encryption
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include <bootloader_flash.h>
|
||||
#include <esp_log.h>
|
||||
#include <esp_spi_flash.h> /* including in bootloader for error values */
|
||||
#include <esp_flash_encrypt.h>
|
||||
|
||||
#ifndef BOOTLOADER_BUILD
|
||||
/* Normal app version maps to esp_spi_flash.h operations...
|
||||
@@ -48,7 +49,11 @@ void bootloader_munmap(const void *mapping)
|
||||
|
||||
esp_err_t bootloader_flash_read(size_t src, void *dest, size_t size, bool allow_decrypt)
|
||||
{
|
||||
return spi_flash_read(src, dest, size);
|
||||
if (allow_decrypt && esp_flash_encryption_enabled()) {
|
||||
return spi_flash_read_encrypted(src, dest, size);
|
||||
} else {
|
||||
return spi_flash_read(src, dest, size);
|
||||
}
|
||||
}
|
||||
|
||||
esp_err_t bootloader_flash_write(size_t dest_addr, void *src, size_t size, bool write_encrypted)
|
||||
|
||||
@@ -62,6 +62,11 @@ void bootloader_fill_random(void *buffer, size_t length)
|
||||
|
||||
void bootloader_random_enable(void)
|
||||
{
|
||||
/* Ensure the hardware RNG is enabled following a soft reset. This should always be the case already (this clock is
|
||||
never disabled while the CPU is running), this is a "belts and braces" type check.
|
||||
*/
|
||||
SET_PERI_REG_MASK(DPORT_WIFI_CLK_EN_REG, DPORT_WIFI_CLK_RNG_EN);
|
||||
|
||||
/* Enable SAR ADC in test mode to feed ADC readings of the 1.1V
|
||||
reference via I2S into the RNG entropy input.
|
||||
|
||||
@@ -135,4 +140,8 @@ void bootloader_random_disable(void)
|
||||
/* Reset i2s peripheral */
|
||||
SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_I2S0_RST);
|
||||
CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_I2S0_RST);
|
||||
|
||||
/* Disable pull supply voltage to SAR ADC */
|
||||
CLEAR_PERI_REG_MASK(RTC_CNTL_TEST_MUX_REG, RTC_CNTL_ENT_RTC);
|
||||
SET_PERI_REG_BITS(RTC_CNTL_TEST_MUX_REG, RTC_CNTL_DTEST_RTC, 0, RTC_CNTL_DTEST_RTC_S);
|
||||
}
|
||||
|
||||
@@ -285,6 +285,9 @@ static esp_err_t encrypt_partition(int index, const esp_partition_info_t *partit
|
||||
} else {
|
||||
should_encrypt = false;
|
||||
}
|
||||
} else if (partition->type == PART_TYPE_DATA && partition->subtype == PART_SUBTYPE_DATA_OTA) {
|
||||
/* check if we have ota data partition and the partition should be encrypted unconditionally */
|
||||
should_encrypt = true;
|
||||
}
|
||||
|
||||
if (!should_encrypt) {
|
||||
|
||||
@@ -17,6 +17,15 @@ config BLUEDROID_MEM_DEBUG
|
||||
help
|
||||
Bluedroid memory debug
|
||||
|
||||
config BT_DRAM_RELEASE
|
||||
bool "Release DRAM from Classic BT controller"
|
||||
depends on BT_ENABLED
|
||||
default n
|
||||
help
|
||||
This option should only be used when BLE only.
|
||||
Open this option will release about 30K DRAM from Classic BT.
|
||||
The released DRAM will be used as system heap memory.
|
||||
|
||||
# Memory reserved at start of DRAM for Bluetooth stack
|
||||
config BT_RESERVE_DRAM
|
||||
hex
|
||||
|
||||
@@ -16,15 +16,16 @@
|
||||
#include "esp_bt_main.h"
|
||||
#include "btc_task.h"
|
||||
#include "btc_main.h"
|
||||
#include "bt.h"
|
||||
#include "future.h"
|
||||
|
||||
static bool esp_already_enable = false;
|
||||
static bool esp_already_init = false;
|
||||
static bool bd_already_enable = false;
|
||||
static bool bd_already_init = false;
|
||||
|
||||
esp_bluedroid_status_t esp_bluedroid_get_status(void)
|
||||
{
|
||||
if (esp_already_init) {
|
||||
if (esp_already_enable) {
|
||||
if (bd_already_init) {
|
||||
if (bd_already_enable) {
|
||||
return ESP_BLUEDROID_STATUS_ENABLED;
|
||||
} else {
|
||||
return ESP_BLUEDROID_STATUS_INITIALIZED;
|
||||
@@ -39,15 +40,20 @@ esp_err_t esp_bluedroid_enable(void)
|
||||
btc_msg_t msg;
|
||||
future_t **future_p;
|
||||
|
||||
if (esp_already_enable) {
|
||||
LOG_ERROR("%s already enable\n", __func__);
|
||||
if (!bd_already_init) {
|
||||
LOG_ERROR("Bludroid not initialised\n");
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
if (bd_already_enable) {
|
||||
LOG_ERROR("Bluedroid already enabled\n");
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
future_p = btc_main_get_future_p(BTC_MAIN_ENABLE_FUTURE);
|
||||
*future_p = future_new();
|
||||
if (*future_p == NULL) {
|
||||
LOG_ERROR("%s failed\n", __func__);
|
||||
LOG_ERROR("Bluedroid enable failed\n");
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
|
||||
@@ -57,11 +63,11 @@ esp_err_t esp_bluedroid_enable(void)
|
||||
btc_transfer_context(&msg, NULL, 0, NULL);
|
||||
|
||||
if (future_await(*future_p) == FUTURE_FAIL) {
|
||||
LOG_ERROR("%s failed\n", __func__);
|
||||
LOG_ERROR("Bluedroid enable failed\n");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
esp_already_enable = true;
|
||||
bd_already_enable = true;
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
@@ -71,15 +77,15 @@ esp_err_t esp_bluedroid_disable(void)
|
||||
btc_msg_t msg;
|
||||
future_t **future_p;
|
||||
|
||||
if (!esp_already_enable) {
|
||||
LOG_ERROR("%s already disable\n", __func__);
|
||||
if (!bd_already_enable) {
|
||||
LOG_ERROR("Bluedroid already disabled\n");
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
future_p = btc_main_get_future_p(BTC_MAIN_DISABLE_FUTURE);
|
||||
*future_p = future_new();
|
||||
if (*future_p == NULL) {
|
||||
LOG_ERROR("%s failed\n", __func__);
|
||||
LOG_ERROR("Bluedroid disable failed\n");
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
|
||||
@@ -89,11 +95,11 @@ esp_err_t esp_bluedroid_disable(void)
|
||||
btc_transfer_context(&msg, NULL, 0, NULL);
|
||||
|
||||
if (future_await(*future_p) == FUTURE_FAIL) {
|
||||
LOG_ERROR("%s failed\n", __func__);
|
||||
LOG_ERROR("Bluedroid disable failed\n");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
esp_already_enable = false;
|
||||
bd_already_enable = false;
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
@@ -103,15 +109,20 @@ esp_err_t esp_bluedroid_init(void)
|
||||
btc_msg_t msg;
|
||||
future_t **future_p;
|
||||
|
||||
if (esp_already_init) {
|
||||
LOG_ERROR("%s already init\n", __func__);
|
||||
if (esp_bt_controller_get_status() != ESP_BT_CONTROLLER_STATUS_ENABLED) {
|
||||
LOG_ERROR("Conroller not initialised\n");
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
if (bd_already_init) {
|
||||
LOG_ERROR("Bluedroid already initialised\n");
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
future_p = btc_main_get_future_p(BTC_MAIN_INIT_FUTURE);
|
||||
*future_p = future_new();
|
||||
if (*future_p == NULL) {
|
||||
LOG_ERROR("%s failed\n", __func__);
|
||||
LOG_ERROR("Bluedroid initialise failed\n");
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
|
||||
@@ -123,11 +134,11 @@ esp_err_t esp_bluedroid_init(void)
|
||||
btc_transfer_context(&msg, NULL, 0, NULL);
|
||||
|
||||
if (future_await(*future_p) == FUTURE_FAIL) {
|
||||
LOG_ERROR("%s failed\n", __func__);
|
||||
LOG_ERROR("Bluedroid initialise failed\n");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
esp_already_init = true;
|
||||
bd_already_init = true;
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
@@ -138,15 +149,20 @@ esp_err_t esp_bluedroid_deinit(void)
|
||||
btc_msg_t msg;
|
||||
future_t **future_p;
|
||||
|
||||
if (!esp_already_init) {
|
||||
LOG_ERROR("%s already deinit\n", __func__);
|
||||
if (!bd_already_init) {
|
||||
LOG_ERROR("Bluedroid already de-initialised\n");
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
if (bd_already_enable) {
|
||||
LOG_ERROR("Bludroid already enabled, do disable first\n");
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
future_p = btc_main_get_future_p(BTC_MAIN_DEINIT_FUTURE);
|
||||
*future_p = future_new();
|
||||
if (*future_p == NULL) {
|
||||
LOG_ERROR("%s failed\n", __func__);
|
||||
LOG_ERROR("Bluedroid de-initialise failed\n");
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
|
||||
@@ -156,15 +172,14 @@ esp_err_t esp_bluedroid_deinit(void)
|
||||
btc_transfer_context(&msg, NULL, 0, NULL);
|
||||
|
||||
if (future_await(*future_p) == FUTURE_FAIL) {
|
||||
LOG_ERROR("%s failed\n", __func__);
|
||||
LOG_ERROR("Bluedroid de-initialise failed\n");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
btc_deinit();
|
||||
|
||||
esp_already_init = false;
|
||||
bd_already_init = false;
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -142,6 +142,27 @@ esp_err_t esp_ble_gatts_add_char(uint16_t service_handle, esp_bt_uuid_t *char_
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
/* parameter validation check */
|
||||
if ((control != NULL) && (control->auto_rsp == GATT_STACK_RSP)){
|
||||
if (char_val == NULL){
|
||||
LOG_ERROR("Error in %s, line=%d, for stack respond attribute, char_val should not be NULL here\n",\
|
||||
__func__, __LINE__);
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
} else if (char_val->attr_max_len == 0){
|
||||
LOG_ERROR("Error in %s, line=%d, for stack respond attribute, attribute max length should not be 0\n",\
|
||||
__func__, __LINE__);
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
}
|
||||
|
||||
if (char_val != NULL){
|
||||
if (char_val->attr_len > char_val->attr_max_len){
|
||||
LOG_ERROR("Error in %s, line=%d,attribute actual length (%d) should not be larger than max length (%d)\n",\
|
||||
__func__, __LINE__, char_val->attr_len, char_val->attr_max_len);
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
}
|
||||
|
||||
memset(&arg, 0, sizeof(btc_ble_gatts_args_t));
|
||||
msg.sig = BTC_SIG_API_CALL;
|
||||
msg.pid = BTC_PID_GATTS;
|
||||
@@ -175,6 +196,29 @@ esp_err_t esp_ble_gatts_add_char_descr (uint16_t service_handle,
|
||||
if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
/* parameter validation check */
|
||||
if ((control != NULL) && (control->auto_rsp == GATT_STACK_RSP)){
|
||||
if (char_descr_val == NULL){
|
||||
LOG_ERROR("Error in %s, line=%d, for stack respond attribute, char_descr_val should not be NULL here\n",\
|
||||
__func__, __LINE__);
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
else if (char_descr_val->attr_max_len == 0){
|
||||
LOG_ERROR("Error in %s, line=%d, for stack respond attribute, attribute max length should not be 0\n",\
|
||||
__func__, __LINE__);
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
}
|
||||
|
||||
if (char_descr_val != NULL){
|
||||
if (char_descr_val->attr_len > char_descr_val->attr_max_len){
|
||||
LOG_ERROR("Error in %s, line=%d,attribute actual length (%d) should not be larger than max length (%d)\n",\
|
||||
__func__, __LINE__, char_descr_val->attr_len, char_descr_val->attr_max_len);
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
memset(&arg, 0, sizeof(btc_ble_gatts_args_t));
|
||||
msg.sig = BTC_SIG_API_CALL;
|
||||
|
||||
@@ -46,6 +46,8 @@ typedef enum {
|
||||
ESP_GAP_BLE_SCAN_RESULT_EVT, /*!< When one scan result ready, the event comes each time */
|
||||
ESP_GAP_BLE_ADV_DATA_RAW_SET_COMPLETE_EVT, /*!< When raw advertising data set complete, the event comes */
|
||||
ESP_GAP_BLE_SCAN_RSP_DATA_RAW_SET_COMPLETE_EVT, /*!< When raw advertising data set complete, the event comes */
|
||||
ESP_GAP_BLE_ADV_START_COMPLETE_EVT, /*!< When start advertising complete, the event comes */
|
||||
ESP_GAP_BLE_SCAN_START_COMPLETE_EVT, /*!< When start scan complete, the event comes */
|
||||
} esp_gap_ble_cb_event_t;
|
||||
|
||||
/// Advertising data maximum length
|
||||
@@ -95,7 +97,7 @@ typedef enum {
|
||||
typedef enum {
|
||||
ADV_CHNL_37 = 0x01,
|
||||
ADV_CHNL_38 = 0x02,
|
||||
ADV_CHNL_39 = 0x03,
|
||||
ADV_CHNL_39 = 0x04,
|
||||
ADV_CHNL_ALL = 0x07,
|
||||
} esp_ble_adv_channel_t;
|
||||
|
||||
@@ -284,6 +286,18 @@ typedef union {
|
||||
struct ble_scan_rsp_data_raw_cmpl_evt_param {
|
||||
esp_bt_status_t status; /*!< Indicate the set raw advertising data operation success status */
|
||||
} scan_rsp_data_raw_cmpl; /*!< Event parameter of ESP_GAP_BLE_SCAN_RSP_DATA_RAW_SET_COMPLETE_EVT */
|
||||
/**
|
||||
* @brief ESP_GAP_BLE_ADV_START_COMPLETE_EVT
|
||||
*/
|
||||
struct ble_adv_start_cmpl_evt_param {
|
||||
esp_bt_status_t status; /*!< Indicate advertising start operation success status */
|
||||
} adv_start_cmpl; /*!< Event parameter of ESP_GAP_BLE_ADV_START_COMPLETE_EVT */
|
||||
/**
|
||||
* @brief ESP_GAP_BLE_SCAN_START_COMPLETE_EVT
|
||||
*/
|
||||
struct ble_scan_start_cmpl_evt_param {
|
||||
esp_bt_status_t status; /*!< Indicate scan start operation success status */
|
||||
} scan_start_cmpl; /*!< Event parameter of ESP_GAP_BLE_SCAN_START_COMPLETE_EVT */
|
||||
} esp_ble_gap_cb_param_t;
|
||||
|
||||
/**
|
||||
|
||||
@@ -4534,12 +4534,11 @@ void bta_dm_ble_observe (tBTA_DM_MSG *p_data)
|
||||
bta_dm_search_cb.p_scan_cback = p_data->ble_observe.p_cback;
|
||||
if ((status = BTM_BleObserve(TRUE, p_data->ble_observe.duration,
|
||||
bta_dm_observe_results_cb, bta_dm_observe_cmpl_cb)) != BTM_CMD_STARTED) {
|
||||
tBTA_DM_SEARCH data;
|
||||
APPL_TRACE_WARNING(" %s BTM_BleObserve failed. status %d\n", __FUNCTION__, status);
|
||||
data.inq_cmpl.num_resps = 0;
|
||||
if (bta_dm_search_cb.p_scan_cback) {
|
||||
bta_dm_search_cb.p_scan_cback(BTA_DM_INQ_CMPL_EVT, &data);
|
||||
}
|
||||
}
|
||||
if (p_data->ble_observe.p_start_scan_cback) {
|
||||
status = (status == BTM_CMD_STARTED ? BTA_SUCCESS : BTA_FAILURE);
|
||||
p_data->ble_observe.p_start_scan_cback(status);
|
||||
}
|
||||
} else {
|
||||
bta_dm_search_cb.p_scan_cback = NULL;
|
||||
@@ -4576,13 +4575,21 @@ void bta_dm_ble_set_adv_params (tBTA_DM_MSG *p_data)
|
||||
*******************************************************************************/
|
||||
void bta_dm_ble_set_adv_params_all (tBTA_DM_MSG *p_data)
|
||||
{
|
||||
BTM_BleSetAdvParamsStartAdv(p_data->ble_set_adv_params_all.adv_int_min,
|
||||
tBTA_STATUS status = BTA_FAILURE;
|
||||
|
||||
if (BTM_BleSetAdvParamsStartAdv(p_data->ble_set_adv_params_all.adv_int_min,
|
||||
p_data->ble_set_adv_params_all.adv_int_max,
|
||||
p_data->ble_set_adv_params_all.adv_type,
|
||||
p_data->ble_set_adv_params_all.addr_type_own,
|
||||
p_data->ble_set_adv_params_all.p_dir_bda,
|
||||
p_data->ble_set_adv_params_all.channel_map,
|
||||
p_data->ble_set_adv_params_all.adv_filter_policy);
|
||||
p_data->ble_set_adv_params_all.adv_filter_policy) == BTM_SUCCESS) {
|
||||
status = BTA_SUCCESS;
|
||||
}
|
||||
|
||||
if (p_data->ble_set_adv_params_all.p_start_adv_cback) {
|
||||
(*p_data->ble_set_adv_params_all.p_start_adv_cback)(status);
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
|
||||
@@ -1009,7 +1009,7 @@ void BTA_DmSetBleAdvParams (UINT16 adv_int_min, UINT16 adv_int_max,
|
||||
void BTA_DmSetBleAdvParamsAll (UINT16 adv_int_min, UINT16 adv_int_max,
|
||||
UINT8 adv_type, tBLE_ADDR_TYPE addr_type_own,
|
||||
tBTM_BLE_ADV_CHNL_MAP chnl_map, tBTM_BLE_AFP adv_fil_pol,
|
||||
tBLE_BD_ADDR *p_dir_bda)
|
||||
tBLE_BD_ADDR *p_dir_bda, tBTA_START_ADV_CMPL_CBACK p_start_adv_cb)
|
||||
{
|
||||
#if BLE_INCLUDED == TRUE
|
||||
tBTA_DM_API_BLE_ADV_PARAMS_ALL *p_msg;
|
||||
@@ -1029,6 +1029,7 @@ void BTA_DmSetBleAdvParamsAll (UINT16 adv_int_min, UINT16 adv_int_max,
|
||||
p_msg->addr_type_own = addr_type_own;
|
||||
p_msg->channel_map = chnl_map;
|
||||
p_msg->adv_filter_policy = adv_fil_pol;
|
||||
p_msg->p_start_adv_cback = p_start_adv_cb;
|
||||
if (p_dir_bda != NULL) {
|
||||
p_msg->p_dir_bda = (tBLE_BD_ADDR *)(p_msg + 1);
|
||||
memcpy(p_msg->p_dir_bda, p_dir_bda, sizeof(tBLE_BD_ADDR));
|
||||
@@ -2127,7 +2128,8 @@ void BTA_DmCloseACL(BD_ADDR bd_addr, BOOLEAN remove_dev, tBTA_TRANSPORT transpor
|
||||
**
|
||||
*******************************************************************************/
|
||||
extern void BTA_DmBleObserve(BOOLEAN start, UINT8 duration,
|
||||
tBTA_DM_SEARCH_CBACK *p_results_cb)
|
||||
tBTA_DM_SEARCH_CBACK *p_results_cb,
|
||||
tBTA_START_SCAN_CMPL_CBACK *p_start_scan_cb)
|
||||
{
|
||||
tBTA_DM_API_BLE_OBSERVE *p_msg;
|
||||
|
||||
@@ -2140,6 +2142,7 @@ extern void BTA_DmBleObserve(BOOLEAN start, UINT8 duration,
|
||||
p_msg->start = start;
|
||||
p_msg->duration = duration;
|
||||
p_msg->p_cback = p_results_cb;
|
||||
p_msg->p_start_scan_cback = p_start_scan_cb;
|
||||
|
||||
bta_sys_sendmsg(p_msg);
|
||||
}
|
||||
|
||||
@@ -471,7 +471,8 @@ typedef struct {
|
||||
BT_HDR hdr;
|
||||
BOOLEAN start;
|
||||
UINT16 duration;
|
||||
tBTA_DM_SEARCH_CBACK *p_cback;
|
||||
tBTA_DM_SEARCH_CBACK *p_cback;
|
||||
tBTA_START_SCAN_CMPL_CBACK *p_start_scan_cback;
|
||||
} tBTA_DM_API_BLE_OBSERVE;
|
||||
|
||||
typedef struct {
|
||||
@@ -506,6 +507,7 @@ typedef struct {
|
||||
tBTM_BLE_ADV_CHNL_MAP channel_map;
|
||||
tBTM_BLE_AFP adv_filter_policy;
|
||||
tBLE_BD_ADDR *p_dir_bda;
|
||||
tBTA_START_ADV_CMPL_CBACK *p_start_adv_cback;
|
||||
} tBTA_DM_API_BLE_ADV_PARAMS_ALL;
|
||||
|
||||
|
||||
|
||||
@@ -400,6 +400,8 @@ typedef struct {
|
||||
|
||||
typedef void (tBTA_SET_ADV_DATA_CMPL_CBACK) (tBTA_STATUS status);
|
||||
|
||||
typedef void (tBTA_START_ADV_CMPL_CBACK) (tBTA_STATUS status);
|
||||
|
||||
/* advertising channel map */
|
||||
#define BTA_BLE_ADV_CHNL_37 BTM_BLE_ADV_CHNL_37
|
||||
#define BTA_BLE_ADV_CHNL_38 BTM_BLE_ADV_CHNL_38
|
||||
@@ -1095,6 +1097,8 @@ typedef void (tBTA_BLE_SCAN_SETUP_CBACK) (tBTA_BLE_BATCH_SCAN_EVT evt,
|
||||
tBTA_DM_BLE_REF_VALUE ref_value,
|
||||
tBTA_STATUS status);
|
||||
|
||||
typedef void (tBTA_START_SCAN_CMPL_CBACK) (tBTA_STATUS status);
|
||||
|
||||
typedef void (tBTA_BLE_TRACK_ADV_CMPL_CBACK)(int action, tBTA_STATUS status,
|
||||
tBTA_DM_BLE_PF_AVBL_SPACE avbl_space,
|
||||
tBTA_DM_BLE_REF_VALUE ref_value);
|
||||
@@ -1891,7 +1895,7 @@ extern void BTA_DmSetBleAdvParams (UINT16 adv_int_min, UINT16 adv_int_max,
|
||||
extern void BTA_DmSetBleAdvParamsAll (UINT16 adv_int_min, UINT16 adv_int_max,
|
||||
UINT8 adv_type, tBLE_ADDR_TYPE addr_type_own,
|
||||
tBTM_BLE_ADV_CHNL_MAP chnl_map, tBTM_BLE_AFP adv_fil_pol,
|
||||
tBLE_BD_ADDR *p_dir_bda);
|
||||
tBLE_BD_ADDR *p_dir_bda, tBTA_START_ADV_CMPL_CBACK p_start_adv_cb);
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
@@ -1997,7 +2001,8 @@ extern void BTA_DmSetEncryption(BD_ADDR bd_addr, tBTA_TRANSPORT transport,
|
||||
**
|
||||
*******************************************************************************/
|
||||
extern void BTA_DmBleObserve(BOOLEAN start, UINT8 duration,
|
||||
tBTA_DM_SEARCH_CBACK *p_results_cb);
|
||||
tBTA_DM_SEARCH_CBACK *p_results_cb,
|
||||
tBTA_START_SCAN_CMPL_CBACK *p_start_scan_cb);
|
||||
|
||||
extern void BTA_DmBleStopAdvertising(void);
|
||||
|
||||
|
||||
@@ -177,6 +177,10 @@ static void blufi_profile_cb(tBTA_GATTS_EVT event, tBTA_GATTS *p_data)
|
||||
blufi_env.prepare_buf = NULL;
|
||||
}
|
||||
|
||||
break;
|
||||
case BTA_GATTS_MTU_EVT:
|
||||
LOG_DEBUG("MTU size %d\n", p_data->req_data.p_data->mtu);
|
||||
blufi_env.frag_size = p_data->req_data.p_data->mtu - BLUFI_MTU_RESERVED_SIZE;
|
||||
break;
|
||||
case BTA_GATTS_CONF_EVT:
|
||||
LOG_DEBUG("CONIRM EVT\n");
|
||||
@@ -264,6 +268,7 @@ static void blufi_profile_cb(tBTA_GATTS_EVT event, tBTA_GATTS *p_data)
|
||||
blufi_env.conn_id = p_data->conn.conn_id;
|
||||
blufi_env.is_connected = false;
|
||||
blufi_env.recv_seq = blufi_env.send_seq = 0;
|
||||
blufi_env.sec_mode = 0x0;
|
||||
|
||||
msg.sig = BTC_SIG_API_CB;
|
||||
msg.pid = BTC_PID_BLUFI;
|
||||
@@ -294,6 +299,7 @@ static tGATT_STATUS btc_blufi_profile_init(void)
|
||||
|
||||
memset(&blufi_env, 0x0, sizeof(blufi_env));
|
||||
blufi_env.cbs = store_p; /* if set callback prior, restore the point */
|
||||
blufi_env.frag_size = BLUFI_FRAG_DATA_DEFAULT_LEN;
|
||||
|
||||
/* register the BLUFI profile to the BTA_GATTS module*/
|
||||
BTA_GATTS_AppRegister(&blufi_app_uuid, blufi_profile_cb);
|
||||
@@ -406,16 +412,16 @@ void btc_blufi_send_encap(uint8_t type, uint8_t *data, int total_data_len)
|
||||
int ret;
|
||||
|
||||
while (remain_len > 0) {
|
||||
if (remain_len > BLUFI_FRAG_DATA_MAX_LEN) {
|
||||
hdr = GKI_getbuf(sizeof(struct blufi_hdr) + 2 + BLUFI_FRAG_DATA_MAX_LEN + 2);
|
||||
if (remain_len > blufi_env.frag_size) {
|
||||
hdr = GKI_getbuf(sizeof(struct blufi_hdr) + 2 + blufi_env.frag_size + 2);
|
||||
if (hdr == NULL) {
|
||||
LOG_ERROR("%s no mem\n", __func__);
|
||||
return;
|
||||
}
|
||||
hdr->fc = 0x0;
|
||||
hdr->data_len = BLUFI_FRAG_DATA_MAX_LEN + 2;
|
||||
hdr->data_len = blufi_env.frag_size + 2;
|
||||
*(uint16_t *)hdr->data = remain_len;
|
||||
memcpy(hdr->data + 2, &data[total_data_len - remain_len], BLUFI_FRAG_DATA_MAX_LEN); //copy first, easy for check sum
|
||||
memcpy(hdr->data + 2, &data[total_data_len - remain_len], blufi_env.frag_size); //copy first, easy for check sum
|
||||
hdr->fc |= BLUFI_FC_FRAG;
|
||||
} else {
|
||||
hdr = GKI_getbuf(sizeof(struct blufi_hdr) + remain_len + 2);
|
||||
|
||||
@@ -33,6 +33,7 @@ typedef struct {
|
||||
BD_ADDR remote_bda;
|
||||
UINT32 trans_id;
|
||||
UINT8 congest;
|
||||
UINT16 frag_size;
|
||||
#define BLUFI_PREPAIR_BUF_MAX_SIZE 1024
|
||||
uint8_t *prepare_buf;
|
||||
int prepare_len;
|
||||
@@ -160,7 +161,9 @@ typedef struct blufi_frag_hdr blufi_frag_hdr_t;
|
||||
#define BLUFI_FC_IS_REQ_ACK(fc) ((fc) & BLUFI_FC_REQ_ACK_MASK)
|
||||
#define BLUFI_FC_IS_FRAG(fc) ((fc) & BLUFI_FC_FRAG_MASK)
|
||||
|
||||
#define BLUFI_FRAG_DATA_MAX_LEN 50
|
||||
/* BLUFI HEADER + TOTAL(REMAIN) LENGTH + CRC + L2CAP RESERVED */
|
||||
#define BLUFI_MTU_RESERVED_SIZE (sizeof(struct blufi_hdr) + 2 + 2 + 3)
|
||||
#define BLUFI_FRAG_DATA_DEFAULT_LEN (GATT_DEF_BLE_MTU_SIZE - BLUFI_MTU_RESERVED_SIZE)
|
||||
|
||||
//function declare
|
||||
void btc_blufi_protocol_handler(uint8_t type, uint8_t *data, int len);
|
||||
|
||||
@@ -367,7 +367,26 @@ static void btc_ble_set_scan_rsp_data_raw(uint8_t *raw_scan_rsp, uint32_t raw_sc
|
||||
BTA_DmBleSetScanRspRaw(raw_scan_rsp, raw_scan_rsp_len, p_scan_rsp_data_cback);
|
||||
}
|
||||
|
||||
static void btc_ble_start_advertising (esp_ble_adv_params_t *ble_adv_params)
|
||||
static void btc_start_adv_callback(tBTA_STATUS status)
|
||||
{
|
||||
esp_ble_gap_cb_param_t param;
|
||||
bt_status_t ret;
|
||||
btc_msg_t msg;
|
||||
|
||||
msg.sig = BTC_SIG_API_CB;
|
||||
msg.pid = BTC_PID_GAP_BLE;
|
||||
msg.act = ESP_GAP_BLE_ADV_START_COMPLETE_EVT;
|
||||
param.adv_start_cmpl.status = status;
|
||||
|
||||
ret = btc_transfer_context(&msg, ¶m,
|
||||
sizeof(esp_ble_gap_cb_param_t), NULL);
|
||||
|
||||
if (ret != BT_STATUS_SUCCESS) {
|
||||
LOG_ERROR("%s btc_transfer_context failed\n", __func__);
|
||||
}
|
||||
}
|
||||
|
||||
static void btc_ble_start_advertising (esp_ble_adv_params_t *ble_adv_params, tBTA_START_ADV_CMPL_CBACK start_adv_cback)
|
||||
{
|
||||
tBLE_BD_ADDR peer_addr;
|
||||
|
||||
@@ -398,7 +417,8 @@ static void btc_ble_start_advertising (esp_ble_adv_params_t *ble_adv_params)
|
||||
ble_adv_params->own_addr_type,
|
||||
ble_adv_params->channel_map,
|
||||
ble_adv_params->adv_filter_policy,
|
||||
&peer_addr);
|
||||
&peer_addr,
|
||||
start_adv_cback);
|
||||
}
|
||||
|
||||
|
||||
@@ -456,8 +476,7 @@ static void btc_search_callback(tBTA_DM_SEARCH_EVT event, tBTA_DM_SEARCH *p_data
|
||||
param.scan_rst.ble_addr_type = p_data->inq_res.ble_addr_type;
|
||||
param.scan_rst.ble_evt_type = p_data->inq_res.ble_evt_type;
|
||||
param.scan_rst.flag = p_data->inq_res.flag;
|
||||
memcpy(param.scan_rst.ble_adv, p_data->inq_res.p_eir,
|
||||
ESP_BLE_ADV_DATA_LEN_MAX);
|
||||
memcpy(param.scan_rst.ble_adv, p_data->inq_res.p_eir, sizeof(param.scan_rst.ble_adv));
|
||||
break;
|
||||
}
|
||||
case BTA_DM_INQ_CMPL_EVT: {
|
||||
@@ -487,12 +506,33 @@ static void btc_search_callback(tBTA_DM_SEARCH_EVT event, tBTA_DM_SEARCH *p_data
|
||||
btc_transfer_context(&msg, ¶m, sizeof(esp_ble_gap_cb_param_t), NULL);
|
||||
}
|
||||
|
||||
|
||||
static void btc_ble_start_scanning(uint8_t duration, tBTA_DM_SEARCH_CBACK *results_cb)
|
||||
static void btc_start_scan_callback(tBTA_STATUS status)
|
||||
{
|
||||
if ((duration != 0) && (results_cb != NULL)) {
|
||||
esp_ble_gap_cb_param_t param;
|
||||
bt_status_t ret;
|
||||
btc_msg_t msg;
|
||||
|
||||
msg.sig = BTC_SIG_API_CB;
|
||||
msg.pid = BTC_PID_GAP_BLE;
|
||||
msg.act = ESP_GAP_BLE_SCAN_START_COMPLETE_EVT;
|
||||
param.scan_start_cmpl.status = status;
|
||||
|
||||
|
||||
ret = btc_transfer_context(&msg, ¶m,
|
||||
sizeof(esp_ble_gap_cb_param_t), NULL);
|
||||
|
||||
if (ret != BT_STATUS_SUCCESS) {
|
||||
LOG_ERROR("%s btc_transfer_context failed\n", __func__);
|
||||
}
|
||||
}
|
||||
|
||||
static void btc_ble_start_scanning(uint8_t duration,
|
||||
tBTA_DM_SEARCH_CBACK *results_cb,
|
||||
tBTA_START_SCAN_CMPL_CBACK *start_scan_cb)
|
||||
{
|
||||
if ((duration != 0) && (results_cb != NULL) && (start_scan_cb != NULL)) {
|
||||
///Start scan the device
|
||||
BTA_DmBleObserve(true, duration, results_cb);
|
||||
BTA_DmBleObserve(true, duration, results_cb, start_scan_cb);
|
||||
} else {
|
||||
LOG_ERROR("The scan duration or p_results_cb invalid\n");
|
||||
}
|
||||
@@ -501,7 +541,7 @@ static void btc_ble_start_scanning(uint8_t duration, tBTA_DM_SEARCH_CBACK *resul
|
||||
static void btc_ble_stop_scanning(void)
|
||||
{
|
||||
uint8_t duration = 0;
|
||||
BTA_DmBleObserve(false, duration, NULL);
|
||||
BTA_DmBleObserve(false, duration, NULL, NULL);
|
||||
}
|
||||
|
||||
|
||||
@@ -576,6 +616,12 @@ void btc_gap_ble_cb_handler(btc_msg_t *msg)
|
||||
case ESP_GAP_BLE_SCAN_RSP_DATA_RAW_SET_COMPLETE_EVT:
|
||||
btc_gap_ble_cb_to_app(ESP_GAP_BLE_SCAN_RSP_DATA_RAW_SET_COMPLETE_EVT, param);
|
||||
break;
|
||||
case ESP_GAP_BLE_ADV_START_COMPLETE_EVT:
|
||||
btc_gap_ble_cb_to_app(ESP_GAP_BLE_ADV_START_COMPLETE_EVT, param);
|
||||
break;
|
||||
case ESP_GAP_BLE_SCAN_START_COMPLETE_EVT:
|
||||
btc_gap_ble_cb_to_app(ESP_GAP_BLE_SCAN_START_COMPLETE_EVT, param);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
||||
@@ -695,13 +741,13 @@ void btc_gap_ble_call_handler(btc_msg_t *msg)
|
||||
btc_ble_set_scan_params(&arg->set_scan_param.scan_params, btc_scan_params_callback);
|
||||
break;
|
||||
case BTC_GAP_BLE_ACT_START_SCAN:
|
||||
btc_ble_start_scanning(arg->start_scan.duration, btc_search_callback);
|
||||
btc_ble_start_scanning(arg->start_scan.duration, btc_search_callback, btc_start_scan_callback);
|
||||
break;
|
||||
case BTC_GAP_BLE_ACT_STOP_SCAN:
|
||||
btc_ble_stop_scanning();
|
||||
break;
|
||||
case BTC_GAP_BLE_ACT_START_ADV:
|
||||
btc_ble_start_advertising(&arg->start_adv.adv_params);
|
||||
btc_ble_start_advertising(&arg->start_adv.adv_params, btc_start_adv_callback);
|
||||
break;
|
||||
case BTC_GAP_BLE_ACT_STOP_ADV:
|
||||
btc_ble_stop_advertising();
|
||||
|
||||
@@ -166,6 +166,30 @@ void btc_gatts_arg_deep_free(btc_msg_t *msg)
|
||||
}
|
||||
break;
|
||||
}
|
||||
case BTC_GATTS_ACT_ADD_CHAR:{
|
||||
if (arg->add_char.char_val.attr_value != NULL) {
|
||||
GKI_freebuf(arg->add_char.char_val.attr_value);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case BTC_GATTS_ACT_ADD_CHAR_DESCR:{
|
||||
if (arg->add_descr.descr_val.attr_value != NULL){
|
||||
GKI_freebuf(arg->add_descr.descr_val.attr_value);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case BTC_GATTS_ACT_CREATE_ATTR_TAB:{
|
||||
if (arg->create_attr_tab.gatts_attr_db != NULL){
|
||||
GKI_freebuf(arg->create_attr_tab.gatts_attr_db);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case BTC_GATTS_ACT_SET_ATTR_VALUE:{
|
||||
if (arg->set_attr_val.value != NULL){
|
||||
GKI_freebuf(arg->set_attr_val.value);
|
||||
}
|
||||
}
|
||||
|
||||
default:
|
||||
LOG_DEBUG("%s Unhandled deep free %d\n", __func__, msg->act);
|
||||
break;
|
||||
@@ -182,13 +206,16 @@ static void btc_gatts_act_create_attr_tab(esp_gatts_attr_db_t *gatts_attr_db,
|
||||
future_t *future_p;
|
||||
esp_ble_gatts_cb_param_t param;
|
||||
|
||||
//set the attribute table create service flag to ture
|
||||
//set the attribute table create service flag to true
|
||||
btc_creat_tab_env.is_tab_creat_svc = true;
|
||||
btc_creat_tab_env.num_handle = max_nb_attr;
|
||||
for(int i = 0; i < max_nb_attr; i++){
|
||||
if(gatts_attr_db[i].att_desc.uuid_length== ESP_UUID_LEN_16){
|
||||
uuid = (gatts_attr_db[i].att_desc.uuid_p[1] << 8) + (gatts_attr_db[i].att_desc.uuid_p[0]);
|
||||
}
|
||||
else{
|
||||
continue;
|
||||
}
|
||||
future_p = future_new();
|
||||
if (future_p == NULL) {
|
||||
LOG_ERROR("%s failed:no mem\n", __func__);
|
||||
|
||||
@@ -221,6 +221,10 @@ static void start_up(void)
|
||||
}
|
||||
|
||||
if (HCI_LE_DATA_LEN_EXT_SUPPORTED(features_ble.as_array)) {
|
||||
/* set default tx data length to MAX 251 */
|
||||
response = AWAIT_COMMAND(packet_factory->make_ble_write_suggested_default_data_length(BTM_BLE_DATA_SIZE_MAX, BTM_BLE_DATA_TX_TIME_MAX));
|
||||
packet_parser->parse_generic_command_complete(response);
|
||||
|
||||
response = AWAIT_COMMAND(packet_factory->make_ble_read_suggested_default_data_length());
|
||||
packet_parser->parse_ble_read_suggested_default_data_length_response(
|
||||
response,
|
||||
|
||||
@@ -154,6 +154,17 @@ static BT_HDR *make_ble_read_suggested_default_data_length(void)
|
||||
return make_command_no_params(HCI_BLE_READ_DEFAULT_DATA_LENGTH);
|
||||
}
|
||||
|
||||
static BT_HDR *make_ble_write_suggested_default_data_length(uint16_t SuggestedMaxTxOctets, uint16_t SuggestedMaxTxTime)
|
||||
{
|
||||
uint8_t *stream;
|
||||
uint8_t parameter_size = sizeof(uint16_t) + sizeof(uint16_t);
|
||||
BT_HDR *packet = make_command(HCI_BLE_WRITE_DEFAULT_DATA_LENGTH, parameter_size, &stream);
|
||||
|
||||
UINT16_TO_STREAM(stream, SuggestedMaxTxOctets);
|
||||
UINT16_TO_STREAM(stream, SuggestedMaxTxTime);
|
||||
return packet;
|
||||
}
|
||||
|
||||
static BT_HDR *make_ble_set_event_mask(const bt_event_mask_t *event_mask)
|
||||
{
|
||||
uint8_t *stream;
|
||||
@@ -215,6 +226,7 @@ static const hci_packet_factory_t interface = {
|
||||
make_ble_read_local_supported_features,
|
||||
make_ble_read_resolving_list_size,
|
||||
make_ble_read_suggested_default_data_length,
|
||||
make_ble_write_suggested_default_data_length,
|
||||
make_ble_set_event_mask
|
||||
};
|
||||
|
||||
|
||||
@@ -40,6 +40,7 @@ typedef struct {
|
||||
BT_HDR *(*make_ble_read_local_supported_features)(void);
|
||||
BT_HDR *(*make_ble_read_resolving_list_size)(void);
|
||||
BT_HDR *(*make_ble_read_suggested_default_data_length)(void);
|
||||
BT_HDR *(*make_ble_write_suggested_default_data_length)(uint16_t SuggestedMaxTxOctets, uint16_t SuggestedMaxTxTime);
|
||||
BT_HDR *(*make_ble_set_event_mask)(const bt_event_mask_t *event_mask);
|
||||
} hci_packet_factory_t;
|
||||
|
||||
|
||||
@@ -43,25 +43,27 @@ enum {
|
||||
SIG_BTIF_WORK = 0xff
|
||||
};
|
||||
|
||||
#define HCI_HOST_TASK_STACK_SIZE 1500
|
||||
#define HCI_HOST_TASK_PRIO (configMAX_PRIORITIES - 2)
|
||||
#define HCI_HOST_TASK_NAME "hciHostT"
|
||||
#define HCI_HOST_QUEUE_NUM 40
|
||||
|
||||
#define HCI_H4_TASK_STACK_SIZE 1500
|
||||
#define HCI_H4_TASK_PRIO (configMAX_PRIORITIES - 3)
|
||||
#define HCI_H4_TASK_NAME "hciH4T"
|
||||
#define HCI_H4_QUEUE_NUM 60
|
||||
#define BT_TASK_EXTRA_STACK_SIZE 512
|
||||
#define HCI_HOST_TASK_STACK_SIZE (2048 + BT_TASK_EXTRA_STACK_SIZE)
|
||||
#define HCI_HOST_TASK_PRIO (configMAX_PRIORITIES - 2)
|
||||
#define HCI_HOST_TASK_NAME "hciHostT"
|
||||
#define HCI_HOST_QUEUE_NUM 40
|
||||
|
||||
#define BTU_TASK_STACK_SIZE 4096
|
||||
#define BTU_TASK_PRIO (configMAX_PRIORITIES - 4)
|
||||
#define BTU_TASK_NAME "btuT"
|
||||
#define BTU_QUEUE_NUM 50
|
||||
#define HCI_H4_TASK_STACK_SIZE (2048 + BT_TASK_EXTRA_STACK_SIZE)
|
||||
#define HCI_H4_TASK_PRIO (configMAX_PRIORITIES - 3)
|
||||
#define HCI_H4_TASK_NAME "hciH4T"
|
||||
#define HCI_H4_QUEUE_NUM 60
|
||||
|
||||
#define BTC_TASK_STACK_SIZE CONFIG_BTC_TASK_STACK_SIZE //by menuconfig
|
||||
#define BTC_TASK_NAME "btcT"
|
||||
#define BTC_TASK_PRIO (configMAX_PRIORITIES - 5)
|
||||
#define BTC_TASK_QUEUE_NUM 20
|
||||
#define BTU_TASK_STACK_SIZE (3584 + BT_TASK_EXTRA_STACK_SIZE)
|
||||
#define BTU_TASK_PRIO (configMAX_PRIORITIES - 4)
|
||||
#define BTU_TASK_NAME "btuT"
|
||||
#define BTU_QUEUE_NUM 50
|
||||
|
||||
#define BTC_TASK_STACK_SIZE (CONFIG_BTC_TASK_STACK_SIZE + BT_TASK_EXTRA_STACK_SIZE) //by menuconfig
|
||||
#define BTC_TASK_NAME "btcT"
|
||||
#define BTC_TASK_PRIO (configMAX_PRIORITIES - 5)
|
||||
#define BTC_TASK_QUEUE_NUM 60
|
||||
|
||||
void btu_task_post(uint32_t sig);
|
||||
void hci_host_task_post(void);
|
||||
|
||||
@@ -2935,14 +2935,18 @@ tBTM_STATUS btm_ble_start_scan(void)
|
||||
tBTM_BLE_INQ_CB *p_inq = &btm_cb.ble_ctr_cb.inq_var;
|
||||
tBTM_STATUS status = BTM_CMD_STARTED;
|
||||
|
||||
/* start scan, disable duplicate filtering */
|
||||
if (!btsnd_hcic_ble_set_scan_enable (BTM_BLE_SCAN_ENABLE, p_inq->scan_duplicate_filter)) {
|
||||
if (p_inq->adv_mode != BTM_BLE_ADV_DISABLE) {
|
||||
status = BTM_NO_RESOURCES;
|
||||
} else {
|
||||
if (p_inq->scan_type == BTM_BLE_SCAN_MODE_ACTI) {
|
||||
btm_ble_set_topology_mask(BTM_BLE_STATE_ACTIVE_SCAN_BIT);
|
||||
/* start scan, disable duplicate filtering */
|
||||
if (!btsnd_hcic_ble_set_scan_enable (BTM_BLE_SCAN_ENABLE, p_inq->scan_duplicate_filter)) {
|
||||
status = BTM_NO_RESOURCES;
|
||||
} else {
|
||||
btm_ble_set_topology_mask(BTM_BLE_STATE_PASSIVE_SCAN_BIT);
|
||||
if (p_inq->scan_type == BTM_BLE_SCAN_MODE_ACTI) {
|
||||
btm_ble_set_topology_mask(BTM_BLE_STATE_ACTIVE_SCAN_BIT);
|
||||
} else {
|
||||
btm_ble_set_topology_mask(BTM_BLE_STATE_PASSIVE_SCAN_BIT);
|
||||
}
|
||||
}
|
||||
}
|
||||
return status;
|
||||
@@ -2961,15 +2965,17 @@ void btm_ble_stop_scan(void)
|
||||
{
|
||||
BTM_TRACE_EVENT ("btm_ble_stop_scan ");
|
||||
|
||||
/* Clear the inquiry callback if set */
|
||||
btm_cb.ble_ctr_cb.inq_var.scan_type = BTM_BLE_SCAN_MODE_NONE;
|
||||
if (btm_cb.ble_ctr_cb.inq_var.adv_mode == BTM_BLE_ADV_DISABLE) {
|
||||
/* Clear the inquiry callback if set */
|
||||
btm_cb.ble_ctr_cb.inq_var.scan_type = BTM_BLE_SCAN_MODE_NONE;
|
||||
|
||||
/* stop discovery now */
|
||||
btsnd_hcic_ble_set_scan_enable (BTM_BLE_SCAN_DISABLE, BTM_BLE_DUPLICATE_ENABLE);
|
||||
/* stop discovery now */
|
||||
btsnd_hcic_ble_set_scan_enable (BTM_BLE_SCAN_DISABLE, BTM_BLE_DUPLICATE_ENABLE);
|
||||
|
||||
btm_update_scanner_filter_policy(SP_ADV_ALL);
|
||||
btm_update_scanner_filter_policy(SP_ADV_ALL);
|
||||
|
||||
btm_cb.ble_ctr_cb.wl_state &= ~BTM_BLE_WL_SCAN;
|
||||
btm_cb.ble_ctr_cb.wl_state &= ~BTM_BLE_WL_SCAN;
|
||||
}
|
||||
}
|
||||
/*******************************************************************************
|
||||
**
|
||||
@@ -3089,9 +3095,15 @@ static BOOLEAN btm_ble_adv_states_operation(BTM_TOPOLOGY_FUNC_PTR *p_handler, UI
|
||||
*******************************************************************************/
|
||||
tBTM_STATUS btm_ble_start_adv(void)
|
||||
{
|
||||
tBTM_BLE_CB *p_ble_cb = & btm_cb.ble_ctr_cb;
|
||||
tBTM_BLE_INQ_CB *p_cb = &btm_cb.ble_ctr_cb.inq_var;
|
||||
tBTM_STATUS rt = BTM_NO_RESOURCES;
|
||||
BTM_TRACE_EVENT ("btm_ble_start_adv\n");
|
||||
|
||||
if (BTM_BLE_IS_OBS_ACTIVE(p_ble_cb->scan_activity)) {
|
||||
return BTM_NO_RESOURCES;
|
||||
}
|
||||
|
||||
if (!btm_ble_adv_states_operation (btm_ble_topology_check, p_cb->evt_type)) {
|
||||
return BTM_WRONG_MODE;
|
||||
}
|
||||
@@ -3133,10 +3145,12 @@ tBTM_STATUS btm_ble_start_adv(void)
|
||||
*******************************************************************************/
|
||||
tBTM_STATUS btm_ble_stop_adv(void)
|
||||
{
|
||||
tBTM_BLE_CB *p_ble_cb = & btm_cb.ble_ctr_cb;
|
||||
tBTM_BLE_INQ_CB *p_cb = &btm_cb.ble_ctr_cb.inq_var;
|
||||
tBTM_STATUS rt = BTM_SUCCESS;
|
||||
|
||||
if (p_cb->adv_mode == BTM_BLE_ADV_ENABLE) {
|
||||
if (p_cb->adv_mode == BTM_BLE_ADV_ENABLE
|
||||
&& !BTM_BLE_IS_OBS_ACTIVE(p_ble_cb->scan_activity)) {
|
||||
if (btsnd_hcic_ble_set_adv_enable (BTM_BLE_ADV_DISABLE)) {
|
||||
p_cb->fast_adv_on = FALSE;
|
||||
p_cb->adv_mode = BTM_BLE_ADV_DISABLE;
|
||||
|
||||
@@ -214,6 +214,7 @@ UINT16 GATTS_CreateService (tGATT_IF gatt_if, tBT_UUID *p_svc_uuid,
|
||||
|
||||
if (p_list) {
|
||||
gatt_remove_an_item_from_list(p_list_info, p_list);
|
||||
gatt_free_attr_value_buffer(p_list);
|
||||
gatt_free_hdl_buffer(p_list);
|
||||
}
|
||||
return (0);
|
||||
@@ -227,6 +228,7 @@ UINT16 GATTS_CreateService (tGATT_IF gatt_if, tBT_UUID *p_svc_uuid,
|
||||
GATT_TRACE_ERROR ("GATTS_ReserveHandles: service DB initialization failed\n");
|
||||
if (p_list) {
|
||||
gatt_remove_an_item_from_list(p_list_info, p_list);
|
||||
gatt_free_attr_value_buffer(p_list);
|
||||
gatt_free_hdl_buffer(p_list);
|
||||
}
|
||||
|
||||
@@ -413,6 +415,7 @@ BOOLEAN GATTS_DeleteService (tGATT_IF gatt_if, tBT_UUID *p_svc_uuid, UINT16 svc_
|
||||
}
|
||||
|
||||
gatt_remove_an_item_from_list(p_list_info, p_list);
|
||||
gatt_free_attr_value_buffer(p_list);
|
||||
gatt_free_hdl_buffer(p_list);
|
||||
|
||||
return (TRUE);
|
||||
|
||||
@@ -268,14 +268,21 @@ static tGATT_STATUS read_attr_value (void *p_attr,
|
||||
status = GATT_SUCCESS;
|
||||
}
|
||||
} else { /* characteristic description or characteristic value */
|
||||
|
||||
if (p_attr16->control.auto_rsp == GATT_RSP_BY_STACK) {
|
||||
if (p_attr16->p_value != NULL && p_attr16->p_value->attr_val.attr_val != NULL) {
|
||||
uint8_t *value = p_attr16->p_value->attr_val.attr_val + offset;
|
||||
len = (mtu >= p_attr16->p_value->attr_val.attr_len) ? (p_attr16->p_value->attr_val.attr_len) : mtu;
|
||||
ARRAY_TO_STREAM(p, value, len);
|
||||
if (p_attr16->p_value == NULL || p_attr16->p_value->attr_val.attr_val == NULL) {
|
||||
status = GATT_ESP_ERROR;
|
||||
}
|
||||
else if (offset > p_attr16->p_value->attr_val.attr_len){
|
||||
/*if offset equal to max_len, should respond with zero byte value
|
||||
//if offset is greater than max_len, should respond with an error*/
|
||||
status = GATT_INVALID_OFFSET;
|
||||
} else {
|
||||
UINT8 *value = (UINT8 *)(p_attr16->p_value->attr_val.attr_val) + offset;
|
||||
UINT16 len_left = p_attr16->p_value->attr_val.attr_len - offset;
|
||||
len = (mtu >= len_left) ? (len_left) : mtu;
|
||||
ARRAY_TO_STREAM(p, value, len);
|
||||
status = GATT_STACK_RSP;
|
||||
}
|
||||
status = GATT_STACK_RSP;
|
||||
|
||||
} else {
|
||||
status = GATT_PENDING;
|
||||
@@ -463,6 +470,27 @@ UINT16 gatts_add_characteristic (tGATT_SVC_DB *p_db, tGATT_PERM perm,
|
||||
tBT_UUID uuid = {LEN_UUID_16, {GATT_UUID_CHAR_DECLARE}};
|
||||
|
||||
GATT_TRACE_DEBUG("gatts_add_characteristic perm=0x%0x property=0x%0x\n", perm, property);
|
||||
/* parameter validation check */
|
||||
if ((control != NULL) && (control->auto_rsp == GATT_STACK_RSP)){
|
||||
if (attr_val == NULL){
|
||||
GATT_TRACE_ERROR("Error in %s, line=%d, for stack respond attribute, attr_val should not be NULL here\n",\
|
||||
__func__, __LINE__);
|
||||
return 0;
|
||||
} else if (attr_val->attr_max_len == 0){
|
||||
GATT_TRACE_ERROR("Error in %s, line=%d, for stack respond attribute, attribute max length should not be 0\n",\
|
||||
__func__, __LINE__);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (attr_val != NULL){
|
||||
if (attr_val->attr_len > attr_val->attr_max_len){
|
||||
GATT_TRACE_ERROR("Error in %s, line=%d,attribute actual length should not be larger than max length\n",\
|
||||
__func__, __LINE__);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if ((p_char_decl = (tGATT_ATTR16 *)allocate_attr_in_db(p_db, &uuid, GATT_PERM_READ)) != NULL) {
|
||||
if (!copy_extra_byte_in_db(p_db, (void **)&p_char_decl->p_value, sizeof(tGATT_CHAR_DECL))) {
|
||||
@@ -483,10 +511,9 @@ UINT16 gatts_add_characteristic (tGATT_SVC_DB *p_db, tGATT_PERM perm,
|
||||
p_char_val->control.auto_rsp = control->auto_rsp;
|
||||
} else {
|
||||
p_char_val->control.auto_rsp = GATT_RSP_DEFAULT;
|
||||
|
||||
}
|
||||
|
||||
if (attr_val != NULL) {
|
||||
if (attr_val != NULL) {
|
||||
if (!copy_extra_byte_in_db(p_db, (void **)&p_char_val->p_value, sizeof(tGATT_ATTR_VAL))) {
|
||||
deallocate_attr_in_db(p_db, p_char_val);
|
||||
return 0;
|
||||
@@ -496,12 +523,27 @@ UINT16 gatts_add_characteristic (tGATT_SVC_DB *p_db, tGATT_PERM perm,
|
||||
p_char_val->p_value->attr_val.attr_len = attr_val->attr_len;
|
||||
p_char_val->p_value->attr_val.attr_max_len = attr_val->attr_max_len;
|
||||
p_char_val->p_value->attr_val.attr_val = GKI_getbuf(attr_val->attr_max_len);
|
||||
if (p_char_val->p_value->attr_val.attr_val != NULL) {
|
||||
GATT_TRACE_DEBUG("attribute value not NULL");
|
||||
memcpy(p_char_val->p_value->attr_val.attr_val, attr_val->attr_val, attr_val->attr_len);
|
||||
if (p_char_val->p_value->attr_val.attr_val == NULL) {
|
||||
deallocate_attr_in_db(p_db, p_char_decl);
|
||||
deallocate_attr_in_db(p_db, p_char_val);
|
||||
GATT_TRACE_WARNING("Warning in %s, line=%d, insufficient resource to allocate for attribute value\n", __func__, __LINE__);
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
//add mask to indicate that p_value->attr_val.attr_val is dynamic allocated
|
||||
p_char_val->mask |= GATT_ATTR_VALUE_ALLOCATED;
|
||||
}
|
||||
|
||||
//initiate characteristic attribute value part
|
||||
memset(p_char_val->p_value->attr_val.attr_val, 0, attr_val->attr_max_len);
|
||||
if (attr_val->attr_val != NULL) {
|
||||
if (attr_val->attr_max_len < attr_val->attr_len){
|
||||
GATT_TRACE_ERROR("Error in %s, Line=%d, attribute actual length (%d) should not larger than max size (%d)\n",
|
||||
__func__, __LINE__, attr_val->attr_len, attr_val->attr_max_len);
|
||||
}
|
||||
UINT16 actual_len = (attr_val->attr_max_len < attr_val->attr_len) ? (attr_val->attr_max_len) : (attr_val->attr_len);
|
||||
memcpy(p_char_val->p_value->attr_val.attr_val, attr_val->attr_val, actual_len);
|
||||
}
|
||||
} else {
|
||||
p_char_val->p_value = NULL;
|
||||
}
|
||||
|
||||
return p_char_val->handle;
|
||||
@@ -582,14 +624,35 @@ UINT16 gatts_add_char_descr (tGATT_SVC_DB *p_db, tGATT_PERM perm,
|
||||
|
||||
GATT_TRACE_DEBUG("gatts_add_char_descr uuid=0x%04x\n", p_descr_uuid->uu.uuid16);
|
||||
|
||||
/* parameter validation check */
|
||||
if ((control != NULL) && (control->auto_rsp == GATT_STACK_RSP)){
|
||||
if (attr_val == NULL){
|
||||
GATT_TRACE_ERROR("Error in %s, line=%d, for stack respond attribute, attr_val should not be NULL here\n",\
|
||||
__func__, __LINE__);
|
||||
return 0;
|
||||
} else if (attr_val->attr_max_len == 0){
|
||||
GATT_TRACE_ERROR("Error in %s, line=%d, for stack respond attribute, attribute max length should not be 0\n",\
|
||||
__func__, __LINE__);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (attr_val != NULL){
|
||||
if (attr_val->attr_len > attr_val->attr_max_len){
|
||||
GATT_TRACE_ERROR("Error in %s, line=%d,attribute actual length (%d) should not be larger than max length (%d)\n",\
|
||||
__func__, __LINE__, attr_val->attr_len, attr_val->attr_max_len);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Add characteristic descriptors */
|
||||
if ((p_char_dscptr = (tGATT_ATTR16 *)allocate_attr_in_db(p_db, p_descr_uuid, perm)) == NULL) {
|
||||
deallocate_attr_in_db(p_db, p_char_dscptr);
|
||||
GATT_TRACE_DEBUG("gatts_add_char_descr Fail for adding char descriptors.");
|
||||
return 0;
|
||||
} else {
|
||||
if (control != NULL) {
|
||||
p_char_dscptr->control.auto_rsp = control->auto_rsp;
|
||||
}
|
||||
p_char_dscptr->control.auto_rsp = (control == NULL) ? GATT_RSP_DEFAULT : (control->auto_rsp);
|
||||
if (attr_val != NULL) {
|
||||
if (!copy_extra_byte_in_db(p_db, (void **)&p_char_dscptr->p_value, sizeof(tGATT_ATTR_VAL))) {
|
||||
deallocate_attr_in_db(p_db, p_char_dscptr);
|
||||
@@ -597,10 +660,21 @@ UINT16 gatts_add_char_descr (tGATT_SVC_DB *p_db, tGATT_PERM perm,
|
||||
}
|
||||
p_char_dscptr->p_value->attr_val.attr_len = attr_val->attr_len;
|
||||
p_char_dscptr->p_value->attr_val.attr_max_len = attr_val->attr_max_len;
|
||||
if (attr_val->attr_val != NULL) {
|
||||
if (attr_val->attr_max_len != 0) {
|
||||
p_char_dscptr->p_value->attr_val.attr_val = GKI_getbuf(attr_val->attr_max_len);
|
||||
if (p_char_dscptr->p_value->attr_val.attr_val != NULL) {
|
||||
memset(p_char_dscptr->p_value->attr_val.attr_val, 0, attr_val->attr_max_len);
|
||||
if (p_char_dscptr->p_value->attr_val.attr_val == NULL) {
|
||||
deallocate_attr_in_db(p_db, p_char_dscptr);
|
||||
GATT_TRACE_WARNING("Warning in %s, line=%d, insufficient resource to allocate for descriptor value\n", __func__, __LINE__);
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
//add mask to indicate that p_value->attr_val.attr_val is dynamic allocated
|
||||
p_char_dscptr->mask |= GATT_ATTR_VALUE_ALLOCATED;
|
||||
}
|
||||
|
||||
//initiate characteristic attribute value part
|
||||
memset(p_char_dscptr->p_value->attr_val.attr_val, 0, attr_val->attr_max_len);
|
||||
if(attr_val->attr_val != NULL) {
|
||||
memcpy(p_char_dscptr->p_value->attr_val.attr_val, attr_val->attr_val, attr_val->attr_len);
|
||||
}
|
||||
}
|
||||
@@ -625,7 +699,7 @@ UINT16 gatts_add_char_descr (tGATT_SVC_DB *p_db, tGATT_PERM perm,
|
||||
**
|
||||
*******************************************************************************/
|
||||
tGATT_STATUS gatts_set_attribute_value(tGATT_SVC_DB *p_db, UINT16 attr_handle,
|
||||
UINT16 length, UINT8 *value)
|
||||
UINT16 length, UINT8 *value)
|
||||
{
|
||||
tGATT_ATTR16 *p_cur;
|
||||
|
||||
@@ -637,51 +711,46 @@ tGATT_STATUS gatts_set_attribute_value(tGATT_SVC_DB *p_db, UINT16 attr_handle,
|
||||
GATT_TRACE_DEBUG("gatts_set_attribute_value Fail:p_db->p_attr_list is NULL.\n");
|
||||
return GATT_INVALID_PDU;
|
||||
}
|
||||
if ((length > 0) && (value == NULL)){
|
||||
GATT_TRACE_ERROR("Error in %s, line=%d, value should not be NULL here\n",__func__, __LINE__);
|
||||
return GATT_INVALID_PDU;
|
||||
}
|
||||
|
||||
p_cur = (tGATT_ATTR16 *) p_db->p_attr_list;
|
||||
|
||||
while (p_cur != NULL) {
|
||||
if (p_cur->handle == attr_handle) {
|
||||
|
||||
/* for characteristic should not be set, return GATT_NOT_FOUND */
|
||||
if (p_cur->uuid_type == GATT_ATTR_UUID_TYPE_16) {
|
||||
switch (p_cur->uuid) {
|
||||
case GATT_UUID_PRI_SERVICE:
|
||||
case GATT_UUID_SEC_SERVICE:
|
||||
case GATT_UUID_CHAR_DECLARE:
|
||||
case GATT_UUID_INCLUDE_SERVICE:
|
||||
return GATT_NOT_FOUND;
|
||||
default:
|
||||
if (p_cur->p_value != NULL && p_cur->p_value->attr_val.attr_max_len < length) {
|
||||
GATT_TRACE_ERROR("gatts_set_attribute_vaule failt:Invalid value length");
|
||||
return GATT_INVALID_ATTR_LEN;
|
||||
} else if (p_cur->p_value != NULL && p_cur->p_value->attr_val.attr_max_len > 0) {
|
||||
memcpy(p_cur->p_value->attr_val.attr_val, value, length);
|
||||
p_cur->p_value->attr_val.attr_len = length;
|
||||
} else {
|
||||
return GATT_INVALID_ATTR_LEN;
|
||||
}
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (p_cur->p_value != NULL && p_cur->p_value->attr_val.attr_max_len < length) {
|
||||
GATT_TRACE_ERROR("gatts_set_attribute_vaule failt:Invalid value length");
|
||||
} else if (p_cur->p_value != NULL && p_cur->p_value->attr_val.attr_max_len > 0) {
|
||||
memcpy(p_cur->p_value->attr_val.attr_val, value, length);
|
||||
p_cur->p_value->attr_val.attr_len = length;
|
||||
} else {
|
||||
return GATT_INVALID_ATTR_LEN;
|
||||
case GATT_UUID_PRI_SERVICE:
|
||||
case GATT_UUID_SEC_SERVICE:
|
||||
case GATT_UUID_CHAR_DECLARE:
|
||||
return GATT_NOT_FOUND;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* in other cases, value can be set*/
|
||||
if ((p_cur->p_value == NULL) || (p_cur->p_value->attr_val.attr_val == NULL) \
|
||||
|| (p_cur->p_value->attr_val.attr_max_len == 0)){
|
||||
GATT_TRACE_ERROR("Error in %s, line=%d, attribute value should not be NULL here\n", __func__, __LINE__);
|
||||
return GATT_NOT_FOUND;
|
||||
} else if (p_cur->p_value->attr_val.attr_max_len < length) {
|
||||
GATT_TRACE_ERROR("gatts_set_attribute_value failed:Invalid value length");
|
||||
return GATT_INVALID_ATTR_LEN;
|
||||
} else{
|
||||
memcpy(p_cur->p_value->attr_val.attr_val, value, length);
|
||||
p_cur->p_value->attr_val.attr_len = length;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
p_cur = p_cur->p_next;
|
||||
}
|
||||
|
||||
return GATT_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function gatts_get_attribute_value
|
||||
@@ -872,20 +941,25 @@ tGATT_STATUS gatts_write_attr_value_by_handle(tGATT_SVC_DB *p_db,
|
||||
return GATT_APP_RSP;
|
||||
}
|
||||
|
||||
if (p_attr->p_value != NULL && (p_attr->p_value->attr_val.attr_max_len >=
|
||||
offset + len)) {
|
||||
if ((p_attr->p_value != NULL) &&
|
||||
(p_attr->p_value->attr_val.attr_max_len >= offset + len) &&
|
||||
p_attr->p_value->attr_val.attr_val != NULL) {
|
||||
memcpy(p_attr->p_value->attr_val.attr_val + offset, p_value, len);
|
||||
p_attr->p_value->attr_val.attr_len = len + offset;
|
||||
return GATT_SUCCESS;
|
||||
} else {
|
||||
return GATT_NOT_LONG;
|
||||
} else if (p_attr->p_value->attr_val.attr_max_len < offset + len){
|
||||
GATT_TRACE_DEBUG("Remote device try to write with a length larger then attribute's max length\n");
|
||||
return GATT_INVALID_ATTR_LEN;
|
||||
} else if ((p_attr->p_value == NULL) || (p_attr->p_value->attr_val.attr_val == NULL)){
|
||||
GATT_TRACE_ERROR("Error in %s, line=%d, %s should not be NULL here\n", __func__, __LINE__, \
|
||||
(p_attr->p_value == NULL) ? "p_value" : "attr_val.attr_val");
|
||||
return GATT_ESP_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
p_attr = (tGATT_ATTR16 *)p_attr->p_next;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return status;
|
||||
@@ -1332,7 +1406,13 @@ static tGATT_STATUS gatts_send_app_read_request(tGATT_TCB *p_tcb, UINT8 op_code,
|
||||
|
||||
gatt_sr_send_req_callback(conn_id,
|
||||
trans_id, GATTS_REQ_TYPE_READ, &sr_data);
|
||||
return (tGATT_STATUS) GATT_PENDING;
|
||||
|
||||
if (need_rsp) {
|
||||
return (tGATT_STATUS) GATT_PENDING;
|
||||
}
|
||||
else{
|
||||
return (tGATT_STATUS) GATT_STACK_RSP;
|
||||
}
|
||||
} else {
|
||||
return (tGATT_STATUS) GATT_BUSY; /* max pending command, application error */
|
||||
}
|
||||
|
||||
@@ -33,6 +33,42 @@
|
||||
#define GATT_MTU_REQ_MIN_LEN 2
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function gatt_send_packet
|
||||
**
|
||||
** Description This function is called to send gatt packets directly
|
||||
|
||||
**
|
||||
** Returns status
|
||||
**
|
||||
*******************************************************************************/
|
||||
tGATT_STATUS gatt_send_packet (tGATT_TCB *p_tcb, UINT8 *p_data, UINT16 len)
|
||||
{
|
||||
BT_HDR *p_msg = NULL;
|
||||
UINT8 *p_m = NULL;
|
||||
UINT16 buf_len;
|
||||
tGATT_STATUS status;
|
||||
|
||||
if (len > p_tcb->payload_size){
|
||||
return GATT_ILLEGAL_PARAMETER;
|
||||
}
|
||||
|
||||
buf_len = (UINT16)(sizeof(BT_HDR) + p_tcb->payload_size + L2CAP_MIN_OFFSET);
|
||||
if ((p_msg = (BT_HDR *)GKI_getbuf(buf_len)) == NULL) {
|
||||
return GATT_NO_RESOURCES;
|
||||
}
|
||||
|
||||
memset(p_msg, 0, buf_len);
|
||||
p_msg->len = len;
|
||||
p_m = (UINT8 *)(p_msg + 1) + L2CAP_MIN_OFFSET;
|
||||
memcpy(p_m, p_data, len);
|
||||
|
||||
status = attp_send_sr_msg(p_tcb, p_msg);
|
||||
return status;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function gatt_sr_enqueue_cmd
|
||||
@@ -300,7 +336,11 @@ void gatt_process_exec_write_req (tGATT_TCB *p_tcb, UINT8 op_code, UINT16 len, U
|
||||
UINT32 trans_id = 0;
|
||||
tGATT_IF gatt_if;
|
||||
UINT16 conn_id;
|
||||
|
||||
UINT16 queue_num = 0;
|
||||
BOOLEAN is_prepare_write_valid = FALSE;
|
||||
BOOLEAN is_need_dequeue_sr_cmd = FALSE;
|
||||
tGATT_PREPARE_WRITE_RECORD *prepare_record = NULL;
|
||||
tGATT_PREPARE_WRITE_QUEUE_DATA * queue_data = NULL;
|
||||
UNUSED(len);
|
||||
|
||||
#if GATT_CONFORMANCE_TESTING == TRUE
|
||||
@@ -319,11 +359,60 @@ void gatt_process_exec_write_req (tGATT_TCB *p_tcb, UINT8 op_code, UINT16 len, U
|
||||
/* mask the flag */
|
||||
flag &= GATT_PREP_WRITE_EXEC;
|
||||
|
||||
prepare_record = &(p_tcb->prepare_write_record);
|
||||
queue_num = prepare_record->queue._count;
|
||||
|
||||
|
||||
/* no prep write is queued */
|
||||
//if received prepare_write packets include stack_rsp and app_rsp,
|
||||
//stack respond to execute_write only when stack_rsp handle has invalid_offset
|
||||
//or invalid_length error;
|
||||
//app need to respond to execute_write if it has received app_rsp handle packets
|
||||
if (((prepare_record->error_code_app == GATT_SUCCESS) &&
|
||||
(prepare_record->total_num == queue_num))
|
||||
|| (flag == GATT_PREP_WRITE_CANCEL)){
|
||||
tGATT_EXEC_WRITE_RSP gatt_exec_write_rsp;
|
||||
gatt_exec_write_rsp.op_code = GATT_RSP_EXEC_WRITE;
|
||||
gatt_send_packet(p_tcb, (UINT8 *)(&gatt_exec_write_rsp), sizeof(gatt_exec_write_rsp));
|
||||
gatt_dequeue_sr_cmd(p_tcb);
|
||||
if (flag != GATT_PREP_WRITE_CANCEL){
|
||||
is_prepare_write_valid = TRUE;
|
||||
}
|
||||
GATT_TRACE_DEBUG("Send execute_write_rsp\n");
|
||||
} else if ((prepare_record->error_code_app == GATT_SUCCESS) &&
|
||||
(prepare_record->total_num > queue_num)){
|
||||
//No error for stack_rsp's handles and there exist some app_rsp's handles,
|
||||
//so exec_write_rsp depends to app's response; but stack_rsp's data is valid
|
||||
//TODO: there exist problem if stack_rsp's data is valid but app_rsp's data is not valid.
|
||||
is_prepare_write_valid = TRUE;
|
||||
} else if(prepare_record->total_num < queue_num) {
|
||||
GATT_TRACE_ERROR("Error in %s, line=%d, prepare write total number (%d) \
|
||||
should not smaller than prepare queue number (%d)\n", \
|
||||
__func__, __LINE__,prepare_record->total_num, queue_num);
|
||||
} else if (prepare_record->error_code_app != GATT_SUCCESS){
|
||||
GATT_TRACE_DEBUG("Send error code for execute_write, code=0x%x\n", prepare_record->error_code_app);
|
||||
is_need_dequeue_sr_cmd = (prepare_record->total_num == queue_num) ? TRUE : FALSE;
|
||||
gatt_send_error_rsp(p_tcb, prepare_record->error_code_app, GATT_REQ_EXEC_WRITE, 0, is_need_dequeue_sr_cmd);
|
||||
}
|
||||
|
||||
//dequeue prepare write data
|
||||
while(GKI_getfirst(&(prepare_record->queue))) {
|
||||
queue_data = GKI_dequeue(&(prepare_record->queue));
|
||||
if (is_prepare_write_valid){
|
||||
if((queue_data->p_attr->p_value != NULL) && (queue_data->p_attr->p_value->attr_val.attr_val != NULL)){
|
||||
memcpy(queue_data->p_attr->p_value->attr_val.attr_val+queue_data->offset, queue_data->value, queue_data->len);
|
||||
}
|
||||
}
|
||||
GKI_freebuf(queue_data);
|
||||
}
|
||||
|
||||
/* according to ble spec, even if there is no prep write queued,
|
||||
* need to respond execute_write_response
|
||||
* Note: exec_write_rsp callback should be called after all data has been written*/
|
||||
if (!gatt_sr_is_prep_cnt_zero(p_tcb)) {
|
||||
trans_id = gatt_sr_enqueue_cmd(p_tcb, op_code, 0);
|
||||
gatt_sr_copy_prep_cnt_to_cback_cnt(p_tcb);
|
||||
if (prepare_record->total_num > queue_num){
|
||||
trans_id = gatt_sr_enqueue_cmd(p_tcb, op_code, 0);
|
||||
gatt_sr_copy_prep_cnt_to_cback_cnt(p_tcb);
|
||||
}
|
||||
|
||||
for (i = 0; i < GATT_MAX_APPS; i++) {
|
||||
if (p_tcb->prep_cnt[i]) {
|
||||
@@ -336,10 +425,10 @@ void gatt_process_exec_write_req (tGATT_TCB *p_tcb, UINT8 op_code, UINT16 len, U
|
||||
p_tcb->prep_cnt[i] = 0;
|
||||
}
|
||||
}
|
||||
} else { /* nothing needs to be executed , send response now */
|
||||
GATT_TRACE_ERROR("gatt_process_exec_write_req: no prepare write pending");
|
||||
gatt_send_error_rsp(p_tcb, GATT_ERROR, GATT_REQ_EXEC_WRITE, 0, FALSE);
|
||||
}
|
||||
|
||||
prepare_record->total_num = 0;
|
||||
prepare_record->error_code_app = GATT_SUCCESS;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
@@ -987,54 +1076,29 @@ void gatts_process_read_by_type_req(tGATT_TCB *p_tcb, UINT8 op_code, UINT16 len,
|
||||
void gatts_process_write_req (tGATT_TCB *p_tcb, UINT8 i_rcb, UINT16 handle,
|
||||
UINT8 op_code, UINT16 len, UINT8 *p_data)
|
||||
{
|
||||
UINT16 buf_len = (UINT16)(sizeof(BT_HDR) + p_tcb->payload_size + L2CAP_MIN_OFFSET);
|
||||
tGATTS_DATA sr_data;
|
||||
UINT32 trans_id;
|
||||
tGATT_STATUS status;
|
||||
UINT8 sec_flag, key_size, *p = p_data, *p_m;
|
||||
UINT8 sec_flag, key_size, *p = p_data;
|
||||
tGATT_SR_REG *p_sreg;
|
||||
UINT16 conn_id, offset = 0;
|
||||
BT_HDR *p_msg = NULL;
|
||||
|
||||
memset(&sr_data, 0, sizeof(tGATTS_DATA));
|
||||
sr_data.write_req.need_rsp = FALSE;
|
||||
|
||||
if ((p_msg = (BT_HDR *)GKI_getbuf(buf_len)) == NULL) {
|
||||
GATT_TRACE_ERROR("gatts_process_write_req failed. no resources.\n");
|
||||
}
|
||||
|
||||
memset(p_msg, 0, buf_len);
|
||||
p_m = (UINT8 *)(p_msg + 1) + L2CAP_MIN_OFFSET;
|
||||
*p_m ++ = op_code + 1;
|
||||
p_msg->len = 1;
|
||||
buf_len = p_tcb->payload_size - 1;
|
||||
|
||||
switch (op_code) {
|
||||
case GATT_REQ_PREPARE_WRITE:
|
||||
sr_data.write_req.is_prep = TRUE;
|
||||
STREAM_TO_UINT16(sr_data.write_req.offset, p);
|
||||
UINT16_TO_STREAM(p_m, sr_data.write_req.is_prep);
|
||||
offset = sr_data.write_req.offset;
|
||||
len -= 2;
|
||||
/* fall through */
|
||||
case GATT_SIGN_CMD_WRITE:
|
||||
if (op_code == GATT_SIGN_CMD_WRITE) {
|
||||
GATT_TRACE_DEBUG("Write CMD with data sigining" );
|
||||
GATT_TRACE_DEBUG("Write CMD with data signing" );
|
||||
len -= GATT_AUTH_SIGN_LEN;
|
||||
}
|
||||
/* fall through */
|
||||
case GATT_CMD_WRITE:
|
||||
case GATT_REQ_WRITE:
|
||||
if (op_code == GATT_REQ_WRITE || op_code == GATT_REQ_PREPARE_WRITE) {
|
||||
sr_data.write_req.need_rsp = TRUE;
|
||||
if(op_code == GATT_REQ_PREPARE_WRITE){
|
||||
memcpy(p_m, p, len);
|
||||
p_msg->len += len;
|
||||
}
|
||||
}
|
||||
sr_data.write_req.handle = handle;
|
||||
sr_data.write_req.len = len;
|
||||
if (len != 0 && p != NULL) {
|
||||
memcpy (sr_data.write_req.value, p, len);
|
||||
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -1059,40 +1123,182 @@ void gatts_process_write_req (tGATT_TCB *p_tcb, UINT8 i_rcb, UINT16 handle,
|
||||
conn_id = GATT_CREATE_CONN_ID(p_tcb->tcb_idx, p_sreg->gatt_if);
|
||||
status = gatts_write_attr_value_by_handle(gatt_cb.sr_reg[i_rcb].p_db,
|
||||
handle, offset, p, len);
|
||||
if((sr_data.write_req.need_rsp == TRUE) && (status == GATT_APP_RSP)){
|
||||
if((op_code == GATT_REQ_WRITE) && (status == GATT_APP_RSP)){
|
||||
sr_data.write_req.need_rsp = TRUE;
|
||||
status = GATT_PENDING;
|
||||
}
|
||||
|
||||
else{
|
||||
sr_data.write_req.need_rsp = FALSE;
|
||||
}
|
||||
|
||||
gatt_sr_send_req_callback(conn_id,
|
||||
trans_id,
|
||||
GATTS_REQ_TYPE_WRITE,
|
||||
&sr_data);
|
||||
|
||||
if(status == GATT_SUCCESS){
|
||||
attp_send_sr_msg(p_tcb, p_msg);
|
||||
gatt_dequeue_sr_cmd(p_tcb);
|
||||
}
|
||||
|
||||
} else {
|
||||
GATT_TRACE_ERROR("max pending command, send error\n");
|
||||
GATT_TRACE_ERROR("Error in %s, line=%d, max pending command, send error\n", __func__, __LINE__);
|
||||
status = GATT_BUSY; /* max pending command, application error */
|
||||
}
|
||||
}
|
||||
|
||||
/* in theroy BUSY is not possible(should already been checked), protected check */
|
||||
if (status != GATT_PENDING && status != GATT_BUSY && status != GATT_SUCCESS &&
|
||||
(op_code == GATT_REQ_PREPARE_WRITE || op_code == GATT_REQ_WRITE)) {
|
||||
gatt_send_error_rsp (p_tcb, status, op_code, handle, FALSE);
|
||||
gatt_dequeue_sr_cmd(p_tcb);
|
||||
/* response should be sent only for write_request */
|
||||
if ((op_code == GATT_REQ_WRITE) && (sr_data.write_req.need_rsp == FALSE)){
|
||||
if (status == GATT_SUCCESS){
|
||||
tGATT_WRITE_REQ_RSP gatt_write_req_rsp;
|
||||
gatt_write_req_rsp.op_code = GATT_RSP_WRITE;
|
||||
gatt_send_packet(p_tcb, (UINT8 *)(&gatt_write_req_rsp), sizeof(gatt_write_req_rsp));
|
||||
gatt_dequeue_sr_cmd(p_tcb);
|
||||
} else if (status != GATT_PENDING){
|
||||
/* note: in case of GATT_BUSY, will respond this application error to remote device */
|
||||
gatt_send_error_rsp (p_tcb, status, op_code, handle, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function gatts_attr_process_preapre_write
|
||||
**
|
||||
** Description This function is called to process the prepare write request
|
||||
** from client.
|
||||
**
|
||||
** Returns void
|
||||
**
|
||||
*******************************************************************************/
|
||||
void gatt_attr_process_prepare_write (tGATT_TCB *p_tcb, UINT8 i_rcb, UINT16 handle,
|
||||
UINT8 op_code, UINT16 len, UINT8 *p_data)
|
||||
{
|
||||
tGATT_STATUS status;
|
||||
tGATT_PREPARE_WRITE_QUEUE_DATA * queue_data = NULL;
|
||||
tGATT_ATTR16 *p_attr;
|
||||
tGATT_ATTR16 *p_attr_temp;
|
||||
tGATTS_DATA sr_data;
|
||||
UINT32 trans_id = 0;
|
||||
UINT8 sec_flag, key_size, *p = p_data;
|
||||
tGATT_SR_REG *p_sreg;
|
||||
UINT16 conn_id, offset = 0;
|
||||
tGATT_SVC_DB *p_db;
|
||||
BOOLEAN is_need_prepare_write_rsp = FALSE;
|
||||
BOOLEAN is_need_queue_data = FALSE;
|
||||
tGATT_PREPARE_WRITE_RECORD *prepare_record = NULL;
|
||||
memset(&sr_data, 0, sizeof(tGATTS_DATA));
|
||||
|
||||
//get offset from p_data
|
||||
STREAM_TO_UINT16(offset, p);
|
||||
len -= 2;
|
||||
p_sreg = &gatt_cb.sr_reg[i_rcb];
|
||||
conn_id = GATT_CREATE_CONN_ID(p_tcb->tcb_idx, p_sreg->gatt_if);
|
||||
//prepare_record = &(prepare_write_record);
|
||||
prepare_record = &(p_tcb->prepare_write_record);
|
||||
|
||||
gatt_sr_get_sec_info(p_tcb->peer_bda,
|
||||
p_tcb->transport,
|
||||
&sec_flag,
|
||||
&key_size);
|
||||
|
||||
status = gatts_write_attr_perm_check (gatt_cb.sr_reg[i_rcb].p_db,
|
||||
op_code,
|
||||
handle,
|
||||
sr_data.write_req.offset,
|
||||
p,
|
||||
len,
|
||||
sec_flag,
|
||||
key_size);
|
||||
|
||||
if (status == GATT_SUCCESS){
|
||||
if ((trans_id = gatt_sr_enqueue_cmd(p_tcb, op_code, handle)) != 0) {
|
||||
p_db = gatt_cb.sr_reg[i_rcb].p_db;
|
||||
if (p_db && p_db->p_attr_list) {
|
||||
p_attr = (tGATT_ATTR16 *)p_db->p_attr_list;
|
||||
while (p_attr && handle >= p_attr->handle) {
|
||||
if (p_attr->handle == handle ) {
|
||||
p_attr_temp = p_attr;
|
||||
if (p_attr->control.auto_rsp == GATT_RSP_BY_APP) {
|
||||
status = GATT_APP_RSP;
|
||||
} else if (p_attr->p_value != NULL &&
|
||||
offset > p_attr->p_value->attr_val.attr_max_len) {
|
||||
status = GATT_INVALID_OFFSET;
|
||||
is_need_prepare_write_rsp = TRUE;
|
||||
is_need_queue_data = TRUE;
|
||||
} else if (p_attr->p_value != NULL &&
|
||||
((offset + len) > p_attr->p_value->attr_val.attr_max_len)){
|
||||
status = GATT_INVALID_ATTR_LEN;
|
||||
is_need_prepare_write_rsp = TRUE;
|
||||
is_need_queue_data = TRUE;
|
||||
} else if (p_attr->p_value == NULL) {
|
||||
LOG_ERROR("Error in %s, attribute of handle 0x%x not allocate value buffer\n",
|
||||
__func__, handle);
|
||||
status = GATT_ESP_ERROR;
|
||||
} else {
|
||||
//valid prepare write request, need to send response and queue the data
|
||||
//status: GATT_SUCCESS
|
||||
is_need_prepare_write_rsp = TRUE;
|
||||
is_need_queue_data = TRUE;
|
||||
}
|
||||
}
|
||||
p_attr = (tGATT_ATTR16 *)p_attr->p_next;
|
||||
}
|
||||
}
|
||||
} else{
|
||||
status = GATT_ESP_ERROR;
|
||||
GATT_TRACE_ERROR("Error in %s, Line %d: GATT BUSY\n", __func__, __LINE__);
|
||||
}
|
||||
}
|
||||
|
||||
if (is_need_queue_data){
|
||||
queue_data = (tGATT_PREPARE_WRITE_QUEUE_DATA *)GKI_getbuf(len + sizeof(tGATT_PREPARE_WRITE_QUEUE_DATA));
|
||||
if (queue_data == NULL){
|
||||
status = GATT_PREPARE_Q_FULL;
|
||||
} else {
|
||||
queue_data->p_attr = p_attr_temp;
|
||||
queue_data->len = len;
|
||||
queue_data->handle = handle;
|
||||
queue_data->offset = offset;
|
||||
memcpy(queue_data->value, p, len);
|
||||
GKI_enqueue(&(prepare_record->queue), queue_data);
|
||||
}
|
||||
}
|
||||
|
||||
if (is_need_prepare_write_rsp){
|
||||
//send prepare write response
|
||||
if (queue_data != NULL){
|
||||
queue_data->op_code = op_code + 1;
|
||||
//5: op_code 1 + handle 2 + offset 2
|
||||
tGATT_STATUS rsp_send_status = gatt_send_packet(p_tcb, &(queue_data->op_code), queue_data->len + 5);
|
||||
gatt_sr_update_prep_cnt(p_tcb, p_sreg->gatt_if, TRUE, FALSE);
|
||||
gatt_dequeue_sr_cmd(p_tcb);
|
||||
|
||||
if (rsp_send_status != GATT_SUCCESS){
|
||||
LOG_ERROR("Error in %s, line=%d, fail to send prepare_write_rsp, status=0x%x\n",
|
||||
__func__, __LINE__, rsp_send_status);
|
||||
}
|
||||
} else{
|
||||
LOG_ERROR("Error in %s, line=%d, queue_data should not be NULL here, fail to send prepare_write_rsp\n",
|
||||
__func__, __LINE__);
|
||||
}
|
||||
}
|
||||
|
||||
if ((status == GATT_APP_RSP) || (is_need_prepare_write_rsp)){
|
||||
prepare_record->total_num++;
|
||||
memset(&sr_data, 0, sizeof(sr_data));
|
||||
sr_data.write_req.is_prep = TRUE;
|
||||
sr_data.write_req.handle = handle;
|
||||
sr_data.write_req.offset = offset;
|
||||
sr_data.write_req.len = len;
|
||||
sr_data.write_req.need_rsp = (status == GATT_APP_RSP) ? TRUE : FALSE;
|
||||
memcpy(sr_data.write_req.value, p, len);
|
||||
gatt_sr_send_req_callback(conn_id, trans_id, GATTS_REQ_TYPE_WRITE, &sr_data);
|
||||
} else{
|
||||
gatt_send_error_rsp(p_tcb, status, GATT_REQ_PREPARE_WRITE, handle, TRUE);
|
||||
}
|
||||
|
||||
if ((prepare_record->error_code_app == GATT_SUCCESS)
|
||||
&& ((status == GATT_INVALID_OFFSET) || (status == GATT_INVALID_ATTR_LEN))){
|
||||
prepare_record->error_code_app = status;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function gatts_process_read_req
|
||||
@@ -1162,6 +1368,10 @@ static void gatts_process_read_req(tGATT_TCB *p_tcb, tGATT_SR_REG *p_rcb, UINT8
|
||||
} else if (reason == GATT_SUCCESS || reason == GATT_STACK_RSP) {
|
||||
attp_send_sr_msg(p_tcb, p_msg);
|
||||
gatt_dequeue_sr_cmd(p_tcb);
|
||||
} else {
|
||||
if (p_msg) {
|
||||
GKI_freebuf(p_msg);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1220,9 +1430,11 @@ void gatts_process_attribute_req (tGATT_TCB *p_tcb, UINT8 op_code,
|
||||
case GATT_REQ_WRITE: /* write char/char descriptor value */
|
||||
case GATT_CMD_WRITE:
|
||||
case GATT_SIGN_CMD_WRITE:
|
||||
case GATT_REQ_PREPARE_WRITE:
|
||||
gatts_process_write_req(p_tcb, i, handle, op_code, len, p);
|
||||
break;
|
||||
|
||||
case GATT_REQ_PREPARE_WRITE:
|
||||
gatt_attr_process_prepare_write (p_tcb, i, handle, op_code, len, p);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -116,6 +116,26 @@ void gatt_free_pending_enc_queue(tGATT_TCB *p_tcb)
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function gatt_free_pending_prepare_write_queue
|
||||
**
|
||||
** Description Free all buffers in pending prepare write packets queue
|
||||
**
|
||||
** Returns None
|
||||
**
|
||||
*******************************************************************************/
|
||||
void gatt_free_pending_prepare_write_queue(tGATT_TCB *p_tcb)
|
||||
{
|
||||
GATT_TRACE_DEBUG("gatt_free_pending_prepare_write_queue");
|
||||
/* release all queued prepare write packets */
|
||||
while (!GKI_queue_is_empty(&(p_tcb->prepare_write_record.queue))) {
|
||||
GKI_freebuf (GKI_dequeue (&(p_tcb->prepare_write_record.queue)));
|
||||
}
|
||||
p_tcb->prepare_write_record.total_num = 0;
|
||||
p_tcb->prepare_write_record.error_code_app = GATT_SUCCESS;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function gatt_delete_dev_from_srv_chg_clt_list
|
||||
@@ -377,11 +397,38 @@ tGATT_HDL_LIST_ELEM *gatt_find_hdl_buffer_by_app_id (tBT_UUID *p_app_uuid128,
|
||||
}
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function gatt_free_attr_value_buffer
|
||||
**
|
||||
** Description free characteristic attribute value buffer in a service
|
||||
**
|
||||
** Returns None
|
||||
**
|
||||
*******************************************************************************/
|
||||
void gatt_free_attr_value_buffer(tGATT_HDL_LIST_ELEM *p)
|
||||
{
|
||||
if (p){
|
||||
tGATT_SVC_DB *p_db = &(p->svc_db);
|
||||
tGATT_ATTR16 *p_attr = p_db->p_attr_list;
|
||||
tGATT_ATTR_VALUE *p_value = NULL;
|
||||
|
||||
while(p_attr){
|
||||
if (p_attr->mask & GATT_ATTR_VALUE_ALLOCATED){
|
||||
p_value = p_attr->p_value;
|
||||
if ((p_value != NULL) && (p_value->attr_val.attr_val != NULL)){
|
||||
GKI_freebuf(p_value->attr_val.attr_val);
|
||||
}
|
||||
}
|
||||
p_attr = p_attr->p_next;
|
||||
}
|
||||
}
|
||||
}
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function gatt_free_hdl_buffer
|
||||
**
|
||||
** Description free a handle buffer
|
||||
** Description free a handle buffer
|
||||
**
|
||||
** Returns None
|
||||
** Returns None
|
||||
**
|
||||
*******************************************************************************/
|
||||
void gatt_free_hdl_buffer(tGATT_HDL_LIST_ELEM *p)
|
||||
@@ -2108,6 +2155,7 @@ void gatt_cleanup_upon_disc(BD_ADDR bda, UINT16 reason, tBT_TRANSPORT transport)
|
||||
btu_stop_timer (&p_tcb->conf_timer_ent);
|
||||
gatt_free_pending_ind(p_tcb);
|
||||
gatt_free_pending_enc_queue(p_tcb);
|
||||
gatt_free_pending_prepare_write_queue(p_tcb);
|
||||
|
||||
for (i = 0; i < GATT_MAX_APPS; i ++) {
|
||||
p_reg = &gatt_cb.cl_rcb[i];
|
||||
|
||||
@@ -133,6 +133,16 @@ typedef struct {
|
||||
UINT8 reason;
|
||||
} tGATT_ERROR;
|
||||
|
||||
/* Execute write response structure */
|
||||
typedef struct {
|
||||
UINT8 op_code;
|
||||
}__attribute__((packed)) tGATT_EXEC_WRITE_RSP;
|
||||
|
||||
/* Write request response structure */
|
||||
typedef struct {
|
||||
UINT8 op_code;
|
||||
}__attribute__((packed)) tGATT_WRITE_REQ_RSP;
|
||||
|
||||
/* server response message to ATT protocol
|
||||
*/
|
||||
typedef union {
|
||||
@@ -175,6 +185,7 @@ typedef struct {
|
||||
tGATT_ATTR_UUID_TYPE uuid_type;
|
||||
tGATT_PERM permission;
|
||||
tGATTS_ATTR_CONTROL control;
|
||||
tGATT_ATTR_MASK mask;
|
||||
UINT16 handle;
|
||||
UINT16 uuid;
|
||||
} tGATT_ATTR16;
|
||||
@@ -187,6 +198,7 @@ typedef struct {
|
||||
tGATT_ATTR_UUID_TYPE uuid_type;
|
||||
tGATT_PERM permission;
|
||||
tGATTS_ATTR_CONTROL control;
|
||||
tGATT_ATTR_MASK mask;
|
||||
UINT16 handle;
|
||||
UINT32 uuid;
|
||||
} tGATT_ATTR32;
|
||||
@@ -200,6 +212,7 @@ typedef struct {
|
||||
tGATT_ATTR_UUID_TYPE uuid_type;
|
||||
tGATT_PERM permission;
|
||||
tGATTS_ATTR_CONTROL control;
|
||||
tGATT_ATTR_MASK mask;
|
||||
UINT16 handle;
|
||||
UINT8 uuid[LEN_UUID_128];
|
||||
} tGATT_ATTR128;
|
||||
@@ -329,6 +342,32 @@ typedef struct {
|
||||
UINT16 count;
|
||||
} tGATT_SRV_LIST_INFO;
|
||||
|
||||
/* prepare write queue data */
|
||||
typedef struct{
|
||||
//len: length of value
|
||||
tGATT_ATTR16 *p_attr;
|
||||
UINT16 len;
|
||||
UINT8 op_code;
|
||||
UINT16 handle;
|
||||
UINT16 offset;
|
||||
UINT8 value[2];
|
||||
}__attribute__((packed)) tGATT_PREPARE_WRITE_QUEUE_DATA;
|
||||
|
||||
/* structure to store prepare write packts information */
|
||||
typedef struct{
|
||||
//only store prepare write packets which need
|
||||
//to be responded by stack (not by application)
|
||||
BUFFER_Q queue;
|
||||
|
||||
//store the total number of prepare write packets
|
||||
//including that should be responded by stack or by application
|
||||
UINT16 total_num;
|
||||
|
||||
//store application error code for prepare write,
|
||||
//invalid offset && invalid length
|
||||
UINT8 error_code_app;
|
||||
}tGATT_PREPARE_WRITE_RECORD;
|
||||
|
||||
typedef struct {
|
||||
BUFFER_Q pending_enc_clcb; /* pending encryption channel q */
|
||||
tGATT_SEC_ACTION sec_act;
|
||||
@@ -362,6 +401,7 @@ typedef struct {
|
||||
|
||||
BOOLEAN in_use;
|
||||
UINT8 tcb_idx;
|
||||
tGATT_PREPARE_WRITE_RECORD prepare_write_record; /* prepare write packets record */
|
||||
} tGATT_TCB;
|
||||
|
||||
|
||||
@@ -584,6 +624,7 @@ extern tGATT_HDL_LIST_ELEM *gatt_find_hdl_buffer_by_handle(UINT16 handle);
|
||||
extern tGATT_HDL_LIST_ELEM *gatt_find_hdl_buffer_by_attr_handle(UINT16 attr_handle);
|
||||
extern tGATT_HDL_LIST_ELEM *gatt_alloc_hdl_buffer(void);
|
||||
extern void gatt_free_hdl_buffer(tGATT_HDL_LIST_ELEM *p);
|
||||
extern void gatt_free_attr_value_buffer(tGATT_HDL_LIST_ELEM *p);
|
||||
extern BOOLEAN gatt_is_last_attribute(tGATT_SRV_LIST_INFO *p_list, tGATT_SRV_LIST_ELEM *p_start, tBT_UUID value);
|
||||
extern void gatt_update_last_pri_srv_info(tGATT_SRV_LIST_INFO *p_list);
|
||||
extern BOOLEAN gatt_add_a_srv_to_list(tGATT_SRV_LIST_INFO *p_list, tGATT_SRV_LIST_ELEM *p_new);
|
||||
|
||||
@@ -65,6 +65,8 @@
|
||||
#define GATT_CONGESTED 0x8f
|
||||
#define GATT_STACK_RSP 0x90
|
||||
#define GATT_APP_RSP 0x91
|
||||
//Error caused by customer application or stack bug
|
||||
#define GATT_ESP_ERROR 0X9f
|
||||
|
||||
/* 0xE0 ~ 0xFC reserved for future use */
|
||||
#define GATT_CCC_CFG_ERR 0xFD /* Client Characteristic Configuration Descriptor Improperly Configured */
|
||||
@@ -324,6 +326,10 @@ typedef struct{
|
||||
uint8_t auto_rsp;
|
||||
}tGATTS_ATTR_CONTROL;
|
||||
|
||||
/* Mask for gatt server attribute */
|
||||
#define GATT_ATTR_VALUE_ALLOCATED 0x01
|
||||
typedef UINT8 tGATT_ATTR_MASK;
|
||||
|
||||
/* Union of the event data which is used in the server respond API to carry the server response information
|
||||
*/
|
||||
typedef union {
|
||||
|
||||
@@ -27,13 +27,24 @@
|
||||
#include "esp_task.h"
|
||||
#include "esp_intr.h"
|
||||
#include "esp_attr.h"
|
||||
#include "esp_phy_init.h"
|
||||
#include "bt.h"
|
||||
|
||||
#if CONFIG_BT_ENABLED
|
||||
|
||||
/* Bluetooth system and controller config */
|
||||
#define BTDM_CFG_BT_EM_RELEASE (1<<0)
|
||||
#define BTDM_CFG_BT_DATA_RELEASE (1<<1)
|
||||
/* Other reserved for future */
|
||||
|
||||
/* not for user call, so don't put to include file */
|
||||
extern void btdm_osi_funcs_register(void *osi_funcs);
|
||||
extern void btdm_controller_init(void);
|
||||
extern void btdm_controller_init(uint32_t config_mask);
|
||||
extern void btdm_controller_schedule(void);
|
||||
extern void btdm_controller_deinit(void);
|
||||
extern int btdm_controller_enable(esp_bt_mode_t mode);
|
||||
extern int btdm_controller_disable(esp_bt_mode_t mode);
|
||||
extern void btdm_rf_bb_init(void);
|
||||
|
||||
/* VHCI function interface */
|
||||
typedef struct vhci_host_callback {
|
||||
@@ -67,9 +78,17 @@ struct osi_funcs_t {
|
||||
void *(*_mutex_create)(void);
|
||||
int32_t (*_mutex_lock)(void *mutex);
|
||||
int32_t (*_mutex_unlock)(void *mutex);
|
||||
esp_err_t (* _read_efuse_mac)(uint8_t mac[6]);
|
||||
int32_t (* _read_efuse_mac)(uint8_t mac[6]);
|
||||
void (* _srand)(unsigned int seed);
|
||||
int (* _rand)(void);
|
||||
};
|
||||
|
||||
/* Static variable declare */
|
||||
static bool btdm_bb_init_flag = false;
|
||||
static esp_bt_controller_status_t btdm_controller_status = ESP_BT_CONTROLLER_STATUS_IDLE;
|
||||
|
||||
static xTaskHandle btControllerTaskHandle;
|
||||
|
||||
static portMUX_TYPE global_int_mux = portMUX_INITIALIZER_UNLOCKED;
|
||||
|
||||
static void IRAM_ATTR interrupt_disable(void)
|
||||
@@ -112,6 +131,21 @@ static int32_t IRAM_ATTR mutex_unlock_wrapper(void *mutex)
|
||||
return (int32_t)xSemaphoreGive(mutex);
|
||||
}
|
||||
|
||||
static int32_t IRAM_ATTR read_mac_wrapper(uint8_t mac[6])
|
||||
{
|
||||
return esp_read_mac(mac, ESP_MAC_BT);
|
||||
}
|
||||
|
||||
static void IRAM_ATTR srand_wrapper(unsigned int seed)
|
||||
{
|
||||
/* empty function */
|
||||
}
|
||||
|
||||
static int IRAM_ATTR rand_wrapper(void)
|
||||
{
|
||||
return (int)esp_random();
|
||||
}
|
||||
|
||||
static struct osi_funcs_t osi_funcs = {
|
||||
._set_isr = xt_set_interrupt_handler,
|
||||
._ints_on = xt_ints_on,
|
||||
@@ -124,7 +158,9 @@ static struct osi_funcs_t osi_funcs = {
|
||||
._mutex_create = mutex_create_wrapper,
|
||||
._mutex_lock = mutex_lock_wrapper,
|
||||
._mutex_unlock = mutex_unlock_wrapper,
|
||||
._read_efuse_mac = esp_efuse_read_mac,
|
||||
._read_efuse_mac = read_mac_wrapper,
|
||||
._srand = srand_wrapper,
|
||||
._rand = rand_wrapper,
|
||||
};
|
||||
|
||||
bool esp_vhci_host_check_send_available(void)
|
||||
@@ -142,17 +178,104 @@ void esp_vhci_host_register_callback(const esp_vhci_host_callback_t *callback)
|
||||
API_vhci_host_register_callback((const vhci_host_callback_t *)callback);
|
||||
}
|
||||
|
||||
static uint32_t btdm_config_mask_load(void)
|
||||
{
|
||||
uint32_t mask = 0x0;
|
||||
|
||||
#ifdef CONFIG_BT_DRAM_RELEASE
|
||||
mask |= (BTDM_CFG_BT_EM_RELEASE | BTDM_CFG_BT_DATA_RELEASE);
|
||||
#endif
|
||||
return mask;
|
||||
}
|
||||
|
||||
static void bt_controller_task(void *pvParam)
|
||||
{
|
||||
uint32_t btdm_cfg_mask = 0;
|
||||
|
||||
btdm_osi_funcs_register(&osi_funcs);
|
||||
btdm_controller_init();
|
||||
|
||||
btdm_cfg_mask = btdm_config_mask_load();
|
||||
btdm_controller_init(btdm_cfg_mask);
|
||||
|
||||
btdm_controller_status = ESP_BT_CONTROLLER_STATUS_INITED;
|
||||
|
||||
/* Loop */
|
||||
btdm_controller_schedule();
|
||||
}
|
||||
|
||||
void esp_bt_controller_init()
|
||||
{
|
||||
if (btdm_controller_status != ESP_BT_CONTROLLER_STATUS_IDLE) {
|
||||
return;
|
||||
}
|
||||
|
||||
xTaskCreatePinnedToCore(bt_controller_task, "btController",
|
||||
ESP_TASK_BT_CONTROLLER_STACK, NULL,
|
||||
ESP_TASK_BT_CONTROLLER_PRIO, NULL, 0);
|
||||
ESP_TASK_BT_CONTROLLER_PRIO, &btControllerTaskHandle, 0);
|
||||
}
|
||||
|
||||
void esp_bt_controller_deinit(void)
|
||||
{
|
||||
vTaskDelete(btControllerTaskHandle);
|
||||
btdm_controller_status = ESP_BT_CONTROLLER_STATUS_IDLE;
|
||||
}
|
||||
|
||||
esp_err_t esp_bt_controller_enable(esp_bt_mode_t mode)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (btdm_controller_status != ESP_BT_CONTROLLER_STATUS_INITED) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
if (mode != ESP_BT_MODE_BTDM) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
esp_phy_load_cal_and_init();
|
||||
|
||||
if (btdm_bb_init_flag == false) {
|
||||
btdm_bb_init_flag = true;
|
||||
btdm_rf_bb_init(); /* only initialise once */
|
||||
}
|
||||
|
||||
ret = btdm_controller_enable(mode);
|
||||
if (ret) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
btdm_controller_status = ESP_BT_CONTROLLER_STATUS_ENABLED;
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_bt_controller_disable(esp_bt_mode_t mode)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (btdm_controller_status != ESP_BT_CONTROLLER_STATUS_ENABLED) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
if (mode != ESP_BT_MODE_BTDM) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
ret = btdm_controller_disable(mode);
|
||||
if (ret) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
esp_phy_rf_deinit();
|
||||
|
||||
btdm_controller_status = ESP_BT_CONTROLLER_STATUS_INITED;
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_bt_controller_status_t esp_bt_controller_get_status(void)
|
||||
{
|
||||
return btdm_controller_status;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -23,14 +23,63 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Bluetooth mode for controller enable/disable
|
||||
*/
|
||||
typedef enum {
|
||||
ESP_BT_MODE_ILDE = 0x00, /*!< Bluetooth is not run */
|
||||
ESP_BT_MODE_BLE = 0x01, /*!< Run BLE mode */
|
||||
ESP_BT_MODE_CLASSIC_BT = 0x02, /*!< Run Classic BT mode */
|
||||
ESP_BT_MODE_BTDM = 0x03, /*!< Run dual mode */
|
||||
} esp_bt_mode_t;
|
||||
|
||||
/**
|
||||
* @brief Initialize BT controller
|
||||
* @brief Bluetooth controller enable/disable/initialised/de-initialised status
|
||||
*/
|
||||
typedef enum {
|
||||
ESP_BT_CONTROLLER_STATUS_IDLE = 0,
|
||||
ESP_BT_CONTROLLER_STATUS_INITED,
|
||||
ESP_BT_CONTROLLER_STATUS_ENABLED,
|
||||
ESP_BT_CONTROLLER_STATUS_NUM,
|
||||
} esp_bt_controller_status_t;
|
||||
|
||||
/**
|
||||
* @brief Initialize BT controller to allocate task and other resource.
|
||||
*
|
||||
* This function should be called only once, before any other BT functions are called.
|
||||
*/
|
||||
void esp_bt_controller_init(void);
|
||||
|
||||
/**
|
||||
* @brief De-initialize BT controller to free resource and delete task.
|
||||
*
|
||||
* This function should be called only once, after any other BT functions are called.
|
||||
* This function is not whole completed, esp_bt_controller_init cannot called after this function.
|
||||
*/
|
||||
void esp_bt_controller_deinit(void);
|
||||
|
||||
/**
|
||||
* @brief Enable BT controller
|
||||
* @param mode : the mode(BLE/BT/BTDM) to enable.
|
||||
* Now only support BTDM.
|
||||
* @return ESP_OK - success, other - failed
|
||||
*/
|
||||
esp_err_t esp_bt_controller_enable(esp_bt_mode_t mode);
|
||||
|
||||
/**
|
||||
* @brief Disable BT controller
|
||||
* @param mode : the mode(BLE/BT/BTDM) to disable.
|
||||
* Now only support BTDM.
|
||||
* @return ESP_OK - success, other - failed
|
||||
*/
|
||||
esp_err_t esp_bt_controller_disable(esp_bt_mode_t mode);
|
||||
|
||||
/**
|
||||
* @brief Get BT controller is initialised/de-initialised/enabled/disabled
|
||||
* @return status value
|
||||
*/
|
||||
esp_bt_controller_status_t esp_bt_controller_get_status(void);
|
||||
|
||||
/** @brief esp_vhci_host_callback
|
||||
* used for vhci call host function to notify what host need to do
|
||||
*/
|
||||
|
||||
Submodule components/bt/lib updated: 9c1eea6bb0...736797b73b
@@ -49,11 +49,11 @@ typedef enum {
|
||||
} adc1_channel_t;
|
||||
|
||||
/**
|
||||
* @brief Configuration ADC1 capture width.
|
||||
* @brief Configure ADC1 capture width.
|
||||
*
|
||||
* The configuration is in effect for all channels of ADC1
|
||||
* The configuration is for all channels of ADC1
|
||||
*
|
||||
* @param width_bit ADC1
|
||||
* @param width_bit Bit capture width for ADC1
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK success
|
||||
@@ -62,10 +62,29 @@ typedef enum {
|
||||
esp_err_t adc1_config_width(adc_bits_width_t width_bit);
|
||||
|
||||
/**
|
||||
* @brief Configuration ADC1 capture attenuation of channels.
|
||||
* @brief Configure the ADC1 channel, including setting attenuation.
|
||||
*
|
||||
* @param channel the ADC1 channel
|
||||
* @param atten attenuation
|
||||
* @note This function also configures the input GPIO pin mux to
|
||||
* connect it to the ADC1 channel. It must be called before calling
|
||||
* adc1_get_voltage() for this channel.
|
||||
*
|
||||
* The default ADC full-scale voltage is 1.1V. To read higher voltages (up to the pin maximum voltage,
|
||||
* usually 3.3V) requires setting >0dB signal attenuation for that ADC channel.
|
||||
*
|
||||
* When VDD_A is 3.3V:
|
||||
*
|
||||
* - 0dB attenuaton (ADC_ATTEN_0db) gives full-scale voltage 1.1V
|
||||
* - 2.5dB attenuation (ADC_ATTEN_2_5db) gives full-scale voltage 1.5V
|
||||
* - 6dB attenuation (ADC_ATTEN_6db) gives full-scale voltage 2.2V
|
||||
* - 11dB attenuation (ADC_ATTEN_11db) gives full-scale voltage 3.9V (see note below)
|
||||
*
|
||||
* @note The full-scale voltage is the voltage corresponding to a maximum reading (depending on ADC1 configured
|
||||
* bit width, this value is: 4095 for 12-bits, 2047 for 11-bits, 1023 for 10-bits, 511 for 9 bits.)
|
||||
*
|
||||
* @note At 11dB attenuation the maximum voltage is limited by VDD_A, not the full scale voltage.
|
||||
*
|
||||
* @param channel ADC1 channel to configure
|
||||
* @param atten Attenuation level
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK success
|
||||
@@ -74,46 +93,38 @@ esp_err_t adc1_config_width(adc_bits_width_t width_bit);
|
||||
esp_err_t adc1_config_channel_atten(adc1_channel_t channel, adc_atten_t atten);
|
||||
|
||||
/**
|
||||
* @brief ADC1 get the value of the voltage.
|
||||
* @brief Take an ADC1 reading on a single channel
|
||||
*
|
||||
* @param channel the ADC1 channel
|
||||
* @note Call adc1_config_width() before the first time this
|
||||
* function is called.
|
||||
*
|
||||
* @note For a given channel, adc1_config_channel_atten(channel)
|
||||
* must be called before the first time this function is called.
|
||||
*
|
||||
* @param channel ADC1 channel to read
|
||||
*
|
||||
* @return
|
||||
* - -1 Parameter error
|
||||
* - Other the value of ADC1 channel
|
||||
* - -1: Parameter error
|
||||
* - Other: ADC1 channel reading.
|
||||
*/
|
||||
int adc1_get_voltage(adc1_channel_t channel);
|
||||
|
||||
/**
|
||||
* @brief Hall Sensor output value.
|
||||
* @note
|
||||
* The Hall Sensor uses Channel_0 and Channel_3 of ADC1.
|
||||
* So, firstly: please configure ADC1 module by calling adc1_config_width before calling hall_sensor_read.
|
||||
We recommend that the WIDTH ADC1 be configured as 12Bit, because the values of hall_sensor_read are small and almost the same if WIDTH ADC1 is configured as 9Bit, 10Bit or 11Bit.
|
||||
* secondly: when you use the hall sensor, please do not use Channel_0 and Channel_3 of ADC1 as
|
||||
* ADC channels.
|
||||
* @brief Read Hall Sensor
|
||||
*
|
||||
* @return the value of hall sensor
|
||||
* @note The Hall Sensor uses channels 0 and 3 of ADC1. Do not configure
|
||||
* these channels for use as ADC channels.
|
||||
*
|
||||
* @note The ADC1 module must be enabled by calling
|
||||
* adc1_config_width() before calling hall_sensor_read(). ADC1
|
||||
* should be configured for 12 bit readings, as the hall sensor
|
||||
* readings are low values and do not cover the full range of the
|
||||
* ADC.
|
||||
*
|
||||
* @return The hall sensor reading.
|
||||
*/
|
||||
int hall_sensor_read();
|
||||
|
||||
/**
|
||||
*----------EXAMPLE TO USE ADC1------------ *
|
||||
* @code{c}
|
||||
* adc1_config_width(ADC_WIDTH_12Bit);//config adc1 width
|
||||
* adc1_config_channel_atten(ADC1_CHANNEL_0,ADC_ATTEN_0db);//config channel0 attenuation
|
||||
* int val=adc1_get_voltage(ADC1_CHANNEL_0);//get the val of channel0
|
||||
* @endcode
|
||||
**/
|
||||
|
||||
/**
|
||||
*----------EXAMPLE TO USE HALL SENSOR------------ *
|
||||
* @code{c}
|
||||
* adc1_config_width(ADC_WIDTH_12Bit);//config adc1 width
|
||||
* int val=hall_sensor_read();
|
||||
* @endcode
|
||||
**/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -29,12 +29,15 @@ typedef enum {
|
||||
} dac_channel_t;
|
||||
|
||||
/**
|
||||
* @brief Set Dac output voltage.
|
||||
* @brief Set DAC output voltage.
|
||||
*
|
||||
* Dac width is 8bit ,and the voltage max is vdd
|
||||
* DAC output is 8-bit. Maximum (255) corresponds to VDD.
|
||||
*
|
||||
* @param channel dac channel
|
||||
* @param dac_value dac output value
|
||||
* @note When this function is called, function for the DAC
|
||||
* channel's GPIO pin is reconfigured for RTC DAC function.
|
||||
*
|
||||
* @param channel DAC channel
|
||||
* @param dac_value DAC output value
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK success
|
||||
@@ -42,13 +45,6 @@ typedef enum {
|
||||
*/
|
||||
esp_err_t dac_out_voltage(dac_channel_t channel, uint8_t dac_value);
|
||||
|
||||
/**
|
||||
*----------EXAMPLE TO USE DAC------------ *
|
||||
* @code{c}
|
||||
* dac_out_voltage(DAC_CHANNEL_1,200);//the dac out voltage ≈ 200*vdd/255
|
||||
* @endcode
|
||||
**/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -302,9 +302,9 @@ int gpio_get_level(gpio_num_t gpio_num);
|
||||
esp_err_t gpio_set_direction(gpio_num_t gpio_num, gpio_mode_t mode);
|
||||
|
||||
/**
|
||||
* @brief GPIO set pull
|
||||
* @brief Configure GPIO pull-up/pull-down resistors
|
||||
*
|
||||
* User this Function,configure GPIO pull mode,such as pull-up,pull-down
|
||||
* Only pins that support both input & output have integrated pull-up and pull-down resistors. Input-only GPIOs 34-39 do not.
|
||||
*
|
||||
* @param gpio_num GPIO number. If you want to set pull up or down mode for e.g. GPIO16, gpio_num should be GPIO_NUM_16 (16);
|
||||
* @param pull GPIO pull up/down mode.
|
||||
@@ -317,7 +317,7 @@ esp_err_t gpio_set_direction(gpio_num_t gpio_num, gpio_mode_t mode);
|
||||
esp_err_t gpio_set_pull_mode(gpio_num_t gpio_num, gpio_pull_mode_t pull);
|
||||
|
||||
/**
|
||||
* @brief enable GPIO wake-up function.
|
||||
* @brief Enable GPIO wake-up function.
|
||||
*
|
||||
* @param gpio_num GPIO number.
|
||||
*
|
||||
@@ -341,15 +341,23 @@ esp_err_t gpio_wakeup_enable(gpio_num_t gpio_num, gpio_int_type_t intr_type);
|
||||
esp_err_t gpio_wakeup_disable(gpio_num_t gpio_num);
|
||||
|
||||
/**
|
||||
* @brief register GPIO interrupt handler, the handler is an ISR.
|
||||
* @brief Register GPIO interrupt handler, the handler is an ISR.
|
||||
* The handler will be attached to the same CPU core that this function is running on.
|
||||
*
|
||||
* This ISR function is called whenever any GPIO interrupt occurs. See
|
||||
* the alternative gpio_install_isr_service() and
|
||||
* gpio_isr_handler_add() API in order to have the driver support
|
||||
* per-GPIO ISRs.
|
||||
*
|
||||
* @param fn Interrupt handler function.
|
||||
* @param intr_alloc_flags Flags used to allocate the interrupt. One or multiple (ORred)
|
||||
* ESP_INTR_FLAG_* values. See esp_intr_alloc.h for more info.
|
||||
* @param arg Parameter for handler function
|
||||
* @param handle Pointer to return handle. If non-NULL, a handle for the interrupt will
|
||||
* be returned here.
|
||||
* @param handle Pointer to return handle. If non-NULL, a handle for the interrupt will be returned here.
|
||||
*
|
||||
* \verbatim embed:rst:leading-asterisk
|
||||
* To disable or remove the ISR, pass the returned handle to the :doc:`interrupt allocation functions </api/system/intr_alloc>`.
|
||||
* \endverbatim
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success ;
|
||||
@@ -402,7 +410,9 @@ esp_err_t gpio_pulldown_en(gpio_num_t gpio_num);
|
||||
esp_err_t gpio_pulldown_dis(gpio_num_t gpio_num);
|
||||
|
||||
/**
|
||||
* @brief Install a GPIO ISR service, so we can assign different ISR handler for different pins
|
||||
* @brief Install the driver's GPIO ISR handler service, which allows per-pin GPIO interrupt handlers.
|
||||
*
|
||||
* This function is incompatible with gpio_isr_register() - if that function is used, a single global ISR is registered for all GPIO interrupts. If this function is used, the ISR service provides a global GPIO ISR and individual pin handlers are registered via the gpio_isr_register() function.
|
||||
*
|
||||
* @param intr_alloc_flags Flags used to allocate the interrupt. One or multiple (ORred)
|
||||
* ESP_INTR_FLAG_* values. See esp_intr_alloc.h for more info.
|
||||
@@ -415,17 +425,24 @@ esp_err_t gpio_pulldown_dis(gpio_num_t gpio_num);
|
||||
esp_err_t gpio_install_isr_service(int intr_alloc_flags);
|
||||
|
||||
/**
|
||||
* @brief Un-install GPIO ISR service, free the resources.
|
||||
* @brief Uninstall the driver's GPIO ISR service, freeing related resources.
|
||||
*/
|
||||
void gpio_uninstall_isr_service();
|
||||
|
||||
/**
|
||||
* @brief Add ISR handler for the corresponding GPIO.
|
||||
* @brief Add ISR handler for the corresponding GPIO pin.
|
||||
*
|
||||
* Interrupt handlers no longer need to be declared with IRAM_ATTR, unless you pass the ESP_INTR_FLAG_IRAM flag
|
||||
* when allocating the ISR in gpio_install_isr_service().
|
||||
* This ISR handler will be called from an ISR. So there probably is some stack size limit, and this limit
|
||||
* is smaller compared to a "raw" interrupt handler due to another level of indirection.
|
||||
* Call this function after using gpio_install_isr_service() to
|
||||
* install the driver's GPIO ISR handler service.
|
||||
*
|
||||
* The pin ISR handlers no longer need to be declared with IRAM_ATTR,
|
||||
* unless you pass the ESP_INTR_FLAG_IRAM flag when allocating the
|
||||
* ISR in gpio_install_isr_service().
|
||||
*
|
||||
* This ISR handler will be called from an ISR. So there is a stack
|
||||
* size limit (configurable as "ISR stack size" in menuconfig). This
|
||||
* limit is smaller compared to a global GPIO interrupt handler due
|
||||
* to the additional level of indirection.
|
||||
*
|
||||
* @param gpio_num GPIO number
|
||||
* @param isr_handler ISR handler function for the corresponding GPIO number.
|
||||
@@ -439,7 +456,7 @@ void gpio_uninstall_isr_service();
|
||||
esp_err_t gpio_isr_handler_add(gpio_num_t gpio_num, gpio_isr_t isr_handler, void* args);
|
||||
|
||||
/**
|
||||
* @brief Remove ISR handler for the corresponding GPIO.
|
||||
* @brief Remove ISR handler for the corresponding GPIO pin.
|
||||
*
|
||||
* @param gpio_num GPIO number
|
||||
*
|
||||
|
||||
@@ -32,9 +32,6 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define I2S_PIN_NO_CHANGE (-1)
|
||||
|
||||
|
||||
/**
|
||||
* @brief I2S bit width per sample.
|
||||
*
|
||||
@@ -147,6 +144,8 @@ typedef struct {
|
||||
size_t size; /*!< I2S data size for I2S_DATA event*/
|
||||
} i2s_event_t;
|
||||
|
||||
#define I2S_PIN_NO_CHANGE (-1) /*!< Use in i2s_pin_config_t for pins which should not be changed */
|
||||
|
||||
/**
|
||||
* @brief I2S pin number for i2s_set_pin
|
||||
*
|
||||
@@ -160,15 +159,18 @@ typedef struct {
|
||||
|
||||
typedef intr_handle_t i2s_isr_handle_t;
|
||||
/**
|
||||
* @brief Set I2S pin number
|
||||
* @brief Set I2S pin number
|
||||
*
|
||||
* @note
|
||||
* Internal signal can be output to multiple GPIO pads
|
||||
* Only one GPIO pad can connect with input signal
|
||||
* @note
|
||||
* The I2S peripheral output signals can be connected to multiple GPIO pads.
|
||||
* However, the I2S peripheral input signal can only be connected to one GPIO pad.
|
||||
*
|
||||
* @param i2s_num I2S_NUM_0 or I2S_NUM_1
|
||||
*
|
||||
* @param pin I2S Pin struct, or NULL for 2-channels, 8-bits DAC pin configuration (GPIO25 & GPIO26)
|
||||
* @param pin I2S Pin structure, or NULL to set 2-channel 8-bit internal DAC pin configuration (GPIO25 & GPIO26)
|
||||
*
|
||||
* Inside the pin configuration structure, set I2S_PIN_NO_CHANGE for any pin where
|
||||
* the current configuration should not be changed.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
@@ -177,15 +179,17 @@ typedef intr_handle_t i2s_isr_handle_t;
|
||||
esp_err_t i2s_set_pin(i2s_port_t i2s_num, const i2s_pin_config_t *pin);
|
||||
|
||||
/**
|
||||
* @brief i2s install and start driver
|
||||
* @brief Install and start I2S driver.
|
||||
*
|
||||
* @param i2s_num I2S_NUM_0, I2S_NUM_1
|
||||
* @param i2s_num I2S_NUM_0, I2S_NUM_1
|
||||
*
|
||||
* @param i2s_config I2S configurations - see i2s_config_t struct
|
||||
* @param i2s_config I2S configurations - see i2s_config_t struct
|
||||
*
|
||||
* @param queue_size I2S event queue size/depth.
|
||||
* @param queue_size I2S event queue size/depth.
|
||||
*
|
||||
* @param i2s_queue I2S event queue handle, if set NULL, driver will not use an event queue.
|
||||
* @param i2s_queue I2S event queue handle, if set NULL, driver will not use an event queue.
|
||||
*
|
||||
* This function must be called before any I2S driver read/write operations.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
@@ -205,68 +209,88 @@ esp_err_t i2s_driver_install(i2s_port_t i2s_num, const i2s_config_t *i2s_config,
|
||||
esp_err_t i2s_driver_uninstall(i2s_port_t i2s_num);
|
||||
|
||||
/**
|
||||
* @brief i2s read data buffer to i2s dma buffer
|
||||
* @brief Write data to I2S DMA transmit buffer.
|
||||
*
|
||||
* @param i2s_num I2S_NUM_0, I2S_NUM_1
|
||||
*
|
||||
* @param src source address to write
|
||||
* @param src Source address to write from
|
||||
*
|
||||
* @param size size of data (size in bytes)
|
||||
* @param size Size of data in bytes
|
||||
*
|
||||
* @param ticks_to_wait Write timeout
|
||||
* @param ticks_to_wait TX buffer wait timeout in RTOS ticks. If this
|
||||
* many ticks pass without space becoming available in the DMA
|
||||
* transmit buffer, then the function will return (note that if the
|
||||
* data is written to the DMA buffer in pieces, the overall operation
|
||||
* may still take longer than this timeout.) Pass portMAX_DELAY for no
|
||||
* timeout.
|
||||
*
|
||||
* @return number of written bytes
|
||||
* Format of the data in source buffer is determined by the I2S
|
||||
* configuration (see i2s_config_t).
|
||||
*
|
||||
* @return Number of bytes written, or ESP_FAIL (-1) for parameter error. If a timeout occurred, bytes written will be less than total size.
|
||||
*/
|
||||
int i2s_write_bytes(i2s_port_t i2s_num, const char *src, size_t size, TickType_t ticks_to_wait);
|
||||
|
||||
/**
|
||||
* @brief i2s write data buffer to i2s dma buffer
|
||||
* @brief Read data from I2S DMA receive buffer
|
||||
*
|
||||
* @param i2s_num I2S_NUM_0, I2S_NUM_1
|
||||
*
|
||||
* @param dest destination address to read
|
||||
* @param dest Destination address to read into
|
||||
*
|
||||
* @param size size of data (size in bytes)
|
||||
* @param size Size of data in bytes
|
||||
*
|
||||
* @param ticks_to_wait Read timeout
|
||||
* @param ticks_to_wait RX buffer wait timeout in RTOS ticks. If this many ticks pass without bytes becoming available in the DMA receive buffer, then the function will return (note that if data is read from the DMA buffer in pieces, the overall operation may still take longer than this timeout.) Pass portMAX_DELAY for no timeout.
|
||||
*
|
||||
* @return number of read bytes
|
||||
* Format of the data in source buffer is determined by the I2S
|
||||
* configuration (see i2s_config_t).
|
||||
*
|
||||
* @return Number of bytes read, or ESP_FAIL (-1) for parameter error. If a timeout occurred, bytes read will be less than total size.
|
||||
*/
|
||||
int i2s_read_bytes(i2s_port_t i2s_num, char* dest, size_t size, TickType_t ticks_to_wait);
|
||||
|
||||
/**
|
||||
* @brief i2s push 1 sample to i2s dma buffer, with the size parameter equal to one sample's size in bytes = bits_per_sample/8.
|
||||
* @brief Push (write) a single sample to the I2S DMA TX buffer.
|
||||
*
|
||||
* Size of the sample is determined by the channel_format (mono or stereo)) & bits_per_sample configuration (see i2s_config_t).
|
||||
*
|
||||
* @param i2s_num I2S_NUM_0, I2S_NUM_1
|
||||
*
|
||||
* @param sample destination address to write (depend on bits_per_sample, size of sample (in bytes) = 2*bits_per_sample/8)
|
||||
* @param sample Pointer to buffer containing sample to write. Size of buffer (in bytes) = (number of channels) * bits_per_sample / 8.
|
||||
*
|
||||
* @param ticks_to_wait Push timeout
|
||||
* @param ticks_to_wait Push timeout in RTOS ticks. If space is not available in the DMA TX buffer within this period, no data is written and function returns 0.
|
||||
*
|
||||
* @return number of push bytes
|
||||
* @return Number of bytes successfully pushed to DMA buffer, or ESP_FAIL (-1) for parameter error. Will be either zero or the size of configured sample buffer.
|
||||
*/
|
||||
int i2s_push_sample(i2s_port_t i2s_num, const char *sample, TickType_t ticks_to_wait);
|
||||
|
||||
/**
|
||||
* @brief Pop 1 sample to i2s dma buffer, with the size parameter equal to one sample's size in bytes = bits_per_sample/8.
|
||||
* @brief Pop (read) a single sample from the I2S DMA RX buffer.
|
||||
*
|
||||
* Size of the sample is determined by the channel_format (mono or stereo)) & bits_per_sample configuration (see i2s_config_t).
|
||||
*
|
||||
* @param i2s_num I2S_NUM_0, I2S_NUM_1
|
||||
*
|
||||
* @param sample destination address to write (depend on bits_per_sample, size of sample (in bytes) = 2*bits_per_sample/8)
|
||||
* @param sample Buffer sample data will be read into. Size of buffer (in bytes) = (number of channels) * bits_per_sample / 8.
|
||||
*
|
||||
* @param ticks_to_wait Pop timeout
|
||||
* @param ticks_to_wait Pop timeout in RTOS ticks. If a sample is not available in the DMA buffer within this period, no data is read and function returns zero.
|
||||
*
|
||||
* @return number of pop bytes
|
||||
* @return Number of bytes successfully read from DMA buffer, or ESP_FAIL (-1) for parameter error. Byte count will be either zero or the size of the configured sample buffer.
|
||||
|
||||
*/
|
||||
int i2s_pop_sample(i2s_port_t i2s_num, char *sample, TickType_t ticks_to_wait);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set clock rate used for I2S RX and TX
|
||||
* @brief Set sample rate used for I2S RX and TX.
|
||||
*
|
||||
* The bit clock rate is determined by the sample rate and i2s_config_t configuration parameters (number of channels, bits_per_sample).
|
||||
*
|
||||
* `bit_clock = rate * (number of channels) * bits_per_sample`
|
||||
*
|
||||
* @param i2s_num I2S_NUM_0, I2S_NUM_1
|
||||
*
|
||||
* @param rate I2S clock (ex: 8000, 44100...)
|
||||
* @param rate I2S sample rate (ex: 8000, 44100...)
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
@@ -275,18 +299,9 @@ int i2s_pop_sample(i2s_port_t i2s_num, char *sample, TickType_t ticks_to_wait);
|
||||
esp_err_t i2s_set_sample_rates(i2s_port_t i2s_num, uint32_t rate);
|
||||
|
||||
/**
|
||||
* @brief Start driver
|
||||
* @brief Stop I2S driver
|
||||
*
|
||||
* @param i2s_num I2S_NUM_0, I2S_NUM_1
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_FAIL Parameter error
|
||||
*/
|
||||
esp_err_t i2s_start(i2s_port_t i2s_num);
|
||||
|
||||
/**
|
||||
* @brief Stop driver
|
||||
* Disables I2S TX/RX, until i2s_start() is called.
|
||||
*
|
||||
* @param i2s_num I2S_NUM_0, I2S_NUM_1
|
||||
*
|
||||
@@ -297,7 +312,23 @@ esp_err_t i2s_start(i2s_port_t i2s_num);
|
||||
esp_err_t i2s_stop(i2s_port_t i2s_num);
|
||||
|
||||
/**
|
||||
* @brief Set the TX DMA buffer contents to all zeroes
|
||||
* @brief Start I2S driver
|
||||
*
|
||||
* It is not necessary to call this function after i2s_driver_install() (it is started automatically), however it is necessary to call it after i2s_stop().
|
||||
*
|
||||
*
|
||||
* @param i2s_num I2S_NUM_0, I2S_NUM_1
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_FAIL Parameter error
|
||||
*/
|
||||
esp_err_t i2s_start(i2s_port_t i2s_num);
|
||||
|
||||
/**
|
||||
* @brief Zero the contents of the TX DMA buffer.
|
||||
*
|
||||
* Pushes zero-byte samples into the TX DMA buffer, until it is full.
|
||||
*
|
||||
* @param i2s_num I2S_NUM_0, I2S_NUM_1
|
||||
*
|
||||
@@ -307,72 +338,6 @@ esp_err_t i2s_stop(i2s_port_t i2s_num);
|
||||
*/
|
||||
esp_err_t i2s_zero_dma_buffer(i2s_port_t i2s_num);
|
||||
|
||||
/***************************EXAMPLE**********************************
|
||||
*
|
||||
*
|
||||
* ----------------EXAMPLE OF I2S SETTING ---------------------
|
||||
* @code{c}
|
||||
*
|
||||
* #include "freertos/queue.h"
|
||||
* #define I2S_INTR_NUM 17 //choose one interrupt number from soc.h
|
||||
* int i2s_num = 0; //i2s port number
|
||||
* i2s_config_t i2s_config = {
|
||||
* .mode = I2S_MODE_MASTER | I2S_MODE_TX,
|
||||
* .sample_rate = 44100,
|
||||
* .bits_per_sample = 16, //16, 32
|
||||
* .channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT, //format LEFT_RIGHT
|
||||
* .communication_format = I2S_COMM_FORMAT_I2S | I2S_COMM_FORMAT_I2S_MSB,
|
||||
* .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1,
|
||||
* .dma_buf_count = 8,
|
||||
* .dma_buf_len = 64
|
||||
* };
|
||||
*
|
||||
* i2s_pin_config_t pin_config = {
|
||||
* .bck_io_num = 26,
|
||||
* .ws_io_num = 25,
|
||||
* .data_out_num = 22,
|
||||
* .data_in_num = I2S_PIN_NO_CHANGE
|
||||
* };
|
||||
*
|
||||
* i2s_driver_install(i2s_num, &i2s_config, 0, NULL); //install and start i2s driver
|
||||
*
|
||||
* i2s_set_pin(i2s_num, &pin_config);
|
||||
*
|
||||
* i2s_set_sample_rates(i2s_num, 22050); //set sample rates
|
||||
*
|
||||
*
|
||||
* i2s_driver_uninstall(i2s_num); //stop & destroy i2s driver
|
||||
*@endcode
|
||||
*
|
||||
* ----------------EXAMPLE USING I2S WITH DAC ---------------------
|
||||
* @code{c}
|
||||
*
|
||||
* #include "freertos/queue.h"
|
||||
* #define I2S_INTR_NUM 17 //choose one interrupt number from soc.h
|
||||
* int i2s_num = 0; //i2s port number
|
||||
* i2s_config_t i2s_config = {
|
||||
* .mode = I2S_MODE_MASTER | I2S_MODE_TX | I2S_MODE_DAC_BUILT_IN,
|
||||
* .sample_rate = 44100,
|
||||
* .bits_per_sample = 8, // Only 8-bit DAC support
|
||||
* .channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT, //
|
||||
* .communication_format = I2S_COMM_FORMAT_I2S_MSB,
|
||||
* .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1,
|
||||
* .dma_buf_count = 8,
|
||||
* .dma_buf_len = 64
|
||||
* };
|
||||
*
|
||||
*
|
||||
* i2s_driver_install(i2s_num, &i2s_config, 0, NULL); //install and start i2s driver
|
||||
*
|
||||
* i2s_set_pin(i2s_num, NULL); //for internal DAC
|
||||
*
|
||||
* i2s_set_sample_rates(i2s_num, 22050); //set sample rates
|
||||
*
|
||||
* i2s_driver_uninstall(i2s_num); //stop & destroy i2s driver
|
||||
*@endcode
|
||||
*-----------------------------------------------------------------------------*
|
||||
***************************END OF EXAMPLE**********************************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -24,7 +24,10 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Pullup/pulldown information for a single GPIO pad
|
||||
* @brief Pin function information for a single GPIO pad's RTC functions.
|
||||
*
|
||||
* This is an internal function of the driver, and is not usually useful
|
||||
* for external use.
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t reg; /*!< Register of RTC pad, or 0 if not an RTC GPIO */
|
||||
@@ -46,10 +49,29 @@ typedef enum {
|
||||
RTC_GPIO_MODE_DISABLED, /*!< Pad (output + input) disable */
|
||||
} rtc_gpio_mode_t;
|
||||
|
||||
#define RTC_GPIO_IS_VALID_GPIO(gpio_num) ((gpio_num < GPIO_PIN_COUNT && rtc_gpio_desc[gpio_num].reg != 0)) //to decide whether it is a valid GPIO number
|
||||
|
||||
/**
|
||||
* @brief Provides access to a constant table of RTC I/O pin
|
||||
* function information.
|
||||
*
|
||||
* This is an internal function of the driver, and is not usually useful
|
||||
* for external use.
|
||||
*/
|
||||
extern const rtc_gpio_desc_t rtc_gpio_desc[GPIO_PIN_COUNT];
|
||||
|
||||
/**
|
||||
* @brief Determine if the specified GPIO is a valid RTC GPIO.
|
||||
*
|
||||
* @param gpio_num GPIO number
|
||||
* @return true if GPIO is valid for RTC GPIO use. talse otherwise.
|
||||
*/
|
||||
inline static bool rtc_gpio_is_valid_gpio(gpio_num_t gpio_num)
|
||||
{
|
||||
return gpio_num < GPIO_PIN_COUNT
|
||||
&& rtc_gpio_desc[gpio_num].reg != 0;
|
||||
}
|
||||
|
||||
#define RTC_GPIO_IS_VALID_GPIO(gpio_num) rtc_gpio_is_valid_gpio(gpio_num) // Deprecated, use rtc_gpio_is_valid_gpio()
|
||||
|
||||
/**
|
||||
* @brief Init a GPIO as RTC GPIO
|
||||
*
|
||||
|
||||
@@ -50,10 +50,12 @@ extern "C" {
|
||||
typedef struct {
|
||||
gpio_num_t gpio_cd; ///< GPIO number of card detect signal
|
||||
gpio_num_t gpio_wp; ///< GPIO number of write protect signal
|
||||
uint8_t width; ///< Bus width used by the slot (might be less than the max width supported)
|
||||
} sdmmc_slot_config_t;
|
||||
|
||||
#define SDMMC_SLOT_NO_CD ((gpio_num_t) -1) ///< indicates that card detect line is not used
|
||||
#define SDMMC_SLOT_NO_WP ((gpio_num_t) -1) ///< indicates that write protect line is not used
|
||||
#define SDMMC_SLOT_WIDTH_DEFAULT 0 ///< use the default width for the slot (8 for slot 0, 4 for slot 1)
|
||||
|
||||
/**
|
||||
* Macro defining default configuration of SDMMC host slot
|
||||
@@ -61,6 +63,7 @@ typedef struct {
|
||||
#define SDMMC_SLOT_CONFIG_DEFAULT() {\
|
||||
.gpio_cd = SDMMC_SLOT_NO_CD, \
|
||||
.gpio_wp = SDMMC_SLOT_NO_WP, \
|
||||
.width = SDMMC_SLOT_WIDTH_DEFAULT, \
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -469,8 +469,6 @@ esp_err_t uart_intr_config(uart_port_t uart_num, const uart_intr_config_t *intr_
|
||||
* @brief Install UART driver.
|
||||
*
|
||||
* UART ISR handler will be attached to the same CPU core that this function is running on.
|
||||
* Users should know that which CPU is running and then pick a INUM that is not used by system.
|
||||
* We can find the information of INUM and interrupt level in soc.h.
|
||||
*
|
||||
* @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2
|
||||
* @param rx_buffer_size UART RX ring buffer size, rx_buffer_size should be greater than UART_FIFO_LEN.
|
||||
@@ -644,7 +642,6 @@ esp_err_t uart_enable_pattern_det_intr(uart_port_t uart_num, char pattern_chr, u
|
||||
* @code{c}
|
||||
* //1. Setup UART
|
||||
* #include "freertos/queue.h"
|
||||
* #define UART_INTR_NUM 17 //choose one interrupt number from soc.h
|
||||
* //a. Set UART parameter
|
||||
* int uart_num = 0; //uart port number
|
||||
* uart_config_t uart_config = {
|
||||
|
||||
@@ -87,7 +87,7 @@ const rtc_gpio_desc_t rtc_gpio_desc[GPIO_PIN_COUNT] = {
|
||||
---------------------------------------------------------------*/
|
||||
esp_err_t rtc_gpio_init(gpio_num_t gpio_num)
|
||||
{
|
||||
RTC_MODULE_CHECK(RTC_GPIO_IS_VALID_GPIO(gpio_num), "RTC_GPIO number error", ESP_ERR_INVALID_ARG);
|
||||
RTC_MODULE_CHECK(rtc_gpio_is_valid_gpio(gpio_num), "RTC_GPIO number error", ESP_ERR_INVALID_ARG);
|
||||
portENTER_CRITICAL(&rtc_spinlock);
|
||||
// 0: GPIO connected to digital GPIO module. 1: GPIO connected to analog RTC module.
|
||||
SET_PERI_REG_MASK(rtc_gpio_desc[gpio_num].reg, (rtc_gpio_desc[gpio_num].mux));
|
||||
@@ -100,7 +100,7 @@ esp_err_t rtc_gpio_init(gpio_num_t gpio_num)
|
||||
|
||||
esp_err_t rtc_gpio_deinit(gpio_num_t gpio_num)
|
||||
{
|
||||
RTC_MODULE_CHECK(RTC_GPIO_IS_VALID_GPIO(gpio_num), "RTC_GPIO number error", ESP_ERR_INVALID_ARG);
|
||||
RTC_MODULE_CHECK(rtc_gpio_is_valid_gpio(gpio_num), "RTC_GPIO number error", ESP_ERR_INVALID_ARG);
|
||||
portENTER_CRITICAL(&rtc_spinlock);
|
||||
//Select Gpio as Digital Gpio
|
||||
CLEAR_PERI_REG_MASK(rtc_gpio_desc[gpio_num].reg, (rtc_gpio_desc[gpio_num].mux));
|
||||
@@ -131,7 +131,7 @@ static esp_err_t rtc_gpio_output_disable(gpio_num_t gpio_num)
|
||||
|
||||
static esp_err_t rtc_gpio_input_enable(gpio_num_t gpio_num)
|
||||
{
|
||||
RTC_MODULE_CHECK(RTC_GPIO_IS_VALID_GPIO(gpio_num), "RTC_GPIO number error", ESP_ERR_INVALID_ARG);
|
||||
RTC_MODULE_CHECK(rtc_gpio_is_valid_gpio(gpio_num), "RTC_GPIO number error", ESP_ERR_INVALID_ARG);
|
||||
portENTER_CRITICAL(&rtc_spinlock);
|
||||
SET_PERI_REG_MASK(rtc_gpio_desc[gpio_num].reg, rtc_gpio_desc[gpio_num].ie);
|
||||
portEXIT_CRITICAL(&rtc_spinlock);
|
||||
@@ -141,7 +141,7 @@ static esp_err_t rtc_gpio_input_enable(gpio_num_t gpio_num)
|
||||
|
||||
static esp_err_t rtc_gpio_input_disable(gpio_num_t gpio_num)
|
||||
{
|
||||
RTC_MODULE_CHECK(RTC_GPIO_IS_VALID_GPIO(gpio_num), "RTC_GPIO number error", ESP_ERR_INVALID_ARG);
|
||||
RTC_MODULE_CHECK(rtc_gpio_is_valid_gpio(gpio_num), "RTC_GPIO number error", ESP_ERR_INVALID_ARG);
|
||||
portENTER_CRITICAL(&rtc_spinlock);
|
||||
CLEAR_PERI_REG_MASK(rtc_gpio_desc[gpio_num].reg, rtc_gpio_desc[gpio_num].ie);
|
||||
portEXIT_CRITICAL(&rtc_spinlock);
|
||||
@@ -152,7 +152,7 @@ static esp_err_t rtc_gpio_input_disable(gpio_num_t gpio_num)
|
||||
esp_err_t rtc_gpio_set_level(gpio_num_t gpio_num, uint32_t level)
|
||||
{
|
||||
int rtc_gpio_num = rtc_gpio_num = rtc_gpio_desc[gpio_num].rtc_num;;
|
||||
RTC_MODULE_CHECK(RTC_GPIO_IS_VALID_GPIO(gpio_num), "RTC_GPIO number error", ESP_ERR_INVALID_ARG);
|
||||
RTC_MODULE_CHECK(rtc_gpio_is_valid_gpio(gpio_num), "RTC_GPIO number error", ESP_ERR_INVALID_ARG);
|
||||
|
||||
if (level) {
|
||||
WRITE_PERI_REG(RTC_GPIO_OUT_W1TS_REG, (1 << (rtc_gpio_num + RTC_GPIO_OUT_DATA_W1TS_S)));
|
||||
@@ -167,7 +167,7 @@ uint32_t rtc_gpio_get_level(gpio_num_t gpio_num)
|
||||
{
|
||||
uint32_t level = 0;
|
||||
int rtc_gpio_num = rtc_gpio_desc[gpio_num].rtc_num;
|
||||
RTC_MODULE_CHECK(RTC_GPIO_IS_VALID_GPIO(gpio_num), "RTC_GPIO number error", ESP_ERR_INVALID_ARG);
|
||||
RTC_MODULE_CHECK(rtc_gpio_is_valid_gpio(gpio_num), "RTC_GPIO number error", ESP_ERR_INVALID_ARG);
|
||||
|
||||
portENTER_CRITICAL(&rtc_spinlock);
|
||||
level = READ_PERI_REG(RTC_GPIO_IN_REG);
|
||||
@@ -177,7 +177,7 @@ uint32_t rtc_gpio_get_level(gpio_num_t gpio_num)
|
||||
|
||||
esp_err_t rtc_gpio_set_direction(gpio_num_t gpio_num, rtc_gpio_mode_t mode)
|
||||
{
|
||||
RTC_MODULE_CHECK(RTC_GPIO_IS_VALID_GPIO(gpio_num), "RTC_GPIO number error", ESP_ERR_INVALID_ARG);
|
||||
RTC_MODULE_CHECK(rtc_gpio_is_valid_gpio(gpio_num), "RTC_GPIO number error", ESP_ERR_INVALID_ARG);
|
||||
|
||||
switch (mode) {
|
||||
case RTC_GPIO_MODE_INPUT_ONLY:
|
||||
|
||||
@@ -299,20 +299,31 @@ esp_err_t sdmmc_host_init_slot(int slot, const sdmmc_slot_config_t* slot_config)
|
||||
}
|
||||
int gpio_cd = slot_config->gpio_cd;
|
||||
int gpio_wp = slot_config->gpio_wp;
|
||||
uint8_t slot_width = slot_config->width;
|
||||
|
||||
// Configure pins
|
||||
const sdmmc_slot_info_t* pslot = &s_slot_info[slot];
|
||||
|
||||
if (slot_width == SDMMC_SLOT_WIDTH_DEFAULT) {
|
||||
slot_width = pslot->width;
|
||||
}
|
||||
else if (slot_width > pslot->width) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
configure_pin(pslot->clk);
|
||||
configure_pin(pslot->cmd);
|
||||
configure_pin(pslot->d0);
|
||||
configure_pin(pslot->d1);
|
||||
configure_pin(pslot->d2);
|
||||
configure_pin(pslot->d3);
|
||||
if (pslot->width == 8) {
|
||||
configure_pin(pslot->d4);
|
||||
configure_pin(pslot->d5);
|
||||
configure_pin(pslot->d6);
|
||||
configure_pin(pslot->d7);
|
||||
if (slot_width >= 4) {
|
||||
configure_pin(pslot->d1);
|
||||
configure_pin(pslot->d2);
|
||||
configure_pin(pslot->d3);
|
||||
if (slot_width == 8) {
|
||||
configure_pin(pslot->d4);
|
||||
configure_pin(pslot->d5);
|
||||
configure_pin(pslot->d6);
|
||||
configure_pin(pslot->d7);
|
||||
}
|
||||
}
|
||||
if (gpio_cd != -1) {
|
||||
gpio_set_direction(gpio_cd, GPIO_MODE_INPUT);
|
||||
|
||||
@@ -502,6 +502,7 @@ static void IRAM_ATTR spi_intr(void *arg)
|
||||
//We have a transaction. Send it.
|
||||
spi_device_t *dev=host->device[i];
|
||||
host->cur_trans=trans;
|
||||
host->cur_cs=i;
|
||||
//We should be done with the transmission.
|
||||
assert(host->hw->cmd.usr == 0);
|
||||
|
||||
@@ -510,7 +511,7 @@ static void IRAM_ATTR spi_intr(void *arg)
|
||||
trans->rxlength=trans->length;
|
||||
}
|
||||
|
||||
//Reconfigure accoding to device settings, but only if we change CSses.
|
||||
//Reconfigure according to device settings, but only if we change CSses.
|
||||
if (i!=prevCs) {
|
||||
//Assumes a hardcoded 80MHz Fapb for now. ToDo: figure out something better once we have
|
||||
//clock scaling working.
|
||||
@@ -599,7 +600,7 @@ static void IRAM_ATTR spi_intr(void *arg)
|
||||
} else {
|
||||
data=trans->rx_buffer;
|
||||
}
|
||||
if (trans->rxlength<THRESH_DMA_TRANS) {
|
||||
if (trans->rxlength <= THRESH_DMA_TRANS) {
|
||||
//No need for DMA; we'll copy the result out of the work registers directly later.
|
||||
} else {
|
||||
host->hw->user.usr_miso_highpart=0;
|
||||
@@ -624,9 +625,9 @@ static void IRAM_ATTR spi_intr(void *arg)
|
||||
} else {
|
||||
data=(uint32_t *)trans->tx_buffer;
|
||||
}
|
||||
if (trans->rxlength < 8*32) {
|
||||
if (trans->length <= THRESH_DMA_TRANS) {
|
||||
//No need for DMA.
|
||||
for (int x=0; x < trans->rxlength; x+=32) {
|
||||
for (int x=0; x < trans->length; x+=32) {
|
||||
//Use memcpy to get around alignment issues for txdata
|
||||
uint32_t word;
|
||||
memcpy(&word, &data[x/32], 4);
|
||||
@@ -655,7 +656,7 @@ static void IRAM_ATTR spi_intr(void *arg)
|
||||
host->hw->addr=trans->address & 0xffffffff;
|
||||
}
|
||||
host->hw->user.usr_mosi=(trans->tx_buffer==NULL)?0:1;
|
||||
host->hw->user.usr_miso=(trans->tx_buffer==NULL)?0:1;
|
||||
host->hw->user.usr_miso=(trans->rx_buffer==NULL)?0:1;
|
||||
|
||||
//Call pre-transmission callback, if any
|
||||
if (dev->cfg.pre_cb) dev->cfg.pre_cb(trans);
|
||||
|
||||
@@ -105,6 +105,28 @@ config MEMMAP_SPISRAM
|
||||
main memory map. Enable this if you have this hardware and want to use it in the same
|
||||
way as on-chip RAM.
|
||||
|
||||
choice NUMBER_OF_MAC_ADDRESS_GENERATED_FROM_EFUSE
|
||||
bool "Number of MAC address generated from the hardware MAC address in efuse"
|
||||
default FOUR_MAC_ADDRESS_FROM_EFUSE
|
||||
help
|
||||
Config the number of MAC address which is generated from the hardware MAC address in efuse.
|
||||
If the number is two, the MAC addresses of WiFi station and bluetooth are generated from
|
||||
the hardware MAC address in efuse. The MAC addresses of WiFi softap and ethernet are derived
|
||||
from that of WiFi station and bluetooth respectively.
|
||||
If the number is four, the MAC addresses of WiFi station, WiFi softap, bluetooth and ethernet
|
||||
are all generated from the hardware MAC address in efuse.
|
||||
|
||||
config TWO_MAC_ADDRESS_FROM_EFUSE
|
||||
bool "Two"
|
||||
config FOUR_MAC_ADDRESS_FROM_EFUSE
|
||||
bool "Four"
|
||||
endchoice
|
||||
|
||||
config NUMBER_OF_MAC_ADDRESS_GENERATED_FROM_EFUSE
|
||||
int
|
||||
default 2 if TWO_MAC_ADDRESS_FROM_EFUSE
|
||||
default 4 if FOUR_MAC_ADDRESS_FROM_EFUSE
|
||||
|
||||
config SYSTEM_EVENT_QUEUE_SIZE
|
||||
int "System event queue size"
|
||||
default 32
|
||||
@@ -491,15 +513,61 @@ config SW_COEXIST_ENABLE
|
||||
automatically managed, no user intervention is required.
|
||||
|
||||
|
||||
config ESP32_WIFI_RX_BUFFER_NUM
|
||||
int "Max number of WiFi RX buffers"
|
||||
config ESP32_WIFI_STATIC_RX_BUFFER_NUM
|
||||
int "Max number of WiFi static RX buffers"
|
||||
depends on WIFI_ENABLED
|
||||
range 2 25
|
||||
default 25
|
||||
default 10
|
||||
help
|
||||
Set the number of WiFi rx buffers. Each buffer takes approximately 1.6KB of RAM.
|
||||
Larger number for higher throughput but more memory. Smaller number for lower
|
||||
throughput but less memory.
|
||||
Set the number of WiFi static rx buffers. Each buffer takes approximately 1.6KB of RAM.
|
||||
The static rx buffers are allocated when esp_wifi_init is called, they are not freed
|
||||
until esp_wifi_deinit is called.
|
||||
WiFi hardware use these buffers to receive packets, generally larger number for higher
|
||||
throughput but more memory, smaller number for lower throughput but less memory.
|
||||
|
||||
config ESP32_WIFI_DYNAMIC_RX_BUFFER_NUM
|
||||
int "Max number of WiFi dynamic RX buffers"
|
||||
depends on WIFI_ENABLED
|
||||
range 0 64
|
||||
default 0
|
||||
help
|
||||
Set the number of WiFi dynamic rx buffers, 0 means no limitation for dynamic rx buffer
|
||||
allocation. The size of dynamic rx buffers is not fixed.
|
||||
For each received packet in static rx buffers, WiFi driver makes a copy
|
||||
to dynamic rx buffers and then deliver it to high layer stack. The dynamic rx buffer
|
||||
is freed when the application, such as socket, successfully received the packet.
|
||||
For some applications, the WiFi driver receiving speed is faster than application
|
||||
consuming speed, we may run out of memory if no limitation for the dynamic rx buffer
|
||||
number. Generally the number of dynamic rx buffer should be no less than static
|
||||
rx buffer number if it is not 0.
|
||||
|
||||
config ESP32_WIFI_DYNAMIC_TX_BUFFER_NUM
|
||||
int "Max number of WiFi dynamic TX buffers"
|
||||
depends on WIFI_ENABLED
|
||||
range 16 64
|
||||
default 32
|
||||
help
|
||||
Set the number of WiFi dynamic tx buffers, 0 means no limitation for dynamic tx buffer
|
||||
allocation. The size of dynamic tx buffers is not fixed.
|
||||
For each tx packet from high layer stack, WiFi driver make a copy of it. For some applications,
|
||||
especially the UDP application, the high layer deliver speed is faster than the WiFi tx
|
||||
speed, we may run out of memory if no limitation for the dynamic tx buffer number.
|
||||
|
||||
|
||||
config ESP32_WIFI_AMPDU_ENABLED
|
||||
bool "WiFi AMPDU"
|
||||
depends on WIFI_ENABLED
|
||||
default y
|
||||
help
|
||||
Select this option to enable AMPDU feature
|
||||
|
||||
|
||||
config ESP32_WIFI_NVS_ENABLED
|
||||
bool "WiFi NVS flash"
|
||||
depends on WIFI_ENABLED
|
||||
default y
|
||||
help
|
||||
Select this option to enable WiFi NVS flash
|
||||
|
||||
config PHY_ENABLED
|
||||
bool
|
||||
@@ -507,19 +575,15 @@ config PHY_ENABLED
|
||||
|
||||
menu PHY
|
||||
visible if PHY_ENABLED
|
||||
|
||||
config ESP32_PHY_AUTO_INIT
|
||||
bool "Initialize PHY in startup code"
|
||||
|
||||
config ESP32_PHY_CALIBRATION_AND_DATA_STORAGE
|
||||
bool "Do phy calibration and store calibration data in NVS"
|
||||
depends on PHY_ENABLED
|
||||
default y
|
||||
help
|
||||
If enabled, PHY will be initialized in startup code, before
|
||||
app_main function runs.
|
||||
If this is undesired, disable this option and call esp_phy_init
|
||||
from the application before enabling WiFi or BT.
|
||||
|
||||
If this option is enabled, startup code will also initialize
|
||||
NVS prior to initializing PHY.
|
||||
If this option is enabled, NVS will be initialized and calibration data will be loaded from there.
|
||||
PHY calibration will be skipped on deep sleep wakeup. If calibration data is not found, full calibration
|
||||
will be performed and stored in NVS. In all other cases, only partial calibration will be performed.
|
||||
|
||||
If unsure, choose 'y'.
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
#
|
||||
|
||||
COMPONENT_SRCDIRS := . hwcrypto
|
||||
LIBS := core rtc
|
||||
LIBS := core rtc rtc_clk
|
||||
ifdef CONFIG_PHY_ENABLED # BT || WIFI
|
||||
LIBS += phy coexist
|
||||
endif
|
||||
|
||||
@@ -26,16 +26,17 @@
|
||||
#if CONFIG_ESP32_ENABLE_COREDUMP
|
||||
#define LOG_LOCAL_LEVEL CONFIG_ESP32_CORE_DUMP_LOG_LEVEL
|
||||
#include "esp_log.h"
|
||||
const static char *TAG = "esp_core_dump";
|
||||
const static DRAM_ATTR char TAG[] = "esp_core_dump";
|
||||
|
||||
#define ESP_COREDUMP_LOGE( format, ... ) if (LOG_LOCAL_LEVEL >= ESP_LOG_ERROR) { ets_printf(LOG_FORMAT(E, format), esp_log_early_timestamp(), TAG, ##__VA_ARGS__); }
|
||||
#define ESP_COREDUMP_LOGW( format, ... ) if (LOG_LOCAL_LEVEL >= ESP_LOG_WARN) { ets_printf(LOG_FORMAT(W, format), esp_log_early_timestamp(), TAG, ##__VA_ARGS__); }
|
||||
#define ESP_COREDUMP_LOGI( format, ... ) if (LOG_LOCAL_LEVEL >= ESP_LOG_INFO) { ets_printf(LOG_FORMAT(I, format), esp_log_early_timestamp(), TAG, ##__VA_ARGS__); }
|
||||
#define ESP_COREDUMP_LOGD( format, ... ) if (LOG_LOCAL_LEVEL >= ESP_LOG_DEBUG) { ets_printf(LOG_FORMAT(D, format), esp_log_early_timestamp(), TAG, ##__VA_ARGS__); }
|
||||
#define ESP_COREDUMP_LOGV( format, ... ) if (LOG_LOCAL_LEVEL >= ESP_LOG_VERBOSE) { ets_printf(LOG_FORMAT(V, format), esp_log_early_timestamp(), TAG, ##__VA_ARGS__); }
|
||||
#define ESP_COREDUMP_LOG( level, format, ... ) if (LOG_LOCAL_LEVEL >= level) { ets_printf(DRAM_STR(format), esp_log_early_timestamp(), (const char *)TAG, ##__VA_ARGS__); }
|
||||
#define ESP_COREDUMP_LOGE( format, ... ) ESP_COREDUMP_LOG(ESP_LOG_ERROR, LOG_FORMAT(E, format), ##__VA_ARGS__)
|
||||
#define ESP_COREDUMP_LOGW( format, ... ) ESP_COREDUMP_LOG(ESP_LOG_WARN, LOG_FORMAT(W, format), ##__VA_ARGS__)
|
||||
#define ESP_COREDUMP_LOGI( format, ... ) ESP_COREDUMP_LOG(ESP_LOG_INFO, LOG_FORMAT(I, format), ##__VA_ARGS__)
|
||||
#define ESP_COREDUMP_LOGD( format, ... ) ESP_COREDUMP_LOG(ESP_LOG_DEBUG, LOG_FORMAT(D, format), ##__VA_ARGS__)
|
||||
#define ESP_COREDUMP_LOGV( format, ... ) ESP_COREDUMP_LOG(ESP_LOG_VERBOSE, LOG_FORMAT(V, format), ##__VA_ARGS__)
|
||||
|
||||
#if CONFIG_ESP32_ENABLE_COREDUMP_TO_FLASH
|
||||
#define ESP_COREDUMP_LOG_PROCESS( format, ... ) if (LOG_LOCAL_LEVEL >= ESP_LOG_DEBUG) { ets_printf(LOG_FORMAT(D, format), esp_log_early_timestamp(), TAG, ##__VA_ARGS__); }
|
||||
#define ESP_COREDUMP_LOG_PROCESS( format, ... ) ESP_COREDUMP_LOGD(format, ##__VA_ARGS__)
|
||||
#else
|
||||
#define ESP_COREDUMP_LOG_PROCESS( format, ... ) do{/*(__VA_ARGS__);*/}while(0)
|
||||
#endif
|
||||
@@ -345,8 +346,9 @@ void esp_core_dump_to_flash(XtExcFrame *frame)
|
||||
#endif
|
||||
|
||||
#if CONFIG_ESP32_ENABLE_COREDUMP_TO_UART
|
||||
|
||||
static void esp_core_dump_b64_encode(const uint8_t *src, uint32_t src_len, uint8_t *dst) {
|
||||
static const char *b64 =
|
||||
const static DRAM_ATTR char b64[] =
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
int i, j, a, b, c;
|
||||
|
||||
@@ -373,14 +375,14 @@ static void esp_core_dump_b64_encode(const uint8_t *src, uint32_t src_len, uint8
|
||||
static esp_err_t esp_core_dump_uart_write_start(void *priv)
|
||||
{
|
||||
esp_err_t err = ESP_OK;
|
||||
ets_printf("================= CORE DUMP START =================\r\n");
|
||||
ets_printf(DRAM_STR("================= CORE DUMP START =================\r\n"));
|
||||
return err;
|
||||
}
|
||||
|
||||
static esp_err_t esp_core_dump_uart_write_end(void *priv)
|
||||
{
|
||||
esp_err_t err = ESP_OK;
|
||||
ets_printf("================= CORE DUMP END =================\r\n");
|
||||
ets_printf(DRAM_STR("================= CORE DUMP END =================\r\n"));
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -398,7 +400,7 @@ static esp_err_t esp_core_dump_uart_write_data(void *priv, void * data, uint32_t
|
||||
memcpy(tmp, addr, len);
|
||||
esp_core_dump_b64_encode((const uint8_t *)tmp, len, (uint8_t *)buf);
|
||||
addr += len;
|
||||
ets_printf("%s\r\n", buf);
|
||||
ets_printf(DRAM_STR("%s\r\n"), buf);
|
||||
}
|
||||
|
||||
return err;
|
||||
@@ -427,7 +429,8 @@ void esp_core_dump_to_uart(XtExcFrame *frame)
|
||||
wr_cfg.priv = NULL;
|
||||
|
||||
//Make sure txd/rxd are enabled
|
||||
gpio_pullup_dis(1);
|
||||
// use direct reg access instead of gpio_pullup_dis which can cause exception when flash cache is disabled
|
||||
REG_CLR_BIT(GPIO_PIN_REG_1, FUN_PU);
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0RXD_U, FUNC_U0RXD_U0RXD);
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0TXD_U, FUNC_U0TXD_U0TXD);
|
||||
|
||||
@@ -438,10 +441,6 @@ void esp_core_dump_to_uart(XtExcFrame *frame)
|
||||
tm_cur = xthal_get_ccount() / (XT_CLOCK_FREQ / 1000);
|
||||
if (tm_cur >= tm_end)
|
||||
break;
|
||||
/* Feed the Cerberus. */
|
||||
TIMERG0.wdt_wprotect = TIMG_WDT_WKEY_VALUE;
|
||||
TIMERG0.wdt_feed = 1;
|
||||
TIMERG0.wdt_wprotect = 0;
|
||||
ch = esp_core_dump_uart_get_char();
|
||||
}
|
||||
ESP_COREDUMP_LOGI("Print core dump to uart...");
|
||||
@@ -455,18 +454,18 @@ void esp_core_dump_init()
|
||||
#if CONFIG_ESP32_ENABLE_COREDUMP_TO_FLASH
|
||||
const esp_partition_t *core_part;
|
||||
|
||||
ESP_LOGI(TAG, "Init core dump to flash");
|
||||
ESP_COREDUMP_LOGI("Init core dump to flash");
|
||||
core_part = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_COREDUMP, NULL);
|
||||
if (!core_part) {
|
||||
ESP_LOGE(TAG, "No core dump partition found!");
|
||||
ESP_COREDUMP_LOGE("No core dump partition found!");
|
||||
return;
|
||||
}
|
||||
ESP_LOGI(TAG, "Found partition '%s' @ %x %d bytes", core_part->label, core_part->address, core_part->size);
|
||||
ESP_COREDUMP_LOGI("Found partition '%s' @ %x %d bytes", core_part->label, core_part->address, core_part->size);
|
||||
s_core_part_start = core_part->address;
|
||||
s_core_part_size = core_part->size;
|
||||
#endif
|
||||
#if CONFIG_ESP32_ENABLE_COREDUMP_TO_UART
|
||||
ESP_LOGI(TAG, "Init core dump to UART");
|
||||
ESP_COREDUMP_LOGI("Init core dump to UART");
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ void esp_set_cpu_freq(void)
|
||||
// wait uart tx finish, otherwise some uart output will be lost
|
||||
uart_tx_wait_idle(CONFIG_CONSOLE_UART_NUM);
|
||||
|
||||
rtc_init_lite(XTAL_AUTO);
|
||||
rtc_init_lite(XTAL_40M);
|
||||
// work around a bug that RTC fast memory may be isolated
|
||||
// from the system after rtc_init_lite
|
||||
SET_PERI_REG_MASK(RTC_CNTL_PWC_REG, RTC_CNTL_FASTMEM_FORCE_NOISO_M);
|
||||
|
||||
@@ -73,9 +73,6 @@ static bool app_cpu_started = false;
|
||||
static void do_global_ctors(void);
|
||||
static void main_task(void* args);
|
||||
extern void app_main(void);
|
||||
#if CONFIG_ESP32_PHY_AUTO_INIT
|
||||
static void do_phy_init();
|
||||
#endif
|
||||
|
||||
extern int _bss_start;
|
||||
extern int _bss_end;
|
||||
@@ -210,17 +207,6 @@ void start_cpu0_default(void)
|
||||
/* init default OS-aware flash access critical section */
|
||||
spi_flash_guard_set(&g_flash_guard_default_ops);
|
||||
|
||||
#if CONFIG_ESP32_PHY_AUTO_INIT
|
||||
nvs_flash_init();
|
||||
do_phy_init();
|
||||
#endif
|
||||
|
||||
#if CONFIG_SW_COEXIST_ENABLE
|
||||
if (coex_init() == ESP_OK) {
|
||||
coexist_set_enable(true);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if CONFIG_ESP32_ENABLE_COREDUMP
|
||||
esp_core_dump_init();
|
||||
#endif
|
||||
@@ -268,39 +254,3 @@ static void main_task(void* args)
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
#if CONFIG_ESP32_PHY_AUTO_INIT
|
||||
static void do_phy_init()
|
||||
{
|
||||
esp_phy_calibration_mode_t calibration_mode = PHY_RF_CAL_PARTIAL;
|
||||
if (rtc_get_reset_reason(0) == DEEPSLEEP_RESET) {
|
||||
calibration_mode = PHY_RF_CAL_NONE;
|
||||
}
|
||||
const esp_phy_init_data_t* init_data = esp_phy_get_init_data();
|
||||
if (init_data == NULL) {
|
||||
ESP_LOGE(TAG, "failed to obtain PHY init data");
|
||||
abort();
|
||||
}
|
||||
esp_phy_calibration_data_t* cal_data =
|
||||
(esp_phy_calibration_data_t*) calloc(sizeof(esp_phy_calibration_data_t), 1);
|
||||
if (cal_data == NULL) {
|
||||
ESP_LOGE(TAG, "failed to allocate memory for RF calibration data");
|
||||
abort();
|
||||
}
|
||||
esp_err_t err = esp_phy_load_cal_data_from_nvs(cal_data);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGW(TAG, "failed to load RF calibration data, falling back to full calibration");
|
||||
calibration_mode = PHY_RF_CAL_FULL;
|
||||
}
|
||||
|
||||
esp_phy_init(init_data, calibration_mode, cal_data);
|
||||
|
||||
if (calibration_mode != PHY_RF_CAL_NONE) {
|
||||
err = esp_phy_store_cal_data_to_nvs(cal_data);
|
||||
} else {
|
||||
err = ESP_OK;
|
||||
}
|
||||
esp_phy_release_init_data(init_data);
|
||||
free(cal_data); // PHY maintains a copy of calibration data, so we can free this
|
||||
}
|
||||
#endif //CONFIG_ESP32_PHY_AUTO_INIT
|
||||
|
||||
|
||||
@@ -82,7 +82,7 @@ void esp_crosscore_int_init() {
|
||||
assert(err == ESP_OK);
|
||||
}
|
||||
|
||||
void esp_crosscore_int_send_yield(int coreId) {
|
||||
void IRAM_ATTR esp_crosscore_int_send_yield(int coreId) {
|
||||
assert(coreId<portNUM_PROCESSORS);
|
||||
//Mark the reason we interrupt the other CPU
|
||||
portENTER_CRITICAL(&reasonSpinlock);
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include "rom/uart.h"
|
||||
#include "soc/cpu.h"
|
||||
#include "soc/rtc_cntl_reg.h"
|
||||
#include "soc/sens_reg.h"
|
||||
#include "soc/dport_reg.h"
|
||||
#include "driver/rtc_io.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
@@ -111,6 +112,13 @@ void IRAM_ATTR esp_deep_sleep_start()
|
||||
// Decide which power domains can be powered down
|
||||
uint32_t pd_flags = get_power_down_flags();
|
||||
|
||||
// Shut down parts of RTC which may have been left enabled by the wireless drivers
|
||||
CLEAR_PERI_REG_MASK(RTC_CNTL_ANA_CONF_REG,
|
||||
RTC_CNTL_CKGEN_I2C_PU | RTC_CNTL_PLL_I2C_PU |
|
||||
RTC_CNTL_RFRX_PBUS_PU | RTC_CNTL_TXRF_I2C_PU);
|
||||
|
||||
SET_PERI_REG_BITS(SENS_SAR_MEAS_WAIT2_REG, SENS_FORCE_XPD_SAR_M, 0, SENS_FORCE_XPD_SAR_S);
|
||||
|
||||
// Configure pins for external wakeup
|
||||
if (s_config.wakeup_triggers & EXT_EVENT0_TRIG_EN) {
|
||||
ext0_wakeup_prepare();
|
||||
|
||||
@@ -193,8 +193,14 @@ void heap_alloc_caps_init() {
|
||||
disable_mem_region((void*)0x3ffe0000, (void*)0x3ffe8000); //knock out ROM data region
|
||||
|
||||
#if CONFIG_BT_ENABLED
|
||||
#if CONFIG_BT_DRAM_RELEASE
|
||||
disable_mem_region((void*)0x3ffb0000, (void*)0x3ffb3000); //knock out BT data region
|
||||
disable_mem_region((void*)0x3ffb8000, (void*)0x3ffbbb28); //knock out BT data region
|
||||
disable_mem_region((void*)0x3ffbdb28, (void*)0x3ffc0000); //knock out BT data region
|
||||
#else
|
||||
disable_mem_region((void*)0x3ffb0000, (void*)0x3ffc0000); //knock out BT data region
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if CONFIG_MEMMAP_TRACEMEM
|
||||
#if CONFIG_MEMMAP_TRACEMEM_TWOBANKS
|
||||
|
||||
@@ -25,6 +25,11 @@ extern "C" {
|
||||
*/
|
||||
esp_err_t coex_init(void);
|
||||
|
||||
/**
|
||||
* @brief De-init software coexist
|
||||
*/
|
||||
void coex_deinit(void);
|
||||
|
||||
/**
|
||||
* @brief Get software coexist enable or not
|
||||
*
|
||||
|
||||
@@ -164,6 +164,14 @@ void esp_deep_sleep_start() __attribute__((noreturn));
|
||||
* Call to this function is equivalent to a call to esp_deep_sleep_enable_timer_wakeup
|
||||
* followed by a call to esp_deep_sleep_start.
|
||||
*
|
||||
* esp_deep_sleep does not shut down WiFi, BT, and higher level protocol
|
||||
* connections gracefully.
|
||||
* Make sure relevant WiFi and BT stack functions are called to close any
|
||||
* connections and deinitialize the peripherals. These include:
|
||||
* - esp_bluedroid_disable
|
||||
* - esp_bt_controller_disable
|
||||
* - esp_wifi_stop
|
||||
*
|
||||
* This function does not return.
|
||||
*
|
||||
* @param time_in_us deep-sleep time, unit: microsecond
|
||||
|
||||
@@ -11,10 +11,10 @@
|
||||
// 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_ERR_H__
|
||||
#define __ESP_ERR_H__
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
@@ -40,15 +40,38 @@ typedef int32_t esp_err_t;
|
||||
|
||||
#define ESP_ERR_WIFI_BASE 0x3000 /*!< Starting number of WiFi error codes */
|
||||
|
||||
void _esp_error_check_failed(esp_err_t rc, const char *file, int line, const char *function, const char *expression) __attribute__((noreturn));
|
||||
|
||||
#ifndef __ASSERT_FUNC
|
||||
/* This won't happen on IDF, which defines __ASSERT_FUNC in assert.h, but it does happen when building on the host which
|
||||
uses /usr/include/assert.h or equivalent.
|
||||
*/
|
||||
#ifdef __ASSERT_FUNCTION
|
||||
#define __ASSERT_FUNC __ASSERT_FUNCTION /* used in glibc assert.h */
|
||||
#else
|
||||
#define __ASSERT_FUNC "??"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Macro which can be used to check the error code,
|
||||
* and terminate the program in case the code is not ESP_OK.
|
||||
* Prints the failed statement to serial output.
|
||||
* Prints the error code, error location, and the failed statement to serial output.
|
||||
*
|
||||
* Disabled if assertions are disabled.
|
||||
*/
|
||||
#define ESP_ERROR_CHECK(x) do { esp_err_t rc = (x); if (rc != ESP_OK) { assert(0 && #x);} } while(0);
|
||||
#ifdef NDEBUG
|
||||
#define ESP_ERROR_CHECK(x) do { (x); } while (0)
|
||||
#else
|
||||
#define ESP_ERROR_CHECK(x) do { \
|
||||
esp_err_t rc = (x); \
|
||||
if (rc != ESP_OK) { \
|
||||
_esp_error_check_failed(rc, __FILE__, __LINE__, \
|
||||
__ASSERT_FUNC, #x); \
|
||||
} \
|
||||
} while(0);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __ESP_ERR_H__ */
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
|
||||
#pragma once
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "esp_err.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
@@ -192,7 +193,7 @@ void esp_phy_release_init_data(const esp_phy_init_data_t* data);
|
||||
* mechanism for loading calibration data, disable
|
||||
* "Initialize PHY in startup code" option in menuconfig and call esp_phy_init
|
||||
* function from the application. For an example usage of esp_phy_init and
|
||||
* this function, see do_phy_init function in cpu_start.c
|
||||
* this function, see esp_phy_store_cal_data_to_nvs function in cpu_start.c
|
||||
*
|
||||
* @param out_cal_data pointer to calibration data structure to be filled with
|
||||
* loaded data.
|
||||
@@ -220,28 +221,39 @@ esp_err_t esp_phy_load_cal_data_from_nvs(esp_phy_calibration_data_t* out_cal_dat
|
||||
esp_err_t esp_phy_store_cal_data_to_nvs(const esp_phy_calibration_data_t* cal_data);
|
||||
|
||||
/**
|
||||
* @brief Initialize PHY module
|
||||
* @brief Initialize PHY and RF module
|
||||
*
|
||||
* PHY module should be initialized in order to use WiFi or BT.
|
||||
* If "Initialize PHY in startup code" option is set in menuconfig,
|
||||
* this function will be called automatically before app_main is called,
|
||||
* using parameters obtained from esp_phy_get_init_data.
|
||||
*
|
||||
* Applications which don't need to enable PHY on every start up should
|
||||
* disable this menuconfig option and call esp_phy_init before calling
|
||||
* esp_wifi_init or esp_bt_controller_init. See do_phy_init function in
|
||||
* cpu_start.c for an example of using this function.
|
||||
* PHY and RF module should be initialized in order to use WiFi or BT.
|
||||
* Now PHY and RF initializing job is done automatically when start WiFi or BT. Users should not
|
||||
* call this API in their application.
|
||||
*
|
||||
* @param init_data PHY parameters. Default set of parameters can
|
||||
* be obtained by calling esp_phy_get_default_init_data
|
||||
* function.
|
||||
* @param mode Calibration mode (Full, partial, or no calibration)
|
||||
* @param[inout] calibration_data
|
||||
* @param is_sleep WiFi wakes up from sleep or not
|
||||
* @return ESP_OK on success.
|
||||
* @return ESP_FAIL on fail.
|
||||
*/
|
||||
esp_err_t esp_phy_rf_init(const esp_phy_init_data_t* init_data,
|
||||
esp_phy_calibration_mode_t mode, esp_phy_calibration_data_t* calibration_data, bool is_sleep);
|
||||
|
||||
/**
|
||||
* @brief De-initialize PHY and RF module
|
||||
*
|
||||
* PHY module should be de-initialized in order to shutdown WiFi or BT.
|
||||
* Now PHY and RF de-initializing job is done automatically when stop WiFi or BT. Users should not
|
||||
* call this API in their application.
|
||||
*
|
||||
* @return ESP_OK on success.
|
||||
*/
|
||||
esp_err_t esp_phy_init(const esp_phy_init_data_t* init_data,
|
||||
esp_phy_calibration_mode_t mode, esp_phy_calibration_data_t* calibration_data);
|
||||
esp_err_t esp_phy_rf_deinit(void);
|
||||
|
||||
/**
|
||||
* @brief Load calibration data from NVS and initialize PHY and RF module
|
||||
*/
|
||||
void esp_phy_load_cal_and_init(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -24,6 +24,17 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
ESP_MAC_WIFI_STA,
|
||||
ESP_MAC_WIFI_SOFTAP,
|
||||
ESP_MAC_BT,
|
||||
ESP_MAC_ETH,
|
||||
} esp_mac_type_t;
|
||||
|
||||
#define TWO_MAC_ADDRESS_FROM_EFUSE 2
|
||||
#define FOUR_MAC_ADDRESS_FROM_EFUSE 4
|
||||
#define NUM_MAC_ADDRESS_FROM_EFUSE CONFIG_NUMBER_OF_MAC_ADDRESS_GENERATED_FROM_EFUSE
|
||||
|
||||
/**
|
||||
* @attention application don't need to call this function anymore. It do nothing and will
|
||||
* be removed in future version.
|
||||
@@ -115,6 +126,47 @@ esp_err_t esp_efuse_read_mac(uint8_t* mac);
|
||||
*/
|
||||
esp_err_t system_efuse_read_mac(uint8_t mac[6]) __attribute__ ((deprecated));
|
||||
|
||||
/**
|
||||
* @brief Read hardware MAC address and set MAC address of the interface.
|
||||
*
|
||||
* This function first reads hardware MAC address from efuse. Then set the MAC address of the interface
|
||||
* including wifi station, wifi softap, bluetooth and ethernet.
|
||||
*
|
||||
* @param mac MAC address of the interface, length: 6 bytes.
|
||||
* @param type type of MAC address, 0:wifi station, 1:wifi softap, 2:bluetooth, 3:ethernet.
|
||||
*
|
||||
* @return ESP_OK on success
|
||||
*/
|
||||
esp_err_t esp_read_mac(uint8_t* mac, esp_mac_type_t type);
|
||||
|
||||
/**
|
||||
* @brief Derive MAC address.
|
||||
*
|
||||
* This function derives a local MAC address from an universal MAC address.
|
||||
* Addresses can either be universally administered addresses or locally administered addresses.
|
||||
* A universally administered address is uniquely assigned to a device by its manufacturer.
|
||||
* The first three octets (in transmission order) identify the organization that issued the identifier
|
||||
* and are known as the Organizationally Unique Identifier (OUI).[4] The remainder of the address
|
||||
* (three octets for MAC-48 and EUI-48 or five for EUI-64) are assigned by that organization in nearly
|
||||
* any manner they please, subject to the constraint of uniqueness. A locally administered address is
|
||||
* assigned to a device by a network administrator, overriding the burned-in address.
|
||||
* Universally administered and locally administered addresses are distinguished by setting
|
||||
* the second-least-significant bit of the first octet of the address. This bit is also referred to
|
||||
* as the U/L bit, short for Universal/Local, which identifies how the address is administered.
|
||||
* If the bit is 0, the address is universally administered. If it is 1, the address is locally administered.
|
||||
* In the example address 06-00-00-00-00-00 the first octet is 06 (hex), the binary form of which is 00000110,
|
||||
* where the second-least-significant bit is 1. Therefore, it is a locally administered address.[7] Consequently,
|
||||
* this bit is 0 in all OUIs.
|
||||
* In ESP32, universal MAC address is generated from the hardware MAC address in efuse.
|
||||
* Local MAC address is derived from the universal MAC address.
|
||||
*
|
||||
* @param dst_mac Derived local MAC address, length: 6 bytes.
|
||||
* @param src_mac Source universal MAC address, length: 6 bytes.
|
||||
*
|
||||
* @return ESP_OK on success
|
||||
*/
|
||||
esp_err_t esp_derive_mac(uint8_t* dst_mac, const uint8_t* src_mac);
|
||||
|
||||
/**
|
||||
* Get SDK version
|
||||
*
|
||||
|
||||
@@ -31,18 +31,6 @@
|
||||
#define ESP_TASK_PRIO_MAX (configMAX_PRIORITIES)
|
||||
#define ESP_TASK_PRIO_MIN (0)
|
||||
|
||||
/* Wifi library task */
|
||||
#define ESP_TASKD_WATCHDOG_PRIO (ESP_TASK_PRIO_MAX - 1)
|
||||
#define ESP_TASKD_WATCHDOG_STACK 2048
|
||||
#define ESP_TASK_WPA2_PRIO (ESP_TASK_PRIO_MAX - 1)
|
||||
#define ESP_TASK_WPA2_STACK 2048
|
||||
#define ESP_TASKD_WIFI_PRIO (ESP_TASK_PRIO_MAX - 2)
|
||||
#define ESP_TASKD_WIFI_STACK 8196
|
||||
#define ESP_TASKD_WIFI_TIMER_PRIO (ESP_TASK_PRIO_MAX - 3)
|
||||
#define ESP_TASKD_WIFI_TIMER_STACK 2048
|
||||
#define ESP_TASK_WPS_PRIO (ESP_TASK_PRIO_MIN + 2)
|
||||
#define ESP_TASK_WPS_STACK 2048
|
||||
|
||||
/* Bt contoller Task */
|
||||
/* controller */
|
||||
#define ESP_TASK_BT_CONTROLLER_PRIO (ESP_TASK_PRIO_MAX - 1)
|
||||
|
||||
@@ -94,14 +94,45 @@ extern "C" {
|
||||
* @brief WiFi stack configuration parameters passed to esp_wifi_init call.
|
||||
*/
|
||||
typedef struct {
|
||||
system_event_handler_t event_handler; /**< WiFi event handler */
|
||||
uint32_t rx_buf_num; /**< WiFi RX buffer number */
|
||||
system_event_handler_t event_handler; /**< WiFi event handler */
|
||||
int static_rx_buf_num; /**< WiFi static RX buffer number */
|
||||
int dynamic_rx_buf_num; /**< WiFi dynamic RX buffer number */
|
||||
int dynamic_tx_buf_num; /**< WiFi dynamic TX buffer number */
|
||||
int ampdu_enable; /**< WiFi AMPDU feature enable flag */
|
||||
int nvs_enable; /**< WiFi NVS flash enable flag */
|
||||
int nano_enable; /**< Nano option for printf/scan family enable flag */
|
||||
int magic; /**< WiFi init magic number, it should be the last field */
|
||||
} wifi_init_config_t;
|
||||
|
||||
#if CONFIG_ESP32_WIFI_AMPDU_ENABLED
|
||||
#define WIFI_AMPDU_ENABLED 1
|
||||
#else
|
||||
#define WIFI_AMPDU_ENABLED 0
|
||||
#endif
|
||||
|
||||
#if CONFIG_ESP32_WIFI_NVS_ENABLED
|
||||
#define WIFI_NVS_ENABLED 1
|
||||
#else
|
||||
#define WIFI_NVS_ENABLED 0
|
||||
#endif
|
||||
|
||||
#if CONFIG_NEWLIB_NANO_FORMAT
|
||||
#define WIFI_NANO_FORMAT_ENABLED 1
|
||||
#else
|
||||
#define WIFI_NANO_FORMAT_ENABLED 0
|
||||
#endif
|
||||
|
||||
#define WIFI_INIT_CONFIG_MAGIC 0x1F2F3F4F
|
||||
#ifdef CONFIG_WIFI_ENABLED
|
||||
#define WIFI_INIT_CONFIG_DEFAULT() { \
|
||||
.event_handler = &esp_event_send, \
|
||||
.rx_buf_num = CONFIG_ESP32_WIFI_RX_BUFFER_NUM, \
|
||||
.static_rx_buf_num = CONFIG_ESP32_WIFI_STATIC_RX_BUFFER_NUM,\
|
||||
.dynamic_rx_buf_num = CONFIG_ESP32_WIFI_DYNAMIC_RX_BUFFER_NUM,\
|
||||
.dynamic_tx_buf_num = CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER_NUM,\
|
||||
.ampdu_enable = WIFI_AMPDU_ENABLED,\
|
||||
.nvs_enable = WIFI_NVS_ENABLED,\
|
||||
.nano_enable = WIFI_NANO_FORMAT_ENABLED,\
|
||||
.magic = WIFI_INIT_CONFIG_MAGIC\
|
||||
};
|
||||
#else
|
||||
#define WIFI_INIT_CONFIG_DEFAULT #error Wifi is disabled in config, WIFI_INIT_CONFIG_DEFAULT will not work
|
||||
@@ -113,8 +144,11 @@ typedef struct {
|
||||
* WiFi NVS structure etc, this WiFi also start WiFi task
|
||||
*
|
||||
* @attention 1. This API must be called before all other WiFi API can be called
|
||||
* @attention 2. event_handler field in cfg should be set to a valid event handler function.
|
||||
* In most cases, use the WIFI_INIT_CONFIG_DEFAULT macro which sets esp_event_send().
|
||||
* @attention 2. Always use WIFI_INIT_CONFIG_DEFAULT macro to init the config to default values, this can
|
||||
* guarantee all the fields got correct value when more fields are added into wifi_init_config_t
|
||||
* in future release. If you want to set your owner initial values, overwrite the default values
|
||||
* which are set by WIFI_INIT_CONFIG_DEFAULT, please be notified that the field 'magic' of
|
||||
* wifi_init_config_t should always be WIFI_INIT_CONFIG_MAGIC!
|
||||
*
|
||||
* @param config provide WiFi init configuration
|
||||
*
|
||||
@@ -130,6 +164,7 @@ esp_err_t esp_wifi_init(wifi_init_config_t *config);
|
||||
* Free all resource allocated in esp_wifi_init and stop WiFi task
|
||||
*
|
||||
* @attention 1. This API should be called if you want to remove WiFi driver from the system
|
||||
* @attention 2. This API can not be called yet and will be done in the future.
|
||||
*
|
||||
* @return ESP_OK: succeed
|
||||
*/
|
||||
@@ -421,6 +456,7 @@ esp_err_t esp_wifi_get_bandwidth(wifi_interface_t ifx, wifi_bandwidth_t *bw);
|
||||
* @brief Set primary/secondary channel of ESP32
|
||||
*
|
||||
* @attention 1. This is a special API for sniffer
|
||||
* @attention 2. This API should be called after esp_wifi_start() or esp_wifi_set_promiscuous()
|
||||
*
|
||||
* @param primary for HT20, primary is the channel number, for HT40, primary is the primary channel
|
||||
* @param second for HT20, second is ignored, for HT40, second is the second channel
|
||||
|
||||
@@ -36,16 +36,6 @@ static inline void *get_sp()
|
||||
return sp;
|
||||
}
|
||||
|
||||
/* Return true if the CPU is in an interrupt context
|
||||
(PS.UM == 0)
|
||||
*/
|
||||
static inline bool cpu_in_interrupt_context(void)
|
||||
{
|
||||
uint32_t ps;
|
||||
RSR(PS, ps);
|
||||
return (ps & PS_UM) == 0;
|
||||
}
|
||||
|
||||
/* Functions to set page attributes for Region Protection option in the CPU.
|
||||
* See Xtensa ISA Reference manual for explanation of arguments (section 4.6.3.2).
|
||||
*/
|
||||
|
||||
@@ -1035,11 +1035,27 @@
|
||||
#define DPORT_WIFI_CLK_EN_V 0xFFFFFFFF
|
||||
#define DPORT_WIFI_CLK_EN_S 0
|
||||
|
||||
/* Mask for all Wifi clock bits - 0, 1, 2, 3, 6, 7, 8, 9, 10, 15 */
|
||||
#define DPORT_WIFI_CLK_WIFI_EN 0x000007cf
|
||||
#define DPORT_WIFI_CLK_WIFI_EN_M ((DPORT_WIFI_CLK_WIFI_EN_V)<<(DPORT_WIFI_CLK_WIFI_EN_S))
|
||||
#define DPORT_WIFI_CLK_WIFI_EN_V 0x1FF
|
||||
#define DPORT_WIFI_CLK_WIFI_EN_S 0
|
||||
/* Mask for all Bluetooth clock bits - 11, 16, 17 */
|
||||
#define DPORT_WIFI_CLK_BT_EN 0x61
|
||||
#define DPORT_WIFI_CLK_BT_EN_M ((DPORT_WIFI_CLK_BT_EN_V)<<(DPORT_WIFI_CLK_BT_EN_S))
|
||||
#define DPORT_WIFI_CLK_BT_EN_V 0x61
|
||||
#define DPORT_WIFI_CLK_BT_EN_S 11
|
||||
/* Remaining single bit clock masks */
|
||||
#define DPORT_WIFI_CLK_SDIOSLAVE_EN BIT(4)
|
||||
#define DPORT_WIFI_CLK_SDIO_HOST_EN BIT(13)
|
||||
#define DPORT_WIFI_CLK_EMAC_EN BIT(14)
|
||||
#define DPORT_WIFI_CLK_RNG_EN BIT(15)
|
||||
|
||||
#define DPORT_CORE_RST_EN_REG (DR_REG_DPORT_BASE + 0x0D0)
|
||||
/* DPORT_CORE_RST : R/W ;bitpos:[31:0] ;default: 32'h0 ; */
|
||||
/*description: */
|
||||
#define DPROT_RW_BTLP_RST (BIT(10))
|
||||
#define DPROT_RW_BTMAC_RST (BIT(9))
|
||||
#define DPORT_RW_BTLP_RST (BIT(10))
|
||||
#define DPORT_RW_BTMAC_RST (BIT(9))
|
||||
#define DPORT_MACPWR_RST (BIT(8))
|
||||
#define DPORT_EMAC_RST (BIT(7))
|
||||
#define DPORT_SDIO_HOST_RST (BIT(6))
|
||||
|
||||
@@ -268,10 +268,10 @@
|
||||
* 2 1 extern level
|
||||
* 3 1 extern level
|
||||
* 4 1 extern level WBB
|
||||
* 5 1 extern level BT Controller
|
||||
* 5 1 extern level BT/BLE Controller
|
||||
* 6 1 timer FreeRTOS Tick(L1) FreeRTOS Tick(L1)
|
||||
* 7 1 software Reserved Reserved
|
||||
* 8 1 extern level BLE Controller
|
||||
* 8 1 extern level BT/BLE BB(RX/TX)
|
||||
* 9 1 extern level
|
||||
* 10 1 extern edge Internal Timer
|
||||
* 11 3 profiling
|
||||
|
||||
@@ -686,7 +686,7 @@ esp_err_t IRAM_ATTR esp_intr_disable(intr_handle_t handle)
|
||||
}
|
||||
|
||||
|
||||
void esp_intr_noniram_disable()
|
||||
void IRAM_ATTR esp_intr_noniram_disable()
|
||||
{
|
||||
int oldint;
|
||||
int cpu=xPortGetCoreID();
|
||||
@@ -705,7 +705,7 @@ void esp_intr_noniram_disable()
|
||||
non_iram_int_disabled[cpu]=oldint&non_iram_int_mask[cpu];
|
||||
}
|
||||
|
||||
void esp_intr_noniram_enable()
|
||||
void IRAM_ATTR esp_intr_noniram_enable()
|
||||
{
|
||||
int cpu=xPortGetCoreID();
|
||||
int intmask=non_iram_int_disabled[cpu];
|
||||
|
||||
@@ -80,9 +80,15 @@ SECTIONS
|
||||
*(.iram1 .iram1.*)
|
||||
*libfreertos.a:(.literal .text .literal.* .text.*)
|
||||
*libesp32.a:panic.o(.literal .text .literal.* .text.*)
|
||||
*libesp32.a:core_dump.o(.literal .text .literal.* .text.*)
|
||||
*libphy.a:(.literal .text .literal.* .text.*)
|
||||
*librtc.a:(.literal .text .literal.* .text.*)
|
||||
*libpp.a:(.literal .text .literal.* .text.*)
|
||||
*librtc_clk.a:(.literal .text .literal.* .text.*)
|
||||
*libpp.a:pp.o(.literal .text .literal.* .text.*)
|
||||
*libpp.a:lmac.o(.literal .text .literal.* .text.*)
|
||||
*libpp.a:wdev.o(.literal .text .literal.* .text.*)
|
||||
*libcore.a:ets_timer.o(.literal .text .literal.* .text.*)
|
||||
*libnet80211.a:ieee80211_misc.o(.literal .text .literal.* .text.*)
|
||||
*libhal.a:(.literal .text .literal.* .text.*)
|
||||
*libcoexist.a:(.literal .text .literal.* .text.*)
|
||||
_iram_text_end = ABSOLUTE(.);
|
||||
|
||||
Submodule components/esp32/lib updated: fc92f2e5bc...ea786aa95d
@@ -34,6 +34,7 @@
|
||||
#include "esp_attr.h"
|
||||
#include "esp_err.h"
|
||||
#include "esp_core_dump.h"
|
||||
#include "esp_spi_flash.h"
|
||||
|
||||
/*
|
||||
Panic handlers; these get called when an unhandled exception occurs or the assembly-level
|
||||
@@ -107,11 +108,8 @@ void __attribute__((weak)) vApplicationStackOverflowHook( TaskHandle_t xTask, s
|
||||
|
||||
static bool abort_called;
|
||||
|
||||
void abort()
|
||||
static __attribute__((noreturn)) inline void invoke_abort()
|
||||
{
|
||||
#if !CONFIG_ESP32_PANIC_SILENT_REBOOT
|
||||
ets_printf("abort() was called at PC 0x%08x\n", (intptr_t)__builtin_return_address(0) - 3);
|
||||
#endif
|
||||
abort_called = true;
|
||||
while(1) {
|
||||
__asm__ ("break 0,0");
|
||||
@@ -119,6 +117,14 @@ void abort()
|
||||
}
|
||||
}
|
||||
|
||||
void abort()
|
||||
{
|
||||
#if !CONFIG_ESP32_PANIC_SILENT_REBOOT
|
||||
ets_printf("abort() was called at PC 0x%08x\n", (intptr_t)__builtin_return_address(0) - 3);
|
||||
#endif
|
||||
invoke_abort();
|
||||
}
|
||||
|
||||
|
||||
static const char *edesc[] = {
|
||||
"IllegalInstruction", "Syscall", "InstructionFetchError", "LoadStoreError",
|
||||
@@ -267,7 +273,7 @@ static void reconfigureAllWdts()
|
||||
TIMERG1.wdt_wprotect = 0;
|
||||
}
|
||||
|
||||
#if CONFIG_ESP32_PANIC_GDBSTUB || CONFIG_ESP32_PANIC_PRINT_HALT
|
||||
#if CONFIG_ESP32_PANIC_GDBSTUB || CONFIG_ESP32_PANIC_PRINT_HALT || CONFIG_ESP32_ENABLE_COREDUMP
|
||||
/*
|
||||
This disables all the watchdogs for when we call the gdbstub.
|
||||
*/
|
||||
@@ -367,11 +373,15 @@ static void commonErrorHandler(XtExcFrame *frame)
|
||||
panicPutStr("Entering gdb stub now.\r\n");
|
||||
esp_gdbstub_panic_handler(frame);
|
||||
#else
|
||||
#if CONFIG_ESP32_ENABLE_COREDUMP
|
||||
disableAllWdts();
|
||||
#if CONFIG_ESP32_ENABLE_COREDUMP_TO_FLASH
|
||||
esp_core_dump_to_flash(frame);
|
||||
#endif
|
||||
#if CONFIG_ESP32_ENABLE_COREDUMP_TO_UART && !CONFIG_ESP32_PANIC_SILENT_REBOOT
|
||||
esp_core_dump_to_uart(frame);
|
||||
#endif
|
||||
reconfigureAllWdts();
|
||||
#endif
|
||||
#if CONFIG_ESP32_PANIC_PRINT_REBOOT || CONFIG_ESP32_PANIC_SILENT_REBOOT
|
||||
panicPutStr("Rebooting...\r\n");
|
||||
@@ -437,4 +447,11 @@ void esp_clear_watchpoint(int no)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void _esp_error_check_failed(esp_err_t rc, const char *file, int line, const char *function, const char *expression)
|
||||
{
|
||||
ets_printf("ESP_ERROR_CHECK failed: esp_err_t 0x%x at 0x%08x\n", rc, (intptr_t)__builtin_return_address(0) - 3);
|
||||
if (spi_flash_cache_enabled()) { // strings may be in flash cache
|
||||
ets_printf("file: \"%s\" line %d\nfunc: %s\nexpression: %s\n", file, line, function, expression);
|
||||
}
|
||||
invoke_abort();
|
||||
}
|
||||
|
||||
@@ -17,7 +17,10 @@
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <sys/lock.h>
|
||||
|
||||
#include "rom/ets_sys.h"
|
||||
#include "rom/rtc.h"
|
||||
#include "soc/dport_reg.h"
|
||||
|
||||
#include "esp_err.h"
|
||||
@@ -25,30 +28,71 @@
|
||||
#include "esp_system.h"
|
||||
#include "esp_log.h"
|
||||
#include "nvs.h"
|
||||
#include "nvs_flash.h"
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#ifdef CONFIG_PHY_ENABLED
|
||||
#include "phy.h"
|
||||
#include "phy_init_data.h"
|
||||
#include "rtc.h"
|
||||
#include "esp_coexist.h"
|
||||
|
||||
static const char* TAG = "phy_init";
|
||||
|
||||
/* Count value to indicate if there is peripheral that has initialized PHY and RF */
|
||||
static int s_phy_rf_init_count = 0;
|
||||
static bool s_mac_rst_flag = false;
|
||||
|
||||
esp_err_t esp_phy_init(const esp_phy_init_data_t* init_data,
|
||||
esp_phy_calibration_mode_t mode, esp_phy_calibration_data_t* calibration_data)
|
||||
static _lock_t s_phy_rf_init_lock;
|
||||
|
||||
esp_err_t esp_phy_rf_init(const esp_phy_init_data_t* init_data,
|
||||
esp_phy_calibration_mode_t mode, esp_phy_calibration_data_t* calibration_data, bool is_sleep)
|
||||
{
|
||||
assert(init_data);
|
||||
assert(calibration_data);
|
||||
assert((s_phy_rf_init_count <= 1) && (s_phy_rf_init_count >= 0));
|
||||
|
||||
REG_SET_BIT(DPORT_CORE_RST_EN_REG, DPORT_MAC_RST);
|
||||
REG_CLR_BIT(DPORT_CORE_RST_EN_REG, DPORT_MAC_RST);
|
||||
// Enable WiFi peripheral clock
|
||||
SET_PERI_REG_MASK(DPORT_WIFI_CLK_EN_REG, 0x87cf);
|
||||
ESP_LOGV(TAG, "register_chipv7_phy, init_data=%p, cal_data=%p, mode=%d",
|
||||
init_data, calibration_data, mode);
|
||||
phy_set_wifi_mode_only(0);
|
||||
register_chipv7_phy(init_data, calibration_data, mode);
|
||||
coex_bt_high_prio();
|
||||
_lock_acquire(&s_phy_rf_init_lock);
|
||||
if (s_phy_rf_init_count == 0) {
|
||||
if (is_sleep == false) {
|
||||
if (s_mac_rst_flag == false) {
|
||||
s_mac_rst_flag = true;
|
||||
REG_SET_BIT(DPORT_CORE_RST_EN_REG, DPORT_MAC_RST);
|
||||
REG_CLR_BIT(DPORT_CORE_RST_EN_REG, DPORT_MAC_RST);
|
||||
}
|
||||
}
|
||||
// Enable WiFi peripheral clock
|
||||
SET_PERI_REG_MASK(DPORT_WIFI_CLK_EN_REG, DPORT_WIFI_CLK_WIFI_EN | DPORT_WIFI_CLK_RNG_EN);
|
||||
ESP_LOGV(TAG, "register_chipv7_phy, init_data=%p, cal_data=%p, mode=%d",
|
||||
init_data, calibration_data, mode);
|
||||
phy_set_wifi_mode_only(0);
|
||||
register_chipv7_phy(init_data, calibration_data, mode);
|
||||
coex_bt_high_prio();
|
||||
} else {
|
||||
#if CONFIG_SW_COEXIST_ENABLE
|
||||
coex_init();
|
||||
#endif
|
||||
}
|
||||
s_phy_rf_init_count++;
|
||||
_lock_release(&s_phy_rf_init_lock);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_phy_rf_deinit(void)
|
||||
{
|
||||
assert((s_phy_rf_init_count <= 2) && (s_phy_rf_init_count >= 1));
|
||||
|
||||
_lock_acquire(&s_phy_rf_init_lock);
|
||||
if (s_phy_rf_init_count == 1) {
|
||||
// Disable PHY and RF.
|
||||
phy_close_rf();
|
||||
// Disable WiFi peripheral clock. Do not disable clock for hardware RNG
|
||||
CLEAR_PERI_REG_MASK(DPORT_WIFI_CLK_EN_REG, DPORT_WIFI_CLK_WIFI_EN);
|
||||
} else {
|
||||
#if CONFIG_SW_COEXIST_ENABLE
|
||||
coex_deinit();
|
||||
#endif
|
||||
}
|
||||
s_phy_rf_init_count--;
|
||||
_lock_release(&s_phy_rf_init_lock);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
@@ -220,4 +264,43 @@ static esp_err_t store_cal_data_to_nvs_handle(nvs_handle handle,
|
||||
return err;
|
||||
}
|
||||
|
||||
void esp_phy_load_cal_and_init(void)
|
||||
{
|
||||
#ifdef CONFIG_ESP32_PHY_CALIBRATION_AND_DATA_STORAGE
|
||||
nvs_flash_init();
|
||||
esp_phy_calibration_mode_t calibration_mode = PHY_RF_CAL_PARTIAL;
|
||||
if (rtc_get_reset_reason(0) == DEEPSLEEP_RESET) {
|
||||
calibration_mode = PHY_RF_CAL_NONE;
|
||||
}
|
||||
const esp_phy_init_data_t* init_data = esp_phy_get_init_data();
|
||||
if (init_data == NULL) {
|
||||
ESP_LOGE(TAG, "failed to obtain PHY init data");
|
||||
abort();
|
||||
}
|
||||
esp_phy_calibration_data_t* cal_data =
|
||||
(esp_phy_calibration_data_t*) calloc(sizeof(esp_phy_calibration_data_t), 1);
|
||||
if (cal_data == NULL) {
|
||||
ESP_LOGE(TAG, "failed to allocate memory for RF calibration data");
|
||||
abort();
|
||||
}
|
||||
esp_err_t err = esp_phy_load_cal_data_from_nvs(cal_data);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGW(TAG, "failed to load RF calibration data, falling back to full calibration");
|
||||
calibration_mode = PHY_RF_CAL_FULL;
|
||||
}
|
||||
|
||||
esp_phy_rf_init(init_data, calibration_mode, cal_data, false);
|
||||
|
||||
if (calibration_mode != PHY_RF_CAL_NONE && err != ESP_OK) {
|
||||
err = esp_phy_store_cal_data_to_nvs(cal_data);
|
||||
} else {
|
||||
err = ESP_OK;
|
||||
}
|
||||
esp_phy_release_init_data(init_data);
|
||||
free(cal_data); // PHY maintains a copy of calibration data, so we can free this
|
||||
#else
|
||||
esp_phy_rf_init(NULL, PHY_RF_CAL_NONE, NULL, false);
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif // CONFIG_PHY_ENABLED
|
||||
|
||||
@@ -135,6 +135,10 @@ void rtc_slp_prep_lite(uint32_t deep_slp, uint32_t cpu_lp_mode);
|
||||
*/
|
||||
uint32_t rtc_sleep(uint32_t cycles_h, uint32_t cycles_l, uint32_t wakeup_opt, uint32_t reject_opt);
|
||||
|
||||
/**
|
||||
* @brief Shutdown PHY and RF. TODO: convert this function to another one.
|
||||
*/
|
||||
void phy_close_rf(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -12,6 +12,8 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "esp_system.h"
|
||||
#include "esp_attr.h"
|
||||
#include "esp_wifi.h"
|
||||
@@ -72,6 +74,87 @@ esp_err_t esp_efuse_read_mac(uint8_t* mac)
|
||||
|
||||
esp_err_t system_efuse_read_mac(uint8_t mac[6]) __attribute__((alias("esp_efuse_read_mac")));
|
||||
|
||||
esp_err_t esp_derive_mac(uint8_t* dst_mac, const uint8_t* src_mac)
|
||||
{
|
||||
uint8_t idx;
|
||||
|
||||
if (dst_mac == NULL || src_mac == NULL) {
|
||||
ESP_LOGE(TAG, "mac address param is NULL");
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
memcpy(dst_mac, src_mac, 6);
|
||||
for (idx = 0; idx < 64; idx++) {
|
||||
dst_mac[0] = src_mac[0] | 0x02;
|
||||
dst_mac[0] ^= idx << 2;
|
||||
|
||||
if (memcmp(dst_mac, src_mac, 6)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_read_mac(uint8_t* mac, esp_mac_type_t type)
|
||||
{
|
||||
uint8_t efuse_mac[6];
|
||||
|
||||
if (mac == NULL) {
|
||||
ESP_LOGE(TAG, "mac address param is NULL");
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
if (type < ESP_MAC_WIFI_STA || type > ESP_MAC_ETH) {
|
||||
ESP_LOGE(TAG, "mac type is incorrect");
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
_Static_assert(NUM_MAC_ADDRESS_FROM_EFUSE == FOUR_MAC_ADDRESS_FROM_EFUSE \
|
||||
|| NUM_MAC_ADDRESS_FROM_EFUSE == TWO_MAC_ADDRESS_FROM_EFUSE, \
|
||||
"incorrect NUM_MAC_ADDRESS_FROM_EFUSE value");
|
||||
|
||||
esp_efuse_read_mac(efuse_mac);
|
||||
|
||||
switch (type) {
|
||||
case ESP_MAC_WIFI_STA:
|
||||
memcpy(mac, efuse_mac, 6);
|
||||
break;
|
||||
case ESP_MAC_WIFI_SOFTAP:
|
||||
if (NUM_MAC_ADDRESS_FROM_EFUSE == FOUR_MAC_ADDRESS_FROM_EFUSE) {
|
||||
memcpy(mac, efuse_mac, 6);
|
||||
mac[5] += 1;
|
||||
}
|
||||
else if (NUM_MAC_ADDRESS_FROM_EFUSE == TWO_MAC_ADDRESS_FROM_EFUSE) {
|
||||
esp_derive_mac(mac, efuse_mac);
|
||||
}
|
||||
break;
|
||||
case ESP_MAC_BT:
|
||||
memcpy(mac, efuse_mac, 6);
|
||||
if (NUM_MAC_ADDRESS_FROM_EFUSE == FOUR_MAC_ADDRESS_FROM_EFUSE) {
|
||||
mac[5] += 2;
|
||||
}
|
||||
else if (NUM_MAC_ADDRESS_FROM_EFUSE == TWO_MAC_ADDRESS_FROM_EFUSE) {
|
||||
mac[5] += 1;
|
||||
}
|
||||
break;
|
||||
case ESP_MAC_ETH:
|
||||
if (NUM_MAC_ADDRESS_FROM_EFUSE == FOUR_MAC_ADDRESS_FROM_EFUSE) {
|
||||
memcpy(mac, efuse_mac, 6);
|
||||
mac[5] += 3;
|
||||
}
|
||||
else if (NUM_MAC_ADDRESS_FROM_EFUSE == TWO_MAC_ADDRESS_FROM_EFUSE) {
|
||||
efuse_mac[5] += 1;
|
||||
esp_derive_mac(mac, efuse_mac);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ESP_LOGW(TAG, "incorrect mac type");
|
||||
break;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
void esp_restart_noos() __attribute__ ((noreturn));
|
||||
|
||||
@@ -132,7 +215,7 @@ void IRAM_ATTR esp_restart_noos()
|
||||
DPORT_BB_RST | DPORT_FE_RST | DPORT_MAC_RST |
|
||||
DPORT_BT_RST | DPORT_BTMAC_RST | DPORT_SDIO_RST |
|
||||
DPORT_SDIO_HOST_RST | DPORT_EMAC_RST | DPORT_MACPWR_RST |
|
||||
DPROT_RW_BTMAC_RST | DPROT_RW_BTLP_RST);
|
||||
DPORT_RW_BTMAC_RST | DPORT_RW_BTLP_RST);
|
||||
REG_WRITE(DPORT_CORE_RST_EN_REG, 0);
|
||||
|
||||
// Reset timer/spi/uart
|
||||
|
||||
@@ -12,15 +12,15 @@ import array
|
||||
import errno
|
||||
import base64
|
||||
|
||||
idf_path = os.getenv('IDF_PATH')
|
||||
if idf_path:
|
||||
sys.path.insert(0, os.path.join(idf_path, 'components', 'esptool_py', 'esptool'))
|
||||
|
||||
try:
|
||||
import esptool
|
||||
except ImportError:
|
||||
idf_path = os.getenv('IDF_PATH')
|
||||
if idf_path is None:
|
||||
print "Esptool is not found! Install it or set proper $IDF_PATH in environment."
|
||||
sys.exit(2)
|
||||
sys.path.append('%s/components/esptool_py/esptool' % idf_path)
|
||||
import esptool
|
||||
print "Esptool is not found! Set proper $IDF_PATH in environment."
|
||||
sys.exit(2)
|
||||
|
||||
__version__ = "0.1-dev"
|
||||
|
||||
|
||||
@@ -75,6 +75,7 @@ struct emac_config_data {
|
||||
bool emac_flow_ctrl_enable;
|
||||
bool emac_flow_ctrl_partner_support;
|
||||
eth_phy_get_partner_pause_enable_func emac_phy_get_partner_pause_enable;
|
||||
eth_phy_power_enable_func emac_phy_power_enable;
|
||||
};
|
||||
|
||||
enum emac_post_type {
|
||||
|
||||
@@ -75,8 +75,7 @@ esp_err_t emac_post(emac_sig_t sig, emac_par_t par);
|
||||
|
||||
static void emac_macaddr_init(void)
|
||||
{
|
||||
esp_efuse_read_mac(&(emac_config.macaddr[0]));
|
||||
emac_config.macaddr[5] = emac_config.macaddr[5] + 3;
|
||||
esp_read_mac(&(emac_config.macaddr[0]), ESP_MAC_ETH);
|
||||
}
|
||||
|
||||
void esp_eth_get_mac(uint8_t mac[6])
|
||||
@@ -225,6 +224,7 @@ static void emac_set_user_config_data(eth_config_t *config )
|
||||
emac_config.emac_flow_ctrl_enable = false;
|
||||
#endif
|
||||
emac_config.emac_phy_get_partner_pause_enable = config->phy_get_partner_pause_enable;
|
||||
emac_config.emac_phy_power_enable = config->phy_power_enable;
|
||||
}
|
||||
|
||||
static void emac_enable_intr()
|
||||
@@ -291,6 +291,11 @@ static esp_err_t emac_verify_args(void)
|
||||
ret = ESP_FAIL;
|
||||
}
|
||||
|
||||
if(emac_config.emac_phy_power_enable == NULL) {
|
||||
ESP_LOGE(TAG, "phy power enable func is null");
|
||||
ret = ESP_FAIL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -537,6 +542,10 @@ static void emac_check_phy_init(void)
|
||||
} else {
|
||||
REG_CLR_BIT(EMAC_GMACCONFIG_REG, EMAC_GMACFESPEED);
|
||||
}
|
||||
#if CONFIG_EMAC_L2_TO_L3_RX_BUF_MODE
|
||||
emac_disable_flowctrl();
|
||||
emac_config.emac_flow_ctrl_partner_support = false;
|
||||
#else
|
||||
if (emac_config.emac_flow_ctrl_enable == true) {
|
||||
if (emac_config.emac_phy_get_partner_pause_enable() == true && emac_config.emac_phy_get_duplex_mode() == ETH_MDOE_FULLDUPLEX) {
|
||||
emac_enable_flowctrl();
|
||||
@@ -549,6 +558,7 @@ static void emac_check_phy_init(void)
|
||||
emac_disable_flowctrl();
|
||||
emac_config.emac_flow_ctrl_partner_support = false;
|
||||
}
|
||||
#endif
|
||||
emac_mac_enable_txrx();
|
||||
}
|
||||
static void emac_process_link_updown(bool link_status)
|
||||
@@ -938,6 +948,8 @@ esp_err_t esp_eth_init(eth_config_t *config)
|
||||
emac_set_user_config_data(config);
|
||||
}
|
||||
|
||||
emac_config.emac_phy_power_enable(true);
|
||||
|
||||
ret = emac_verify_args();
|
||||
|
||||
if (ret != ESP_OK) {
|
||||
|
||||
@@ -80,7 +80,7 @@ typedef void (*eth_phy_func)(void);
|
||||
typedef esp_err_t (*eth_tcpip_input_func)(void *buffer, uint16_t len, void *eb);
|
||||
typedef void (*eth_gpio_config_func)(void);
|
||||
typedef bool (*eth_phy_get_partner_pause_enable_func)(void);
|
||||
|
||||
typedef void (*eth_phy_power_enable_func)(bool enable);
|
||||
|
||||
/**
|
||||
* @brief ethernet configuration
|
||||
@@ -98,6 +98,7 @@ typedef struct {
|
||||
eth_gpio_config_func gpio_config; /*!< gpio config func */
|
||||
bool flow_ctrl_enable; /*!< flag of flow ctrl enable */
|
||||
eth_phy_get_partner_pause_enable_func phy_get_partner_pause_enable; /*!< get partner pause enable */
|
||||
eth_phy_power_enable_func phy_power_enable; /*!< enable or disable phy power */
|
||||
|
||||
} eth_config_t;
|
||||
|
||||
|
||||
@@ -152,7 +152,7 @@ static int fat_mode_conv(int m)
|
||||
}
|
||||
if ((m & O_CREAT) && (m & O_EXCL)) {
|
||||
res |= FA_CREATE_NEW;
|
||||
} else if (m & O_CREAT) {
|
||||
} else if ((m & O_CREAT) && (m & O_TRUNC)) {
|
||||
res |= FA_CREATE_ALWAYS;
|
||||
} else if (m & O_APPEND) {
|
||||
res |= FA_OPEN_ALWAYS;
|
||||
|
||||
@@ -39,14 +39,19 @@ esp_err_t esp_vfs_fat_sdmmc_mount(const char* base_path,
|
||||
sdmmc_host_init();
|
||||
|
||||
// enable card slot
|
||||
sdmmc_host_init_slot(host_config->slot, slot_config);
|
||||
esp_err_t err = sdmmc_host_init_slot(host_config->slot, slot_config);
|
||||
if (err != ESP_OK) {
|
||||
return err;
|
||||
}
|
||||
|
||||
s_card = malloc(sizeof(sdmmc_card_t));
|
||||
if (s_card == NULL) {
|
||||
return ESP_ERR_NO_MEM;
|
||||
err = ESP_ERR_NO_MEM;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
// probe and initialize card
|
||||
esp_err_t err = sdmmc_card_init(host_config, s_card);
|
||||
err = sdmmc_card_init(host_config, s_card);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGD(TAG, "sdmmc_card_init failed 0x(%x)", err);
|
||||
goto fail;
|
||||
@@ -104,6 +109,7 @@ esp_err_t esp_vfs_fat_sdmmc_mount(const char* base_path,
|
||||
return ESP_OK;
|
||||
|
||||
fail:
|
||||
sdmmc_host_deinit();
|
||||
free(workbuf);
|
||||
esp_vfs_unregister(base_path);
|
||||
free(s_card);
|
||||
|
||||
@@ -52,6 +52,25 @@ static void create_file_with_text(const char* name, const char* text)
|
||||
TEST_ASSERT_EQUAL(0, fclose(f));
|
||||
}
|
||||
|
||||
TEST_CASE("Mount fails cleanly without card inserted", "[fatfs][ignore]")
|
||||
{
|
||||
HEAP_SIZE_CAPTURE();
|
||||
sdmmc_host_t host = SDMMC_HOST_DEFAULT();
|
||||
sdmmc_slot_config_t slot_config = SDMMC_SLOT_CONFIG_DEFAULT();
|
||||
esp_vfs_fat_sdmmc_mount_config_t mount_config = {
|
||||
.format_if_mount_failed = false,
|
||||
.max_files = 5
|
||||
};
|
||||
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
printf("Initializing card, attempt %d ", i);
|
||||
esp_err_t err = esp_vfs_fat_sdmmc_mount("/sdcard", &host, &slot_config, &mount_config, NULL);
|
||||
printf(" err=%d\n", err);
|
||||
TEST_ESP_ERR(ESP_FAIL, err);
|
||||
}
|
||||
HEAP_SIZE_CHECK(0);
|
||||
}
|
||||
|
||||
TEST_CASE("can create and write file on sd card", "[fatfs][ignore]")
|
||||
{
|
||||
HEAP_SIZE_CAPTURE();
|
||||
@@ -69,6 +88,55 @@ TEST_CASE("can create and write file on sd card", "[fatfs][ignore]")
|
||||
HEAP_SIZE_CHECK(0);
|
||||
}
|
||||
|
||||
TEST_CASE("overwrite and append file on sd card", "[fatfs][ignore]")
|
||||
{
|
||||
HEAP_SIZE_CAPTURE();
|
||||
|
||||
sdmmc_host_t host = SDMMC_HOST_DEFAULT();
|
||||
sdmmc_slot_config_t slot_config = SDMMC_SLOT_CONFIG_DEFAULT();
|
||||
esp_vfs_fat_sdmmc_mount_config_t mount_config = {
|
||||
.format_if_mount_failed = true,
|
||||
.max_files = 5
|
||||
};
|
||||
TEST_ESP_OK(esp_vfs_fat_sdmmc_mount("/sdcard", &host, &slot_config, &mount_config, NULL));
|
||||
|
||||
/* Create new file with 'aaaa' */
|
||||
const char *NAME = "/sdcard/hello.txt";
|
||||
create_file_with_text(NAME, "aaaa");
|
||||
|
||||
/* Append 'bbbb' to file */
|
||||
FILE *f_a = fopen(NAME, "a");
|
||||
TEST_ASSERT_NOT_NULL(f_a);
|
||||
TEST_ASSERT_NOT_EQUAL(EOF, fputs("bbbb", f_a));
|
||||
TEST_ASSERT_EQUAL(0, fclose(f_a));
|
||||
|
||||
/* Read back 8 bytes from file, verify it's 'aaaabbbb' */
|
||||
char buf[10] = { 0 };
|
||||
FILE *f_r = fopen(NAME, "r");
|
||||
TEST_ASSERT_NOT_NULL(f_r);
|
||||
TEST_ASSERT_EQUAL(8, fread(buf, 1, 8, f_r));
|
||||
TEST_ASSERT_EQUAL_STRING_LEN("aaaabbbb", buf, 8);
|
||||
|
||||
/* Be sure we're at end of file */
|
||||
TEST_ASSERT_EQUAL(0, fread(buf, 1, 8, f_r));
|
||||
|
||||
TEST_ASSERT_EQUAL(0, fclose(f_r));
|
||||
|
||||
/* Overwrite file with 'cccc' */
|
||||
create_file_with_text(NAME, "cccc");
|
||||
|
||||
/* Verify file now only contains 'cccc' */
|
||||
f_r = fopen(NAME, "r");
|
||||
TEST_ASSERT_NOT_NULL(f_r);
|
||||
bzero(buf, sizeof(buf));
|
||||
TEST_ASSERT_EQUAL(4, fread(buf, 1, 8, f_r)); // trying to read 8 bytes, only expecting 4
|
||||
TEST_ASSERT_EQUAL_STRING_LEN("cccc", buf, 4);
|
||||
TEST_ASSERT_EQUAL(0, fclose(f_r));
|
||||
|
||||
TEST_ESP_OK(esp_vfs_fat_sdmmc_unmount());
|
||||
HEAP_SIZE_CHECK(0);
|
||||
}
|
||||
|
||||
TEST_CASE("can read file on sd card", "[fatfs][ignore]")
|
||||
{
|
||||
HEAP_SIZE_CAPTURE();
|
||||
|
||||
@@ -254,7 +254,7 @@
|
||||
#define configUSE_TIMERS 1
|
||||
#define configTIMER_TASK_PRIORITY 1
|
||||
#define configTIMER_QUEUE_LENGTH 10
|
||||
#define configTIMER_TASK_STACK_DEPTH configMINIMAL_STACK_SIZE
|
||||
#define configTIMER_TASK_STACK_DEPTH 2048
|
||||
|
||||
#define INCLUDE_xTimerPendFunctionCall 1
|
||||
#define INCLUDE_eTaskGetState 1
|
||||
|
||||
@@ -194,6 +194,12 @@ void vPortYieldOtherCore( BaseType_t coreid) PRIVILEGED_FUNCTION;
|
||||
*/
|
||||
void vPortSetStackWatchpoint( void* pxStackStart );
|
||||
|
||||
/*
|
||||
* Returns true if the current core is in ISR context; low prio ISR, med prio ISR or timer tick ISR. High prio ISRs
|
||||
* aren't detected here, but they normally cannot call C code, so that should not be an issue anyway.
|
||||
*/
|
||||
BaseType_t xPortInIsrContext();
|
||||
|
||||
/*
|
||||
* The structures and methods of manipulating the MPU are contained within the
|
||||
* port layer.
|
||||
@@ -216,6 +222,9 @@ static inline uint32_t xPortGetCoreID() {
|
||||
return id;
|
||||
}
|
||||
|
||||
/* Get tick rate per second */
|
||||
uint32_t xPortGetTickRateHz(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -115,7 +115,7 @@ extern void _xt_coproc_init(void);
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
unsigned port_xSchedulerRunning[portNUM_PROCESSORS] = {0}; // Duplicate of inaccessible xSchedulerRunning; needed at startup to avoid counting nesting
|
||||
unsigned port_interruptNesting[portNUM_PROCESSORS] = {0}; // Interrupt nesting level
|
||||
unsigned port_interruptNesting[portNUM_PROCESSORS] = {0}; // Interrupt nesting level. Increased/decreased in portasm.c, _frxt_int_enter/_frxt_int_exit
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
@@ -256,9 +256,24 @@ void vPortStoreTaskMPUSettings( xMPU_SETTINGS *xMPUSettings, const struct xMEMOR
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Returns true if the current core is in ISR context; low prio ISR, med prio ISR or timer tick ISR. High prio ISRs
|
||||
* aren't detected here, but they normally cannot call C code, so that should not be an issue anyway.
|
||||
*/
|
||||
BaseType_t xPortInIsrContext()
|
||||
{
|
||||
unsigned int irqStatus;
|
||||
BaseType_t ret;
|
||||
irqStatus=portENTER_CRITICAL_NESTED();
|
||||
ret=(port_interruptNesting[xPortGetCoreID()] != 0);
|
||||
portEXIT_CRITICAL_NESTED(irqStatus);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
void vPortAssertIfInISR()
|
||||
{
|
||||
configASSERT(port_interruptNesting[xPortGetCoreID()]==0)
|
||||
configASSERT(xPortInIsrContext());
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -406,7 +421,9 @@ void vPortSetStackWatchpoint( void* pxStackStart ) {
|
||||
esp_set_watchpoint(1, (char*)addr, 32, ESP_WATCHPOINT_STORE);
|
||||
}
|
||||
|
||||
|
||||
uint32_t xPortGetTickRateHz(void) {
|
||||
return (uint32_t)configTICK_RATE_HZ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -132,8 +132,8 @@ _frxt_int_enter:
|
||||
l32i a2, a2, 0 /* a2 = current TCB */
|
||||
beqz a2, 1f
|
||||
s32i a1, a2, TOPOFSTACK_OFFS /* pxCurrentTCB->pxTopOfStack = SP */
|
||||
movi a1, port_IntStackTop /* a1 = top of intr stack */
|
||||
movi a2, configISR_STACK_SIZE
|
||||
movi a1, port_IntStack+configISR_STACK_SIZE /* a1 = top of intr stack for CPU 0 */
|
||||
movi a2, configISR_STACK_SIZE /* add configISR_STACK_SIZE * cpu_num to arrive at top of stack for cpu_num */
|
||||
mull a2, a4, a2
|
||||
add a1, a1, a2 /* for current proc */
|
||||
|
||||
|
||||
@@ -632,7 +632,7 @@ static void prvAddNewTaskToReadyList( TCB_t *pxNewTCB, TaskFunction_t pxTaskCode
|
||||
*/
|
||||
void taskYIELD_OTHER_CORE( BaseType_t xCoreID, UBaseType_t uxPriority )
|
||||
{
|
||||
TCB_t *curTCB = xTaskGetCurrentTaskHandle();
|
||||
TCB_t *curTCB = pxCurrentTCB[xCoreID];
|
||||
BaseType_t i;
|
||||
|
||||
if (xCoreID != tskNO_AFFINITY) {
|
||||
@@ -1056,11 +1056,15 @@ static void prvAddNewTaskToReadyList( TCB_t *pxNewTCB, TaskFunction_t pxTaskCode
|
||||
taskENTER_CRITICAL(&xTaskQueueMutex);
|
||||
{
|
||||
uxCurrentNumberOfTasks++;
|
||||
if( pxCurrentTCB[ xPortGetCoreID() ] == NULL )
|
||||
//If the task has no affinity and nothing is scheduled on this core, just throw it this core.
|
||||
//If it has affinity, throw it on the core that needs it if nothing is already scheduled there.
|
||||
BaseType_t xMyCore = xCoreID;
|
||||
if ( xMyCore == tskNO_AFFINITY) xMyCore = xPortGetCoreID();
|
||||
if( pxCurrentTCB[ xMyCore ] == NULL )
|
||||
{
|
||||
/* There are no other tasks, or all the other tasks are in
|
||||
the suspended state - make this the current task. */
|
||||
pxCurrentTCB[ xPortGetCoreID() ] = pxNewTCB;
|
||||
pxCurrentTCB[ xMyCore ] = pxNewTCB;
|
||||
|
||||
if( uxCurrentNumberOfTasks == ( UBaseType_t ) 1 )
|
||||
{
|
||||
@@ -1121,12 +1125,13 @@ static void prvAddNewTaskToReadyList( TCB_t *pxNewTCB, TaskFunction_t pxTaskCode
|
||||
|
||||
portSETUP_TCB( pxNewTCB );
|
||||
}
|
||||
curTCB = pxCurrentTCB[ xPortGetCoreID() ];
|
||||
|
||||
taskEXIT_CRITICAL(&xTaskQueueMutex);
|
||||
|
||||
if( xSchedulerRunning != pdFALSE )
|
||||
{
|
||||
taskENTER_CRITICAL(&xTaskQueueMutex);
|
||||
curTCB = pxCurrentTCB[ xPortGetCoreID() ];
|
||||
/* Scheduler is running. If the created task is of a higher priority than an executing task
|
||||
then it should run now.
|
||||
ToDo: This only works for the current core. If a task is scheduled on an other processor,
|
||||
@@ -1141,7 +1146,7 @@ static void prvAddNewTaskToReadyList( TCB_t *pxNewTCB, TaskFunction_t pxTaskCode
|
||||
*/
|
||||
if( tskCAN_RUN_HERE( xCoreID ) && curTCB->uxPriority < pxNewTCB->uxPriority )
|
||||
{
|
||||
taskYIELD_IF_USING_PREEMPTION();
|
||||
taskYIELD_IF_USING_PREEMPTION_MUX(&xTaskQueueMutex);
|
||||
}
|
||||
else if( xCoreID != xPortGetCoreID() ) {
|
||||
taskYIELD_OTHER_CORE(xCoreID, pxNewTCB->uxPriority);
|
||||
@@ -2659,11 +2664,13 @@ BaseType_t xSwitchRequired = pdFALSE;
|
||||
|
||||
void vTaskSwitchContext( void )
|
||||
{
|
||||
tskTCB * pxTCB;
|
||||
//This can be called both from IRQ as well as normal context, so we can't
|
||||
//use taskENTER_CRITICAL() here. Instead, save the irq status and disable
|
||||
//IRQs, so we can use taskENTER_CRITICAL_ISR and friends.
|
||||
//Note: This can be called from interrupt context as well as from non-interrupt context (voluntary yield). The
|
||||
//taskENTER_CRITICAL/taskEXIT_CRITICAL is modified to work in both scenarios for the ESP32, so we can freely use
|
||||
//them here. However, in case of a voluntary yield, a nonvoluntary yield can still happen *during* the voluntary
|
||||
//yield. Disabling interrupts using portENTER_CRITICAL_NESTED puts a stop to this and makes the rest of the code a
|
||||
//bit neater.
|
||||
int irqstate=portENTER_CRITICAL_NESTED();
|
||||
tskTCB * pxTCB;
|
||||
if( uxSchedulerSuspended[ xPortGetCoreID() ] != ( UBaseType_t ) pdFALSE )
|
||||
{
|
||||
/* The scheduler is currently suspended - do not allow a context
|
||||
@@ -3012,9 +3019,14 @@ BaseType_t xReturn;
|
||||
|
||||
This function assumes that a check has already been made to ensure that
|
||||
pxEventList is not empty. */
|
||||
pxUnblockedTCB = ( TCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxEventList );
|
||||
configASSERT( pxUnblockedTCB );
|
||||
( void ) uxListRemove( &( pxUnblockedTCB->xEventListItem ) );
|
||||
if ( ( listLIST_IS_EMPTY( pxEventList ) ) == pdFALSE ) {
|
||||
pxUnblockedTCB = ( TCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxEventList );
|
||||
configASSERT( pxUnblockedTCB );
|
||||
( void ) uxListRemove( &( pxUnblockedTCB->xEventListItem ) );
|
||||
} else {
|
||||
taskEXIT_CRITICAL_ISR(&xTaskQueueMutex);
|
||||
return pdFALSE;
|
||||
}
|
||||
|
||||
if( uxSchedulerSuspended[ xPortGetCoreID() ] == ( UBaseType_t ) pdFALSE )
|
||||
{
|
||||
@@ -3025,9 +3037,7 @@ BaseType_t xReturn;
|
||||
{
|
||||
/* The delayed and ready lists cannot be accessed, so hold this task
|
||||
pending until the scheduler is resumed. */
|
||||
taskENTER_CRITICAL(&xTaskQueueMutex);
|
||||
vListInsertEnd( &( xPendingReadyList[ xPortGetCoreID() ] ), &( pxUnblockedTCB->xEventListItem ) );
|
||||
taskEXIT_CRITICAL(&xTaskQueueMutex);
|
||||
}
|
||||
|
||||
if ( tskCAN_RUN_HERE(pxUnblockedTCB->xCoreID) && pxUnblockedTCB->uxPriority >= pxCurrentTCB[ xPortGetCoreID() ]->uxPriority )
|
||||
|
||||
51
components/freertos/test/test_freertos_isinisrcontext.c
Normal file
51
components/freertos/test/test_freertos_isinisrcontext.c
Normal file
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
See if xPortInIsrContext works
|
||||
*/
|
||||
|
||||
#include <esp_types.h>
|
||||
#include <stdio.h>
|
||||
#include "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 "esp_intr_alloc.h"
|
||||
#include "xtensa/hal.h"
|
||||
|
||||
static volatile int in_int_context, int_handled;
|
||||
|
||||
|
||||
static void testint(void *arg) {
|
||||
xthal_set_ccompare(1, xthal_get_ccount()+8000000000);
|
||||
ets_printf("INT!\n");
|
||||
if (xPortInIsrContext()) in_int_context++;
|
||||
int_handled++;
|
||||
}
|
||||
|
||||
|
||||
static void testthread(void *arg) {
|
||||
intr_handle_t handle;
|
||||
in_int_context=0;
|
||||
int_handled=0;
|
||||
TEST_ASSERT(!xPortInIsrContext());
|
||||
xthal_set_ccompare(2, xthal_get_ccount()+8000000);
|
||||
esp_intr_alloc(ETS_INTERNAL_TIMER1_INTR_SOURCE, 0, &testint, NULL, &handle);
|
||||
vTaskDelay(100 / portTICK_PERIOD_MS);
|
||||
TEST_ASSERT(int_handled);
|
||||
TEST_ASSERT(in_int_context);
|
||||
esp_intr_free(handle);
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
|
||||
TEST_CASE("xPortInIsrContext test", "[freertos]")
|
||||
{
|
||||
xTaskCreatePinnedToCore(testthread, "tst" , 4096, NULL, 3, NULL, 0);
|
||||
vTaskDelay(150 / portTICK_PERIOD_MS);
|
||||
xTaskCreatePinnedToCore(testthread, "tst" , 4096, NULL, 3, NULL, 1);
|
||||
vTaskDelay(150 / portTICK_PERIOD_MS);
|
||||
}
|
||||
|
||||
@@ -2935,12 +2935,18 @@ initial condition:
|
||||
test script: InitCondBase
|
||||
- check cmd set:
|
||||
- ''
|
||||
- - FREBOOT UT1
|
||||
- ['']
|
||||
- - DELAY 3
|
||||
- ['']
|
||||
- - UT UT1 -
|
||||
- [R UT1 C Tests C Failures C Ignored]
|
||||
force restore cmd set:
|
||||
- ''
|
||||
- - FREBOOT UT1
|
||||
- ['']
|
||||
- - DELAY 3
|
||||
- ['']
|
||||
- - UT UT1 -
|
||||
- [R UT1 C Tests C Failures C Ignored]
|
||||
initial condition detail: At UT menu page
|
||||
@@ -2948,6 +2954,8 @@ initial condition:
|
||||
- ''
|
||||
- - FREBOOT UT1
|
||||
- ['']
|
||||
- - DELAY 3
|
||||
- ['']
|
||||
- - UT UT1 -
|
||||
- [R UT1 C Tests C Failures C Ignored]
|
||||
restore post cmd set:
|
||||
|
||||
@@ -2,7 +2,7 @@ menu "LWIP"
|
||||
|
||||
config L2_TO_L3_COPY
|
||||
bool "Enable copy between Layer2 and Layer3 packets"
|
||||
default 0
|
||||
default n
|
||||
help
|
||||
If this feature is enabled, all traffic from layer2(WIFI Driver) will be
|
||||
copied to a new buffer before sending it to layer3(LWIP stack), freeing
|
||||
@@ -35,14 +35,14 @@ config LWIP_THREAD_LOCAL_STORAGE_INDEX
|
||||
|
||||
config LWIP_SO_REUSE
|
||||
bool "Enable SO_REUSEADDR option"
|
||||
default 0
|
||||
default n
|
||||
help
|
||||
Enabling this option allows binding to a port which remains in
|
||||
TIME_WAIT.
|
||||
|
||||
config LWIP_SO_RCVBUF
|
||||
bool "Enable SO_RCVBUF option"
|
||||
default 0
|
||||
default n
|
||||
help
|
||||
Enabling this option allows checking for available data on a netconn.
|
||||
|
||||
@@ -57,14 +57,14 @@ config LWIP_DHCP_MAX_NTP_SERVERS
|
||||
|
||||
config LWIP_IP_FRAG
|
||||
bool "Enable fragment outgoing IP packets"
|
||||
default 0
|
||||
default n
|
||||
help
|
||||
Enabling this option allows fragmenting outgoing IP packets if their size
|
||||
exceeds MTU.
|
||||
|
||||
config LWIP_IP_REASSEMBLY
|
||||
bool "Enable reassembly incoming fragmented IP packets"
|
||||
default 0
|
||||
default n
|
||||
help
|
||||
Enabling this option allows reassemblying incoming fragmented IP packets.
|
||||
|
||||
@@ -82,6 +82,13 @@ config TCP_SYNMAXRTX
|
||||
help
|
||||
Set maximum number of retransmissions of SYN segments.
|
||||
|
||||
config LWIP_DHCP_DOES_ARP_CHECK
|
||||
bool "Enable an ARP check on the offered address"
|
||||
default y
|
||||
help
|
||||
Enabling this option allows check if the offered IP address is not already
|
||||
in use by another host on the network.
|
||||
|
||||
endmenu
|
||||
|
||||
|
||||
|
||||
@@ -550,10 +550,17 @@ dhcp_t1_timeout(struct netif *netif)
|
||||
DHCP_STATE_RENEWING, not DHCP_STATE_BOUND */
|
||||
dhcp_renew(netif);
|
||||
/* Calculate next timeout */
|
||||
#if ESP_DHCP_TIMER
|
||||
if (((netif->dhcp->t2_timeout - dhcp->lease_used) / 2) >= (60 + DHCP_COARSE_TIMER_SECS / 2) )
|
||||
{
|
||||
netif->dhcp->t1_renew_time = (netif->dhcp->t2_timeout - dhcp->lease_used) / 2;
|
||||
}
|
||||
#else
|
||||
if (((netif->dhcp->t2_timeout - dhcp->lease_used) / 2) >= ((60 + DHCP_COARSE_TIMER_SECS / 2) / DHCP_COARSE_TIMER_SECS))
|
||||
{
|
||||
netif->dhcp->t1_renew_time = ((netif->dhcp->t2_timeout - dhcp->lease_used) / 2);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -576,10 +583,17 @@ dhcp_t2_timeout(struct netif *netif)
|
||||
DHCP_STATE_REBINDING, not DHCP_STATE_BOUND */
|
||||
dhcp_rebind(netif);
|
||||
/* Calculate next timeout */
|
||||
#if ESP_DHCP_TIMER
|
||||
if (((netif->dhcp->t0_timeout - dhcp->lease_used) / 2) >= (60 + DHCP_COARSE_TIMER_SECS / 2))
|
||||
{
|
||||
netif->dhcp->t2_rebind_time = ((netif->dhcp->t0_timeout - dhcp->lease_used) / 2);
|
||||
}
|
||||
#else
|
||||
if (((netif->dhcp->t0_timeout - dhcp->lease_used) / 2) >= ((60 + DHCP_COARSE_TIMER_SECS / 2) / DHCP_COARSE_TIMER_SECS))
|
||||
{
|
||||
netif->dhcp->t2_rebind_time = ((netif->dhcp->t0_timeout - dhcp->lease_used) / 2);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1029,7 +1043,12 @@ dhcp_discover(struct netif *netif)
|
||||
autoip_start(netif);
|
||||
}
|
||||
#endif /* LWIP_DHCP_AUTOIP_COOP */
|
||||
msecs = (dhcp->tries < 6 ? 1 << dhcp->tries : 60) * 1000;
|
||||
|
||||
/* Since for embedded devices it's not that hard to miss a discover packet, so lower
|
||||
* the discover retry backoff time from (2,4,8,16,32,60,60)s to (500m,1,2,4,8,15,15)s.
|
||||
* Original msecs = (dhcp->tries < 6 ? 1 << dhcp->tries : 60) * 1000;
|
||||
*/
|
||||
msecs = (dhcp->tries < 6 ? 1 << dhcp->tries : 60) * 250;
|
||||
dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS;
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_discover(): set request timeout %"U16_F" msecs\n", msecs));
|
||||
return result;
|
||||
@@ -1055,6 +1074,47 @@ dhcp_bind(struct netif *netif)
|
||||
/* reset time used of lease */
|
||||
dhcp->lease_used = 0;
|
||||
|
||||
#if ESP_DHCP_TIMER
|
||||
if (dhcp->offered_t0_lease != 0xffffffffUL) {
|
||||
/* set renewal period timer */
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_bind(): t0 renewal timer %"U32_F" secs\n", dhcp->offered_t0_lease));
|
||||
timeout = dhcp->offered_t0_lease;
|
||||
dhcp->t0_timeout = timeout;
|
||||
if (dhcp->t0_timeout == 0) {
|
||||
dhcp->t0_timeout = 120;
|
||||
}
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_bind(): set request timeout %"U32_F" msecs\n", dhcp->offered_t0_lease*1000));
|
||||
}
|
||||
|
||||
/* temporary DHCP lease? */
|
||||
if (dhcp->offered_t1_renew != 0xffffffffUL) {
|
||||
/* set renewal period timer */
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_bind(): t1 renewal timer %"U32_F" secs\n", dhcp->offered_t1_renew));
|
||||
timeout = dhcp->offered_t1_renew;
|
||||
dhcp->t1_timeout = timeout;
|
||||
if (dhcp->t1_timeout == 0) {
|
||||
dhcp->t1_timeout = dhcp->t0_timeout>>1;
|
||||
}
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_bind(): set request timeout %"U32_F" msecs\n", dhcp->offered_t1_renew*1000));
|
||||
dhcp->t1_renew_time = dhcp->t1_timeout;
|
||||
}
|
||||
/* set renewal period timer */
|
||||
if (dhcp->offered_t2_rebind != 0xffffffffUL) {
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_bind(): t2 rebind timer %"U32_F" secs\n", dhcp->offered_t2_rebind));
|
||||
timeout = dhcp->offered_t2_rebind;
|
||||
dhcp->t2_timeout = timeout;
|
||||
if (dhcp->t2_timeout == 0) {
|
||||
dhcp->t2_timeout = (dhcp->t0_timeout>>3)*7;
|
||||
}
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_bind(): set request timeout %"U32_F" msecs\n", dhcp->offered_t2_rebind*1000));
|
||||
dhcp->t2_rebind_time = dhcp->t2_timeout;
|
||||
}
|
||||
|
||||
/* If we have sub 1 minute lease, t2 and t1 will kick in at the same time. */
|
||||
if ((dhcp->t1_timeout >= dhcp->t2_timeout) && (dhcp->t2_timeout > 0)) {
|
||||
dhcp->t1_timeout = 0;
|
||||
}
|
||||
#else
|
||||
if (dhcp->offered_t0_lease != 0xffffffffUL) {
|
||||
/* set renewal period timer */
|
||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_bind(): t0 renewal timer %"U32_F" secs\n", dhcp->offered_t0_lease));
|
||||
@@ -1103,6 +1163,7 @@ dhcp_bind(struct netif *netif)
|
||||
if ((dhcp->t1_timeout >= dhcp->t2_timeout) && (dhcp->t2_timeout > 0)) {
|
||||
dhcp->t1_timeout = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (dhcp->subnet_mask_given) {
|
||||
/* copy offered network mask */
|
||||
|
||||
@@ -45,7 +45,7 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
/** period (in seconds) of the application calling dhcp_coarse_tmr() */
|
||||
#define DHCP_COARSE_TIMER_SECS 60
|
||||
#define DHCP_COARSE_TIMER_SECS 1
|
||||
/** period (in milliseconds) of the application calling dhcp_coarse_tmr() */
|
||||
#define DHCP_COARSE_TIMER_MSECS (DHCP_COARSE_TIMER_SECS * 1000UL)
|
||||
/** period (in milliseconds) of the application calling dhcp_fine_tmr() */
|
||||
@@ -76,12 +76,12 @@ struct dhcp
|
||||
struct dhcp_msg *msg_out; /* outgoing msg */
|
||||
u16_t options_out_len; /* outgoing msg options length */
|
||||
u16_t request_timeout; /* #ticks with period DHCP_FINE_TIMER_SECS for request timeout */
|
||||
u16_t t1_timeout; /* #ticks with period DHCP_COARSE_TIMER_SECS for renewal time */
|
||||
u16_t t2_timeout; /* #ticks with period DHCP_COARSE_TIMER_SECS for rebind time */
|
||||
u16_t t1_renew_time; /* #ticks with period DHCP_COARSE_TIMER_SECS until next renew try */
|
||||
u16_t t2_rebind_time; /* #ticks with period DHCP_COARSE_TIMER_SECS until next rebind try */
|
||||
u16_t lease_used; /* #ticks with period DHCP_COARSE_TIMER_SECS since last received DHCP ack */
|
||||
u16_t t0_timeout; /* #ticks with period DHCP_COARSE_TIMER_SECS for lease time */
|
||||
u32_t t1_timeout; /* #ticks with period DHCP_COARSE_TIMER_SECS for renewal time */
|
||||
u32_t t2_timeout; /* #ticks with period DHCP_COARSE_TIMER_SECS for rebind time */
|
||||
u32_t t1_renew_time; /* #ticks with period DHCP_COARSE_TIMER_SECS until next renew try */
|
||||
u32_t t2_rebind_time; /* #ticks with period DHCP_COARSE_TIMER_SECS until next rebind try */
|
||||
u32_t lease_used; /* #ticks with period DHCP_COARSE_TIMER_SECS since last received DHCP ack */
|
||||
u32_t t0_timeout; /* #ticks with period DHCP_COARSE_TIMER_SECS for lease time */
|
||||
ip_addr_t server_ip_addr; /* dhcp server address that offered this lease (ip_addr_t because passed to UDP) */
|
||||
ip4_addr_t offered_ip_addr;
|
||||
ip4_addr_t offered_sn_mask;
|
||||
|
||||
@@ -206,6 +206,11 @@
|
||||
|
||||
#define DHCP_MAXRTX 0
|
||||
|
||||
/**
|
||||
* DHCP_DOES_ARP_CHECK==1: Do an ARP check on the offered address.
|
||||
*/
|
||||
#define DHCP_DOES_ARP_CHECK CONFIG_LWIP_DHCP_DOES_ARP_CHECK
|
||||
|
||||
/*
|
||||
------------------------------------
|
||||
---------- AUTOIP options ----------
|
||||
@@ -597,6 +602,7 @@
|
||||
#define ESP_LIGHT_SLEEP 1
|
||||
#define ESP_L2_TO_L3_COPY CONFIG_L2_TO_L3_COPY
|
||||
#define ESP_CNT_DEBUG 0
|
||||
#define ESP_DHCP_TIMER 1
|
||||
|
||||
#define TCP_WND_DEFAULT (4*TCP_MSS)
|
||||
#define TCP_SND_BUF_DEFAULT (2*TCP_MSS)
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#include MBEDTLS_CONFIG_FILE
|
||||
#endif
|
||||
|
||||
#include "platform.h"
|
||||
#include "bignum.h"
|
||||
#include "ecp.h"
|
||||
|
||||
|
||||
@@ -491,7 +491,7 @@ static const uint8_t * _mdns_read_fqdn(const uint8_t * packet, const uint8_t * s
|
||||
&& (strcmp(buf, MDNS_DEFAULT_DOMAIN) != 0)
|
||||
&& (strcmp(buf, "ip6") != 0)
|
||||
&& (strcmp(buf, "in-addr") != 0)) {
|
||||
sprintf((char*)name, "%s.%s", name->host, buf);
|
||||
snprintf((char*)name, MDNS_NAME_BUF_LEN, "%s.%s", name->host, buf);
|
||||
} else if (strcmp(buf, MDNS_SUB_STR) == 0) {
|
||||
name->sub = 1;
|
||||
} else {
|
||||
@@ -499,7 +499,7 @@ static const uint8_t * _mdns_read_fqdn(const uint8_t * packet, const uint8_t * s
|
||||
}
|
||||
} else {
|
||||
size_t address = (((uint16_t)len & 0x3F) << 8) | start[index++];
|
||||
if ((packet + address) > start) {
|
||||
if ((packet + address) >= start) {
|
||||
//reference address can not be after where we are
|
||||
return NULL;
|
||||
}
|
||||
@@ -1182,13 +1182,13 @@ static mdns_service_t * _mdns_create_service(const char * service, const char *
|
||||
s->txt = NULL;
|
||||
s->port = port;
|
||||
|
||||
s->service = strdup(service);
|
||||
s->service = strndup(service, MDNS_NAME_BUF_LEN - 1);
|
||||
if (!s->service) {
|
||||
free(s);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
s->proto = strdup(proto);
|
||||
s->proto = strndup(proto, MDNS_NAME_BUF_LEN - 1);
|
||||
if (!s->proto) {
|
||||
free((char *)s->service);
|
||||
free(s);
|
||||
@@ -1341,7 +1341,7 @@ static void _mdns_parse_packet(mdns_server_t * server, const uint8_t * data, siz
|
||||
(strcmp(name->proto, server->search.proto) != 0)) {
|
||||
continue;//not searching for service or wrong service/proto
|
||||
}
|
||||
sprintf(answer->instance, "%s", name->host);
|
||||
strlcpy(answer->instance, name->host, MDNS_NAME_BUF_LEN);
|
||||
} else if (type == MDNS_TYPE_SRV) {
|
||||
if (server->search.host[0] ||
|
||||
(strcmp(name->service, server->search.service) != 0) ||
|
||||
@@ -1353,7 +1353,7 @@ static void _mdns_parse_packet(mdns_server_t * server, const uint8_t * data, siz
|
||||
continue;//instance name is not the same as the one in the PTR record
|
||||
}
|
||||
} else {
|
||||
sprintf(answer->instance, "%s", name->host);
|
||||
strlcpy(answer->instance, name->host, MDNS_NAME_BUF_LEN);
|
||||
}
|
||||
//parse record value
|
||||
if (!_mdns_parse_fqdn(data, data_ptr + MDNS_SRV_FQDN_OFFSET, name)) {
|
||||
@@ -1367,15 +1367,19 @@ static void _mdns_parse_packet(mdns_server_t * server, const uint8_t * data, siz
|
||||
if (answer->host[0]) {
|
||||
if (strcmp(answer->host, name->host) != 0) {
|
||||
answer->addr = 0;
|
||||
sprintf(answer->host, "%s", name->host);
|
||||
strlcpy(answer->host, name->host, MDNS_NAME_BUF_LEN);
|
||||
}
|
||||
} else {
|
||||
sprintf(answer->host, "%s", name->host);
|
||||
strlcpy(answer->host, name->host, MDNS_NAME_BUF_LEN);
|
||||
}
|
||||
} else if (type == MDNS_TYPE_TXT) {
|
||||
uint16_t i=0,b=0, y;
|
||||
while(i < data_len) {
|
||||
uint8_t partLen = data_ptr[i++];
|
||||
//check if partLen will fit in the buffer
|
||||
if (partLen > (MDNS_TXT_MAX_LEN - b - 1)) {
|
||||
break;
|
||||
}
|
||||
for(y=0; y<partLen; y++) {
|
||||
char d = data_ptr[i++];
|
||||
answer->txt[b++] = d;
|
||||
@@ -1391,7 +1395,7 @@ static void _mdns_parse_packet(mdns_server_t * server, const uint8_t * data, siz
|
||||
continue;//wrong host
|
||||
}
|
||||
} else if (!answer->ptr) {
|
||||
sprintf(answer->host, "%s", name->host);
|
||||
strlcpy(answer->host, name->host, MDNS_NAME_BUF_LEN);
|
||||
} else if (strcmp(answer->host, name->host) != 0) {
|
||||
continue;//wrong host
|
||||
}
|
||||
@@ -1402,7 +1406,7 @@ static void _mdns_parse_packet(mdns_server_t * server, const uint8_t * data, siz
|
||||
continue;//wrong host
|
||||
}
|
||||
} else if (!answer->ptr) {
|
||||
sprintf(answer->host, "%s", name->host);
|
||||
strlcpy(answer->host, name->host, MDNS_NAME_BUF_LEN);
|
||||
} else if (strcmp(answer->host, name->host) != 0) {
|
||||
continue;//wrong host
|
||||
}
|
||||
@@ -1534,6 +1538,9 @@ esp_err_t mdns_set_hostname(mdns_server_t * server, const char * hostname)
|
||||
if (!server) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
if (strlen(hostname) > (MDNS_NAME_BUF_LEN - 1)) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
MDNS_MUTEX_LOCK();
|
||||
free((char*)server->hostname);
|
||||
server->hostname = (char *)malloc(strlen(hostname)+1);
|
||||
@@ -1541,7 +1548,7 @@ esp_err_t mdns_set_hostname(mdns_server_t * server, const char * hostname)
|
||||
MDNS_MUTEX_UNLOCK();
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
sprintf((char *)server->hostname, "%s", hostname);
|
||||
strlcpy((char *)server->hostname, hostname, MDNS_NAME_BUF_LEN);
|
||||
MDNS_MUTEX_UNLOCK();
|
||||
return ERR_OK;
|
||||
}
|
||||
@@ -1551,6 +1558,9 @@ esp_err_t mdns_set_instance(mdns_server_t * server, const char * instance)
|
||||
if (!server) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
if (strlen(instance) > (MDNS_NAME_BUF_LEN - 1)) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
MDNS_MUTEX_LOCK();
|
||||
free((char*)server->instance);
|
||||
server->instance = (char *)malloc(strlen(instance)+1);
|
||||
@@ -1558,7 +1568,7 @@ esp_err_t mdns_set_instance(mdns_server_t * server, const char * instance)
|
||||
MDNS_MUTEX_UNLOCK();
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
sprintf((char *)server->instance, "%s", instance);
|
||||
strlcpy((char *)server->instance, instance, MDNS_NAME_BUF_LEN);
|
||||
MDNS_MUTEX_UNLOCK();
|
||||
return ERR_OK;
|
||||
}
|
||||
@@ -1655,6 +1665,9 @@ esp_err_t mdns_service_instance_set(mdns_server_t * server, const char * service
|
||||
if (!server || !server->services || !service || !proto) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
if (strlen(instance) > (MDNS_NAME_BUF_LEN - 1)) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
mdns_srv_item_t * s = _mdns_get_service_item(server, service, proto);
|
||||
if (!s) {
|
||||
return ESP_ERR_NOT_FOUND;
|
||||
@@ -1741,10 +1754,10 @@ uint32_t mdns_query(mdns_server_t * server, const char * service, const char * p
|
||||
mdns_result_free(server);
|
||||
if (proto) {
|
||||
server->search.host[0] = 0;
|
||||
snprintf(server->search.service, MDNS_NAME_MAX_LEN, "%s", service);
|
||||
snprintf(server->search.proto, MDNS_NAME_MAX_LEN, "%s", proto);
|
||||
strlcpy(server->search.service, service, MDNS_NAME_BUF_LEN);
|
||||
strlcpy(server->search.proto, proto, MDNS_NAME_BUF_LEN);
|
||||
} else {
|
||||
snprintf(server->search.host, MDNS_NAME_MAX_LEN, "%s", service);
|
||||
strlcpy(server->search.host, service, MDNS_NAME_BUF_LEN);
|
||||
server->search.service[0] = 0;
|
||||
server->search.proto[0] = 0;
|
||||
qtype = MDNS_TYPE_A;
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include "freertos/semphr.h"
|
||||
#include "freertos/portmacro.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/portable.h"
|
||||
|
||||
/* Notes on our newlib lock implementation:
|
||||
*
|
||||
@@ -126,7 +127,7 @@ static int IRAM_ATTR lock_acquire_generic(_lock_t *lock, uint32_t delay, uint8_t
|
||||
}
|
||||
|
||||
BaseType_t success;
|
||||
if (cpu_in_interrupt_context()) {
|
||||
if (xPortInIsrContext()) {
|
||||
/* In ISR Context */
|
||||
if (mutex_type == queueQUEUE_TYPE_RECURSIVE_MUTEX) {
|
||||
abort(); /* recursive mutexes make no sense in ISR context */
|
||||
@@ -180,7 +181,7 @@ static void IRAM_ATTR lock_release_generic(_lock_t *lock, uint8_t mutex_type) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (cpu_in_interrupt_context()) {
|
||||
if (xPortInIsrContext()) {
|
||||
if (mutex_type == queueQUEUE_TYPE_RECURSIVE_MUTEX) {
|
||||
abort(); /* indicates logic bug, it shouldn't be possible to lock recursively in ISR */
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ TEST_PROGRAM=test_nvs
|
||||
all: $(TEST_PROGRAM)
|
||||
|
||||
SOURCE_FILES = \
|
||||
esp_error_check_stub.cpp \
|
||||
$(addprefix ../src/, \
|
||||
nvs_types.cpp \
|
||||
nvs_api.cpp \
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
#include "catch.hpp"
|
||||
#include "esp_err.h"
|
||||
|
||||
void _esp_error_check_failed(esp_err_t rc, const char *file, int line, const char *function, const char *expression)
|
||||
{
|
||||
printf("ESP_ERROR_CHECK failed: esp_err_t 0x%x at %p\n", rc, __builtin_return_address(0));
|
||||
printf("file: \"%s\" line %d\nfunc: %s\nexpression: %s\n", file, line, function, expression);
|
||||
abort();
|
||||
}
|
||||
70
components/openssl/Kconfig
Normal file
70
components/openssl/Kconfig
Normal file
@@ -0,0 +1,70 @@
|
||||
menu "OpenSSL"
|
||||
|
||||
config OPENSSL_DEBUG
|
||||
bool "Enable OpenSSL debugging"
|
||||
default n
|
||||
help
|
||||
Enable OpenSSL debugging function.
|
||||
|
||||
If the option is enabled, "SSL_DEBUG" works.
|
||||
|
||||
config OPENSSL_DEBUG_LEVEL
|
||||
int "OpenSSL debugging level"
|
||||
default 0
|
||||
range 0 255
|
||||
depends on OPENSSL_DEBUG
|
||||
help
|
||||
OpenSSL debugging level.
|
||||
|
||||
Only function whose debugging level is higher than "OPENSSL_DEBUG_LEVEL" works.
|
||||
|
||||
For example:
|
||||
If OPENSSL_DEBUG_LEVEL = 2, you use function "SSL_DEBUG(1, "malloc failed")". Because 1 < 2, it will not print.
|
||||
|
||||
config OPENSSL_LOWLEVEL_DEBUG
|
||||
bool "Enable OpenSSL low-level module debugging"
|
||||
default n
|
||||
depends on OPENSSL_DEBUG
|
||||
select MBEDTLS_DEBUG
|
||||
help
|
||||
If the option is enabled, low-level module debugging function of OpenSSL is enabled, e.g. mbedtls internal debugging function.
|
||||
|
||||
choice OPENSSL_ASSERT
|
||||
prompt "Select OpenSSL assert function"
|
||||
default CONFIG_OPENSSL_ASSERT_EXIT
|
||||
help
|
||||
OpenSSL function needs "assert" function to check if input parameters are valid.
|
||||
|
||||
If you want to use assert debugging function, "OPENSSL_DEBUG" should be enabled.
|
||||
|
||||
config OPENSSL_ASSERT_DO_NOTHING
|
||||
bool "Do nothing"
|
||||
help
|
||||
Do nothing and "SSL_ASSERT" does not work.
|
||||
|
||||
config OPENSSL_ASSERT_EXIT
|
||||
bool "Check and exit"
|
||||
help
|
||||
Enable assert exiting, it will check and return error code.
|
||||
|
||||
config OPENSSL_ASSERT_DEBUG
|
||||
bool "Show debugging message"
|
||||
depends on OPENSSL_DEBUG
|
||||
help
|
||||
Enable assert debugging, it will check and show debugging message.
|
||||
|
||||
config OPENSSL_ASSERT_DEBUG_EXIT
|
||||
bool "Show debugging message and exit"
|
||||
depends on OPENSSL_DEBUG
|
||||
help
|
||||
Enable assert debugging and exiting, it will check, show debugging message and return error code.
|
||||
|
||||
config OPENSSL_ASSERT_DEBUG_BLOCK
|
||||
bool "Show debugging message and block"
|
||||
depends on OPENSSL_DEBUG
|
||||
help
|
||||
Enable assert debugging and blocking, it will check, show debugging message and block by "while (1);".
|
||||
|
||||
endchoice
|
||||
|
||||
endmenu
|
||||
@@ -22,72 +22,170 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef SSL_DEBUG_ENBALE
|
||||
#define SSL_DEBUG_ENBALE 0
|
||||
#endif
|
||||
|
||||
#ifndef SSL_DEBUG_LEVEL
|
||||
#define SSL_DEBUG_LEVEL 0
|
||||
#endif
|
||||
|
||||
#ifndef SSL_ASSERT_ENABLE
|
||||
#define SSL_ASSERT_ENABLE 0
|
||||
#endif
|
||||
|
||||
#ifndef SSL_DEBUG_LOCATION_ENABLE
|
||||
#define SSL_DEBUG_LOCATION_ENABLE 0
|
||||
#endif
|
||||
|
||||
#if SSL_DEBUG_ENBALE
|
||||
#if !defined(SSL_PRINT_LOG) || !defined(SSL_ERROR_LOG) || !defined(SSL_LOCAL_LOG)
|
||||
#include "stdio.h"
|
||||
extern int printf(const char *fmt, ...);
|
||||
#ifndef SSL_PRINT_LOG
|
||||
#define SSL_PRINT_LOG printf
|
||||
#endif
|
||||
#ifndef SSL_ERROR_LOG
|
||||
#define SSL_ERROR_LOG printf
|
||||
#endif
|
||||
#ifndef SSL_LOCAL_LOG
|
||||
#define SSL_LOCAL_LOG printf
|
||||
#endif
|
||||
#endif
|
||||
#ifdef CONFIG_OPENSSL_DEBUG_LEVEL
|
||||
#define SSL_DEBUG_LEVEL CONFIG_OPENSSL_DEBUG_LEVEL
|
||||
#else
|
||||
#ifdef SSL_PRINT_LOG
|
||||
#undef SSL_PRINT_LOG
|
||||
#endif
|
||||
#define SSL_PRINT_LOG(...)
|
||||
|
||||
#ifdef SSL_ERROR_LOG
|
||||
#undef SSL_ERROR_LOG
|
||||
#endif
|
||||
#define SSL_ERROR_LOG(...)
|
||||
#ifdef SSL_LOCAL_LOG
|
||||
#undef SSL_LOCAL_LOG
|
||||
#endif
|
||||
#define SSL_LOCAL_LOG(...)
|
||||
#define SSL_DEBUG_LEVEL 0
|
||||
#endif
|
||||
|
||||
#if SSL_DEBUG_LOCATION_ENABLE
|
||||
#define SSL_DEBUG_LOCATION() SSL_LOCAL_LOG("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__)
|
||||
#define SSL_DEBUG_ON (SSL_DEBUG_LEVEL + 1)
|
||||
#define SSL_DEBUG_OFF (SSL_DEBUG_LEVEL - 1)
|
||||
|
||||
#ifdef CONFIG_OPENSSL_DEBUG
|
||||
#ifndef SSL_DEBUG_LOG
|
||||
#error "SSL_DEBUG_LOG is not defined"
|
||||
#endif
|
||||
|
||||
#ifndef SSL_DEBUG_FL
|
||||
#define SSL_DEBUG_FL "\n"
|
||||
#endif
|
||||
|
||||
#define SSL_SHOW_LOCATION() \
|
||||
SSL_DEBUG_LOG("SSL assert : %s %d\n", \
|
||||
__FILE__, __LINE__)
|
||||
|
||||
#define SSL_DEBUG(level, fmt, ...) \
|
||||
{ \
|
||||
if (level > SSL_DEBUG_LEVEL) { \
|
||||
SSL_DEBUG_LOG(fmt SSL_DEBUG_FL, ##__VA_ARGS__); \
|
||||
} \
|
||||
}
|
||||
#else /* CONFIG_OPENSSL_DEBUG */
|
||||
#define SSL_SHOW_LOCATION()
|
||||
|
||||
#define SSL_DEBUG(level, fmt, ...)
|
||||
#endif /* CONFIG_OPENSSL_DEBUG */
|
||||
|
||||
/**
|
||||
* OpenSSL assert function
|
||||
*
|
||||
* if select "CONFIG_OPENSSL_ASSERT_DEBUG", SSL_ASSERT* will show error file name and line
|
||||
* if select "CONFIG_OPENSSL_ASSERT_EXIT", SSL_ASSERT* will just return error code.
|
||||
* if select "CONFIG_OPENSSL_ASSERT_DEBUG_EXIT" SSL_ASSERT* will show error file name and line,
|
||||
* then return error code.
|
||||
* if select "CONFIG_OPENSSL_ASSERT_DEBUG_BLOCK", SSL_ASSERT* will show error file name and line,
|
||||
* then block here with "while (1)"
|
||||
*
|
||||
* SSL_ASSERT1 may will return "-1", so function's return argument is integer.
|
||||
* SSL_ASSERT2 may will return "NULL", so function's return argument is a point.
|
||||
* SSL_ASSERT2 may will return nothing, so function's return argument is "void".
|
||||
*/
|
||||
#if defined(CONFIG_OPENSSL_ASSERT_DEBUG)
|
||||
#define SSL_ASSERT1(s) \
|
||||
{ \
|
||||
if (!(s)) { \
|
||||
SSL_SHOW_LOCATION(); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define SSL_ASSERT2(s) \
|
||||
{ \
|
||||
if (!(s)) { \
|
||||
SSL_SHOW_LOCATION(); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define SSL_ASSERT3(s) \
|
||||
{ \
|
||||
if (!(s)) { \
|
||||
SSL_SHOW_LOCATION(); \
|
||||
} \
|
||||
}
|
||||
#elif defined(CONFIG_OPENSSL_ASSERT_EXIT)
|
||||
#define SSL_ASSERT1(s) \
|
||||
{ \
|
||||
if (!(s)) { \
|
||||
return -1; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define SSL_ASSERT2(s) \
|
||||
{ \
|
||||
if (!(s)) { \
|
||||
return NULL; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define SSL_ASSERT3(s) \
|
||||
{ \
|
||||
if (!(s)) { \
|
||||
return ; \
|
||||
} \
|
||||
}
|
||||
#elif defined(CONFIG_OPENSSL_ASSERT_DEBUG_EXIT)
|
||||
#define SSL_ASSERT1(s) \
|
||||
{ \
|
||||
if (!(s)) { \
|
||||
SSL_SHOW_LOCATION(); \
|
||||
return -1; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define SSL_ASSERT2(s) \
|
||||
{ \
|
||||
if (!(s)) { \
|
||||
SSL_SHOW_LOCATION(); \
|
||||
return NULL; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define SSL_ASSERT3(s) \
|
||||
{ \
|
||||
if (!(s)) { \
|
||||
SSL_SHOW_LOCATION(); \
|
||||
return ; \
|
||||
} \
|
||||
}
|
||||
#elif defined(CONFIG_OPENSSL_ASSERT_DEBUG_BLOCK)
|
||||
#define SSL_ASSERT1(s) \
|
||||
{ \
|
||||
if (!(s)) { \
|
||||
SSL_SHOW_LOCATION(); \
|
||||
while (1); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define SSL_ASSERT2(s) \
|
||||
{ \
|
||||
if (!(s)) { \
|
||||
SSL_SHOW_LOCATION(); \
|
||||
while (1); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define SSL_ASSERT3(s) \
|
||||
{ \
|
||||
if (!(s)) { \
|
||||
SSL_SHOW_LOCATION(); \
|
||||
while (1); \
|
||||
} \
|
||||
}
|
||||
#else
|
||||
#define SSL_DEBUG_LOCATION()
|
||||
#define SSL_ASSERT1(s)
|
||||
#define SSL_ASSERT2(s)
|
||||
#define SSL_ASSERT3(s)
|
||||
#endif
|
||||
|
||||
#if SSL_ASSERT_ENABLE
|
||||
#define SSL_ASSERT(s) { if (!(s)) { SSL_DEBUG_LOCATION(); } }
|
||||
#else
|
||||
#define SSL_ASSERT(s)
|
||||
#endif
|
||||
#define SSL_PLATFORM_DEBUG_LEVEL SSL_DEBUG_OFF
|
||||
#define SSL_PLATFORM_ERROR_LEVEL SSL_DEBUG_ON
|
||||
|
||||
#define SSL_ERR(err, go, fmt, ...) { SSL_DEBUG_LOCATION(); SSL_ERROR_LOG(fmt, ##__VA_ARGS__); ret = err; goto go; }
|
||||
#define SSL_CERT_DEBUG_LEVEL SSL_DEBUG_OFF
|
||||
#define SSL_CERT_ERROR_LEVEL SSL_DEBUG_ON
|
||||
|
||||
#define SSL_RET(go, fmt, ...) { SSL_DEBUG_LOCATION(); SSL_ERROR_LOG(fmt, ##__VA_ARGS__); goto go; }
|
||||
#define SSL_PKEY_DEBUG_LEVEL SSL_DEBUG_OFF
|
||||
#define SSL_PKEY_ERROR_LEVEL SSL_DEBUG_ON
|
||||
|
||||
#define SSL_DEBUG(level, fmt, ...) { if (level > SSL_DEBUG_LEVEL) {SSL_PRINT_LOG(fmt, ##__VA_ARGS__);} }
|
||||
#define SSL_X509_DEBUG_LEVEL SSL_DEBUG_OFF
|
||||
#define SSL_X509_ERROR_LEVEL SSL_DEBUG_ON
|
||||
|
||||
#define SSL_LIB_DEBUG_LEVEL SSL_DEBUG_OFF
|
||||
#define SSL_LIB_ERROR_LEVEL SSL_DEBUG_ON
|
||||
|
||||
#define SSL_STACK_DEBUG_LEVEL SSL_DEBUG_OFF
|
||||
#define SSL_STACK_ERROR_LEVEL SSL_DEBUG_ON
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -15,34 +15,6 @@
|
||||
#ifndef _SSL_OPT_H_
|
||||
#define _SSL_OPT_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* if not define "ESP32_IDF_PLATFORM", system will use esp8266 platform interface
|
||||
*/
|
||||
#define ESP32_IDF_PLATFORM
|
||||
|
||||
/**
|
||||
* openssl debug print function enable
|
||||
*/
|
||||
#define SSL_DEBUG_ENBALE 0
|
||||
|
||||
/**
|
||||
* openssl debug print function level. function whose level is lower that "SSL_DEBUG_LEVEL"
|
||||
* will not print message
|
||||
*/
|
||||
#define SSL_DEBUG_LEVEL 0
|
||||
|
||||
/**
|
||||
* openssl assert function enable, it will check the input paramter and print the message
|
||||
*/
|
||||
#define SSL_ASSERT_ENABLE 0
|
||||
|
||||
/**
|
||||
* openssl location function enable, it will print location of the positioning error
|
||||
*/
|
||||
#define SSL_DEBUG_LOCATION_ENABLE 0
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#endif
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user