forked from espressif/esp-idf
Compare commits
222 Commits
v3.3-beta3
...
v3.3
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6ccb4cf5b7 | ||
|
|
f8e24754d1 | ||
|
|
86975b7e8f | ||
|
|
c2bb7d7cd6 | ||
|
|
cc3ba7186f | ||
|
|
7d28c02fd5 | ||
|
|
3becdd7850 | ||
|
|
ef11260310 | ||
|
|
7b39d5e5c5 | ||
|
|
d5b0b36758 | ||
|
|
0a609be968 | ||
|
|
148a269808 | ||
|
|
5b11428f00 | ||
|
|
4cd7fd89f5 | ||
|
|
ceb56a7a72 | ||
|
|
ebfa74310c | ||
|
|
b482ba117d | ||
|
|
07735424a2 | ||
|
|
f2f5a237c0 | ||
|
|
3be1c70d46 | ||
|
|
beb34b5390 | ||
|
|
3991084777 | ||
|
|
088439c634 | ||
|
|
dbd05d8986 | ||
|
|
7c5dd19c83 | ||
|
|
a6fb161309 | ||
|
|
0929dbbc9b | ||
|
|
4c27f9ced8 | ||
|
|
b800dfe6f1 | ||
|
|
caa1ef0cb6 | ||
|
|
97e7c14f4e | ||
|
|
c157c696e7 | ||
|
|
d900cb5a35 | ||
|
|
4cb729283d | ||
|
|
6a3e160aaf | ||
|
|
70ecb7ec94 | ||
|
|
21e2c417e8 | ||
|
|
3ca82d5923 | ||
|
|
7af04d857f | ||
|
|
e070e1886f | ||
|
|
6da2bec1e8 | ||
|
|
73345bae44 | ||
|
|
2d26163019 | ||
|
|
ff2624f09c | ||
|
|
11d141e87d | ||
|
|
91f29bef17 | ||
|
|
8ed62223cd | ||
|
|
de7a50dca0 | ||
|
|
a9eac4a124 | ||
|
|
3e27184c38 | ||
|
|
5758b739f1 | ||
|
|
2d7124e319 | ||
|
|
232408981d | ||
|
|
9821e533db | ||
|
|
6d8990f39b | ||
|
|
83a9a4dc70 | ||
|
|
630ffde6bb | ||
|
|
6af30250a8 | ||
|
|
30d2f13358 | ||
|
|
d7569b5862 | ||
|
|
db9979701a | ||
|
|
dca5ed2263 | ||
|
|
0ef3af367d | ||
|
|
9afe47425b | ||
|
|
f5d33fa889 | ||
|
|
29cef5a9cc | ||
|
|
40171d7307 | ||
|
|
e64bae3a0c | ||
|
|
a71fad46d4 | ||
|
|
2c9acce0ff | ||
|
|
8e58b31a69 | ||
|
|
bf152907a4 | ||
|
|
47ca5d53df | ||
|
|
c1fe8ceb83 | ||
|
|
db38c37cf7 | ||
|
|
71ce87c79e | ||
|
|
611c300a92 | ||
|
|
b7eb82d191 | ||
|
|
933674301f | ||
|
|
3b2e231ae3 | ||
|
|
881cd4310c | ||
|
|
13e6e9f592 | ||
|
|
cfc73a6de7 | ||
|
|
62e359a4e1 | ||
|
|
ab4024c84e | ||
|
|
f4ee20165e | ||
|
|
e443467f37 | ||
|
|
a6f990ffb9 | ||
|
|
43561a40d2 | ||
|
|
55f5c2e08d | ||
|
|
e4418f4f92 | ||
|
|
968728bf95 | ||
|
|
2073a6e738 | ||
|
|
95b72a96f8 | ||
|
|
2617dee69f | ||
|
|
f94db7bba7 | ||
|
|
f7f02c9a43 | ||
|
|
52f0b86965 | ||
|
|
12bbe0f39b | ||
|
|
536b2d8a65 | ||
|
|
f5ab51c9b7 | ||
|
|
8a5c712730 | ||
|
|
2287c28b41 | ||
|
|
129ac11c31 | ||
|
|
166918e802 | ||
|
|
4b028cca86 | ||
|
|
a9d266b921 | ||
|
|
dc9c2f3b60 | ||
|
|
ae1389afd9 | ||
|
|
92f1d7ae39 | ||
|
|
f73c972280 | ||
|
|
378a5b159a | ||
|
|
2ef218059b | ||
|
|
28a8349fb8 | ||
|
|
4acc941c3d | ||
|
|
4ae01f0c9d | ||
|
|
2c4e0cf878 | ||
|
|
4b739249c2 | ||
|
|
b3f4755ac2 | ||
|
|
9185c370dc | ||
|
|
b62182d75a | ||
|
|
890a341db4 | ||
|
|
04815c2d27 | ||
|
|
0af6d8ffe3 | ||
|
|
43b2563f5a | ||
|
|
16586524e9 | ||
|
|
f60acb2196 | ||
|
|
1d2a9efa55 | ||
|
|
5ab4a9da51 | ||
|
|
b63be2e08e | ||
|
|
6cf4e14671 | ||
|
|
39f7d1ad0b | ||
|
|
d3a29c2d08 | ||
|
|
31a8a488f0 | ||
|
|
b908d4325b | ||
|
|
54c148d289 | ||
|
|
60b937b5ca | ||
|
|
b816edac3c | ||
|
|
2ee0f98d05 | ||
|
|
f83296e448 | ||
|
|
09515bdfde | ||
|
|
081b623a34 | ||
|
|
871e95087e | ||
|
|
a3b3f9ae2d | ||
|
|
fb6f343ce5 | ||
|
|
e1069de9aa | ||
|
|
a219e9f819 | ||
|
|
8f8113f5cd | ||
|
|
cf3647fe40 | ||
|
|
06651c0951 | ||
|
|
d54fadef41 | ||
|
|
3b4353da5d | ||
|
|
261c5bf6a8 | ||
|
|
6132d7bce3 | ||
|
|
1db04ae574 | ||
|
|
6d4adb46f3 | ||
|
|
e681f449bc | ||
|
|
f3725a7821 | ||
|
|
34f6773471 | ||
|
|
d0e7fd4369 | ||
|
|
13a3edee8a | ||
|
|
56866567ae | ||
|
|
bc83d470e3 | ||
|
|
a298d32d65 | ||
|
|
172a216edb | ||
|
|
d5923f0e2e | ||
|
|
cd9249970f | ||
|
|
676a27c7cf | ||
|
|
33121c3311 | ||
|
|
38509b2b95 | ||
|
|
e821c22a8c | ||
|
|
8c363321db | ||
|
|
ce279988c3 | ||
|
|
7200b8bf77 | ||
|
|
7e5cd986a9 | ||
|
|
fa1e983028 | ||
|
|
71e344da20 | ||
|
|
620bba3a66 | ||
|
|
8f7f32c0a5 | ||
|
|
3cbbc3bbac | ||
|
|
5c42c831f5 | ||
|
|
8c57aa0242 | ||
|
|
0d5609ba92 | ||
|
|
e209307297 | ||
|
|
4ac347b295 | ||
|
|
fc3aa765cf | ||
|
|
31c94b25c5 | ||
|
|
5b8d1c9da3 | ||
|
|
7f784c84d2 | ||
|
|
532c8847c7 | ||
|
|
6dc31101ce | ||
|
|
7d9330d1af | ||
|
|
618aa6a3a4 | ||
|
|
762bf705bb | ||
|
|
5988e77a3a | ||
|
|
26e7f3fde6 | ||
|
|
ba2ff1876f | ||
|
|
0757e019f4 | ||
|
|
c68390f922 | ||
|
|
8e3a1876cb | ||
|
|
cc8652d8d2 | ||
|
|
3cd8538f53 | ||
|
|
0033b31442 | ||
|
|
56afb3bd1c | ||
|
|
e622ee0f41 | ||
|
|
2d50291b05 | ||
|
|
c9b1e1df60 | ||
|
|
9a72c11e6e | ||
|
|
39dbe7daa8 | ||
|
|
554a28e8a1 | ||
|
|
7a2885885c | ||
|
|
d154723a84 | ||
|
|
16918e400e | ||
|
|
510f726935 | ||
|
|
3295ed0995 | ||
|
|
924895f832 | ||
|
|
403268a13a | ||
|
|
d6badc53eb | ||
|
|
2f72645320 | ||
|
|
2f2f0fbcbd | ||
|
|
ec4c75b692 | ||
|
|
90ddbaac16 |
1
.flake8
1
.flake8
@@ -156,6 +156,7 @@ exclude =
|
||||
components/protocomm/python/sec0_pb2.py,
|
||||
components/protocomm/python/sec1_pb2.py,
|
||||
components/protocomm/python/session_pb2.py,
|
||||
components/wifi_provisioning/python/wifi_scan_pb2.py,
|
||||
components/wifi_provisioning/python/wifi_config_pb2.py,
|
||||
components/wifi_provisioning/python/wifi_constants_pb2.py,
|
||||
examples/provisioning/custom_config/components/custom_provisioning/python/custom_config_pb2.py,
|
||||
|
||||
1016
.gitlab-ci.yml
1016
.gitlab-ci.yml
File diff suppressed because it is too large
Load Diff
21
.readthedocs.yml
Normal file
21
.readthedocs.yml
Normal file
@@ -0,0 +1,21 @@
|
||||
# .readthedocs.yml
|
||||
# Read the Docs configuration file
|
||||
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
|
||||
|
||||
# Required
|
||||
version: 2
|
||||
|
||||
# Optionally build your docs in additional formats such as PDF and ePub
|
||||
formats:
|
||||
- pdf
|
||||
|
||||
# Optionally set the version of Python and requirements required to build your docs
|
||||
python:
|
||||
version: 2.7
|
||||
install:
|
||||
- requirements: docs/requirements.txt
|
||||
|
||||
# We need to list all the submodules included in documentation build by Doxygen
|
||||
submodules:
|
||||
include:
|
||||
- components/mqtt/esp-mqtt
|
||||
@@ -8,9 +8,16 @@ PARTTOOL_PY := $(PYTHON) $(IDF_PATH)/components/partition_table/parttool.py
|
||||
# Generate blank partition file
|
||||
BLANK_OTA_DATA_FILE = $(BUILD_DIR_BASE)/ota_data_initial.bin
|
||||
|
||||
$(BLANK_OTA_DATA_FILE): partition_table_get_info $(PARTITION_TABLE_BIN) | check_python_dependencies
|
||||
# Copy PARTITION_TABLE_CSV_PATH definition here from $IDF_PATH/components/partition_table/Makefile.projbuild
|
||||
# to avoid undefined variables warning for PARTITION_TABLE_CSV_PATH
|
||||
ifndef PARTITION_TABLE_CSV_PATH
|
||||
PARTITION_TABLE_ROOT := $(call dequote,$(if $(CONFIG_PARTITION_TABLE_CUSTOM),$(PROJECT_PATH),$(IDF_PATH)/components/partition_table))
|
||||
PARTITION_TABLE_CSV_PATH := $(call dequote,$(abspath $(PARTITION_TABLE_ROOT)/$(call dequote,$(CONFIG_PARTITION_TABLE_FILENAME))))
|
||||
endif
|
||||
|
||||
$(BLANK_OTA_DATA_FILE): partition_table_get_info $(PARTITION_TABLE_CSV_PATH) | check_python_dependencies
|
||||
$(shell if [ "$(OTA_DATA_OFFSET)" != "" ] && [ "$(OTA_DATA_SIZE)" != "" ]; then \
|
||||
$(PARTTOOL_PY) --partition-type data --partition-subtype ota --partition-table-file $(PARTITION_TABLE_BIN) \
|
||||
$(PARTTOOL_PY) --partition-type data --partition-subtype ota --partition-table-file $(PARTITION_TABLE_CSV_PATH) \
|
||||
-q generate_blank_partition_file --output $(BLANK_OTA_DATA_FILE); \
|
||||
fi; )
|
||||
$(eval BLANK_OTA_DATA_FILE = $(shell if [ "$(OTA_DATA_OFFSET)" != "" ] && [ "$(OTA_DATA_SIZE)" != "" ]; then \
|
||||
@@ -22,11 +29,11 @@ blank_ota_data: $(BLANK_OTA_DATA_FILE)
|
||||
# expand to empty values.
|
||||
ESPTOOL_ALL_FLASH_ARGS += $(OTA_DATA_OFFSET) $(BLANK_OTA_DATA_FILE)
|
||||
|
||||
erase_otadata: $(PARTITION_TABLE_BIN) partition_table_get_info | check_python_dependencies
|
||||
$(OTATOOL_PY) --partition-table-file $(PARTITION_TABLE_BIN) erase_otadata
|
||||
erase_otadata: $(PARTITION_TABLE_CSV_PATH) partition_table_get_info | check_python_dependencies
|
||||
$(OTATOOL_PY) --partition-table-file $(PARTITION_TABLE_CSV_PATH) erase_otadata
|
||||
|
||||
read_otadata: $(PARTITION_TABLE_BIN) partition_table_get_info | check_python_dependencies
|
||||
$(OTATOOL_PY) --partition-table-file $(PARTITION_TABLE_BIN) read_otadata
|
||||
read_otadata: $(PARTITION_TABLE_CSV_PATH) partition_table_get_info | check_python_dependencies
|
||||
$(OTATOOL_PY) --partition-table-file $(PARTITION_TABLE_CSV_PATH) read_otadata
|
||||
|
||||
erase_ota: erase_otadata
|
||||
@echo "WARNING: erase_ota is deprecated. Use erase_otadata instead."
|
||||
|
||||
@@ -295,7 +295,7 @@ static void test_flow1(void)
|
||||
// 3 Stage: run OTA0 -> check it -> copy OTA0 to OTA1 -> reboot --//--
|
||||
// 4 Stage: run OTA1 -> check it -> copy OTA1 to OTA0 -> reboot --//--
|
||||
// 5 Stage: run OTA0 -> check it -> erase OTA_DATA for next tests -> PASS
|
||||
TEST_CASE_MULTIPLE_STAGES("Switching between factory, OTA0, OTA1, OTA0", "[app_update][reset=DEEPSLEEP_RESET, DEEPSLEEP_RESET, DEEPSLEEP_RESET, DEEPSLEEP_RESET]", start_test, test_flow1, test_flow1, test_flow1, test_flow1);
|
||||
TEST_CASE_MULTIPLE_STAGES("Switching between factory, OTA0, OTA1, OTA0", "[app_update][timeout=90][reset=DEEPSLEEP_RESET, DEEPSLEEP_RESET, DEEPSLEEP_RESET, DEEPSLEEP_RESET]", start_test, test_flow1, test_flow1, test_flow1, test_flow1);
|
||||
|
||||
static void test_flow2(void)
|
||||
{
|
||||
@@ -332,7 +332,7 @@ static void test_flow2(void)
|
||||
// 2 Stage: run factory -> check it -> copy factory to OTA0 -> reboot --//--
|
||||
// 3 Stage: run OTA0 -> check it -> corrupt ota data -> reboot --//--
|
||||
// 4 Stage: run factory -> check it -> erase OTA_DATA for next tests -> PASS
|
||||
TEST_CASE_MULTIPLE_STAGES("Switching between factory, OTA0, corrupt ota_sec1, factory", "[app_update][reset=DEEPSLEEP_RESET, DEEPSLEEP_RESET, DEEPSLEEP_RESET]", start_test, test_flow2, test_flow2, test_flow2);
|
||||
TEST_CASE_MULTIPLE_STAGES("Switching between factory, OTA0, corrupt ota_sec1, factory", "[app_update][timeout=90][reset=DEEPSLEEP_RESET, DEEPSLEEP_RESET, DEEPSLEEP_RESET]", start_test, test_flow2, test_flow2, test_flow2);
|
||||
|
||||
static void test_flow3(void)
|
||||
{
|
||||
@@ -376,7 +376,7 @@ static void test_flow3(void)
|
||||
// 3 Stage: run OTA0 -> check it -> copy OTA0 to OTA1 -> reboot --//--
|
||||
// 3 Stage: run OTA1 -> check it -> corrupt ota sector2 -> reboot --//--
|
||||
// 4 Stage: run OTA0 -> check it -> erase OTA_DATA for next tests -> PASS
|
||||
TEST_CASE_MULTIPLE_STAGES("Switching between factory, OTA0, OTA1, currupt ota_sec2, OTA0", "[app_update][reset=DEEPSLEEP_RESET, DEEPSLEEP_RESET, DEEPSLEEP_RESET, DEEPSLEEP_RESET]", start_test, test_flow3, test_flow3, test_flow3, test_flow3);
|
||||
TEST_CASE_MULTIPLE_STAGES("Switching between factory, OTA0, OTA1, currupt ota_sec2, OTA0", "[app_update][timeout=90][reset=DEEPSLEEP_RESET, DEEPSLEEP_RESET, DEEPSLEEP_RESET, DEEPSLEEP_RESET]", start_test, test_flow3, test_flow3, test_flow3, test_flow3);
|
||||
|
||||
#ifdef CONFIG_BOOTLOADER_FACTORY_RESET
|
||||
#define STORAGE_NAMESPACE "update_ota"
|
||||
@@ -443,7 +443,7 @@ static void test_flow4(void)
|
||||
// 2 Stage: run factory -> check it -> copy factory to OTA0 -> reboot --//--
|
||||
// 3 Stage: run OTA0 -> check it -> set_pin_factory_reset -> reboot --//--
|
||||
// 4 Stage: run factory -> check it -> erase OTA_DATA for next tests -> PASS
|
||||
TEST_CASE_MULTIPLE_STAGES("Switching between factory, OTA0, sets pin_factory_reset, factory", "[app_update][reset=DEEPSLEEP_RESET, DEEPSLEEP_RESET, DEEPSLEEP_RESET]", start_test, test_flow4, test_flow4, test_flow4);
|
||||
TEST_CASE_MULTIPLE_STAGES("Switching between factory, OTA0, sets pin_factory_reset, factory", "[app_update][timeout=90][reset=DEEPSLEEP_RESET, DEEPSLEEP_RESET, DEEPSLEEP_RESET]", start_test, test_flow4, test_flow4, test_flow4);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_BOOTLOADER_APP_TEST
|
||||
@@ -486,7 +486,7 @@ static void test_flow5(void)
|
||||
// 2 Stage: run factory -> check it -> copy factory to Test and set pin_test_app -> reboot --//--
|
||||
// 3 Stage: run test -> check it -> reset pin_test_app -> reboot --//--
|
||||
// 4 Stage: run factory -> check it -> erase OTA_DATA for next tests -> PASS
|
||||
TEST_CASE_MULTIPLE_STAGES("Switching between factory, test, factory", "[app_update][reset=DEEPSLEEP_RESET, DEEPSLEEP_RESET, DEEPSLEEP_RESET]", start_test, test_flow5, test_flow5, test_flow5);
|
||||
TEST_CASE_MULTIPLE_STAGES("Switching between factory, test, factory", "[app_update][timeout=90][reset=DEEPSLEEP_RESET, DEEPSLEEP_RESET, DEEPSLEEP_RESET]", start_test, test_flow5, test_flow5, test_flow5);
|
||||
#endif
|
||||
|
||||
static const esp_partition_t* app_update(void)
|
||||
@@ -580,7 +580,7 @@ static void test_rollback1_1(void)
|
||||
// 3 Stage: run OTA0 -> check it -> esp_ota_mark_app_valid_cancel_rollback() -> reboot --//--
|
||||
// 4 Stage: run OTA0 -> check it -> esp_ota_mark_app_invalid_rollback_and_reboot() -> reboot
|
||||
// 5 Stage: run factory -> check it -> erase OTA_DATA for next tests -> PASS
|
||||
TEST_CASE_MULTIPLE_STAGES("Test rollback. factory, OTA0, OTA0, rollback -> factory", "[app_update][reset=DEEPSLEEP_RESET, DEEPSLEEP_RESET, DEEPSLEEP_RESET, SW_CPU_RESET]", start_test, test_rollback1, test_rollback1, test_rollback1, test_rollback1_1);
|
||||
TEST_CASE_MULTIPLE_STAGES("Test rollback. factory, OTA0, OTA0, rollback -> factory", "[app_update][timeout=90][reset=DEEPSLEEP_RESET, DEEPSLEEP_RESET, DEEPSLEEP_RESET, SW_CPU_RESET]", start_test, test_rollback1, test_rollback1, test_rollback1, test_rollback1_1);
|
||||
|
||||
static void test_rollback2(void)
|
||||
{
|
||||
@@ -678,7 +678,7 @@ static void test_rollback2_1(void)
|
||||
// 3 Stage: run OTA0 -> check it -> esp_ota_mark_app_valid_cancel_rollback(), copy to next app slot -> reboot --//--
|
||||
// 4 Stage: run OTA1 -> check it -> PENDING_VERIFY/esp_ota_mark_app_invalid_rollback_and_reboot() -> reboot
|
||||
// 5 Stage: run OTA0(rollback) -> check it -> erase OTA_DATA for next tests -> PASS
|
||||
TEST_CASE_MULTIPLE_STAGES("Test rollback. factory, OTA0, OTA1, rollback -> OTA0", "[app_update][reset=DEEPSLEEP_RESET, DEEPSLEEP_RESET, DEEPSLEEP_RESET, SW_CPU_RESET]", start_test, test_rollback2, test_rollback2, test_rollback2, test_rollback2_1);
|
||||
TEST_CASE_MULTIPLE_STAGES("Test rollback. factory, OTA0, OTA1, rollback -> OTA0", "[app_update][timeout=90][reset=DEEPSLEEP_RESET, DEEPSLEEP_RESET, DEEPSLEEP_RESET, SW_CPU_RESET]", start_test, test_rollback2, test_rollback2, test_rollback2, test_rollback2_1);
|
||||
|
||||
static void test_erase_last_app_flow(void)
|
||||
{
|
||||
@@ -729,4 +729,4 @@ static void test_erase_last_app_rollback(void)
|
||||
// 3 Stage: run OTA0 -> check it -> copy factory to OTA1 -> reboot --//--
|
||||
// 4 Stage: run OTA1 -> check it -> erase OTA0 and rollback -> reboot
|
||||
// 5 Stage: run factory -> check it -> erase OTA_DATA for next tests -> PASS
|
||||
TEST_CASE_MULTIPLE_STAGES("Test erase_last_boot_app_partition. factory, OTA1, OTA0, factory", "[app_update][reset=DEEPSLEEP_RESET, DEEPSLEEP_RESET, DEEPSLEEP_RESET, SW_CPU_RESET]", start_test, test_erase_last_app_flow, test_erase_last_app_flow, test_erase_last_app_flow, test_erase_last_app_rollback);
|
||||
TEST_CASE_MULTIPLE_STAGES("Test erase_last_boot_app_partition. factory, OTA1, OTA0, factory", "[app_update][timeout=90][reset=DEEPSLEEP_RESET, DEEPSLEEP_RESET, DEEPSLEEP_RESET, SW_CPU_RESET]", start_test, test_erase_last_app_flow, test_erase_last_app_flow, test_erase_last_app_flow, test_erase_last_app_rollback);
|
||||
|
||||
@@ -504,16 +504,5 @@ menu "Security features"
|
||||
|
||||
Only set this option in testing environments.
|
||||
|
||||
config SECURE_BOOT_TEST_MODE
|
||||
bool "Secure boot test mode: don't permanently set any eFuses"
|
||||
depends on SECURE_BOOT_INSECURE
|
||||
default N
|
||||
help
|
||||
If this option is set, all permanent secure boot changes (via eFuse) are disabled.
|
||||
|
||||
Log output will state changes which would be applied, but they will not be.
|
||||
|
||||
This option is for testing purposes only - it completely disables secure boot protection.
|
||||
|
||||
endmenu # Potentially Insecure
|
||||
endmenu # Security features
|
||||
|
||||
@@ -49,10 +49,11 @@ if((NOT CONFIG_SECURE_BOOT_ENABLED) OR
|
||||
CONFIG_SECURE_BOOTLOADER_ONE_TIME_FLASH)
|
||||
externalproject_add(bootloader
|
||||
# TODO: support overriding the bootloader in COMPONENT_PATHS
|
||||
SOURCE_DIR "${IDF_PATH}/components/bootloader/subproject"
|
||||
SOURCE_DIR "${CMAKE_CURRENT_LIST_DIR}/subproject"
|
||||
BINARY_DIR "${bootloader_build_dir}"
|
||||
CMAKE_ARGS -DSDKCONFIG=${SDKCONFIG} -DIDF_PATH=${IDF_PATH}
|
||||
-DSECURE_BOOT_SIGNING_KEY=${secure_boot_signing_key}
|
||||
-DEXTRA_COMPONENT_DIRS=${CMAKE_CURRENT_LIST_DIR}
|
||||
INSTALL_COMMAND ""
|
||||
BUILD_ALWAYS 1 # no easy way around this...
|
||||
BUILD_BYPRODUCTS ${bootloader_binary_files}
|
||||
|
||||
@@ -27,9 +27,9 @@ target_linker_script(bootloader.elf
|
||||
# as cmake won't attach linker args to a header-only library, attach
|
||||
# linker args directly to the bootloader.elf
|
||||
set(ESP32_BOOTLOADER_LINKER_SCRIPTS
|
||||
"../../esp32/ld/esp32.rom.ld"
|
||||
"../../esp32/ld/esp32.rom.spiram_incompatible_fns.ld"
|
||||
"../../esp32/ld/esp32.peripherals.ld")
|
||||
"${IDF_PATH}/components/esp32/ld/esp32.rom.ld"
|
||||
"${IDF_PATH}/components/esp32/ld/esp32.rom.spiram_incompatible_fns.ld"
|
||||
"${IDF_PATH}/components/esp32/ld/esp32.peripherals.ld")
|
||||
|
||||
target_linker_script(bootloader.elf ${ESP32_BOOTLOADER_LINKER_SCRIPTS})
|
||||
|
||||
|
||||
@@ -136,3 +136,16 @@ int bootloader_common_select_otadata(const esp_ota_select_entry_t *two_otadata,
|
||||
* - ESP_FAIL: mapping is fail.
|
||||
*/
|
||||
esp_err_t bootloader_common_get_partition_description(const esp_partition_pos_t *partition, esp_app_desc_t *app_desc);
|
||||
|
||||
/**
|
||||
* @brief Configure VDDSDIO, call this API to rise VDDSDIO to 1.9V when VDDSDIO regulator is enabled as 1.8V mode.
|
||||
*/
|
||||
void bootloader_common_vddsdio_configure();
|
||||
|
||||
/**
|
||||
* @brief Set the flash CS setup and hold time.
|
||||
*
|
||||
* CS setup time is recomemded to be 1.5T, and CS hold time is recommended to be 2.5T.
|
||||
* cs_setup = 1, cs_setup_time = 0; cs_hold = 1, cs_hold_time = 1
|
||||
*/
|
||||
void bootloader_common_set_flash_cs_timing();
|
||||
|
||||
@@ -46,6 +46,25 @@ static inline bool esp_secure_boot_enabled(void) {
|
||||
return REG_READ(EFUSE_BLK0_RDATA6_REG) & EFUSE_RD_ABS_DONE_0;
|
||||
}
|
||||
|
||||
/** @brief Generate secure digest from bootloader image
|
||||
*
|
||||
* @important This function is intended to be called from bootloader code only.
|
||||
*
|
||||
* If secure boot is not yet enabled for bootloader, this will:
|
||||
* 1) generate the secure boot key and burn it on EFUSE
|
||||
* (without enabling R/W protection)
|
||||
* 2) generate the digest from bootloader and save it
|
||||
* to flash address 0x0
|
||||
*
|
||||
* If first boot gets interrupted after calling this function
|
||||
* but before esp_secure_boot_permanently_enable() is called, then
|
||||
* the key burned on EFUSE will not be regenerated, unless manually
|
||||
* done using espefuse.py tool
|
||||
*
|
||||
* @return ESP_OK if secure boot digest is generated
|
||||
* successfully or found to be already present
|
||||
*/
|
||||
esp_err_t esp_secure_boot_generate_digest(void);
|
||||
|
||||
/** @brief Enable secure boot if it is not already enabled.
|
||||
*
|
||||
@@ -54,9 +73,13 @@ static inline bool esp_secure_boot_enabled(void) {
|
||||
*
|
||||
* @important This function is intended to be called from bootloader code only.
|
||||
*
|
||||
* @important This will enable r/w protection of secure boot key on EFUSE,
|
||||
* therefore it is to be ensured that esp_secure_boot_generate_digest()
|
||||
* is called before this
|
||||
*
|
||||
* If secure boot is not yet enabled for bootloader, this will
|
||||
* generate the secure boot digest and enable secure boot by blowing
|
||||
* the EFUSE_RD_ABS_DONE_0 efuse.
|
||||
* 1) enable R/W protection of secure boot key on EFUSE
|
||||
* 2) enable secure boot by blowing the EFUSE_RD_ABS_DONE_0 efuse.
|
||||
*
|
||||
* This function does not verify secure boot of the bootloader (the
|
||||
* ROM bootloader does this.)
|
||||
@@ -64,7 +87,6 @@ static inline bool esp_secure_boot_enabled(void) {
|
||||
* Will fail if efuses have been part-burned in a way that indicates
|
||||
* secure boot should not or could not be correctly enabled.
|
||||
*
|
||||
*
|
||||
* @return ESP_ERR_INVALID_STATE if efuse state doesn't allow
|
||||
* secure boot to be enabled cleanly. ESP_OK if secure boot
|
||||
* is enabled on this chip from now on.
|
||||
|
||||
@@ -30,6 +30,13 @@
|
||||
bootloader_support components only.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Get number of free pages
|
||||
*
|
||||
* @return Number of free pages
|
||||
*/
|
||||
uint32_t bootloader_mmap_get_free_pages();
|
||||
|
||||
/**
|
||||
* @brief Map a region of flash to data memory
|
||||
*
|
||||
|
||||
@@ -27,6 +27,9 @@
|
||||
#include "bootloader_flash.h"
|
||||
#include "bootloader_common.h"
|
||||
#include "soc/gpio_periph.h"
|
||||
#include "soc/efuse_reg.h"
|
||||
#include "soc/rtc.h"
|
||||
#include "soc/spi_reg.h"
|
||||
#include "esp_image_format.h"
|
||||
#include "bootloader_sha.h"
|
||||
#include "sys/param.h"
|
||||
@@ -257,3 +260,28 @@ esp_err_t bootloader_common_get_partition_description(const esp_partition_pos_t
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
void bootloader_common_vddsdio_configure()
|
||||
{
|
||||
#if CONFIG_BOOTLOADER_VDDSDIO_BOOST_1_9V
|
||||
rtc_vddsdio_config_t cfg = rtc_vddsdio_get_config();
|
||||
if (cfg.enable == 1 && cfg.tieh == RTC_VDDSDIO_TIEH_1_8V) { // VDDSDIO regulator is enabled @ 1.8V
|
||||
cfg.drefh = 3;
|
||||
cfg.drefm = 3;
|
||||
cfg.drefl = 3;
|
||||
cfg.force = 1;
|
||||
rtc_vddsdio_set_config(cfg);
|
||||
ets_delay_us(10); // wait for regulator to become stable
|
||||
}
|
||||
#endif // CONFIG_BOOTLOADER_VDDSDIO_BOOST
|
||||
}
|
||||
|
||||
void bootloader_common_set_flash_cs_timing()
|
||||
{
|
||||
SET_PERI_REG_MASK(SPI_USER_REG(0), SPI_CS_HOLD_M | SPI_CS_SETUP_M);
|
||||
SET_PERI_REG_BITS(SPI_CTRL2_REG(0), SPI_HOLD_TIME_V, 1, SPI_HOLD_TIME_S);
|
||||
SET_PERI_REG_BITS(SPI_CTRL2_REG(0), SPI_SETUP_TIME_V, 0, SPI_SETUP_TIME_S);
|
||||
SET_PERI_REG_MASK(SPI_USER_REG(1), SPI_CS_HOLD_M | SPI_CS_SETUP_M);
|
||||
SET_PERI_REG_BITS(SPI_CTRL2_REG(1), SPI_HOLD_TIME_V, 1, SPI_HOLD_TIME_S);
|
||||
SET_PERI_REG_BITS(SPI_CTRL2_REG(1), SPI_SETUP_TIME_V, 0, SPI_SETUP_TIME_S);
|
||||
}
|
||||
|
||||
@@ -25,6 +25,11 @@ static const char *TAG = "bootloader_mmap";
|
||||
|
||||
static spi_flash_mmap_handle_t map;
|
||||
|
||||
uint32_t bootloader_mmap_get_free_pages()
|
||||
{
|
||||
return spi_flash_mmap_get_free_pages(SPI_FLASH_MMAP_DATA);
|
||||
}
|
||||
|
||||
const void *bootloader_mmap(uint32_t src_addr, uint32_t size)
|
||||
{
|
||||
if (map) {
|
||||
@@ -91,12 +96,22 @@ static const char *TAG = "bootloader_flash";
|
||||
*/
|
||||
#define MMU_BLOCK0_VADDR 0x3f400000
|
||||
#define MMU_BLOCK50_VADDR 0x3f720000
|
||||
#define MMU_FREE_PAGES ((MMU_BLOCK50_VADDR - MMU_BLOCK0_VADDR) / FLASH_BLOCK_SIZE)
|
||||
|
||||
static bool mapped;
|
||||
|
||||
// Current bootloader mapping (ab)used for bootloader_read()
|
||||
static uint32_t current_read_mapping = UINT32_MAX;
|
||||
|
||||
uint32_t bootloader_mmap_get_free_pages()
|
||||
{
|
||||
/**
|
||||
* Allow mapping up to 50 of the 51 available MMU blocks (last one used for reads)
|
||||
* Since, bootloader_mmap function below assumes it to be 0x320000 (50 pages), we can safely do this.
|
||||
*/
|
||||
return MMU_FREE_PAGES;
|
||||
}
|
||||
|
||||
const void *bootloader_mmap(uint32_t src_addr, uint32_t size)
|
||||
{
|
||||
if (mapped) {
|
||||
|
||||
@@ -33,12 +33,10 @@
|
||||
#include "soc/cpu.h"
|
||||
#include "soc/rtc.h"
|
||||
#include "soc/dport_reg.h"
|
||||
#include "soc/io_mux_reg.h"
|
||||
#include "soc/efuse_reg.h"
|
||||
#include "soc/rtc_cntl_reg.h"
|
||||
#include "soc/timer_group_reg.h"
|
||||
#include "soc/gpio_reg.h"
|
||||
#include "soc/gpio_sig_map.h"
|
||||
#include "soc/gpio_periph.h"
|
||||
#include "soc/rtc_wdt.h"
|
||||
|
||||
#include "sdkconfig.h"
|
||||
@@ -50,6 +48,7 @@
|
||||
#include "bootloader_random.h"
|
||||
#include "bootloader_config.h"
|
||||
#include "bootloader_clock.h"
|
||||
#include "bootloader_common.h"
|
||||
|
||||
#include "flash_qio_mode.h"
|
||||
|
||||
@@ -63,7 +62,6 @@ static const char* TAG = "boot";
|
||||
static esp_err_t bootloader_main();
|
||||
static void print_flash_info(const esp_image_header_t* pfhdr);
|
||||
static void update_flash_config(const esp_image_header_t* pfhdr);
|
||||
static void vddsdio_configure();
|
||||
static void flash_gpio_configure(const esp_image_header_t* pfhdr);
|
||||
static void uart_console_configure(void);
|
||||
static void wdt_reset_check(void);
|
||||
@@ -119,7 +117,7 @@ esp_err_t bootloader_init()
|
||||
|
||||
static esp_err_t bootloader_main()
|
||||
{
|
||||
vddsdio_configure();
|
||||
bootloader_common_vddsdio_configure();
|
||||
/* Read and keep flash ID, for further use. */
|
||||
g_rom_flashchip.device_id = bootloader_read_flash_id();
|
||||
esp_image_header_t fhdr;
|
||||
@@ -287,21 +285,6 @@ static void print_flash_info(const esp_image_header_t* phdr)
|
||||
#endif
|
||||
}
|
||||
|
||||
static void vddsdio_configure()
|
||||
{
|
||||
#if CONFIG_BOOTLOADER_VDDSDIO_BOOST_1_9V
|
||||
rtc_vddsdio_config_t cfg = rtc_vddsdio_get_config();
|
||||
if (cfg.enable == 1 && cfg.tieh == RTC_VDDSDIO_TIEH_1_8V) { // VDDSDIO regulator is enabled @ 1.8V
|
||||
cfg.drefh = 3;
|
||||
cfg.drefm = 3;
|
||||
cfg.drefl = 3;
|
||||
cfg.force = 1;
|
||||
rtc_vddsdio_set_config(cfg);
|
||||
ets_delay_us(10); // wait for regulator to become stable
|
||||
}
|
||||
#endif // CONFIG_BOOTLOADER_VDDSDIO_BOOST
|
||||
}
|
||||
|
||||
#define FLASH_CLK_IO 6
|
||||
#define FLASH_CS_IO 11
|
||||
#define FLASH_SPIQ_IO 7
|
||||
@@ -322,10 +305,11 @@ static void IRAM_ATTR flash_gpio_configure(const esp_image_header_t* pfhdr)
|
||||
int drv = 2;
|
||||
switch (pfhdr->spi_mode) {
|
||||
case ESP_IMAGE_SPI_MODE_QIO:
|
||||
spi_cache_dummy = SPI0_R_DIO_DUMMY_CYCLELEN;
|
||||
spi_cache_dummy = SPI0_R_QIO_DUMMY_CYCLELEN;
|
||||
break;
|
||||
case ESP_IMAGE_SPI_MODE_DIO:
|
||||
spi_cache_dummy = SPI0_R_DIO_DUMMY_CYCLELEN; //qio 3
|
||||
spi_cache_dummy = SPI0_R_DIO_DUMMY_CYCLELEN;
|
||||
SET_PERI_REG_BITS(SPI_USER1_REG(0), SPI_USR_ADDR_BITLEN_V, SPI0_R_DIO_ADDR_BITSLEN, SPI_USR_ADDR_BITLEN_S);
|
||||
break;
|
||||
case ESP_IMAGE_SPI_MODE_QOUT:
|
||||
case ESP_IMAGE_SPI_MODE_DOUT:
|
||||
@@ -350,6 +334,10 @@ static void IRAM_ATTR flash_gpio_configure(const esp_image_header_t* pfhdr)
|
||||
SET_PERI_REG_BITS(SPI_USER1_REG(0), SPI_USR_DUMMY_CYCLELEN_V, spi_cache_dummy + FLASH_IO_MATRIX_DUMMY_40M,
|
||||
SPI_USR_DUMMY_CYCLELEN_S); //DUMMY
|
||||
break;
|
||||
case ESP_IMAGE_SPI_SPEED_26M:
|
||||
case ESP_IMAGE_SPI_SPEED_20M:
|
||||
SET_PERI_REG_BITS(SPI_USER1_REG(0), SPI_USR_DUMMY_CYCLELEN_V, spi_cache_dummy, SPI_USR_DUMMY_CYCLELEN_S); //DUMMY
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -409,6 +397,9 @@ static void IRAM_ATTR flash_gpio_configure(const esp_image_header_t* pfhdr)
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
// improve the flash cs timing.
|
||||
bootloader_common_set_flash_cs_timing();
|
||||
}
|
||||
|
||||
static void uart_console_configure(void)
|
||||
@@ -442,10 +433,18 @@ static void uart_console_configure(void)
|
||||
// (arrays should be optimized away by the compiler)
|
||||
const uint32_t tx_idx_list[3] = { U0TXD_OUT_IDX, U1TXD_OUT_IDX, U2TXD_OUT_IDX };
|
||||
const uint32_t rx_idx_list[3] = { U0RXD_IN_IDX, U1RXD_IN_IDX, U2RXD_IN_IDX };
|
||||
const uint32_t uart_reset[3] = { DPORT_UART_RST, DPORT_UART1_RST, DPORT_UART2_RST };
|
||||
const uint32_t tx_idx = tx_idx_list[uart_num];
|
||||
const uint32_t rx_idx = rx_idx_list[uart_num];
|
||||
|
||||
PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[uart_rx_gpio]);
|
||||
gpio_pad_pullup(uart_rx_gpio);
|
||||
|
||||
gpio_matrix_out(uart_tx_gpio, tx_idx, 0, 0);
|
||||
gpio_matrix_in(uart_rx_gpio, rx_idx, 0);
|
||||
|
||||
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, uart_reset[uart_num]);
|
||||
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, uart_reset[uart_num]);
|
||||
}
|
||||
#endif // CONFIG_CONSOLE_UART_CUSTOM
|
||||
|
||||
|
||||
@@ -478,24 +478,71 @@ void bootloader_utility_load_boot_image(const bootloader_state_t *bs, int start_
|
||||
// Copy loaded segments to RAM, set up caches for mapped segments, and start application.
|
||||
static void load_image(const esp_image_metadata_t* image_data)
|
||||
{
|
||||
/**
|
||||
* Rough steps for a first boot, when encryption and secure boot are both disabled:
|
||||
* 1) Generate secure boot key and write to EFUSE.
|
||||
* 2) Write plaintext digest based on plaintext bootloader
|
||||
* 3) Generate flash encryption key and write to EFUSE.
|
||||
* 4) Encrypt flash in-place including bootloader, then digest,
|
||||
* then app partitions and other encrypted partitions
|
||||
* 5) Burn EFUSE to enable flash encryption (FLASH_CRYPT_CNT)
|
||||
* 6) Burn EFUSE to enable secure boot (ABS_DONE_0)
|
||||
*
|
||||
* If power failure happens during Step 1, probably the next boot will continue from Step 2.
|
||||
* There is some small chance that EFUSEs will be part-way through being written so will be
|
||||
* somehow corrupted here. Thankfully this window of time is very small, but if that's the
|
||||
* case, one has to use the espefuse tool to manually set the remaining bits and enable R/W
|
||||
* protection. Once the relevant EFUSE bits are set and R/W protected, Step 1 will be skipped
|
||||
* successfully on further reboots.
|
||||
*
|
||||
* If power failure happens during Step 2, Step 1 will be skipped and Step 2 repeated:
|
||||
* the digest will get re-written on the next boot.
|
||||
*
|
||||
* If power failure happens during Step 3, it's possible that EFUSE was partially written
|
||||
* with the generated flash encryption key, though the time window for that would again
|
||||
* be very small. On reboot, Step 1 will be skipped and Step 2 repeated, though, Step 3
|
||||
* may fail due to the above mentioned reason, in which case, one has to use the espefuse
|
||||
* tool to manually set the remaining bits and enable R/W protection. Once the relevant EFUSE
|
||||
* bits are set and R/W protected, Step 3 will be skipped successfully on further reboots.
|
||||
*
|
||||
* If power failure happens after start of 4 and before end of 5, the next boot will fail
|
||||
* (bootloader header is encrypted and flash encryption isn't enabled yet, so it looks like
|
||||
* noise to the ROM bootloader). The check in the ROM is pretty basic so if the first byte of
|
||||
* ciphertext happens to be the magic byte E9 then it may try to boot, but it will definitely
|
||||
* crash (no chance that the remaining ciphertext will look like a valid bootloader image).
|
||||
* Only solution is to reflash with all plaintext and the whole process starts again: skips
|
||||
* Step 1, repeats Step 2, skips Step 3, etc.
|
||||
*
|
||||
* If power failure happens after 5 but before 6, the device will reboot with flash
|
||||
* encryption on and will regenerate an encrypted digest in Step 2. This should still
|
||||
* be valid as the input data for the digest is read via flash cache (so will be decrypted)
|
||||
* and the code in secure_boot_generate() tells bootloader_flash_write() to encrypt the data
|
||||
* on write if flash encryption is enabled. Steps 3 - 5 are skipped (encryption already on),
|
||||
* then Step 6 enables secure boot.
|
||||
*/
|
||||
|
||||
#if defined(CONFIG_SECURE_BOOT_ENABLED) || defined(CONFIG_FLASH_ENCRYPTION_ENABLED)
|
||||
esp_err_t err;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SECURE_BOOT_ENABLED
|
||||
/* Generate secure digest from this bootloader to protect future
|
||||
modifications */
|
||||
ESP_LOGI(TAG, "Checking secure boot...");
|
||||
err = esp_secure_boot_permanently_enable();
|
||||
/* Steps 1 & 2 (see above for full description):
|
||||
* 1) Generate secure boot EFUSE key
|
||||
* 2) Compute digest of plaintext bootloader
|
||||
*/
|
||||
err = esp_secure_boot_generate_digest();
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Bootloader digest generation failed (%d). SECURE BOOT IS NOT ENABLED.", err);
|
||||
/* Allow booting to continue, as the failure is probably
|
||||
due to user-configured EFUSEs for testing...
|
||||
*/
|
||||
ESP_LOGE(TAG, "Bootloader digest generation for secure boot failed (%d).", err);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_FLASH_ENCRYPTION_ENABLED
|
||||
/* encrypt flash */
|
||||
/* Steps 3, 4 & 5 (see above for full description):
|
||||
* 3) Generate flash encryption EFUSE key
|
||||
* 4) Encrypt flash contents
|
||||
* 5) Burn EFUSE to enable flash encryption
|
||||
*/
|
||||
ESP_LOGI(TAG, "Checking flash encryption...");
|
||||
bool flash_encryption_enabled = esp_flash_encryption_enabled();
|
||||
err = esp_flash_encrypt_check_and_update();
|
||||
@@ -503,7 +550,24 @@ static void load_image(const esp_image_metadata_t* image_data)
|
||||
ESP_LOGE(TAG, "Flash encryption check failed (%d).", err);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SECURE_BOOT_ENABLED
|
||||
/* Step 6 (see above for full description):
|
||||
* 6) Burn EFUSE to enable secure boot
|
||||
*/
|
||||
ESP_LOGI(TAG, "Checking secure boot...");
|
||||
err = esp_secure_boot_permanently_enable();
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "FAILED TO ENABLE SECURE BOOT (%d).", err);
|
||||
/* Panic here as secure boot is not properly enabled
|
||||
due to one of the reasons in above function
|
||||
*/
|
||||
abort();
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_FLASH_ENCRYPTION_ENABLED
|
||||
if (!flash_encryption_enabled && esp_flash_encryption_enabled()) {
|
||||
/* Flash encryption was just enabled for the first time,
|
||||
so issue a system reset to ensure flash encryption
|
||||
|
||||
@@ -368,24 +368,22 @@ static esp_err_t process_segment(int index, uint32_t flash_addr, esp_image_segme
|
||||
}
|
||||
#endif // BOOTLOADER_BUILD
|
||||
|
||||
#ifndef BOOTLOADER_BUILD
|
||||
uint32_t free_page_count = spi_flash_mmap_get_free_pages(SPI_FLASH_MMAP_DATA);
|
||||
ESP_LOGD(TAG, "free data page_count 0x%08x",free_page_count);
|
||||
uint32_t offset_page = 0;
|
||||
while (data_len >= free_page_count * SPI_FLASH_MMU_PAGE_SIZE) {
|
||||
offset_page = ((data_addr & MMAP_ALIGNED_MASK) != 0)?1:0;
|
||||
err = process_segment_data(load_addr, data_addr, (free_page_count - offset_page) * SPI_FLASH_MMU_PAGE_SIZE, do_load, sha_handle, checksum);
|
||||
uint32_t free_page_count = bootloader_mmap_get_free_pages();
|
||||
ESP_LOGD(TAG, "free data page_count 0x%08x", free_page_count);
|
||||
|
||||
int32_t data_len_remain = data_len;
|
||||
while (data_len_remain > 0) {
|
||||
uint32_t offset_page = ((data_addr & MMAP_ALIGNED_MASK) != 0) ? 1 : 0;
|
||||
/* Data we could map in case we are not aligned to PAGE boundary is one page size lesser. */
|
||||
data_len = MIN(data_len_remain, ((free_page_count - offset_page) * SPI_FLASH_MMU_PAGE_SIZE));
|
||||
err = process_segment_data(load_addr, data_addr, data_len, do_load, sha_handle, checksum);
|
||||
if (err != ESP_OK) {
|
||||
return err;
|
||||
}
|
||||
data_addr += (free_page_count - offset_page) * SPI_FLASH_MMU_PAGE_SIZE;
|
||||
data_len -= (free_page_count - offset_page) * SPI_FLASH_MMU_PAGE_SIZE;
|
||||
}
|
||||
#endif
|
||||
err = process_segment_data(load_addr, data_addr, data_len, do_load, sha_handle, checksum);
|
||||
if (err != ESP_OK) {
|
||||
return err;
|
||||
data_addr += data_len;
|
||||
data_len_remain -= data_len;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
|
||||
err:
|
||||
|
||||
@@ -225,18 +225,18 @@ static esp_err_t encrypt_bootloader()
|
||||
return err;
|
||||
}
|
||||
|
||||
if (esp_secure_boot_enabled()) {
|
||||
/* If secure boot is enabled and bootloader was plaintext, also
|
||||
need to encrypt secure boot IV+digest.
|
||||
*/
|
||||
ESP_LOGD(TAG, "Encrypting secure bootloader IV & digest...");
|
||||
err = esp_flash_encrypt_region(FLASH_OFFS_SECURE_BOOT_IV_DIGEST,
|
||||
FLASH_SECTOR_SIZE);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to encrypt bootloader IV & digest in place: 0x%x", err);
|
||||
return err;
|
||||
}
|
||||
#ifdef CONFIG_SECURE_BOOT_ENABLED
|
||||
/* If secure boot is enabled and bootloader was plaintext, also
|
||||
* need to encrypt secure boot IV+digest.
|
||||
*/
|
||||
ESP_LOGD(TAG, "Encrypting secure bootloader IV & digest...");
|
||||
err = esp_flash_encrypt_region(FLASH_OFFS_SECURE_BOOT_IV_DIGEST,
|
||||
FLASH_SECTOR_SIZE);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to encrypt bootloader IV & digest in place: 0x%x", err);
|
||||
return err;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
ESP_LOGW(TAG, "no valid bootloader was found");
|
||||
|
||||
@@ -36,6 +36,12 @@
|
||||
#include "esp_flash_encrypt.h"
|
||||
#include "esp_efuse.h"
|
||||
|
||||
/* The following API implementations are used only when called
|
||||
* from the bootloader code.
|
||||
*/
|
||||
|
||||
#ifdef BOOTLOADER_BUILD
|
||||
|
||||
static const char* TAG = "secure_boot";
|
||||
|
||||
/**
|
||||
@@ -95,18 +101,15 @@ static bool secure_boot_generate(uint32_t image_len){
|
||||
/* Burn values written to the efuse write registers */
|
||||
static inline void burn_efuses()
|
||||
{
|
||||
#ifdef CONFIG_SECURE_BOOT_TEST_MODE
|
||||
ESP_LOGE(TAG, "SECURE BOOT TEST MODE. Not really burning any efuses! NOT SECURE");
|
||||
#else
|
||||
esp_efuse_burn_new_values();
|
||||
#endif
|
||||
}
|
||||
|
||||
esp_err_t esp_secure_boot_permanently_enable(void) {
|
||||
esp_err_t esp_secure_boot_generate_digest(void)
|
||||
{
|
||||
esp_err_t err;
|
||||
if (esp_secure_boot_enabled())
|
||||
{
|
||||
ESP_LOGI(TAG, "bootloader secure boot is already enabled, continuing..");
|
||||
if (esp_secure_boot_enabled()) {
|
||||
ESP_LOGI(TAG, "bootloader secure boot is already enabled."
|
||||
" No need to generate digest. continuing..");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
@@ -124,6 +127,7 @@ esp_err_t esp_secure_boot_permanently_enable(void) {
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Generate secure boot key and keep in EFUSE */
|
||||
uint32_t dis_reg = REG_READ(EFUSE_BLK0_RDATA0_REG);
|
||||
bool efuse_key_read_protected = dis_reg & EFUSE_RD_DIS_BLK2;
|
||||
bool efuse_key_write_protected = dis_reg & EFUSE_WR_DIS_BLK2;
|
||||
@@ -140,16 +144,11 @@ esp_err_t esp_secure_boot_permanently_enable(void) {
|
||||
ESP_LOGI(TAG, "Generating new secure boot key...");
|
||||
esp_efuse_write_random_key(EFUSE_BLK2_WDATA0_REG);
|
||||
burn_efuses();
|
||||
ESP_LOGI(TAG, "Read & write protecting new key...");
|
||||
REG_WRITE(EFUSE_BLK0_WDATA0_REG, EFUSE_WR_DIS_BLK2 | EFUSE_RD_DIS_BLK2);
|
||||
burn_efuses();
|
||||
efuse_key_read_protected = true;
|
||||
efuse_key_write_protected = true;
|
||||
|
||||
} else {
|
||||
ESP_LOGW(TAG, "Using pre-loaded secure boot key in EFUSE block 2");
|
||||
}
|
||||
|
||||
/* Generate secure boot digest using programmed key in EFUSE */
|
||||
ESP_LOGI(TAG, "Generating secure boot digest...");
|
||||
uint32_t image_len = bootloader_data.image_len;
|
||||
if(bootloader_data.image.hash_appended) {
|
||||
@@ -162,7 +161,28 @@ esp_err_t esp_secure_boot_permanently_enable(void) {
|
||||
}
|
||||
ESP_LOGI(TAG, "Digest generation complete.");
|
||||
|
||||
#ifndef CONFIG_SECURE_BOOT_TEST_MODE
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_secure_boot_permanently_enable(void)
|
||||
{
|
||||
if (esp_secure_boot_enabled()) {
|
||||
ESP_LOGI(TAG, "bootloader secure boot is already enabled, continuing..");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
uint32_t dis_reg = REG_READ(EFUSE_BLK0_RDATA0_REG);
|
||||
bool efuse_key_read_protected = dis_reg & EFUSE_RD_DIS_BLK2;
|
||||
bool efuse_key_write_protected = dis_reg & EFUSE_WR_DIS_BLK2;
|
||||
if (efuse_key_read_protected == false
|
||||
&& efuse_key_write_protected == false) {
|
||||
ESP_LOGI(TAG, "Read & write protecting new key...");
|
||||
REG_WRITE(EFUSE_BLK0_WDATA0_REG, EFUSE_WR_DIS_BLK2 | EFUSE_RD_DIS_BLK2);
|
||||
burn_efuses();
|
||||
efuse_key_read_protected = true;
|
||||
efuse_key_write_protected = true;
|
||||
}
|
||||
|
||||
if (!efuse_key_read_protected) {
|
||||
ESP_LOGE(TAG, "Pre-loaded key is not read protected. Refusing to blow secure boot efuse.");
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
@@ -171,7 +191,6 @@ esp_err_t esp_secure_boot_permanently_enable(void) {
|
||||
ESP_LOGE(TAG, "Pre-loaded key is not write protected. Refusing to blow secure boot efuse.");
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
#endif
|
||||
|
||||
ESP_LOGI(TAG, "blowing secure boot efuse...");
|
||||
ESP_LOGD(TAG, "before updating, EFUSE_BLK0_RDATA6 %x", REG_READ(EFUSE_BLK0_RDATA6_REG));
|
||||
@@ -200,11 +219,9 @@ esp_err_t esp_secure_boot_permanently_enable(void) {
|
||||
ESP_LOGI(TAG, "secure boot is now enabled for bootloader image");
|
||||
return ESP_OK;
|
||||
} else {
|
||||
#ifdef CONFIG_SECURE_BOOT_TEST_MODE
|
||||
ESP_LOGE(TAG, "secure boot not enabled due to test mode");
|
||||
#else
|
||||
ESP_LOGE(TAG, "secure boot not enabled for bootloader image, EFUSE_RD_ABS_DONE_0 is probably write protected!");
|
||||
#endif
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // #ifdef BOOTLOADER_BUILD
|
||||
|
||||
@@ -21,12 +21,7 @@
|
||||
|
||||
#include "uECC.h"
|
||||
|
||||
#ifdef BOOTLOADER_BUILD
|
||||
#include "rom/sha.h"
|
||||
typedef SHA_CTX sha_context;
|
||||
#else
|
||||
#include "mbedtls/sha256.h"
|
||||
#endif
|
||||
#include <sys/param.h>
|
||||
|
||||
static const char* TAG = "secure_boot";
|
||||
|
||||
@@ -37,6 +32,9 @@ extern const uint8_t signature_verification_key_end[] asm("_binary_signature_ver
|
||||
|
||||
#define DIGEST_LEN 32
|
||||
|
||||
/* Mmap source address mask */
|
||||
#define MMAP_ALIGNED_MASK 0x0000FFFF
|
||||
|
||||
esp_err_t esp_secure_boot_verify_signature(uint32_t src_addr, uint32_t length)
|
||||
{
|
||||
uint8_t digest[DIGEST_LEN];
|
||||
@@ -45,26 +43,44 @@ esp_err_t esp_secure_boot_verify_signature(uint32_t src_addr, uint32_t length)
|
||||
|
||||
ESP_LOGD(TAG, "verifying signature src_addr 0x%x length 0x%x", src_addr, length);
|
||||
|
||||
data = bootloader_mmap(src_addr, length + sizeof(esp_secure_boot_sig_block_t));
|
||||
if(data == NULL) {
|
||||
ESP_LOGE(TAG, "bootloader_mmap(0x%x, 0x%x) failed", src_addr, length+sizeof(esp_secure_boot_sig_block_t));
|
||||
return ESP_FAIL;
|
||||
bootloader_sha256_handle_t handle = bootloader_sha256_start();
|
||||
|
||||
uint32_t free_page_count = bootloader_mmap_get_free_pages();
|
||||
ESP_LOGD(TAG, "free data page_count 0x%08x", free_page_count);
|
||||
|
||||
int32_t data_len_remain = length;
|
||||
uint32_t data_addr = src_addr;
|
||||
while (data_len_remain > 0) {
|
||||
uint32_t offset_page = ((data_addr & MMAP_ALIGNED_MASK) != 0) ? 1 : 0;
|
||||
/* Data we could map in case we are not aligned to PAGE boundary is one page size lesser. */
|
||||
uint32_t data_len = MIN(data_len_remain, ((free_page_count - offset_page) * SPI_FLASH_MMU_PAGE_SIZE));
|
||||
data = (const uint8_t *) bootloader_mmap(data_addr, data_len);
|
||||
if(!data) {
|
||||
ESP_LOGE(TAG, "bootloader_mmap(0x%x, 0x%x) failed", data_addr, data_len);
|
||||
bootloader_sha256_finish(handle, NULL);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
bootloader_sha256_data(handle, data, data_len);
|
||||
bootloader_munmap(data);
|
||||
|
||||
data_addr += data_len;
|
||||
data_len_remain -= data_len;
|
||||
}
|
||||
|
||||
// Calculate digest of main image
|
||||
#ifdef BOOTLOADER_BUILD
|
||||
bootloader_sha256_handle_t handle = bootloader_sha256_start();
|
||||
bootloader_sha256_data(handle, data, length);
|
||||
/* Done! Get the digest */
|
||||
bootloader_sha256_finish(handle, digest);
|
||||
#else
|
||||
/* Use thread-safe mbedTLS version */
|
||||
mbedtls_sha256_ret(data, length, digest, 0);
|
||||
#endif
|
||||
|
||||
// Map the signature block and verify the signature
|
||||
sigblock = (const esp_secure_boot_sig_block_t *)(data + length);
|
||||
// Map the signature block
|
||||
sigblock = (const esp_secure_boot_sig_block_t *) bootloader_mmap(src_addr + length, sizeof(esp_secure_boot_sig_block_t));
|
||||
if(!sigblock) {
|
||||
ESP_LOGE(TAG, "bootloader_mmap(0x%x, 0x%x) failed", src_addr + length, sizeof(esp_secure_boot_sig_block_t));
|
||||
return ESP_FAIL;
|
||||
}
|
||||
// Verify the signature
|
||||
esp_err_t err = esp_secure_boot_verify_signature_block(sigblock, digest);
|
||||
bootloader_munmap(data);
|
||||
// Unmap
|
||||
bootloader_munmap(sigblock);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
@@ -1263,6 +1263,16 @@ menu Bluetooth
|
||||
Bluedroid will report adv data or scan response to application layer immediately.
|
||||
|
||||
# Memory reserved at start of DRAM for Bluetooth stack
|
||||
|
||||
config BLE_ESTABLISH_LINK_CONNECTION_TIMEOUT
|
||||
int "Timeout of BLE connection establishment"
|
||||
depends on BLUEDROID_ENABLED
|
||||
range 1 60
|
||||
default 30
|
||||
help
|
||||
Bluetooth Connection establishment maximum time, if connection time exceeds this value, the connection
|
||||
establishment fails, ESP_GATTC_OPEN_EVT or ESP_GATTS_OPEN_EVT is triggered.
|
||||
|
||||
config BT_RESERVE_DRAM
|
||||
hex
|
||||
default 0xdb5c if BT_ENABLED
|
||||
|
||||
@@ -715,10 +715,13 @@ void btc_gatts_call_handler(btc_msg_t *msg)
|
||||
#else
|
||||
//BTA_DmAddBleDevice(p_cb->bd_addr.address, addr_type, device_type);
|
||||
#endif
|
||||
/*
|
||||
not support background connection
|
||||
// Mark background connections
|
||||
if (!arg->open.is_direct) {
|
||||
BTA_DmBleSetBgConnType(BTM_BLE_CONN_AUTO, NULL);
|
||||
}
|
||||
*/
|
||||
|
||||
transport = BTA_GATT_TRANSPORT_LE;
|
||||
|
||||
|
||||
@@ -315,6 +315,7 @@ static void btc_spp_init(btc_spp_args_t *arg)
|
||||
{
|
||||
if (osi_mutex_new(&spp_local_param.spp_slot_mutex) != 0) {
|
||||
BTC_TRACE_ERROR("%s osi_mutex_new failed\n", __func__);
|
||||
return;
|
||||
}
|
||||
spp_local_param.spp_mode = arg->init.mode;
|
||||
spp_local_param.spp_slot_id = 0;
|
||||
@@ -323,6 +324,10 @@ static void btc_spp_init(btc_spp_args_t *arg)
|
||||
|
||||
static void btc_spp_uninit(void)
|
||||
{
|
||||
if (!spp_local_param.spp_slot_mutex) {
|
||||
BTC_TRACE_ERROR("%s SPP have not been init\n", __func__);
|
||||
return;
|
||||
}
|
||||
osi_mutex_lock(&spp_local_param.spp_slot_mutex, OSI_MUTEX_MAX_TIMEOUT);
|
||||
for (size_t i = 1; i <= BTA_JV_MAX_RFC_SR_SESSION; i++) {
|
||||
if (spp_local_param.spp_slots[i] != NULL && spp_local_param.spp_slots[i]->connected) {
|
||||
|
||||
@@ -166,6 +166,12 @@
|
||||
#define GATT_MAX_PHY_CHANNEL CONFIG_BT_ACL_CONNECTIONS
|
||||
#endif /* CONFIG_BT_ACL_CONNECTIONS */
|
||||
|
||||
#if(CONFIG_BLE_ESTABLISH_LINK_CONNECTION_TIMEOUT)
|
||||
#define BLE_ESTABLISH_LINK_CONNECTION_TIMEOUT CONFIG_BLE_ESTABLISH_LINK_CONNECTION_TIMEOUT
|
||||
#else
|
||||
#define BLE_ESTABLISH_LINK_CONNECTION_TIMEOUT 30
|
||||
#endif
|
||||
|
||||
//------------------Added from bdroid_buildcfg.h---------------------
|
||||
#ifndef L2CAP_EXTFEA_SUPPORTED_MASK
|
||||
#define L2CAP_EXTFEA_SUPPORTED_MASK (L2CAP_EXTFEA_ENH_RETRANS | L2CAP_EXTFEA_STREAM_MODE | L2CAP_EXTFEA_NO_CRC | L2CAP_EXTFEA_FIXED_CHNLS)
|
||||
|
||||
@@ -189,10 +189,10 @@ task_post_status_t hci_hal_h4_task_post(task_post_t timeout)
|
||||
evt.par = 0;
|
||||
|
||||
if (xQueueSend(xHciH4Queue, &evt, timeout) != pdTRUE) {
|
||||
return TASK_POST_SUCCESS;
|
||||
return TASK_POST_FAIL;
|
||||
}
|
||||
|
||||
return TASK_POST_FAIL;
|
||||
return TASK_POST_SUCCESS;
|
||||
}
|
||||
|
||||
#if (C2H_FLOW_CONTROL_INCLUDED == TRUE)
|
||||
|
||||
@@ -2006,9 +2006,18 @@ void btm_ble_conn_complete(UINT8 *p, UINT16 evt_len, BOOLEAN enhanced)
|
||||
btm_ble_disable_resolving_list(BTM_BLE_RL_ADV, TRUE);
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
btm_ble_update_mode_operation(role, bda, status);
|
||||
BOOLEAN bg_con = btm_ble_update_mode_operation(role, bda, status);
|
||||
if (status != HCI_SUCCESS && !bg_con) {
|
||||
// notify connection failed
|
||||
l2c_link_hci_disc_comp (handle, status);
|
||||
#if (SMP_INCLUDED == TRUE)
|
||||
/* Notify security manager */
|
||||
btm_sec_disconnected (handle, status);
|
||||
#endif ///SMP_INCLUDED == TRUE
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -4229,8 +4229,9 @@ void btm_ble_update_link_topology_mask(UINT8 link_role, BOOLEAN increase)
|
||||
** Returns void
|
||||
**
|
||||
*******************************************************************************/
|
||||
void btm_ble_update_mode_operation(UINT8 link_role, BD_ADDR bd_addr, UINT8 status)
|
||||
BOOLEAN btm_ble_update_mode_operation(UINT8 link_role, BD_ADDR bd_addr, UINT8 status)
|
||||
{
|
||||
BOOLEAN bg_con = FALSE;
|
||||
if (status == HCI_ERR_DIRECTED_ADVERTISING_TIMEOUT) {
|
||||
btm_cb.ble_ctr_cb.inq_var.adv_mode = BTM_BLE_ADV_DISABLE;
|
||||
/* make device fall back into undirected adv mode by default */
|
||||
@@ -4249,8 +4250,10 @@ void btm_ble_update_mode_operation(UINT8 link_role, BD_ADDR bd_addr, UINT8 statu
|
||||
now in order */
|
||||
if (btm_ble_get_conn_st() == BLE_CONN_IDLE && status != HCI_ERR_HOST_REJECT_RESOURCES &&
|
||||
!btm_send_pending_direct_conn()) {
|
||||
btm_ble_resume_bg_conn();
|
||||
bg_con = btm_ble_resume_bg_conn();
|
||||
}
|
||||
|
||||
return bg_con;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
|
||||
@@ -448,7 +448,7 @@ BOOLEAN btm_ble_start_auto_conn(BOOLEAN start);
|
||||
BOOLEAN btm_ble_start_select_conn(BOOLEAN start, tBTM_BLE_SEL_CBACK *p_select_cback);
|
||||
BOOLEAN btm_ble_renew_bg_conn_params(BOOLEAN add, BD_ADDR bd_addr);
|
||||
void btm_write_dir_conn_wl(BD_ADDR target_addr);
|
||||
void btm_ble_update_mode_operation(UINT8 link_role, BD_ADDR bda, UINT8 status);
|
||||
BOOLEAN btm_ble_update_mode_operation(UINT8 link_role, BD_ADDR bda, UINT8 status);
|
||||
BOOLEAN btm_execute_wl_dev_operation(void);
|
||||
void btm_ble_update_link_topology_mask(UINT8 role, BOOLEAN increase);
|
||||
|
||||
|
||||
@@ -66,7 +66,7 @@
|
||||
#define L2CAP_WAIT_UNPARK_TOUT 2 /* 2 seconds */
|
||||
#define L2CAP_LINK_INFO_RESP_TOUT 2 /* 2 seconds */
|
||||
#define L2CAP_UPDATE_CONN_PARAM_TOUT 6 /* 6 seconds */
|
||||
#define L2CAP_BLE_LINK_CONNECT_TOUT 30 /* 30 seconds */
|
||||
#define L2CAP_BLE_LINK_CONNECT_TOUT BLE_ESTABLISH_LINK_CONNECTION_TIMEOUT // configed in menuconfig
|
||||
#define L2CAP_BLE_CONN_PARAM_UPD_TOUT 30 /* 30 seconds */
|
||||
|
||||
/* quick timer uses millisecond unit */
|
||||
|
||||
@@ -196,7 +196,8 @@ extern void btdm_controller_enable_sleep(bool enable);
|
||||
extern void btdm_controller_set_sleep_mode(uint8_t mode);
|
||||
extern uint8_t btdm_controller_get_sleep_mode(void);
|
||||
extern bool btdm_power_state_active(void);
|
||||
extern void btdm_wakeup_request(void);
|
||||
extern void btdm_wakeup_request(bool request_lock);
|
||||
extern void btdm_wakeup_request_end(void);
|
||||
/* Low Power Clock */
|
||||
extern bool btdm_lpclk_select_src(uint32_t sel);
|
||||
extern bool btdm_lpclk_set_div(uint32_t div);
|
||||
@@ -879,6 +880,8 @@ bool esp_vhci_host_check_send_available(void)
|
||||
|
||||
void esp_vhci_host_send_packet(uint8_t *data, uint16_t len)
|
||||
{
|
||||
bool do_wakeup_request = false;
|
||||
|
||||
if (!btdm_power_state_active()) {
|
||||
#if CONFIG_PM_ENABLE
|
||||
if (semphr_take_wrapper(s_pm_lock_sem, 0)) {
|
||||
@@ -886,9 +889,15 @@ void esp_vhci_host_send_packet(uint8_t *data, uint16_t len)
|
||||
}
|
||||
esp_timer_stop(s_btdm_slp_tmr);
|
||||
#endif
|
||||
btdm_wakeup_request();
|
||||
do_wakeup_request = true;
|
||||
btdm_wakeup_request(true);
|
||||
}
|
||||
|
||||
API_vhci_host_send_packet(data, len);
|
||||
|
||||
if (do_wakeup_request) {
|
||||
btdm_wakeup_request_end();
|
||||
}
|
||||
}
|
||||
|
||||
esp_err_t esp_vhci_host_register_callback(const esp_vhci_host_callback_t *callback)
|
||||
@@ -1290,7 +1299,7 @@ esp_err_t esp_bt_controller_disable(void)
|
||||
if (btdm_controller_get_sleep_mode() == BTDM_MODEM_SLEEP_MODE_ORIG) {
|
||||
btdm_controller_enable_sleep(false);
|
||||
if (!btdm_power_state_active()) {
|
||||
btdm_wakeup_request();
|
||||
btdm_wakeup_request(false);
|
||||
}
|
||||
while (!btdm_power_state_active()) {
|
||||
ets_delay_us(1000);
|
||||
@@ -1426,7 +1435,7 @@ void esp_bt_controller_wakeup_request(void)
|
||||
return;
|
||||
}
|
||||
|
||||
btdm_wakeup_request();
|
||||
btdm_wakeup_request(false);
|
||||
}
|
||||
|
||||
esp_err_t esp_bredr_sco_datapath_set(esp_sco_data_path_t data_path)
|
||||
|
||||
Submodule components/bt/lib updated: 70d6a277d7...4b35933006
@@ -22,21 +22,34 @@
|
||||
#include "soc/soc.h"
|
||||
#include "esp_log.h"
|
||||
#include "soc/gpio_periph.h"
|
||||
#include "esp_ipc.h"
|
||||
|
||||
static const char* GPIO_TAG = "gpio";
|
||||
#define GPIO_CHECK(a, str, ret_val) \
|
||||
if (!(a)) { \
|
||||
ESP_LOGE(GPIO_TAG,"%s(%d): %s", __FUNCTION__, __LINE__, str); \
|
||||
return (ret_val); \
|
||||
}
|
||||
#define GPIO_ISR_CORE_ID_UNINIT (3)
|
||||
|
||||
typedef struct {
|
||||
gpio_isr_t fn; /*!< isr function */
|
||||
void* args; /*!< isr function args */
|
||||
} gpio_isr_func_t;
|
||||
|
||||
// Used by the IPC call to register the interrupt service routine.
|
||||
typedef struct {
|
||||
int source; /*!< ISR source */
|
||||
int intr_alloc_flags; /*!< ISR alloc flag */
|
||||
void (*fn)(void*); /*!< ISR function */
|
||||
void *arg; /*!< ISR function args*/
|
||||
void *handle; /*!< ISR handle */
|
||||
esp_err_t ret;
|
||||
} gpio_isr_alloc_t;
|
||||
|
||||
static const char* GPIO_TAG = "gpio";
|
||||
static gpio_isr_func_t* gpio_isr_func = NULL;
|
||||
static gpio_isr_handle_t gpio_isr_handle;
|
||||
static uint32_t isr_core_id = GPIO_ISR_CORE_ID_UNINIT;
|
||||
static portMUX_TYPE gpio_spinlock = portMUX_INITIALIZER_UNLOCKED;
|
||||
|
||||
esp_err_t gpio_pullup_en(gpio_num_t gpio_num)
|
||||
@@ -102,7 +115,6 @@ static void gpio_intr_status_clr(gpio_num_t gpio_num)
|
||||
|
||||
static esp_err_t gpio_intr_enable_on_core (gpio_num_t gpio_num, uint32_t core_id)
|
||||
{
|
||||
GPIO_CHECK(GPIO_IS_VALID_GPIO(gpio_num), "GPIO number error", ESP_ERR_INVALID_ARG);
|
||||
gpio_intr_status_clr(gpio_num);
|
||||
if (core_id == 0) {
|
||||
GPIO.pin[gpio_num].int_ena = GPIO_PRO_CPU_INTR_ENA; //enable pro cpu intr
|
||||
@@ -114,7 +126,13 @@ static esp_err_t gpio_intr_enable_on_core (gpio_num_t gpio_num, uint32_t core_id
|
||||
|
||||
esp_err_t gpio_intr_enable(gpio_num_t gpio_num)
|
||||
{
|
||||
return gpio_intr_enable_on_core (gpio_num, xPortGetCoreID());
|
||||
GPIO_CHECK(GPIO_IS_VALID_GPIO(gpio_num), "GPIO number error", ESP_ERR_INVALID_ARG);
|
||||
portENTER_CRITICAL(&gpio_spinlock);
|
||||
if(isr_core_id == GPIO_ISR_CORE_ID_UNINIT) {
|
||||
isr_core_id = xPortGetCoreID();
|
||||
}
|
||||
portEXIT_CRITICAL(&gpio_spinlock);
|
||||
return gpio_intr_enable_on_core (gpio_num, isr_core_id);
|
||||
}
|
||||
|
||||
esp_err_t gpio_intr_disable(gpio_num_t gpio_num)
|
||||
@@ -332,11 +350,9 @@ void IRAM_ATTR gpio_intr_service(void* arg)
|
||||
//GPIO intr process
|
||||
uint32_t gpio_num = 0;
|
||||
//read status to get interrupt status for GPIO0-31
|
||||
uint32_t gpio_intr_status;
|
||||
gpio_intr_status = GPIO.status;
|
||||
const uint32_t gpio_intr_status = (isr_core_id == 0) ? GPIO.pcpu_int : GPIO.acpu_int;
|
||||
//read status1 to get interrupt status for GPIO32-39
|
||||
uint32_t gpio_intr_status_h;
|
||||
gpio_intr_status_h = GPIO.status1.intr_st;
|
||||
const uint32_t gpio_intr_status_h = (isr_core_id == 0) ? GPIO.pcpu_int1.intr : GPIO.acpu_int1.intr;
|
||||
|
||||
if (gpio_isr_func == NULL) {
|
||||
return;
|
||||
@@ -395,12 +411,12 @@ esp_err_t gpio_install_isr_service(int intr_alloc_flags)
|
||||
esp_err_t ret;
|
||||
portENTER_CRITICAL(&gpio_spinlock);
|
||||
gpio_isr_func = (gpio_isr_func_t*) calloc(GPIO_NUM_MAX, sizeof(gpio_isr_func_t));
|
||||
portEXIT_CRITICAL(&gpio_spinlock);
|
||||
if (gpio_isr_func == NULL) {
|
||||
ret = ESP_ERR_NO_MEM;
|
||||
} else {
|
||||
ret = gpio_isr_register(gpio_intr_service, NULL, intr_alloc_flags, &gpio_isr_handle);
|
||||
}
|
||||
portEXIT_CRITICAL(&gpio_spinlock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -413,14 +429,37 @@ void gpio_uninstall_isr_service()
|
||||
esp_intr_free(gpio_isr_handle);
|
||||
free(gpio_isr_func);
|
||||
gpio_isr_func = NULL;
|
||||
isr_core_id = GPIO_ISR_CORE_ID_UNINIT;
|
||||
portEXIT_CRITICAL(&gpio_spinlock);
|
||||
return;
|
||||
}
|
||||
|
||||
static void gpio_isr_register_on_core_static(void *param)
|
||||
{
|
||||
gpio_isr_alloc_t *p = (gpio_isr_alloc_t *)param;
|
||||
//We need to check the return value.
|
||||
p->ret = esp_intr_alloc(p->source, p->intr_alloc_flags, p->fn, p->arg, p->handle);
|
||||
}
|
||||
|
||||
esp_err_t gpio_isr_register(void (*fn)(void*), void * arg, int intr_alloc_flags, gpio_isr_handle_t *handle)
|
||||
{
|
||||
GPIO_CHECK(fn, "GPIO ISR null", ESP_ERR_INVALID_ARG);
|
||||
return esp_intr_alloc(ETS_GPIO_INTR_SOURCE, intr_alloc_flags, fn, arg, handle);
|
||||
gpio_isr_alloc_t p;
|
||||
p.source = ETS_GPIO_INTR_SOURCE;
|
||||
p.intr_alloc_flags = intr_alloc_flags;
|
||||
p.fn = fn;
|
||||
p.arg = arg;
|
||||
p.handle = handle;
|
||||
portENTER_CRITICAL(&gpio_spinlock);
|
||||
if(isr_core_id == GPIO_ISR_CORE_ID_UNINIT) {
|
||||
isr_core_id = xPortGetCoreID();
|
||||
}
|
||||
portEXIT_CRITICAL(&gpio_spinlock);
|
||||
esp_err_t ret = esp_ipc_call_blocking(isr_core_id, gpio_isr_register_on_core_static, (void *)&p);
|
||||
if(ret != ESP_OK || p.ret != ESP_OK) {
|
||||
return ESP_ERR_NOT_FOUND;
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t gpio_wakeup_enable(gpio_num_t gpio_num, gpio_int_type_t intr_type)
|
||||
|
||||
@@ -90,6 +90,7 @@ typedef struct {
|
||||
bool use_apll; /*!< I2S use APLL clock */
|
||||
bool tx_desc_auto_clear; /*!< I2S auto clear tx descriptor on underflow */
|
||||
int fixed_mclk; /*!< I2S fixed MLCK clock */
|
||||
double real_rate;
|
||||
} i2s_obj_t;
|
||||
|
||||
static i2s_obj_t *p_i2s_obj[I2S_NUM_MAX] = {0};
|
||||
@@ -176,6 +177,12 @@ esp_err_t i2s_enable_tx_intr(i2s_port_t i2s_num)
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
float i2s_get_clk(i2s_port_t i2s_num)
|
||||
{
|
||||
I2S_CHECK((i2s_num < I2S_NUM_MAX), "i2s_num error", ESP_ERR_INVALID_ARG);
|
||||
return p_i2s_obj[i2s_num]->real_rate;
|
||||
}
|
||||
|
||||
static esp_err_t i2s_isr_register(i2s_port_t i2s_num, int intr_alloc_flags, void (*fn)(void*), void * arg, i2s_isr_handle_t *handle)
|
||||
{
|
||||
return esp_intr_alloc(ETS_I2S0_INTR_SOURCE + i2s_num, intr_alloc_flags, fn, arg, handle);
|
||||
@@ -251,7 +258,7 @@ static esp_err_t i2s_apll_calculate_fi2s(int rate, int bits_per_sample, int *sdm
|
||||
max_rate = i2s_apll_get_fi2s(bits_per_sample, 255, 255, _sdm2, 0);
|
||||
min_rate = i2s_apll_get_fi2s(bits_per_sample, 0, 0, _sdm2, 31);
|
||||
avg = (max_rate + min_rate)/2;
|
||||
if(abs(avg - rate) < min_diff) {
|
||||
if (abs(avg - rate) < min_diff) {
|
||||
min_diff = abs(avg - rate);
|
||||
*sdm2 = _sdm2;
|
||||
}
|
||||
@@ -261,11 +268,21 @@ static esp_err_t i2s_apll_calculate_fi2s(int rate, int bits_per_sample, int *sdm
|
||||
max_rate = i2s_apll_get_fi2s(bits_per_sample, 255, 255, *sdm2, _odir);
|
||||
min_rate = i2s_apll_get_fi2s(bits_per_sample, 0, 0, *sdm2, _odir);
|
||||
avg = (max_rate + min_rate)/2;
|
||||
if(abs(avg - rate) < min_diff) {
|
||||
if (abs(avg - rate) < min_diff) {
|
||||
min_diff = abs(avg - rate);
|
||||
*odir = _odir;
|
||||
}
|
||||
}
|
||||
min_diff = APLL_MAX_FREQ;
|
||||
for (_sdm2 = 4; _sdm2 < 9; _sdm2 ++) {
|
||||
max_rate = i2s_apll_get_fi2s(bits_per_sample, 255, 255, _sdm2, *odir);
|
||||
min_rate = i2s_apll_get_fi2s(bits_per_sample, 0, 0, _sdm2, *odir);
|
||||
avg = (max_rate + min_rate)/2;
|
||||
if (abs(avg - rate) < min_diff) {
|
||||
min_diff = abs(avg - rate);
|
||||
*sdm2 = _sdm2;
|
||||
}
|
||||
}
|
||||
|
||||
min_diff = APLL_MAX_FREQ;
|
||||
for (_sdm1 = 0; _sdm1 < 256; _sdm1 ++) {
|
||||
@@ -453,6 +470,7 @@ esp_err_t i2s_set_clk(i2s_port_t i2s_num, uint32_t rate, i2s_bits_per_sample_t b
|
||||
I2S[i2s_num]->sample_rate_conf.rx_bck_div_num = m_scale;
|
||||
I2S[i2s_num]->clkm_conf.clka_en = 1;
|
||||
double fi2s_rate = i2s_apll_get_fi2s(bits, sdm0, sdm1, sdm2, odir);
|
||||
p_i2s_obj[i2s_num]->real_rate = fi2s_rate/bits/channel/m_scale;
|
||||
ESP_LOGI(I2S_TAG, "APLL: Req RATE: %d, real rate: %0.3f, BITS: %u, CLKM: %u, BCK_M: %u, MCLK: %0.3f, SCLK: %f, diva: %d, divb: %d",
|
||||
rate, fi2s_rate/bits/channel/m_scale, bits, 1, m_scale, fi2s_rate, fi2s_rate/8, 1, 0);
|
||||
} else {
|
||||
@@ -463,6 +481,7 @@ esp_err_t i2s_set_clk(i2s_port_t i2s_num, uint32_t rate, i2s_bits_per_sample_t b
|
||||
I2S[i2s_num]->sample_rate_conf.tx_bck_div_num = bck;
|
||||
I2S[i2s_num]->sample_rate_conf.rx_bck_div_num = bck;
|
||||
double real_rate = (double) (I2S_BASE_CLK / (bck * bits * clkmInteger) / 2);
|
||||
p_i2s_obj[i2s_num]->real_rate = real_rate;
|
||||
ESP_LOGI(I2S_TAG, "PLL_D2: Req RATE: %d, real rate: %0.3f, BITS: %u, CLKM: %u, BCK: %u, MCLK: %0.3f, SCLK: %f, diva: %d, divb: %d",
|
||||
rate, real_rate, bits, clkmInteger, bck, (double)I2S_BASE_CLK / mclk, real_rate*bits*channel, 64, clkmDecimals);
|
||||
}
|
||||
|
||||
@@ -503,6 +503,16 @@ esp_err_t i2s_zero_dma_buffer(i2s_port_t i2s_num);
|
||||
*/
|
||||
esp_err_t i2s_set_clk(i2s_port_t i2s_num, uint32_t rate, i2s_bits_per_sample_t bits, i2s_channel_t ch);
|
||||
|
||||
/**
|
||||
* @brief get clock set on particular port number.
|
||||
*
|
||||
* @param i2s_num I2S_NUM_0, I2S_NUM_1
|
||||
*
|
||||
* @return
|
||||
* - actual clock set by i2s driver
|
||||
*/
|
||||
float i2s_get_clk(i2s_port_t i2s_num);
|
||||
|
||||
/**
|
||||
* @brief Set built-in ADC mode for I2S DMA, this function will initialize ADC pad,
|
||||
* and set ADC parameters.
|
||||
|
||||
@@ -29,26 +29,26 @@ static uint32_t get_rst_en_reg(periph_module_t periph);
|
||||
|
||||
void periph_module_enable(periph_module_t periph)
|
||||
{
|
||||
portENTER_CRITICAL(&periph_spinlock);
|
||||
portENTER_CRITICAL_SAFE(&periph_spinlock);
|
||||
DPORT_SET_PERI_REG_MASK(get_clk_en_reg(periph), get_clk_en_mask(periph));
|
||||
DPORT_CLEAR_PERI_REG_MASK(get_rst_en_reg(periph), get_rst_en_mask(periph, true));
|
||||
portEXIT_CRITICAL(&periph_spinlock);
|
||||
portEXIT_CRITICAL_SAFE(&periph_spinlock);
|
||||
}
|
||||
|
||||
void periph_module_disable(periph_module_t periph)
|
||||
{
|
||||
portENTER_CRITICAL(&periph_spinlock);
|
||||
portENTER_CRITICAL_SAFE(&periph_spinlock);
|
||||
DPORT_CLEAR_PERI_REG_MASK(get_clk_en_reg(periph), get_clk_en_mask(periph));
|
||||
DPORT_SET_PERI_REG_MASK(get_rst_en_reg(periph), get_rst_en_mask(periph, false));
|
||||
portEXIT_CRITICAL(&periph_spinlock);
|
||||
portEXIT_CRITICAL_SAFE(&periph_spinlock);
|
||||
}
|
||||
|
||||
void periph_module_reset(periph_module_t periph)
|
||||
{
|
||||
portENTER_CRITICAL(&periph_spinlock);
|
||||
portENTER_CRITICAL_SAFE(&periph_spinlock);
|
||||
DPORT_SET_PERI_REG_MASK(get_rst_en_reg(periph), get_rst_en_mask(periph, false));
|
||||
DPORT_CLEAR_PERI_REG_MASK(get_rst_en_reg(periph), get_rst_en_mask(periph, false));
|
||||
portEXIT_CRITICAL(&periph_spinlock);
|
||||
portEXIT_CRITICAL_SAFE(&periph_spinlock);
|
||||
}
|
||||
|
||||
static uint32_t get_clk_en_mask(periph_module_t periph)
|
||||
|
||||
@@ -501,9 +501,9 @@ esp_err_t rmt_config(const rmt_config_t* rmt_param)
|
||||
|
||||
static void IRAM_ATTR rmt_fill_memory(rmt_channel_t channel, const rmt_item32_t* item, uint16_t item_num, uint16_t mem_offset)
|
||||
{
|
||||
portENTER_CRITICAL(&rmt_spinlock);
|
||||
portENTER_CRITICAL_SAFE(&rmt_spinlock);
|
||||
RMT.apb_conf.fifo_mask = RMT_DATA_MODE_MEM;
|
||||
portEXIT_CRITICAL(&rmt_spinlock);
|
||||
portEXIT_CRITICAL_SAFE(&rmt_spinlock);
|
||||
int i;
|
||||
for(i = 0; i < item_num; i++) {
|
||||
RMTMEM.chan[channel].data32[i + mem_offset].val = item[i].val;
|
||||
|
||||
@@ -1964,15 +1964,15 @@ static void rtc_isr(void* arg)
|
||||
{
|
||||
uint32_t status = REG_READ(RTC_CNTL_INT_ST_REG);
|
||||
rtc_isr_handler_t* it;
|
||||
portENTER_CRITICAL(&s_rtc_isr_handler_list_lock);
|
||||
portENTER_CRITICAL_ISR(&s_rtc_isr_handler_list_lock);
|
||||
SLIST_FOREACH(it, &s_rtc_isr_handler_list, next) {
|
||||
if (it->mask & status) {
|
||||
portEXIT_CRITICAL(&s_rtc_isr_handler_list_lock);
|
||||
portEXIT_CRITICAL_ISR(&s_rtc_isr_handler_list_lock);
|
||||
(*it->handler)(it->handler_arg);
|
||||
portENTER_CRITICAL(&s_rtc_isr_handler_list_lock);
|
||||
portENTER_CRITICAL_ISR(&s_rtc_isr_handler_list_lock);
|
||||
}
|
||||
}
|
||||
portEXIT_CRITICAL(&s_rtc_isr_handler_list_lock);
|
||||
portEXIT_CRITICAL_ISR(&s_rtc_isr_handler_list_lock);
|
||||
REG_WRITE(RTC_CNTL_INT_CLR_REG, status);
|
||||
}
|
||||
|
||||
|
||||
@@ -1174,7 +1174,7 @@ static SPI_MASTER_ISR_ATTR esp_err_t setup_priv_desc(spi_transaction_t *trans_de
|
||||
}
|
||||
if (send_ptr && isdma && !esp_ptr_dma_capable( send_ptr )) {
|
||||
//if txbuf in the desc not DMA-capable, malloc a new one
|
||||
ESP_LOGI( SPI_TAG, "Allocate TX buffer for DMA" );
|
||||
ESP_LOGD( SPI_TAG, "Allocate TX buffer for DMA" );
|
||||
uint32_t *temp = heap_caps_malloc((trans_desc->length + 7) / 8, MALLOC_CAP_DMA);
|
||||
if (temp == NULL) goto clean_up;
|
||||
|
||||
|
||||
@@ -467,12 +467,14 @@ static void SPI_SLAVE_ISR_ATTR spi_intr(void *arg)
|
||||
}
|
||||
}
|
||||
|
||||
//Disable interrupt before checking to avoid concurrency issue.
|
||||
esp_intr_disable(host->intr);
|
||||
//Grab next transaction
|
||||
r = xQueueReceiveFromISR(host->trans_queue, &trans, &do_yield);
|
||||
if (!r) {
|
||||
//No packet waiting. Disable interrupt.
|
||||
esp_intr_disable(host->intr);
|
||||
} else {
|
||||
if (r) {
|
||||
//enable the interrupt again if there is packet to send
|
||||
esp_intr_enable(host->intr);
|
||||
|
||||
//We have a transaction. Send it.
|
||||
host->hw->slave.trans_done = 0; //clear int bit
|
||||
host->cur_trans = trans;
|
||||
|
||||
@@ -616,3 +616,128 @@ TEST_CASE("GPIO drive capability test", "[gpio][ignore]")
|
||||
drive_capability_set_get(GPIO_OUTPUT_IO, GPIO_DRIVE_CAP_3);
|
||||
prompt_to_continue("If this test finishes");
|
||||
}
|
||||
|
||||
#if !CONFIG_FREERTOS_UNICORE
|
||||
void gpio_enable_task(void *param)
|
||||
{
|
||||
int gpio_num = (int)param;
|
||||
TEST_ESP_OK(gpio_intr_enable(gpio_num));
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
/** Test the GPIO Interrupt Enable API with dual core enabled. The GPIO ISR service routine is registered on one core.
|
||||
* When the GPIO interrupt on another core is enabled, the GPIO interrupt will be lost.
|
||||
* First on the core 0, Do the following steps:
|
||||
* 1. Configure the GPIO18 input_output mode, and enable the rising edge interrupt mode.
|
||||
* 2. Trigger the GPIO18 interrupt and check if the interrupt responds correctly.
|
||||
* 3. Disable the GPIO18 interrupt
|
||||
* Then on the core 1, Do the following steps:
|
||||
* 1. Enable the GPIO18 interrupt again.
|
||||
* 2. Trigger the GPIO18 interrupt and check if the interrupt responds correctly.
|
||||
*
|
||||
*/
|
||||
TEST_CASE("GPIO Enable/Disable interrupt on multiple cores", "[gpio][ignore]")
|
||||
{
|
||||
const int test_io18 = GPIO_NUM_18;
|
||||
gpio_config_t io_conf;
|
||||
io_conf.intr_type = GPIO_INTR_NEGEDGE;
|
||||
io_conf.mode = GPIO_MODE_INPUT_OUTPUT;
|
||||
io_conf.pin_bit_mask = (1ULL << test_io18);
|
||||
io_conf.pull_down_en = 0;
|
||||
io_conf.pull_up_en = 1;
|
||||
TEST_ESP_OK(gpio_config(&io_conf));
|
||||
TEST_ESP_OK(gpio_set_level(test_io18, 0));
|
||||
TEST_ESP_OK(gpio_install_isr_service(0));
|
||||
TEST_ESP_OK(gpio_isr_handler_add(test_io18, gpio_isr_edge_handler, (void*) test_io18));
|
||||
vTaskDelay(1000 / portTICK_RATE_MS);
|
||||
TEST_ESP_OK(gpio_set_level(test_io18, 1));
|
||||
vTaskDelay(100 / portTICK_RATE_MS);
|
||||
TEST_ESP_OK(gpio_set_level(test_io18, 0));
|
||||
vTaskDelay(100 / portTICK_RATE_MS);
|
||||
TEST_ESP_OK(gpio_intr_disable(test_io18));
|
||||
TEST_ASSERT(edge_intr_times == 1);
|
||||
xTaskCreatePinnedToCore(gpio_enable_task, "gpio_enable_task", 1024*4, (void*)test_io18, 8, NULL, (xPortGetCoreID() == 0));
|
||||
vTaskDelay(1000 / portTICK_RATE_MS);
|
||||
TEST_ESP_OK(gpio_set_level(test_io18, 1));
|
||||
vTaskDelay(100 / portTICK_RATE_MS);
|
||||
TEST_ESP_OK(gpio_set_level(test_io18, 0));
|
||||
vTaskDelay(100 / portTICK_RATE_MS);
|
||||
TEST_ESP_OK(gpio_intr_disable(test_io18));
|
||||
TEST_ESP_OK(gpio_isr_handler_remove(test_io18));
|
||||
gpio_uninstall_isr_service();
|
||||
TEST_ASSERT(edge_intr_times == 2);
|
||||
}
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
int gpio_num;
|
||||
int isr_cnt;
|
||||
} gpio_isr_param_t;
|
||||
|
||||
static void gpio_isr_handler(void* arg)
|
||||
{
|
||||
gpio_isr_param_t *param = (gpio_isr_param_t *)arg;
|
||||
ets_printf("GPIO[%d] intr, val: %d\n", param->gpio_num, gpio_get_level(param->gpio_num));
|
||||
param->isr_cnt++;
|
||||
}
|
||||
|
||||
/** The previous GPIO interrupt service routine polls the interrupt raw status register to find the GPIO that triggered the interrupt.
|
||||
* But this will incorrectly handle the interrupt disabled GPIOs, because the raw interrupt status register can still be set when
|
||||
* the trigger signal arrives, even if the interrupt is disabled.
|
||||
* First on the core 0:
|
||||
* 1. Configure the GPIO18 and GPIO19 input_output mode.
|
||||
* 2. Enable GPIO18 dual edge triggered interrupt, enable GPIO19 falling edge triggered interrupt.
|
||||
* 3. Trigger GPIO18 interrupt, then disable the GPIO8 interrupt, and then trigger GPIO18 again(This time will not respond to the interrupt).
|
||||
* 4. Trigger GPIO19 interrupt.
|
||||
* If the bug is not fixed, you will see, in the step 4, the interrupt of GPIO18 will also respond.
|
||||
*/
|
||||
TEST_CASE("GPIO ISR service test", "[gpio][ignore]")
|
||||
{
|
||||
const int test_io18 = GPIO_NUM_18;
|
||||
const int test_io19 = GPIO_NUM_19;
|
||||
static gpio_isr_param_t io18_param = {
|
||||
.gpio_num = GPIO_NUM_18,
|
||||
.isr_cnt = 0,
|
||||
};
|
||||
static gpio_isr_param_t io19_param = {
|
||||
.gpio_num = GPIO_NUM_19,
|
||||
.isr_cnt = 0,
|
||||
};
|
||||
gpio_config_t io_conf;
|
||||
io_conf.intr_type = GPIO_INTR_DISABLE;
|
||||
io_conf.mode = GPIO_MODE_INPUT_OUTPUT;
|
||||
io_conf.pin_bit_mask = (1ULL << test_io18) | (1ULL << test_io19);
|
||||
io_conf.pull_down_en = 0;
|
||||
io_conf.pull_up_en = 1;
|
||||
TEST_ESP_OK(gpio_config(&io_conf));
|
||||
TEST_ESP_OK(gpio_set_level(test_io18, 0));
|
||||
TEST_ESP_OK(gpio_set_level(test_io19, 0));
|
||||
TEST_ESP_OK(gpio_install_isr_service(0));
|
||||
TEST_ESP_OK(gpio_set_intr_type(test_io18, GPIO_INTR_ANYEDGE));
|
||||
TEST_ESP_OK(gpio_set_intr_type(test_io19, GPIO_INTR_NEGEDGE));
|
||||
TEST_ESP_OK(gpio_isr_handler_add(test_io18, gpio_isr_handler, (void*)&io18_param));
|
||||
TEST_ESP_OK(gpio_isr_handler_add(test_io19, gpio_isr_handler, (void*)&io19_param));
|
||||
printf("Triggering the interrupt of GPIO18\n");
|
||||
vTaskDelay(1000 / portTICK_RATE_MS);
|
||||
//Rising edge
|
||||
TEST_ESP_OK(gpio_set_level(test_io18, 1));
|
||||
printf("Disable the interrupt of GPIO18");
|
||||
vTaskDelay(100 / portTICK_RATE_MS);
|
||||
//Disable GPIO18 interrupt, GPIO18 will not respond to the next falling edge interrupt.
|
||||
TEST_ESP_OK(gpio_intr_disable(test_io18));
|
||||
vTaskDelay(100 / portTICK_RATE_MS);
|
||||
//Falling edge
|
||||
TEST_ESP_OK(gpio_set_level(test_io18, 0));
|
||||
|
||||
printf("Triggering the interrupt of GPIO19\n");
|
||||
vTaskDelay(100 / portTICK_RATE_MS);
|
||||
TEST_ESP_OK(gpio_set_level(test_io19, 1));
|
||||
vTaskDelay(100 / portTICK_RATE_MS);
|
||||
//Falling edge
|
||||
TEST_ESP_OK(gpio_set_level(test_io19, 0));
|
||||
vTaskDelay(100 / portTICK_RATE_MS);
|
||||
TEST_ESP_OK(gpio_isr_handler_remove(test_io18));
|
||||
TEST_ESP_OK(gpio_isr_handler_remove(test_io19));
|
||||
gpio_uninstall_isr_service();
|
||||
TEST_ASSERT((io18_param.isr_cnt == 1) && (io19_param.isr_cnt == 1));
|
||||
}
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "freertos/task.h"
|
||||
#include "driver/i2s.h"
|
||||
#include "unity.h"
|
||||
#include "math.h"
|
||||
|
||||
#define SAMPLE_RATE (36000)
|
||||
#define SAMPLE_BITS (16)
|
||||
@@ -18,6 +19,7 @@
|
||||
#define SLAVE_WS_IO 26
|
||||
#define DATA_IN_IO 21
|
||||
#define DATA_OUT_IO 22
|
||||
#define PERCENT_DIFF 0.0001
|
||||
|
||||
/**
|
||||
* i2s initialize test
|
||||
@@ -267,3 +269,54 @@ TEST_CASE("I2S memory leaking test", "[i2s]")
|
||||
vTaskDelay(100 / portTICK_PERIOD_MS);
|
||||
TEST_ASSERT(initial_size == esp_get_free_heap_size());
|
||||
}
|
||||
|
||||
/*
|
||||
* The I2S APLL clock variation test used to test the difference between the different sample rates, different bits per sample
|
||||
* and the APLL clock generate for it. The TEST_CASE passes PERCENT_DIFF variation from the provided sample rate in APLL generated clock
|
||||
* The percentage difference calculated as (mod((obtained clock rate - desired clock rate)/(desired clock rate))) * 100.
|
||||
*/
|
||||
TEST_CASE("I2S APLL clock variation test", "[i2s]")
|
||||
{
|
||||
i2s_pin_config_t pin_config = {
|
||||
.bck_io_num = MASTER_BCK_IO,
|
||||
.ws_io_num = MASTER_WS_IO,
|
||||
.data_out_num = DATA_OUT_IO,
|
||||
.data_in_num = -1
|
||||
};
|
||||
|
||||
i2s_config_t i2s_config = {
|
||||
.mode = I2S_MODE_MASTER | I2S_MODE_TX,
|
||||
.sample_rate = SAMPLE_RATE,
|
||||
.bits_per_sample = SAMPLE_BITS,
|
||||
.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT,
|
||||
.communication_format = I2S_COMM_FORMAT_I2S,
|
||||
.dma_buf_count = 6,
|
||||
.dma_buf_len = 60,
|
||||
.use_apll = true,
|
||||
.intr_alloc_flags = 0,
|
||||
};
|
||||
|
||||
TEST_ESP_OK(i2s_driver_install(I2S_NUM_0, &i2s_config, 0, NULL));
|
||||
TEST_ESP_OK(i2s_set_pin(I2S_NUM_0, &pin_config));
|
||||
TEST_ESP_OK(i2s_driver_uninstall(I2S_NUM_0));
|
||||
int initial_size = esp_get_free_heap_size();
|
||||
|
||||
uint32_t sample_rate_arr[8] = { 10675, 11025, 16000, 22050, 32000, 44100, 48000, 96000 };
|
||||
int bits_per_sample_arr[3] = { 16, 24, 32 };
|
||||
|
||||
for (int i = 0; i < (sizeof(sample_rate_arr)/sizeof(sample_rate_arr[0])); i++) {
|
||||
for (int j = 0; j < (sizeof(bits_per_sample_arr)/sizeof(bits_per_sample_arr[0])); j++) {
|
||||
i2s_config.sample_rate = sample_rate_arr[i];
|
||||
i2s_config.bits_per_sample = bits_per_sample_arr[j];
|
||||
|
||||
TEST_ESP_OK(i2s_driver_install(I2S_NUM_0, &i2s_config, 0, NULL));
|
||||
TEST_ESP_OK(i2s_set_pin(I2S_NUM_0, &pin_config));
|
||||
TEST_ASSERT((fabs((i2s_get_clk(I2S_NUM_0) - sample_rate_arr[i]))/(sample_rate_arr[i]))*100 < PERCENT_DIFF);
|
||||
TEST_ESP_OK(i2s_driver_uninstall(I2S_NUM_0));
|
||||
TEST_ASSERT(initial_size == esp_get_free_heap_size());
|
||||
}
|
||||
}
|
||||
|
||||
vTaskDelay(100 / portTICK_PERIOD_MS);
|
||||
TEST_ASSERT(initial_size == esp_get_free_heap_size());
|
||||
}
|
||||
|
||||
@@ -909,6 +909,9 @@ static IRAM_ATTR void spi_transmit_polling_measure(spi_device_handle_t spi, spi_
|
||||
|
||||
TEST_CASE("spi_speed","[spi]")
|
||||
{
|
||||
#ifdef CONFIG_FREERTOS_CHECK_PORT_CRITICAL_COMPLIANCE
|
||||
return;
|
||||
#endif
|
||||
uint32_t t_flight;
|
||||
//to get rid of the influence of randomly interrupts, we measured the performance by median value
|
||||
uint32_t t_flight_sorted[TEST_TIMES];
|
||||
|
||||
@@ -39,19 +39,19 @@ static const char* TIMER_TAG = "timer_group";
|
||||
static timg_dev_t *TG[2] = {&TIMERG0, &TIMERG1};
|
||||
static portMUX_TYPE timer_spinlock[TIMER_GROUP_MAX] = {portMUX_INITIALIZER_UNLOCKED, portMUX_INITIALIZER_UNLOCKED};
|
||||
|
||||
#define TIMER_ENTER_CRITICAL(mux) portENTER_CRITICAL(mux);
|
||||
#define TIMER_EXIT_CRITICAL(mux) portEXIT_CRITICAL(mux);
|
||||
#define TIMER_ENTER_CRITICAL(mux) portENTER_CRITICAL_SAFE(mux);
|
||||
#define TIMER_EXIT_CRITICAL(mux) portEXIT_CRITICAL_SAFE(mux);
|
||||
|
||||
esp_err_t timer_get_counter_value(timer_group_t group_num, timer_idx_t timer_num, uint64_t* timer_val)
|
||||
{
|
||||
TIMER_CHECK(group_num < TIMER_GROUP_MAX, TIMER_GROUP_NUM_ERROR, ESP_ERR_INVALID_ARG);
|
||||
TIMER_CHECK(timer_num < TIMER_MAX, TIMER_NUM_ERROR, ESP_ERR_INVALID_ARG);
|
||||
TIMER_CHECK(timer_val != NULL, TIMER_PARAM_ADDR_ERROR, ESP_ERR_INVALID_ARG);
|
||||
portENTER_CRITICAL(&timer_spinlock[group_num]);
|
||||
portENTER_CRITICAL_SAFE(&timer_spinlock[group_num]);
|
||||
TG[group_num]->hw_timer[timer_num].update = 1;
|
||||
*timer_val = ((uint64_t) TG[group_num]->hw_timer[timer_num].cnt_high << 32)
|
||||
| (TG[group_num]->hw_timer[timer_num].cnt_low);
|
||||
portEXIT_CRITICAL(&timer_spinlock[group_num]);
|
||||
portEXIT_CRITICAL_SAFE(&timer_spinlock[group_num]);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
@@ -154,10 +154,10 @@ esp_err_t timer_get_alarm_value(timer_group_t group_num, timer_idx_t timer_num,
|
||||
TIMER_CHECK(group_num < TIMER_GROUP_MAX, TIMER_GROUP_NUM_ERROR, ESP_ERR_INVALID_ARG);
|
||||
TIMER_CHECK(timer_num < TIMER_MAX, TIMER_NUM_ERROR, ESP_ERR_INVALID_ARG);
|
||||
TIMER_CHECK(alarm_value != NULL, TIMER_PARAM_ADDR_ERROR, ESP_ERR_INVALID_ARG);
|
||||
portENTER_CRITICAL(&timer_spinlock[group_num]);
|
||||
portENTER_CRITICAL_SAFE(&timer_spinlock[group_num]);
|
||||
*alarm_value = ((uint64_t) TG[group_num]->hw_timer[timer_num].alarm_high << 32)
|
||||
| (TG[group_num]->hw_timer[timer_num].alarm_low);
|
||||
portEXIT_CRITICAL(&timer_spinlock[group_num]);
|
||||
portEXIT_CRITICAL_SAFE(&timer_spinlock[group_num]);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -691,9 +691,9 @@ esp_err_t uart_intr_config(uart_port_t uart_num, const uart_intr_config_t *intr_
|
||||
//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);
|
||||
UART[uart_num]->conf1.rx_tout_thrhd = (intr_conf->rx_timeout_thresh * UART_TOUT_REF_FACTOR_DEFAULT);
|
||||
} else {
|
||||
UART[uart_num]->conf1.rx_tout_thrhd = ((intr_conf->rx_timeout_thresh) & UART_RX_TOUT_THRHD_V);
|
||||
UART[uart_num]->conf1.rx_tout_thrhd = intr_conf->rx_timeout_thresh;
|
||||
}
|
||||
UART[uart_num]->conf1.rx_tout_en = 1;
|
||||
} else {
|
||||
@@ -734,14 +734,19 @@ static void uart_rx_intr_handler_default(void *param)
|
||||
uart_obj_t *p_uart = (uart_obj_t*) param;
|
||||
uint8_t uart_num = p_uart->uart_num;
|
||||
uart_dev_t* uart_reg = UART[uart_num];
|
||||
int rx_fifo_len = uart_reg->status.rxfifo_cnt;
|
||||
int rx_fifo_len = 0;
|
||||
uint8_t buf_idx = 0;
|
||||
uint32_t uart_intr_status = UART[uart_num]->int_st.val;
|
||||
uint32_t uart_intr_status = 0;
|
||||
uart_event_t uart_event;
|
||||
portBASE_TYPE HPTaskAwoken = 0;
|
||||
static uint8_t pat_flg = 0;
|
||||
while(uart_intr_status != 0x0) {
|
||||
buf_idx = 0;
|
||||
while(1) {
|
||||
uart_intr_status = uart_reg->int_st.val;
|
||||
// The `continue statement` may cause the interrupt to loop infinitely
|
||||
// we exit the interrupt here
|
||||
if(uart_intr_status == 0) {
|
||||
break;
|
||||
}
|
||||
uart_event.type = UART_EVENT_MAX;
|
||||
if(uart_intr_status & UART_TXFIFO_EMPTY_INT_ST_M) {
|
||||
uart_clear_intr_status(uart_num, UART_TXFIFO_EMPTY_INT_CLR_M);
|
||||
@@ -753,15 +758,12 @@ static void uart_rx_intr_handler_default(void *param)
|
||||
if(p_uart->tx_waiting_fifo == true && p_uart->tx_buf_size == 0) {
|
||||
p_uart->tx_waiting_fifo = false;
|
||||
xSemaphoreGiveFromISR(p_uart->tx_fifo_sem, &HPTaskAwoken);
|
||||
if(HPTaskAwoken == pdTRUE) {
|
||||
portYIELD_FROM_ISR();
|
||||
}
|
||||
} else {
|
||||
//We don't use TX ring buffer, because the size is zero.
|
||||
if(p_uart->tx_buf_size == 0) {
|
||||
continue;
|
||||
}
|
||||
int tx_fifo_rem = UART_FIFO_LEN - UART[uart_num]->status.txfifo_cnt;
|
||||
int tx_fifo_rem = UART_FIFO_LEN - uart_reg->status.txfifo_cnt;
|
||||
bool en_tx_flg = false;
|
||||
//We need to put a loop here, in case all the buffer items are very short.
|
||||
//That would cause a watch_dog reset because empty interrupt happens so often.
|
||||
@@ -782,9 +784,6 @@ static void uart_rx_intr_handler_default(void *param)
|
||||
}
|
||||
//We have saved the data description from the 1st item, return buffer.
|
||||
vRingbufferReturnItemFromISR(p_uart->tx_ring_buf, p_uart->tx_head, &HPTaskAwoken);
|
||||
if(HPTaskAwoken == pdTRUE) {
|
||||
portYIELD_FROM_ISR();
|
||||
}
|
||||
}else if(p_uart->tx_ptr == NULL) {
|
||||
//Update the TX item pointer, we will need this to return item to buffer.
|
||||
p_uart->tx_ptr = (uint8_t*) p_uart->tx_head;
|
||||
@@ -817,9 +816,6 @@ static void uart_rx_intr_handler_default(void *param)
|
||||
if (p_uart->tx_len_cur == 0) {
|
||||
//Return item to ring buffer.
|
||||
vRingbufferReturnItemFromISR(p_uart->tx_ring_buf, p_uart->tx_head, &HPTaskAwoken);
|
||||
if(HPTaskAwoken == pdTRUE) {
|
||||
portYIELD_FROM_ISR();
|
||||
}
|
||||
p_uart->tx_head = NULL;
|
||||
p_uart->tx_ptr = NULL;
|
||||
//Sending item done, now we need to send break if there is a record.
|
||||
@@ -862,8 +858,8 @@ static void uart_rx_intr_handler_default(void *param)
|
||||
}
|
||||
if (p_uart->rx_buffer_full_flg == false) {
|
||||
//We have to read out all data in RX FIFO to clear the interrupt signal
|
||||
while (buf_idx < rx_fifo_len) {
|
||||
p_uart->rx_data_buf[buf_idx++] = uart_reg->fifo.rw_byte;
|
||||
for(buf_idx = 0; buf_idx < rx_fifo_len; buf_idx++) {
|
||||
p_uart->rx_data_buf[buf_idx] = uart_reg->fifo.rw_byte;
|
||||
}
|
||||
uint8_t pat_chr = uart_reg->at_cmd_char.data;
|
||||
int pat_num = uart_reg->at_cmd_char.char_num;
|
||||
@@ -923,9 +919,6 @@ static void uart_rx_intr_handler_default(void *param)
|
||||
p_uart->rx_buffered_len += p_uart->rx_stash_len;
|
||||
UART_EXIT_CRITICAL_ISR(&uart_spinlock[uart_num]);
|
||||
}
|
||||
if(HPTaskAwoken == pdTRUE) {
|
||||
portYIELD_FROM_ISR();
|
||||
}
|
||||
} else {
|
||||
uart_disable_intr_mask_from_isr(uart_num, UART_RXFIFO_FULL_INT_ENA_M | UART_RXFIFO_TOUT_INT_ENA_M);
|
||||
uart_clear_intr_status(uart_num, UART_RXFIFO_FULL_INT_CLR_M | UART_RXFIFO_TOUT_INT_CLR_M);
|
||||
@@ -981,9 +974,6 @@ static void uart_rx_intr_handler_default(void *param)
|
||||
p_uart->tx_waiting_brk = 0;
|
||||
} else {
|
||||
xSemaphoreGiveFromISR(p_uart->tx_brk_sem, &HPTaskAwoken);
|
||||
if(HPTaskAwoken == pdTRUE) {
|
||||
portYIELD_FROM_ISR();
|
||||
}
|
||||
}
|
||||
} else if(uart_intr_status & UART_TX_BRK_IDLE_DONE_INT_ST_M) {
|
||||
uart_disable_intr_mask_from_isr(uart_num, UART_TX_BRK_IDLE_DONE_INT_ENA_M);
|
||||
@@ -1014,9 +1004,6 @@ static void uart_rx_intr_handler_default(void *param)
|
||||
UART_EXIT_CRITICAL_ISR(&uart_spinlock[uart_num]);
|
||||
}
|
||||
xSemaphoreGiveFromISR(p_uart_obj[uart_num]->tx_done_sem, &HPTaskAwoken);
|
||||
if (HPTaskAwoken == pdTRUE) {
|
||||
portYIELD_FROM_ISR();
|
||||
}
|
||||
} else {
|
||||
uart_reg->int_clr.val = uart_intr_status; /*simply clear all other intr status*/
|
||||
uart_event.type = UART_EVENT_MAX;
|
||||
@@ -1026,11 +1013,10 @@ static void uart_rx_intr_handler_default(void *param)
|
||||
if (pdFALSE == xQueueSendFromISR(p_uart->xQueueUart, (void * )&uart_event, &HPTaskAwoken)) {
|
||||
ESP_EARLY_LOGV(UART_TAG, "UART event queue full");
|
||||
}
|
||||
if(HPTaskAwoken == pdTRUE) {
|
||||
portYIELD_FROM_ISR();
|
||||
}
|
||||
}
|
||||
uart_intr_status = uart_reg->int_st.val;
|
||||
}
|
||||
if(HPTaskAwoken == pdTRUE) {
|
||||
portYIELD_FROM_ISR();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1040,20 +1026,27 @@ esp_err_t uart_wait_tx_done(uart_port_t uart_num, TickType_t ticks_to_wait)
|
||||
UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_FAIL);
|
||||
UART_CHECK((p_uart_obj[uart_num]), "uart driver error", ESP_FAIL);
|
||||
BaseType_t res;
|
||||
portTickType ticks_end = xTaskGetTickCount() + ticks_to_wait;
|
||||
portTickType ticks_start = xTaskGetTickCount();
|
||||
//Take tx_mux
|
||||
res = xSemaphoreTake(p_uart_obj[uart_num]->tx_mux, (portTickType)ticks_to_wait);
|
||||
if(res == pdFALSE) {
|
||||
return ESP_ERR_TIMEOUT;
|
||||
}
|
||||
ticks_to_wait = ticks_end - xTaskGetTickCount();
|
||||
xSemaphoreTake(p_uart_obj[uart_num]->tx_done_sem, 0);
|
||||
ticks_to_wait = ticks_end - xTaskGetTickCount();
|
||||
if(UART[uart_num]->status.txfifo_cnt == 0) {
|
||||
typeof(UART0.status) status = UART[uart_num]->status;
|
||||
//Wait txfifo_cnt = 0, and the transmitter state machine is in idle state.
|
||||
if(status.txfifo_cnt == 0 && status.st_utx_out == 0) {
|
||||
xSemaphoreGive(p_uart_obj[uart_num]->tx_mux);
|
||||
return ESP_OK;
|
||||
}
|
||||
uart_enable_intr_mask(uart_num, UART_TX_DONE_INT_ENA_M);
|
||||
|
||||
TickType_t ticks_end = xTaskGetTickCount();
|
||||
if (ticks_end - ticks_start > ticks_to_wait) {
|
||||
ticks_to_wait = 0;
|
||||
} else {
|
||||
ticks_to_wait = ticks_to_wait - (ticks_end - ticks_start);
|
||||
}
|
||||
//take 2nd tx_done_sem, wait given from ISR
|
||||
res = xSemaphoreTake(p_uart_obj[uart_num]->tx_done_sem, (portTickType)ticks_to_wait);
|
||||
if(res == pdFALSE) {
|
||||
@@ -1543,7 +1536,13 @@ esp_err_t uart_set_rx_timeout(uart_port_t uart_num, const uint8_t tout_thresh)
|
||||
// The tout_thresh = 1, defines TOUT interrupt timeout equal to
|
||||
// transmission time of one symbol (~11 bit) on current baudrate
|
||||
if (tout_thresh > 0) {
|
||||
UART[uart_num]->conf1.rx_tout_thrhd = (tout_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 = tout_thresh * UART_TOUT_REF_FACTOR_DEFAULT;
|
||||
} else {
|
||||
UART[uart_num]->conf1.rx_tout_thrhd = tout_thresh;
|
||||
}
|
||||
UART[uart_num]->conf1.rx_tout_en = 1;
|
||||
} else {
|
||||
UART[uart_num]->conf1.rx_tout_en = 0;
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
#include <assert.h>
|
||||
#include "esp_efuse_table.h"
|
||||
|
||||
// md5_digest_table 544d434da010ce22f7db1b14d38e1d66
|
||||
// md5_digest_table 2e23344575b3d07f01ecb695294e9770
|
||||
// This file was generated from the file esp_efuse_table.csv. DO NOT CHANGE THIS FILE MANUALLY.
|
||||
// If you want to change some fields, you need to change esp_efuse_table.csv file
|
||||
// then run `efuse_common_table` or `efuse_custom_table` command it will generate this file.
|
||||
@@ -151,6 +151,10 @@ static const esp_efuse_desc_t CHIP_VER_REV1[] = {
|
||||
{EFUSE_BLK0, 111, 1}, // EFUSE_RD_CHIP_VER_REV1,
|
||||
};
|
||||
|
||||
static const esp_efuse_desc_t CHIP_VER_REV2[] = {
|
||||
{EFUSE_BLK0, 180, 1}, // EFUSE_RD_CHIP_VER_REV2,
|
||||
};
|
||||
|
||||
static const esp_efuse_desc_t XPD_SDIO_REG[] = {
|
||||
{EFUSE_BLK0, 142, 1}, // EFUSE_RD_XPD_SDIO_REG,
|
||||
};
|
||||
@@ -336,6 +340,11 @@ const esp_efuse_desc_t* ESP_EFUSE_CHIP_VER_REV1[] = {
|
||||
NULL
|
||||
};
|
||||
|
||||
const esp_efuse_desc_t* ESP_EFUSE_CHIP_VER_REV2[] = {
|
||||
&CHIP_VER_REV2[0], // EFUSE_RD_CHIP_VER_REV2
|
||||
NULL
|
||||
};
|
||||
|
||||
const esp_efuse_desc_t* ESP_EFUSE_XPD_SDIO_REG[] = {
|
||||
&XPD_SDIO_REG[0], // EFUSE_RD_XPD_SDIO_REG
|
||||
NULL
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
##########################################################################
|
||||
# *) The value MAX_BLK_LEN depends on CONFIG_EFUSE_MAX_BLK_LEN, will be replaced with "None" - 256. "3/4" - 192. "REPEAT" - 128.
|
||||
# !!!!!!!!!!! #
|
||||
# After editing this file, run the command manually "make efuse_common_table" or "idf.py efuse_common_table"
|
||||
# After editing this file, run the command manually "make efuse_common_table" or "idf.py efuse_common_table"
|
||||
# this will generate new source files, next rebuild all the sources.
|
||||
# !!!!!!!!!!! #
|
||||
|
||||
@@ -36,11 +36,11 @@ ABS_DONE_0, EFUSE_BLK0, 196, 1, Secure boot is enabled for
|
||||
ENCRYPT_FLASH_KEY, EFUSE_BLK1, 0, MAX_BLK_LEN, Flash encrypt. Key. (length = "None" - 256. "3/4" - 192. "REPEAT" - 128)
|
||||
ENCRYPT_CONFIG, EFUSE_BLK0, 188, 4, Flash encrypt. EFUSE_FLASH_CRYPT_CONFIG_M
|
||||
|
||||
DISABLE_DL_ENCRYPT, EFUSE_BLK0, 199, 1, Flash encrypt. Disable UART bootloader encryption. EFUSE_DISABLE_DL_ENCRYPT.
|
||||
DISABLE_DL_DECRYPT, EFUSE_BLK0, 200, 1, Flash encrypt. Disable UART bootloader decryption. EFUSE_DISABLE_DL_DECRYPT.
|
||||
DISABLE_DL_CACHE, EFUSE_BLK0, 201, 1, Flash encrypt. Disable UART bootloader MMU cache. EFUSE_DISABLE_DL_CACHE.
|
||||
DISABLE_JTAG, EFUSE_BLK0, 198, 1, Flash encrypt. Disable JTAG. EFUSE_RD_DISABLE_JTAG.
|
||||
CONSOLE_DEBUG_DISABLE, EFUSE_BLK0, 194, 1, Flash encrypt. Disable ROM BASIC interpreter fallback. EFUSE_RD_CONSOLE_DEBUG_DISABLE.
|
||||
DISABLE_DL_ENCRYPT, EFUSE_BLK0, 199, 1, Flash encrypt. Disable UART bootloader encryption. EFUSE_DISABLE_DL_ENCRYPT.
|
||||
DISABLE_DL_DECRYPT, EFUSE_BLK0, 200, 1, Flash encrypt. Disable UART bootloader decryption. EFUSE_DISABLE_DL_DECRYPT.
|
||||
DISABLE_DL_CACHE, EFUSE_BLK0, 201, 1, Flash encrypt. Disable UART bootloader MMU cache. EFUSE_DISABLE_DL_CACHE.
|
||||
DISABLE_JTAG, EFUSE_BLK0, 198, 1, Flash encrypt. Disable JTAG. EFUSE_RD_DISABLE_JTAG.
|
||||
CONSOLE_DEBUG_DISABLE, EFUSE_BLK0, 194, 1, Flash encrypt. Disable ROM BASIC interpreter fallback. EFUSE_RD_CONSOLE_DEBUG_DISABLE.
|
||||
FLASH_CRYPT_CNT, EFUSE_BLK0, 20, 7, Flash encrypt. Flash encryption is enabled if this field has an odd number of bits set. EFUSE_FLASH_CRYPT_CNT.
|
||||
|
||||
# Write protection #
|
||||
@@ -53,7 +53,7 @@ WR_DIS_BLK3, EFUSE_BLK0, 9, 1, Write protection for EFUSE_B
|
||||
# Read protection #
|
||||
###################
|
||||
RD_DIS_BLK1, EFUSE_BLK0, 16, 1, Flash encrypt. efuse_key_read_protected. EFUSE_RD_DIS_BLK1
|
||||
RD_DIS_BLK2, EFUSE_BLK0, 17, 1, Security boot. efuse_key_read_protected. EFUSE_RD_DIS_BLK2
|
||||
RD_DIS_BLK2, EFUSE_BLK0, 17, 1, Security boot. efuse_key_read_protected. EFUSE_RD_DIS_BLK2
|
||||
RD_DIS_BLK3, EFUSE_BLK0, 18, 1, Read protection for EFUSE_BLK3. EFUSE_RD_DIS_BLK3
|
||||
|
||||
# Chip info #
|
||||
@@ -64,6 +64,7 @@ CHIP_VER_PKG, EFUSE_BLK0, 105, 3, EFUSE_RD_CHIP_VER_PKG
|
||||
CHIP_CPU_FREQ_LOW, EFUSE_BLK0, 108, 1, EFUSE_RD_CHIP_CPU_FREQ_LOW
|
||||
CHIP_CPU_FREQ_RATED, EFUSE_BLK0, 109, 1, EFUSE_RD_CHIP_CPU_FREQ_RATED
|
||||
CHIP_VER_REV1, EFUSE_BLK0, 111, 1, EFUSE_RD_CHIP_VER_REV1
|
||||
CHIP_VER_REV2, EFUSE_BLK0, 180, 1, EFUSE_RD_CHIP_VER_REV2
|
||||
XPD_SDIO_REG, EFUSE_BLK0, 142, 1, EFUSE_RD_XPD_SDIO_REG
|
||||
SDIO_TIEH, EFUSE_BLK0, 143, 1, EFUSE_RD_SDIO_TIEH
|
||||
SDIO_FORCE, EFUSE_BLK0, 144, 1, EFUSE_RD_SDIO_FORCE
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 7 and column 87.
|
@@ -17,7 +17,7 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
// md5_digest_table 544d434da010ce22f7db1b14d38e1d66
|
||||
// md5_digest_table 2e23344575b3d07f01ecb695294e9770
|
||||
// This file was generated from the file esp_efuse_table.csv. DO NOT CHANGE THIS FILE MANUALLY.
|
||||
// If you want to change some fields, you need to change esp_efuse_table.csv file
|
||||
// then run `efuse_common_table` or `efuse_custom_table` command it will generate this file.
|
||||
@@ -52,6 +52,7 @@ extern const esp_efuse_desc_t* ESP_EFUSE_CHIP_VER_PKG[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_CHIP_CPU_FREQ_LOW[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_CHIP_CPU_FREQ_RATED[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_CHIP_VER_REV1[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_CHIP_VER_REV2[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_XPD_SDIO_REG[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_SDIO_TIEH[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_SDIO_FORCE[];
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include "esp_log.h"
|
||||
#include "soc/efuse_reg.h"
|
||||
#include "bootloader_random.h"
|
||||
#include "soc/apb_ctrl_reg.h"
|
||||
|
||||
const static char *TAG = "efuse";
|
||||
|
||||
@@ -31,8 +32,29 @@ const static char *TAG = "efuse";
|
||||
// Returns chip version from efuse
|
||||
uint8_t esp_efuse_get_chip_ver(void)
|
||||
{
|
||||
uint8_t chip_ver;
|
||||
esp_efuse_read_field_blob(ESP_EFUSE_CHIP_VER_REV1, &chip_ver, 1);
|
||||
uint8_t eco_bit0, eco_bit1, eco_bit2;
|
||||
esp_efuse_read_field_blob(ESP_EFUSE_CHIP_VER_REV1, &eco_bit0, 1);
|
||||
esp_efuse_read_field_blob(ESP_EFUSE_CHIP_VER_REV2, &eco_bit1, 1);
|
||||
eco_bit2 = (REG_READ(APB_CTRL_DATE_REG) & 80000000) >> 31;
|
||||
uint32_t combine_value = (eco_bit2 << 2) | (eco_bit1 << 1) | eco_bit0;
|
||||
uint8_t chip_ver = 0;
|
||||
switch (combine_value) {
|
||||
case 0:
|
||||
chip_ver = 0;
|
||||
break;
|
||||
case 1:
|
||||
chip_ver = 1;
|
||||
break;
|
||||
case 3:
|
||||
chip_ver = 2;
|
||||
break;
|
||||
case 7:
|
||||
chip_ver = 3;
|
||||
break;
|
||||
default:
|
||||
chip_ver = 0;
|
||||
break;
|
||||
}
|
||||
return chip_ver;
|
||||
}
|
||||
|
||||
@@ -104,13 +126,14 @@ void esp_efuse_write_random_key(uint32_t blk_wdata0_reg)
|
||||
} else { // 3/4 Coding Scheme
|
||||
bootloader_fill_random(raw, sizeof(raw));
|
||||
esp_err_t r = esp_efuse_apply_34_encoding(raw, buf, sizeof(raw));
|
||||
(void) r;
|
||||
assert(r == ESP_OK);
|
||||
}
|
||||
|
||||
ESP_LOGV(TAG, "Writing random values to address 0x%08x", blk_wdata0_reg);
|
||||
for (int i = 0; i < 8; i++) {
|
||||
ESP_LOGV(TAG, "EFUSE_BLKx_WDATA%d_REG = 0x%08x", i, buf[i]);
|
||||
REG_WRITE(blk_wdata0_reg + 4*i, buf[i]);
|
||||
REG_WRITE(blk_wdata0_reg + 4 * i, buf[i]);
|
||||
}
|
||||
bzero(buf, sizeof(buf));
|
||||
bzero(raw, sizeof(raw));
|
||||
|
||||
@@ -6,6 +6,34 @@ menu "ESP32-specific"
|
||||
default "y" if IDF_TARGET="esp32"
|
||||
default "n"
|
||||
|
||||
choice ESP32_REV_MIN
|
||||
prompt "Minimum Supported ESP32 Revision"
|
||||
default ESP32_REV_MIN_0
|
||||
help
|
||||
Minimum revision that ESP-IDF would support.
|
||||
ESP-IDF performs different strategy on different esp32 revision.
|
||||
|
||||
config ESP32_REV_MIN_0
|
||||
bool "Rev 0"
|
||||
config ESP32_REV_MIN_1
|
||||
bool "Rev 1"
|
||||
config ESP32_REV_MIN_2
|
||||
bool "Rev 2"
|
||||
config ESP32_REV_MIN_3
|
||||
bool "Rev 3"
|
||||
endchoice
|
||||
|
||||
config ESP32_REV_MIN
|
||||
int
|
||||
default 0 if ESP32_REV_MIN_0
|
||||
default 1 if ESP32_REV_MIN_1
|
||||
default 2 if ESP32_REV_MIN_2
|
||||
default 3 if ESP32_REV_MIN_3
|
||||
|
||||
config ESP32_DPORT_WORKAROUND
|
||||
bool
|
||||
default "y" if !FREERTOS_UNICORE && ESP32_REV_MIN < 2
|
||||
|
||||
choice ESP32_DEFAULT_CPU_FREQ_MHZ
|
||||
prompt "CPU frequency"
|
||||
default ESP32_DEFAULT_CPU_FREQ_160
|
||||
@@ -239,16 +267,84 @@ menu "ESP32-specific"
|
||||
bool "VSPI host (SPI3)"
|
||||
endchoice
|
||||
|
||||
config PICO_PSRAM_CS_IO
|
||||
int "PSRAM CS IO for ESP32-PICO chip"
|
||||
depends on SPIRAM_SUPPORT
|
||||
range 0 33
|
||||
default 10
|
||||
help
|
||||
When ESP32-PICO chip connect a external psram, the clock IO and data IO is fixed, but the CS IO can be
|
||||
any unused GPIO, user can config it based on hardware design.
|
||||
menu "PSRAM clock and cs IO for ESP32-DOWD"
|
||||
|
||||
endmenu
|
||||
config D0WD_PSRAM_CLK_IO
|
||||
int "PSRAM CLK IO number"
|
||||
depends on SPIRAM_SUPPORT
|
||||
range 0 33
|
||||
default 17
|
||||
help
|
||||
The PSRAM CLOCK IO can be any unused GPIO, user can config it based on hardware design. If user use
|
||||
1.8V flash and 1.8V psram, this value can only be one of 6, 7, 8, 9, 10, 11, 16, 17.
|
||||
|
||||
config D0WD_PSRAM_CS_IO
|
||||
int "PSRAM CS IO number"
|
||||
depends on SPIRAM_SUPPORT
|
||||
range 0 33
|
||||
default 16
|
||||
help
|
||||
The PSRAM CS IO can be any unused GPIO, user can config it based on hardware design. If user use
|
||||
1.8V flash and 1.8V psram, this value can only be one of 6, 7, 8, 9, 10, 11, 16, 17.
|
||||
endmenu
|
||||
|
||||
menu "PSRAM clock and cs IO for ESP32-D2WD"
|
||||
|
||||
config D2WD_PSRAM_CLK_IO
|
||||
int "PSRAM CLK IO number"
|
||||
depends on SPIRAM_SUPPORT
|
||||
range 0 33
|
||||
default 9
|
||||
help
|
||||
User can config it based on hardware design. For ESP32-D2WD chip, the psram can only be 1.8V psram,
|
||||
so this value can only be one of 6, 7, 8, 9, 10, 11, 16, 17.
|
||||
|
||||
config D2WD_PSRAM_CS_IO
|
||||
int "PSRAM CS IO number"
|
||||
depends on SPIRAM_SUPPORT
|
||||
range 0 33
|
||||
default 10
|
||||
help
|
||||
User can config it based on hardware design. For ESP32-D2WD chip, the psram can only be 1.8V psram,
|
||||
so this value can only be one of 6, 7, 8, 9, 10, 11, 16, 17.
|
||||
endmenu
|
||||
|
||||
menu "PSRAM clock and cs IO for ESP32-PICO"
|
||||
|
||||
config PICO_PSRAM_CS_IO
|
||||
int "PSRAM CS IO number"
|
||||
depends on SPIRAM_SUPPORT
|
||||
range 0 33
|
||||
default 10
|
||||
help
|
||||
The PSRAM CS IO can be any unused GPIO, user can config it based on hardware design.
|
||||
|
||||
For ESP32-PICO chip, the psram share clock with flash, so user do not need to configure the clock
|
||||
IO.
|
||||
For the reference hardware design, please refer to
|
||||
https://www.espressif.com/sites/default/files/documentation/esp32-pico-d4_datasheet_en.pdf
|
||||
|
||||
endmenu
|
||||
|
||||
config SPIRAM_SPIWP_SD3_PIN
|
||||
int "SPI PSRAM WP(SD3) Pin when customising pins via eFuse (read help)"
|
||||
depends on FLASHMODE_DIO || FLASHMODE_DOUT
|
||||
range 0 33
|
||||
default 7
|
||||
help
|
||||
This value is ignored unless flash mode is set to DIO or DOUT and the SPI flash pins have been
|
||||
overriden by setting the eFuses SPI_PAD_CONFIG_xxx.
|
||||
|
||||
When this is the case, the eFuse config only defines 3 of the 4 Quad I/O data pins. The WP pin (aka
|
||||
ESP32 pin "SD_DATA_3" or SPI flash pin "IO2") is not specified in eFuse. And the psram only has QPI
|
||||
mode, the WP pin is necessary, so we need to configure this value here.
|
||||
|
||||
When flash mode is set to QIO or QOUT, the PSRAM WP pin will be set as the value configured in
|
||||
bootloader.
|
||||
|
||||
For ESP32-PICO chip, the default value of this config should be 7.
|
||||
|
||||
endmenu # "SPI RAM config"
|
||||
|
||||
config MEMMAP_TRACEMEM
|
||||
bool
|
||||
@@ -1006,7 +1102,8 @@ menu Wi-Fi
|
||||
|
||||
config ESP32_WIFI_DYNAMIC_RX_BUFFER_NUM
|
||||
int "Max number of WiFi dynamic RX buffers"
|
||||
range 0 128
|
||||
range 0 128 if !LWIP_WND_SCALE
|
||||
range 0 1024 if LWIP_WND_SCALE
|
||||
default 32
|
||||
help
|
||||
Set the number of WiFi dynamic RX buffers, 0 means unlimited RX buffers will be allocated
|
||||
|
||||
@@ -72,6 +72,7 @@
|
||||
#include "pm_impl.h"
|
||||
#include "trax.h"
|
||||
#include "esp_ota_ops.h"
|
||||
#include "bootloader_common.h"
|
||||
|
||||
#define STRINGIFY(s) STRINGIFY2(s)
|
||||
#define STRINGIFY2(s) #s
|
||||
@@ -173,6 +174,8 @@ void IRAM_ATTR call_start_cpu0()
|
||||
abort();
|
||||
#endif
|
||||
}
|
||||
# else // If psram is uninitialized, we need to improve the flash cs timing.
|
||||
bootloader_common_set_flash_cs_timing();
|
||||
#endif
|
||||
|
||||
ESP_EARLY_LOGI(TAG, "Pro cpu up.");
|
||||
@@ -390,6 +393,16 @@ void start_cpu0_default(void)
|
||||
spi_flash_init();
|
||||
/* init default OS-aware flash access critical section */
|
||||
spi_flash_guard_set(&g_flash_guard_default_ops);
|
||||
|
||||
uint8_t revision = esp_efuse_get_chip_ver();
|
||||
ESP_LOGI(TAG, "Chip Revision: %d", revision);
|
||||
if (revision > CONFIG_ESP32_REV_MIN) {
|
||||
ESP_LOGW(TAG, "Chip revision is higher than the one configured in menuconfig. Suggest to upgrade it.");
|
||||
} else if(revision != CONFIG_ESP32_REV_MIN) {
|
||||
ESP_LOGE(TAG, "ESP-IDF can't support this chip revision. Modify minimum supported revision in menuconfig");
|
||||
abort();
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM_ENABLE
|
||||
esp_pm_impl_init();
|
||||
#ifdef CONFIG_PM_DFS_INIT_AUTO
|
||||
|
||||
@@ -96,9 +96,9 @@ void esp_crosscore_int_init() {
|
||||
static void IRAM_ATTR esp_crosscore_int_send(int core_id, uint32_t reason_mask) {
|
||||
assert(core_id<portNUM_PROCESSORS);
|
||||
//Mark the reason we interrupt the other CPU
|
||||
portENTER_CRITICAL(&reason_spinlock);
|
||||
portENTER_CRITICAL_ISR(&reason_spinlock);
|
||||
reason[core_id] |= reason_mask;
|
||||
portEXIT_CRITICAL(&reason_spinlock);
|
||||
portEXIT_CRITICAL_ISR(&reason_spinlock);
|
||||
//Poke the other CPU.
|
||||
if (core_id==0) {
|
||||
DPORT_WRITE_PERI_REG(DPORT_CPU_INTR_FROM_CPU_0_REG, DPORT_CPU_INTR_FROM_CPU_0);
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
* DPORT access is used for do protection when dual core access DPORT internal register and APB register via DPORT simultaneously
|
||||
* This function will be initialize after FreeRTOS startup.
|
||||
* When cpu0 want to access DPORT register, it should notify cpu1 enter in high-priority interrupt for be mute. When cpu1 already in high-priority interrupt,
|
||||
* cpu0 can access DPORT register. Currently, cpu1 will wait for cpu0 finish access and exit high-priority interrupt.
|
||||
* cpu0 can access DPORT register. Currently, cpu1 will wait for cpu0 finish access and exit high-priority interrupt.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
@@ -116,7 +116,7 @@ void IRAM_ATTR esp_dport_access_stall_other_cpu_end(void)
|
||||
{
|
||||
#ifndef CONFIG_FREERTOS_UNICORE
|
||||
int cpu_id = xPortGetCoreID();
|
||||
|
||||
|
||||
if (dport_core_state[0] == DPORT_CORE_STATE_IDLE
|
||||
|| dport_core_state[1] == DPORT_CORE_STATE_IDLE) {
|
||||
return;
|
||||
@@ -249,7 +249,7 @@ void IRAM_ATTR esp_dport_access_read_buffer(uint32_t *buff_out, uint32_t address
|
||||
*/
|
||||
uint32_t IRAM_ATTR esp_dport_access_reg_read(uint32_t reg)
|
||||
{
|
||||
#if defined(BOOTLOADER_BUILD) || defined(CONFIG_FREERTOS_UNICORE) || !defined(ESP_PLATFORM)
|
||||
#if defined(BOOTLOADER_BUILD) || !defined(CONFIG_ESP32_DPORT_WORKAROUND) || !defined(ESP_PLATFORM)
|
||||
return _DPORT_REG_READ(reg);
|
||||
#else
|
||||
uint32_t apb;
|
||||
@@ -295,7 +295,7 @@ uint32_t IRAM_ATTR esp_dport_access_reg_read(uint32_t reg)
|
||||
*/
|
||||
uint32_t IRAM_ATTR esp_dport_access_sequence_reg_read(uint32_t reg)
|
||||
{
|
||||
#if defined(BOOTLOADER_BUILD) || defined(CONFIG_FREERTOS_UNICORE) || !defined(ESP_PLATFORM)
|
||||
#if defined(BOOTLOADER_BUILD) || !defined(CONFIG_ESP32_DPORT_WORKAROUND) || !defined(ESP_PLATFORM)
|
||||
return _DPORT_REG_READ(reg);
|
||||
#else
|
||||
uint32_t apb;
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
@@ -53,6 +54,8 @@
|
||||
extern void esp_dport_access_stall_other_cpu_start_wrap(void);
|
||||
extern void esp_dport_access_stall_other_cpu_end_wrap(void);
|
||||
|
||||
#define TAG "esp_adapter"
|
||||
|
||||
/*
|
||||
If CONFIG_WIFI_LWIP_ALLOCATION_FROM_SPIRAM_FIRST is enabled. Prefer to allocate a chunk of memory in SPIRAM firstly.
|
||||
If failed, try to allocate it in internal memory then.
|
||||
@@ -218,6 +221,41 @@ static void semphr_delete_wrapper(void *semphr)
|
||||
vSemaphoreDelete(semphr);
|
||||
}
|
||||
|
||||
static void wifi_thread_semphr_free(void* data)
|
||||
{
|
||||
xSemaphoreHandle *sem = (xSemaphoreHandle*)(data);
|
||||
|
||||
if (sem) {
|
||||
vSemaphoreDelete(sem);
|
||||
}
|
||||
}
|
||||
|
||||
static void * wifi_thread_semphr_get_wrapper(void)
|
||||
{
|
||||
static bool s_wifi_thread_sem_key_init = false;
|
||||
static pthread_key_t s_wifi_thread_sem_key;
|
||||
xSemaphoreHandle sem = NULL;
|
||||
|
||||
if (s_wifi_thread_sem_key_init == false) {
|
||||
if (0 != pthread_key_create(&s_wifi_thread_sem_key, wifi_thread_semphr_free)) {
|
||||
return NULL;
|
||||
}
|
||||
s_wifi_thread_sem_key_init = true;
|
||||
}
|
||||
|
||||
sem = pthread_getspecific(s_wifi_thread_sem_key);
|
||||
if (!sem) {
|
||||
sem = xSemaphoreCreateCounting(1, 0);
|
||||
if (sem) {
|
||||
pthread_setspecific(s_wifi_thread_sem_key, sem);
|
||||
ESP_LOGV(TAG, "thread sem create: sem=%p", sem);
|
||||
}
|
||||
}
|
||||
|
||||
ESP_LOGV(TAG, "thread sem get: sem=%p", sem);
|
||||
return (void*)sem;
|
||||
}
|
||||
|
||||
static int32_t IRAM_ATTR semphr_take_from_isr_wrapper(void *semphr, void *hptw)
|
||||
{
|
||||
return (int32_t)xSemaphoreTakeFromISR(semphr, hptw);
|
||||
@@ -478,6 +516,7 @@ wifi_osi_funcs_t g_wifi_osi_funcs = {
|
||||
._semphr_delete = semphr_delete_wrapper,
|
||||
._semphr_take = semphr_take_wrapper,
|
||||
._semphr_give = semphr_give_wrapper,
|
||||
._wifi_thread_semphr_get = wifi_thread_semphr_get_wrapper,
|
||||
._mutex_create = mutex_create_wrapper,
|
||||
._recursive_mutex_create = recursive_mutex_create_wrapper,
|
||||
._mutex_delete = mutex_delete_wrapper,
|
||||
|
||||
@@ -365,6 +365,10 @@ static esp_err_t esp_system_event_debug(system_event_t *event)
|
||||
ESP_LOGD(TAG, "SYSTEM_EVENT_STA_WPS_ER_PIN");
|
||||
break;
|
||||
}
|
||||
case SYSTEM_EVENT_STA_WPS_ER_PBC_OVERLAP: {
|
||||
ESP_LOGD(TAG, "SYSTEM_EVENT_STA_WPS_ER_PBC_OVERLAP");
|
||||
break;
|
||||
}
|
||||
case SYSTEM_EVENT_AP_START: {
|
||||
ESP_LOGD(TAG, "SYSTEM_EVENT_AP_START");
|
||||
break;
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include <string.h>
|
||||
#include "mbedtls/aes.h"
|
||||
#include "hwcrypto/aes.h"
|
||||
#include "mbedtls/platform_util.h"
|
||||
#include "soc/dport_reg.h"
|
||||
#include "soc/hwcrypto_reg.h"
|
||||
#include <sys/lock.h>
|
||||
@@ -49,6 +50,11 @@
|
||||
*/
|
||||
static portMUX_TYPE aes_spinlock = portMUX_INITIALIZER_UNLOCKED;
|
||||
|
||||
static inline bool valid_key_length(const esp_aes_context *ctx)
|
||||
{
|
||||
return ctx->key_bytes == 128/8 || ctx->key_bytes == 192/8 || ctx->key_bytes == 256/8;
|
||||
}
|
||||
|
||||
void esp_aes_acquire_hardware( void )
|
||||
{
|
||||
portENTER_CRITICAL(&aes_spinlock);
|
||||
@@ -93,6 +99,7 @@ int esp_aes_setkey( esp_aes_context *ctx, const unsigned char *key,
|
||||
}
|
||||
ctx->key_bytes = keybits / 8;
|
||||
memcpy(ctx->key, key, ctx->key_bytes);
|
||||
ctx->key_in_hardware = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -102,35 +109,83 @@ int esp_aes_setkey( esp_aes_context *ctx, const unsigned char *key,
|
||||
*
|
||||
* Call only while holding esp_aes_acquire_hardware().
|
||||
*/
|
||||
static inline void esp_aes_setkey_hardware( esp_aes_context *ctx, int mode)
|
||||
static void esp_aes_setkey_hardware(esp_aes_context *ctx, int mode)
|
||||
{
|
||||
const uint32_t MODE_DECRYPT_BIT = 4;
|
||||
unsigned mode_reg_base = (mode == ESP_AES_ENCRYPT) ? 0 : MODE_DECRYPT_BIT;
|
||||
|
||||
ctx->key_in_hardware = 0;
|
||||
|
||||
for (int i = 0; i < ctx->key_bytes/4; ++i) {
|
||||
DPORT_REG_WRITE(AES_KEY_BASE + i * 4, *(((uint32_t *)ctx->key) + i));
|
||||
ctx->key_in_hardware += 4;
|
||||
}
|
||||
|
||||
DPORT_REG_WRITE(AES_MODE_REG, mode_reg_base + ((ctx->key_bytes / 8) - 2));
|
||||
|
||||
/* Fault injection check: all words of key data should have been written to hardware */
|
||||
if (ctx->key_in_hardware < 16
|
||||
|| ctx->key_in_hardware != ctx->key_bytes) {
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
/* Run a single 16 byte block of AES, using the hardware engine.
|
||||
*
|
||||
* Call only while holding esp_aes_acquire_hardware().
|
||||
*/
|
||||
static inline void esp_aes_block(const void *input, void *output)
|
||||
static int esp_aes_block(esp_aes_context *ctx, const void *input, void *output)
|
||||
{
|
||||
const uint32_t *input_words = (const uint32_t *)input;
|
||||
uint32_t i0, i1, i2, i3;
|
||||
uint32_t *output_words = (uint32_t *)output;
|
||||
uint32_t *mem_block = (uint32_t *)AES_TEXT_BASE;
|
||||
|
||||
for(int i = 0; i < 4; i++) {
|
||||
mem_block[i] = input_words[i];
|
||||
/* If no key is written to hardware yet, either the user hasn't called
|
||||
mbedtls_aes_setkey_enc/mbedtls_aes_setkey_dec - meaning we also don't
|
||||
know which mode to use - or a fault skipped the
|
||||
key write to hardware. Treat this as a fatal error and zero the output block.
|
||||
*/
|
||||
if (ctx->key_in_hardware != ctx->key_bytes) {
|
||||
bzero(output, 16);
|
||||
return MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH;
|
||||
}
|
||||
|
||||
/* Storing i0,i1,i2,i3 in registers not an array
|
||||
helps a lot with optimisations at -Os level */
|
||||
i0 = input_words[0];
|
||||
DPORT_REG_WRITE(AES_TEXT_BASE, i0);
|
||||
|
||||
i1 = input_words[1];
|
||||
DPORT_REG_WRITE(AES_TEXT_BASE + 4, i1);
|
||||
|
||||
i2 = input_words[2];
|
||||
DPORT_REG_WRITE(AES_TEXT_BASE + 8, i2);
|
||||
|
||||
i3 = input_words[3];
|
||||
DPORT_REG_WRITE(AES_TEXT_BASE + 12, i3);
|
||||
|
||||
DPORT_REG_WRITE(AES_START_REG, 1);
|
||||
|
||||
while (DPORT_REG_READ(AES_IDLE_REG) != 1) { }
|
||||
esp_dport_access_read_buffer(output_words, (uint32_t)&mem_block[0], 4);
|
||||
|
||||
esp_dport_access_read_buffer(output_words, AES_TEXT_BASE, 4);
|
||||
|
||||
/* Physical security check: Verify the AES accelerator actually ran, and wasn't
|
||||
skipped due to external fault injection while starting the peripheral.
|
||||
|
||||
Note that i0,i1,i2,i3 are copied from input buffer in case input==output.
|
||||
|
||||
Bypassing this check requires at least one additional fault.
|
||||
*/
|
||||
if(i0 == output_words[0] && i1 == output_words[1] && i2 == output_words[2] && i3 == output_words[3]) {
|
||||
// calling zeroing functions to narrow the
|
||||
// window for a double-fault of the abort step, here
|
||||
memset(output, 0, 16);
|
||||
mbedtls_platform_zeroize(output, 16);
|
||||
abort();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -140,11 +195,18 @@ int esp_internal_aes_encrypt( esp_aes_context *ctx,
|
||||
const unsigned char input[16],
|
||||
unsigned char output[16] )
|
||||
{
|
||||
int r;
|
||||
|
||||
if (!valid_key_length(ctx)) {
|
||||
return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH;
|
||||
}
|
||||
|
||||
esp_aes_acquire_hardware();
|
||||
ctx->key_in_hardware = 0;
|
||||
esp_aes_setkey_hardware(ctx, ESP_AES_ENCRYPT);
|
||||
esp_aes_block(input, output);
|
||||
r = esp_aes_block(ctx, input, output);
|
||||
esp_aes_release_hardware();
|
||||
return 0;
|
||||
return r;
|
||||
}
|
||||
|
||||
void esp_aes_encrypt( esp_aes_context *ctx,
|
||||
@@ -162,11 +224,18 @@ int esp_internal_aes_decrypt( esp_aes_context *ctx,
|
||||
const unsigned char input[16],
|
||||
unsigned char output[16] )
|
||||
{
|
||||
int r;
|
||||
|
||||
if (!valid_key_length(ctx)) {
|
||||
return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH;
|
||||
}
|
||||
|
||||
esp_aes_acquire_hardware();
|
||||
ctx->key_in_hardware = 0;
|
||||
esp_aes_setkey_hardware(ctx, ESP_AES_DECRYPT);
|
||||
esp_aes_block(input, output);
|
||||
r = esp_aes_block(ctx, input, output);
|
||||
esp_aes_release_hardware();
|
||||
return 0;
|
||||
return r;
|
||||
}
|
||||
|
||||
void esp_aes_decrypt( esp_aes_context *ctx,
|
||||
@@ -176,7 +245,6 @@ void esp_aes_decrypt( esp_aes_context *ctx,
|
||||
esp_internal_aes_decrypt(ctx, input, output);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* AES-ECB block encryption/decryption
|
||||
*/
|
||||
@@ -185,12 +253,19 @@ int esp_aes_crypt_ecb( esp_aes_context *ctx,
|
||||
const unsigned char input[16],
|
||||
unsigned char output[16] )
|
||||
{
|
||||
int r;
|
||||
|
||||
if (!valid_key_length(ctx)) {
|
||||
return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH;
|
||||
}
|
||||
|
||||
esp_aes_acquire_hardware();
|
||||
ctx->key_in_hardware = 0;
|
||||
esp_aes_setkey_hardware(ctx, mode);
|
||||
esp_aes_block(input, output);
|
||||
r = esp_aes_block(ctx, input, output);
|
||||
esp_aes_release_hardware();
|
||||
|
||||
return 0;
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
@@ -214,14 +289,19 @@ int esp_aes_crypt_cbc( esp_aes_context *ctx,
|
||||
return ( ERR_ESP_AES_INVALID_INPUT_LENGTH );
|
||||
}
|
||||
|
||||
if (!valid_key_length(ctx)) {
|
||||
return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH;
|
||||
}
|
||||
|
||||
esp_aes_acquire_hardware();
|
||||
ctx->key_in_hardware = 0;
|
||||
|
||||
esp_aes_setkey_hardware(ctx, mode);
|
||||
|
||||
if ( mode == ESP_AES_DECRYPT ) {
|
||||
while ( length > 0 ) {
|
||||
memcpy(temp, input_words, 16);
|
||||
esp_aes_block(input_words, output_words);
|
||||
esp_aes_block(ctx, input_words, output_words);
|
||||
|
||||
for ( i = 0; i < 4; i++ ) {
|
||||
output_words[i] = output_words[i] ^ iv_words[i];
|
||||
@@ -240,7 +320,7 @@ int esp_aes_crypt_cbc( esp_aes_context *ctx,
|
||||
output_words[i] = input_words[i] ^ iv_words[i];
|
||||
}
|
||||
|
||||
esp_aes_block(output_words, output_words);
|
||||
esp_aes_block(ctx, output_words, output_words);
|
||||
memcpy( iv_words, output_words, 16 );
|
||||
|
||||
input_words += 4;
|
||||
@@ -268,14 +348,19 @@ int esp_aes_crypt_cfb128( esp_aes_context *ctx,
|
||||
int c;
|
||||
size_t n = *iv_off;
|
||||
|
||||
if (!valid_key_length(ctx)) {
|
||||
return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH;
|
||||
}
|
||||
|
||||
esp_aes_acquire_hardware();
|
||||
ctx->key_in_hardware = 0;
|
||||
|
||||
esp_aes_setkey_hardware(ctx, ESP_AES_ENCRYPT);
|
||||
|
||||
if ( mode == ESP_AES_DECRYPT ) {
|
||||
while ( length-- ) {
|
||||
if ( n == 0 ) {
|
||||
esp_aes_block(iv, iv );
|
||||
esp_aes_block(ctx, iv, iv );
|
||||
}
|
||||
|
||||
c = *input++;
|
||||
@@ -287,7 +372,7 @@ int esp_aes_crypt_cfb128( esp_aes_context *ctx,
|
||||
} else {
|
||||
while ( length-- ) {
|
||||
if ( n == 0 ) {
|
||||
esp_aes_block(iv, iv );
|
||||
esp_aes_block(ctx, iv, iv );
|
||||
}
|
||||
|
||||
iv[n] = *output++ = (unsigned char)( iv[n] ^ *input++ );
|
||||
@@ -316,13 +401,18 @@ int esp_aes_crypt_cfb8( esp_aes_context *ctx,
|
||||
unsigned char c;
|
||||
unsigned char ov[17];
|
||||
|
||||
if (!valid_key_length(ctx)) {
|
||||
return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH;
|
||||
}
|
||||
|
||||
esp_aes_acquire_hardware();
|
||||
ctx->key_in_hardware = 0;
|
||||
|
||||
esp_aes_setkey_hardware(ctx, ESP_AES_ENCRYPT);
|
||||
|
||||
while ( length-- ) {
|
||||
memcpy( ov, iv, 16 );
|
||||
esp_aes_block(iv, iv);
|
||||
esp_aes_block(ctx, iv, iv);
|
||||
|
||||
if ( mode == ESP_AES_DECRYPT ) {
|
||||
ov[16] = *input;
|
||||
@@ -356,13 +446,18 @@ int esp_aes_crypt_ctr( esp_aes_context *ctx,
|
||||
int c, i;
|
||||
size_t n = *nc_off;
|
||||
|
||||
if (!valid_key_length(ctx)) {
|
||||
return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH;
|
||||
}
|
||||
|
||||
esp_aes_acquire_hardware();
|
||||
ctx->key_in_hardware = 0;
|
||||
|
||||
esp_aes_setkey_hardware(ctx, ESP_AES_ENCRYPT);
|
||||
|
||||
while ( length-- ) {
|
||||
if ( n == 0 ) {
|
||||
esp_aes_block(nonce_counter, stream_block);
|
||||
esp_aes_block(ctx, nonce_counter, stream_block);
|
||||
|
||||
for ( i = 16; i > 0; i-- )
|
||||
if ( ++nonce_counter[i - 1] != 0 ) {
|
||||
|
||||
@@ -226,6 +226,9 @@ void esp_sha_wait_idle(void)
|
||||
|
||||
void esp_sha_read_digest_state(esp_sha_type sha_type, void *digest_state)
|
||||
{
|
||||
uint32_t *digest_state_words = NULL;
|
||||
uint32_t *reg_addr_buf = NULL;
|
||||
uint32_t word_len = sha_length(sha_type)/4;
|
||||
#ifndef NDEBUG
|
||||
{
|
||||
SemaphoreHandle_t *engine_state = sha_get_engine_state(sha_type);
|
||||
@@ -243,20 +246,30 @@ void esp_sha_read_digest_state(esp_sha_type sha_type, void *digest_state)
|
||||
|
||||
DPORT_REG_WRITE(SHA_LOAD_REG(sha_type), 1);
|
||||
while(DPORT_REG_READ(SHA_BUSY_REG(sha_type)) == 1) { }
|
||||
uint32_t *digest_state_words = (uint32_t *)digest_state;
|
||||
uint32_t *reg_addr_buf = (uint32_t *)(SHA_TEXT_BASE);
|
||||
digest_state_words = (uint32_t *)digest_state;
|
||||
reg_addr_buf = (uint32_t *)(SHA_TEXT_BASE);
|
||||
if(sha_type == SHA2_384 || sha_type == SHA2_512) {
|
||||
/* for these ciphers using 64-bit states, swap each pair of words */
|
||||
DPORT_INTERRUPT_DISABLE(); // Disable interrupt only on current CPU.
|
||||
for(int i = 0; i < sha_length(sha_type)/4; i += 2) {
|
||||
for(int i = 0; i < word_len; i += 2) {
|
||||
digest_state_words[i+1] = DPORT_SEQUENCE_REG_READ((uint32_t)®_addr_buf[i]);
|
||||
digest_state_words[i] = DPORT_SEQUENCE_REG_READ((uint32_t)®_addr_buf[i+1]);
|
||||
}
|
||||
DPORT_INTERRUPT_RESTORE(); // restore the previous interrupt level
|
||||
} else {
|
||||
esp_dport_access_read_buffer(digest_state_words, (uint32_t)®_addr_buf[0], sha_length(sha_type)/4);
|
||||
esp_dport_access_read_buffer(digest_state_words, (uint32_t)®_addr_buf[0], word_len);
|
||||
}
|
||||
esp_sha_unlock_memory_block();
|
||||
|
||||
/* Fault injection check: verify SHA engine actually ran,
|
||||
state is not all zeroes.
|
||||
*/
|
||||
for (int i = 0; i < word_len; i++) {
|
||||
if (digest_state_words[i] != 0) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
abort(); // SHA peripheral returned all zero state, probably due to fault injection
|
||||
}
|
||||
|
||||
void esp_sha_block(esp_sha_type sha_type, const void *data_block, bool is_first_block)
|
||||
@@ -310,6 +323,8 @@ void esp_sha(esp_sha_type sha_type, const unsigned char *input, size_t ilen, uns
|
||||
|
||||
esp_sha_lock_engine(sha_type);
|
||||
|
||||
bzero(output, sha_length(sha_type));
|
||||
|
||||
SHA_CTX ctx;
|
||||
ets_sha_init(&ctx);
|
||||
|
||||
@@ -353,4 +368,14 @@ void esp_sha(esp_sha_type sha_type, const unsigned char *input, size_t ilen, uns
|
||||
}
|
||||
|
||||
esp_sha_unlock_engine(sha_type);
|
||||
|
||||
/* Fault injection check: verify SHA engine actually ran,
|
||||
state is not all zeroes.
|
||||
*/
|
||||
for (int i = 0; i < sha_length(sha_type); i++) {
|
||||
if (output[i] != 0) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
abort(); // SHA peripheral returned all zero state, probably due to fault injection
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ uint32_t esp_dport_access_sequence_reg_read(uint32_t reg);
|
||||
//only call in case of panic().
|
||||
void esp_dport_access_int_abort(void);
|
||||
|
||||
#if defined(BOOTLOADER_BUILD) || defined(CONFIG_FREERTOS_UNICORE) || !defined(ESP_PLATFORM)
|
||||
#if defined(BOOTLOADER_BUILD) || !defined(CONFIG_ESP32_DPORT_WORKAROUND) || !defined(ESP_PLATFORM)
|
||||
#define DPORT_STALL_OTHER_CPU_START()
|
||||
#define DPORT_STALL_OTHER_CPU_END()
|
||||
#define DPORT_INTERRUPT_DISABLE()
|
||||
|
||||
@@ -40,6 +40,7 @@ typedef enum {
|
||||
SYSTEM_EVENT_STA_WPS_ER_FAILED, /**< ESP32 station wps fails in enrollee mode */
|
||||
SYSTEM_EVENT_STA_WPS_ER_TIMEOUT, /**< ESP32 station wps timeout in enrollee mode */
|
||||
SYSTEM_EVENT_STA_WPS_ER_PIN, /**< ESP32 station wps pin code in enrollee mode */
|
||||
SYSTEM_EVENT_STA_WPS_ER_PBC_OVERLAP, /*!< ESP32 station wps overlap in enrollee mode */
|
||||
SYSTEM_EVENT_AP_START, /**< ESP32 soft-AP start */
|
||||
SYSTEM_EVENT_AP_STOP, /**< ESP32 soft-AP stop */
|
||||
SYSTEM_EVENT_AP_STACONNECTED, /**< a station connected to ESP32 soft-AP */
|
||||
|
||||
@@ -1479,6 +1479,13 @@ esp_err_t esp_mesh_switch_channel(const uint8_t *new_bssid, int csa_newchan, int
|
||||
*/
|
||||
esp_err_t esp_mesh_get_router_bssid(uint8_t *router_bssid);
|
||||
|
||||
/**
|
||||
* @brief Get the TSF time
|
||||
*
|
||||
* @return the TSF time
|
||||
*/
|
||||
int64_t esp_mesh_get_tsf_time(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1102,6 +1102,19 @@ esp_err_t esp_wifi_set_ant(const wifi_ant_config_t *config);
|
||||
*/
|
||||
esp_err_t esp_wifi_get_ant(wifi_ant_config_t *config);
|
||||
|
||||
/**
|
||||
* @brief A general API to set/get WiFi internal configuration, it's for debug only
|
||||
*
|
||||
* @param cmd : ioctl command type
|
||||
* @param cfg : configuration for the command
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: succeed
|
||||
* - others: failed
|
||||
*/
|
||||
esp_err_t esp_wifi_internal_ioctl(int cmd, wifi_ioctl_config_t *cfg);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -44,6 +44,7 @@ typedef struct {
|
||||
void (*_semphr_delete)(void *semphr);
|
||||
int32_t (*_semphr_take)(void *semphr, uint32_t block_time_tick);
|
||||
int32_t (*_semphr_give)(void *semphr);
|
||||
void *(*_wifi_thread_semphr_get)(void);
|
||||
void *(*_mutex_create)(void);
|
||||
void *(*_recursive_mutex_create)(void);
|
||||
void (*_mutex_delete)(void *mutex);
|
||||
|
||||
@@ -492,6 +492,34 @@ typedef enum {
|
||||
WIFI_PHY_RATE_MAX,
|
||||
} wifi_phy_rate_t;
|
||||
|
||||
/**
|
||||
* @brief WiFi ioctl command type
|
||||
*
|
||||
*/
|
||||
typedef enum {
|
||||
WIFI_IOCTL_SET_STA_HT2040_COEX = 1, /**< Set the configuration of STA's HT2040 coexist management */
|
||||
WIFI_IOCTL_GET_STA_HT2040_COEX, /**< Get the configuration of STA's HT2040 coexist management */
|
||||
WIFI_IOCTL_MAX,
|
||||
} wifi_ioctl_cmd_t;
|
||||
|
||||
/**
|
||||
* @brief Configuration for STA's HT2040 coexist management
|
||||
*
|
||||
*/
|
||||
typedef struct {
|
||||
int enable; /**< Indicate whether STA's HT2040 coexist management is enabled or not */
|
||||
} wifi_ht2040_coex_t;
|
||||
|
||||
/**
|
||||
* @brief Configuration for WiFi ioctl
|
||||
*
|
||||
*/
|
||||
typedef struct {
|
||||
union {
|
||||
wifi_ht2040_coex_t ht2040_coex; /**< Configuration of STA's HT2040 coexist management */
|
||||
} data; /**< Configuration of ioctl command */
|
||||
} wifi_ioctl_config_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -41,17 +41,13 @@ extern "C" {
|
||||
/**
|
||||
* \brief AES context structure
|
||||
*
|
||||
* \note buf is able to hold 32 extra bytes, which can be used:
|
||||
* - for alignment purposes if VIA padlock is used, and/or
|
||||
* - to simplify key expansion in the 256-bit case by
|
||||
* generating an extra round key
|
||||
*/
|
||||
typedef struct {
|
||||
uint8_t key_bytes;
|
||||
volatile uint8_t key_in_hardware; /* This variable is used for fault injection checks, so marked volatile to avoid optimisation */
|
||||
uint8_t key[32];
|
||||
} esp_aes_context;
|
||||
|
||||
|
||||
/**
|
||||
* \brief The AES XTS context-type definition.
|
||||
*/
|
||||
|
||||
@@ -86,7 +86,8 @@ extern "C" {
|
||||
#define SPI0_R_QIO_DUMMY_CYCLELEN 3
|
||||
#define SPI0_R_QIO_ADDR_BITSLEN 31
|
||||
#define SPI0_R_FAST_DUMMY_CYCLELEN 7
|
||||
#define SPI0_R_DIO_DUMMY_CYCLELEN 3
|
||||
#define SPI0_R_DIO_DUMMY_CYCLELEN 1
|
||||
#define SPI0_R_DIO_ADDR_BITSLEN 27
|
||||
#define SPI0_R_FAST_ADDR_BITSLEN 23
|
||||
#define SPI0_R_SIO_ADDR_BITSLEN 23
|
||||
|
||||
|
||||
@@ -494,7 +494,7 @@ static void IRAM_ATTR shared_intr_isr(void *arg)
|
||||
{
|
||||
vector_desc_t *vd=(vector_desc_t*)arg;
|
||||
shared_vector_desc_t *sh_vec=vd->shared_vec_info;
|
||||
portENTER_CRITICAL(&spinlock);
|
||||
portENTER_CRITICAL_ISR(&spinlock);
|
||||
while(sh_vec) {
|
||||
if (!sh_vec->disabled) {
|
||||
if ((sh_vec->statusreg == NULL) || (*sh_vec->statusreg & sh_vec->statusmask)) {
|
||||
@@ -512,7 +512,7 @@ static void IRAM_ATTR shared_intr_isr(void *arg)
|
||||
}
|
||||
sh_vec=sh_vec->next;
|
||||
}
|
||||
portEXIT_CRITICAL(&spinlock);
|
||||
portEXIT_CRITICAL_ISR(&spinlock);
|
||||
}
|
||||
|
||||
#if CONFIG_SYSVIEW_ENABLE
|
||||
@@ -520,7 +520,7 @@ static void IRAM_ATTR shared_intr_isr(void *arg)
|
||||
static void IRAM_ATTR non_shared_intr_isr(void *arg)
|
||||
{
|
||||
non_shared_isr_arg_t *ns_isr_arg=(non_shared_isr_arg_t*)arg;
|
||||
portENTER_CRITICAL(&spinlock);
|
||||
portENTER_CRITICAL_ISR(&spinlock);
|
||||
traceISR_ENTER(ns_isr_arg->source+ETS_INTERNAL_INTR_SOURCE_OFF);
|
||||
// FIXME: can we call ISR and check port_switch_flag after releasing spinlock?
|
||||
// when CONFIG_SYSVIEW_ENABLE = 0 ISRs for non-shared IRQs are called without spinlock
|
||||
@@ -529,7 +529,7 @@ static void IRAM_ATTR non_shared_intr_isr(void *arg)
|
||||
if (!port_switch_flag[xPortGetCoreID()]) {
|
||||
traceISR_EXIT();
|
||||
}
|
||||
portEXIT_CRITICAL(&spinlock);
|
||||
portEXIT_CRITICAL_ISR(&spinlock);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -794,7 +794,7 @@ int esp_intr_get_cpu(intr_handle_t handle)
|
||||
esp_err_t IRAM_ATTR esp_intr_enable(intr_handle_t handle)
|
||||
{
|
||||
if (!handle) return ESP_ERR_INVALID_ARG;
|
||||
portENTER_CRITICAL(&spinlock);
|
||||
portENTER_CRITICAL_SAFE(&spinlock);
|
||||
int source;
|
||||
if (handle->shared_vector_desc) {
|
||||
handle->shared_vector_desc->disabled=0;
|
||||
@@ -810,14 +810,14 @@ esp_err_t IRAM_ATTR esp_intr_enable(intr_handle_t handle)
|
||||
if (handle->vector_desc->cpu!=xPortGetCoreID()) return ESP_ERR_INVALID_ARG; //Can only enable these ints on this cpu
|
||||
ESP_INTR_ENABLE(handle->vector_desc->intno);
|
||||
}
|
||||
portEXIT_CRITICAL(&spinlock);
|
||||
portEXIT_CRITICAL_SAFE(&spinlock);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t IRAM_ATTR esp_intr_disable(intr_handle_t handle)
|
||||
{
|
||||
if (!handle) return ESP_ERR_INVALID_ARG;
|
||||
portENTER_CRITICAL(&spinlock);
|
||||
portENTER_CRITICAL_SAFE(&spinlock);
|
||||
int source;
|
||||
bool disabled = 1;
|
||||
if (handle->shared_vector_desc) {
|
||||
@@ -850,7 +850,7 @@ esp_err_t IRAM_ATTR esp_intr_disable(intr_handle_t handle)
|
||||
}
|
||||
ESP_INTR_DISABLE(handle->vector_desc->intno);
|
||||
}
|
||||
portEXIT_CRITICAL(&spinlock);
|
||||
portEXIT_CRITICAL_SAFE(&spinlock);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
|
||||
Submodule components/esp32/lib updated: fbe87f4076...de6c4ab211
@@ -264,7 +264,7 @@ void IRAM_ATTR esp_pm_impl_switch_mode(pm_mode_t mode,
|
||||
{
|
||||
bool need_switch = false;
|
||||
uint32_t mode_mask = BIT(mode);
|
||||
portENTER_CRITICAL(&s_switch_lock);
|
||||
portENTER_CRITICAL_SAFE(&s_switch_lock);
|
||||
uint32_t count;
|
||||
if (lock_or_unlock == MODE_LOCK) {
|
||||
count = ++s_mode_lock_counts[mode];
|
||||
@@ -291,7 +291,7 @@ void IRAM_ATTR esp_pm_impl_switch_mode(pm_mode_t mode,
|
||||
s_last_mode_change_time = now;
|
||||
#endif // WITH_PROFILING
|
||||
}
|
||||
portEXIT_CRITICAL(&s_switch_lock);
|
||||
portEXIT_CRITICAL_SAFE(&s_switch_lock);
|
||||
if (need_switch && new_mode != s_mode) {
|
||||
do_switch(new_mode);
|
||||
}
|
||||
|
||||
@@ -111,7 +111,7 @@ esp_err_t IRAM_ATTR esp_pm_lock_acquire(esp_pm_lock_handle_t handle)
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
portENTER_CRITICAL(&handle->spinlock);
|
||||
portENTER_CRITICAL_SAFE(&handle->spinlock);
|
||||
if (handle->count++ == 0) {
|
||||
pm_time_t now = 0;
|
||||
#ifdef WITH_PROFILING
|
||||
@@ -123,7 +123,7 @@ esp_err_t IRAM_ATTR esp_pm_lock_acquire(esp_pm_lock_handle_t handle)
|
||||
handle->times_taken++;
|
||||
#endif
|
||||
}
|
||||
portEXIT_CRITICAL(&handle->spinlock);
|
||||
portEXIT_CRITICAL_SAFE(&handle->spinlock);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
@@ -137,7 +137,7 @@ esp_err_t IRAM_ATTR esp_pm_lock_release(esp_pm_lock_handle_t handle)
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
esp_err_t ret = ESP_OK;
|
||||
portENTER_CRITICAL(&handle->spinlock);
|
||||
portENTER_CRITICAL_SAFE(&handle->spinlock);
|
||||
if (handle->count == 0) {
|
||||
ret = ESP_ERR_INVALID_STATE;
|
||||
goto out;
|
||||
@@ -151,11 +151,10 @@ esp_err_t IRAM_ATTR esp_pm_lock_release(esp_pm_lock_handle_t handle)
|
||||
esp_pm_impl_switch_mode(handle->mode, MODE_UNLOCK, now);
|
||||
}
|
||||
out:
|
||||
portEXIT_CRITICAL(&handle->spinlock);
|
||||
portEXIT_CRITICAL_SAFE(&handle->spinlock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
esp_err_t esp_pm_dump_locks(FILE* stream)
|
||||
{
|
||||
#ifndef CONFIG_PM_ENABLE
|
||||
@@ -201,5 +200,3 @@ esp_err_t esp_pm_dump_locks(FILE* stream)
|
||||
#endif
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include "rom/spi_flash.h"
|
||||
#include "rom/gpio.h"
|
||||
#include "rom/cache.h"
|
||||
#include "rom/efuse.h"
|
||||
#include "soc/io_mux_reg.h"
|
||||
#include "soc/dport_reg.h"
|
||||
#include "soc/gpio_sig_map.h"
|
||||
@@ -35,6 +36,7 @@
|
||||
#include "driver/gpio.h"
|
||||
#include "driver/spi_common.h"
|
||||
#include "driver/periph_ctrl.h"
|
||||
#include "bootloader_common.h"
|
||||
|
||||
#if CONFIG_SPIRAM_SUPPORT
|
||||
#include "soc/rtc.h"
|
||||
@@ -94,43 +96,36 @@ typedef enum {
|
||||
// WARNING: PSRAM shares all but the CS and CLK pins with the flash, so these defines
|
||||
// hardcode the flash pins as well, making this code incompatible with either a setup
|
||||
// that has the flash on non-standard pins or ESP32s with built-in flash.
|
||||
#define FLASH_CLK_IO 6
|
||||
#define FLASH_CLK_IO 6
|
||||
#define FLASH_CS_IO 11
|
||||
#define FLASH_SPIQ_SD0_IO 7
|
||||
#define FLASH_SPID_SD1_IO 8
|
||||
#define FLASH_SPIWP_SD3_IO 10
|
||||
#define FLASH_SPIHD_SD2_IO 9
|
||||
|
||||
#define PSRAM_CLK_IO 17
|
||||
#define PSRAM_CS_IO 16
|
||||
#define PSRAM_SPIQ_SD0_IO 7
|
||||
#define PSRAM_SPID_SD1_IO 8
|
||||
#define PSRAM_SPIQ_SD0_IO 7
|
||||
#define PSRAM_SPID_SD1_IO 8
|
||||
#define PSRAM_SPIWP_SD3_IO 10
|
||||
#define PSRAM_SPIHD_SD2_IO 9
|
||||
#define PSRAM_SPIHD_SD2_IO 9
|
||||
|
||||
// IO-pins of ESP32-PICO-D4 for PSRAM. PSRAM share clock with flash.
|
||||
// The CS IO can be overwrite via menuconfig.
|
||||
#define PICO_FLASH_CLK_IO 6
|
||||
#define PICO_FLASH_CS_IO 16
|
||||
#define PICO_FLASH_SPIQ_SD0_IO 17
|
||||
#define PICO_FLASH_SPID_SD1_IO 8
|
||||
#define PICO_FLASH_SPIWP_SD3_IO 7
|
||||
#define PICO_FLASH_SPIHD_SD2_IO 11
|
||||
#define FLASH_HSPI_CLK_IO 14
|
||||
#define FLASH_HSPI_CS_IO 15
|
||||
#define PSRAM_HSPI_SPIQ_SD0_IO 12
|
||||
#define PSRAM_HSPI_SPID_SD1_IO 13
|
||||
#define PSRAM_HSPI_SPIWP_SD3_IO 2
|
||||
#define PSRAM_HSPI_SPIHD_SD2_IO 4
|
||||
|
||||
#define PICO_PSRAM_CLK_IO 6
|
||||
#define PICO_PSRAM_CS_IO CONFIG_PICO_PSRAM_CS_IO
|
||||
#define PICO_PSRAM_SPIQ_SD0_IO 17
|
||||
#define PICO_PSRAM_SPID_SD1_IO 8
|
||||
#define PICO_PSRAM_SPIWP_SD3_IO 7
|
||||
#define PICO_PSRAM_SPIHD_SD2_IO 11
|
||||
// PSRAM clock and cs IO should be configured based on hardware design.
|
||||
// For ESP32-WROVER or ESP32-WROVER-B module, the clock IO is IO17, the cs IO is IO16,
|
||||
// they are the default value for these two configs.
|
||||
#define D0WD_PSRAM_CLK_IO CONFIG_D0WD_PSRAM_CLK_IO // Default value is 17
|
||||
#define D0WD_PSRAM_CS_IO CONFIG_D0WD_PSRAM_CS_IO // Default value is 16
|
||||
|
||||
#define D2WD_PSRAM_CLK_IO CONFIG_D2WD_PSRAM_CLK_IO // Default value is 9
|
||||
#define D2WD_PSRAM_CS_IO CONFIG_D2WD_PSRAM_CS_IO // Default value is 10
|
||||
|
||||
// For ESP32-PICO chip, the psram share clock with flash. The flash clock pin is fixed, which is IO6.
|
||||
#define PICO_PSRAM_CLK_IO 6
|
||||
#define PICO_PSRAM_CS_IO CONFIG_PICO_PSRAM_CS_IO // Default value is 10
|
||||
|
||||
typedef struct {
|
||||
uint8_t flash_clk_io;
|
||||
uint8_t flash_cs_io;
|
||||
uint8_t flash_spiq_sd0_io;
|
||||
uint8_t flash_spid_sd1_io;
|
||||
uint8_t flash_spiwp_sd3_io;
|
||||
uint8_t flash_spihd_sd2_io;
|
||||
uint8_t psram_clk_io;
|
||||
uint8_t psram_cs_io;
|
||||
uint8_t psram_spiq_sd0_io;
|
||||
@@ -491,7 +486,6 @@ void psram_set_cs_timing(psram_spi_num_t spi_num, psram_clk_mode_t clk_mode)
|
||||
void IRAM_ATTR psram_spi_init(psram_spi_num_t spi_num, psram_cache_mode_t mode)
|
||||
{
|
||||
CLEAR_PERI_REG_MASK(SPI_SLAVE_REG(spi_num), SPI_TRANS_DONE << 5);
|
||||
SET_PERI_REG_MASK(SPI_USER_REG(spi_num), SPI_CS_SETUP);
|
||||
// SPI_CPOL & SPI_CPHA
|
||||
CLEAR_PERI_REG_MASK(SPI_PIN_REG(spi_num), SPI_CK_IDLE_EDGE);
|
||||
CLEAR_PERI_REG_MASK(SPI_USER_REG(spi_num), SPI_CK_OUT_EDGE);
|
||||
@@ -508,32 +502,21 @@ void IRAM_ATTR psram_spi_init(psram_spi_num_t spi_num, psram_cache_mode_t mode)
|
||||
psram_set_cs_timing(spi_num, s_clk_mode);
|
||||
}
|
||||
|
||||
/*
|
||||
* Psram mode init will overwrite original flash speed mode, so that it is possible to change psram and flash speed after OTA.
|
||||
* Flash read mode(QIO/QOUT/DIO/DOUT) will not be changed in app bin. It is decided by bootloader, OTA can not change this mode.
|
||||
*/
|
||||
static void IRAM_ATTR psram_gpio_config(psram_io_t psram_io, psram_cache_mode_t mode)
|
||||
//psram gpio init , different working frequency we have different solutions
|
||||
static void IRAM_ATTR psram_gpio_config(psram_io_t *psram_io, psram_cache_mode_t mode)
|
||||
{
|
||||
int spi_cache_dummy = 0;
|
||||
uint32_t rd_mode_reg = READ_PERI_REG(SPI_CTRL_REG(0));
|
||||
if (rd_mode_reg & (SPI_FREAD_QIO_M | SPI_FREAD_DIO_M)) {
|
||||
if (rd_mode_reg & SPI_FREAD_QIO_M) {
|
||||
spi_cache_dummy = SPI0_R_QIO_DUMMY_CYCLELEN;
|
||||
} else if (rd_mode_reg & (SPI_FREAD_QUAD_M | SPI_FREAD_DUAL_M)) {
|
||||
} else if (rd_mode_reg & SPI_FREAD_DIO_M) {
|
||||
spi_cache_dummy = SPI0_R_DIO_DUMMY_CYCLELEN;
|
||||
SET_PERI_REG_BITS(SPI_USER1_REG(0), SPI_USR_ADDR_BITLEN_V, SPI0_R_DIO_ADDR_BITSLEN, SPI_USR_ADDR_BITLEN_S);
|
||||
} else if (rd_mode_reg & (SPI_FREAD_QUAD_M | SPI_FREAD_DUAL_M)) {
|
||||
spi_cache_dummy = SPI0_R_FAST_DUMMY_CYCLELEN;
|
||||
} else {
|
||||
spi_cache_dummy = SPI0_R_FAST_DUMMY_CYCLELEN;
|
||||
}
|
||||
// In bootloader, all the signals are already configured,
|
||||
// We keep the following code in case the bootloader is some older version.
|
||||
gpio_matrix_out(psram_io.flash_cs_io, SPICS0_OUT_IDX, 0, 0);
|
||||
gpio_matrix_out(psram_io.psram_spiq_sd0_io, SPIQ_OUT_IDX, 0, 0);
|
||||
gpio_matrix_in(psram_io.psram_spiq_sd0_io, SPIQ_IN_IDX, 0);
|
||||
gpio_matrix_out(psram_io.psram_spid_sd1_io, SPID_OUT_IDX, 0, 0);
|
||||
gpio_matrix_in(psram_io.psram_spid_sd1_io, SPID_IN_IDX, 0);
|
||||
gpio_matrix_out(psram_io.psram_spiwp_sd3_io, SPIWP_OUT_IDX, 0, 0);
|
||||
gpio_matrix_in(psram_io.psram_spiwp_sd3_io, SPIWP_IN_IDX, 0);
|
||||
gpio_matrix_out(psram_io.psram_spihd_sd2_io, SPIHD_OUT_IDX, 0, 0);
|
||||
gpio_matrix_in(psram_io.psram_spihd_sd2_io, SPIHD_IN_IDX, 0);
|
||||
|
||||
switch (mode) {
|
||||
case PSRAM_CACHE_F80M_S40M:
|
||||
@@ -544,8 +527,8 @@ static void IRAM_ATTR psram_gpio_config(psram_io_t psram_io, psram_cache_mode_t
|
||||
esp_rom_spiflash_config_clk(_SPI_80M_CLK_DIV, _SPI_CACHE_PORT);
|
||||
esp_rom_spiflash_config_clk(_SPI_40M_CLK_DIV, _SPI_FLASH_PORT);
|
||||
//set drive ability for clock
|
||||
SET_PERI_REG_BITS(GPIO_PIN_MUX_REG[psram_io.flash_clk_io], FUN_DRV, 3, FUN_DRV_S);
|
||||
SET_PERI_REG_BITS(GPIO_PIN_MUX_REG[psram_io.psram_clk_io], FUN_DRV, 2, FUN_DRV_S);
|
||||
SET_PERI_REG_BITS(GPIO_PIN_MUX_REG[psram_io->flash_clk_io], FUN_DRV, 3, FUN_DRV_S);
|
||||
SET_PERI_REG_BITS(GPIO_PIN_MUX_REG[psram_io->psram_clk_io], FUN_DRV, 2, FUN_DRV_S);
|
||||
break;
|
||||
case PSRAM_CACHE_F80M_S80M:
|
||||
extra_dummy = PSRAM_IO_MATRIX_DUMMY_80M;
|
||||
@@ -555,8 +538,8 @@ static void IRAM_ATTR psram_gpio_config(psram_io_t psram_io, psram_cache_mode_t
|
||||
esp_rom_spiflash_config_clk(_SPI_80M_CLK_DIV, _SPI_CACHE_PORT);
|
||||
esp_rom_spiflash_config_clk(_SPI_80M_CLK_DIV, _SPI_FLASH_PORT);
|
||||
//set drive ability for clock
|
||||
SET_PERI_REG_BITS(GPIO_PIN_MUX_REG[psram_io.flash_clk_io], FUN_DRV, 3, FUN_DRV_S);
|
||||
SET_PERI_REG_BITS(GPIO_PIN_MUX_REG[psram_io.psram_clk_io], FUN_DRV, 3, FUN_DRV_S);
|
||||
SET_PERI_REG_BITS(GPIO_PIN_MUX_REG[psram_io->flash_clk_io], FUN_DRV, 3, FUN_DRV_S);
|
||||
SET_PERI_REG_BITS(GPIO_PIN_MUX_REG[psram_io->psram_clk_io], FUN_DRV, 3, FUN_DRV_S);
|
||||
break;
|
||||
case PSRAM_CACHE_F40M_S40M:
|
||||
extra_dummy = PSRAM_IO_MATRIX_DUMMY_40M;
|
||||
@@ -566,36 +549,54 @@ static void IRAM_ATTR psram_gpio_config(psram_io_t psram_io, psram_cache_mode_t
|
||||
esp_rom_spiflash_config_clk(_SPI_40M_CLK_DIV, _SPI_CACHE_PORT);
|
||||
esp_rom_spiflash_config_clk(_SPI_40M_CLK_DIV, _SPI_FLASH_PORT);
|
||||
//set drive ability for clock
|
||||
SET_PERI_REG_BITS(GPIO_PIN_MUX_REG[psram_io.flash_clk_io], FUN_DRV, 2, FUN_DRV_S);
|
||||
SET_PERI_REG_BITS(GPIO_PIN_MUX_REG[psram_io.psram_clk_io], FUN_DRV, 2, FUN_DRV_S);
|
||||
SET_PERI_REG_BITS(GPIO_PIN_MUX_REG[psram_io->flash_clk_io], FUN_DRV, 2, FUN_DRV_S);
|
||||
SET_PERI_REG_BITS(GPIO_PIN_MUX_REG[psram_io->psram_clk_io], FUN_DRV, 2, FUN_DRV_S);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
SET_PERI_REG_MASK(SPI_USER_REG(0), SPI_USR_DUMMY); // dummy en
|
||||
SET_PERI_REG_MASK(SPI_USER_REG(0), SPI_USR_DUMMY); // dummy enable
|
||||
|
||||
// In bootloader, all the signals are already configured,
|
||||
// We keep the following code in case the bootloader is some older version.
|
||||
gpio_matrix_out(psram_io->flash_cs_io, SPICS0_OUT_IDX, 0, 0);
|
||||
gpio_matrix_out(psram_io->psram_cs_io, SPICS1_OUT_IDX, 0, 0);
|
||||
gpio_matrix_out(psram_io->psram_spiq_sd0_io, SPIQ_OUT_IDX, 0, 0);
|
||||
gpio_matrix_in(psram_io->psram_spiq_sd0_io, SPIQ_IN_IDX, 0);
|
||||
gpio_matrix_out(psram_io->psram_spid_sd1_io, SPID_OUT_IDX, 0, 0);
|
||||
gpio_matrix_in(psram_io->psram_spid_sd1_io, SPID_IN_IDX, 0);
|
||||
gpio_matrix_out(psram_io->psram_spiwp_sd3_io, SPIWP_OUT_IDX, 0, 0);
|
||||
gpio_matrix_in(psram_io->psram_spiwp_sd3_io, SPIWP_IN_IDX, 0);
|
||||
gpio_matrix_out(psram_io->psram_spihd_sd2_io, SPIHD_OUT_IDX, 0, 0);
|
||||
gpio_matrix_in(psram_io->psram_spihd_sd2_io, SPIHD_IN_IDX, 0);
|
||||
|
||||
//select pin function gpio
|
||||
PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[psram_io.flash_spiq_sd0_io], PIN_FUNC_GPIO);
|
||||
PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[psram_io.flash_spid_sd1_io], PIN_FUNC_GPIO);
|
||||
PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[psram_io.flash_spihd_sd2_io], PIN_FUNC_GPIO);
|
||||
PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[psram_io.flash_spiwp_sd3_io], PIN_FUNC_GPIO);
|
||||
//flash clock signal should come from IO MUX.
|
||||
PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[psram_io.flash_clk_io], FUNC_SD_CLK_SPICLK);
|
||||
PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[psram_io.flash_cs_io], PIN_FUNC_GPIO);
|
||||
PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[psram_io.psram_cs_io], PIN_FUNC_GPIO);
|
||||
PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[psram_io.psram_clk_io], PIN_FUNC_GPIO);
|
||||
if ((psram_io->flash_clk_io == FLASH_CLK_IO) && (psram_io->flash_clk_io != psram_io->psram_clk_io)) {
|
||||
//flash clock signal should come from IO MUX.
|
||||
PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[psram_io->flash_clk_io], FUNC_SD_CLK_SPICLK);
|
||||
} else {
|
||||
//flash clock signal should come from GPIO matrix.
|
||||
PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[psram_io->flash_clk_io], PIN_FUNC_GPIO);
|
||||
}
|
||||
PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[psram_io->flash_cs_io], PIN_FUNC_GPIO);
|
||||
PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[psram_io->psram_cs_io], PIN_FUNC_GPIO);
|
||||
PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[psram_io->psram_clk_io], PIN_FUNC_GPIO);
|
||||
PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[psram_io->psram_spiq_sd0_io], PIN_FUNC_GPIO);
|
||||
PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[psram_io->psram_spid_sd1_io], PIN_FUNC_GPIO);
|
||||
PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[psram_io->psram_spihd_sd2_io], PIN_FUNC_GPIO);
|
||||
PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[psram_io->psram_spiwp_sd3_io], PIN_FUNC_GPIO);
|
||||
|
||||
uint32_t flash_id = g_rom_flashchip.device_id;
|
||||
if (flash_id == FLASH_ID_GD25LQ32C) {
|
||||
// Set drive ability for 1.8v flash in 80Mhz.
|
||||
SET_PERI_REG_BITS(GPIO_PIN_MUX_REG[psram_io.flash_spiq_sd0_io], FUN_DRV_V, 3, FUN_DRV_S);
|
||||
SET_PERI_REG_BITS(GPIO_PIN_MUX_REG[psram_io.flash_spid_sd1_io], FUN_DRV_V, 3, FUN_DRV_S);
|
||||
SET_PERI_REG_BITS(GPIO_PIN_MUX_REG[psram_io.flash_spihd_sd2_io], FUN_DRV_V, 3, FUN_DRV_S);
|
||||
SET_PERI_REG_BITS(GPIO_PIN_MUX_REG[psram_io.flash_spiwp_sd3_io], FUN_DRV_V, 3, FUN_DRV_S);
|
||||
SET_PERI_REG_BITS(GPIO_PIN_MUX_REG[psram_io.flash_cs_io], FUN_DRV_V, 3, FUN_DRV_S);
|
||||
SET_PERI_REG_BITS(GPIO_PIN_MUX_REG[psram_io.flash_clk_io], FUN_DRV_V, 3, FUN_DRV_S);
|
||||
SET_PERI_REG_BITS(GPIO_PIN_MUX_REG[psram_io.psram_cs_io], FUN_DRV_V, 3, FUN_DRV_S);
|
||||
SET_PERI_REG_BITS(GPIO_PIN_MUX_REG[psram_io.psram_clk_io], FUN_DRV_V, 3, FUN_DRV_S);
|
||||
SET_PERI_REG_BITS(GPIO_PIN_MUX_REG[psram_io->flash_cs_io], FUN_DRV_V, 3, FUN_DRV_S);
|
||||
SET_PERI_REG_BITS(GPIO_PIN_MUX_REG[psram_io->flash_clk_io], FUN_DRV_V, 3, FUN_DRV_S);
|
||||
SET_PERI_REG_BITS(GPIO_PIN_MUX_REG[psram_io->psram_cs_io], FUN_DRV_V, 3, FUN_DRV_S);
|
||||
SET_PERI_REG_BITS(GPIO_PIN_MUX_REG[psram_io->psram_clk_io], FUN_DRV_V, 3, FUN_DRV_S);
|
||||
SET_PERI_REG_BITS(GPIO_PIN_MUX_REG[psram_io->psram_spiq_sd0_io], FUN_DRV_V, 3, FUN_DRV_S);
|
||||
SET_PERI_REG_BITS(GPIO_PIN_MUX_REG[psram_io->psram_spid_sd1_io], FUN_DRV_V, 3, FUN_DRV_S);
|
||||
SET_PERI_REG_BITS(GPIO_PIN_MUX_REG[psram_io->psram_spihd_sd2_io], FUN_DRV_V, 3, FUN_DRV_S);
|
||||
SET_PERI_REG_BITS(GPIO_PIN_MUX_REG[psram_io->psram_spiwp_sd3_io], FUN_DRV_V, 3, FUN_DRV_S);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -612,15 +613,24 @@ psram_size_t psram_get_size()
|
||||
}
|
||||
}
|
||||
|
||||
//psram gpio init , different working frequency we have different solutions
|
||||
/*
|
||||
* Psram mode init will overwrite original flash speed mode, so that it is possible to change psram and flash speed after OTA.
|
||||
* Flash read mode(QIO/QOUT/DIO/DOUT) will not be changed in app bin. It is decided by bootloader, OTA can not change this mode.
|
||||
*/
|
||||
esp_err_t IRAM_ATTR psram_enable(psram_cache_mode_t mode, psram_vaddr_mode_t vaddrmode) //psram init
|
||||
{
|
||||
psram_io_t psram_io;
|
||||
psram_io_t psram_io = {0};
|
||||
uint32_t chip_ver = REG_GET_FIELD(EFUSE_BLK0_RDATA3_REG, EFUSE_RD_CHIP_VER_PKG);
|
||||
uint32_t pkg_ver = chip_ver & 0x7;
|
||||
if (pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32D2WDQ5) {
|
||||
ESP_EARLY_LOGE(TAG, "ESP32D2WD do not support psram yet");
|
||||
return ESP_FAIL;
|
||||
ESP_EARLY_LOGI(TAG, "This chip is ESP32-D2WD");
|
||||
rtc_vddsdio_config_t cfg = rtc_vddsdio_get_config();
|
||||
if (cfg.tieh != RTC_VDDSDIO_TIEH_1_8V) {
|
||||
ESP_EARLY_LOGE(TAG, "VDDSDIO is not 1.8V");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
psram_io.psram_clk_io = D2WD_PSRAM_CLK_IO;
|
||||
psram_io.psram_cs_io = D2WD_PSRAM_CS_IO;
|
||||
} else if ((pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32PICOD2) || (pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32PICOD4)) {
|
||||
ESP_EARLY_LOGI(TAG, "This chip is ESP32-PICO");
|
||||
rtc_vddsdio_config_t cfg = rtc_vddsdio_get_config();
|
||||
@@ -628,36 +638,49 @@ esp_err_t IRAM_ATTR psram_enable(psram_cache_mode_t mode, psram_vaddr_mode_t vad
|
||||
ESP_EARLY_LOGE(TAG, "VDDSDIO is not 3.3V");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
psram_io.flash_clk_io = PICO_FLASH_CLK_IO;
|
||||
psram_io.flash_cs_io = PICO_FLASH_CS_IO;
|
||||
psram_io.flash_spiq_sd0_io = PICO_FLASH_SPIQ_SD0_IO;
|
||||
psram_io.flash_spid_sd1_io = PICO_FLASH_SPID_SD1_IO;
|
||||
psram_io.flash_spiwp_sd3_io = PICO_FLASH_SPIWP_SD3_IO;
|
||||
psram_io.flash_spihd_sd2_io = PICO_FLASH_SPIHD_SD2_IO;
|
||||
psram_io.psram_clk_io = PICO_PSRAM_CLK_IO;
|
||||
psram_io.psram_cs_io = PICO_PSRAM_CS_IO;
|
||||
psram_io.psram_spiq_sd0_io = PICO_PSRAM_SPIQ_SD0_IO;
|
||||
psram_io.psram_spid_sd1_io = PICO_PSRAM_SPID_SD1_IO;
|
||||
psram_io.psram_spiwp_sd3_io = PICO_PSRAM_SPIWP_SD3_IO;
|
||||
psram_io.psram_spihd_sd2_io = PICO_PSRAM_SPIHD_SD2_IO;
|
||||
|
||||
s_clk_mode = PSRAM_CLK_MODE_NORM;
|
||||
psram_io.psram_clk_io = PICO_PSRAM_CLK_IO;
|
||||
psram_io.psram_cs_io = PICO_PSRAM_CS_IO;
|
||||
} else if ((pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32D0WDQ6) || (pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32D0WDQ5)){
|
||||
ESP_EARLY_LOGI(TAG, "This chip is ESP32-D0WD");
|
||||
psram_io.psram_clk_io = D0WD_PSRAM_CLK_IO;
|
||||
psram_io.psram_cs_io = D0WD_PSRAM_CS_IO;
|
||||
} else {
|
||||
ESP_EARLY_LOGE(TAG, "Not a valid or known package id: %d", pkg_ver);
|
||||
abort();
|
||||
}
|
||||
|
||||
const uint32_t spiconfig = ets_efuse_get_spiconfig();
|
||||
if (spiconfig == EFUSE_SPICONFIG_SPI_DEFAULTS) {
|
||||
psram_io.flash_clk_io = FLASH_CLK_IO;
|
||||
psram_io.flash_cs_io = FLASH_CS_IO;
|
||||
psram_io.flash_spiq_sd0_io = FLASH_SPIQ_SD0_IO;
|
||||
psram_io.flash_spid_sd1_io = FLASH_SPID_SD1_IO;
|
||||
psram_io.flash_spiwp_sd3_io = FLASH_SPIWP_SD3_IO;
|
||||
psram_io.flash_spihd_sd2_io = FLASH_SPIHD_SD2_IO;
|
||||
psram_io.psram_clk_io = PSRAM_CLK_IO;
|
||||
psram_io.psram_cs_io = PSRAM_CS_IO;
|
||||
psram_io.psram_spiq_sd0_io = PSRAM_SPIQ_SD0_IO;
|
||||
psram_io.psram_spid_sd1_io = PSRAM_SPID_SD1_IO;
|
||||
psram_io.psram_spiwp_sd3_io = PSRAM_SPIWP_SD3_IO;
|
||||
psram_io.psram_spihd_sd2_io = PSRAM_SPIHD_SD2_IO;
|
||||
} else if (spiconfig == EFUSE_SPICONFIG_HSPI_DEFAULTS) {
|
||||
psram_io.flash_clk_io = FLASH_HSPI_CLK_IO;
|
||||
psram_io.flash_cs_io = FLASH_HSPI_CS_IO;
|
||||
psram_io.psram_spiq_sd0_io = PSRAM_HSPI_SPIQ_SD0_IO;
|
||||
psram_io.psram_spid_sd1_io = PSRAM_HSPI_SPID_SD1_IO;
|
||||
psram_io.psram_spiwp_sd3_io = PSRAM_HSPI_SPIWP_SD3_IO;
|
||||
psram_io.psram_spihd_sd2_io = PSRAM_HSPI_SPIHD_SD2_IO;
|
||||
} else {
|
||||
psram_io.flash_clk_io = EFUSE_SPICONFIG_RET_SPICLK(spiconfig);
|
||||
psram_io.flash_cs_io = EFUSE_SPICONFIG_RET_SPICS0(spiconfig);
|
||||
psram_io.psram_spiq_sd0_io = EFUSE_SPICONFIG_RET_SPIQ(spiconfig);
|
||||
psram_io.psram_spid_sd1_io = EFUSE_SPICONFIG_RET_SPID(spiconfig);
|
||||
psram_io.psram_spihd_sd2_io = EFUSE_SPICONFIG_RET_SPIHD(spiconfig);
|
||||
|
||||
// If flash mode is set to QIO or QOUT, the WP pin is equal the value configured in bootloader.
|
||||
// If flash mode is set to DIO or DOUT, the WP pin should config it via menuconfig.
|
||||
#if CONFIG_FLASHMODE_QIO || CONFIG_FLASHMODE_QOUT
|
||||
psram_io.psram_spiwp_sd3_io = CONFIG_BOOTLOADER_SPI_WP_PIN;
|
||||
#else
|
||||
psram_io.psram_spiwp_sd3_io = CONFIG_SPIRAM_SPIWP_SD3_PIN;
|
||||
#endif
|
||||
}
|
||||
|
||||
WRITE_PERI_REG(GPIO_ENABLE_W1TC_REG, BIT(psram_io.psram_clk_io) | BIT(psram_io.psram_cs_io)); //DISABLE OUPUT FOR IO16/17
|
||||
assert(mode < PSRAM_CACHE_MAX && "we don't support any other mode for now.");
|
||||
s_psram_mode = mode;
|
||||
|
||||
@@ -666,7 +689,6 @@ esp_err_t IRAM_ATTR psram_enable(psram_cache_mode_t mode, psram_vaddr_mode_t vad
|
||||
|
||||
psram_spi_init(PSRAM_SPI_1, mode);
|
||||
|
||||
gpio_matrix_out(psram_io.psram_cs_io, SPICS1_OUT_IDX, 0, 0);
|
||||
switch (mode) {
|
||||
case PSRAM_CACHE_F80M_S80M:
|
||||
gpio_matrix_out(psram_io.psram_clk_io, SPICLK_OUT_IDX, 0, 0);
|
||||
@@ -691,25 +713,16 @@ esp_err_t IRAM_ATTR psram_enable(psram_cache_mode_t mode, psram_vaddr_mode_t vad
|
||||
}
|
||||
break;
|
||||
}
|
||||
#if CONFIG_BOOTLOADER_VDDSDIO_BOOST_1_9V
|
||||
// For flash 80Mhz, we must update ldo voltage in case older version of bootloader didn't do this.
|
||||
rtc_vddsdio_config_t cfg = rtc_vddsdio_get_config();
|
||||
if (cfg.enable == 1 && cfg.tieh == RTC_VDDSDIO_TIEH_1_8V) { // VDDSDIO regulator is enabled @ 1.8V
|
||||
cfg.drefh = 3;
|
||||
cfg.drefm = 3;
|
||||
cfg.drefl = 3;
|
||||
cfg.force = 1;
|
||||
rtc_vddsdio_set_config(cfg);
|
||||
ets_delay_us(10); // wait for regulator to become stable
|
||||
}
|
||||
#endif
|
||||
|
||||
// Rise VDDSIO for 1.8V psram.
|
||||
bootloader_common_vddsdio_configure();
|
||||
// GPIO related settings
|
||||
psram_gpio_config(psram_io, mode);
|
||||
psram_gpio_config(&psram_io, mode);
|
||||
psram_read_id(&s_psram_id);
|
||||
if (!PSRAM_IS_VALID(s_psram_id)) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
|
||||
if (PSRAM_IS_32MBIT_VER0(s_psram_id)) {
|
||||
s_clk_mode = PSRAM_CLK_MODE_DCLK;
|
||||
if (mode == PSRAM_CACHE_F80M_S80M) {
|
||||
@@ -776,42 +789,43 @@ static void IRAM_ATTR psram_cache_init(psram_cache_mode_t psram_cache_mode, psra
|
||||
CLEAR_PERI_REG_MASK(SPI_DATE_REG(0), BIT(30)); //pre clk div
|
||||
break;
|
||||
}
|
||||
SET_PERI_REG_MASK(SPI_CACHE_SCTRL_REG(0), SPI_CACHE_SRAM_USR_WCMD_M); // cache write command enable
|
||||
SET_PERI_REG_BITS(SPI_CACHE_SCTRL_REG(0), SPI_SRAM_ADDR_BITLEN_V, 23, SPI_SRAM_ADDR_BITLEN_S); //write address for cache command.
|
||||
SET_PERI_REG_MASK(SPI_CACHE_SCTRL_REG(0), SPI_USR_SRAM_QIO_M); //enable qio mode for cache command
|
||||
CLEAR_PERI_REG_MASK(SPI_CACHE_SCTRL_REG(0), SPI_USR_SRAM_DIO_M); //disable dio mode for cache command
|
||||
|
||||
SET_PERI_REG_MASK(SPI_CACHE_SCTRL_REG(0), SPI_USR_RD_SRAM_DUMMY_M); //enable cache read dummy
|
||||
SET_PERI_REG_MASK(SPI_CACHE_SCTRL_REG(0), SPI_CACHE_SRAM_USR_RCMD_M); //enable user mode for cache read command
|
||||
CLEAR_PERI_REG_MASK(SPI_CACHE_SCTRL_REG(0), SPI_USR_SRAM_DIO_M); //disable dio mode for cache command
|
||||
SET_PERI_REG_MASK(SPI_CACHE_SCTRL_REG(0), SPI_USR_SRAM_QIO_M); //enable qio mode for cache command
|
||||
SET_PERI_REG_MASK(SPI_CACHE_SCTRL_REG(0), SPI_CACHE_SRAM_USR_RCMD_M); //enable cache read command
|
||||
SET_PERI_REG_MASK(SPI_CACHE_SCTRL_REG(0), SPI_CACHE_SRAM_USR_WCMD_M); //enable cache write command
|
||||
SET_PERI_REG_BITS(SPI_CACHE_SCTRL_REG(0), SPI_SRAM_ADDR_BITLEN_V, 23, SPI_SRAM_ADDR_BITLEN_S); //write address for cache command.
|
||||
SET_PERI_REG_MASK(SPI_CACHE_SCTRL_REG(0), SPI_USR_RD_SRAM_DUMMY_M); //enable cache read dummy
|
||||
|
||||
//config sram cache r/w command
|
||||
SET_PERI_REG_BITS(SPI_SRAM_DRD_CMD_REG(0), SPI_CACHE_SRAM_USR_RD_CMD_BITLEN_V, 7,
|
||||
SPI_CACHE_SRAM_USR_RD_CMD_BITLEN_S);
|
||||
SET_PERI_REG_BITS(SPI_SRAM_DRD_CMD_REG(0), SPI_CACHE_SRAM_USR_RD_CMD_VALUE_V, PSRAM_FAST_READ_QUAD,
|
||||
SPI_CACHE_SRAM_USR_RD_CMD_VALUE_S); //0xEB
|
||||
SET_PERI_REG_BITS(SPI_SRAM_DWR_CMD_REG(0), SPI_CACHE_SRAM_USR_WR_CMD_BITLEN, 7,
|
||||
SPI_CACHE_SRAM_USR_WR_CMD_BITLEN_S);
|
||||
SET_PERI_REG_BITS(SPI_SRAM_DWR_CMD_REG(0), SPI_CACHE_SRAM_USR_WR_CMD_VALUE, PSRAM_QUAD_WRITE,
|
||||
SPI_CACHE_SRAM_USR_WR_CMD_VALUE_S); //0x38
|
||||
SET_PERI_REG_BITS(SPI_SRAM_DRD_CMD_REG(0), SPI_CACHE_SRAM_USR_RD_CMD_BITLEN_V, 7,
|
||||
SPI_CACHE_SRAM_USR_RD_CMD_BITLEN_S);
|
||||
SET_PERI_REG_BITS(SPI_SRAM_DRD_CMD_REG(0), SPI_CACHE_SRAM_USR_RD_CMD_VALUE_V, PSRAM_FAST_READ_QUAD,
|
||||
SPI_CACHE_SRAM_USR_RD_CMD_VALUE_S); //0x0b
|
||||
SET_PERI_REG_BITS(SPI_CACHE_SCTRL_REG(0), SPI_SRAM_DUMMY_CYCLELEN_V, PSRAM_FAST_READ_QUAD_DUMMY + extra_dummy,
|
||||
SPI_SRAM_DUMMY_CYCLELEN_S); //dummy, psram cache : 40m--+1dummy,80m--+2dummy
|
||||
SPI_SRAM_DUMMY_CYCLELEN_S); //dummy, psram cache : 40m--+1dummy; 80m--+2dummy
|
||||
|
||||
//config sram cache r/w command
|
||||
switch (psram_cache_mode) {
|
||||
case PSRAM_CACHE_F80M_S80M: //in this mode , no delay is needed
|
||||
break;
|
||||
case PSRAM_CACHE_F80M_S40M: //is sram is @40M, need 2 cycles of delay
|
||||
case PSRAM_CACHE_F80M_S40M: //if sram is @40M, need 2 cycles of delay
|
||||
case PSRAM_CACHE_F40M_S40M:
|
||||
default:
|
||||
if (s_clk_mode == PSRAM_CLK_MODE_DCLK) {
|
||||
SET_PERI_REG_BITS(SPI_SRAM_DRD_CMD_REG(0), SPI_CACHE_SRAM_USR_RD_CMD_BITLEN_V, 15,
|
||||
SPI_CACHE_SRAM_USR_RD_CMD_BITLEN_S); //read command length, 2 bytes(1byte for delay),sending in qio mode in cache
|
||||
SET_PERI_REG_BITS(SPI_SRAM_DRD_CMD_REG(0), SPI_CACHE_SRAM_USR_RD_CMD_VALUE_V, ((PSRAM_FAST_READ_QUAD) << 8),
|
||||
SPI_CACHE_SRAM_USR_RD_CMD_VALUE_S); //0x0b, read command value,(0x00 for delay,0x0b for cmd)
|
||||
SPI_CACHE_SRAM_USR_RD_CMD_VALUE_S); //0xEB, read command value,(0x00 for delay,0xeb for cmd)
|
||||
SET_PERI_REG_BITS(SPI_SRAM_DWR_CMD_REG(0), SPI_CACHE_SRAM_USR_WR_CMD_BITLEN, 15,
|
||||
SPI_CACHE_SRAM_USR_WR_CMD_BITLEN_S); //write command length,2 bytes(1byte for delay,send in qio mode in cache)
|
||||
SET_PERI_REG_BITS(SPI_SRAM_DWR_CMD_REG(0), SPI_CACHE_SRAM_USR_WR_CMD_VALUE, ((PSRAM_QUAD_WRITE) << 8),
|
||||
SPI_CACHE_SRAM_USR_WR_CMD_VALUE_S); //0x38, write command value,(0x00 for delay)
|
||||
SET_PERI_REG_BITS(SPI_CACHE_SCTRL_REG(0), SPI_SRAM_DUMMY_CYCLELEN_V, PSRAM_FAST_READ_QUAD_DUMMY + extra_dummy,
|
||||
SPI_SRAM_DUMMY_CYCLELEN_S); //dummy, psram cache : 40m--+1dummy,80m--+2dummy
|
||||
SPI_SRAM_DUMMY_CYCLELEN_S); //dummy, psram cache : 40m--+1dummy; 80m--+2dummy
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -205,7 +205,7 @@ esp_err_t esp_read_mac(uint8_t* mac, esp_mac_type_t type)
|
||||
ESP_LOGW(TAG, "incorrect mac type");
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
@@ -296,16 +296,16 @@ void IRAM_ATTR esp_restart_noos()
|
||||
WRITE_PERI_REG(GPIO_FUNC5_IN_SEL_CFG_REG, 0x30);
|
||||
|
||||
// Reset wifi/bluetooth/ethernet/sdio (bb/mac)
|
||||
DPORT_SET_PERI_REG_MASK(DPORT_CORE_RST_EN_REG,
|
||||
DPORT_SET_PERI_REG_MASK(DPORT_CORE_RST_EN_REG,
|
||||
DPORT_BB_RST | DPORT_FE_RST | DPORT_MAC_RST |
|
||||
DPORT_BT_RST | DPORT_BTMAC_RST | DPORT_SDIO_RST |
|
||||
DPORT_SDIO_HOST_RST | DPORT_EMAC_RST | DPORT_MACPWR_RST |
|
||||
DPORT_SDIO_HOST_RST | DPORT_EMAC_RST | DPORT_MACPWR_RST |
|
||||
DPORT_RW_BTMAC_RST | DPORT_RW_BTLP_RST);
|
||||
DPORT_REG_WRITE(DPORT_CORE_RST_EN_REG, 0);
|
||||
|
||||
// Reset timer/spi/uart
|
||||
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG,
|
||||
DPORT_TIMERS_RST | DPORT_SPI01_RST | DPORT_UART_RST);
|
||||
DPORT_TIMERS_RST | DPORT_SPI01_RST | DPORT_UART_RST | DPORT_UART1_RST | DPORT_UART2_RST);
|
||||
DPORT_REG_WRITE(DPORT_PERIP_RST_EN_REG, 0);
|
||||
|
||||
// Set CPU back to XTAL source, no PLL, same as hard reset
|
||||
@@ -355,35 +355,27 @@ const char* esp_get_idf_version(void)
|
||||
return IDF_VER;
|
||||
}
|
||||
|
||||
static void get_chip_info_esp32(esp_chip_info_t* out_info)
|
||||
void esp_chip_info(esp_chip_info_t* out_info)
|
||||
{
|
||||
uint32_t reg = REG_READ(EFUSE_BLK0_RDATA3_REG);
|
||||
uint32_t efuse_rd3 = REG_READ(EFUSE_BLK0_RDATA3_REG);
|
||||
memset(out_info, 0, sizeof(*out_info));
|
||||
|
||||
|
||||
out_info->model = CHIP_ESP32;
|
||||
if ((reg & EFUSE_RD_CHIP_VER_REV1_M) != 0) {
|
||||
out_info->revision = 1;
|
||||
}
|
||||
if ((reg & EFUSE_RD_CHIP_VER_DIS_APP_CPU_M) == 0) {
|
||||
out_info->revision = esp_efuse_get_chip_ver();
|
||||
|
||||
if ((efuse_rd3 & EFUSE_RD_CHIP_VER_DIS_APP_CPU_M) == 0) {
|
||||
out_info->cores = 2;
|
||||
} else {
|
||||
out_info->cores = 1;
|
||||
}
|
||||
out_info->features = CHIP_FEATURE_WIFI_BGN;
|
||||
if ((reg & EFUSE_RD_CHIP_VER_DIS_BT_M) == 0) {
|
||||
if ((efuse_rd3 & EFUSE_RD_CHIP_VER_DIS_BT_M) == 0) {
|
||||
out_info->features |= CHIP_FEATURE_BT | CHIP_FEATURE_BLE;
|
||||
}
|
||||
int package = (reg & EFUSE_RD_CHIP_VER_PKG_M) >> EFUSE_RD_CHIP_VER_PKG_S;
|
||||
int package = (efuse_rd3 & EFUSE_RD_CHIP_VER_PKG_M) >> EFUSE_RD_CHIP_VER_PKG_S;
|
||||
if (package == EFUSE_RD_CHIP_VER_PKG_ESP32D2WDQ5 ||
|
||||
package == EFUSE_RD_CHIP_VER_PKG_ESP32PICOD2 ||
|
||||
package == EFUSE_RD_CHIP_VER_PKG_ESP32PICOD4) {
|
||||
out_info->features |= CHIP_FEATURE_EMB_FLASH;
|
||||
}
|
||||
}
|
||||
|
||||
void esp_chip_info(esp_chip_info_t* out_info)
|
||||
{
|
||||
// Only ESP32 is supported now, in the future call one of the
|
||||
// chip-specific functions based on sdkconfig choice
|
||||
return get_chip_info_esp32(out_info);
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
|
||||
#include "esp_event.h"
|
||||
#include "esp_event_internal.h"
|
||||
#include "esp_task.h"
|
||||
|
||||
/* ------------------------- Static Variables ------------------------------- */
|
||||
|
||||
|
||||
@@ -297,6 +297,26 @@ esp_err_t esp_http_client_delete_header(esp_http_client_handle_t client, const c
|
||||
return http_header_delete(client->request->headers, key);
|
||||
}
|
||||
|
||||
esp_err_t esp_http_client_get_username(esp_http_client_handle_t client, char **value)
|
||||
{
|
||||
if (client == NULL || value == NULL) {
|
||||
ESP_LOGE(TAG, "client or value must not be NULL");
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
*value = client->connection_info.username;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_http_client_get_password(esp_http_client_handle_t client, char **value)
|
||||
{
|
||||
if (client == NULL || value == NULL) {
|
||||
ESP_LOGE(TAG, "client or value must not be NULL");
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
*value = client->connection_info.password;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t _set_config(esp_http_client_handle_t client, const esp_http_client_config_t *config)
|
||||
{
|
||||
client->connection_info.method = config->method;
|
||||
@@ -589,6 +609,17 @@ esp_err_t esp_http_client_cleanup(esp_http_client_handle_t client)
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_http_client_set_redirection(esp_http_client_handle_t client)
|
||||
{
|
||||
if (client == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
if (client->location == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
return esp_http_client_set_url(client, client->location);
|
||||
}
|
||||
|
||||
static esp_err_t esp_http_check_response(esp_http_client_handle_t client)
|
||||
{
|
||||
char *auth_header = NULL;
|
||||
@@ -661,10 +692,15 @@ esp_err_t esp_http_client_set_url(esp_http_client_handle_t client, const char *u
|
||||
ESP_LOGE(TAG, "Error parse url %s", url);
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
old_host = client->connection_info.host;
|
||||
if (client->connection_info.host) {
|
||||
old_host = strdup(client->connection_info.host);
|
||||
}
|
||||
old_port = client->connection_info.port;
|
||||
|
||||
if (purl.field_data[UF_HOST].len) {
|
||||
// Whether the passed url is absolute or is just a path
|
||||
bool is_absolute_url = (bool) purl.field_data[UF_HOST].len;
|
||||
|
||||
if (is_absolute_url) {
|
||||
http_utils_assign_string(&client->connection_info.host, url + purl.field_data[UF_HOST].off, purl.field_data[UF_HOST].len);
|
||||
HTTP_MEM_CHECK(TAG, client->connection_info.host, return ESP_ERR_NO_MEM);
|
||||
}
|
||||
@@ -673,11 +709,17 @@ esp_err_t esp_http_client_set_url(esp_http_client_handle_t client, const char *u
|
||||
&& strcasecmp(old_host, (const void *)client->connection_info.host) != 0) {
|
||||
ESP_LOGD(TAG, "New host assign = %s", client->connection_info.host);
|
||||
if (esp_http_client_set_header(client, "Host", client->connection_info.host) != ESP_OK) {
|
||||
free(old_host);
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
esp_http_client_close(client);
|
||||
}
|
||||
|
||||
if (old_host) {
|
||||
free(old_host);
|
||||
old_host = NULL;
|
||||
}
|
||||
|
||||
if (purl.field_data[UF_SCHEMA].len) {
|
||||
http_utils_assign_string(&client->connection_info.scheme, url + purl.field_data[UF_SCHEMA].off, purl.field_data[UF_SCHEMA].len);
|
||||
HTTP_MEM_CHECK(TAG, client->connection_info.scheme, return ESP_ERR_NO_MEM);
|
||||
@@ -715,7 +757,8 @@ esp_err_t esp_http_client_set_url(esp_http_client_handle_t client, const char *u
|
||||
} else {
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
} else {
|
||||
} else if (is_absolute_url) {
|
||||
// Only reset authentication info if the passed URL is full
|
||||
free(client->connection_info.username);
|
||||
free(client->connection_info.password);
|
||||
client->connection_info.username = NULL;
|
||||
@@ -1076,6 +1119,7 @@ static esp_err_t esp_http_client_request_send(esp_http_client_handle_t client, i
|
||||
|
||||
client->data_written_index = 0;
|
||||
client->data_write_left = client->post_len;
|
||||
http_dispatch_event(client, HTTP_EVENT_HEADER_SENT, NULL, 0);
|
||||
client->state = HTTP_STATE_REQ_COMPLETE_HEADER;
|
||||
return ESP_OK;
|
||||
}
|
||||
@@ -1116,7 +1160,7 @@ esp_err_t esp_http_client_open(esp_http_client_handle_t client, int write_len)
|
||||
return err;
|
||||
}
|
||||
if ((err = esp_http_client_request_send(client, write_len)) != ESP_OK) {
|
||||
return err;
|
||||
return err;
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
@@ -235,13 +235,43 @@ esp_err_t esp_http_client_set_header(esp_http_client_handle_t client, const char
|
||||
*/
|
||||
esp_err_t esp_http_client_get_header(esp_http_client_handle_t client, const char *key, char **value);
|
||||
|
||||
/**
|
||||
* @brief Get http request username.
|
||||
* The address of username buffer will be assigned to value parameter.
|
||||
* This function must be called after `esp_http_client_init`.
|
||||
*
|
||||
* @param[in] client The esp_http_client handle
|
||||
* @param[out] value The username value
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK
|
||||
* - ESP_ERR_INVALID_ARG
|
||||
*/
|
||||
esp_err_t esp_http_client_get_username(esp_http_client_handle_t client, char **value);
|
||||
|
||||
/**
|
||||
* @brief Get http request password.
|
||||
* The address of password buffer will be assigned to value parameter.
|
||||
* This function must be called after `esp_http_client_init`.
|
||||
*
|
||||
* @param[in] client The esp_http_client handle
|
||||
* @param[out] value The password value
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK
|
||||
* - ESP_ERR_INVALID_ARG
|
||||
*/
|
||||
esp_err_t esp_http_client_get_password(esp_http_client_handle_t client, char **value);
|
||||
|
||||
/**
|
||||
* @brief Set http request method
|
||||
*
|
||||
* @param[in] client The esp_http_client handle
|
||||
* @param[in] method The method
|
||||
*
|
||||
* @return ESP_OK
|
||||
* @return
|
||||
* - ESP_OK
|
||||
* - ESP_ERR_INVALID_ARG
|
||||
*/
|
||||
esp_err_t esp_http_client_set_method(esp_http_client_handle_t client, esp_http_client_method_t method);
|
||||
|
||||
@@ -376,6 +406,18 @@ esp_err_t esp_http_client_cleanup(esp_http_client_handle_t client);
|
||||
*/
|
||||
esp_http_client_transport_t esp_http_client_get_transport_type(esp_http_client_handle_t client);
|
||||
|
||||
/**
|
||||
* @brief Set redirection URL.
|
||||
* When received the 30x code from the server, the client stores the redirect URL provided by the server.
|
||||
* This function will set the current URL to redirect to enable client to execute the redirection request.
|
||||
*
|
||||
* @param[in] client The esp_http_client handle
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK
|
||||
* - ESP_FAIL
|
||||
*/
|
||||
esp_err_t esp_http_client_set_redirection(esp_http_client_handle_t client);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -20,7 +20,11 @@
|
||||
#include "unity.h"
|
||||
#include "test_utils.h"
|
||||
|
||||
TEST_CASE("Input Param Tests", "[ESP HTTP CLIENT]")
|
||||
#define HOST "httpbin.org"
|
||||
#define USERNAME "user"
|
||||
#define PASSWORD "challenge"
|
||||
|
||||
TEST_CASE("Test in common case: Only URL and hostname are specified.", "[ESP HTTP CLIENT]")
|
||||
{
|
||||
esp_http_client_config_t config_incorrect = {0};
|
||||
|
||||
@@ -38,10 +42,88 @@ TEST_CASE("Input Param Tests", "[ESP HTTP CLIENT]")
|
||||
|
||||
|
||||
esp_http_client_config_t config_with_hostname_path = {
|
||||
.host = "httpbin.org",
|
||||
.host = HOST,
|
||||
.path = "/get",
|
||||
};
|
||||
client = esp_http_client_init(&config_with_hostname_path);
|
||||
TEST_ASSERT(client != NULL);
|
||||
TEST_ASSERT(esp_http_client_cleanup(client) == ESP_OK);
|
||||
}
|
||||
|
||||
TEST_CASE("Get username and password after initialization.", "[ESP HTTP CLIENT]")
|
||||
{
|
||||
esp_http_client_config_t config_with_auth = {
|
||||
.host = HOST,
|
||||
.path = "/",
|
||||
.username = USERNAME,
|
||||
.password = PASSWORD
|
||||
};
|
||||
char *value = NULL;
|
||||
esp_http_client_handle_t client = esp_http_client_init(&config_with_auth);
|
||||
TEST_ASSERT_NOT_NULL(client);
|
||||
// Test with username
|
||||
esp_err_t r = esp_http_client_get_username(client, &value);
|
||||
TEST_ASSERT_EQUAL(ESP_OK, r);
|
||||
TEST_ASSERT_NOT_NULL(value);
|
||||
TEST_ASSERT_EQUAL_STRING(USERNAME, value);
|
||||
// Test with password
|
||||
value = NULL;
|
||||
r = esp_http_client_get_password(client, &value);
|
||||
TEST_ASSERT_EQUAL(ESP_OK, r);
|
||||
TEST_ASSERT_NOT_NULL(value);
|
||||
TEST_ASSERT_EQUAL_STRING(PASSWORD, value);
|
||||
esp_http_client_cleanup(client);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test case to test that, the esp_http_client_set_url won't drop username and password
|
||||
* when pass a path "/abc" for url.
|
||||
**/
|
||||
TEST_CASE("Username is unmodified when we change to new path", "[ESP HTTP CLIENT]")
|
||||
{
|
||||
esp_http_client_config_t config_with_auth = {
|
||||
.host = HOST,
|
||||
.path = "/",
|
||||
.username = USERNAME,
|
||||
.password = PASSWORD
|
||||
};
|
||||
char *value = NULL;
|
||||
esp_http_client_handle_t client = esp_http_client_init(&config_with_auth);
|
||||
TEST_ASSERT_NOT_NULL(client);
|
||||
esp_err_t r = esp_http_client_get_username(client, &value);
|
||||
TEST_ASSERT_EQUAL(ESP_OK, r);
|
||||
TEST_ASSERT_NOT_NULL(value);
|
||||
TEST_ASSERT_EQUAL_STRING(USERNAME, value);
|
||||
esp_http_client_set_url(client, "/something-else/");
|
||||
r = esp_http_client_get_username(client, &value);
|
||||
TEST_ASSERT_EQUAL(ESP_OK, r);
|
||||
TEST_ASSERT_NOT_NULL(value);
|
||||
TEST_ASSERT_EQUAL_STRING(USERNAME, value);
|
||||
esp_http_client_cleanup(client);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test case to test that, the esp_http_client_set_url will reset username and password
|
||||
* when passing a full URL with username & password missing.
|
||||
**/
|
||||
TEST_CASE("Username is reset if new absolute URL doesnot specify username.", "[ESP HTTP CLIENT]")
|
||||
{
|
||||
esp_http_client_config_t config_with_auth = {
|
||||
.host = HOST,
|
||||
.path = "/",
|
||||
.username = USERNAME,
|
||||
.password = PASSWORD
|
||||
};
|
||||
char *value = NULL;
|
||||
esp_http_client_handle_t client = esp_http_client_init(&config_with_auth);
|
||||
TEST_ASSERT_NOT_NULL(client);
|
||||
esp_err_t r = esp_http_client_get_username(client, &value);
|
||||
TEST_ASSERT_EQUAL(ESP_OK, r);
|
||||
TEST_ASSERT_NOT_NULL(value);
|
||||
TEST_ASSERT_EQUAL_STRING(USERNAME, value);
|
||||
esp_http_client_set_url(client, "http://" HOST "/get");
|
||||
r = esp_http_client_get_username(client, &value);
|
||||
TEST_ASSERT_EQUAL(ESP_OK, r);
|
||||
TEST_ASSERT_NULL(value);
|
||||
esp_http_client_cleanup(client);
|
||||
}
|
||||
|
||||
@@ -20,4 +20,23 @@ menu "HTTP Server"
|
||||
Using TCP_NODEALY socket option ensures that HTTP error response reaches the client before the
|
||||
underlying socket is closed. Please note that turning this off may cause multiple test failures
|
||||
|
||||
config HTTPD_PURGE_BUF_LEN
|
||||
int "Length of temporary buffer for purging data"
|
||||
default 32
|
||||
help
|
||||
This sets the size of the temporary buffer used to receive and discard any remaining data that is
|
||||
received from the HTTP client in the request, but not processed as part of the server HTTP request
|
||||
handler.
|
||||
|
||||
If the remaining data is larger than the available buffer size, the buffer will be filled in multiple
|
||||
iterations. The buffer should be small enough to fit on the stack, but large enough to avoid excessive
|
||||
iterations.
|
||||
|
||||
config HTTPD_LOG_PURGE_DATA
|
||||
bool "Log purged content data at Debug level"
|
||||
default n
|
||||
help
|
||||
Enabling this will log discarded binary HTTP request data at Debug level.
|
||||
For large content data this may not be desirable as it will clutter the log.
|
||||
|
||||
endmenu
|
||||
|
||||
@@ -99,7 +99,9 @@ typedef void (*httpd_free_ctx_fn_t)(void *ctx);
|
||||
*
|
||||
* @param[in] hd server instance
|
||||
* @param[in] sockfd session socket file descriptor
|
||||
* @return status
|
||||
* @return
|
||||
* - ESP_OK : On success
|
||||
* - Any value other than ESP_OK will signal the server to close the socket immediately
|
||||
*/
|
||||
typedef esp_err_t (*httpd_open_func_t)(httpd_handle_t hd, int sockfd);
|
||||
|
||||
@@ -199,6 +201,8 @@ typedef struct httpd_config {
|
||||
*
|
||||
* If a context needs to be maintained between these functions, store it in the session using
|
||||
* httpd_sess_set_transport_ctx() and retrieve it later with httpd_sess_get_transport_ctx()
|
||||
*
|
||||
* Returning a value other than ESP_OK will immediately close the new socket.
|
||||
*/
|
||||
httpd_open_func_t open_fn;
|
||||
|
||||
@@ -870,7 +874,10 @@ size_t httpd_req_get_url_query_len(httpd_req_t *r);
|
||||
* a URI handler where httpd_req_t* request pointer is valid
|
||||
* - If output size is greater than input, then the value is truncated,
|
||||
* accompanied by truncation error as return value
|
||||
* - Use httpd_req_get_url_query_len() to know the right buffer length
|
||||
* - Prior to calling this function, one can use httpd_req_get_url_query_len()
|
||||
* to know the query string length beforehand and hence allocate the buffer
|
||||
* of right size (usually query string length + 1 for null termination)
|
||||
* for storing the query string
|
||||
*
|
||||
* @param[in] r The request being responded to
|
||||
* @param[out] buf Pointer to the buffer into which the query string will be copied (if found)
|
||||
|
||||
@@ -254,6 +254,15 @@ static esp_err_t httpd_server_init(struct httpd_data *hd)
|
||||
.sin6_port = htons(hd->config.server_port)
|
||||
};
|
||||
|
||||
/* Enable SO_REUSEADDR to allow binding to the same
|
||||
* address and port when restarting the server */
|
||||
int enable = 1;
|
||||
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(enable)) < 0) {
|
||||
/* This will fail if CONFIG_LWIP_SO_REUSE is not enabled. But
|
||||
* it does not affect the normal working of the HTTP Server */
|
||||
ESP_LOGW(TAG, LOG_FMT("error enabling SO_REUSEADDR (%d)"), errno);
|
||||
}
|
||||
|
||||
int ret = bind(fd, (struct sockaddr *)&serv_addr, sizeof(serv_addr));
|
||||
if (ret < 0) {
|
||||
ESP_LOGE(TAG, LOG_FMT("error in bind (%d)"), errno);
|
||||
|
||||
@@ -711,18 +711,25 @@ esp_err_t httpd_req_delete(struct httpd_data *hd)
|
||||
/* Finish off reading any pending/leftover data */
|
||||
while (ra->remaining_len) {
|
||||
/* Any length small enough not to overload the stack, but large
|
||||
* enough to finish off the buffers fast
|
||||
*/
|
||||
char dummy[32];
|
||||
int recv_len = MIN(sizeof(dummy) - 1, ra->remaining_len);
|
||||
int ret = httpd_req_recv(r, dummy, recv_len);
|
||||
if (ret < 0) {
|
||||
* enough to finish off the buffers fast */
|
||||
char dummy[CONFIG_HTTPD_PURGE_BUF_LEN];
|
||||
int recv_len = MIN(sizeof(dummy), ra->remaining_len);
|
||||
recv_len = httpd_req_recv(r, dummy, recv_len);
|
||||
if (recv_len < 0) {
|
||||
httpd_req_cleanup(r);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
dummy[ret] = '\0';
|
||||
ESP_LOGD(TAG, LOG_FMT("purging data : %s"), dummy);
|
||||
ESP_LOGD(TAG, LOG_FMT("purging data size : %d bytes"), recv_len);
|
||||
|
||||
#ifdef CONFIG_HTTPD_LOG_PURGE_DATA
|
||||
/* Enabling this will log discarded binary HTTP content data at
|
||||
* Debug level. For large content data this may not be desirable
|
||||
* as it will clutter the log */
|
||||
ESP_LOGD(TAG, "================= PURGED DATA =================");
|
||||
ESP_LOG_BUFFER_HEX_LEVEL(TAG, dummy, recv_len, ESP_LOG_DEBUG);
|
||||
ESP_LOGD(TAG, "===============================================");
|
||||
#endif
|
||||
}
|
||||
|
||||
httpd_req_cleanup(r);
|
||||
|
||||
@@ -77,7 +77,11 @@ esp_err_t httpd_sess_new(struct httpd_data *hd, int newfd)
|
||||
/* Call user-defined session opening function */
|
||||
if (hd->config.open_fn) {
|
||||
esp_err_t ret = hd->config.open_fn(hd, hd->hd_sd[i].fd);
|
||||
if (ret != ESP_OK) return ret;
|
||||
if (ret != ESP_OK) {
|
||||
httpd_sess_delete(hd, hd->hd_sd[i].fd);
|
||||
ESP_LOGD(TAG, LOG_FMT("open_fn failed for fd = %d"), newfd);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
Submodule components/esptool_py/esptool updated: 9ad444a6e0...1a7dbf787e
@@ -75,6 +75,7 @@ struct emac_config_data {
|
||||
eth_phy_get_partner_pause_enable_func emac_phy_get_partner_pause_enable;
|
||||
eth_phy_power_enable_func emac_phy_power_enable;
|
||||
uint32_t reset_timeout_ms;
|
||||
bool promiscuous_enable;
|
||||
};
|
||||
|
||||
enum emac_post_type {
|
||||
|
||||
@@ -99,3 +99,13 @@ void emac_mac_init(void)
|
||||
REG_CLR_BIT(EMAC_GMACCONFIG_REG, EMAC_EMACFESPEED);
|
||||
REG_SET_BIT(EMAC_GMACFF_REG, EMAC_PAM);
|
||||
}
|
||||
|
||||
void emac_enable_promiscuous(void)
|
||||
{
|
||||
REG_SET_BIT(EMAC_GMACFF_REG, EMAC_PMODE);
|
||||
}
|
||||
|
||||
void emac_disable_promiscuous(void)
|
||||
{
|
||||
REG_CLR_BIT(EMAC_GMACFF_REG, EMAC_PMODE);
|
||||
}
|
||||
|
||||
@@ -53,6 +53,8 @@ void emac_disable_dma_rx(void);
|
||||
void emac_enable_flowctrl(void);
|
||||
void emac_disable_flowctrl(void);
|
||||
void emac_mac_enable_txrx(void);
|
||||
void emac_enable_promiscuous(void);
|
||||
void emac_disable_promiscuous(void);
|
||||
|
||||
static inline uint32_t emac_read_tx_cur_reg(void)
|
||||
{
|
||||
|
||||
@@ -325,6 +325,7 @@ static void emac_set_user_config_data(eth_config_t *config)
|
||||
#endif
|
||||
emac_config.emac_phy_get_partner_pause_enable = config->phy_get_partner_pause_enable;
|
||||
emac_config.emac_phy_power_enable = config->phy_power_enable;
|
||||
emac_config.promiscuous_enable = config->promiscuous_enable;
|
||||
}
|
||||
|
||||
static void emac_enable_intr()
|
||||
@@ -823,6 +824,13 @@ static void emac_start(void *param)
|
||||
|
||||
emac_mac_init();
|
||||
|
||||
/* check if enable promiscuous mode */
|
||||
if(emac_config.promiscuous_enable){
|
||||
emac_enable_promiscuous();
|
||||
}else{
|
||||
emac_disable_promiscuous();
|
||||
}
|
||||
|
||||
emac_enable_intr();
|
||||
|
||||
emac_config.emac_status = EMAC_RUNTIME_START;
|
||||
|
||||
@@ -70,11 +70,19 @@ esp_err_t phy_ip101_init(void)
|
||||
esp_err_t res1, res2;
|
||||
ESP_LOGD(TAG, "phy_ip101_init()");
|
||||
phy_ip101_dump_registers();
|
||||
|
||||
esp_eth_smi_write(MII_BASIC_MODE_CONTROL_REG, MII_SOFTWARE_RESET);
|
||||
|
||||
do {
|
||||
// Call esp_eth_smi_wait_value() with a timeout so it prints an error periodically
|
||||
res1 = esp_eth_smi_wait_value(MII_PHY_IDENTIFIER_1_REG, IP101_PHY_ID1, UINT16_MAX, 1000);
|
||||
res2 = esp_eth_smi_wait_value(MII_PHY_IDENTIFIER_2_REG, IP101_PHY_ID2, IP101_PHY_ID2_MASK, 1000);
|
||||
} while (res1 != ESP_OK || res2 != ESP_OK);
|
||||
|
||||
uint32_t data = esp_eth_smi_read(MII_BASIC_MODE_CONTROL_REG);
|
||||
data |= MII_AUTO_NEGOTIATION_ENABLE | MII_RESTART_AUTO_NEGOTIATION;
|
||||
esp_eth_smi_write(MII_BASIC_MODE_CONTROL_REG, data);
|
||||
|
||||
ets_delay_us(300);
|
||||
// TODO: only do this if config.flow_ctrl_enable == true
|
||||
phy_mii_enable_flow_ctrl();
|
||||
@@ -97,6 +105,8 @@ const eth_config_t phy_ip101_default_ethernet_config = {
|
||||
.phy_get_duplex_mode = phy_ip101_get_duplex_mode,
|
||||
.phy_get_partner_pause_enable = phy_mii_get_partner_pause_enable,
|
||||
.phy_power_enable = phy_ip101_power_enable,
|
||||
.reset_timeout_ms = 1000,
|
||||
.promiscuous_enable = false,
|
||||
};
|
||||
|
||||
void phy_ip101_dump_registers()
|
||||
|
||||
@@ -114,7 +114,8 @@ const eth_config_t phy_lan8720_default_ethernet_config = {
|
||||
.phy_get_speed_mode = phy_lan8720_get_speed_mode,
|
||||
.phy_get_duplex_mode = phy_lan8720_get_duplex_mode,
|
||||
.phy_get_partner_pause_enable = phy_mii_get_partner_pause_enable,
|
||||
.reset_timeout_ms = 1000
|
||||
.reset_timeout_ms = 1000,
|
||||
.promiscuous_enable = false,
|
||||
};
|
||||
|
||||
void phy_lan8720_dump_registers()
|
||||
|
||||
@@ -125,7 +125,8 @@ const eth_config_t phy_tlk110_default_ethernet_config = {
|
||||
.phy_get_duplex_mode = phy_tlk110_get_duplex_mode,
|
||||
.phy_get_partner_pause_enable = phy_mii_get_partner_pause_enable,
|
||||
.phy_power_enable = phy_tlk110_power_enable,
|
||||
.reset_timeout_ms = 1000
|
||||
.reset_timeout_ms = 1000,
|
||||
.promiscuous_enable = false,
|
||||
};
|
||||
|
||||
void phy_tlk110_dump_registers()
|
||||
|
||||
@@ -128,6 +128,7 @@ typedef struct {
|
||||
eth_phy_get_partner_pause_enable_func phy_get_partner_pause_enable; /*!< get partner pause enable */
|
||||
eth_phy_power_enable_func phy_power_enable; /*!< enable or disable phy power */
|
||||
uint32_t reset_timeout_ms; /*!< timeout value for reset emac */
|
||||
bool promiscuous_enable; /*!< set true to enable promiscuous mode */
|
||||
} eth_config_t;
|
||||
|
||||
/**
|
||||
|
||||
@@ -419,4 +419,19 @@ menu "FreeRTOS"
|
||||
abort the application. This option is also required for GDB backtraces and C++
|
||||
exceptions to work correctly inside top-level task functions.
|
||||
|
||||
config FREERTOS_CHECK_MUTEX_GIVEN_BY_OWNER
|
||||
bool "Check that mutex semaphore is given by owner task"
|
||||
default y
|
||||
help
|
||||
If enabled, assert that when a mutex semaphore is given, the task giving the
|
||||
semaphore is the task which is currently holding the mutex.
|
||||
|
||||
config FREERTOS_CHECK_PORT_CRITICAL_COMPLIANCE
|
||||
bool "Tests compliance with Vanilla FreeRTOS port*_CRITICAL calls"
|
||||
default n
|
||||
help
|
||||
If enabled, context of port*_CRITICAL calls (ISR or Non-ISR)
|
||||
would be checked to be in compliance with Vanilla FreeRTOS.
|
||||
e.g Calling port*_CRITICAL from ISR context would cause assert failure
|
||||
|
||||
endmenu
|
||||
|
||||
@@ -209,8 +209,34 @@ void vPortCPUReleaseMutex(portMUX_TYPE *mux, const char *function, int line);
|
||||
|
||||
void vTaskEnterCritical( portMUX_TYPE *mux, const char *function, int line );
|
||||
void vTaskExitCritical( portMUX_TYPE *mux, const char *function, int line );
|
||||
|
||||
#ifdef CONFIG_FREERTOS_CHECK_PORT_CRITICAL_COMPLIANCE
|
||||
/* Calling port*_CRITICAL from ISR context would cause an assert failure.
|
||||
* If the parent function is called from both ISR and Non-ISR context then call port*_CRITICAL_SAFE
|
||||
*/
|
||||
#define portENTER_CRITICAL(mux) do { \
|
||||
if(!xPortInIsrContext()) { \
|
||||
vTaskEnterCritical(mux, __FUNCTION__, __LINE__); \
|
||||
} else { \
|
||||
ets_printf("%s:%d (%s)- port*_CRITICAL called from ISR context!\n", __FILE__, __LINE__, \
|
||||
__FUNCTION__); \
|
||||
abort(); \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#define portEXIT_CRITICAL(mux) do { \
|
||||
if(!xPortInIsrContext()) { \
|
||||
vTaskExitCritical(mux, __FUNCTION__, __LINE__); \
|
||||
} else { \
|
||||
ets_printf("%s:%d (%s)- port*_CRITICAL called from ISR context!\n", __FILE__, __LINE__, \
|
||||
__FUNCTION__); \
|
||||
abort(); \
|
||||
} \
|
||||
} while(0)
|
||||
#else
|
||||
#define portENTER_CRITICAL(mux) vTaskEnterCritical(mux, __FUNCTION__, __LINE__)
|
||||
#define portEXIT_CRITICAL(mux) vTaskExitCritical(mux, __FUNCTION__, __LINE__)
|
||||
#endif
|
||||
#define portENTER_CRITICAL_ISR(mux) vTaskEnterCritical(mux, __FUNCTION__, __LINE__)
|
||||
#define portEXIT_CRITICAL_ISR(mux) vTaskExitCritical(mux, __FUNCTION__, __LINE__)
|
||||
#else
|
||||
@@ -229,12 +255,54 @@ void vPortCPUAcquireMutex(portMUX_TYPE *mux);
|
||||
bool vPortCPUAcquireMutexTimeout(portMUX_TYPE *mux, int timeout_cycles);
|
||||
void vPortCPUReleaseMutex(portMUX_TYPE *mux);
|
||||
|
||||
#ifdef CONFIG_FREERTOS_CHECK_PORT_CRITICAL_COMPLIANCE
|
||||
/* Calling port*_CRITICAL from ISR context would cause an assert failure.
|
||||
* If the parent function is called from both ISR and Non-ISR context then call port*_CRITICAL_SAFE
|
||||
*/
|
||||
#define portENTER_CRITICAL(mux) do { \
|
||||
if(!xPortInIsrContext()) { \
|
||||
vTaskEnterCritical(mux); \
|
||||
} else { \
|
||||
ets_printf("%s:%d (%s)- port*_CRITICAL called from ISR context!\n", __FILE__, __LINE__, \
|
||||
__FUNCTION__); \
|
||||
abort(); \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#define portEXIT_CRITICAL(mux) do { \
|
||||
if(!xPortInIsrContext()) { \
|
||||
vTaskExitCritical(mux); \
|
||||
} else { \
|
||||
ets_printf("%s:%d (%s)- port*_CRITICAL called from ISR context!\n", __FILE__, __LINE__, \
|
||||
__FUNCTION__); \
|
||||
abort(); \
|
||||
} \
|
||||
} while(0)
|
||||
#else
|
||||
#define portENTER_CRITICAL(mux) vTaskEnterCritical(mux)
|
||||
#define portEXIT_CRITICAL(mux) vTaskExitCritical(mux)
|
||||
#endif
|
||||
#define portENTER_CRITICAL_ISR(mux) vTaskEnterCritical(mux)
|
||||
#define portEXIT_CRITICAL_ISR(mux) vTaskExitCritical(mux)
|
||||
#endif
|
||||
|
||||
#define portENTER_CRITICAL_SAFE(mux) do { \
|
||||
if (xPortInIsrContext()) { \
|
||||
portENTER_CRITICAL_ISR(mux); \
|
||||
} else { \
|
||||
portENTER_CRITICAL(mux); \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#define portEXIT_CRITICAL_SAFE(mux) do { \
|
||||
if (xPortInIsrContext()) { \
|
||||
portEXIT_CRITICAL_ISR(mux); \
|
||||
} else { \
|
||||
portEXIT_CRITICAL(mux); \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
|
||||
// Critical section management. NW-TODO: replace XTOS_SET_INTLEVEL with more efficient version, if any?
|
||||
// These cannot be nested. They should be used with a lot of care and cannot be called from interrupt level.
|
||||
//
|
||||
|
||||
@@ -2464,12 +2464,11 @@ BaseType_t xSwitchRequired = pdFALSE;
|
||||
Increments the tick then checks to see if the new tick value will cause any
|
||||
tasks to be unblocked. */
|
||||
|
||||
/* Only let core 0 increase the tick count, to keep accurate track of time. */
|
||||
/* ToDo: This doesn't really play nice with the logic below: it means when core 1 is
|
||||
running a low-priority task, it will keep running it until there is a context
|
||||
switch, even when this routine (running on core 0) unblocks a bunch of high-priority
|
||||
tasks... this is less than optimal -- JD. */
|
||||
if ( xPortGetCoreID()!=0 ) {
|
||||
/* Only allow core 0 increase the tick count in the case of xPortSysTickHandler processing. */
|
||||
/* And allow core 0 and core 1 to unwind uxPendedTicks during xTaskResumeAll. */
|
||||
|
||||
if ( xPortInIsrContext() )
|
||||
{
|
||||
#if ( configUSE_TICK_HOOK == 1 )
|
||||
vApplicationTickHook();
|
||||
#endif /* configUSE_TICK_HOOK */
|
||||
@@ -2477,11 +2476,10 @@ BaseType_t xSwitchRequired = pdFALSE;
|
||||
esp_vApplicationTickHook();
|
||||
#endif /* CONFIG_FREERTOS_LEGACY_HOOKS */
|
||||
|
||||
/*
|
||||
We can't really calculate what we need, that's done on core 0... just assume we need a switch.
|
||||
ToDo: Make this more intelligent? -- JD
|
||||
*/
|
||||
return pdTRUE;
|
||||
if (xPortGetCoreID() == 1 )
|
||||
{
|
||||
return pdTRUE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2606,39 +2604,11 @@ BaseType_t xSwitchRequired = pdFALSE;
|
||||
}
|
||||
#endif /* ( ( configUSE_PREEMPTION == 1 ) && ( configUSE_TIME_SLICING == 1 ) ) */
|
||||
|
||||
{
|
||||
/* Guard against the tick hook being called when the pended tick
|
||||
count is being unwound (when the scheduler is being unlocked). */
|
||||
if( uxPendedTicks == ( UBaseType_t ) 0U )
|
||||
{
|
||||
#if ( configUSE_TICK_HOOK == 1 )
|
||||
vApplicationTickHook();
|
||||
#endif /* configUSE_TICK_HOOK */
|
||||
#if ( CONFIG_FREERTOS_LEGACY_HOOKS == 1 )
|
||||
esp_vApplicationTickHook();
|
||||
#endif /* CONFIG_FREERTOS_LEGACY_HOOKS */
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
taskEXIT_CRITICAL_ISR(&xTaskQueueMutex);
|
||||
}
|
||||
else
|
||||
{
|
||||
++uxPendedTicks;
|
||||
|
||||
/* The tick hook gets called at regular intervals, even if the
|
||||
scheduler is locked. */
|
||||
#if ( configUSE_TICK_HOOK == 1 )
|
||||
{
|
||||
vApplicationTickHook();
|
||||
}
|
||||
#endif
|
||||
#if ( CONFIG_FREERTOS_LEGACY_HOOKS == 1 )
|
||||
esp_vApplicationTickHook();
|
||||
#endif /* CONFIG_FREERTOS_LEGACY_HOOKS */
|
||||
}
|
||||
|
||||
#if ( configUSE_PREEMPTION == 1 )
|
||||
|
||||
@@ -40,8 +40,8 @@ TEST_CASE("portMUX spinlocks (no contention)", "[freertos]")
|
||||
BENCHMARK_START();
|
||||
|
||||
for (int i = 0; i < REPEAT_OPS; i++) {
|
||||
portENTER_CRITICAL(&mux);
|
||||
portEXIT_CRITICAL(&mux);
|
||||
portENTER_CRITICAL_ISR(&mux);
|
||||
portEXIT_CRITICAL_ISR(&mux);
|
||||
}
|
||||
BENCHMARK_END("no contention lock");
|
||||
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
/* Tests for FreeRTOS task suspend & resume */
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/semphr.h"
|
||||
#include "freertos/timers.h"
|
||||
#include "freertos/queue.h"
|
||||
#include "freertos/xtensa_api.h"
|
||||
#include "unity.h"
|
||||
@@ -12,6 +14,11 @@
|
||||
|
||||
#include "driver/timer.h"
|
||||
|
||||
#include "esp_ipc.h"
|
||||
#include "esp_freertos_hooks.h"
|
||||
#include "sdkconfig.h"
|
||||
|
||||
|
||||
/* Counter task counts a target variable forever */
|
||||
static void task_count(void *vp_counter)
|
||||
{
|
||||
@@ -171,4 +178,189 @@ TEST_CASE("Resume task from ISR (other core)", "[freertos]")
|
||||
{
|
||||
test_resume_task_from_isr(!UNITY_FREERTOS_CPU);
|
||||
}
|
||||
#endif
|
||||
|
||||
static volatile bool block;
|
||||
static bool suspend_both_cpus;
|
||||
|
||||
static void IRAM_ATTR suspend_scheduler_while_block_set(void* arg)
|
||||
{
|
||||
vTaskSuspendAll();
|
||||
|
||||
while (block) { };
|
||||
ets_delay_us(1);
|
||||
xTaskResumeAll();
|
||||
}
|
||||
|
||||
static void IRAM_ATTR suspend_scheduler_on_both_cpus()
|
||||
{
|
||||
block = true;
|
||||
if (suspend_both_cpus) {
|
||||
TEST_ESP_OK(esp_ipc_call((xPortGetCoreID() == 0) ? 1 : 0, &suspend_scheduler_while_block_set, NULL));
|
||||
}
|
||||
|
||||
vTaskSuspendAll();
|
||||
}
|
||||
|
||||
static void IRAM_ATTR resume_scheduler_on_both_cpus()
|
||||
{
|
||||
block = false;
|
||||
xTaskResumeAll();
|
||||
}
|
||||
|
||||
static const int waiting_ms = 2000;
|
||||
static const int delta_ms = 100;
|
||||
static int duration_wait_task_ms;
|
||||
static int duration_ctrl_task_ms;
|
||||
|
||||
static void waiting_task(void *pvParameters)
|
||||
{
|
||||
int cpu_id = xPortGetCoreID();
|
||||
int64_t start_time = esp_timer_get_time();
|
||||
printf("Start waiting_task cpu=%d\n", cpu_id);
|
||||
|
||||
vTaskDelay(waiting_ms / portTICK_PERIOD_MS);
|
||||
|
||||
duration_wait_task_ms = (esp_timer_get_time() - start_time) / 1000;
|
||||
printf("Finish waiting_task cpu=%d, time=%d ms\n", cpu_id, duration_wait_task_ms);
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
static void control_task(void *pvParameters)
|
||||
{
|
||||
int cpu_id = xPortGetCoreID();
|
||||
ets_delay_us(2000); // let to start the waiting_task first
|
||||
printf("Start control_task cpu=%d\n", cpu_id);
|
||||
int64_t start_time = esp_timer_get_time();
|
||||
|
||||
suspend_scheduler_on_both_cpus();
|
||||
ets_delay_us(waiting_ms * 1000 + delta_ms * 1000);
|
||||
resume_scheduler_on_both_cpus();
|
||||
|
||||
duration_ctrl_task_ms = (esp_timer_get_time() - start_time) / 1000;
|
||||
printf("Finish control_task cpu=%d, time=%d ms\n", cpu_id, duration_ctrl_task_ms);
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
static void test_scheduler_suspend1(int cpu)
|
||||
{
|
||||
/* This test tests a case then both CPUs were in suspend state and then resume CPUs back.
|
||||
* A task for which a wait time has been set and this time has elapsed in the suspended state should in any case be ready to start.
|
||||
* (In an old implementation of xTaskIncrementTick function the counting for waiting_task() will be continued
|
||||
* (excluding time in suspended) after control_task() is finished.)
|
||||
*/
|
||||
duration_wait_task_ms = 0;
|
||||
duration_ctrl_task_ms = 0;
|
||||
|
||||
printf("Test for CPU%d\n", cpu);
|
||||
int other_cpu = (cpu == 0) ? 1 : 0;
|
||||
xTaskCreatePinnedToCore(&waiting_task, "waiting_task", 8192, NULL, 5, NULL, other_cpu);
|
||||
xTaskCreatePinnedToCore(&control_task, "control_task", 8192, NULL, 5, NULL, cpu);
|
||||
|
||||
vTaskDelay(waiting_ms * 2 / portTICK_PERIOD_MS);
|
||||
TEST_ASSERT_INT_WITHIN(4, waiting_ms + delta_ms + 4, duration_ctrl_task_ms);
|
||||
if (suspend_both_cpus == false && cpu == 1) {
|
||||
// CPU0 continues to increase the TickCount and the wait_task does not depend on Suspended Scheduler on CPU1
|
||||
TEST_ASSERT_INT_WITHIN(2, waiting_ms, duration_wait_task_ms);
|
||||
} else {
|
||||
TEST_ASSERT_INT_WITHIN(4, waiting_ms + delta_ms + 4, duration_wait_task_ms);
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
TEST_CASE("Test the waiting task not missed due to scheduler suspension on both CPUs", "[freertos]")
|
||||
{
|
||||
printf("Suspend both CPUs:\n");
|
||||
suspend_both_cpus = true;
|
||||
test_scheduler_suspend1(0);
|
||||
test_scheduler_suspend1(1);
|
||||
}
|
||||
|
||||
TEST_CASE("Test the waiting task not missed due to scheduler suspension on one CPU", "[freertos]")
|
||||
{
|
||||
printf("Suspend only one CPU:\n");
|
||||
suspend_both_cpus = false;
|
||||
test_scheduler_suspend1(0);
|
||||
test_scheduler_suspend1(1);
|
||||
}
|
||||
|
||||
static uint32_t count_tick[2];
|
||||
|
||||
static void IRAM_ATTR tick_hook()
|
||||
{
|
||||
++count_tick[xPortGetCoreID()];
|
||||
}
|
||||
|
||||
static void test_scheduler_suspend2(int cpu)
|
||||
{
|
||||
esp_register_freertos_tick_hook_for_cpu(tick_hook, 0);
|
||||
esp_register_freertos_tick_hook_for_cpu(tick_hook, 1);
|
||||
|
||||
memset(count_tick, 0, sizeof(count_tick));
|
||||
|
||||
printf("Test for CPU%d\n", cpu);
|
||||
xTaskCreatePinnedToCore(&control_task, "control_task", 8192, NULL, 5, NULL, cpu);
|
||||
|
||||
vTaskDelay(waiting_ms * 2 / portTICK_PERIOD_MS);
|
||||
esp_deregister_freertos_tick_hook(tick_hook);
|
||||
|
||||
printf("count_tick[cpu0] = %d, count_tick[cpu1] = %d\n", count_tick[0], count_tick[1]);
|
||||
|
||||
TEST_ASSERT_INT_WITHIN(1, waiting_ms * 2, count_tick[0]);
|
||||
TEST_ASSERT_INT_WITHIN(1, waiting_ms * 2, count_tick[1]);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
TEST_CASE("Test suspend-resume CPU. The number of tick_hook should be the same for both CPUs", "[freertos]")
|
||||
{
|
||||
printf("Suspend both CPUs:\n");
|
||||
suspend_both_cpus = true;
|
||||
test_scheduler_suspend2(0);
|
||||
test_scheduler_suspend2(1);
|
||||
|
||||
printf("Suspend only one CPU:\n");
|
||||
suspend_both_cpus = false;
|
||||
test_scheduler_suspend2(0);
|
||||
test_scheduler_suspend2(1);
|
||||
}
|
||||
|
||||
static int duration_timer_ms;
|
||||
|
||||
static void timer_callback(void *arg)
|
||||
{
|
||||
++duration_timer_ms;
|
||||
}
|
||||
|
||||
static void test_scheduler_suspend3(int cpu)
|
||||
{
|
||||
duration_timer_ms = 0;
|
||||
duration_ctrl_task_ms = 0;
|
||||
|
||||
printf("Test for CPU%d\n", cpu);
|
||||
TimerHandle_t count_time = xTimerCreate("count_time", 1, pdTRUE, NULL, timer_callback);
|
||||
xTimerStart( count_time, portMAX_DELAY);
|
||||
xTaskCreatePinnedToCore(&control_task, "control_task", 8192, NULL, 5, NULL, cpu);
|
||||
|
||||
vTaskDelay(waiting_ms * 2 / portTICK_PERIOD_MS);
|
||||
xTimerDelete(count_time, portMAX_DELAY);
|
||||
printf("Finish duration_timer_ms=%d ms\n", duration_timer_ms);
|
||||
|
||||
TEST_ASSERT_INT_WITHIN(2, waiting_ms * 2, duration_timer_ms);
|
||||
TEST_ASSERT_INT_WITHIN(5, waiting_ms + delta_ms, duration_ctrl_task_ms);
|
||||
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
TEST_CASE("Test suspend-resume CPU works with xTimer", "[freertos]")
|
||||
{
|
||||
printf("Suspend both CPUs:\n");
|
||||
suspend_both_cpus = true;
|
||||
test_scheduler_suspend3(0);
|
||||
test_scheduler_suspend3(1);
|
||||
|
||||
printf("Suspend only one CPU:\n");
|
||||
suspend_both_cpus = false;
|
||||
test_scheduler_suspend3(0);
|
||||
test_scheduler_suspend3(1);
|
||||
}
|
||||
#endif // CONFIG_FREERTOS_UNICORE
|
||||
|
||||
@@ -2,181 +2,227 @@
|
||||
test script: InitCondMesh
|
||||
restore post cmd set:
|
||||
- ''
|
||||
- - 'MSSC SSC[1-<node_num>] mesh -F -o 4 -a 1'
|
||||
- ['P SSC[1-<node_num>] C +MESHFLAG:OK']
|
||||
- - 'MSSC SSC[1-<node_num>] mesh -F -o 5 -a 1'
|
||||
- ['P SSC[1-<node_num>] C +MESHFLAG:OK']
|
||||
- - 'MSSC SSC[1-<node_num>] mesh -Q -o 1'
|
||||
- ['P SSC[1-<node_num>] C MESH_NETWORK']
|
||||
- - 'MSSC SSC[1-<node_num>] mesh -Q -o 3'
|
||||
- ['P SSC[1-<node_num>] C +MESH_CONFIG:ALL']
|
||||
- - 'MSSC SSC[1-<node_num>] ram'
|
||||
- ['P SSC[1-<node_num>] C +FREEHEAP:']
|
||||
# - - 'MSSC SSC[1-<node_num>] mesh -Q -o 1'
|
||||
# - ['P SSC[1-<node_num>] C MESH_NETWORK']
|
||||
|
||||
.mesh_get_device_mac: &mesh_get_device_mac
|
||||
.mesh_get_all_dut_mac: &mesh_get_all_dut_mac
|
||||
LIST_MERGE:
|
||||
- - 'MSSC SSC[1-<node_num>] mac'
|
||||
- ['R SSC[1-<node_num>] A <device_mac>:\+STAMAC:(.+)\r\n']
|
||||
|
||||
.mesh_check_get_tree: &mesh_check_get_tree
|
||||
.mesh_check_tree_num: &mesh_check_tree_num
|
||||
LIST_MERGE:
|
||||
- - 'MSSC SSC[1-<node_num>] mac'
|
||||
- ['P SSC[1-<node_num>] A <device_mac>:\+STAMAC:(.+)\r\n']
|
||||
- - 'MSSC SSC[1-<node_num>] mesh -Q -o 2'
|
||||
- ['P SSC[1-<node_num>] T <node_num>']
|
||||
- ['P SSC[1-<node_num>] T topo']
|
||||
- - 'MESHTREE'
|
||||
- ['P PC_COM RE "MESHTREE:%%s%20nodes"%%(<node_num>)']
|
||||
- ['R PC_COM RE "MESHTREE:%%s"%%(<tree_node_num>)']
|
||||
|
||||
.mesh_check_tree_stable: &mesh_check_tree_stable
|
||||
.mesh_tree_stably: &mesh_tree_stably
|
||||
LIST_MERGE:
|
||||
- - 'DELAY 10'
|
||||
- ['']
|
||||
- - 'SSC MNODE(0) mesh -Q -o 1 -t 10'
|
||||
- ['R MNODE(0) C MESH_STABLE_CHECK:PASS']
|
||||
- - 'SSC MNODE(0) mesh -Q -o 1 -t <stable_check_time>'
|
||||
- ['P MNODE(0) RE "MESH_NETWORK:1,%%s"%%(<node_num>)', 'P MNODE(0) C MESH_STABLE_CHECK:PASS']
|
||||
|
||||
.reboot_all: &reboot_all
|
||||
.deinit_mesh: &deinit_mesh
|
||||
LIST_MERGE:
|
||||
- - 'MSSC SSC[1-<node_num>] reboot'
|
||||
- ['P SSC[1-<node_num>] C !!!ready!!!']
|
||||
- - 'MSSC SSC[1-<node_num>] mesh -I -o 1'
|
||||
- ['P SSC[1-<node_num>] C +MESH:DEINITED']
|
||||
|
||||
.force_reboot: &force_reboot
|
||||
.mesh_force_reboot: &mesh_force_reboot
|
||||
LIST_MERGE:
|
||||
- - 'FPOWERON SSC[1-<node_num>]'
|
||||
- ['']
|
||||
- - 'DELAY 1'
|
||||
- ['']
|
||||
- - 'MSSC SSC[1-<node_num>] restore'
|
||||
- ['P SSC[1-<node_num>] C !!!ready!!!']
|
||||
|
||||
.all_nodes_mesh_config: &all_nodes_mesh_config
|
||||
.mesh_config_all_duts: &mesh_config_all_duts
|
||||
LIST_MERGE:
|
||||
- - 'MSSC SSC[1-<node_num>] mesh -I'
|
||||
- ['P SSC[1-<node_num>] C +MESH:INITED']
|
||||
- - 'MSSC SSC[1-<node_num>] mesh -A -o 12 -t <duration_ms> -c <cnx_rssi> -l <select_rssi> -f <switch_rssi> -b <backoff_rssi>'
|
||||
- ['P SSC[1-<node_num>] C +MESH_SET_PARENT_SWITCH:OK']
|
||||
- - 'MSSC SSC[1-<node_num>] mesh -A -o 14 -t <threshold_high> -c <threshold_medium> -l <threshold_low>'
|
||||
- ['P SSC[1-<node_num>] C +MESH_RSSI_THRESHOLD:OK']
|
||||
- - 'MSSC SSC[1-<node_num>] mesh -A -o 9 -t <auth_mode> -s <map_password>'
|
||||
- ['P SSC[1-<node_num>] C +MESH_SET_AP_AUTH_MODE:OK']
|
||||
- - 'MSSC SSC[1-<node_num>] mesh -P -g <mesh_id> -s <ap_ssid> -p <ap_password> -n <ap_channel> -m <max_connect> -y <max_layer>'
|
||||
- ['P SSC[1-<node_num>] C +MESH:CONFIG,OK']
|
||||
- - 'MSSC SSC[1-<node_num>] meshset -M -o 0 -t <map_auth_mode> -e <map_password> -l 10'
|
||||
- ['P SSC[1-<node_num>] C +MESHSET:MAP_AUTH,OK']
|
||||
- - 'MSSC SSC[1-<node_num>] meshset -G -o 0 -m <mesh_id> -s <router_ssid> -p <router_password> -n
|
||||
<router_channel> -b <router_bssid> -t <max_connect> -e <map_password> -i <ie_encrypt>'
|
||||
- ['P SSC[1-<node_num>] C +MESHSET:CFG,OK']
|
||||
- - 'MSSC SSC[1-<node_num>] meshset -L -o 0 -l <max_layer>'
|
||||
- ['P SSC[1-<node_num>] C +MESHSET:MLAYER,OK']
|
||||
- - 'MSSC SSC[1-<node_num>] meshset -W -o 0 -t <duration_ms> -n <cnx_rssi> -l <select_rssi> -i <switch_rssi> -k <backoff_rssi>'
|
||||
- ['P SSC[1-<node_num>] C +MESHSET:SWITCH,OK']
|
||||
- - 'MSSC SSC[1-<node_num>] meshset -K -o 0 -i <allow_roots>'
|
||||
- ['P SSC[1-<node_num>] C +MESHSET:ALLOW_ROOTS,OK']
|
||||
- - 'MSSC SSC[1-<node_num>] meshset -J -o 0 -t <assoc_expire>'
|
||||
- ['P SSC[1-<node_num>] C +MESHSET:ASSOC,OK']
|
||||
|
||||
.root_do_connect: &root_do_connect
|
||||
.mesh_set_same_ssid_softap: &mesh_set_same_ssid_softap
|
||||
LIST_MERGE:
|
||||
- - 'SOC SOC1 LISTEN <test_tcp_port1> <pc_ip>'
|
||||
- ['R SOC_COM L OK']
|
||||
- - 'SSC MNODE(0) mesh -S -o 0 -i <pc_ip> -t <test_tcp_port1>'
|
||||
- ['P MNODE(0) C +CONNECT,OK']
|
||||
- ['P SOC1 C +ACCEPT']
|
||||
- - 'SOC SOC1 MACCEPT GSOC1'
|
||||
- ['R SOC_COM L OK']
|
||||
- - 'MSSC SSC[1-3] op -S -o 2'
|
||||
- ['P SSC[1-3] C +MODE:OK']
|
||||
- - 'MSSC SSC[1-3] ap -S -s <target_ssid> -p <target_password> -t <target_auth_enum> -n
|
||||
[<router_channel>,<router_channel>,<wrong_channel>]'
|
||||
- ['P SSC[1-3] C +SAP:OK']
|
||||
|
||||
initial condition:
|
||||
- tag: ENABLED_1
|
||||
- tag: MESH_DEINIT_STA
|
||||
<<: *MESH_INIT_COND
|
||||
initial condition detail: if mesh tree not exist, start one node first, then start others, after mesh network
|
||||
established, root connect server
|
||||
initial condition detail: all DUTs with mesh not inited, station mode
|
||||
check cmd set:
|
||||
- ''
|
||||
- *mesh_check_get_tree
|
||||
- *mesh_check_tree_stable
|
||||
- *root_do_connect
|
||||
- - MSSC SSC[1-<node_num>] mesh -Q
|
||||
- - P SSC[1-<node_num>] C MESH_STATE_NONE
|
||||
- - MSSC SSC[1-<node_num>] op -S -o 1
|
||||
- - P SSC[1-<node_num>] C +MODE:OK
|
||||
- *mesh_get_all_dut_mac
|
||||
restore cmd set:
|
||||
- ''
|
||||
- *reboot_all
|
||||
- *all_nodes_mesh_config
|
||||
- - SSC SSC1 mesh -T
|
||||
- - P SSC1 C +MESH:START,OK
|
||||
- - DELAY 10
|
||||
- - P SSC1 C MESH_EVENT_CONNECTED
|
||||
- - SSC SSC[2-<node_num>] mesh -T
|
||||
- - P SSC[2-<node_num>] C +MESH:START,OK
|
||||
- - DELAY <delay_time>
|
||||
- - ''
|
||||
- *mesh_check_get_tree
|
||||
- *mesh_check_tree_stable
|
||||
- *root_do_connect
|
||||
- - MSSC SSC[1-<node_num>] mesh -I -o 1
|
||||
- - P SSC[1-<node_num>] C +MESH_DEINITED
|
||||
- - MSSC SSC[1-<node_num>] op -S -o 1
|
||||
- - P SSC[1-<node_num>] C +MODE:OK
|
||||
- *mesh_get_all_dut_mac
|
||||
force restore cmd set:
|
||||
- ''
|
||||
- *force_reboot
|
||||
- *all_nodes_mesh_config
|
||||
- - SSC SSC1 mesh -T
|
||||
- - P SSC1 C +MESH:START,OK
|
||||
- - DELAY 10
|
||||
- - P SSC1 C MESH_EVENT_CONNECTED
|
||||
- - SSC SSC[2-<node_num>] mesh -T
|
||||
- - P SSC[2-<node_num>] C +MESH:START,OK
|
||||
- - DELAY <delay_time>
|
||||
- - ''
|
||||
- *mesh_check_get_tree
|
||||
- *mesh_check_tree_stable
|
||||
- *root_do_connect
|
||||
- tag: ENABLED_2
|
||||
# - - MSSC SSC[1-<node_num>] reboot
|
||||
- - FREBOOT SSC[1-<node_num>]
|
||||
- - P SSC[1-<node_num>] C !!!ready!!!
|
||||
- *mesh_get_all_dut_mac
|
||||
- tag: MESH_INIT1
|
||||
<<: *MESH_INIT_COND
|
||||
initial condition detail: if mesh tree not exist, start all nodes together
|
||||
initial condition detail: DUTs with mesh network already established, router....
|
||||
check cmd set:
|
||||
- ''
|
||||
- *mesh_check_get_tree
|
||||
- *mesh_check_tree_stable
|
||||
- *mesh_get_all_dut_mac
|
||||
- - VALUE <tree_node_num> <node_num>
|
||||
- - R PC_COM L OK
|
||||
- *mesh_check_tree_num
|
||||
- *mesh_tree_stably
|
||||
- - MSSC SSC[1-<node_num>] mesh -Q -o 3
|
||||
- - P SSC[1-<node_num>] RE "MID,%%s"%%(<mesh_id>)
|
||||
- P SSC[1-<node_num>] RE "MROUTER,%%s"%%(<router_ssid>)
|
||||
- P SSC[1-<node_num>] RE "SWITCH_PARENT,%%s"%%(<duration_ms>)
|
||||
- P SSC[1-<node_num>] C NO_SPECIFIC_SETTINGS
|
||||
restore cmd set:
|
||||
- ''
|
||||
- *reboot_all
|
||||
- *all_nodes_mesh_config
|
||||
- - MSSC SSC[1-<node_num>] mesh -I -o 1
|
||||
- - P SSC[1-<node_num>] C MESH_DEINITED
|
||||
- - MSSC SSC[1-<node_num>] op -S -o 1
|
||||
- - P SSC[1-<node_num>] C +MODE:OK
|
||||
- *mesh_get_all_dut_mac
|
||||
- - MSSC SSC[1-<node_num>] mesh -I
|
||||
- - P SSC[1-<node_num>] C +MESH:INIT,OK
|
||||
- *mesh_config_all_duts
|
||||
- - MSSC SSC[1-<node_num>] mesh -T
|
||||
- - P SSC[1-<node_num>] C +MESH:START,OK
|
||||
- - DELAY <delay_time>
|
||||
- - ''
|
||||
- *mesh_check_get_tree
|
||||
- *mesh_check_tree_stable
|
||||
- - VALUE <tree_node_num> <node_num>
|
||||
- - R PC_COM L OK
|
||||
- *mesh_check_tree_num
|
||||
- *mesh_tree_stably
|
||||
force restore cmd set:
|
||||
- ''
|
||||
- *force_reboot
|
||||
- *all_nodes_mesh_config
|
||||
- - MSSC SSC[1-<node_num>] reboot
|
||||
- - P SSC[1-<node_num>] C !!!ready!!!
|
||||
- *mesh_get_all_dut_mac
|
||||
- - MSSC SSC[1-<node_num>] mesh -I
|
||||
- - P SSC[1-<node_num>] C +MESH:INIT,OK
|
||||
- *mesh_config_all_duts
|
||||
- - MSSC SSC[1-<node_num>] mesh -T
|
||||
- - P SSC[1-<node_num>] C +MESH:START,OK
|
||||
- - DELAY <delay_time>
|
||||
- - ''
|
||||
- *mesh_check_get_tree
|
||||
- *mesh_check_tree_stable
|
||||
- tag: ENABLED_3
|
||||
- - VALUE <tree_node_num> <node_num>
|
||||
- - R PC_COM L OK
|
||||
- *mesh_check_tree_num
|
||||
- *mesh_tree_stably
|
||||
- tag: MESH_INIT_SWITCH
|
||||
<<: *MESH_INIT_COND
|
||||
initial condition detail: all mesh nodes configed but not started
|
||||
initial condition detail: 3 duts in softAP mode with same ssid/password, all duts establish network
|
||||
check cmd set:
|
||||
- ''
|
||||
- - SSC SSC[1-3] ap -Q
|
||||
- - P SSC[1-3] RE "RE "APCONFIG:%%s"%%(<target_ssid>)
|
||||
- - MSSC SSC[4-<node_num>] mac
|
||||
- - R SSC[4-<node_num>] A <device_mac>:\+STAMAC:(.+)\r\n
|
||||
- - VALUE <tree_node_num> <node_num>-3
|
||||
- - R PC_COM L OK
|
||||
- - MSSC SSC[4-<node_num>] mesh -Q -o 2
|
||||
- - P SSC[4-<node_num>] T topo
|
||||
- - MESHTREE
|
||||
- - R PC_COM RE "TREE_TOTAL_NODES:%%s"%%(<tree_node_num>)
|
||||
- - MSSC SSC[4-<node_num>] mesh -Q -o 3
|
||||
- P SSC[4-<node_num>] RE "MROUTER,%%s"%%(<target_ssid>)
|
||||
- - DELAY 5
|
||||
- - P PC_COM C +DELAYDONE
|
||||
- P SSC[4-<node_num>] NC MESH_EVENT_DISCONNECTED
|
||||
restore cmd set:
|
||||
- ''
|
||||
- - ASSERT
|
||||
- - ''
|
||||
restore cmd set:
|
||||
- ''
|
||||
- *reboot_all
|
||||
- *all_nodes_mesh_config
|
||||
- *mesh_get_device_mac
|
||||
force restore cmd set:
|
||||
- ''
|
||||
- *force_reboot
|
||||
- *all_nodes_mesh_config
|
||||
- *mesh_get_device_mac
|
||||
- tag: DISABLED_1
|
||||
- - MSSC SSC[1-<node_num>] reboot
|
||||
- - P SSC[1-<node_num>] C !!!ready!!!
|
||||
- *mesh_get_all_dut_mac
|
||||
- *mesh_set_same_ssid_softap
|
||||
- - MSSC SSC[4-<node_num>] mesh -I
|
||||
- - P SSC[4-<node_num>] C +MESH:INIT,OK
|
||||
- - MSSC SSC[4-<node_num>] meshset -M -o 0 -t <map_auth_mode> -e <map_password> -l 10
|
||||
- - P SSC[4-<node_num>] C +MESHSET:MAP_AUTH,OK
|
||||
- - MSSC SSC[4-<node_num>] meshset -G -o 0 -m <mesh_id> -s <target_ssid> -p <target_password> -n <try_channel> -h 1 -t
|
||||
<max_connect> -e <map_password> -i <ie_encrypt>
|
||||
- - P SSC[4-<node_num>] C +MESHSET:CFG,OK
|
||||
- - MSSC SSC[4-<node_num>] meshset -L -o 0 -l <max_layer>
|
||||
- - P SSC[4-<node_num>] C +MESHSET:MLAYER,OK
|
||||
- - MSSC SSC[4-<node_num>] meshset -W -o 0 -t <duration_ms> -n <cnx_rssi> -l <select_rssi> -i <switch_rssi> -k <backoff_rssi>
|
||||
- - P SSC[4-<node_num>] C +MESHSET:SWITCH,OK
|
||||
- - MSSC SSC[4-<node_num>] meshset -K -o 0 -i <allow_roots>
|
||||
- - P SSC[4-<node_num>] C +MESHSET:ALLOW_ROOTS,OK
|
||||
- - MSSC SSC[4-<node_num>] mesh -T
|
||||
- - P SSC[4-<node_num>] C +MESH:START,OK
|
||||
- - DELAY <delay_time>
|
||||
- - ''
|
||||
- - VALUE <tree_node_num> <node_num>-3
|
||||
- - R PC_COM L OK
|
||||
- - MSSC SSC[4-<node_num>] mesh -Q -o 2
|
||||
- - P SSC[4-<node_num>] T topo
|
||||
- - MESHTREE
|
||||
- - R PC_COM RE "TREE_TOTAL_NODES:%%s"%%(<tree_node_num>)
|
||||
- - DELAY 10
|
||||
- - P PC_COM C +DELAYDONE
|
||||
- P SSC[4-<node_num>] NC MESH_EVENT_DISCONNECTED
|
||||
- tag: MESH_NO_ROUTER
|
||||
<<: *MESH_INIT_COND
|
||||
initial condition detail: all mesh node in softap+sta mode, disable all mesh node
|
||||
restore post cmd set:
|
||||
- ''
|
||||
initial condition detail: DUTs with mesh network already established, router....
|
||||
check cmd set:
|
||||
- ''
|
||||
- *mesh_get_all_dut_mac
|
||||
- - VALUE <tree_node_num> <node_num>
|
||||
- - R PC_COM L OK
|
||||
- *mesh_check_tree_num
|
||||
- *mesh_tree_stably
|
||||
- - MSSC SSC[1-<node_num>] mesh -Q -o 3
|
||||
- - P SSC[1-<node_num>] RE "MID,%%s"%%(<mesh_id>)
|
||||
- P SSC[1-<node_num>] C NO_ROUTER
|
||||
restore cmd set:
|
||||
- ''
|
||||
- - ASSERT
|
||||
- - ''
|
||||
restore cmd set:
|
||||
- ''
|
||||
- *reboot_all
|
||||
- - MSSC SSC[1-<node_num>] op -S -o 3
|
||||
- - P SSC[1-<node_num>] C +MODE:OK
|
||||
- - MSSC SSC[1-<node_num>] sta -D
|
||||
- - P SSC[1-<node_num>] C +QAP:OK
|
||||
- *mesh_get_device_mac
|
||||
force restore cmd set:
|
||||
- ''
|
||||
- *force_reboot
|
||||
- - MSSC SSC[1-<node_num>] op -S -o 3
|
||||
- - P SSC[1-<node_num>] C +MODE:OK
|
||||
- - MSSC SSC[1-<node_num>] sta -D
|
||||
- - P SSC[1-<node_num>] C +QAP:OK
|
||||
- *mesh_get_device_mac
|
||||
- - ASSERT
|
||||
- - ''
|
||||
- tag: MESH_STABLE
|
||||
<<: *MESH_INIT_COND
|
||||
initial condition detail: DUTs with mesh network already established and stable, never restore
|
||||
check cmd set:
|
||||
- ''
|
||||
- *mesh_get_all_dut_mac
|
||||
- - MSSC SSC[1-<node_num>] mesh -Q -o 2
|
||||
- - P SSC[1-<node_num>] T topo
|
||||
- - MESHTREE stable
|
||||
- - P PC_COM RE "MESHTREE:%%s%20nodes"%%(<node_num>)
|
||||
restore cmd set:
|
||||
- ''
|
||||
- - ASSERT
|
||||
- - ''
|
||||
force restore cmd set:
|
||||
- ''
|
||||
- - ASSERT
|
||||
- - ''
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -12,19 +12,6 @@ WIFI_SCAN_0303
|
||||
WIFI_SCAN_0303_01
|
||||
WIFI_CONN_0302
|
||||
WIFI_CONN_0302_01
|
||||
WIFI_CONN_0101
|
||||
WIFI_CONN_0101_01
|
||||
WIFI_CONN_0102
|
||||
WIFI_CONN_0103
|
||||
WIFI_CONN_0103_01
|
||||
WIFI_SCAN_0101
|
||||
WIFI_SCAN_0101_01
|
||||
WIFI_SCAN_0102
|
||||
WIFI_SCAN_0102_01
|
||||
WIFI_SCAN_0103
|
||||
WIFI_SCAN_0103_01
|
||||
WIFI_SCAN_0104
|
||||
WIFI_SCAN_0104_01
|
||||
WIFI_MODE_0102
|
||||
WIFI_MODE_0103
|
||||
WIFI_ADDR_0102
|
||||
|
||||
1213
components/idf_test/integration_test/TC_IT_BLUEDROID_GAP.yml
Normal file
1213
components/idf_test/integration_test/TC_IT_BLUEDROID_GAP.yml
Normal file
File diff suppressed because it is too large
Load Diff
1209
components/idf_test/integration_test/TC_IT_BLUEDROID_GATT.yml
Normal file
1209
components/idf_test/integration_test/TC_IT_BLUEDROID_GATT.yml
Normal file
File diff suppressed because it is too large
Load Diff
606
components/idf_test/integration_test/TC_IT_BLUEDROID_SMP.yml
Normal file
606
components/idf_test/integration_test/TC_IT_BLUEDROID_SMP.yml
Normal file
@@ -0,0 +1,606 @@
|
||||
.SMP_CASE: &SMP_CASE
|
||||
SDK: ESP32_IDF
|
||||
Test App: SSC_BLE
|
||||
auto test: 'Yes'
|
||||
category: Function
|
||||
test point 1: basic function
|
||||
initial condition: BLE_INIT_SMP
|
||||
test environment: SSC_T2_5
|
||||
execution time: 0
|
||||
module: BLUEDROID
|
||||
sub module: SMP
|
||||
version: v1 (2017-05-26)
|
||||
CI ready: 'Yes'
|
||||
level: Integration
|
||||
allow fail: ''
|
||||
|
||||
.just_work_pair: &just_work_pair
|
||||
LIST_MERGE:
|
||||
- - "SSC SSC1 bleconn -C -p 0x10 -a <dut2_bt_mac>"
|
||||
- ['P SSC1 C +BLECONN:GapConnect,OK', 'P SSC2 C +BLECONN:GapConnect,OK']
|
||||
- - "SSC SSC2 blesmp -E -r <dut1_bt_mac> -z Enc"
|
||||
- ['P SSC[1-2] C +BLESMP:AuthComplete,Success,0']
|
||||
|
||||
.slave_passkey_entry_pair: &slave_passkey_entry_pair
|
||||
LIST_MERGE:
|
||||
- - "SSC SSC1 bleconn -C -p 0x10 -a <dut2_bt_mac>"
|
||||
- ['P SSC1 C +BLECONN:GapConnect,OK', 'P SSC2 C +BLECONN:GapConnect,OK']
|
||||
- - "SSC SSC2 blesmp -E -r <dut1_bt_mac> -z Enc"
|
||||
- ['P SSC2 C +BLESMP:PassKeyReq', 'P SSC1 A <key>:BLESMP:PassKeyNotify,(\d+)']
|
||||
- - "SSC SSC2 blesmp -K -r <dut1_bt_mac> -a 1 -k <key>"
|
||||
- ['P SSC[1-2] C +BLESMP:AuthComplete,Success,0']
|
||||
|
||||
.master_passkey_entry_pair: &master_passkey_entry_pair
|
||||
LIST_MERGE:
|
||||
- - "SSC SSC1 bleconn -C -p 0x10 -a <dut2_bt_mac>"
|
||||
- ['P SSC1 C +BLECONN:GapConnect,OK', 'P SSC2 C +BLECONN:GapConnect,OK']
|
||||
- - "SSC SSC2 blesmp -E -r <dut1_bt_mac> -z Enc"
|
||||
- ['P SSC1 C +BLESMP:PassKeyReq', 'P SSC2 A <key>:BLESMP:PassKeyNotify,(\d+)']
|
||||
- - "SSC SSC1 blesmp -K -r <dut2_bt_mac> -a 1 -k <key>"
|
||||
- ['P SSC[1-2] C +BLESMP:AuthComplete,Success,0']
|
||||
|
||||
.both_side_passkey_entry_pair: &both_side_passkey_entry_pair
|
||||
LIST_MERGE:
|
||||
- - "SSC SSC1 bleconn -C -p 0x10 -a <dut2_bt_mac>"
|
||||
- ['P SSC1 C +BLECONN:GapConnect,OK', 'P SSC2 C +BLECONN:GapConnect,OK']
|
||||
- - "SSC SSC2 blesmp -E -r <dut1_bt_mac> -z Enc"
|
||||
- ['P SSC[1,2] C +BLESMP:PassKeyReq']
|
||||
- - "SSC SSC[1,2] blesmp -K -r <dut[2,1]_bt_mac> -a 1 -k 123456"
|
||||
- ['P SSC[1-2] C +BLESMP:AuthComplete,Success,0']
|
||||
|
||||
.numberic_comparision_pair: &numberic_comparision_pair
|
||||
LIST_MERGE:
|
||||
- - "SSC SSC1 bleconn -C -p 0x10 -a <dut2_bt_mac>"
|
||||
- ['P SSC1 C +BLECONN:GapConnect,OK', 'P SSC2 C +BLECONN:GapConnect,OK']
|
||||
- - "SSC SSC2 blesmp -E -r <dut1_bt_mac> -z Enc"
|
||||
- ['R SSC2 A <key>:BLESMP:NCReq,(\d+)', 'R SSC1 C NCReq P <key>']
|
||||
- - "SSC SSC[1-2] blesmp -C -r <dut[2,1]_bt_mac> -a 1"
|
||||
- ['P SSC[1-2] C +BLESMP:AuthComplete,Success,0']
|
||||
|
||||
.check_connection: &check_connection
|
||||
LIST_MERGE:
|
||||
- - "SSC SSC1 gattc -D -z primaryService -p 0x10 -r <dut2_bt_mac>"
|
||||
- ["R SSC1 C +GATTC:Discover,OK"]
|
||||
|
||||
.disconnect: &disconnect
|
||||
LIST_MERGE:
|
||||
- - "SSC SSC1 bleconn -D -z all"
|
||||
- ['P SSC1 C +BLECONN:GapDisconnect,OK', 'P SSC2 C +BLECONN:GapDisconnect,OK']
|
||||
- - "SSC SSC2 bleadv -D -z start"
|
||||
- ['P SSC2 C +BLEADV:OK']
|
||||
|
||||
.connect: &connect
|
||||
LIST_MERGE:
|
||||
- - "SSC SSC1 bleconn -C -p 0x10 -a <dut2_bt_mac>"
|
||||
- ['P SSC1 C +BLECONN:GapConnect,OK', 'P SSC2 C +BLECONN:GapConnect,OK']
|
||||
|
||||
.config_just_work: &config_just_work
|
||||
LIST_MERGE:
|
||||
- - "SSC SSC[1-2] blesmp -S -z AuthReqMode -v 0x00"
|
||||
- ['P SSC[1-2] C +BLESMP:OK']
|
||||
- - "SSC SSC[1-2] blesmp -S -z IOCAP -v 0x04"
|
||||
- ['P SSC[1-2] C +BLESMP:OK']
|
||||
|
||||
.config_master_passkey_entry: &config_master_passkey_entry
|
||||
LIST_MERGE:
|
||||
- - "SSC SSC[1-2] blesmp -S -z AuthReqMode -v 0x0C"
|
||||
- ['P SSC[1-2] C +BLESMP:OK']
|
||||
- - "SSC SSC1 blesmp -S -z IOCAP -v 0x02"
|
||||
- ['P SSC1 C +BLESMP:OK']
|
||||
- - "SSC SSC2 blesmp -S -z IOCAP -v 0x04"
|
||||
- ['P SSC2 C +BLESMP:OK']
|
||||
|
||||
.config_slave_passkey_entry: &config_slave_passkey_entry
|
||||
LIST_MERGE:
|
||||
- - "SSC SSC[1-2] blesmp -S -z AuthReqMode -v 0x04"
|
||||
- ['P SSC[1-2] C +BLESMP:OK']
|
||||
- - "SSC SSC[1-2] blesmp -S -z IOCAP -v 0x04"
|
||||
- ['P SSC[1-2] C +BLESMP:OK']
|
||||
|
||||
.config_both_side_passkey_entry: &config_both_side_passkey_entry
|
||||
LIST_MERGE:
|
||||
- - "SSC SSC[1-2] blesmp -S -z AuthReqMode -v 0x04"
|
||||
- ['P SSC[1-2] C +BLESMP:OK']
|
||||
- - "SSC SSC[1-2] blesmp -S -z IOCAP -v 0x02"
|
||||
- ['P SSC[1-2] C +BLESMP:OK']
|
||||
|
||||
.config_numberic_comparision: &config_numberic_comparision
|
||||
LIST_MERGE:
|
||||
- - "SSC SSC[1-2] blesmp -S -z AuthReqMode -v 0x0C"
|
||||
- ['P SSC[1-2] C +BLESMP:OK']
|
||||
- - "SSC SSC[1-2] blesmp -S -z IOCAP -v 0x04"
|
||||
- ['P SSC[1-2] C +BLESMP:OK']
|
||||
|
||||
.config_bond_device: &config_bond_device
|
||||
LIST_MERGE:
|
||||
- - "SSC SSC2 blesmp -S -z AuthReqMode -v 0x01"
|
||||
- ['P SSC2 C +BLESMP:OK']
|
||||
- - "SSC SSC2 blesmp -S -z IOCAP -v 0x03"
|
||||
- ['P SSC2 C +BLESMP:OK']
|
||||
|
||||
test cases:
|
||||
- ID: BLUEDROID_SMP_04001
|
||||
<<: *SMP_CASE
|
||||
test point 2: BLE SMP key test
|
||||
summary: BLE SMP set key size less than required for BLUEDROID
|
||||
allow fail: 1/2
|
||||
steps: |
|
||||
1. set key size 7
|
||||
2. set key size 6
|
||||
3. do just work pair
|
||||
expected result: |
|
||||
1. succeed
|
||||
2. LTK size is 7
|
||||
3. succeed
|
||||
cmd set:
|
||||
- ""
|
||||
- *config_numberic_comparision
|
||||
- - "SSC SSC1 blesmp -S -z KeySize -v 0x07"
|
||||
- ['P SSC1 C +BLESMP:OK']
|
||||
- - "SSC SSC1 blesmp -S -z KeySize -v 0x06"
|
||||
- ['P SSC1 C +BLESMP:OK']
|
||||
- *connect
|
||||
- - "SSC SSC2 blesmp -E -r <dut1_bt_mac> -z Enc"
|
||||
- ['R SSC2 A <key>:BLESMP:NCReq,(\d+)', 'R SSC1 C NCReq P <key>']
|
||||
- - "SSC SSC[1-2] blesmp -C -r <dut[2,1]_bt_mac> -a 1"
|
||||
- ['P SSC[1-2] C +BLESMP:Key,LocalLTK,16 C +BLESMP:AuthComplete,Success,0']
|
||||
- ID: BLUEDROID_SMP_04002
|
||||
<<: *SMP_CASE
|
||||
test point 2: BLE SMP key test
|
||||
summary: BLE SMP set key size greater than required for BLUEDROID
|
||||
allow fail: 1/2
|
||||
steps: |
|
||||
1. set key size 16
|
||||
2. set key size 17
|
||||
3. do just work pair
|
||||
expected result: |
|
||||
1. succeed
|
||||
2. LTK size is 17
|
||||
3. succeed
|
||||
cmd set:
|
||||
- ""
|
||||
- *config_numberic_comparision
|
||||
- - "SSC SSC1 blesmp -S -z KeySize -v 0x10"
|
||||
- ['P SSC1 C +BLESMP:OK']
|
||||
- - "SSC SSC1 blesmp -S -z KeySize -v 0x11"
|
||||
- ['P SSC1 C +BLESMP:OK']
|
||||
- *connect
|
||||
- - "SSC SSC2 blesmp -E -r <dut1_bt_mac> -z Enc"
|
||||
- ['R SSC2 A <key>:BLESMP:NCReq,(\d+)', 'R SSC1 C NCReq P <key>']
|
||||
- - "SSC SSC[1-2] blesmp -C -r <dut[2,1]_bt_mac> -a 1"
|
||||
- ['P SSC[1-2] C +BLESMP:Key,LocalLTK,16 C +BLESMP:AuthComplete,Success,0']
|
||||
- ID: BLUEDROID_SMP_05001
|
||||
<<: *SMP_CASE
|
||||
test point 2: BLE SMP unsuccessful pair reply test
|
||||
summary: BLE SMP unsuccessful passkey entry test for BLUEDROID
|
||||
steps: |
|
||||
1. enter passkey entry phase
|
||||
2. entry incorrect passkey and accept
|
||||
3. enter passkey entry phase
|
||||
4. entry correct passkey and reject
|
||||
5. enter passkey entry phase
|
||||
6. send numberic comparision accept
|
||||
7. enter passkey entry phase
|
||||
8. send numberic comparision reject
|
||||
expected result: |
|
||||
1. succeed
|
||||
2. pair failed
|
||||
3. succeed
|
||||
4. pair failed
|
||||
5. succeed
|
||||
6. pair failed
|
||||
7. succeed
|
||||
8. pair failed
|
||||
cmd set:
|
||||
- ""
|
||||
- *config_slave_passkey_entry
|
||||
- - LOOP 2 5 "[1,0]" "['000001','<key>']"
|
||||
- ""
|
||||
- *connect
|
||||
- - "SSC SSC2 blesmp -E -r <dut1_bt_mac> -z Enc"
|
||||
- ['P SSC2 C +BLESMP:PassKeyReq', 'P SSC1 A <key>:BLESMP:PassKeyNotify,(\d+)']
|
||||
- - "SSC SSC2 blesmp -K -r <dut1_bt_mac> -a {%d} -k {%s}"
|
||||
- ['P SSC[1-2] C +BLESMP:AuthComplete,Fail']
|
||||
- *disconnect
|
||||
- - LOOP 2 5 "[1,0]"
|
||||
- ""
|
||||
- *connect
|
||||
- - "SSC SSC2 blesmp -E -r <dut1_bt_mac> -z Enc"
|
||||
- ['P SSC2 C +BLESMP:PassKeyReq', 'P SSC1 A <key>:BLESMP:PassKeyNotify,(\d+)']
|
||||
- - "SSC SSC[1-2] blesmp -C -r <dut[2,1]_bt_mac> -a {%d}"
|
||||
- ['P SSC[1-2] C +BLESMP:AuthComplete,Fail']
|
||||
- *disconnect
|
||||
- ID: BLUEDROID_SMP_05002
|
||||
<<: *SMP_CASE
|
||||
test point 2: BLE SMP unsuccessful pair reply test
|
||||
summary: BLE SMP unsuccessful numberic comparision test for BLUEDROID
|
||||
steps: |
|
||||
1. enter numberic comparision phase
|
||||
2. entry passkey and accept
|
||||
3. enter numberic comparision phase
|
||||
4. send numberic comparision reject
|
||||
expected result: |
|
||||
1. succeed
|
||||
2. pair failed
|
||||
3. succeed
|
||||
4. pair failed
|
||||
cmd set:
|
||||
- ""
|
||||
- *config_numberic_comparision
|
||||
- - LOOP 2 6 "[1,0]"
|
||||
- ""
|
||||
- *connect
|
||||
- - "SSC SSC2 blesmp -E -r <dut1_bt_mac> -z Enc"
|
||||
- ['R SSC2 A <key>:BLESMP:NCReq,(\d+)', 'R SSC1 C NCReq P <key>']
|
||||
- - "SSC SSC2 blesmp -K -r <dut1_bt_mac> -a {%d} -k 000001"
|
||||
- []
|
||||
- - DELAY 10
|
||||
- ['P SSC[1-2] C +BLESMP:AuthComplete,Fail']
|
||||
- *disconnect
|
||||
- - LOOP 2 5 "[1,0]" "[0,1]"
|
||||
- ""
|
||||
- *connect
|
||||
- - "SSC SSC2 blesmp -E -r <dut1_bt_mac> -z Enc"
|
||||
- ['R SSC2 A <key>:BLESMP:NCReq,(\d+)', 'R SSC1 C NCReq P <key>']
|
||||
- - "SSC SSC[1,2] blesmp -C -r <dut[2,1]_bt_mac> -a [{%d},{%d}]"
|
||||
- ['P SSC[1-2] C +BLESMP:AuthComplete,Fail']
|
||||
- *disconnect
|
||||
- ID: BLUEDROID_SMP_06001
|
||||
<<: *SMP_CASE
|
||||
test environment: SSC_T1_4
|
||||
initial condition: BLE_DEINIT1
|
||||
test point 2: BLE SMP use API in abnormal state
|
||||
summary: BLE SMP use API when BLE not initialized, not enabled or not registered callback for BLUEDROID
|
||||
steps: |
|
||||
1. set security parameter
|
||||
2. send security response
|
||||
3. send passkey reply
|
||||
4. send confirm reply
|
||||
5. init BLE
|
||||
6. set security parameter
|
||||
7. send security response
|
||||
8. send passkey reply
|
||||
9. send confirm reply
|
||||
10. init BLE
|
||||
11. set security parameter
|
||||
12. send security response
|
||||
13. send passkey reply
|
||||
14. send confirm reply
|
||||
expected result: |
|
||||
1. failed
|
||||
2. failed
|
||||
3. failed
|
||||
4. failed
|
||||
5. succeed
|
||||
6. failed
|
||||
7. failed
|
||||
8. failed
|
||||
9. failed
|
||||
10. succeed
|
||||
11. failed
|
||||
12. failed
|
||||
13. failed
|
||||
14. failed
|
||||
cmd set:
|
||||
- ""
|
||||
- - "SSC SSC1 blesmp -S -z AuthReqMode -v 0x0C"
|
||||
- ['P SSC1 C +BLESMP:ERROR']
|
||||
- - "SSC SSC1 blesmp -R -a 1 -r <dut1_bt_mac>"
|
||||
- ['P SSC1 C +BLESMP:ERROR']
|
||||
- - "SSC SSC1 blesmp -K -r <dut1_bt_mac> -a 1 -k 123456"
|
||||
- ['P SSC1 C +BLESMP:ERROR']
|
||||
- - "SSC SSC1 blesmp -C -r <dut1_bt_mac> -a 1"
|
||||
- ['P SSC1 C +BLESMP:ERROR']
|
||||
- - SSC SSC1 bt -D -z init
|
||||
- ['R SSC1 C +BT:']
|
||||
- - "SSC SSC1 blesmp -S -z AuthReqMode -v 0x0C"
|
||||
- ['P SSC1 C +BLESMP']
|
||||
- - "SSC SSC1 blesmp -R -a 1 -r <dut1_bt_mac>"
|
||||
- ['P SSC1 C +BLESMP']
|
||||
- - "SSC SSC1 blesmp -K -r <dut1_bt_mac> -a 1 -k 123456"
|
||||
- ['P SSC1 C +BLESMP']
|
||||
- - "SSC SSC1 blesmp -C -r <dut1_bt_mac> -a 1"
|
||||
- ['P SSC1 C +BLESMP']
|
||||
- - SSC SSC1 bt -D -z enable
|
||||
- ['R SSC1 C +BT:']
|
||||
- - "SSC SSC1 blesmp -S -z AuthReqMode -v 0x0C"
|
||||
- ['P SSC1 C +BLESMP']
|
||||
- - "SSC SSC1 blesmp -R -a 1 -r <dut1_bt_mac>"
|
||||
- ['P SSC1 C +BLESMP']
|
||||
- - "SSC SSC1 blesmp -K -r <dut1_bt_mac> -a 1 -k 123456"
|
||||
- ['P SSC1 C +BLESMP']
|
||||
- - "SSC SSC1 blesmp -C -r <dut1_bt_mac> -a 1"
|
||||
- ['P SSC1 C +BLESMP']
|
||||
- ID: BLUEDROID_SMP_07002
|
||||
<<: *SMP_CASE
|
||||
test point 2: BLE SMP no bond test and repairing
|
||||
summary: BLE SMP just work pairing and reboot for BLUEDROID
|
||||
steps: |
|
||||
1. DUT1 and DUT2 SMP with just work pair
|
||||
2. DUT1 reboot
|
||||
3. DUT1 connect to DUT2
|
||||
4. DUT2 send auth request
|
||||
expected result: |
|
||||
1. succeed
|
||||
2. succeed
|
||||
3. succeed
|
||||
4. failed
|
||||
cmd set:
|
||||
- ""
|
||||
- *config_just_work
|
||||
- - "SSC SSC1 bleconn -C -p 0x10 -a <dut2_bt_mac>"
|
||||
- ['P SSC1 C +BLECONN:GapConnect,OK', 'P SSC2 C +BLECONN:GapConnect,OK']
|
||||
- - "SSC SSC1 blesmp -E -r <dut2_bt_mac> -z Enc"
|
||||
- ['P SSC[1-2] C +BLESMP:AuthComplete,Success,0']
|
||||
- - "SSC SSC1 reboot"
|
||||
- ['P SSC2 C +BLECONN:GapDisconnect,OK']
|
||||
- - "SSC SSC1 ble -R"
|
||||
- ['R SSC1 C +BLE:']
|
||||
- - "SSC SSC2 bleadv -D -z start"
|
||||
- ['R SSC2 C +BLEADV:OK']
|
||||
- *slave_passkey_entry_pair
|
||||
- ID: BLUEDROID_SMP_07005
|
||||
<<: *SMP_CASE
|
||||
test point 2: BLE SMP no bond test and repairing
|
||||
summary: BLE SMP initiator with master passkey entry and reconnect for BLUEDROID
|
||||
steps: |
|
||||
1. DUT1 and DUT2 SMP with master passkey entry
|
||||
2. DUT1 disconnect
|
||||
3. DUT1 connect to DUT2
|
||||
4. DUT2 send auth request
|
||||
expected result: |
|
||||
1. succeed
|
||||
2. succeed
|
||||
3. connect succeed
|
||||
4. succeed
|
||||
cmd set:
|
||||
- ""
|
||||
- *config_master_passkey_entry
|
||||
- *master_passkey_entry_pair
|
||||
- *disconnect
|
||||
- - "SSC SSC1 bleconn -C -p 0x10 -a <dut2_bt_mac>"
|
||||
- ['P SSC1 C +BLECONN:GapConnect,OK', 'P SSC2 C +BLECONN:GapConnect']
|
||||
- - "SSC SSC2 blesmp -E -r <dut1_bt_mac> -z Enc"
|
||||
- ['P SSC[1-2] C +BLESMP:AuthComplete,Success,0']
|
||||
- ID: BLUEDROID_SMP_07006
|
||||
<<: *SMP_CASE
|
||||
test point 2: BLE SMP no bond test and repairing
|
||||
summary: BLE SMP initiator with master passkey entry and reboot for BLUEDROID
|
||||
steps: |
|
||||
1. DUT1 and DUT2 SMP bond with lagecy pairing
|
||||
2. DUT1 reboot
|
||||
3. DUT1 connect to DUT2
|
||||
4. DUT2 send auth requst
|
||||
expected result: |
|
||||
1. succeed
|
||||
2. succeed
|
||||
3. connect succeed
|
||||
4. fail
|
||||
cmd set:
|
||||
- ""
|
||||
- *config_master_passkey_entry
|
||||
- *master_passkey_entry_pair
|
||||
- - "SSC SSC1 reboot"
|
||||
- ['P SSC2 C +BLECONN:GapDisconnect,OK']
|
||||
- - "SSC SSC1 ble -R"
|
||||
- ['R SSC1 C +BLE:']
|
||||
- - "SSC SSC2 bleadv -D -z start"
|
||||
- ['R SSC2 C +BLEADV:OK']
|
||||
- *numberic_comparision_pair
|
||||
- ID: BLUEDROID_SMP_07007
|
||||
<<: *SMP_CASE
|
||||
test point 2: BLE SMP no bond test and repairing
|
||||
summary: BLE SMP initiator numberic comparision and reconnect for BLUEDROID
|
||||
steps: |
|
||||
1. DUT1 and DUT2 SMP with numberic comparision
|
||||
2. DUT1 disconnect
|
||||
3. DUT1 connect to DUT2
|
||||
4. DUT2 send auth requst
|
||||
expected result: |
|
||||
1. succeed
|
||||
2. succeed
|
||||
3. connect succeed
|
||||
4. succeed
|
||||
cmd set:
|
||||
- ""
|
||||
- *config_numberic_comparision
|
||||
- *numberic_comparision_pair
|
||||
- *disconnect
|
||||
- - "SSC SSC1 bleconn -C -p 0x10 -a <dut2_bt_mac>"
|
||||
- ['P SSC1 C +BLECONN:GapConnect,OK', 'P SSC2 C +BLECONN:GapConnect']
|
||||
- - "SSC SSC2 blesmp -E -r <dut1_bt_mac> -z Enc"
|
||||
- ['P SSC[1-2] C +BLESMP:AuthComplete,Success,0']
|
||||
- ID: BLUEDROID_SMP_07008
|
||||
<<: *SMP_CASE
|
||||
test point 2: BLE SMP no bond test and repairing
|
||||
summary: BLE SMP initiator numberic comparision and reboot for BLUEDROID
|
||||
steps: |
|
||||
1. DUT1 and DUT2 SMP with numberic comparision
|
||||
2. DUT1 disconnect
|
||||
3. DUT1 and DUT2 reboot
|
||||
4. DUT2 send auth requst
|
||||
expected result: |
|
||||
1. succeed
|
||||
2. succeed
|
||||
3. connect succeed
|
||||
4. failed
|
||||
cmd set:
|
||||
- ""
|
||||
- *config_numberic_comparision
|
||||
- *numberic_comparision_pair
|
||||
- - "SSC SSC1 reboot"
|
||||
- ['P SSC2 C +BLECONN:GapDisconnect,OK']
|
||||
- - "SSC SSC1 ble -R"
|
||||
- ['R SSC1 C +BLE:']
|
||||
- - "SSC SSC2 bleadv -D -z start"
|
||||
- ['R SSC2 C +BLEADV:OK']
|
||||
- *numberic_comparision_pair
|
||||
- ID: BLUEDROID_SMP_08001
|
||||
<<: *SMP_CASE
|
||||
test point 2: BLE SMP bond item management test
|
||||
summary: BLE SMP get bond list and number without bond device for BLUEDROID
|
||||
steps: |
|
||||
1. DUT1 get bond list
|
||||
2. DUT1 get bond number
|
||||
expected result: |
|
||||
1. succeed
|
||||
2. succeed
|
||||
cmd set:
|
||||
- ""
|
||||
- - "SSC SSC1 blesmp -B -z getlist -n 1"
|
||||
- ['P SSC1 C +BLESMP:GetBondList,OK,0']
|
||||
- - "SSC SSC1 blesmp -B -z getnum"
|
||||
- ['P SSC1 C +BLESMP:GetBondNum,0']
|
||||
- ID: BLUEDROID_SMP_08002
|
||||
<<: *SMP_CASE
|
||||
test point 2: BLE SMP bond item management test
|
||||
summary: BLE SMP remove bond after connected
|
||||
steps: |
|
||||
1. DUT2 set AuthReqMode and RspKey
|
||||
2. pairing
|
||||
3. remove bond
|
||||
expected result: |
|
||||
1. Succeed
|
||||
2. Succeed
|
||||
3. Succeed
|
||||
cmd set:
|
||||
- ""
|
||||
- *config_bond_device
|
||||
- - "SSC SSC2 bleadv -D -z start"
|
||||
- ['R SSC2 C +BLEADV:Start,OK']
|
||||
- *connect
|
||||
- - "SSC SSC2 blesmp -E -r <dut1_bt_mac> -z Enc"
|
||||
- ['P SSC1 C +BLESMP:AuthComplete,Success,0','P SSC2 C +BLESMP:AuthComplete,Success,0']
|
||||
- - "SSC SSC1 blesmp -B -z getnum"
|
||||
- ['P SSC1 C +BLESMP:GetBondNum,1']
|
||||
- - "SSC SSC1 blesmp -B -z remove -r <dut2_bt_mac>"
|
||||
- ['P SSC1 RE "\+BLESMP:RemoveBond,Success,%%s"%%(<dut2_bt_mac>)']
|
||||
- ID: BLUEDROID_SMP_08003
|
||||
<<: *SMP_CASE
|
||||
test point 2: BLE SMP bond item management test
|
||||
summary: BLE SMP get bond list and number when pairing and after reboot for BLUEDROID
|
||||
steps: |
|
||||
1. all slaves set AuthReqMode and RspKey
|
||||
2. do pairing
|
||||
3. master and slave get bond list and num
|
||||
4. reboot
|
||||
5. master and slave get bond list and num
|
||||
6. slave remove bond device
|
||||
expected result: |
|
||||
1. Succeed
|
||||
2. Succeed
|
||||
3. Succeed
|
||||
4. succeed
|
||||
5. succeed
|
||||
6. succeed
|
||||
test environment: SSC_T5_1
|
||||
initial condition: BLE_INIT_SMP5
|
||||
allow fail: 3/5
|
||||
cmd set:
|
||||
- ""
|
||||
- - "SSC SSC[2-5] blesmp -S -z AuthReqMode -v 0x01"
|
||||
- ['P SSC[2-5] C +BLESMP:OK']
|
||||
- - "SSC SSC[2-5] blesmp -S -z IOCAP -v 0x03"
|
||||
- ['P SSC[2-5] C +BLESMP:OK']
|
||||
- - "SSC SSC[2-5] blesmp -S -z RspKey -v 0x03"
|
||||
- ['P SSC[2-5] C +BLESMP:OK']
|
||||
- - LOOP 4 4 "[2,3,4,5]" "[2,3,4,5]" "[2,3,4,5]" "[2,3,4,5]" "[2,3,4,5]" "[2,3,4,5]" "[2,3,4,5]"
|
||||
- ""
|
||||
- - "SSC SSC{%d} bleadv -D -z start"
|
||||
- ['R SSC{%d} C +BLEADV:Start,OK']
|
||||
- - "SSC SSC1 bleconn -C -p 0x10 -a <dut{%d}_bt_mac>"
|
||||
- ['P SSC1 C +BLECONN:GapConnect,OK', 'P SSC{%d} C +BLECONN:GapConnect']
|
||||
- - "SSC SSC{%d} blesmp -E -r <dut1_bt_mac> -z Enc"
|
||||
- ['P SSC1 C +BLESMP:SecReq']
|
||||
- - "SSC SSC1 blesmp -R -a 1 -r <dut{%d}_bt_mac>"
|
||||
- ['P SSC1 C +BLESMP:AuthComplete,Success,0','P SSC{%d} C +BLESMP:AuthComplete,Success,0']
|
||||
- - "SSC SSC1 blesmp -B -z getlist -n 4"
|
||||
- ['P SSC1 C +BLESMP:GetBondList,OK,4']
|
||||
- - "SSC SSC1 blesmp -B -z getnum"
|
||||
- ['P SSC1 C +BLESMP:GetBondNum,4']
|
||||
- - "SSC SSC2 blesmp -B -z getnum"
|
||||
- ['P SSC2 C +BLESMP:GetBondNum,1']
|
||||
- - "SSC SSC[1-2] reboot"
|
||||
- ['R SSC[1-2] C !!!ready!!!']
|
||||
- - "SSC SSC[1-2] ble -R"
|
||||
- ["R SSC[1-2] C +BLE:OK"]
|
||||
- - "SSC SSC1 blesmp -B -z getnum"
|
||||
- ['P SSC1 C +BLESMP:GetBondNum,4']
|
||||
- - "SSC SSC2 blesmp -B -z getnum"
|
||||
- ['P SSC2 C +BLESMP:GetBondNum,1']
|
||||
- - "SSC SSC2 blesmp -B -z remove -r <dut1_bt_mac>"
|
||||
- ['P SSC2 RE "\+BLESMP:RemoveBond,Success,%%s"%%(<dut1_bt_mac>)']
|
||||
- ID: BLUEDROID_SMP_08004
|
||||
<<: *SMP_CASE
|
||||
test point 2: BLE SMP bond item management test
|
||||
summary: BLE SMP remove bond which not bond for BLUEDROID
|
||||
steps: |
|
||||
1. DUT1 remove bond
|
||||
expected result: |
|
||||
1. failed
|
||||
cmd set:
|
||||
- ""
|
||||
- - "SSC SSC1 blesmp -B -z remove -r <dut2_bt_mac>"
|
||||
- ['P SSC1 C +BLESMP:RemoveBond,Fail']
|
||||
- ID: BLUEDROID_SMP_08005
|
||||
<<: *SMP_CASE
|
||||
test point 2: BLE SMP remove bond
|
||||
summary: BLE SMP bond 15/16 devices and get list
|
||||
steps: |
|
||||
1. DUT2 set AuthReqMode and RspKey
|
||||
2. DUT2 set static random address
|
||||
3. DUT1 and DUT2 do pairing
|
||||
4. loop step 2 and step3 16 times
|
||||
5. get bond list and bond num
|
||||
6. DUT2 set static random address
|
||||
7. DUT1 and DUT2 do pairing
|
||||
8. get bond list and bond num
|
||||
expected result: |
|
||||
1. Succeed
|
||||
2. Succeed
|
||||
3. Succeed
|
||||
4. succeed
|
||||
5. succeed
|
||||
6. succeed
|
||||
7. succeed
|
||||
8. succeed
|
||||
cmd set:
|
||||
- ""
|
||||
- - "SSC SSC[1-2] blesmp -S -z AuthReqMode -v 0x01"
|
||||
- ['P SSC[1-2] C +BLESMP:OK']
|
||||
- - "SSC SSC[1-2] blesmp -S -z IOCAP -v 0x03"
|
||||
- ['P SSC[1-2] C +BLESMP:OK']
|
||||
- - "SSC SSC[1-2] blesmp -S -z RspKey -v 0x03"
|
||||
- ['P SSC[1-2] C +BLESMP:OK']
|
||||
- - LOOP 15 7 "range(0,15)" "range(0,15)" "range(0,15)"
|
||||
- ""
|
||||
- - "SSC SSC2 bleadv -D -z stop"
|
||||
- ['R SSC2 C +BLEADV:Stop,OK']
|
||||
- - "SSC SSC2 ble -S -z randAddr -a c0:9b:0e:36:6d:7{%x} -r 1"
|
||||
- ["R SSC2 C +BLECONN:SetRandAddr,OK"]
|
||||
- - "SSC SSC2 bleadv -D -z start -o 1"
|
||||
- ['R SSC2 C +BLEADV:Start,OK']
|
||||
- - "SSC SSC1 bleconn -C -p 0x10 -a c0:9b:0e:36:6d:7{%x} -r 1"
|
||||
- ['P SSC1 C +BLECONN:GapConnect,OK', 'P SSC2 C +BLECONN:GapConnect']
|
||||
- - "SSC SSC2 blesmp -E -r <dut1_bt_mac> -z Enc"
|
||||
- ['P SSC1 C +BLESMP:SecReq']
|
||||
- - "SSC SSC1 blesmp -R -a 1 -r c0:9b:0e:36:6d:7{%x}"
|
||||
- ['P SSC1 C +BLESMP:AuthComplete,Success,0','P SSC2 C +BLESMP:AuthComplete,Success,0']
|
||||
- - "SSC SSC1 bleconn -D -z all"
|
||||
- ['P SSC1 C +BLE:CLOSE', 'P SSC2 C +BLECONN:GapDisconnect,OK']
|
||||
- - "SSC SSC1 blesmp -B -z getlist -n 16"
|
||||
- ['P SSC1 C +BLESMP:GetBondList,OK,15']
|
||||
- - "SSC SSC2 ble -S -z randAddr -a c1:0a:d3:25:7a:cf -r 1"
|
||||
- ["R SSC2 C +BLECONN:SetRandAddr,OK"]
|
||||
- - "SSC SSC2 bleadv -D -z stop"
|
||||
- ['R SSC2 C +BLEADV:Stop,OK']
|
||||
- - "SSC SSC2 bleadv -D -z start -o 1"
|
||||
- ['R SSC2 C +BLEADV:Start,OK']
|
||||
- - "SSC SSC1 bleconn -C -p 0x10 -a c1:0a:d3:25:7a:cf -r 1"
|
||||
- ['P SSC1 C +BLECONN:GapConnect,OK', 'P SSC2 C +BLECONN:GapConnect']
|
||||
- - "SSC SSC2 blesmp -E -r <dut1_bt_mac> -z Enc"
|
||||
- ['P SSC1 C +BLESMP:SecReq']
|
||||
- - "SSC SSC1 blesmp -R -a 1 -r c1:0a:d3:25:7a:cf"
|
||||
- ['P SSC1 C +BLESMP:AuthComplete,Success,0','P SSC2 C +BLESMP:AuthComplete,Success,0']
|
||||
- - "SSC SSC1 blesmp -B -z getlist -n 16"
|
||||
- ['P SSC1 C +BLESMP:GetBondList,OK,15']
|
||||
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user