forked from espressif/esp-idf
Compare commits
59 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
054e82b4b3 | ||
|
|
7d4a9db191 | ||
|
|
8f81157432 | ||
|
|
5141570f24 | ||
|
|
f86d512672 | ||
|
|
ab341359f5 | ||
|
|
f98da26b38 | ||
|
|
d0cd624d2b | ||
|
|
c8c4bd099e | ||
|
|
36c14cf214 | ||
|
|
a7c9cf3a6b | ||
|
|
9aee394dc6 | ||
|
|
05eb9d155f | ||
|
|
0669fe8f02 | ||
|
|
cabb97f9a9 | ||
|
|
41b1db4dc6 | ||
|
|
8bc76b3684 | ||
|
|
245b753904 | ||
|
|
86a6c21e79 | ||
|
|
8cc0379da1 | ||
|
|
e56bfadc58 | ||
|
|
583e80708b | ||
|
|
5cf4d8a1ec | ||
|
|
ef3c6ac276 | ||
|
|
4129436f7e | ||
|
|
0808a04ee8 | ||
|
|
c99977b67c | ||
|
|
8d3d3fdd4a | ||
|
|
c4973908e4 | ||
|
|
3bb43d5f03 | ||
|
|
209d454b5f | ||
|
|
b385fe0586 | ||
|
|
487c4b6725 | ||
|
|
667846cba1 | ||
|
|
ccbb261c35 | ||
|
|
f35fd2a6b0 | ||
|
|
5682a5ef36 | ||
|
|
b66af09b75 | ||
|
|
9b5841f17c | ||
|
|
103de7acdc | ||
|
|
c2b39f4a5f | ||
|
|
2bd198d180 | ||
|
|
5b2fee13cd | ||
|
|
6ceedabb27 | ||
|
|
dac71d688a | ||
|
|
dc304fb3af | ||
|
|
6ae56b61cf | ||
|
|
6698be57c8 | ||
|
|
ef9dbff112 | ||
|
|
561f8ff513 | ||
|
|
945d2e697c | ||
|
|
94c4f32df0 | ||
|
|
ab62202eb9 | ||
|
|
063c23deff | ||
|
|
3868307efd | ||
|
|
e0c834285f | ||
|
|
e99b4e85b9 | ||
|
|
20ab122f80 | ||
|
|
98dd235819 |
127
.gitlab-ci.yml
127
.gitlab-ci.yml
@@ -1,9 +1,9 @@
|
||||
stages:
|
||||
- build
|
||||
- assign_test
|
||||
- host_test
|
||||
- unit_test
|
||||
- test
|
||||
- test_report
|
||||
- integration_test
|
||||
- deploy
|
||||
|
||||
variables:
|
||||
@@ -133,6 +133,8 @@ build_ssc_01:
|
||||
build_ssc_02:
|
||||
<<: *build_ssc_template
|
||||
|
||||
# If you want to add new build ssc jobs, please add it into dependencies of `assign_test` and `.test_template`
|
||||
|
||||
build_esp_idf_tests:
|
||||
<<: *build_template
|
||||
artifacts:
|
||||
@@ -140,7 +142,7 @@ build_esp_idf_tests:
|
||||
- tools/unit-test-app/output
|
||||
- components/idf_test/unit_test/TestCaseAll.yml
|
||||
- components/idf_test/unit_test/CIConfigs/*.yml
|
||||
expire_in: 6 mos
|
||||
expire_in: 1 mos
|
||||
script:
|
||||
- cd tools/unit-test-app
|
||||
- make help # make sure kconfig tools are built in single process
|
||||
@@ -199,6 +201,7 @@ build_examples_06:
|
||||
build_examples_07:
|
||||
<<: *build_examples_template
|
||||
|
||||
# If you want to add new build example jobs, please add it into dependencies of `.example_test_template`
|
||||
|
||||
build_docs:
|
||||
stage: build
|
||||
@@ -222,54 +225,44 @@ build_docs:
|
||||
- make html
|
||||
- ./check_doc_warnings.sh
|
||||
|
||||
test_nvs_on_host:
|
||||
stage: test
|
||||
image: $CI_DOCKER_REGISTRY/esp32-ci-env
|
||||
.host_test_template: &host_test_template
|
||||
stage: host_test
|
||||
image: $CI_DOCKER_REGISTRY/esp32-ci-env$BOT_DOCKER_IMAGE_TAG
|
||||
tags:
|
||||
- nvs_host_test
|
||||
- host_test
|
||||
dependencies: []
|
||||
|
||||
test_nvs_on_host:
|
||||
<<: *host_test_template
|
||||
script:
|
||||
- cd components/nvs_flash/test_nvs_host
|
||||
- make test
|
||||
|
||||
test_partition_table_on_host:
|
||||
stage: test
|
||||
image: $CI_DOCKER_REGISTRY/esp32-ci-env
|
||||
<<: *host_test_template
|
||||
tags:
|
||||
- build
|
||||
dependencies: []
|
||||
script:
|
||||
- cd components/partition_table/test_gen_esp32part_host
|
||||
- ./gen_esp32part_tests.py
|
||||
|
||||
test_wl_on_host:
|
||||
stage: test
|
||||
image: $CI_DOCKER_REGISTRY/esp32-ci-env
|
||||
tags:
|
||||
- wl_host_test
|
||||
<<: *host_test_template
|
||||
artifacts:
|
||||
paths:
|
||||
- components/wear_levelling/test_wl_host/coverage_report.zip
|
||||
dependencies: []
|
||||
script:
|
||||
- cd components/wear_levelling/test_wl_host
|
||||
- make test
|
||||
|
||||
test_multi_heap_on_host:
|
||||
stage: test
|
||||
image: $CI_DOCKER_REGISTRY/esp32-ci-env
|
||||
tags:
|
||||
- wl_host_test
|
||||
<<: *host_test_template
|
||||
script:
|
||||
- cd components/heap/test_multi_heap_host
|
||||
- ./test_all_configs.sh
|
||||
|
||||
test_build_system:
|
||||
stage: test
|
||||
image: $CI_DOCKER_REGISTRY/esp32-ci-env
|
||||
tags:
|
||||
- build_test
|
||||
dependencies: []
|
||||
<<: *host_test_template
|
||||
script:
|
||||
- ${IDF_PATH}/tools/ci/test_configure_ci_environment.sh
|
||||
- rm -rf test_build_system
|
||||
@@ -277,60 +270,6 @@ test_build_system:
|
||||
- cd test_build_system
|
||||
- ${IDF_PATH}/tools/ci/test_build_system.sh
|
||||
|
||||
test_report:
|
||||
stage: test_report
|
||||
image: $CI_DOCKER_REGISTRY/esp32-ci-env
|
||||
tags:
|
||||
- report
|
||||
only:
|
||||
- master
|
||||
- triggers
|
||||
- /^release\/v/
|
||||
- /^v\d+\.\d+(\.\d+)?($|-)/
|
||||
variables:
|
||||
LOG_PATH: "$CI_PROJECT_DIR/$CI_COMMIT_SHA"
|
||||
TEST_CASE_FILE_PATH: "$CI_PROJECT_DIR/components/idf_test"
|
||||
REPORT_PATH: "$CI_PROJECT_DIR/CI_Test_Report"
|
||||
MODULE_UPDATE_FILE: "$CI_PROJECT_DIR/tools/unit-test-app/tools/ModuleDefinition.yml"
|
||||
#dependencies:
|
||||
#We need all UT* and IT* artifacts except for only a few other
|
||||
artifacts:
|
||||
when: always
|
||||
paths:
|
||||
- $REPORT_PATH
|
||||
- $LOG_PATH
|
||||
expire_in: 12 mos
|
||||
script:
|
||||
# calc log path
|
||||
- VER_NUM=`git rev-list HEAD | wc -l | awk '{print $1}'`
|
||||
- SHA_ID=`echo $CI_COMMIT_SHA | cut -c 1-7`
|
||||
- REVISION="${VER_NUM}_${SHA_ID}"
|
||||
# replace / to _ in branch name
|
||||
- ESCAPED_BRANCH_NAME=`echo $CI_COMMIT_REF_NAME | sed 's/\//___/g'`
|
||||
# result path and artifacts path
|
||||
- RESULT_PATH="$CI_PROJECT_NAME/$ESCAPED_BRANCH_NAME/$REVISION"
|
||||
- ARTIFACTS_PATH="$GITLAB_HTTP_SERVER/idf/esp-idf/builds/$CI_JOB_ID/artifacts/browse/$CI_COMMIT_SHA"
|
||||
# clone test bench
|
||||
- git clone $GITLAB_SSH_SERVER/yinling/auto_test_script.git
|
||||
- cd auto_test_script
|
||||
- python $CHECKOUT_REF_SCRIPT auto_test_script
|
||||
# generate report
|
||||
- TEST_RESULT=Pass
|
||||
- python CITestReport.py -l $LOG_PATH -t $TEST_CASE_FILE_PATH -p $REPORT_PATH -r $RESULT_PATH -a $ARTIFACTS_PATH -m $MODULE_UPDATE_FILE || TEST_RESULT=Fail
|
||||
# commit to CI-test-result project
|
||||
- git clone $GITLAB_SSH_SERVER/qa/CI-test-result.git
|
||||
- rm -rf "CI-test-result/RawData/$RESULT_PATH"
|
||||
- cp -R $CI_PROJECT_NAME CI-test-result/RawData
|
||||
- cd CI-test-result
|
||||
# config git user
|
||||
- git config --global user.email "ci-test-result@espressif.com"
|
||||
- git config --global user.name "ci-test-result"
|
||||
# commit test result
|
||||
- git add .
|
||||
- git commit . -m "update test result for $CI_PROJECT_NAME/$CI_COMMIT_REF_NAME/$CI_COMMIT_SHA, pipeline ID $CI_PIPELINE_ID" || exit 0
|
||||
- git push origin master
|
||||
- test "${TEST_RESULT}" = "Pass" || exit 1
|
||||
|
||||
push_master_to_github:
|
||||
stage: deploy
|
||||
image: $CI_DOCKER_REGISTRY/esp32-ci-env
|
||||
@@ -362,8 +301,8 @@ push_master_to_github:
|
||||
|
||||
|
||||
deploy_docs:
|
||||
stage: deploy
|
||||
image: $CI_DOCKER_REGISTRY/esp32-ci-env
|
||||
stage: host_test
|
||||
image: $CI_DOCKER_REGISTRY/esp32-ci-env$BOT_DOCKER_IMAGE_TAG
|
||||
tags:
|
||||
- deploy
|
||||
only:
|
||||
@@ -389,8 +328,8 @@ deploy_docs:
|
||||
- ssh $DOCS_SERVER -x "cd $DOCS_PATH && tar xzvf $GIT_VER.tar.gz && rm -f latest && ln -s $GIT_VER latest"
|
||||
|
||||
check_doc_links:
|
||||
stage: test
|
||||
image: $CI_DOCKER_REGISTRY/esp32-ci-env
|
||||
stage: host_test
|
||||
image: $CI_DOCKER_REGISTRY/esp32-ci-env$BOT_DOCKER_IMAGE_TAG
|
||||
tags:
|
||||
- check_doc_links
|
||||
only:
|
||||
@@ -478,21 +417,28 @@ assign_test:
|
||||
- python CIAssignTestCases.py -t $IDF_PATH/components/idf_test/integration_test -c $IDF_PATH/.gitlab-ci.yml -b $IDF_PATH/SSC/ssc_bin
|
||||
|
||||
.example_test_template: &example_test_template
|
||||
stage: test
|
||||
stage: integration_test
|
||||
when: on_success
|
||||
only:
|
||||
- master
|
||||
- /^release\/v/
|
||||
- /^v\d+\.\d+(\.\d+)?($|-)/
|
||||
- triggers
|
||||
# gitlab ci do not support match job with RegEx or wildcard now in dependencies.
|
||||
# we have a lot build example jobs and the binaries them exceed the limitation of artifacts.
|
||||
# we can't artifact them in one job. For example test jobs, download all artifacts from previous stages.
|
||||
dependencies:
|
||||
- assign_test
|
||||
- build_examples_00
|
||||
- build_examples_01
|
||||
- build_examples_02
|
||||
- build_examples_03
|
||||
- build_examples_04
|
||||
- build_examples_05
|
||||
- build_examples_06
|
||||
- build_examples_07
|
||||
artifacts:
|
||||
when: always
|
||||
paths:
|
||||
- $LOG_PATH
|
||||
expire_in: 6 mos
|
||||
expire_in: 1 mos
|
||||
variables:
|
||||
TEST_FW_PATH: "$CI_PROJECT_DIR/tools/tiny-test-fw"
|
||||
TEST_CASE_PATH: "$CI_PROJECT_DIR/examples"
|
||||
@@ -506,14 +452,13 @@ assign_test:
|
||||
- python Runner.py $TEST_CASE_PATH -c $CONFIG_FILE
|
||||
|
||||
.test_template: &test_template
|
||||
stage: test
|
||||
stage: integration_test
|
||||
when: on_success
|
||||
only:
|
||||
- master
|
||||
- /^release\/v/
|
||||
- /^v\d+\.\d+(\.\d+)?($|-)/
|
||||
- triggers
|
||||
allow_failure: true
|
||||
dependencies:
|
||||
- assign_test
|
||||
- build_ssc_00
|
||||
@@ -523,7 +468,7 @@ assign_test:
|
||||
when: always
|
||||
paths:
|
||||
- $LOG_PATH
|
||||
expire_in: 6 mos
|
||||
expire_in: 1 mos
|
||||
variables:
|
||||
LOCAL_ENV_CONFIG_PATH: "$CI_PROJECT_DIR/ci-test-runner-configs/$CI_RUNNER_DESCRIPTION/ESP32_IDF"
|
||||
LOG_PATH: "$CI_PROJECT_DIR/$CI_COMMIT_SHA"
|
||||
@@ -564,7 +509,7 @@ nvs_compatible_test:
|
||||
paths:
|
||||
- $LOG_PATH
|
||||
- nvs_wifi.bin
|
||||
expire_in: 6 mos
|
||||
expire_in: 1 mos
|
||||
tags:
|
||||
- ESP32_IDF
|
||||
- NVS_Compatible
|
||||
|
||||
@@ -156,6 +156,38 @@ config BT_ACL_CONNECTIONS
|
||||
help
|
||||
Maximum BT/BLE connection count
|
||||
|
||||
config BLE_SCAN_DUPLICATE
|
||||
bool "BLE Scan Duplicate Options "
|
||||
depends on BLUEDROID_ENABLED
|
||||
default y
|
||||
help
|
||||
This select enables parameters setting of BLE scan duplicate.
|
||||
|
||||
config DUPLICATE_SCAN_CACHE_SIZE
|
||||
int "Maximum number of devices in scan duplicate filter"
|
||||
depends on BLE_SCAN_DUPLICATE
|
||||
range 10 200
|
||||
default 20
|
||||
help
|
||||
Maximum number of devices which can be recorded in scan duplicate filter.
|
||||
When the maximum amount of device in the filter is reached, the cache will be refreshed.
|
||||
|
||||
config BLE_MESH_SCAN_DUPLICATE_EN
|
||||
bool "Special duplicate scan mechanism for BLE Mesh scan"
|
||||
depends on BLE_SCAN_DUPLICATE
|
||||
default n
|
||||
help
|
||||
This enables the BLE scan duplicate for special BLE Mesh scan.
|
||||
|
||||
config MESH_DUPLICATE_SCAN_CACHE_SIZE
|
||||
int "Maximum number of Mesh adv packets in scan duplicate filter"
|
||||
depends on BLE_MESH_SCAN_DUPLICATE_EN
|
||||
range 10 200
|
||||
default 50
|
||||
help
|
||||
Maximum number of adv packets which can be recorded in duplicate scan cache for BLE Mesh.
|
||||
When the maximum amount of device in the filter is reached, the cache will be refreshed.
|
||||
|
||||
config SMP_ENABLE
|
||||
bool
|
||||
depends on BLUEDROID_ENABLED
|
||||
|
||||
@@ -264,6 +264,13 @@ typedef enum {
|
||||
3. directed advertising packets addressed to this device.*/
|
||||
} esp_ble_scan_filter_t;
|
||||
|
||||
/// Ble scan duplicate type
|
||||
typedef enum {
|
||||
BLE_SCAN_DUPLICATE_DISABLE = 0x0, /*!< the Link Layer should generate advertising reports to the host for each packet received */
|
||||
BLE_SCAN_DUPLICATE_ENABLE = 0x1, /*!< the Link Layer should filter out duplicate advertising reports to the Host */
|
||||
BLE_SCAN_DUPLICATE_MAX = 0x2, /*!< 0x02 – 0xFF, Reserved for future use */
|
||||
} esp_ble_scan_duplicate_t;
|
||||
|
||||
/// Ble scan parameters
|
||||
typedef struct {
|
||||
esp_ble_scan_type_t scan_type; /*!< Scan type */
|
||||
@@ -279,6 +286,9 @@ typedef struct {
|
||||
Range: 0x0004 to 0x4000 Default: 0x0010 (10 ms)
|
||||
Time = N * 0.625 msec
|
||||
Time Range: 2.5 msec to 10240 msec */
|
||||
esp_ble_scan_duplicate_t scan_duplicate; /*!< The Scan_Duplicates parameter controls whether the Link Layer should filter out
|
||||
duplicate advertising reports (BLE_SCAN_DUPLICATE_ENABLE) to the Host, or if the Link Layer should generate
|
||||
advertising reports for each packet received */
|
||||
} esp_ble_scan_params_t;
|
||||
|
||||
/// Connection update parameters
|
||||
|
||||
@@ -4568,6 +4568,7 @@ void bta_dm_ble_set_scan_fil_params(tBTA_DM_MSG *p_data)
|
||||
p_data->ble_set_scan_fil_params.scan_window,
|
||||
p_data->ble_set_scan_fil_params.scan_mode,
|
||||
p_data->ble_set_scan_fil_params.addr_type_own,
|
||||
p_data->ble_set_scan_fil_params.scan_duplicate_filter,
|
||||
p_data->ble_set_scan_fil_params.scan_filter_policy,
|
||||
p_data->ble_set_scan_fil_params.scan_param_setup_cback);
|
||||
}
|
||||
|
||||
@@ -968,6 +968,7 @@ void BTA_DmSetBleScanParams(tGATT_IF client_if, UINT32 scan_interval,
|
||||
** scan_interval - scan interval
|
||||
** scan_window - scan window
|
||||
** scan_mode - scan mode
|
||||
** scan_duplicate_filter - scan duplicate filter
|
||||
** scan_param_setup_status_cback - Set scan param status callback
|
||||
**
|
||||
** Returns void
|
||||
@@ -975,7 +976,7 @@ void BTA_DmSetBleScanParams(tGATT_IF client_if, UINT32 scan_interval,
|
||||
*******************************************************************************/
|
||||
void BTA_DmSetBleScanFilterParams(tGATT_IF client_if, UINT32 scan_interval,
|
||||
UINT32 scan_window, tBLE_SCAN_MODE scan_mode, UINT8 scan_fil_poilcy,
|
||||
UINT8 addr_type_own, tBLE_SCAN_PARAM_SETUP_CBACK scan_param_setup_cback)
|
||||
UINT8 addr_type_own, UINT8 scan_duplicate_filter, tBLE_SCAN_PARAM_SETUP_CBACK scan_param_setup_cback)
|
||||
{
|
||||
tBTA_DM_API_BLE_SCAN_FILTER_PARAMS *p_msg;
|
||||
|
||||
@@ -987,6 +988,7 @@ void BTA_DmSetBleScanFilterParams(tGATT_IF client_if, UINT32 scan_interval,
|
||||
p_msg->scan_window = scan_window;
|
||||
p_msg->scan_mode = scan_mode;
|
||||
p_msg->addr_type_own = addr_type_own;
|
||||
p_msg->scan_duplicate_filter = scan_duplicate_filter;
|
||||
p_msg->scan_filter_policy = scan_fil_poilcy;
|
||||
p_msg->scan_param_setup_cback = scan_param_setup_cback;
|
||||
|
||||
|
||||
@@ -485,6 +485,7 @@ typedef struct {
|
||||
UINT32 scan_window;
|
||||
tBLE_SCAN_MODE scan_mode;
|
||||
UINT8 addr_type_own;
|
||||
UINT8 scan_duplicate_filter;
|
||||
UINT8 scan_filter_policy;
|
||||
tBLE_SCAN_PARAM_SETUP_CBACK scan_param_setup_cback;
|
||||
} tBTA_DM_API_BLE_SCAN_FILTER_PARAMS;
|
||||
|
||||
@@ -1902,6 +1902,7 @@ extern void BTA_DmSetBleScanParams(tGATT_IF client_if, UINT32 scan_interval,
|
||||
** scan_interval - scan interval
|
||||
** scan_window - scan window
|
||||
** scan_mode - scan mode
|
||||
** scan_duplicate_filter - scan duplicate filter
|
||||
** scan_param_setup_status_cback - Set scan param status callback
|
||||
**
|
||||
** Returns void
|
||||
@@ -1909,7 +1910,7 @@ extern void BTA_DmSetBleScanParams(tGATT_IF client_if, UINT32 scan_interval,
|
||||
*******************************************************************************/
|
||||
extern void BTA_DmSetBleScanFilterParams(tGATT_IF client_if, UINT32 scan_interval,
|
||||
UINT32 scan_window, tBLE_SCAN_MODE scan_mode, UINT8 scan_fil_poilcy,
|
||||
UINT8 addr_type_own, tBLE_SCAN_PARAM_SETUP_CBACK scan_param_setup_cback);
|
||||
UINT8 addr_type_own, UINT8 scan_duplicate_filter, tBLE_SCAN_PARAM_SETUP_CBACK scan_param_setup_cback);
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
|
||||
@@ -41,7 +41,9 @@ static void btc_enable_bluetooth(void)
|
||||
|
||||
static void btc_disable_bluetooth(void)
|
||||
{
|
||||
#if (SMP_INCLUDED)
|
||||
btc_config_shut_down();
|
||||
#endif /* #if (SMP_INCLUDED) */
|
||||
if (BTA_DisableBluetooth() != BTA_SUCCESS) {
|
||||
future_ready(*btc_main_get_future_p(BTC_MAIN_DISABLE_FUTURE), FUTURE_FAIL);
|
||||
}
|
||||
|
||||
@@ -209,6 +209,9 @@ static void blufi_profile_cb(tBTA_GATTS_EVT event, tBTA_GATTS *p_data)
|
||||
break;
|
||||
case BTA_GATTS_CONF_EVT:
|
||||
LOG_DEBUG("CONIRM EVT\n");
|
||||
if (p_data && p_data->req_data.value){
|
||||
osi_free(p_data->req_data.value);
|
||||
}
|
||||
/* Nothing */
|
||||
break;
|
||||
case BTA_GATTS_CREATE_EVT:
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
#include "bt_utils.h"
|
||||
#include "btc_common.h"
|
||||
#include "btc_manage.h"
|
||||
#include "alarm.h"
|
||||
|
||||
#if BTC_AV_INCLUDED
|
||||
|
||||
@@ -80,7 +81,7 @@ typedef struct {
|
||||
} btc_av_cb_t;
|
||||
|
||||
typedef struct {
|
||||
bt_bdaddr_t *target_bda;
|
||||
bt_bdaddr_t target_bda;
|
||||
uint16_t uuid;
|
||||
} btc_av_connect_req_t;
|
||||
|
||||
@@ -88,7 +89,8 @@ typedef struct {
|
||||
** Static variables
|
||||
******************************************************************************/
|
||||
static btc_av_cb_t btc_av_cb = {0};
|
||||
static TIMER_LIST_ENT tle_av_open_on_rc;
|
||||
|
||||
static osi_alarm_t *tle_av_open_on_rc = NULL;
|
||||
|
||||
/* both interface and media task needs to be ready to alloc incoming request */
|
||||
#define CHECK_BTAV_INIT() do \
|
||||
@@ -203,19 +205,18 @@ UNUSED_ATTR static const char *dump_av_sm_event_name(btc_av_sm_event_t event)
|
||||
** Returns void
|
||||
**
|
||||
*******************************************************************************/
|
||||
static void btc_initiate_av_open_tmr_hdlr(TIMER_LIST_ENT *tle)
|
||||
static void btc_initiate_av_open_tmr_hdlr(void *arg)
|
||||
{
|
||||
UNUSED(arg);
|
||||
BD_ADDR peer_addr;
|
||||
UNUSED(tle);
|
||||
btc_av_connect_req_t connect_req;
|
||||
UNUSED(tle);
|
||||
/* is there at least one RC connection - There should be */
|
||||
if (btc_rc_get_connected_peer(peer_addr)) {
|
||||
LOG_DEBUG("%s Issuing connect to the remote RC peer", __FUNCTION__);
|
||||
/* In case of AVRCP connection request, we will initiate SRC connection */
|
||||
connect_req.target_bda = (bt_bdaddr_t *)&peer_addr;
|
||||
memcpy(connect_req.target_bda.address, peer_addr, sizeof(bt_bdaddr_t));
|
||||
connect_req.uuid = UUID_SERVCLASS_AUDIO_SOURCE;
|
||||
btc_sm_dispatch(btc_av_cb.sm_handle, BTC_AV_CONNECT_REQ_EVT, (char *)&connect_req);
|
||||
btc_dispatch_sm_event(BTC_AV_CONNECT_REQ_EVT, &connect_req, sizeof(btc_av_connect_req_t));
|
||||
} else {
|
||||
LOG_ERROR("%s No connected RC peers", __FUNCTION__);
|
||||
}
|
||||
@@ -289,7 +290,7 @@ static BOOLEAN btc_av_state_idle_handler(btc_sm_event_t event, void *p_data)
|
||||
case BTA_AV_PENDING_EVT:
|
||||
case BTC_AV_CONNECT_REQ_EVT: {
|
||||
if (event == BTC_AV_CONNECT_REQ_EVT) {
|
||||
memcpy(&btc_av_cb.peer_bda, ((btc_av_connect_req_t *)p_data)->target_bda,
|
||||
memcpy(&btc_av_cb.peer_bda, &((btc_av_connect_req_t *)p_data)->target_bda,
|
||||
sizeof(bt_bdaddr_t));
|
||||
BTA_AvOpen(btc_av_cb.peer_bda.address, btc_av_cb.bta_handle,
|
||||
TRUE, BTA_SEC_AUTHENTICATE, ((btc_av_connect_req_t *)p_data)->uuid);
|
||||
@@ -313,10 +314,8 @@ static BOOLEAN btc_av_state_idle_handler(btc_sm_event_t event, void *p_data)
|
||||
*/
|
||||
|
||||
LOG_DEBUG("BTA_AV_RC_OPEN_EVT received w/o AV");
|
||||
memset(&tle_av_open_on_rc, 0, sizeof(tle_av_open_on_rc));
|
||||
tle_av_open_on_rc.param = (UINT32)btc_initiate_av_open_tmr_hdlr;
|
||||
btu_start_timer(&tle_av_open_on_rc, BTU_TTYPE_USER_FUNC,
|
||||
BTC_TIMEOUT_AV_OPEN_ON_RC_SECS);
|
||||
tle_av_open_on_rc = osi_alarm_new("AVconn", btc_initiate_av_open_tmr_hdlr, NULL, BTC_TIMEOUT_AV_OPEN_ON_RC_SECS * 1000);
|
||||
osi_alarm_set(tle_av_open_on_rc, BTC_TIMEOUT_AV_OPEN_ON_RC_SECS * 1000);
|
||||
btc_rc_handler(event, p_data);
|
||||
break;
|
||||
|
||||
@@ -329,9 +328,9 @@ static BOOLEAN btc_av_state_idle_handler(btc_sm_event_t event, void *p_data)
|
||||
break;
|
||||
|
||||
case BTA_AV_RC_CLOSE_EVT:
|
||||
if (tle_av_open_on_rc.in_use) {
|
||||
LOG_DEBUG("BTA_AV_RC_CLOSE_EVT: Stopping AV timer.");
|
||||
btu_stop_timer(&tle_av_open_on_rc);
|
||||
if (tle_av_open_on_rc) {
|
||||
osi_alarm_free(tle_av_open_on_rc);
|
||||
tle_av_open_on_rc = NULL;
|
||||
}
|
||||
btc_rc_handler(event, p_data);
|
||||
break;
|
||||
@@ -616,7 +615,7 @@ static BOOLEAN btc_av_state_opened_handler(btc_sm_event_t event, void *p_data)
|
||||
break;
|
||||
|
||||
case BTC_AV_CONNECT_REQ_EVT:
|
||||
if (memcmp ((bt_bdaddr_t *)p_data, &(btc_av_cb.peer_bda),
|
||||
if (memcmp (&((btc_av_connect_req_t *)p_data)->target_bda, &(btc_av_cb.peer_bda),
|
||||
sizeof(btc_av_cb.peer_bda)) == 0) {
|
||||
LOG_DEBUG("%s: Ignore BTC_AVCONNECT_REQ_EVT for same device\n", __func__);
|
||||
} else {
|
||||
@@ -972,7 +971,7 @@ bt_status_t btc_a2d_sink_init(void)
|
||||
static bt_status_t connect_int(bt_bdaddr_t *bd_addr, uint16_t uuid)
|
||||
{
|
||||
btc_av_connect_req_t connect_req;
|
||||
connect_req.target_bda = bd_addr;
|
||||
memcpy(&connect_req.target_bda, bd_addr, sizeof(bt_bdaddr_t));
|
||||
connect_req.uuid = uuid;
|
||||
LOG_DEBUG("%s\n", __FUNCTION__);
|
||||
|
||||
@@ -1001,7 +1000,6 @@ bt_status_t btc_a2d_sink_connect(bt_bdaddr_t *remote_bda)
|
||||
static void btc_a2d_sink_deinit(void)
|
||||
{
|
||||
LOG_DEBUG("%s\n", __FUNCTION__);
|
||||
|
||||
btc_dm_disable_service(BTA_A2DP_SOURCE_SERVICE_ID);
|
||||
#if (BTA_AV_SINK_INCLUDED == TRUE)
|
||||
btc_dm_disable_service(BTA_A2DP_SINK_SERVICE_ID);
|
||||
@@ -1232,6 +1230,9 @@ void btc_a2dp_call_handler(btc_msg_t *msg)
|
||||
btc_a2dp_sink_reg_data_cb(arg->data_cb);
|
||||
break;
|
||||
}
|
||||
case BTC_AV_CONNECT_REQ_EVT:
|
||||
btc_sm_dispatch(btc_av_cb.sm_handle, msg->act, (char *)msg->arg);
|
||||
break;
|
||||
default:
|
||||
LOG_WARN("%s : unhandled event: %d\n", __FUNCTION__, msg->act);
|
||||
}
|
||||
|
||||
@@ -520,9 +520,8 @@ static void btc_ble_start_advertising (esp_ble_adv_params_t *ble_adv_params, tBT
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
LOG_DEBUG("API_Ble_AppStartAdvertising\n");
|
||||
|
||||
LOG_DEBUG("API_Ble_AppStartAdvertising\n");
|
||||
memcpy(peer_addr.bda, ble_adv_params->peer_addr, ESP_BD_ADDR_LEN);
|
||||
peer_addr.type = ble_adv_params->peer_addr_type;
|
||||
BTA_DmSetBleAdvParamsAll(ble_adv_params->adv_int_min,
|
||||
@@ -561,6 +560,7 @@ static void btc_ble_set_scan_params(esp_ble_scan_params_t *scan_params, tBLE_SCA
|
||||
BLE_ISVALID_PARAM(scan_params->scan_window, BTM_BLE_SCAN_WIN_MIN, BTM_BLE_SCAN_WIN_MAX) &&
|
||||
BLE_ISVALID_PARAM(scan_params->own_addr_type, BLE_ADDR_TYPE_PUBLIC, BLE_ADDR_TYPE_RPA_RANDOM) &&
|
||||
BLE_ISVALID_PARAM(scan_params->scan_filter_policy, BLE_SCAN_FILTER_ALLOW_ALL, BLE_SCAN_FILTER_ALLOW_WLIST_PRA_DIR) &&
|
||||
BLE_ISVALID_PARAM(scan_params->scan_duplicate, BLE_SCAN_DUPLICATE_DISABLE, BLE_SCAN_DUPLICATE_MAX -1) &&
|
||||
(scan_params->scan_type == BTM_BLE_SCAN_MODE_ACTI || scan_params->scan_type == BTM_BLE_SCAN_MODE_PASS)) {
|
||||
BTA_DmSetBleScanFilterParams(ESP_DEFAULT_GATT_IF, /*client_if*/
|
||||
scan_params->scan_interval,
|
||||
@@ -568,6 +568,7 @@ static void btc_ble_set_scan_params(esp_ble_scan_params_t *scan_params, tBLE_SCA
|
||||
scan_params->scan_type,
|
||||
scan_params->scan_filter_policy,
|
||||
scan_params->own_addr_type,
|
||||
scan_params->scan_duplicate,
|
||||
scan_param_setup_cback);
|
||||
} else {
|
||||
btc_scan_params_callback(ESP_DEFAULT_GATT_IF, BTM_ILLEGAL_VALUE);
|
||||
@@ -723,12 +724,12 @@ static void btc_add_whitelist_complete_callback(UINT8 status, tBTM_WL_OPERATION
|
||||
}
|
||||
}
|
||||
|
||||
static void btc_set_rand_addr_callback(UINT8 status)
|
||||
static void btc_set_rand_addr_callback(UINT8 status)
|
||||
{
|
||||
esp_ble_gap_cb_param_t param;
|
||||
bt_status_t ret;
|
||||
btc_msg_t msg;
|
||||
param.set_rand_addr_cmpl.status = btc_btm_status_to_esp_status(status); //todo status
|
||||
param.set_rand_addr_cmpl.status = btc_btm_status_to_esp_status(status); //todo status
|
||||
msg.sig = BTC_SIG_API_CB;
|
||||
msg.pid = BTC_PID_GAP_BLE;
|
||||
msg.act = ESP_GAP_BLE_SET_STATIC_RAND_ADDR_EVT;
|
||||
@@ -1010,6 +1011,13 @@ void btc_gap_ble_arg_deep_free(btc_msg_t *msg)
|
||||
}
|
||||
break;
|
||||
}
|
||||
case BTC_GAP_BLE_SET_SECURITY_PARAM_EVT: {
|
||||
uint8_t *value = ((btc_ble_gap_args_t *)msg->arg)->set_security_param.value;
|
||||
if (value) {
|
||||
osi_free(value);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
LOG_DEBUG("Unhandled deep free %d\n", msg->act);
|
||||
break;
|
||||
@@ -1108,36 +1116,37 @@ void btc_gap_ble_call_handler(btc_msg_t *msg)
|
||||
break;
|
||||
}
|
||||
case BTC_GAP_BLE_SET_SECURITY_PARAM_EVT: {
|
||||
uint8_t *value = arg->set_security_param.value;
|
||||
switch(arg->set_security_param.param_type) {
|
||||
case ESP_BLE_SM_PASSKEY:
|
||||
break;
|
||||
case ESP_BLE_SM_AUTHEN_REQ_MODE: {
|
||||
uint8_t authen_req = 0;
|
||||
STREAM_TO_UINT8(authen_req, arg->set_security_param.value);
|
||||
STREAM_TO_UINT8(authen_req, value);
|
||||
bta_dm_co_ble_set_auth_req(authen_req);
|
||||
break;
|
||||
}
|
||||
case ESP_BLE_SM_IOCAP_MODE: {
|
||||
uint8_t iocap = 0;
|
||||
STREAM_TO_UINT8(iocap, arg->set_security_param.value);
|
||||
STREAM_TO_UINT8(iocap, value);
|
||||
bta_dm_co_ble_set_io_cap(iocap);
|
||||
break;
|
||||
}
|
||||
case ESP_BLE_SM_SET_INIT_KEY: {
|
||||
uint8_t init_key = 0;
|
||||
STREAM_TO_UINT8(init_key, arg->set_security_param.value);
|
||||
STREAM_TO_UINT8(init_key, value);
|
||||
bta_dm_co_ble_set_init_key_req(init_key);
|
||||
break;
|
||||
}
|
||||
case ESP_BLE_SM_SET_RSP_KEY: {
|
||||
uint8_t rsp_key = 0;
|
||||
STREAM_TO_UINT8(rsp_key, arg->set_security_param.value);
|
||||
STREAM_TO_UINT8(rsp_key, value);
|
||||
bta_dm_co_ble_set_rsp_key_req(rsp_key);
|
||||
break;
|
||||
}
|
||||
case ESP_BLE_SM_MAX_KEY_SIZE: {
|
||||
uint8_t key_size = 0;
|
||||
STREAM_TO_UINT8(key_size, arg->set_security_param.value);
|
||||
STREAM_TO_UINT8(key_size, value);
|
||||
bta_dm_co_ble_set_max_key_size(key_size);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -671,7 +671,7 @@ void btc_gattc_call_handler(btc_msg_t *msg)
|
||||
btc_ble_gattc_args_t *arg = (btc_ble_gattc_args_t *)(msg->arg);
|
||||
switch (msg->act) {
|
||||
case BTC_GATTC_ACT_APP_REGISTER:
|
||||
LOG_ERROR("%s()", __func__);
|
||||
LOG_DEBUG("%s()", __func__);
|
||||
btc_gattc_app_register(arg);
|
||||
break;
|
||||
case BTC_GATTC_ACT_APP_UNREGISTER:
|
||||
|
||||
@@ -506,6 +506,8 @@ static void btc_gatts_cb_param_copy_req(btc_msg_t *msg, void *p_dest, void *p_sr
|
||||
if (p_dest_data->req_data.p_data != NULL) {
|
||||
memcpy(p_dest_data->req_data.p_data, p_src_data->req_data.p_data,
|
||||
sizeof(tBTA_GATTS_REQ_DATA));
|
||||
} else {
|
||||
LOG_ERROR("%s %d no mem\n", __func__, msg->act);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -759,6 +761,9 @@ void btc_gatts_cb_handler(btc_msg_t *msg)
|
||||
param.write.conn_id = BTC_GATT_GET_CONN_ID(p_data->req_data.conn_id);
|
||||
param.write.trans_id = p_data->req_data.trans_id;
|
||||
memcpy(param.write.bda, p_data->req_data.remote_bda, ESP_BD_ADDR_LEN);
|
||||
if (p_data->req_data.p_data == NULL) {
|
||||
break;
|
||||
}
|
||||
param.write.handle = p_data->req_data.p_data->write_req.handle;
|
||||
param.write.offset = p_data->req_data.p_data->write_req.offset;
|
||||
param.write.need_rsp = p_data->req_data.p_data->write_req.need_rsp;
|
||||
@@ -775,6 +780,9 @@ void btc_gatts_cb_handler(btc_msg_t *msg)
|
||||
param.exec_write.conn_id = BTC_GATT_GET_CONN_ID(p_data->req_data.conn_id);
|
||||
param.exec_write.trans_id = p_data->req_data.trans_id;
|
||||
memcpy(param.exec_write.bda, p_data->req_data.remote_bda, ESP_BD_ADDR_LEN);
|
||||
if (p_data->req_data.p_data == NULL) {
|
||||
break;
|
||||
}
|
||||
param.exec_write.exec_write_flag = p_data->req_data.p_data->exec_write;
|
||||
|
||||
btc_gatts_cb_to_app(ESP_GATTS_EXEC_WRITE_EVT, gatts_if, ¶m);
|
||||
|
||||
@@ -403,7 +403,6 @@ tBTM_STATUS BTM_BleObserve(BOOLEAN start, UINT32 duration,
|
||||
BTM_BLE_DEFAULT_SFP);
|
||||
}
|
||||
|
||||
p_inq->scan_duplicate_filter = BTM_BLE_DUPLICATE_DISABLE;
|
||||
status = btm_ble_start_scan();
|
||||
}
|
||||
|
||||
@@ -442,7 +441,6 @@ tBTM_STATUS BTM_BleObserve(BOOLEAN start, UINT32 duration,
|
||||
tBTM_STATUS BTM_BleScan(BOOLEAN start, UINT32 duration,
|
||||
tBTM_INQ_RESULTS_CB *p_results_cb, tBTM_CMPL_CB *p_cmpl_cb)
|
||||
{
|
||||
tBTM_BLE_INQ_CB *p_inq = &btm_cb.ble_ctr_cb.inq_var;
|
||||
tBTM_STATUS status = BTM_WRONG_MODE;
|
||||
|
||||
if (!controller_get_interface()->supports_ble()) {
|
||||
@@ -467,7 +465,6 @@ tBTM_STATUS BTM_BleScan(BOOLEAN start, UINT32 duration,
|
||||
/* enable resolving list */
|
||||
btm_ble_enable_resolving_list_for_platform(BTM_BLE_RL_SCAN);
|
||||
#endif
|
||||
p_inq->scan_duplicate_filter = BTM_BLE_DUPLICATE_DISABLE;
|
||||
status = btm_ble_start_scan();
|
||||
}
|
||||
|
||||
@@ -1370,7 +1367,7 @@ void BTM_BleSetScanParams(tGATT_IF client_if, UINT32 scan_interval, UINT32 scan_
|
||||
}
|
||||
|
||||
void BTM_BleSetScanFilterParams(tGATT_IF client_if, UINT32 scan_interval, UINT32 scan_window,
|
||||
tBLE_SCAN_MODE scan_mode, UINT8 addr_type_own, tBTM_BLE_SFP scan_filter_policy,
|
||||
tBLE_SCAN_MODE scan_mode, UINT8 addr_type_own, UINT8 scan_duplicate_filter, tBTM_BLE_SFP scan_filter_policy,
|
||||
tBLE_SCAN_PARAM_SETUP_CBACK scan_setup_status_cback)
|
||||
{
|
||||
tBTM_BLE_INQ_CB *p_cb = &btm_cb.ble_ctr_cb.inq_var;
|
||||
@@ -1413,6 +1410,7 @@ void BTM_BleSetScanFilterParams(tGATT_IF client_if, UINT32 scan_interval, UINT32
|
||||
p_cb->scan_window = scan_window;
|
||||
p_cb->sfp = scan_filter_policy;
|
||||
p_cb->scan_params_set = TRUE;
|
||||
p_cb->scan_duplicate_filter = scan_duplicate_filter;
|
||||
|
||||
btsnd_hcic_ble_set_scan_params(p_cb->scan_type, (UINT16)scan_interval,
|
||||
(UINT16)scan_window,
|
||||
@@ -2282,7 +2280,6 @@ tBTM_STATUS btm_ble_start_inquiry (UINT8 mode, UINT8 duration)
|
||||
/* enable IRK list */
|
||||
btm_ble_enable_resolving_list_for_platform(BTM_BLE_RL_SCAN);
|
||||
#endif
|
||||
p_ble_cb->inq_var.scan_duplicate_filter = BTM_BLE_DUPLICATE_DISABLE;
|
||||
status = btm_ble_start_scan();
|
||||
} else if ((p_ble_cb->inq_var.scan_interval != BTM_BLE_LOW_LATENCY_SCAN_INT) ||
|
||||
(p_ble_cb->inq_var.scan_window != BTM_BLE_LOW_LATENCY_SCAN_WIN)) {
|
||||
@@ -3196,6 +3193,9 @@ tBTM_STATUS btm_ble_start_scan(void)
|
||||
tBTM_STATUS status = BTM_CMD_STARTED;
|
||||
// recoverly the scan parameters to the controller before start scan
|
||||
btm_ble_recover_scan_params();
|
||||
if(p_inq->scan_duplicate_filter > BTM_BLE_DUPLICATE_MAX) {
|
||||
p_inq->scan_duplicate_filter = BTM_BLE_DUPLICATE_DISABLE;
|
||||
}
|
||||
/* 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;
|
||||
|
||||
@@ -906,7 +906,30 @@ static void btu_hcif_hdl_command_complete (UINT16 opcode, UINT8 *p, UINT16 evt_l
|
||||
case HCI_BLE_CLEAR_WHITE_LIST:
|
||||
btm_ble_clear_white_list_complete(p, evt_len);
|
||||
break;
|
||||
|
||||
case HCI_BLE_WRITE_ADV_PARAMS: {
|
||||
uint8_t status;
|
||||
STREAM_TO_UINT8 (status, p);
|
||||
if(status != HCI_SUCCESS) {
|
||||
HCI_TRACE_ERROR("hci write adv params error 0x%x", status);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case HCI_BLE_RC_PARAM_REQ_REPLY: {
|
||||
uint8_t status;
|
||||
STREAM_TO_UINT8 (status, p);
|
||||
if(status != HCI_SUCCESS) {
|
||||
HCI_TRACE_ERROR("hci connection params reply command error 0x%x", status);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case HCI_BLE_RC_PARAM_REQ_NEG_REPLY: {
|
||||
uint8_t status;
|
||||
STREAM_TO_UINT8 (status, p);
|
||||
if(status != HCI_SUCCESS) {
|
||||
HCI_TRACE_ERROR("hci connection params neg reply command error 0x%x", status);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case HCI_BLE_REMOVE_WHITE_LIST:
|
||||
btm_ble_remove_from_white_list_complete(p, evt_len);
|
||||
break;
|
||||
|
||||
@@ -1050,6 +1050,7 @@ void BTM_BleSetScanParams(tGATT_IF client_if, UINT32 scan_interval,
|
||||
** scan_window - Scan window
|
||||
** scan_type - Scan type
|
||||
** addr_type_own - owner address type
|
||||
** scan_duplicate_filter - scan duplicate filter
|
||||
** scan_filter_policy - scan filter policy
|
||||
** scan_setup_status_cback - Scan setup status callback
|
||||
**
|
||||
@@ -1057,7 +1058,7 @@ void BTM_BleSetScanParams(tGATT_IF client_if, UINT32 scan_interval,
|
||||
**
|
||||
*******************************************************************************/
|
||||
void BTM_BleSetScanFilterParams(tGATT_IF client_if, UINT32 scan_interval, UINT32 scan_window,
|
||||
tBLE_SCAN_MODE scan_mode, UINT8 addr_type_own, tBTM_BLE_SFP scan_filter_policy,
|
||||
tBLE_SCAN_MODE scan_mode, UINT8 addr_type_own, UINT8 scan_duplicate_filter, tBTM_BLE_SFP scan_filter_policy,
|
||||
tBLE_SCAN_PARAM_SETUP_CBACK scan_setup_status_cback);
|
||||
|
||||
|
||||
|
||||
@@ -55,8 +55,9 @@
|
||||
|
||||
#define BTM_BLE_ENC_MASK 0x03
|
||||
|
||||
#define BTM_BLE_DUPLICATE_ENABLE 1
|
||||
#define BTM_BLE_DUPLICATE_DISABLE 0
|
||||
#define BTM_BLE_DUPLICATE_ENABLE 1
|
||||
#define BTM_BLE_DUPLICATE_MAX BTM_BLE_DUPLICATE_ENABLE
|
||||
|
||||
#define BTM_BLE_GAP_DISC_SCAN_INT 18 /* Interval(scan_int) = 11.25 ms= 0x0010 * 0.625 ms */
|
||||
#define BTM_BLE_GAP_DISC_SCAN_WIN 18 /* scan_window = 11.25 ms= 0x0010 * 0.625 ms */
|
||||
|
||||
@@ -50,6 +50,8 @@
|
||||
#define BTDM_CFG_BT_DATA_RELEASE (1<<0)
|
||||
#define BTDM_CFG_HCI_UART (1<<1)
|
||||
#define BTDM_CFG_CONTROLLER_RUN_APP_CPU (1<<2)
|
||||
#define BTDM_CFG_SCAN_DUPLICATE_OPTIONS (1<<3)
|
||||
#define BTDM_CFG_SEND_ADV_RESERVED_SIZE (1<<4)
|
||||
/* Other reserved for future */
|
||||
|
||||
/* not for user call, so don't put to include file */
|
||||
@@ -600,6 +602,10 @@ static uint32_t btdm_config_mask_load(void)
|
||||
#if CONFIG_BTDM_CONTROLLER_PINNED_TO_CORE == 1
|
||||
mask |= BTDM_CFG_CONTROLLER_RUN_APP_CPU;
|
||||
#endif
|
||||
mask |= BTDM_CFG_SCAN_DUPLICATE_OPTIONS;
|
||||
|
||||
mask |= BTDM_CFG_SEND_ADV_RESERVED_SIZE;
|
||||
|
||||
return mask;
|
||||
}
|
||||
|
||||
|
||||
@@ -35,9 +35,19 @@ typedef struct {
|
||||
uint8_t controller_task_prio; /*!< Bluetooth controller task priority */
|
||||
uint8_t hci_uart_no; /*!< If use UART1/2 as HCI IO interface, indicate UART number */
|
||||
uint32_t hci_uart_baudrate; /*!< If use UART1/2 as HCI IO interface, indicate UART baudrate */
|
||||
uint8_t scan_duplicate_mode; /*!< If use UART1/2 as HCI IO interface, indicate UART baudrate */
|
||||
uint16_t normal_adv_size; /*!< Normal adv size for scan duplicate */
|
||||
uint16_t mesh_adv_size; /*!< Mesh adv size for scan duplicate */
|
||||
uint16_t send_adv_reserved_size; /*!< Controller minimum memory value */
|
||||
uint32_t controller_debug_flag; /*!< Controller debug log flag */
|
||||
} esp_bt_controller_config_t;
|
||||
|
||||
#ifdef CONFIG_BT_ENABLED
|
||||
/* While scanning, if the free memory value in controller is less than SCAN_SEND_ADV_RESERVED_SIZE,
|
||||
the adv packet will be discarded until the memory is restored. */
|
||||
#define SCAN_SEND_ADV_RESERVED_SIZE 1000
|
||||
/* open controller log debug when adv lost */
|
||||
#define CONTROLLER_ADV_LOST_DEBUG_BIT (0<<0)
|
||||
|
||||
#ifdef CONFIG_BT_HCI_UART_NO
|
||||
#define BT_HCI_UART_NO_DEFAULT CONFIG_BT_HCI_UART_NO
|
||||
@@ -51,11 +61,42 @@ typedef struct {
|
||||
#define BT_HCI_UART_BAUDRATE_DEFAULT 921600
|
||||
#endif /* BT_HCI_UART_BAUDRATE_DEFAULT */
|
||||
|
||||
/* normal adv cache size */
|
||||
#ifdef CONFIG_DUPLICATE_SCAN_CACHE_SIZE
|
||||
#define NORMAL_SCAN_DUPLICATE_CACHE_SIZE CONFIG_DUPLICATE_SCAN_CACHE_SIZE
|
||||
#else
|
||||
#define NORMAL_SCAN_DUPLICATE_CACHE_SIZE 20
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_BLE_MESH_SCAN_DUPLICATE_EN
|
||||
#define CONFIG_BLE_MESH_SCAN_DUPLICATE_EN FALSE
|
||||
#endif
|
||||
|
||||
#define SCAN_DUPLICATE_MODE_NORMAL_ADV_ONLY 0
|
||||
#define SCAN_DUPLICATE_MODE_NORMAL_ADV_MESH_ADV 1
|
||||
|
||||
#if CONFIG_BLE_MESH_SCAN_DUPLICATE_EN
|
||||
#define SCAN_DUPLICATE_MODE SCAN_DUPLICATE_MODE_NORMAL_ADV_MESH_ADV
|
||||
#ifdef CONFIG_MESH_DUPLICATE_SCAN_CACHE_SIZE
|
||||
#define MESH_DUPLICATE_SCAN_CACHE_SIZE CONFIG_MESH_DUPLICATE_SCAN_CACHE_SIZE
|
||||
#else
|
||||
#define MESH_DUPLICATE_SCAN_CACHE_SIZE 50
|
||||
#endif
|
||||
#else
|
||||
#define SCAN_DUPLICATE_MODE SCAN_DUPLICATE_MODE_NORMAL_ADV_ONLY
|
||||
#define MESH_DUPLICATE_SCAN_CACHE_SIZE 0
|
||||
#endif
|
||||
|
||||
#define BT_CONTROLLER_INIT_CONFIG_DEFAULT() { \
|
||||
.controller_task_stack_size = ESP_TASK_BT_CONTROLLER_STACK, \
|
||||
.controller_task_prio = ESP_TASK_BT_CONTROLLER_PRIO, \
|
||||
.hci_uart_no = BT_HCI_UART_NO_DEFAULT, \
|
||||
.hci_uart_baudrate = BT_HCI_UART_BAUDRATE_DEFAULT, \
|
||||
.scan_duplicate_mode = SCAN_DUPLICATE_MODE, \
|
||||
.normal_adv_size = NORMAL_SCAN_DUPLICATE_CACHE_SIZE, \
|
||||
.mesh_adv_size = MESH_DUPLICATE_SCAN_CACHE_SIZE, \
|
||||
.send_adv_reserved_size = SCAN_SEND_ADV_RESERVED_SIZE, \
|
||||
.controller_debug_flag = CONTROLLER_ADV_LOST_DEBUG_BIT, \
|
||||
};
|
||||
#else
|
||||
#define BT_CONTROLLER_INIT_CONFIG_DEFAULT() {0}; _Static_assert(0, "please enable bluetooth in menuconfig to use bt.h");
|
||||
|
||||
Submodule components/bt/lib updated: b76cf6aa30...959eeeb517
73
components/driver/adc1_i2s_private.h
Normal file
73
components/driver/adc1_i2s_private.h
Normal file
@@ -0,0 +1,73 @@
|
||||
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef _DRIVER_ADC1_I2S_PRIVATE_H_
|
||||
#define _DRIVER_ADC1_I2S_PRIVATE_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "esp_err.h"
|
||||
|
||||
|
||||
/**
|
||||
* @brief Force power on for SAR ADC.
|
||||
* This function should be called for the scenario in which ADC are controlled by digital function like DMA.
|
||||
* When the ADC power is always on, RTC FSM can still be functional.
|
||||
* This is an internal API for I2S module to call to enable I2S-ADC function.
|
||||
* Note that adc_power_off() can still power down ADC.
|
||||
*/
|
||||
void adc_power_always_on();
|
||||
|
||||
/**
|
||||
* @brief For I2S dma to claim the usage of ADC1.
|
||||
*
|
||||
* Other tasks will be forbidden to use ADC1 between ``adc1_i2s_mode_acquire`` and ``adc1_i2s_release``.
|
||||
* The I2S module may have to wait for a short time for the current conversion (if exist) to finish.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK success
|
||||
* - ESP_ERR_TIMEOUT reserved for future use. Currently the function will wait until success.
|
||||
*/
|
||||
esp_err_t adc1_i2s_mode_acquire();
|
||||
|
||||
/**
|
||||
* @brief For ADC1 to claim the usage of ADC1.
|
||||
*
|
||||
* Other tasks will be forbidden to use ADC1 between ``adc1_adc_mode_acquire`` and ``adc1_i2s_release``.
|
||||
* The ADC1 may have to wait for some time for the I2S read operation to finish.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK success
|
||||
* - ESP_ERR_TIMEOUT reserved for future use. Currently the function will wait until success.
|
||||
*/
|
||||
esp_err_t adc1_adc_mode_acquire();
|
||||
|
||||
/**
|
||||
* @brief to let other tasks use the ADC1 when I2S is not work.
|
||||
*
|
||||
* Other tasks will be forbidden to use ADC1 between ``adc1_adc/i2s_mode_acquire`` and ``adc1_i2s_release``.
|
||||
* Call this function to release the occupation of ADC1
|
||||
*
|
||||
* @return always return ESP_OK.
|
||||
*/
|
||||
esp_err_t adc1_lock_release();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /*_DRIVER_ADC1_I2S_PRIVATE_H_*/
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
#include "driver/i2s.h"
|
||||
#include "driver/rtc_io.h"
|
||||
#include "driver/dac.h"
|
||||
#include "adc1_i2s_private.h"
|
||||
|
||||
#include "esp_intr.h"
|
||||
#include "esp_err.h"
|
||||
@@ -84,12 +85,14 @@ typedef struct {
|
||||
int bits_per_sample; /*!< Bits per sample*/
|
||||
i2s_mode_t mode; /*!< I2S Working mode*/
|
||||
int use_apll; /*!< I2S use APLL clock */
|
||||
uint32_t sample_rate; /*!< I2S sample rate */
|
||||
} i2s_obj_t;
|
||||
|
||||
static i2s_obj_t *p_i2s_obj[I2S_NUM_MAX] = {0};
|
||||
static i2s_dev_t* I2S[I2S_NUM_MAX] = {&I2S0, &I2S1};
|
||||
static portMUX_TYPE i2s_spinlock[I2S_NUM_MAX] = {portMUX_INITIALIZER_UNLOCKED, portMUX_INITIALIZER_UNLOCKED};
|
||||
|
||||
static int _i2s_adc_unit = -1;
|
||||
static int _i2s_adc_channel = -1;
|
||||
/**
|
||||
* @brief Pre define APLL parameters, save compute time
|
||||
* | bits_per_sample | rate | sdm0 | sdm1 | sdm2 | odir
|
||||
@@ -322,12 +325,11 @@ esp_err_t i2s_set_clk(i2s_port_t i2s_num, uint32_t rate, i2s_bits_per_sample_t b
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
|
||||
if (p_i2s_obj[i2s_num] == NULL) {
|
||||
ESP_LOGE(I2S_TAG, "Not initialized yet");
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
p_i2s_obj[i2s_num]->sample_rate = rate;
|
||||
double clkmdiv = (double)I2S_BASE_CLK / (rate * factor);
|
||||
|
||||
if (clkmdiv > 256) {
|
||||
@@ -652,6 +654,18 @@ esp_err_t i2s_start(i2s_port_t i2s_num)
|
||||
I2S_CHECK((i2s_num < I2S_NUM_MAX), "i2s_num error", ESP_ERR_INVALID_ARG);
|
||||
//start DMA link
|
||||
I2S_ENTER_CRITICAL();
|
||||
i2s_reset_fifo(i2s_num);
|
||||
//reset dma
|
||||
I2S[i2s_num]->lc_conf.in_rst = 1;
|
||||
I2S[i2s_num]->lc_conf.in_rst = 0;
|
||||
I2S[i2s_num]->lc_conf.out_rst = 1;
|
||||
I2S[i2s_num]->lc_conf.out_rst = 0;
|
||||
|
||||
I2S[i2s_num]->conf.tx_reset = 1;
|
||||
I2S[i2s_num]->conf.tx_reset = 0;
|
||||
I2S[i2s_num]->conf.rx_reset = 1;
|
||||
I2S[i2s_num]->conf.rx_reset = 0;
|
||||
|
||||
esp_intr_disable(p_i2s_obj[i2s_num]->i2s_isr_handle);
|
||||
I2S[i2s_num]->int_clr.val = 0xFFFFFFFF;
|
||||
if (p_i2s_obj[i2s_num]->mode & I2S_MODE_TX) {
|
||||
@@ -685,17 +699,6 @@ esp_err_t i2s_stop(i2s_port_t i2s_num)
|
||||
i2s_disable_rx_intr(i2s_num);
|
||||
}
|
||||
I2S[i2s_num]->int_clr.val = I2S[i2s_num]->int_st.val; //clear pending interrupt
|
||||
i2s_reset_fifo(i2s_num);
|
||||
//reset dma
|
||||
I2S[i2s_num]->lc_conf.in_rst = 1;
|
||||
I2S[i2s_num]->lc_conf.in_rst = 0;
|
||||
I2S[i2s_num]->lc_conf.out_rst = 1;
|
||||
I2S[i2s_num]->lc_conf.out_rst = 0;
|
||||
|
||||
I2S[i2s_num]->conf.tx_reset = 1;
|
||||
I2S[i2s_num]->conf.tx_reset = 0;
|
||||
I2S[i2s_num]->conf.rx_reset = 1;
|
||||
I2S[i2s_num]->conf.rx_reset = 0;
|
||||
I2S_EXIT_CRITICAL();
|
||||
return ESP_OK;
|
||||
}
|
||||
@@ -722,10 +725,18 @@ esp_err_t i2s_set_dac_mode(i2s_dac_mode_t dac_mode)
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t _i2s_adc_mode_recover()
|
||||
{
|
||||
I2S_CHECK(((_i2s_adc_unit != -1) && (_i2s_adc_channel != -1)), "i2s ADC recover error, not initialized...", ESP_ERR_INVALID_ARG);
|
||||
return adc_i2s_mode_init(_i2s_adc_unit, _i2s_adc_channel);
|
||||
}
|
||||
|
||||
esp_err_t i2s_set_adc_mode(adc_unit_t adc_unit, adc1_channel_t adc_channel)
|
||||
{
|
||||
I2S_CHECK((adc_unit < ADC_UNIT_2), "i2s ADC unit error, only support ADC1 for now", ESP_ERR_INVALID_ARG);
|
||||
// For now, we only support SAR ADC1.
|
||||
_i2s_adc_unit = adc_unit;
|
||||
_i2s_adc_channel = adc_channel;
|
||||
return adc_i2s_mode_init(adc_unit, adc_channel);
|
||||
}
|
||||
|
||||
@@ -864,7 +875,7 @@ static esp_err_t i2s_param_config(i2s_port_t i2s_num, const i2s_config_t *i2s_co
|
||||
//initialize the specific ADC channel.
|
||||
//in the current stage, we only support ADC1 and single channel mode.
|
||||
//In default data mode, the ADC data is in 12-bit resolution mode.
|
||||
adc_power_on();
|
||||
adc_power_always_on();
|
||||
}
|
||||
// configure I2S data port interface.
|
||||
i2s_reset_fifo(i2s_num);
|
||||
@@ -1171,6 +1182,27 @@ esp_err_t i2s_write(i2s_port_t i2s_num, const void *src, size_t size, size_t *by
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t i2s_adc_enable(i2s_port_t i2s_num)
|
||||
{
|
||||
I2S_CHECK((i2s_num < I2S_NUM_MAX), "i2s_num error", ESP_ERR_INVALID_ARG);
|
||||
I2S_CHECK((p_i2s_obj[i2s_num] != NULL), "Not initialized yet", ESP_ERR_INVALID_STATE);
|
||||
I2S_CHECK((p_i2s_obj[i2s_num]->mode & I2S_MODE_ADC_BUILT_IN), "i2s built-in adc not enabled", ESP_ERR_INVALID_STATE);
|
||||
|
||||
adc1_i2s_mode_acquire();
|
||||
_i2s_adc_mode_recover();
|
||||
return i2s_set_clk(i2s_num, p_i2s_obj[i2s_num]->sample_rate, p_i2s_obj[i2s_num]->bits_per_sample, p_i2s_obj[i2s_num]->channel_num);
|
||||
}
|
||||
|
||||
esp_err_t i2s_adc_disable(i2s_port_t i2s_num)
|
||||
{
|
||||
I2S_CHECK((i2s_num < I2S_NUM_MAX), "i2s_num error", ESP_ERR_INVALID_ARG);
|
||||
I2S_CHECK((p_i2s_obj[i2s_num] != NULL), "Not initialized yet", ESP_ERR_INVALID_STATE);
|
||||
I2S_CHECK((p_i2s_obj[i2s_num]->mode & I2S_MODE_ADC_BUILT_IN), "i2s built-in adc not enabled", ESP_ERR_INVALID_STATE);
|
||||
|
||||
adc1_lock_release();
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t i2s_write_expand(i2s_port_t i2s_num, const void *src, size_t size, size_t src_bits, size_t aim_bits, size_t *bytes_written, TickType_t ticks_to_wait)
|
||||
{
|
||||
char *data_ptr;
|
||||
|
||||
@@ -204,12 +204,13 @@ int adc1_get_voltage(adc1_channel_t channel) __attribute__((deprecated));
|
||||
/** @endcond */
|
||||
|
||||
/**
|
||||
* @brief Power on SAR ADC
|
||||
* @brief Enable ADC power
|
||||
*/
|
||||
void adc_power_on();
|
||||
|
||||
/**
|
||||
* @brief Power off SAR ADC
|
||||
* This function will force power down for ADC
|
||||
*/
|
||||
void adc_power_off();
|
||||
|
||||
|
||||
@@ -353,6 +353,8 @@ int i2s_read_bytes(i2s_port_t i2s_num, void *dest, size_t size, TickType_t ticks
|
||||
*
|
||||
* @note If the built-in ADC mode is enabled, we should call i2s_adc_start and i2s_adc_stop around the whole reading process,
|
||||
* to prevent the data getting corrupted.
|
||||
* @note If the built-in ADC mode is enabled, we should call i2s_adc_start and i2s_adc_stop around the whole reading process,
|
||||
* to prevent the data getting corrupted.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
@@ -485,6 +487,31 @@ esp_err_t i2s_set_clk(i2s_port_t i2s_num, uint32_t rate, i2s_bits_per_sample_t b
|
||||
*/
|
||||
esp_err_t i2s_set_adc_mode(adc_unit_t adc_unit, adc1_channel_t adc_channel);
|
||||
|
||||
/**
|
||||
* @brief Start to use I2S built-in ADC mode
|
||||
* @note This function would acquire the lock of ADC to prevent the data getting corrupted
|
||||
* during the I2S peripheral is being used to do fully continuous ADC sampling.
|
||||
*
|
||||
* @param i2s_num i2s port index
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
* - ESP_ERR_INVALID_STATE driver state error
|
||||
* - ESP_FAIL Internal driver error
|
||||
*/
|
||||
esp_err_t i2s_adc_enable(i2s_port_t i2s_num);
|
||||
|
||||
/**
|
||||
* @brief Stop to use I2S built-in ADC mode
|
||||
* @param i2s_num i2s port index
|
||||
* @note This function would release the lock of ADC so that other tasks can use ADC.
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
* - ESP_ERR_INVALID_STATE driver state error
|
||||
*/
|
||||
esp_err_t i2s_adc_disable(i2s_port_t i2s_num);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#include "sys/lock.h"
|
||||
#include "driver/rtc_cntl.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "adc1_i2s_private.h"
|
||||
|
||||
#ifndef NDEBUG
|
||||
// Enable built-in checks in queue.h in debug builds
|
||||
@@ -99,6 +100,9 @@ static _lock_t adc2_wifi_lock = NULL;
|
||||
//prevent ADC2 being used by tasks (regardless of WIFI)
|
||||
portMUX_TYPE adc2_spinlock = portMUX_INITIALIZER_UNLOCKED;
|
||||
|
||||
//prevent ADC1 being used by I2S dma and other tasks at the same time.
|
||||
static _lock_t adc1_i2s_lock = NULL;
|
||||
|
||||
typedef struct {
|
||||
TimerHandle_t timer;
|
||||
uint32_t filtered_val[TOUCH_PAD_MAX];
|
||||
@@ -108,12 +112,6 @@ typedef struct {
|
||||
} touch_pad_filter_t;
|
||||
static touch_pad_filter_t *s_touch_pad_filter = NULL;
|
||||
|
||||
typedef enum {
|
||||
ADC_FORCE_FSM = 0x0,
|
||||
ADC_FORCE_DISABLE = 0x2,
|
||||
ADC_FORCE_ENABLE = 0x3,
|
||||
} adc_force_mode_t;
|
||||
|
||||
//Reg,Mux,Fun,IE,Up,Down,Rtc_number
|
||||
const rtc_gpio_desc_t rtc_gpio_desc[GPIO_PIN_COUNT] = {
|
||||
{RTC_IO_TOUCH_PAD1_REG, RTC_IO_TOUCH_PAD1_MUX_SEL_M, RTC_IO_TOUCH_PAD1_FUN_SEL_S, RTC_IO_TOUCH_PAD1_FUN_IE_M, RTC_IO_TOUCH_PAD1_RUE_M, RTC_IO_TOUCH_PAD1_RDE_M, RTC_IO_TOUCH_PAD1_SLP_SEL_M, RTC_IO_TOUCH_PAD1_SLP_IE_M, RTC_IO_TOUCH_PAD1_HOLD_M, RTC_CNTL_TOUCH_PAD1_HOLD_FORCE_M, RTC_IO_TOUCH_PAD1_DRV_V, RTC_IO_TOUCH_PAD1_DRV_S, RTCIO_GPIO0_CHANNEL}, //0
|
||||
@@ -1025,10 +1023,21 @@ static esp_err_t adc_set_atten(adc_unit_t adc_unit, adc_channel_t channel, adc_a
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
void adc_power_always_on()
|
||||
{
|
||||
portENTER_CRITICAL(&rtc_spinlock);
|
||||
SENS.sar_meas_wait2.force_xpd_sar = SENS_FORCE_XPD_SAR_PU;
|
||||
portEXIT_CRITICAL(&rtc_spinlock);
|
||||
}
|
||||
|
||||
void adc_power_on()
|
||||
{
|
||||
portENTER_CRITICAL(&rtc_spinlock);
|
||||
SENS.sar_meas_wait2.force_xpd_sar = ADC_FORCE_FSM;
|
||||
if (SENS.sar_meas_wait2.force_xpd_sar & SENS_FORCE_XPD_SAR_SW_M) {
|
||||
SENS.sar_meas_wait2.force_xpd_sar = SENS_FORCE_XPD_SAR_PU;
|
||||
} else {
|
||||
SENS.sar_meas_wait2.force_xpd_sar = SENS_FORCE_XPD_SAR_FSM;
|
||||
}
|
||||
portEXIT_CRITICAL(&rtc_spinlock);
|
||||
}
|
||||
|
||||
@@ -1037,7 +1046,7 @@ void adc_power_off()
|
||||
portENTER_CRITICAL(&rtc_spinlock);
|
||||
//Bit1 0:Fsm 1: SW mode
|
||||
//Bit0 0:SW mode power down 1: SW mode power on
|
||||
SENS.sar_meas_wait2.force_xpd_sar = ADC_FORCE_DISABLE;
|
||||
SENS.sar_meas_wait2.force_xpd_sar = SENS_FORCE_XPD_SAR_PD;
|
||||
portEXIT_CRITICAL(&rtc_spinlock);
|
||||
}
|
||||
|
||||
@@ -1161,7 +1170,7 @@ esp_err_t adc_i2s_mode_init(adc_unit_t adc_unit, adc_channel_t channel)
|
||||
|
||||
uint8_t table_len = 1;
|
||||
//POWER ON SAR
|
||||
adc_power_on();
|
||||
adc_power_always_on();
|
||||
adc_gpio_init(adc_unit, channel);
|
||||
adc_set_i2s_data_len(adc_unit, table_len);
|
||||
adc_set_i2s_data_pattern(adc_unit, 0, channel, ADC_WIDTH_BIT_12, ADC_ATTEN_DB_11);
|
||||
@@ -1246,12 +1255,55 @@ esp_err_t adc1_config_width(adc_bits_width_t width_bit)
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t adc1_i2s_mode_acquire()
|
||||
{
|
||||
//lazy initialization
|
||||
//for i2s, block until acquire the lock
|
||||
_lock_acquire( &adc1_i2s_lock );
|
||||
ESP_LOGD( RTC_MODULE_TAG, "i2s mode takes adc1 lock." );
|
||||
portENTER_CRITICAL(&rtc_spinlock);
|
||||
SENS.sar_meas_wait2.force_xpd_sar = SENS_FORCE_XPD_SAR_PU;
|
||||
//switch SARADC into DIG channel
|
||||
SENS.sar_read_ctrl.sar1_dig_force = 1;
|
||||
portEXIT_CRITICAL(&rtc_spinlock);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t adc1_adc_mode_acquire()
|
||||
{
|
||||
//lazy initialization
|
||||
//for adc1, block until acquire the lock
|
||||
_lock_acquire( &adc1_i2s_lock );
|
||||
ESP_LOGD( RTC_MODULE_TAG, "adc mode takes adc1 lock." );
|
||||
portENTER_CRITICAL(&rtc_spinlock);
|
||||
// for now the WiFi would use ADC2 and set xpd_sar force on.
|
||||
// so we can not reset xpd_sar to fsm mode directly.
|
||||
// We should handle this after the synchronization mechanism is established.
|
||||
|
||||
//switch SARADC into RTC channel
|
||||
SENS.sar_read_ctrl.sar1_dig_force = 0;
|
||||
portEXIT_CRITICAL(&rtc_spinlock);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t adc1_lock_release()
|
||||
{
|
||||
RTC_MODULE_CHECK((uint32_t*)adc1_i2s_lock != NULL, "adc1 lock release called before acquire", ESP_ERR_INVALID_STATE );
|
||||
// for now the WiFi would use ADC2 and set xpd_sar force on.
|
||||
// so we can not reset xpd_sar to fsm mode directly.
|
||||
// We should handle this after the synchronization mechanism is established.
|
||||
|
||||
_lock_release( &adc1_i2s_lock );
|
||||
ESP_LOGD( RTC_MODULE_TAG, "returns adc1 lock." );
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
int adc1_get_raw(adc1_channel_t channel)
|
||||
{
|
||||
uint16_t adc_value;
|
||||
RTC_MODULE_CHECK(channel < ADC1_CHANNEL_MAX, "ADC Channel Err", ESP_ERR_INVALID_ARG);
|
||||
|
||||
adc_power_on();
|
||||
adc1_adc_mode_acquire();
|
||||
adc_power_on();
|
||||
|
||||
portENTER_CRITICAL(&rtc_spinlock);
|
||||
//Adc Controler is Rtc module,not ulp coprocessor
|
||||
@@ -1274,6 +1326,7 @@ int adc1_get_raw(adc1_channel_t channel)
|
||||
while (SENS.sar_meas_start1.meas1_done_sar == 0);
|
||||
adc_value = SENS.sar_meas_start1.meas1_data_sar;
|
||||
portEXIT_CRITICAL(&rtc_spinlock);
|
||||
adc1_lock_release();
|
||||
return adc_value;
|
||||
}
|
||||
|
||||
@@ -1467,6 +1520,8 @@ esp_err_t adc2_vref_to_gpio(gpio_num_t gpio)
|
||||
rtc_gpio_input_disable(gpio);
|
||||
rtc_gpio_pullup_dis(gpio);
|
||||
rtc_gpio_pulldown_dis(gpio);
|
||||
//force fsm
|
||||
adc_power_always_on(); //Select power source of ADC
|
||||
|
||||
RTCCNTL.bias_conf.dbg_atten = 0; //Check DBG effect outside sleep mode
|
||||
//set dtest (MUX_SEL : 0 -> RTC; 1-> vdd_sar2)
|
||||
@@ -1475,8 +1530,6 @@ esp_err_t adc2_vref_to_gpio(gpio_num_t gpio)
|
||||
RTCCNTL.test_mux.ent_rtc = 1;
|
||||
//set sar2_en_test
|
||||
SENS.sar_start_force.sar2_en_test = 1;
|
||||
//force fsm
|
||||
SENS.sar_meas_wait2.force_xpd_sar = ADC_FORCE_ENABLE; //Select power source of ADC
|
||||
//set sar2 en force
|
||||
SENS.sar_meas_start2.sar2_en_pad_force = 1; //Pad bitmap controlled by SW
|
||||
//set en_pad for channels 7,8,9 (bits 0x380)
|
||||
|
||||
@@ -43,6 +43,8 @@ static const char* UART_TAG = "uart";
|
||||
#define UART_EMPTY_THRESH_DEFAULT (10)
|
||||
#define UART_FULL_THRESH_DEFAULT (120)
|
||||
#define UART_TOUT_THRESH_DEFAULT (10)
|
||||
#define UART_CLKDIV_FRAG_BIT_WIDTH (3)
|
||||
#define UART_TOUT_REF_FACTOR_DEFAULT (UART_CLK_FREQ/(REF_CLK_FREQ<<UART_CLKDIV_FRAG_BIT_WIDTH))
|
||||
#define UART_TX_IDLE_NUM_DEFAULT (0)
|
||||
#define UART_PATTERN_DET_QLEN_DEFAULT (10)
|
||||
|
||||
@@ -654,7 +656,13 @@ esp_err_t uart_intr_config(uart_port_t uart_num, const uart_intr_config_t *intr_
|
||||
UART_ENTER_CRITICAL(&uart_spinlock[uart_num]);
|
||||
UART[uart_num]->int_clr.val = UART_INTR_MASK;
|
||||
if(intr_conf->intr_enable_mask & UART_RXFIFO_TOUT_INT_ENA_M) {
|
||||
UART[uart_num]->conf1.rx_tout_thrhd = ((intr_conf->rx_timeout_thresh) & UART_RX_TOUT_THRHD_V);
|
||||
//Hardware issue workaround: when using ref_tick, the rx timeout threshold needs increase to 10 times.
|
||||
//T_ref = T_apb * APB_CLK/(REF_TICK << CLKDIV_FRAG_BIT_WIDTH)
|
||||
if(UART[uart_num]->conf0.tick_ref_always_on == 0) {
|
||||
UART[uart_num]->conf1.rx_tout_thrhd = ((intr_conf->rx_timeout_thresh * UART_TOUT_REF_FACTOR_DEFAULT) & UART_RX_TOUT_THRHD_V);
|
||||
} else {
|
||||
UART[uart_num]->conf1.rx_tout_thrhd = ((intr_conf->rx_timeout_thresh) & UART_RX_TOUT_THRHD_V);
|
||||
}
|
||||
UART[uart_num]->conf1.rx_tout_en = 1;
|
||||
} else {
|
||||
UART[uart_num]->conf1.rx_tout_en = 0;
|
||||
@@ -1132,8 +1140,8 @@ int uart_read_bytes(uart_port_t uart_num, uint8_t* buf, uint32_t length, TickTyp
|
||||
if(res == pdTRUE) {
|
||||
UART_ENTER_CRITICAL(&uart_spinlock[uart_num]);
|
||||
p_uart_obj[uart_num]->rx_buffered_len += p_uart_obj[uart_num]->rx_stash_len;
|
||||
UART_EXIT_CRITICAL(&uart_spinlock[uart_num]);
|
||||
p_uart_obj[uart_num]->rx_buffer_full_flg = false;
|
||||
UART_EXIT_CRITICAL(&uart_spinlock[uart_num]);
|
||||
uart_enable_rx_intr(p_uart_obj[uart_num]->uart_num);
|
||||
}
|
||||
}
|
||||
@@ -1178,6 +1186,14 @@ esp_err_t uart_flush_input(uart_port_t uart_num)
|
||||
}
|
||||
data = (uint8_t*) xRingbufferReceive(p_uart->rx_ring_buf, &size, (portTickType) 0);
|
||||
if(data == NULL) {
|
||||
if( p_uart_obj[uart_num]->rx_buffered_len != 0 ) {
|
||||
ESP_LOGE(UART_TAG, "rx_buffered_len error");
|
||||
p_uart_obj[uart_num]->rx_buffered_len = 0;
|
||||
}
|
||||
//We also need to clear the `rx_buffer_full_flg` here.
|
||||
UART_ENTER_CRITICAL(&uart_spinlock[uart_num]);
|
||||
p_uart_obj[uart_num]->rx_buffer_full_flg = false;
|
||||
UART_EXIT_CRITICAL(&uart_spinlock[uart_num]);
|
||||
break;
|
||||
}
|
||||
UART_ENTER_CRITICAL(&uart_spinlock[uart_num]);
|
||||
@@ -1190,8 +1206,8 @@ esp_err_t uart_flush_input(uart_port_t uart_num)
|
||||
if(res == pdTRUE) {
|
||||
UART_ENTER_CRITICAL(&uart_spinlock[uart_num]);
|
||||
p_uart_obj[uart_num]->rx_buffered_len += p_uart_obj[uart_num]->rx_stash_len;
|
||||
UART_EXIT_CRITICAL(&uart_spinlock[uart_num]);
|
||||
p_uart_obj[uart_num]->rx_buffer_full_flg = false;
|
||||
UART_EXIT_CRITICAL(&uart_spinlock[uart_num]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,3 +38,7 @@ CFLAGS+=-mfix-esp32-psram-cache-issue
|
||||
CXXFLAGS+=-mfix-esp32-psram-cache-issue
|
||||
endif
|
||||
|
||||
# Enable dynamic esp_timer overflow value if building unit tests
|
||||
ifneq ("$(TEST_COMPONENTS_LIST)","")
|
||||
CPPFLAGS += -DESP_TIMER_DYNAMIC_OVERFLOW_VAL
|
||||
endif
|
||||
|
||||
@@ -44,7 +44,7 @@ static volatile uint32_t reason[ portNUM_PROCESSORS ];
|
||||
ToDo: There is a small chance the CPU already has yielded when this ISR is serviced. In that case, it's running the intended task but
|
||||
the ISR will cause it to switch _away_ from it. portYIELD_FROM_ISR will probably just schedule the task again, but have to check that.
|
||||
*/
|
||||
static void esp_crosscore_isr_handle_yield()
|
||||
static inline void IRAM_ATTR esp_crosscore_isr_handle_yield()
|
||||
{
|
||||
portYIELD_FROM_ISR();
|
||||
}
|
||||
|
||||
@@ -82,7 +82,18 @@
|
||||
* ISR happens follow set_alarm, so change the ALARM_OVERFLOW_VAL to resolve this problem.
|
||||
* Set it to 0xefffffffUL. The remain 0x10000000UL(about 3 second) is enough to handle ISR.
|
||||
*/
|
||||
#define ALARM_OVERFLOW_VAL 0xefffffffUL
|
||||
#define DEFAULT_ALARM_OVERFLOW_VAL 0xefffffffUL
|
||||
|
||||
/* Provision to set lower overflow value for unit testing. Lowering the
|
||||
* overflow value helps check for race conditions which occur near overflow
|
||||
* moment.
|
||||
*/
|
||||
#ifndef ESP_TIMER_DYNAMIC_OVERFLOW_VAL
|
||||
#define ALARM_OVERFLOW_VAL DEFAULT_ALARM_OVERFLOW_VAL
|
||||
#else
|
||||
static uint32_t s_alarm_overflow_val = DEFAULT_ALARM_OVERFLOW_VAL;
|
||||
#define ALARM_OVERFLOW_VAL (s_alarm_overflow_val)
|
||||
#endif
|
||||
|
||||
static const char* TAG = "esp_timer_impl";
|
||||
|
||||
@@ -206,18 +217,6 @@ void IRAM_ATTR esp_timer_impl_set_alarm(uint64_t timestamp)
|
||||
// Adjust current time if overflow has happened
|
||||
bool overflow = timer_overflow_happened();
|
||||
uint64_t cur_count = REG_READ(FRC_TIMER_COUNT_REG(1));
|
||||
uint32_t offset = s_timer_ticks_per_us * 2; //remain 2us for more safe
|
||||
|
||||
//If overflow is going to happen in 1us, let's wait until it happens,
|
||||
//else we think it will not happen before new alarm set.
|
||||
//And we should wait current timer count less than ALARM_OVERFLOW_VAL,
|
||||
//maybe equals to 0.
|
||||
if (cur_count + offset >= ALARM_OVERFLOW_VAL) {
|
||||
do {
|
||||
overflow = timer_overflow_happened();
|
||||
cur_count = REG_READ(FRC_TIMER_COUNT_REG(1));
|
||||
} while(!overflow || cur_count == ALARM_OVERFLOW_VAL);
|
||||
}
|
||||
|
||||
if (overflow) {
|
||||
assert(time_after_timebase_us > s_timer_us_per_overflow);
|
||||
@@ -227,13 +226,17 @@ void IRAM_ATTR esp_timer_impl_set_alarm(uint64_t timestamp)
|
||||
// Calculate desired timer compare value (may exceed 2^32-1)
|
||||
uint64_t compare_val = time_after_timebase_us * s_timer_ticks_per_us;
|
||||
uint32_t alarm_reg_val = ALARM_OVERFLOW_VAL;
|
||||
// Use calculated alarm value if it is less than 2^32-1
|
||||
// Use calculated alarm value if it is less than ALARM_OVERFLOW_VAL.
|
||||
// Note that if by the time we update ALARM_REG, COUNT_REG value is higher,
|
||||
// interrupt will not happen for another ALARM_OVERFLOW_VAL timer ticks,
|
||||
// so need to check if alarm value is too close in the future (e.g. <2 us away).
|
||||
const uint32_t offset = s_timer_ticks_per_us * 2;
|
||||
if (compare_val < ALARM_OVERFLOW_VAL) {
|
||||
// If we by the time we update ALARM_REG, COUNT_REG value is higher,
|
||||
// interrupt will not happen for another 2^32 timer ticks, so need to
|
||||
// check if alarm value is too close in the future (e.g. <1 us away).
|
||||
if (compare_val < cur_count + offset) {
|
||||
compare_val = cur_count + offset;
|
||||
if (compare_val > ALARM_OVERFLOW_VAL) {
|
||||
compare_val = ALARM_OVERFLOW_VAL;
|
||||
}
|
||||
}
|
||||
alarm_reg_val = (uint32_t) compare_val;
|
||||
}
|
||||
@@ -361,3 +364,17 @@ uint64_t IRAM_ATTR esp_timer_impl_get_min_period_us()
|
||||
{
|
||||
return 50;
|
||||
}
|
||||
|
||||
#ifdef ESP_TIMER_DYNAMIC_OVERFLOW_VAL
|
||||
uint32_t esp_timer_impl_get_overflow_val()
|
||||
{
|
||||
return s_alarm_overflow_val;
|
||||
}
|
||||
|
||||
void esp_timer_impl_set_overflow_val(uint32_t overflow_val)
|
||||
{
|
||||
s_alarm_overflow_val = overflow_val;
|
||||
/* update alarm value */
|
||||
esp_timer_impl_update_apb_freq(esp_clk_apb_freq() / 1000000);
|
||||
}
|
||||
#endif // ESP_TIMER_DYNAMIC_OVERFLOW_VAL
|
||||
|
||||
@@ -89,7 +89,6 @@ SECTIONS
|
||||
*libesp32.a:core_dump.o(.literal .text .literal.* .text.*)
|
||||
*libapp_trace.a:(.literal .text .literal.* .text.*)
|
||||
*libxtensa-debug-module.a:eri.o(.literal .text .literal.* .text.*)
|
||||
*libphy.a:(.literal .text .literal.* .text.*)
|
||||
*librtc.a:(.literal .text .literal.* .text.*)
|
||||
*libsoc.a:(.literal .text .literal.* .text.*)
|
||||
*libhal.a:(.literal .text .literal.* .text.*)
|
||||
|
||||
Submodule components/esp32/lib updated: a472a0ce53...798ce93fbf
@@ -241,19 +241,34 @@ static esp_err_t store_cal_data_to_nvs_handle(nvs_handle handle,
|
||||
const esp_phy_calibration_data_t* cal_data)
|
||||
{
|
||||
esp_err_t err;
|
||||
uint32_t cal_format_version = phy_get_rf_cal_version() & (~BIT(16));
|
||||
ESP_LOGV(TAG, "phy_get_rf_cal_version: %d\n", cal_format_version);
|
||||
err = nvs_set_u32(handle, PHY_CAL_VERSION_KEY, cal_format_version);
|
||||
|
||||
err = nvs_set_blob(handle, PHY_CAL_DATA_KEY, cal_data, sizeof(*cal_data));
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "%s: store calibration data failed(0x%x)\n", __func__, err);
|
||||
return err;
|
||||
}
|
||||
|
||||
uint8_t sta_mac[6];
|
||||
esp_efuse_mac_get_default(sta_mac);
|
||||
err = nvs_set_blob(handle, PHY_CAL_MAC_KEY, sta_mac, sizeof(sta_mac));
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "%s: store calibration mac failed(0x%x)\n", __func__, err);
|
||||
return err;
|
||||
}
|
||||
err = nvs_set_blob(handle, PHY_CAL_DATA_KEY, cal_data, sizeof(*cal_data));
|
||||
|
||||
uint32_t cal_format_version = phy_get_rf_cal_version() & (~BIT(16));
|
||||
ESP_LOGV(TAG, "phy_get_rf_cal_version: %d\n", cal_format_version);
|
||||
err = nvs_set_u32(handle, PHY_CAL_VERSION_KEY, cal_format_version);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "%s: store calibration version failed(0x%x)\n", __func__, err);
|
||||
return err;
|
||||
}
|
||||
|
||||
err = nvs_commit(handle);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "%s: store calibration nvs commit failed(0x%x)\n", __func__, err);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
@@ -2,8 +2,10 @@
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/param.h>
|
||||
#include "unity.h"
|
||||
#include "esp_timer.h"
|
||||
#include "../esp_timer_impl.h"
|
||||
#include "esp_heap_caps.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
@@ -14,6 +16,20 @@
|
||||
#define WITH_PROFILING 1
|
||||
#endif
|
||||
|
||||
extern uint32_t esp_timer_impl_get_overflow_val();
|
||||
extern void esp_timer_impl_set_overflow_val(uint32_t overflow_val);
|
||||
|
||||
static uint32_t s_old_overflow_val;
|
||||
|
||||
static void setup_overflow()
|
||||
{
|
||||
s_old_overflow_val = esp_timer_impl_get_overflow_val();
|
||||
esp_timer_impl_set_overflow_val(0x7fffff); /* overflow every ~0.1 sec */}
|
||||
|
||||
static void teardown_overflow()
|
||||
{
|
||||
esp_timer_impl_set_overflow_val(s_old_overflow_val);
|
||||
}
|
||||
|
||||
TEST_CASE("esp_timer orders timers correctly", "[esp_timer]")
|
||||
{
|
||||
@@ -26,6 +42,7 @@ TEST_CASE("esp_timer orders timers correctly", "[esp_timer]")
|
||||
const size_t num_timers = sizeof(timeouts)/sizeof(timeouts[0]);
|
||||
esp_timer_handle_t handles[num_timers];
|
||||
char* names[num_timers];
|
||||
setup_overflow();
|
||||
for (size_t i = 0; i < num_timers; ++i) {
|
||||
asprintf(&names[i], "timer%d", i);
|
||||
esp_timer_create_args_t args = {
|
||||
@@ -35,6 +52,7 @@ TEST_CASE("esp_timer orders timers correctly", "[esp_timer]")
|
||||
TEST_ESP_OK(esp_timer_create(&args, &handles[i]));
|
||||
TEST_ESP_OK(esp_timer_start_once(handles[i], timeouts[i] * 100));
|
||||
}
|
||||
teardown_overflow();
|
||||
char* stream_str[1024];
|
||||
FILE* stream = fmemopen(stream_str, sizeof(stream_str), "r+");
|
||||
TEST_ESP_OK(esp_timer_dump(stream));
|
||||
@@ -67,6 +85,42 @@ TEST_CASE("esp_timer orders timers correctly", "[esp_timer]")
|
||||
fclose(stream);
|
||||
}
|
||||
|
||||
TEST_CASE("esp_timer_impl_set_alarm stress test", "[esp_timer]")
|
||||
{
|
||||
const int test_time_sec = 10;
|
||||
|
||||
void set_alarm_task(void* arg)
|
||||
{
|
||||
SemaphoreHandle_t done = (SemaphoreHandle_t) arg;
|
||||
|
||||
uint64_t start = esp_timer_impl_get_time();
|
||||
uint64_t now = start;
|
||||
int count = 0;
|
||||
const int delays[] = {50, 5000, 10000000};
|
||||
const int delays_count = sizeof(delays)/sizeof(delays[0]);
|
||||
while (now - start < test_time_sec * 1000000) {
|
||||
now = esp_timer_impl_get_time();
|
||||
esp_timer_impl_set_alarm(now + delays[count % delays_count]);
|
||||
++count;
|
||||
}
|
||||
xSemaphoreGive(done);
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
SemaphoreHandle_t done = xSemaphoreCreateCounting(portNUM_PROCESSORS, 0);
|
||||
setup_overflow();
|
||||
xTaskCreatePinnedToCore(&set_alarm_task, "set_alarm_0", 4096, done, UNITY_FREERTOS_PRIORITY, NULL, 0);
|
||||
#if portNUM_PROCESSORS == 2
|
||||
xTaskCreatePinnedToCore(&set_alarm_task, "set_alarm_1", 4096, done, UNITY_FREERTOS_PRIORITY, NULL, 1);
|
||||
#endif
|
||||
|
||||
TEST_ASSERT(xSemaphoreTake(done, test_time_sec * 2 * 1000 / portTICK_PERIOD_MS));
|
||||
#if portNUM_PROCESSORS == 2
|
||||
TEST_ASSERT(xSemaphoreTake(done, test_time_sec * 2 * 1000 / portTICK_PERIOD_MS));
|
||||
#endif
|
||||
teardown_overflow();
|
||||
vSemaphoreDelete(done);
|
||||
}
|
||||
|
||||
TEST_CASE("esp_timer produces correct delay", "[esp_timer]")
|
||||
{
|
||||
@@ -89,6 +143,7 @@ TEST_CASE("esp_timer produces correct delay", "[esp_timer]")
|
||||
const size_t delays_count = sizeof(delays_ms)/sizeof(delays_ms[0]);
|
||||
|
||||
ref_clock_init();
|
||||
setup_overflow();
|
||||
for (size_t i = 0; i < delays_count; ++i) {
|
||||
t_end = 0;
|
||||
int64_t t_start = ref_clock_get();
|
||||
@@ -102,6 +157,7 @@ TEST_CASE("esp_timer produces correct delay", "[esp_timer]")
|
||||
|
||||
TEST_ASSERT_INT32_WITHIN(portTICK_PERIOD_MS, delays_ms[i], ms_diff);
|
||||
}
|
||||
teardown_overflow();
|
||||
ref_clock_deinit();
|
||||
|
||||
TEST_ESP_OK( esp_timer_dump(stdout) );
|
||||
@@ -149,6 +205,7 @@ TEST_CASE("periodic esp_timer produces correct delays", "[esp_timer]")
|
||||
};
|
||||
TEST_ESP_OK(esp_timer_create(&create_args, &timer1));
|
||||
ref_clock_init();
|
||||
setup_overflow();
|
||||
args.timer = timer1;
|
||||
args.t_start = ref_clock_get();
|
||||
args.done = xSemaphoreCreateBinary();
|
||||
@@ -160,6 +217,7 @@ TEST_CASE("periodic esp_timer produces correct delays", "[esp_timer]")
|
||||
for (size_t i = 0; i < NUM_INTERVALS; ++i) {
|
||||
TEST_ASSERT_INT32_WITHIN(portTICK_PERIOD_MS, (i + 1) * delay_ms, args.intervals[i]);
|
||||
}
|
||||
teardown_overflow();
|
||||
ref_clock_deinit();
|
||||
TEST_ESP_OK( esp_timer_dump(stdout) );
|
||||
|
||||
@@ -316,6 +374,7 @@ TEST_CASE("esp_timer for very short intervals", "[esp_timer]")
|
||||
esp_timer_handle_t timer1, timer2;
|
||||
ESP_ERROR_CHECK( esp_timer_create(&timer_args, &timer1) );
|
||||
ESP_ERROR_CHECK( esp_timer_create(&timer_args, &timer2) );
|
||||
setup_overflow();
|
||||
const int timeout_ms = 10;
|
||||
for (int timeout_delta_us = -150; timeout_delta_us < 150; timeout_delta_us++) {
|
||||
printf("delta=%d", timeout_delta_us);
|
||||
@@ -328,6 +387,7 @@ TEST_CASE("esp_timer for very short intervals", "[esp_timer]")
|
||||
TEST_ESP_ERR(ESP_ERR_INVALID_STATE, esp_timer_stop(timer2));
|
||||
}
|
||||
|
||||
teardown_overflow();
|
||||
vSemaphoreDelete(semaphore);
|
||||
}
|
||||
|
||||
@@ -344,40 +404,75 @@ TEST_CASE("esp_timer_get_time call takes less than 1us", "[esp_timer]")
|
||||
TEST_PERFORMANCE_LESS_THAN(ESP_TIMER_GET_TIME_PER_CALL, "%dns", ns_per_call);
|
||||
}
|
||||
|
||||
/* This test runs for about 10 minutes and is disabled in CI.
|
||||
* Such run time is needed to have FRC2 timer overflow a few times.
|
||||
*/
|
||||
TEST_CASE("esp_timer_get_time returns monotonic values", "[esp_timer][ignore]")
|
||||
TEST_CASE("esp_timer_get_time returns monotonic values", "[esp_timer]")
|
||||
{
|
||||
void timer_test_task(void* arg) {
|
||||
int64_t delta = esp_timer_get_time() - ref_clock_get();
|
||||
typedef struct {
|
||||
SemaphoreHandle_t done;
|
||||
bool pass;
|
||||
int test_cnt;
|
||||
int error_cnt;
|
||||
int64_t total_sq_error;
|
||||
int64_t max_error;
|
||||
} test_state_t;
|
||||
|
||||
const int iter_count = 1000000000;
|
||||
for (int i = 0; i < iter_count; ++i) {
|
||||
int64_t now = esp_timer_get_time();
|
||||
int64_t ref_now = ref_clock_get();
|
||||
int64_t diff = now - (ref_now + delta);
|
||||
void timer_test_task(void* arg) {
|
||||
test_state_t* state = (test_state_t*) arg;
|
||||
state->pass = true;
|
||||
int64_t start_time = ref_clock_get();
|
||||
int64_t delta = esp_timer_get_time() - start_time;
|
||||
|
||||
int64_t now = start_time;
|
||||
int error_repeat_cnt = 0;
|
||||
while (now - start_time < 10000000) { /* 10 seconds */
|
||||
int64_t hs_now = esp_timer_get_time();
|
||||
now = ref_clock_get();
|
||||
int64_t diff = hs_now - (now + delta);
|
||||
/* Allow some difference due to rtos tick interrupting task between
|
||||
* getting 'now' and 'ref_now'.
|
||||
*/
|
||||
TEST_ASSERT_INT32_WITHIN(100, 0, (int) diff);
|
||||
if (abs(diff) > 100) {
|
||||
error_repeat_cnt++;
|
||||
state->error_cnt++;
|
||||
} else {
|
||||
error_repeat_cnt = 0;
|
||||
}
|
||||
if (error_repeat_cnt > 2) {
|
||||
printf("diff=%lld\n", diff);
|
||||
state->pass = false;
|
||||
}
|
||||
state->max_error = MAX(state->max_error, abs(diff));
|
||||
state->test_cnt++;
|
||||
state->total_sq_error += diff * diff;
|
||||
}
|
||||
|
||||
xSemaphoreGive((SemaphoreHandle_t) arg);
|
||||
xSemaphoreGive(state->done);
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
ref_clock_init();
|
||||
SemaphoreHandle_t done_1 = xSemaphoreCreateBinary();
|
||||
SemaphoreHandle_t done_2 = xSemaphoreCreateBinary();
|
||||
setup_overflow();
|
||||
|
||||
xTaskCreatePinnedToCore(&timer_test_task, "t1", 4096, (void*) done_1, 6, NULL, 0);
|
||||
xTaskCreatePinnedToCore(&timer_test_task, "t2", 4096, (void*) done_2, 6, NULL, 1);
|
||||
test_state_t states[portNUM_PROCESSORS] = {0};
|
||||
SemaphoreHandle_t done = xSemaphoreCreateCounting(portNUM_PROCESSORS, 0);
|
||||
for (int i = 0; i < portNUM_PROCESSORS; ++i) {
|
||||
states[i].done = done;
|
||||
xTaskCreatePinnedToCore(&timer_test_task, "test", 4096, &states[i], 6, NULL, i);
|
||||
}
|
||||
|
||||
TEST_ASSERT_TRUE( xSemaphoreTake(done_1, portMAX_DELAY) );
|
||||
TEST_ASSERT_TRUE( xSemaphoreTake(done_2, portMAX_DELAY) );
|
||||
vSemaphoreDelete(done_1);
|
||||
vSemaphoreDelete(done_2);
|
||||
for (int i = 0; i < portNUM_PROCESSORS; ++i) {
|
||||
TEST_ASSERT_TRUE( xSemaphoreTake(done, portMAX_DELAY) );
|
||||
printf("CPU%d: %s test_cnt=%d error_cnt=%d std_error=%d |max_error|=%d\n",
|
||||
i, states[i].pass ? "PASS" : "FAIL",
|
||||
states[i].test_cnt, states[i].error_cnt,
|
||||
(int) sqrt(states[i].total_sq_error / states[i].test_cnt), (int) states[i].max_error);
|
||||
}
|
||||
|
||||
vSemaphoreDelete(done);
|
||||
teardown_overflow();
|
||||
ref_clock_deinit();
|
||||
|
||||
for (int i = 0; i < portNUM_PROCESSORS; ++i) {
|
||||
TEST_ASSERT(states[i].pass);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Can dump esp_timer stats", "[esp_timer]")
|
||||
|
||||
@@ -2458,8 +2458,7 @@ Queue_t * const pxQueue = ( Queue_t * ) xQueue;
|
||||
{
|
||||
BaseType_t xReturn;
|
||||
|
||||
//ToDo: figure out locking
|
||||
// taskENTER_CRITICAL(&pxQueue->mux);
|
||||
taskENTER_CRITICAL(&(((Queue_t * )xQueueOrSemaphore)->mux));
|
||||
{
|
||||
if( ( ( Queue_t * ) xQueueOrSemaphore )->pxQueueSetContainer != NULL )
|
||||
{
|
||||
@@ -2478,7 +2477,7 @@ Queue_t * const pxQueue = ( Queue_t * ) xQueue;
|
||||
xReturn = pdPASS;
|
||||
}
|
||||
}
|
||||
// taskEXIT_CRITICAL(&pxQueue->mux);
|
||||
taskEXIT_CRITICAL(&(((Queue_t * )xQueueOrSemaphore)->mux));
|
||||
|
||||
return xReturn;
|
||||
}
|
||||
@@ -2507,12 +2506,12 @@ Queue_t * const pxQueue = ( Queue_t * ) xQueue;
|
||||
}
|
||||
else
|
||||
{
|
||||
// taskENTER_CRITICAL(&pxQueue->mux);
|
||||
taskENTER_CRITICAL(&(pxQueueOrSemaphore->mux));
|
||||
{
|
||||
/* The queue is no longer contained in the set. */
|
||||
pxQueueOrSemaphore->pxQueueSetContainer = NULL;
|
||||
}
|
||||
// taskEXIT_CRITICAL(&pxQueue->mux);
|
||||
taskEXIT_CRITICAL(&(pxQueueOrSemaphore->mux));
|
||||
xReturn = pdPASS;
|
||||
}
|
||||
|
||||
@@ -2555,9 +2554,15 @@ Queue_t * const pxQueue = ( Queue_t * ) xQueue;
|
||||
Queue_t *pxQueueSetContainer = pxQueue->pxQueueSetContainer;
|
||||
BaseType_t xReturn = pdFALSE;
|
||||
|
||||
/* This function must be called form a critical section. */
|
||||
/*
|
||||
* This function is called with a Queue's / Semaphore's spinlock already
|
||||
* acquired. Acquiring the Queue set's spinlock is still necessary.
|
||||
*/
|
||||
|
||||
configASSERT( pxQueueSetContainer );
|
||||
|
||||
//Acquire the Queue set's spinlock
|
||||
portENTER_CRITICAL(&(pxQueueSetContainer->mux));
|
||||
configASSERT( pxQueueSetContainer->uxMessagesWaiting < pxQueueSetContainer->uxLength );
|
||||
|
||||
if( pxQueueSetContainer->uxMessagesWaiting < pxQueueSetContainer->uxLength )
|
||||
@@ -2588,6 +2593,9 @@ Queue_t * const pxQueue = ( Queue_t * ) xQueue;
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
|
||||
//Release the Queue set's spinlock
|
||||
portEXIT_CRITICAL(&(pxQueueSetContainer->mux));
|
||||
|
||||
return xReturn;
|
||||
}
|
||||
|
||||
|
||||
137
components/freertos/test/test_queuesets.c
Normal file
137
components/freertos/test/test_queuesets.c
Normal file
@@ -0,0 +1,137 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/queue.h"
|
||||
#include "freertos/semphr.h"
|
||||
#include "unity.h"
|
||||
|
||||
/*
|
||||
* Basic queue set tests. Multiple queues are added to a queue set then each
|
||||
* queue is filled in a sequential order. The members returned from the queue
|
||||
* set must adhered to the order in which the queues were filled.
|
||||
*/
|
||||
#define NO_OF_QUEUES 5
|
||||
#define QUEUE_LEN 4
|
||||
#define ITEM_SIZE sizeof(uint32_t)
|
||||
|
||||
static QueueHandle_t handles[NO_OF_QUEUES];
|
||||
static QueueSetHandle_t set_handle;
|
||||
|
||||
TEST_CASE("Test Queue sets", "[freertos]")
|
||||
{
|
||||
//Create queue set, queues, and add queues to queue set
|
||||
set_handle = xQueueCreateSet(NO_OF_QUEUES * QUEUE_LEN);
|
||||
for (int i = 0; i < NO_OF_QUEUES; i++) {
|
||||
handles[i] = xQueueCreate(QUEUE_LEN, ITEM_SIZE);
|
||||
TEST_ASSERT_MESSAGE(handles[i] != NULL, "Failed to create queue");
|
||||
TEST_ASSERT_MESSAGE(xQueueAddToSet(handles[i], set_handle) == pdPASS, "Failed to add to queue set");
|
||||
}
|
||||
|
||||
//Fill queue set via filling each queue
|
||||
for (int i = 0; i < NO_OF_QUEUES; i++) {
|
||||
for (int j = 0; j < QUEUE_LEN; j++) {
|
||||
uint32_t item_num = (i * QUEUE_LEN) + j;
|
||||
TEST_ASSERT_MESSAGE(xQueueSendToBack(handles[i], &item_num, portMAX_DELAY) == pdTRUE, "Failed to send to queue");
|
||||
}
|
||||
}
|
||||
|
||||
//Check queue set is notified in correct order
|
||||
for (int i = 0; i < NO_OF_QUEUES; i++) {
|
||||
for (int j = 0; j < QUEUE_LEN; j++) {
|
||||
QueueSetMemberHandle_t member = xQueueSelectFromSet(set_handle, portMAX_DELAY);
|
||||
TEST_ASSERT_EQUAL_MESSAGE(handles[i], member, "Incorrect queue set member returned");
|
||||
uint32_t item;
|
||||
xQueueReceive((QueueHandle_t)member, &item, 0);
|
||||
TEST_ASSERT_EQUAL_MESSAGE(((i * QUEUE_LEN) + j), item, "Incorrect item value");
|
||||
}
|
||||
}
|
||||
|
||||
//Remove queues from queue set and delete queues
|
||||
for (int i = 0; i < NO_OF_QUEUES; i++) {
|
||||
TEST_ASSERT_MESSAGE(xQueueRemoveFromSet(handles[i], set_handle), "Failed to remove from queue set");
|
||||
vQueueDelete(handles[i]);
|
||||
}
|
||||
vQueueDelete(set_handle);
|
||||
}
|
||||
|
||||
/*
|
||||
* Queue set thread safety test. Test the SMP thread safety by adding two queues
|
||||
* to a queue set and have a task on each core send to the queues simultaneously.
|
||||
* Check returned queue set members are valid.
|
||||
*/
|
||||
#ifndef CONFIG_FREERTOS_UNICORE
|
||||
static volatile bool sync_flags[portNUM_PROCESSORS];
|
||||
static SemaphoreHandle_t sync_sem;
|
||||
|
||||
static void send_task(void *arg)
|
||||
{
|
||||
QueueHandle_t queue = (QueueHandle_t)arg;
|
||||
|
||||
//Wait until task on the other core starts running
|
||||
xSemaphoreTake(sync_sem, portMAX_DELAY);
|
||||
sync_flags[xPortGetCoreID()] = true;
|
||||
while (!sync_flags[!xPortGetCoreID()]) {
|
||||
;
|
||||
}
|
||||
|
||||
//Fill queue
|
||||
for (int i = 0; i < QUEUE_LEN; i++) {
|
||||
uint32_t item = i;
|
||||
xQueueSendToBack(queue, &item, portMAX_DELAY);
|
||||
}
|
||||
|
||||
xSemaphoreGive(sync_sem);
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
TEST_CASE("Test Queue sets thread safety", "[freertos]")
|
||||
{
|
||||
//Create queue set, queues, and a send task on each core
|
||||
sync_sem = xSemaphoreCreateCounting(portNUM_PROCESSORS, 0);
|
||||
QueueHandle_t queue_handles[portNUM_PROCESSORS];
|
||||
QueueSetHandle_t queueset_handle = xQueueCreateSet(portNUM_PROCESSORS * QUEUE_LEN);
|
||||
for (int i = 0; i < portNUM_PROCESSORS; i++) {
|
||||
sync_flags[i] = false;
|
||||
queue_handles[i] = xQueueCreate(QUEUE_LEN, ITEM_SIZE);
|
||||
TEST_ASSERT_MESSAGE(xQueueAddToSet(queue_handles[i], queueset_handle) == pdPASS, "Failed to add to queue set");
|
||||
xTaskCreatePinnedToCore(send_task, "send", 2048, (void *)queue_handles[i], 10, NULL, i);
|
||||
}
|
||||
|
||||
//Start both send tasks
|
||||
portDISABLE_INTERRUPTS();
|
||||
for (int i = 0; i < portNUM_PROCESSORS; i++) {
|
||||
xSemaphoreGive(sync_sem);
|
||||
}
|
||||
portENABLE_INTERRUPTS();
|
||||
vTaskDelay(2);
|
||||
|
||||
//Check returned queue set members are valid
|
||||
uint32_t expect_0 = 0;
|
||||
uint32_t expect_1 = 0;
|
||||
for (int i = 0; i < (portNUM_PROCESSORS * QUEUE_LEN); i++) {
|
||||
QueueSetMemberHandle_t member = xQueueSelectFromSet(queueset_handle, portMAX_DELAY);
|
||||
uint32_t item;
|
||||
if (member == queue_handles[0]) {
|
||||
xQueueReceive((QueueHandle_t)member, &item, 0);
|
||||
TEST_ASSERT_EQUAL_MESSAGE(expect_0, item, "Incorrect item value");
|
||||
expect_0++;
|
||||
} else if (member == queue_handles[1]) {
|
||||
xQueueReceive((QueueHandle_t)member, &item, 0);
|
||||
TEST_ASSERT_EQUAL_MESSAGE(expect_1, item, "Incorrect item value");
|
||||
expect_1++;
|
||||
} else {
|
||||
TEST_ASSERT_MESSAGE(0, "Incorrect queue set member returned");
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < portNUM_PROCESSORS; i++) {
|
||||
xSemaphoreTake(sync_sem, portMAX_DELAY);
|
||||
}
|
||||
for (int i = 0; i < portNUM_PROCESSORS; i++) {
|
||||
xQueueRemoveFromSet(queueset_handle, handles[i]);
|
||||
vQueueDelete(queue_handles[i]);
|
||||
}
|
||||
vQueueDelete(queueset_handle);
|
||||
}
|
||||
#endif
|
||||
@@ -798,7 +798,7 @@ test cases:
|
||||
- ['R PC_COM C +NIC_START:OK']
|
||||
- - "SSC SSC1 bleadv -D -z stop"
|
||||
- ["R SSC1 C +BLEADV"]
|
||||
- - LOOP 2 2 "['0x20-0x40','0xA0-0xB0']" "['NPDU','PDU']"
|
||||
- - LOOP 2 2 "['0x20-0x40','0xA0-0xB0']" "['PDU','PDU']"
|
||||
- [""]
|
||||
- - "SSC SSC1 bleadv -D -z start -t 2 -i {%s}"
|
||||
- ["R SSC1 C +BLEADV:OK"]
|
||||
@@ -842,7 +842,7 @@ test cases:
|
||||
- ['R PC_COM C +NIC_START:OK']
|
||||
- - "SSC SSC1 bleadv -D -z stop"
|
||||
- ["R SSC1 C +BLEADV"]
|
||||
- - LOOP 2 2 "['0x20-0x40','0xA0-0xB0']" "['NPDU','PDU']"
|
||||
- - LOOP 2 2 "['0x20-0x40','0xA0-0xB0']" "['PDU','PDU']"
|
||||
- [""]
|
||||
- - "SSC SSC1 bleadv -D -z start -t 3 -i {%s}"
|
||||
- ["R SSC1 C +BLEADV:OK"]
|
||||
@@ -890,7 +890,7 @@ test cases:
|
||||
- ["R SSC1 C +BLEADV:OK"]
|
||||
- - "SSC SSC2 bleadv -D -z stop"
|
||||
- ["R SSC2 C +BLEADV:OK"]
|
||||
- - "SSC SSC2 blescan -L -c 0 -s 0"
|
||||
- - "SSC SSC2 blescan -L -c 0 -s 0 -d 1"
|
||||
- ["R SSC2 C +BLESCAN:SetScanParam,OK"]
|
||||
- - "SSC SSC2 blescan -D -z start -t 3 -e 2"
|
||||
- - 'P SSC2 RE "\+BTSCANEXT:%%s,man,0x1011121314151617181910111213141516171819"%%(<dut1_bt_mac>)'
|
||||
@@ -944,7 +944,7 @@ test cases:
|
||||
- ["R SSC2 C +BLEADV:OK"]
|
||||
- - LOOP 4 2 "[0,1,2,3]"
|
||||
- ['']
|
||||
- - "SSC SSC2 blescan -L -c 0 -s 1 -o {%d}"
|
||||
- - "SSC SSC2 blescan -L -c 0 -s 1 -o {%d} -d 1"
|
||||
- ["R SSC2 C +BLESCAN:SetScanParam,OK"]
|
||||
- - "SSC SSC2 blescan -D -z start -t 1"
|
||||
- ['R SSC2 P <dut1_bt_mac> C Complete']
|
||||
@@ -1075,7 +1075,7 @@ test cases:
|
||||
- ["R SSC1 C +BLEADV:OK"]
|
||||
- - "SSC SSC1 bleadv -D -z start"
|
||||
- ["R SSC1 C +BLEADV:OK"]
|
||||
- - "SSC SSC2 blescan -L -c 0"
|
||||
- - "SSC SSC2 blescan -L -c 0 -d 1"
|
||||
- ["R SSC2 C +BLESCAN:SetScanParam,OK"]
|
||||
- - "SSC SSC2 blescan -D -z start -t 1"
|
||||
- ["R SSC2 P <dut1_bt_mac> C Complete"]
|
||||
@@ -1538,6 +1538,8 @@ test cases:
|
||||
- ""
|
||||
- - "SSC SSC1 bleadv -D -z stop"
|
||||
- ["R SSC1 C +BLEADV"]
|
||||
- - "SSC SSC2 blescan -L -c 0 -d 1"
|
||||
- ['R SSC2 C +BLESCAN']
|
||||
- - "SSC SSC1 bleadv -R -t 1 -r 0x020AEB06FF1112131415051220004000021901020106"
|
||||
- ["R SSC1 C +BLEADV:OK"]
|
||||
- - "SSC SSC1 bleadv -D -z start"
|
||||
@@ -1584,6 +1586,8 @@ test cases:
|
||||
- ["R SSC1 C +BLEADV"]
|
||||
- - "SSC SSC2 bleadv -D -z stop"
|
||||
- ["R SSC2 C +BLEADV:OK"]
|
||||
- - "SSC SSC2 blescan -L -c 0 -d 1"
|
||||
- ['R SSC2 C +BLESCAN']
|
||||
- - LOOP 4 3 "['0302ABCD','0303ABCD','0504ABCDABCD','0505ABCDABCD',]" "['insrv16,0xABCD','srv16,0xABCD','insrv32,0xABCDABCD','srv32,0xABCDABCD']"
|
||||
- - "SSC SSC1 bleadv -R -t 1 -r 0x{%s}"
|
||||
- ["R SSC1 C +BLEADV:OK"]
|
||||
@@ -1633,6 +1637,8 @@ test cases:
|
||||
- ["R SSC1 C +BLEADV"]
|
||||
- - "SSC SSC2 bleadv -D -z stop"
|
||||
- ["R SSC2 C +BLEADV:OK"]
|
||||
- - "SSC SSC2 blescan -L -c 0 -d 1"
|
||||
- ['R SSC2 C +BLESCAN']
|
||||
- - LOOP 3 3 "['0416ABCDEF','0620ABCDABCDEF','1221ABCDABCDABCDABCDABCDABCDABCDABCDEF',]" "['srvdata,0xABCDEF','srvdata32,0xABCDABCDEF','srvdata128,0xABCDABCDABCDABCDABCDABCDABCDABCDEF']"
|
||||
- - "SSC SSC1 bleadv -R -t 1 -r 0x{%s}"
|
||||
- ["R SSC1 C +BLEADV:OK"]
|
||||
@@ -1671,6 +1677,8 @@ test cases:
|
||||
- ""
|
||||
- - "SSC SSC1 bleadv -D -z stop"
|
||||
- ["R SSC1 C +BLEADV"]
|
||||
- - "SSC SSC2 blescan -L -c 0 -d 1"
|
||||
- ['R SSC2 C +BLESCAN']
|
||||
- - "SSC SSC1 bleadv -R -t 1 -r 0x15FF1011121314151617181910111213141516171819"
|
||||
- ["R SSC1 C +BLEADV:OK"]
|
||||
- - "SSC SSC1 bleadv -R -t 2 -r 0x020AEB051220004000021901020106"
|
||||
|
||||
@@ -83,7 +83,7 @@ config LWIP_STATS
|
||||
|
||||
config LWIP_ETHARP_TRUST_IP_MAC
|
||||
bool "Enable LWIP ARP trust"
|
||||
default y
|
||||
default n
|
||||
help
|
||||
Enabling this option allows ARP table to be updated.
|
||||
|
||||
@@ -96,6 +96,17 @@ config LWIP_ETHARP_TRUST_IP_MAC
|
||||
The peer *is* in the ARP table if it requested our address before.
|
||||
Also notice that this slows down input processing of every IP packet!
|
||||
|
||||
There are two known issues in real application if this feature is enabled:
|
||||
- The LAN peer may have bug to update the ARP table after the ARP entry is aged out.
|
||||
If the ARP entry on the LAN peer is aged out but failed to be updated, all IP packets
|
||||
sent from LWIP to the LAN peer will be dropped by LAN peer.
|
||||
- The LAN peer may not be trustful, the LAN peer may send IP packets to LWIP with
|
||||
two different MACs, but the same IP address. If this happens, the LWIP has problem
|
||||
to receive IP packets from LAN peer.
|
||||
|
||||
So the recommendation is to disable this option.
|
||||
Here the LAN peer means the other side to which the ESP station or soft-AP is connected.
|
||||
|
||||
config TCPIP_RECVMBOX_SIZE
|
||||
int "TCPIP task receive mail box size"
|
||||
default 32
|
||||
@@ -308,6 +319,16 @@ config TCP_QUEUE_OOSEQ
|
||||
Disable this option to save some RAM during TCP sessions, at the expense
|
||||
of increased retransmissions if segments arrive out of order.
|
||||
|
||||
config ESP_TCP_KEEP_CONNECTION_WHEN_IP_CHANGES
|
||||
bool "Keep TCP connections when IP changed"
|
||||
default n
|
||||
help
|
||||
This option is enabled when the following scenario happen:
|
||||
network dropped and reconnected, IP changes is like: 192.168.0.2->0.0.0.0->192.168.0.2
|
||||
|
||||
Disable this option to keep consistent with the original LWIP code behavior.
|
||||
|
||||
|
||||
choice TCP_OVERSIZE
|
||||
prompt "Pre-allocate transmit PBUF size"
|
||||
default TCP_OVERSIZE_MSS
|
||||
|
||||
@@ -407,9 +407,9 @@ netconn_accept(struct netconn *conn, struct netconn **new_conn)
|
||||
#if TCP_LISTEN_BACKLOG
|
||||
/* Let the stack know that we have accepted the connection. */
|
||||
API_MSG_VAR_ALLOC_DONTFAIL(msg);
|
||||
API_MSG_VAR_REF(msg).msg.conn = conn;
|
||||
/* don't care for the return value of lwip_netconn_do_recv */
|
||||
TCPIP_APIMSG_NOERR(&API_MSG_VAR_REF(msg), lwip_netconn_do_recv);
|
||||
API_MSG_VAR_REF(msg).msg.conn = newconn;
|
||||
/* don't care for the return value of lwip_netconn_do_accepted */
|
||||
TCPIP_APIMSG_NOERR(&API_MSG_VAR_REF(msg), lwip_netconn_do_accepted);
|
||||
API_MSG_VAR_FREE(msg);
|
||||
#endif /* TCP_LISTEN_BACKLOG */
|
||||
|
||||
|
||||
@@ -536,6 +536,9 @@ accept_function(void *arg, struct tcp_pcb *newpcb, err_t err)
|
||||
to the application thread */
|
||||
newconn->last_err = err;
|
||||
|
||||
/* handle backlog counter */
|
||||
tcp_backlog_delayed(newpcb);
|
||||
|
||||
if (sys_mbox_trypost(&conn->acceptmbox, newconn) != ERR_OK) {
|
||||
ESP_STATS_DROP_INC(esp.acceptmbox_post_fail);
|
||||
/* When returning != ERR_OK, the pcb is aborted in tcp_process(),
|
||||
@@ -1503,24 +1506,38 @@ lwip_netconn_do_recv(void *m)
|
||||
msg->err = ERR_OK;
|
||||
if (msg->conn->pcb.tcp != NULL) {
|
||||
if (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_TCP) {
|
||||
#if TCP_LISTEN_BACKLOG
|
||||
if (msg->conn->pcb.tcp->state == LISTEN) {
|
||||
tcp_accepted(msg->conn->pcb.tcp);
|
||||
} else
|
||||
#endif /* TCP_LISTEN_BACKLOG */
|
||||
{
|
||||
u32_t remaining = msg->msg.r.len;
|
||||
do {
|
||||
u16_t recved = (remaining > 0xffff) ? 0xffff : (u16_t)remaining;
|
||||
tcp_recved(msg->conn->pcb.tcp, recved);
|
||||
remaining -= recved;
|
||||
} while (remaining != 0);
|
||||
}
|
||||
u32_t remaining = msg->msg.r.len;
|
||||
do {
|
||||
u16_t recved = (remaining > 0xffff) ? 0xffff : (u16_t)remaining;
|
||||
tcp_recved(msg->conn->pcb.tcp, recved);
|
||||
remaining -= recved;
|
||||
} while (remaining != 0);
|
||||
}
|
||||
}
|
||||
TCPIP_APIMSG_ACK(msg);
|
||||
}
|
||||
|
||||
#if TCP_LISTEN_BACKLOG
|
||||
/** Indicate that a TCP pcb has been accepted
|
||||
* Called from netconn_accept
|
||||
*
|
||||
* @param m the api_msg pointing to the connection
|
||||
*/
|
||||
void
|
||||
lwip_netconn_do_accepted(void *m)
|
||||
{
|
||||
struct api_msg_msg *msg = (struct api_msg_msg *)m;
|
||||
|
||||
msg->err = ERR_OK;
|
||||
if (msg->conn->pcb.tcp != NULL) {
|
||||
if (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_TCP) {
|
||||
tcp_backlog_accepted(msg->conn->pcb.tcp);
|
||||
}
|
||||
}
|
||||
TCPIP_APIMSG_ACK(msg);
|
||||
}
|
||||
#endif /* TCP_LISTEN_BACKLOG */
|
||||
|
||||
/**
|
||||
* See if more data needs to be written from a previous call to netconn_write.
|
||||
* Called initially from lwip_netconn_do_write. If the first call can't send all data
|
||||
|
||||
@@ -133,16 +133,14 @@ bool ip4_netif_exist(const ip4_addr_t *src, const ip4_addr_t *dest)
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* Source based IPv4 routing hook function. This function works only
|
||||
* when destination IP is broadcast IP.
|
||||
* Source based IPv4 routing hook function.
|
||||
*/
|
||||
struct netif *
|
||||
ip4_route_src_hook(const ip4_addr_t *dest, const ip4_addr_t *src)
|
||||
{
|
||||
struct netif *netif = NULL;
|
||||
|
||||
/* destination IP is broadcast IP? */
|
||||
if ((src != NULL) && (dest->addr == IPADDR_BROADCAST)) {
|
||||
if ((src != NULL) && !ip4_addr_isany(src)) {
|
||||
/* iterate through netifs */
|
||||
for (netif = netif_list; netif != NULL; netif = netif->next) {
|
||||
/* is the netif up, does it have a link and a valid address? */
|
||||
|
||||
@@ -453,10 +453,10 @@ void
|
||||
netif_set_ipaddr(struct netif *netif, const ip4_addr_t *ipaddr)
|
||||
{
|
||||
ip4_addr_t new_addr = (ipaddr ? *ipaddr : *IP4_ADDR_ANY);
|
||||
#if ESP_LWIP
|
||||
#if ESP_TCP_KEEP_CONNECTION_WHEN_IP_CHANGES
|
||||
ip4_addr_t *last_addr = ip_2_ip4(&netif->last_ip_addr);
|
||||
#else
|
||||
ip4_addr_t *last_addr = netif_ip4_addr(netif);
|
||||
ip4_addr_t *last_addr = ip_2_ip4(&(netif->ip_addr));
|
||||
#endif
|
||||
|
||||
/* address is actually being changed? */
|
||||
|
||||
@@ -149,6 +149,22 @@ tcp_tmr(void)
|
||||
}
|
||||
}
|
||||
|
||||
#if LWIP_CALLBACK_API || TCP_LISTEN_BACKLOG
|
||||
/** Called when a listen pcb is closed. Iterates one pcb list and removes the
|
||||
* closed listener pcb from pcb->listener if matching.
|
||||
*/
|
||||
static void
|
||||
tcp_remove_listener(struct tcp_pcb *list, struct tcp_pcb_listen *lpcb)
|
||||
{
|
||||
struct tcp_pcb *pcb;
|
||||
for (pcb = list; pcb != NULL; pcb = pcb->next) {
|
||||
if (pcb->listener == lpcb) {
|
||||
pcb->listener = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
tcp_set_fin_wait_1(struct tcp_pcb *pcb)
|
||||
{
|
||||
@@ -158,6 +174,70 @@ tcp_set_fin_wait_1(struct tcp_pcb *pcb)
|
||||
#endif
|
||||
}
|
||||
|
||||
/** Called when a listen pcb is closed. Iterates all pcb lists and removes the
|
||||
* closed listener pcb from pcb->listener if matching.
|
||||
*/
|
||||
static void
|
||||
tcp_listen_closed(struct tcp_pcb *pcb)
|
||||
{
|
||||
#if LWIP_CALLBACK_API || TCP_LISTEN_BACKLOG
|
||||
size_t i;
|
||||
LWIP_ASSERT("pcb != NULL", pcb != NULL);
|
||||
LWIP_ASSERT("pcb->state == LISTEN", pcb->state == LISTEN);
|
||||
for (i = 1; i < LWIP_ARRAYSIZE(tcp_pcb_lists); i++) {
|
||||
tcp_remove_listener(*tcp_pcb_lists[i], (struct tcp_pcb_listen *)pcb);
|
||||
}
|
||||
#endif
|
||||
LWIP_UNUSED_ARG(pcb);
|
||||
}
|
||||
|
||||
#if TCP_LISTEN_BACKLOG
|
||||
/** @ingroup tcp_raw
|
||||
* Delay accepting a connection in respect to the listen backlog:
|
||||
* the number of outstanding connections is increased until
|
||||
* tcp_backlog_accepted() is called.
|
||||
*
|
||||
* ATTENTION: the caller is responsible for calling tcp_backlog_accepted()
|
||||
* or else the backlog feature will get out of sync!
|
||||
*
|
||||
* @param pcb the connection pcb which is not fully accepted yet
|
||||
*/
|
||||
void
|
||||
tcp_backlog_delayed(struct tcp_pcb *pcb)
|
||||
{
|
||||
LWIP_ASSERT("pcb != NULL", pcb != NULL);
|
||||
if ((pcb->flags & TF_BACKLOGPEND) == 0) {
|
||||
if (pcb->listener != NULL) {
|
||||
pcb->listener->accepts_pending++;
|
||||
LWIP_ASSERT("accepts_pending != 0", pcb->listener->accepts_pending != 0);
|
||||
pcb->flags |= TF_BACKLOGPEND;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** @ingroup tcp_raw
|
||||
* A delayed-accept a connection is accepted (or closed/aborted): decreases
|
||||
* the number of outstanding connections after calling tcp_backlog_delayed().
|
||||
*
|
||||
* ATTENTION: the caller is responsible for calling tcp_backlog_accepted()
|
||||
* or else the backlog feature will get out of sync!
|
||||
*
|
||||
* @param pcb the connection pcb which is now fully accepted (or closed/aborted)
|
||||
*/
|
||||
void
|
||||
tcp_backlog_accepted(struct tcp_pcb *pcb)
|
||||
{
|
||||
LWIP_ASSERT("pcb != NULL", pcb != NULL);
|
||||
if ((pcb->flags & TF_BACKLOGPEND) != 0) {
|
||||
if (pcb->listener != NULL) {
|
||||
LWIP_ASSERT("accepts_pending != 0", pcb->listener->accepts_pending != 0);
|
||||
pcb->listener->accepts_pending--;
|
||||
pcb->flags &= ~TF_BACKLOGPEND;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* TCP_LISTEN_BACKLOG */
|
||||
|
||||
/**
|
||||
* Closes the TX side of a connection held by the PCB.
|
||||
* For tcp_close(), a RST is sent if the application didn't receive all data
|
||||
@@ -227,6 +307,7 @@ tcp_close_shutdown(struct tcp_pcb *pcb, u8_t rst_on_unacked_data)
|
||||
break;
|
||||
case LISTEN:
|
||||
err = ERR_OK;
|
||||
tcp_listen_closed(pcb);
|
||||
tcp_pcb_remove(&tcp_listen_pcbs.pcbs, pcb);
|
||||
memp_free(MEMP_TCP_PCB_LISTEN, pcb);
|
||||
pcb = NULL;
|
||||
@@ -241,6 +322,7 @@ tcp_close_shutdown(struct tcp_pcb *pcb, u8_t rst_on_unacked_data)
|
||||
case SYN_RCVD:
|
||||
err = tcp_send_fin(pcb);
|
||||
if (err == ERR_OK) {
|
||||
tcp_backlog_accepted(pcb);
|
||||
MIB2_STATS_INC(mib2.tcpattemptfails);
|
||||
tcp_set_fin_wait_1(pcb);
|
||||
}
|
||||
@@ -408,6 +490,7 @@ tcp_abandon(struct tcp_pcb *pcb, int reset)
|
||||
pcb->ooseq = NULL;
|
||||
}
|
||||
#endif /* TCP_QUEUE_OOSEQ */
|
||||
tcp_backlog_accepted(pcb);
|
||||
if (send_rst) {
|
||||
LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_abandon: sending RST\n"));
|
||||
tcp_rst(seqno, ackno, &pcb->local_ip, &pcb->remote_ip, local_port, pcb->remote_port);
|
||||
@@ -1747,27 +1830,7 @@ tcp_pcb_purge(struct tcp_pcb *pcb)
|
||||
|
||||
LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge\n"));
|
||||
|
||||
#if TCP_LISTEN_BACKLOG
|
||||
if (pcb->state == SYN_RCVD) {
|
||||
/* Need to find the corresponding listen_pcb and decrease its accepts_pending */
|
||||
struct tcp_pcb_listen *lpcb;
|
||||
LWIP_ASSERT("tcp_pcb_purge: pcb->state == SYN_RCVD but tcp_listen_pcbs is NULL",
|
||||
tcp_listen_pcbs.listen_pcbs != NULL);
|
||||
for (lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = lpcb->next) {
|
||||
if ((lpcb->local_port == pcb->local_port) &&
|
||||
(IP_IS_V6_VAL(pcb->local_ip) == IP_IS_V6_VAL(lpcb->local_ip)) &&
|
||||
(ip_addr_isany(&lpcb->local_ip) ||
|
||||
ip_addr_cmp(&pcb->local_ip, &lpcb->local_ip))) {
|
||||
/* port and address of the listen pcb match the timed-out pcb */
|
||||
LWIP_ASSERT("tcp_pcb_purge: listen pcb does not have accepts pending",
|
||||
lpcb->accepts_pending > 0);
|
||||
lpcb->accepts_pending--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* TCP_LISTEN_BACKLOG */
|
||||
|
||||
tcp_backlog_accepted(pcb);
|
||||
|
||||
if (pcb->refused_data != NULL) {
|
||||
LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge: data left on ->refused_data\n"));
|
||||
@@ -1917,6 +1980,31 @@ tcp_eff_send_mss_impl(u16_t sendmss, const ip_addr_t *dest
|
||||
}
|
||||
#endif /* TCP_CALCULATE_EFF_SEND_MSS */
|
||||
|
||||
/** Helper function for tcp_netif_ip4_addr_changed() that iterates a pcb list */
|
||||
static void
|
||||
tcp_netif_ip_addr_changed_pcblist(const ip4_addr_t* old_addr, struct tcp_pcb* pcb_list)
|
||||
{
|
||||
struct tcp_pcb *pcb;
|
||||
pcb = pcb_list;
|
||||
while (pcb != NULL) {
|
||||
/* PCB bound to current local interface address? */
|
||||
if (ip4_addr_cmp(ip_2_ip4(&pcb->local_ip), old_addr)
|
||||
#if LWIP_AUTOIP
|
||||
/* connections to link-local addresses must persist (RFC3927 ch. 1.9) */
|
||||
&& (!IP_IS_V4_VAL(pcb->local_ip) || !ip4_addr_islinklocal(ip_2_ip4(&pcb->local_ip)))
|
||||
#endif /* LWIP_AUTOIP */
|
||||
) {
|
||||
/* this connection must be aborted */
|
||||
struct tcp_pcb *next = pcb->next;
|
||||
LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_STATE, ("netif_set_ipaddr: aborting TCP pcb %p\n", (void *)pcb));
|
||||
tcp_abort(pcb);
|
||||
pcb = next;
|
||||
} else {
|
||||
pcb = pcb->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if LWIP_IPV4
|
||||
/** This function is called from netif.c when address is changed or netif is removed
|
||||
*
|
||||
@@ -1927,18 +2015,29 @@ void tcp_netif_ipv4_addr_changed(const ip4_addr_t* old_addr, const ip4_addr_t* n
|
||||
{
|
||||
struct tcp_pcb_listen *lpcb, *next;
|
||||
|
||||
if (!ip4_addr_isany(new_addr)) {
|
||||
/* PCB bound to current local interface address? */
|
||||
for (lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = next) {
|
||||
next = lpcb->next;
|
||||
/* Is this an IPv4 pcb? */
|
||||
if (!IP_IS_V6_VAL(lpcb->local_ip)) {
|
||||
/* PCB bound to current local interface address? */
|
||||
if ((!(ip4_addr_isany(ip_2_ip4(&lpcb->local_ip)))) &&
|
||||
(ip4_addr_cmp(ip_2_ip4(&lpcb->local_ip), old_addr))) {
|
||||
/* The PCB is listening to the old ipaddr and
|
||||
* is set to listen to the new one instead */
|
||||
ip_addr_copy_from_ip4(lpcb->local_ip, *new_addr);
|
||||
if (!ip4_addr_isany(old_addr)) {
|
||||
#if ESP_TCP_KEEP_CONNECTION_WHEN_IP_CHANGES
|
||||
if ((new_addr == NULL) || ((!ip4_addr_isany_val(*new_addr)) && (!ip4_addr_cmp(old_addr, new_addr)))) {
|
||||
#endif
|
||||
tcp_netif_ip_addr_changed_pcblist(old_addr, tcp_active_pcbs);
|
||||
tcp_netif_ip_addr_changed_pcblist(old_addr, tcp_bound_pcbs);
|
||||
#if ESP_TCP_KEEP_CONNECTION_WHEN_IP_CHANGES
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!ip4_addr_isany(new_addr)) {
|
||||
/* PCB bound to current local interface address? */
|
||||
for (lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = next) {
|
||||
next = lpcb->next;
|
||||
/* Is this an IPv4 pcb? */
|
||||
if (!IP_IS_V6_VAL(lpcb->local_ip)) {
|
||||
/* PCB bound to current local interface address? */
|
||||
if ((!(ip4_addr_isany(ip_2_ip4(&lpcb->local_ip)))) &&
|
||||
(ip4_addr_cmp(ip_2_ip4(&lpcb->local_ip), old_addr))) {
|
||||
/* The PCB is listening to the old ipaddr and
|
||||
* is set to listen to the new one instead */
|
||||
ip_addr_copy_from_ip4(lpcb->local_ip, *new_addr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -568,6 +568,7 @@ tcp_listen_input(struct tcp_pcb_listen *pcb)
|
||||
}
|
||||
#if TCP_LISTEN_BACKLOG
|
||||
pcb->accepts_pending++;
|
||||
npcb->flags |= TF_BACKLOGPEND;
|
||||
#endif /* TCP_LISTEN_BACKLOG */
|
||||
/* Set up the new PCB. */
|
||||
ip_addr_copy(npcb->local_ip, *ip_current_dest_addr());
|
||||
@@ -582,6 +583,10 @@ tcp_listen_input(struct tcp_pcb_listen *pcb)
|
||||
#if LWIP_CALLBACK_API
|
||||
npcb->accept = pcb->accept;
|
||||
#endif /* LWIP_CALLBACK_API */
|
||||
|
||||
#if LWIP_CALLBACK_API || TCP_LISTEN_BACKLOG
|
||||
npcb->listener = pcb;
|
||||
#endif
|
||||
/* inherit socket options */
|
||||
npcb->so_options = pcb->so_options & SOF_INHERITED;
|
||||
/* Register the new PCB so that we can begin receiving segments
|
||||
@@ -785,11 +790,19 @@ tcp_process(struct tcp_pcb *pcb)
|
||||
if (TCP_SEQ_BETWEEN(ackno, pcb->lastack+1, pcb->snd_nxt)) {
|
||||
pcb->state = ESTABLISHED;
|
||||
LWIP_DEBUGF(TCP_DEBUG, ("TCP connection established %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest));
|
||||
#if LWIP_CALLBACK_API || TCP_LISTEN_BACKLOG
|
||||
#if LWIP_CALLBACK_API
|
||||
LWIP_ASSERT("pcb->accept != NULL", pcb->accept != NULL);
|
||||
#endif
|
||||
/* Call the accept function. */
|
||||
TCP_EVENT_ACCEPT(pcb, ERR_OK, err);
|
||||
|
||||
if (pcb->listener == NULL) {
|
||||
err = ERR_VAL;
|
||||
} else {
|
||||
#endif
|
||||
tcp_backlog_accepted(pcb);
|
||||
/* Call the accept function. */
|
||||
TCP_EVENT_ACCEPT(pcb, ERR_OK, err);
|
||||
}
|
||||
if (err != ERR_OK) {
|
||||
/* If the accept function returns with an error, we abort
|
||||
* the connection. */
|
||||
|
||||
@@ -232,6 +232,9 @@ void lwip_netconn_do_disconnect (void *m);
|
||||
void lwip_netconn_do_listen (void *m);
|
||||
void lwip_netconn_do_send (void *m);
|
||||
void lwip_netconn_do_recv (void *m);
|
||||
#if TCP_LISTEN_BACKLOG
|
||||
void lwip_netconn_do_accepted (void *m);
|
||||
#endif
|
||||
void lwip_netconn_do_write (void *m);
|
||||
void lwip_netconn_do_getaddr (void *m);
|
||||
void lwip_netconn_do_close (void *m);
|
||||
|
||||
@@ -138,7 +138,7 @@ typedef u16_t tcpflags_t;
|
||||
#define TCPWND16(x) (x)
|
||||
#define TCP_WND_MAX(pcb) TCP_WND(pcb)
|
||||
typedef u16_t tcpwnd_size_t;
|
||||
typedef u8_t tcpflags_t;
|
||||
typedef u16_t tcpflags_t;
|
||||
#endif
|
||||
|
||||
enum tcp_state {
|
||||
@@ -203,6 +203,9 @@ struct tcp_pcb {
|
||||
#define TF_NAGLEMEMERR 0x80U /* nagle enabled, memerr, try to output to prevent delayed ACK to happen */
|
||||
#if LWIP_WND_SCALE
|
||||
#define TF_WND_SCALE 0x0100U /* Window Scale option enabled */
|
||||
#endif
|
||||
#if TCP_LISTEN_BACKLOG
|
||||
#define TF_BACKLOGPEND 0x0200U /* If this is set, a connection pcb has increased the backlog on its listener */
|
||||
#endif
|
||||
|
||||
/* the rest of the fields are in host byte order
|
||||
@@ -311,6 +314,10 @@ struct tcp_pcb {
|
||||
u8_t rcv_scale;
|
||||
#endif
|
||||
|
||||
#if TCP_LISTEN_BACKLOG
|
||||
struct tcp_pcb_listen *listener;
|
||||
#endif
|
||||
|
||||
#if ESP_STATS_TCP
|
||||
#define ESP_STATS_TCP_ARRAY_SIZE 20
|
||||
u16_t retry_cnt[TCP_MAXRTX];
|
||||
@@ -383,16 +390,17 @@ void tcp_err (struct tcp_pcb *pcb, tcp_err_fn err);
|
||||
#define tcp_nagle_disabled(pcb) (((pcb)->flags & TF_NODELAY) != 0)
|
||||
|
||||
#if TCP_LISTEN_BACKLOG
|
||||
#define tcp_accepted(pcb) do { \
|
||||
LWIP_ASSERT("pcb->state == LISTEN (called for wrong pcb?)", pcb->state == LISTEN); \
|
||||
(((struct tcp_pcb_listen *)(pcb))->accepts_pending--); } while(0)
|
||||
#define tcp_backlog_set(pcb, new_backlog) do { \
|
||||
LWIP_ASSERT("pcb->state == LISTEN (called for wrong pcb?)", (pcb)->state == LISTEN); \
|
||||
((struct tcp_pcb_listen *)(pcb))->backlog = ((new_backlog) ? (new_backlog) : 1); } while(0)
|
||||
void tcp_backlog_delayed(struct tcp_pcb* pcb);
|
||||
void tcp_backlog_accepted(struct tcp_pcb* pcb);
|
||||
#else /* TCP_LISTEN_BACKLOG */
|
||||
#define tcp_accepted(pcb) LWIP_ASSERT("pcb->state == LISTEN (called for wrong pcb?)", \
|
||||
(pcb)->state == LISTEN)
|
||||
#define tcp_backlog_set(pcb, new_backlog)
|
||||
#define tcp_backlog_delayed(pcb)
|
||||
#define tcp_backlog_accepted(pcb)
|
||||
#endif /* TCP_LISTEN_BACKLOG */
|
||||
#define tcp_accepted(pcb) do { LWIP_UNUSED_ARG(pcb); } while(0) /* compatibility define, not needed any more */
|
||||
|
||||
void tcp_recved (struct tcp_pcb *pcb, u16_t len);
|
||||
err_t tcp_bind (struct tcp_pcb *pcb, const ip_addr_t *ipaddr,
|
||||
|
||||
@@ -294,6 +294,12 @@
|
||||
*/
|
||||
#define TCP_QUEUE_OOSEQ CONFIG_TCP_QUEUE_OOSEQ
|
||||
|
||||
/**
|
||||
* ESP_TCP_KEEP_CONNECTION_WHEN_IP_CHANGES==1: Keep TCP connection when IP changed
|
||||
* scenario happens: 192.168.0.2 -> 0.0.0.0 -> 192.168.0.2 or 192.168.0.2 -> 0.0.0.0
|
||||
*/
|
||||
|
||||
#define ESP_TCP_KEEP_CONNECTION_WHEN_IP_CHANGES CONFIG_ESP_TCP_KEEP_CONNECTION_WHEN_IP_CHANGES
|
||||
/*
|
||||
* LWIP_EVENT_API==1: The user defines lwip_tcp_event() to receive all
|
||||
* events (accept, sent, etc) that happen in the system.
|
||||
|
||||
@@ -60,7 +60,7 @@ void HashList::insert(const Item& item, size_t index)
|
||||
newBlock->mCount++;
|
||||
}
|
||||
|
||||
void HashList::erase(size_t index)
|
||||
void HashList::erase(size_t index, bool itemShouldExist)
|
||||
{
|
||||
for (auto it = mBlockList.begin(); it != mBlockList.end();) {
|
||||
bool haveEntries = false;
|
||||
@@ -82,7 +82,9 @@ void HashList::erase(size_t index)
|
||||
++it;
|
||||
}
|
||||
}
|
||||
assert(false && "item should have been present in cache");
|
||||
if (itemShouldExist) {
|
||||
assert(false && "item should have been present in cache");
|
||||
}
|
||||
}
|
||||
|
||||
size_t HashList::find(size_t start, const Item& item)
|
||||
|
||||
@@ -29,7 +29,7 @@ public:
|
||||
~HashList();
|
||||
|
||||
void insert(const Item& item, size_t index);
|
||||
void erase(const size_t index);
|
||||
void erase(const size_t index, bool itemShouldExist=true);
|
||||
size_t find(size_t start, const Item& item);
|
||||
void clear();
|
||||
|
||||
|
||||
@@ -314,7 +314,6 @@ esp_err_t Page::eraseEntryAndSpan(size_t index)
|
||||
{
|
||||
auto state = mEntryTable.get(index);
|
||||
assert(state == EntryState::WRITTEN || state == EntryState::EMPTY);
|
||||
mHashList.erase(index);
|
||||
|
||||
size_t span = 1;
|
||||
if (state == EntryState::WRITTEN) {
|
||||
@@ -324,6 +323,7 @@ esp_err_t Page::eraseEntryAndSpan(size_t index)
|
||||
return rc;
|
||||
}
|
||||
if (item.calculateCrc32() != item.crc32) {
|
||||
mHashList.erase(index, false);
|
||||
rc = alterEntryState(index, EntryState::ERASED);
|
||||
--mUsedEntryCount;
|
||||
++mErasedEntryCount;
|
||||
@@ -331,6 +331,7 @@ esp_err_t Page::eraseEntryAndSpan(size_t index)
|
||||
return rc;
|
||||
}
|
||||
} else {
|
||||
mHashList.erase(index);
|
||||
span = item.span;
|
||||
for (ptrdiff_t i = index + span - 1; i >= static_cast<ptrdiff_t>(index); --i) {
|
||||
if (mEntryTable.get(i) == EntryState::WRITTEN) {
|
||||
@@ -511,11 +512,6 @@ esp_err_t Page::mLoadEntryTable()
|
||||
return err;
|
||||
}
|
||||
|
||||
mHashList.insert(item, i);
|
||||
|
||||
// search for potential duplicate item
|
||||
size_t duplicateIndex = mHashList.find(0, item);
|
||||
|
||||
if (item.crc32 != item.calculateCrc32()) {
|
||||
err = eraseEntryAndSpan(i);
|
||||
if (err != ESP_OK) {
|
||||
@@ -525,6 +521,10 @@ esp_err_t Page::mLoadEntryTable()
|
||||
continue;
|
||||
}
|
||||
|
||||
mHashList.insert(item, i);
|
||||
|
||||
// search for potential duplicate item
|
||||
size_t duplicateIndex = mHashList.find(0, item);
|
||||
|
||||
if (item.datatype == ItemType::BLOB || item.datatype == ItemType::SZ) {
|
||||
span = item.span;
|
||||
@@ -576,8 +576,6 @@ esp_err_t Page::mLoadEntryTable()
|
||||
return err;
|
||||
}
|
||||
|
||||
mHashList.insert(item, i);
|
||||
|
||||
if (item.crc32 != item.calculateCrc32()) {
|
||||
err = eraseEntryAndSpan(i);
|
||||
if (err != ESP_OK) {
|
||||
@@ -586,9 +584,11 @@ esp_err_t Page::mLoadEntryTable()
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
assert(item.span > 0);
|
||||
|
||||
mHashList.insert(item, i);
|
||||
|
||||
size_t span = item.span;
|
||||
i += span - 1;
|
||||
}
|
||||
@@ -726,7 +726,11 @@ esp_err_t Page::findItem(uint8_t nsIndex, ItemType datatype, const char* key, si
|
||||
|
||||
auto crc32 = item.calculateCrc32();
|
||||
if (item.crc32 != crc32) {
|
||||
eraseEntryAndSpan(i);
|
||||
rc = eraseEntryAndSpan(i);
|
||||
if (rc != ESP_OK) {
|
||||
mState = PageState::INVALID;
|
||||
return rc;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
@@ -259,6 +259,25 @@ TEST_CASE("Page validates blob size", "[nvs]")
|
||||
TEST_ESP_OK(page.writeItem(1, ItemType::BLOB, "2", buf, Page::BLOB_MAX_SIZE));
|
||||
}
|
||||
|
||||
TEST_CASE("Page handles invalid CRC of variable length items", "[nvs][cur]")
|
||||
{
|
||||
SpiFlashEmulator emu(4);
|
||||
{
|
||||
Page page;
|
||||
TEST_ESP_OK(page.load(0));
|
||||
char buf[128] = {0};
|
||||
TEST_ESP_OK(page.writeItem(1, ItemType::BLOB, "1", buf, sizeof(buf)));
|
||||
}
|
||||
// corrupt header of the item (64 is the offset of the first item in page)
|
||||
uint32_t overwrite_buf = 0;
|
||||
emu.write(64, &overwrite_buf, 4);
|
||||
// load page again
|
||||
{
|
||||
Page page;
|
||||
TEST_ESP_OK(page.load(0));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("can init PageManager in empty flash", "[nvs]")
|
||||
{
|
||||
SpiFlashEmulator emu(4);
|
||||
|
||||
@@ -96,6 +96,7 @@
|
||||
#define SENS_FORCE_XPD_SAR_M ((SENS_FORCE_XPD_SAR_V)<<(SENS_FORCE_XPD_SAR_S))
|
||||
#define SENS_FORCE_XPD_SAR_V 0x3
|
||||
#define SENS_FORCE_XPD_SAR_S 18
|
||||
#define SENS_FORCE_XPD_SAR_SW_M (BIT1)
|
||||
#define SENS_FORCE_XPD_SAR_FSM 0 // Use FSM to control power down
|
||||
#define SENS_FORCE_XPD_SAR_PD 2 // Force power down
|
||||
#define SENS_FORCE_XPD_SAR_PU 3 // Force power up
|
||||
|
||||
@@ -42,7 +42,7 @@ Project Properties
|
||||
|
||||
* Click on the "C/C++ Build" properties page (top-level):
|
||||
|
||||
* Uncheck "Use default build command" and enter this for the custom build command: ``python ${IDF_PATH}/tools/windows/eclipse_make.py``.
|
||||
* Uncheck "Use default build command" and enter this for the custom build command: ``python ${IDF_PATH}/tools/windows/eclipse_make.py``
|
||||
|
||||
* Click on the "Environment" properties page under "C/C++ Build":
|
||||
|
||||
@@ -56,10 +56,15 @@ Project Properties
|
||||
|
||||
* Click the "Providers" tab
|
||||
|
||||
* In the list of providers, click "CDT GCC Built-in Compiler Settings Cygwin". Under "Command to get compiler specs", replace the text ``${COMMAND}`` at the beginning of the line with ``xtensa-esp32-elf-gcc``. This means the full "Command to get compiler specs" should be ``xtensa-esp32-elf-gcc ${FLAGS} -E -P -v -dD "${INPUTS}"``.
|
||||
* In the list of providers, click "CDT Cross GCC Built-in Compiler Settings". Change "Command to get compiler specs" to ``xtensa-esp32-elf-gcc ${FLAGS} -E -P -v -dD "${INPUTS}"``.
|
||||
|
||||
* In the list of providers, click "CDT GCC Build Output Parser" and type ``xtensa-esp32-elf-`` at the beginning of the Compiler command pattern, and wrap remaining part with brackets. This means the full Compiler command pattern should be ``xtensa-esp32-elf-((g?cc)|([gc]\+\+)|(clang))``
|
||||
* In the list of providers, click "CDT GCC Build Output Parser" and change the "Compiler command pattern" to ``xtensa-esp32-elf-(gcc|g\+\+|c\+\+|cc|cpp|clang)``
|
||||
|
||||
Navigate to "C/C++ General" -> "Indexer" property page:
|
||||
|
||||
* Check "Enable project specific settings" to enable the rest of the settings on this page.
|
||||
|
||||
* Uncheck "Allow heuristic resolution of includes". When this option is enabled Eclipse sometimes fails to find correct header directories.
|
||||
|
||||
Building in Eclipse
|
||||
-------------------
|
||||
|
||||
@@ -58,9 +58,15 @@ Navigate to "C/C++ General" -> "Preprocessor Include Paths" property page:
|
||||
|
||||
* Click the "Providers" tab
|
||||
|
||||
* In the list of providers, click "CDT Cross GCC Built-in Compiler Settings". Under "Command to get compiler specs", replace the text ``${COMMAND}`` at the beginning of the line with ``xtensa-esp32-elf-gcc``. This means the full "Command to get compiler specs" should be ``xtensa-esp32-elf-gcc ${FLAGS} -E -P -v -dD "${INPUTS}"``.
|
||||
* In the list of providers, click "CDT Cross GCC Built-in Compiler Settings". Change "Command to get compiler specs" to ``xtensa-esp32-elf-gcc ${FLAGS} -E -P -v -dD "${INPUTS}"``.
|
||||
|
||||
* In the list of providers, click "CDT GCC Build Output Parser" and type ``xtensa-esp32-elf-`` at the beginning of the Compiler command pattern. This means the full Compiler command pattern should be ``xtensa-esp32-elf-(g?cc)|([gc]\+\+)|(clang)``
|
||||
* In the list of providers, click "CDT GCC Build Output Parser" and change the "Compiler command pattern" to ``xtensa-esp32-elf-(gcc|g\+\+|c\+\+|cc|cpp|clang)``
|
||||
|
||||
Navigate to "C/C++ General" -> "Indexer" property page:
|
||||
|
||||
* Check "Enable project specific settings" to enable the rest of the settings on this page.
|
||||
|
||||
* Uncheck "Allow heuristic resolution of includes". When this option is enabled Eclipse sometimes fails to find correct header directories.
|
||||
|
||||
.. _eclipse-build-project:
|
||||
|
||||
|
||||
@@ -47,7 +47,8 @@ static esp_ble_scan_params_t ble_scan_params = {
|
||||
.own_addr_type = BLE_ADDR_TYPE_PUBLIC,
|
||||
.scan_filter_policy = BLE_SCAN_FILTER_ALLOW_ALL,
|
||||
.scan_interval = 0x50,
|
||||
.scan_window = 0x30
|
||||
.scan_window = 0x30,
|
||||
.scan_duplicate = BLE_SCAN_DUPLICATE_DISABLE
|
||||
};
|
||||
|
||||
static void esp_eddystone_show_inform(const esp_eddystone_result_t* res)
|
||||
|
||||
@@ -43,7 +43,8 @@ static esp_ble_scan_params_t ble_scan_params = {
|
||||
.own_addr_type = BLE_ADDR_TYPE_PUBLIC,
|
||||
.scan_filter_policy = BLE_SCAN_FILTER_ALLOW_ALL,
|
||||
.scan_interval = 0x50,
|
||||
.scan_window = 0x30
|
||||
.scan_window = 0x30,
|
||||
.scan_duplicate = BLE_SCAN_DUPLICATE_DISABLE
|
||||
};
|
||||
|
||||
#elif (IBEACON_MODE == IBEACON_SENDER)
|
||||
|
||||
@@ -93,7 +93,8 @@ static esp_ble_scan_params_t ble_scan_params = {
|
||||
.own_addr_type = BLE_ADDR_TYPE_PUBLIC,
|
||||
.scan_filter_policy = BLE_SCAN_FILTER_ALLOW_ALL,
|
||||
.scan_interval = 0x50,
|
||||
.scan_window = 0x30
|
||||
.scan_window = 0x30,
|
||||
.scan_duplicate = BLE_SCAN_DUPLICATE_DISABLE
|
||||
};
|
||||
|
||||
static const char device_name[] = "ESP_SPP_SERVER";
|
||||
|
||||
@@ -77,7 +77,8 @@ static esp_ble_scan_params_t ble_scan_params = {
|
||||
.own_addr_type = BLE_ADDR_TYPE_PUBLIC,
|
||||
.scan_filter_policy = BLE_SCAN_FILTER_ALLOW_ALL,
|
||||
.scan_interval = 0x50,
|
||||
.scan_window = 0x30
|
||||
.scan_window = 0x30,
|
||||
.scan_duplicate = BLE_SCAN_DUPLICATE_DISABLE
|
||||
};
|
||||
|
||||
struct gattc_profile_inst {
|
||||
|
||||
@@ -64,7 +64,8 @@ static esp_ble_scan_params_t ble_scan_params = {
|
||||
.own_addr_type = BLE_ADDR_TYPE_RANDOM,
|
||||
.scan_filter_policy = BLE_SCAN_FILTER_ALLOW_ALL,
|
||||
.scan_interval = 0x50,
|
||||
.scan_window = 0x30
|
||||
.scan_window = 0x30,
|
||||
.scan_duplicate = BLE_SCAN_DUPLICATE_DISABLE
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -100,7 +100,8 @@ static esp_ble_scan_params_t ble_scan_params = {
|
||||
.own_addr_type = BLE_ADDR_TYPE_PUBLIC,
|
||||
.scan_filter_policy = BLE_SCAN_FILTER_ALLOW_ALL,
|
||||
.scan_interval = 0x50,
|
||||
.scan_window = 0x30
|
||||
.scan_window = 0x30,
|
||||
.scan_duplicate = BLE_SCAN_DUPLICATE_DISABLE
|
||||
};
|
||||
|
||||
struct gattc_profile_inst {
|
||||
|
||||
@@ -9,8 +9,11 @@
|
||||
#include "driver/i2s.h"
|
||||
#include "driver/adc.h"
|
||||
#include "audio_example_file.h"
|
||||
#include "esp_adc_cal.h"
|
||||
|
||||
static const char* TAG = "ad/da";
|
||||
#define V_REF 1100
|
||||
#define ADC1_TEST_CHANNEL (ADC1_CHANNEL_7)
|
||||
|
||||
#define PARTITION_NAME "storage"
|
||||
|
||||
@@ -36,6 +39,10 @@ static const char* TAG = "ad/da";
|
||||
#define EXAMPLE_I2S_FORMAT (I2S_CHANNEL_FMT_RIGHT_LEFT)
|
||||
//I2S channel number
|
||||
#define EXAMPLE_I2S_CHANNEL_NUM ((EXAMPLE_I2S_FORMAT < I2S_CHANNEL_FMT_ONLY_RIGHT) ? (2) : (1))
|
||||
//I2S built-in ADC unit
|
||||
#define I2S_ADC_UNIT ADC_UNIT_1
|
||||
//I2S built-in ADC channel
|
||||
#define I2S_ADC_CHANNEL ADC1_CHANNEL_0
|
||||
|
||||
//flash record size, for recording 5 seconds' data
|
||||
#define FLASH_RECORD_SIZE (EXAMPLE_I2S_CHANNEL_NUM * EXAMPLE_I2S_SAMPLE_RATE * EXAMPLE_I2S_SAMPLE_BITS / 8 * 5)
|
||||
@@ -45,6 +52,7 @@ static const char* TAG = "ad/da";
|
||||
//flash read / write address
|
||||
#define FLASH_ADDR (0x200000)
|
||||
|
||||
|
||||
/**
|
||||
* @brief I2S ADC/DAC mode init.
|
||||
*/
|
||||
@@ -66,7 +74,7 @@ void example_i2s_init()
|
||||
//init DAC pad
|
||||
i2s_set_dac_mode(I2S_DAC_CHANNEL_BOTH_EN);
|
||||
//init ADC pad
|
||||
i2s_set_adc_mode(ADC_UNIT_1, ADC1_CHANNEL_0);
|
||||
i2s_set_adc_mode(I2S_ADC_UNIT, I2S_ADC_CHANNEL);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -193,10 +201,8 @@ void example_i2s_adc_dac(void*arg)
|
||||
ESP_LOGE(TAG, "Partition error: can't find partition name: %s\n", PARTITION_NAME);
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
//1. Erase flash
|
||||
example_erase_flash();
|
||||
example_i2s_init();
|
||||
int i2s_read_len = EXAMPLE_I2S_READ_LEN;
|
||||
int flash_wr_size = 0;
|
||||
size_t bytes_read, bytes_written;
|
||||
@@ -205,6 +211,7 @@ void example_i2s_adc_dac(void*arg)
|
||||
#if RECORD_IN_FLASH_EN
|
||||
char* i2s_read_buff = (char*) calloc(i2s_read_len, sizeof(char));
|
||||
uint8_t* flash_write_buff = (uint8_t*) calloc(i2s_read_len, sizeof(char));
|
||||
i2s_adc_enable(EXAMPLE_I2S_NUM);
|
||||
while (flash_wr_size < FLASH_RECORD_SIZE) {
|
||||
//read data from I2S bus, in this case, from ADC.
|
||||
i2s_read(EXAMPLE_I2S_NUM, i2s_read_buff, i2s_read_len, &bytes_read, portMAX_DELAY);
|
||||
@@ -214,6 +221,7 @@ void example_i2s_adc_dac(void*arg)
|
||||
flash_wr_size += i2s_read_len;
|
||||
ets_printf("Sound recording %u%%\n", flash_wr_size * 100 / FLASH_RECORD_SIZE);
|
||||
}
|
||||
i2s_adc_disable(EXAMPLE_I2S_NUM);
|
||||
free(i2s_read_buff);
|
||||
i2s_read_buff = NULL;
|
||||
free(flash_write_buff);
|
||||
@@ -257,10 +265,28 @@ void example_i2s_adc_dac(void*arg)
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
void adc_read_task(void* arg)
|
||||
{
|
||||
adc1_config_width(ADC_WIDTH_12Bit);
|
||||
adc1_config_channel_atten(ADC1_TEST_CHANNEL, ADC_ATTEN_11db);
|
||||
esp_adc_cal_characteristics_t characteristics;
|
||||
esp_adc_cal_characterize(ADC_UNIT_1, ADC_ATTEN_11db, ADC_WIDTH_12Bit, ESP_ADC_CAL_VAL_DEFAULT_VREF, &characteristics);
|
||||
|
||||
while(1) {
|
||||
uint32_t voltage;
|
||||
esp_err_t ret = esp_adc_cal_get_voltage(ADC1_TEST_CHANNEL, &characteristics, &voltage);
|
||||
assert(ret==ESP_OK);
|
||||
ESP_LOGI(TAG, "%d mV", voltage);
|
||||
vTaskDelay(200 / portTICK_RATE_MS);
|
||||
}
|
||||
}
|
||||
|
||||
esp_err_t app_main()
|
||||
{
|
||||
example_i2s_init();
|
||||
esp_log_level_set("I2S", ESP_LOG_INFO);
|
||||
xTaskCreate(example_i2s_adc_dac, "example_i2s_adc_dac", 1024 * 2, NULL, 5, NULL);
|
||||
xTaskCreate(adc_read_task, "ADC read task", 2048, NULL, 5, NULL);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -17,6 +17,8 @@ import os
|
||||
import re
|
||||
import subprocess
|
||||
import functools
|
||||
import random
|
||||
import tempfile
|
||||
|
||||
import DUT
|
||||
|
||||
@@ -40,6 +42,8 @@ class IDFDUT(DUT.SerialDUT):
|
||||
""" IDF DUT, extends serial with ESPTool methods """
|
||||
|
||||
CHIP_TYPE_PATTERN = re.compile(r"Detecting chip type[.:\s]+(.+)")
|
||||
# if need to erase NVS partition in start app
|
||||
ERASE_NVS = True
|
||||
|
||||
def __init__(self, name, port, log_file, app, **kwargs):
|
||||
self.download_config, self.partition_table = app.process_app_info()
|
||||
@@ -68,24 +72,39 @@ class IDFDUT(DUT.SerialDUT):
|
||||
return cls.get_chip(app, port) is not None
|
||||
|
||||
@_tool_method
|
||||
def start_app(self):
|
||||
def start_app(self, erase_nvs=ERASE_NVS):
|
||||
"""
|
||||
download and start app.
|
||||
|
||||
:param: erase_nvs: whether erase NVS partition during flash
|
||||
:return: None
|
||||
"""
|
||||
if erase_nvs:
|
||||
address = self.partition_table["nvs"]["offset"]
|
||||
size = self.partition_table["nvs"]["size"]
|
||||
nvs_file = tempfile.NamedTemporaryFile()
|
||||
nvs_file.write(chr(0xFF) * size)
|
||||
nvs_file.flush()
|
||||
download_config = self.download_config + [address, nvs_file.name]
|
||||
else:
|
||||
download_config = self.download_config
|
||||
|
||||
retry_baud_rates = ["921600", "115200"]
|
||||
error = IDFToolError()
|
||||
for baud_rate in retry_baud_rates:
|
||||
try:
|
||||
subprocess.check_output(["python", self.app.esptool,
|
||||
"--port", self.port, "--baud", baud_rate]
|
||||
+ self.download_config)
|
||||
break
|
||||
except subprocess.CalledProcessError as error:
|
||||
continue
|
||||
else:
|
||||
raise error
|
||||
try:
|
||||
for baud_rate in retry_baud_rates:
|
||||
try:
|
||||
subprocess.check_output(["python", self.app.esptool,
|
||||
"--port", self.port, "--baud", baud_rate]
|
||||
+ download_config)
|
||||
break
|
||||
except subprocess.CalledProcessError as error:
|
||||
continue
|
||||
else:
|
||||
raise error
|
||||
finally:
|
||||
if erase_nvs:
|
||||
nvs_file.close()
|
||||
|
||||
@_tool_method
|
||||
def reset(self):
|
||||
@@ -96,6 +115,17 @@ class IDFDUT(DUT.SerialDUT):
|
||||
"""
|
||||
subprocess.check_output(["python", self.app.esptool, "--port", self.port, "run"])
|
||||
|
||||
@_tool_method
|
||||
def erase_partition(self, partition):
|
||||
"""
|
||||
:param partition: partition name to erase
|
||||
:return: None
|
||||
"""
|
||||
address = self.partition_table[partition]["offset"]
|
||||
size = self.partition_table[partition]["size"]
|
||||
with open(".erase_partition.tmp", "wb") as f:
|
||||
f.write(chr(0xFF) * size)
|
||||
|
||||
@_tool_method
|
||||
def dump_flush(self, output_file, **kwargs):
|
||||
"""
|
||||
|
||||
@@ -20,9 +20,8 @@ from IDF.IDFApp import IDFApp, Example, UT
|
||||
from IDF.IDFDUT import IDFDUT
|
||||
|
||||
|
||||
def idf_example_test(app=Example, dut=IDFDUT, chip="ESP32",
|
||||
module="examples", execution_time=1,
|
||||
**kwargs):
|
||||
def idf_example_test(app=Example, dut=IDFDUT, chip="ESP32", module="examples", execution_time=1,
|
||||
level="example", erase_nvs=True, **kwargs):
|
||||
"""
|
||||
decorator for testing idf examples (with default values for some keyword args).
|
||||
|
||||
@@ -31,12 +30,19 @@ def idf_example_test(app=Example, dut=IDFDUT, chip="ESP32",
|
||||
:param chip: chip supported, string or tuple
|
||||
:param module: module, string
|
||||
:param execution_time: execution time in minutes, int
|
||||
:param level: test level, could be used to filter test cases, string
|
||||
:param erase_nvs: if need to erase_nvs in DUT.start_app()
|
||||
:param kwargs: other keyword args
|
||||
:return: test method
|
||||
"""
|
||||
# not use partial function as define as function support auto generating document
|
||||
try:
|
||||
# try to config the default behavior of erase nvs
|
||||
dut.ERASE_NVS = erase_nvs
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
return TinyFW.test_method(app=app, dut=dut, chip=chip, module=module,
|
||||
execution_time=execution_time, **kwargs)
|
||||
execution_time=execution_time, level=level, **kwargs)
|
||||
|
||||
|
||||
def log_performance(item, value):
|
||||
|
||||
Reference in New Issue
Block a user