Compare commits

..

27 Commits

Author SHA1 Message Date
Angus Gratton
054e82b4b3 Merge branch 'test/workaround_ci_failures_v3.0' into 'release/v3.0'
CI: erase nvs partition before test (backport v3.0)

See merge request idf/esp-idf!2870
2018-08-01 17:02:50 +08:00
Jiang Jiang Jian
7d4a9db191 Merge branch 'bugfix/btdm_fix_slave_cant_receive_long_packets_in_smp_for_v3.0' into 'release/v3.0'
component/bt: fix slave cant receive long packets in smp for v3.0

See merge request idf/esp-idf!2857
2018-08-01 14:40:05 +08:00
He Yin Ling
8f81157432 CI: add stage host_test:
1. Add `host_test` stage for test jobs running on host.
2. Rename stage `test` to `integration_test`.
2018-07-29 00:26:38 +08:00
He Yin Ling
5141570f24 CI: minor optimize of CI config file:
1. set shorter expire time for artifacts
2. set dependency for example test jobs, to limit the artifacts it downloads
2018-07-29 00:20:15 +08:00
He Yin Ling
f86d512672 CI: remove test report stage:
Test report is not used as expected:

1. we rarely download and use test report
2. current test report method doesn't handle large amount data well,
   need to be replaced by other methods

Test report also make test jobs allow to fail. It breaks the
original flow of Gitlab CI and make user confused.
2018-07-29 00:17:25 +08:00
Jiang Jiang Jian
ab341359f5 Merge branch 'bugfix/ampdu_duplicate_v3.0' into 'release/v3.0'
Wifi: fix ampdu duplicate issue (backport v3.0)

See merge request idf/esp-idf!2804
2018-07-28 17:56:25 +08:00
He Yin Ling
f98da26b38 CI: erase nvs partition before test:
Latest NVS partition bin can't be parsed by old IDF revision. Need to erase before test.
2018-07-28 15:18:10 +08:00
zwj
d0cd624d2b component/bt: fix slave cant receive long packets in smp 2018-07-26 11:39:47 +08:00
Ivan Grokhotkov
c8c4bd099e Merge branch 'bugfix/fix_uart_timeout_bug_when_enable_reftick_v3.0' into 'release/v3.0'
driver(uart): fix uart timeout bug when enable reftick for release v3.0

See merge request idf/esp-idf!2811
2018-07-24 13:16:54 +08:00
Angus Gratton
36c14cf214 Merge branch 'bugfix/add_queueset_critical_sections_v3.0' into 'release/v3.0'
freertos: Add critical sections to queue sets (backport v3.0)

See merge request idf/esp-idf!2788
2018-07-20 10:03:59 +08:00
hou wen xiang
a7c9cf3a6b driver(uart): Fix uart time_out bug when using ref_tick for release v3.0 2018-07-18 17:35:59 +08:00
Jiang Jiang Jian
9aee394dc6 Merge branch 'bugfix/tw23835_add_source_ip_route_for_unicast_v3.0' into 'release/v3.0'
lwip: add source ip based route for unicast packet (backport v3.0)

See merge request idf/esp-idf!2781
2018-07-18 17:34:19 +08:00
chenyudong
05eb9d155f Wifi: fix ampdu duplicate issue
fix ampdu duplicate issue
2018-07-18 14:51:29 +08:00
Jiang Jiang Jian
0669fe8f02 Merge branch 'bugfix/tw23835_add_source_ip_route_for_unicast_v3.0' into 'release/v3.0'
lwip: add source ip based route for unicast packet (backport v3.0)

See merge request idf/esp-idf!2781
2018-07-17 14:12:13 +08:00
Darian Leung
cabb97f9a9 freertos: Add critical sections to queue sets.
Queue sets are not SMP safe. This commit adds
critical sections to queue sets. Unit tests for
queue sets have also been added.
2018-07-16 19:30:46 +08:00
Liu Zhi Fu
41b1db4dc6 lwip: add source ip based route for unicast packet
Add source IP based route for unicast packets forwarding.
2018-07-16 17:11:01 +08:00
Jiang Jiang Jian
8bc76b3684 Merge branch 'bugfix/tw23667_tcp_pcb_purge_assert_v3.0' into 'release/v3.0'
lwip: fix the assertion in tcp_pcb_purge() (backport v3.0)

See merge request idf/esp-idf!2723
2018-07-15 14:53:58 +08:00
Jiang Jiang Jian
245b753904 Merge branch 'bugfix/disable_lwip_trust_ip_by_default_v3.0' into 'release/v3.0'
lwip: disable ETHARP_TRUST_IP_MAC by default (backport v3.0)

See merge request idf/esp-idf!2721
2018-07-15 14:53:46 +08:00
Liu Zhi Fu
86a6c21e79 lwip: fix the assertion in tcp_pcb_purge()
Fix the assertion in tcp_pcb_purge().
2018-07-14 09:59:59 +08:00
Liu Zhi Fu
8cc0379da1 lwip: disable ETHARP_TRUST_IP_MAC by default
Disable ETHARP_TRUST_IP_MAC by default because:
1. The LAN peer may not be trustful
2. The LAN peer may has problem to update its ARP entry
2018-07-14 09:57:47 +08:00
Jiang Jiang Jian
e56bfadc58 Merge branch 'feature/ble_mesh_idf_v3.0' into 'release/v3.0'
Component/bt: add scan duplicate for v3.0

See merge request idf/esp-idf!2445
2018-07-13 19:10:49 +08:00
Ivan Grokhotkov
583e80708b Merge branch 'bugfix/esp_timer_set_alarm_v3.0' into 'release/v3.0'
esp_timer: remove busy loop in esp_timer_impl_set_alarm (backport v3.0)

See merge request idf/esp-idf!2726
2018-07-13 15:00:23 +08:00
zhiweijian
5cf4d8a1ec Component/bt: add scan duplicate for ble mesh in idf3.0 2018-07-12 07:35:13 +00:00
Ivan Grokhotkov
ef3c6ac276 esp_timer: test for monotonic values of esp_timer_get_timer in CI
Reduce test time by increasing overflow rate, make test more robust.
2018-07-09 15:42:30 +08:00
Ivan Grokhotkov
4129436f7e esp_timer: add test for esp_timer_impl_set_alarm
Ref https://github.com/espressif/esp-idf/issues/1891
2018-07-09 15:42:30 +08:00
Ivan Grokhotkov
0808a04ee8 esp_timer: reduce overflow value in unit tests
This allows testing for race conditions which occur near timer
overflow point more effectively.
2018-07-09 12:06:11 +08:00
Ivan Grokhotkov
c99977b67c esp_timer: don’t busy loop in esp_timer_impl_set_alarm
Previously the loop in esp_timer_impl_set_alarm was necessary to catch
the case when timer count wraps around (goes from 2^32 - 1 to 0).
Since ALARM_OVERFLOW_VAL was reduced from 2^32 - 1 to 0xefffffff,
this is no longer necessary.

Fixes https://github.com/espressif/esp-idf/issues/1891
2018-07-09 12:06:11 +08:00
40 changed files with 725 additions and 239 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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);
}

View File

@@ -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;

View File

@@ -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;

View File

@@ -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);
/*******************************************************************************

View File

@@ -560,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,
@@ -567,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);

View File

@@ -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:

View File

@@ -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;

View File

@@ -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;

View File

@@ -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);

View File

@@ -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 */

View File

@@ -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;
}

View File

@@ -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");

View File

@@ -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;

View File

@@ -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

View File

@@ -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

View File

@@ -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]")

View File

@@ -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;
}

View 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

View File

@@ -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"

View File

@@ -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

View File

@@ -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 */

View File

@@ -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

View File

@@ -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? */

View File

@@ -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,39 +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;
/*
* The official LWIP will assert the system if tcp_listen_pcbs.listen_pcbs is NULL, it's a bug.
*
* Considering following scenario:
* 1. On TCP server side, one of TCP pcb is in SYNC_RECV state and is waiting for TCP ACK from TCP client.
* 2. The TCP server is closed by application, which causes the tcp_listen_pcbs.listen_pcbs to become NULL.
* 3. When SYNC_RECV state timeout (20s by default), tcp_pcb_purge() is called in tcp_slowtmr(), it asserts
* the system.
* This is a normal scenario, should NOT assert the system. So just remove it.
*
*/
if (tcp_listen_pcbs.listen_pcbs) {
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"));

View File

@@ -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. */

View File

@@ -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);

View File

@@ -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,

View File

@@ -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)

View File

@@ -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)

View File

@@ -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";

View File

@@ -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 {

View File

@@ -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
};

View File

@@ -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 {

View File

@@ -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):
"""

View File

@@ -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):