Merge branch 'master' into feature/esp32s2beta_merge
This commit is contained in:
commit
5830f529d8
115 changed files with 2439 additions and 622 deletions
6
.github/workflows/issue_comment.yml
vendored
6
.github/workflows/issue_comment.yml
vendored
|
@ -1,12 +1,14 @@
|
||||||
|
name: Sync issue comments to JIRA
|
||||||
|
|
||||||
on: issue_comment
|
on: issue_comment
|
||||||
name: Sync issue and PR comments to JIRA
|
|
||||||
jobs:
|
jobs:
|
||||||
syncToJIRA:
|
syncToJIRA:
|
||||||
name: Sync to JIRA
|
name: Sync to JIRA
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@master
|
- uses: actions/checkout@master
|
||||||
- name: Sync to JIRA
|
- name: Sync issue comments to JIRA
|
||||||
uses: espressif/github-actions/sync_issues_to_jira@master
|
uses: espressif/github-actions/sync_issues_to_jira@master
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
6
.github/workflows/issues.yml
vendored
6
.github/workflows/issues.yml
vendored
|
@ -1,12 +1,14 @@
|
||||||
on: issues
|
|
||||||
name: Sync issues to JIRA
|
name: Sync issues to JIRA
|
||||||
|
|
||||||
|
on: issues
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
syncToJIRA:
|
syncToJIRA:
|
||||||
name: Sync to JIRA
|
name: Sync to JIRA
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@master
|
- uses: actions/checkout@master
|
||||||
- name: Sync to JIRA
|
- name: Sync issues to JIRA project
|
||||||
uses: espressif/github-actions/sync_issues_to_jira@master
|
uses: espressif/github-actions/sync_issues_to_jira@master
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
16
.github/workflows/pull_request.yml
vendored
16
.github/workflows/pull_request.yml
vendored
|
@ -1,16 +0,0 @@
|
||||||
on: pull_request
|
|
||||||
name: Sync PRs to JIRA
|
|
||||||
jobs:
|
|
||||||
syncToJIRA:
|
|
||||||
name: Sync to JIRA
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@master
|
|
||||||
- name: Sync to JIRA
|
|
||||||
uses: espressif/github-actions/sync_issues_to_jira@master
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
JIRA_PASS: ${{ secrets.JIRA_PASS }}
|
|
||||||
JIRA_PROJECT: IDFGH
|
|
||||||
JIRA_URL: ${{ secrets.JIRA_URL }}
|
|
||||||
JIRA_USER: ${{ secrets.JIRA_USER }}
|
|
32
.github/workflows/python_lint.yml
vendored
Normal file
32
.github/workflows/python_lint.yml
vendored
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
name: Python CI
|
||||||
|
|
||||||
|
# This workflow will be triggered when a PR modifies some python relevant files
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
paths:
|
||||||
|
- "*.py"
|
||||||
|
- "requirements.txt"
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
python_lint:
|
||||||
|
name: python lint
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
python-version: [2.7, 3.5, 3.6, 3.7]
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@master
|
||||||
|
- name: Set up Python environment
|
||||||
|
uses: actions/setup-python@master
|
||||||
|
with:
|
||||||
|
python-version: ${{ matrix.python-version }}
|
||||||
|
- name: Install dependencies
|
||||||
|
run: |
|
||||||
|
pip install --upgrade pip
|
||||||
|
pip install -r requirements.txt
|
||||||
|
- name: Lint with flake8
|
||||||
|
run: |
|
||||||
|
pip install flake8
|
||||||
|
flake8 . --config=.flake8
|
|
@ -67,7 +67,7 @@ variables:
|
||||||
rm -rf "$CUSTOM_TOOLCHAIN_PATH"
|
rm -rf "$CUSTOM_TOOLCHAIN_PATH"
|
||||||
|
|
||||||
.setup_tools_unless_target_test: &setup_tools_unless_target_test |
|
.setup_tools_unless_target_test: &setup_tools_unless_target_test |
|
||||||
if [ "$CI_JOB_STAGE" != "target_test" ]; then
|
if [[ "$SETUP_TOOLS" == "1" || "$CI_JOB_STAGE" != "target_test" ]]; then
|
||||||
tools/idf_tools.py --non-interactive install && eval "$(tools/idf_tools.py --non-interactive export)" || exit 1
|
tools/idf_tools.py --non-interactive install && eval "$(tools/idf_tools.py --non-interactive export)" || exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
|
@ -1,7 +0,0 @@
|
||||||
language: python
|
|
||||||
sudo: false
|
|
||||||
python:
|
|
||||||
- "3.4"
|
|
||||||
script:
|
|
||||||
- pip install flake8
|
|
||||||
- travis_wait 20 python -m flake8 --config=.flake8 .
|
|
77
Kconfig
77
Kconfig
|
@ -82,6 +82,83 @@ mainmenu "Espressif IoT Development Framework Configuration"
|
||||||
|
|
||||||
endmenu # SDK tool configuration
|
endmenu # SDK tool configuration
|
||||||
|
|
||||||
|
menu "Build type"
|
||||||
|
|
||||||
|
choice APP_BUILD_TYPE
|
||||||
|
prompt "Application build type"
|
||||||
|
default APP_BUILD_TYPE_APP_2NDBOOT
|
||||||
|
help
|
||||||
|
Select the way the application is built.
|
||||||
|
|
||||||
|
By default, the application is built as a binary file in a format compatible with
|
||||||
|
the ESP32 bootloader. In addition to this application, 2nd stage bootloader is
|
||||||
|
also built. Application and bootloader binaries can be written into flash and
|
||||||
|
loaded/executed from there.
|
||||||
|
|
||||||
|
Another option, useful for only very small and limited applications, is to only link
|
||||||
|
the .elf file of the application, such that it can be loaded directly into RAM over
|
||||||
|
JTAG. Note that since IRAM and DRAM sizes are very limited, it is not possible to
|
||||||
|
build any complex application this way. However for kinds of testing and debugging,
|
||||||
|
this option may provide faster iterations, since the application does not need to be
|
||||||
|
written into flash.
|
||||||
|
Note that at the moment, ESP-IDF does not contain all the startup code required to
|
||||||
|
initialize the CPUs and ROM memory (data/bss). Therefore it is necessary to execute
|
||||||
|
a bit of ROM code prior to executing the application. A gdbinit file may look as follows:
|
||||||
|
|
||||||
|
# Connect to a running instance of OpenOCD
|
||||||
|
target remote :3333
|
||||||
|
# Reset and halt the target
|
||||||
|
mon reset halt
|
||||||
|
# Run to a specific point in ROM code,
|
||||||
|
# where most of initialization is complete.
|
||||||
|
thb *0x40007901
|
||||||
|
c
|
||||||
|
# Load the application into RAM
|
||||||
|
load
|
||||||
|
# Run till app_main
|
||||||
|
tb app_main
|
||||||
|
c
|
||||||
|
|
||||||
|
Execute this gdbinit file as follows:
|
||||||
|
|
||||||
|
xtensa-esp32-elf-gdb build/app-name.elf -x gdbinit
|
||||||
|
|
||||||
|
Recommended sdkconfig.defaults for building loadable ELF files is as follows.
|
||||||
|
CONFIG_APP_BUILD_TYPE_ELF_RAM is required, other options help reduce application
|
||||||
|
memory footprint.
|
||||||
|
|
||||||
|
CONFIG_APP_BUILD_TYPE_ELF_RAM=y
|
||||||
|
CONFIG_VFS_SUPPORT_TERMIOS=
|
||||||
|
CONFIG_NEWLIB_NANO_FORMAT=y
|
||||||
|
CONFIG_ESP32_PANIC_PRINT_HALT=y
|
||||||
|
CONFIG_ESP32_DEBUG_STUBS_ENABLE=
|
||||||
|
CONFIG_ESP_ERR_TO_NAME_LOOKUP=
|
||||||
|
|
||||||
|
|
||||||
|
config APP_BUILD_TYPE_APP_2NDBOOT
|
||||||
|
bool
|
||||||
|
prompt "Default (binary application + 2nd stage bootloader)"
|
||||||
|
select APP_BUILD_GENERATE_BINARIES
|
||||||
|
select APP_BUILD_BOOTLOADER
|
||||||
|
select APP_BUILD_USE_FLASH_SECTIONS
|
||||||
|
|
||||||
|
config APP_BUILD_TYPE_ELF_RAM
|
||||||
|
bool
|
||||||
|
prompt "ELF file, loadable into RAM (EXPERIMENTAL))"
|
||||||
|
endchoice # APP_BUILD_TYPE
|
||||||
|
|
||||||
|
# Hidden options, set according to the choice above
|
||||||
|
config APP_BUILD_GENERATE_BINARIES
|
||||||
|
bool # Whether to generate .bin files or not
|
||||||
|
|
||||||
|
config APP_BUILD_BOOTLOADER
|
||||||
|
bool # Whether to build the bootloader
|
||||||
|
|
||||||
|
config APP_BUILD_USE_FLASH_SECTIONS
|
||||||
|
bool # Whether to place code/data into memory-mapped flash sections
|
||||||
|
|
||||||
|
endmenu # Build type
|
||||||
|
|
||||||
source "$COMPONENT_KCONFIGS_PROJBUILD"
|
source "$COMPONENT_KCONFIGS_PROJBUILD"
|
||||||
|
|
||||||
menu "Compiler options"
|
menu "Compiler options"
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
idf_component_register(PRIV_REQUIRES partition_table)
|
idf_component_register(PRIV_REQUIRES partition_table)
|
||||||
|
|
||||||
# Do not generate flash file when building bootloader or is in early expansion of the build
|
# Do not generate flash file when building bootloader or is in early expansion of the build
|
||||||
if(BOOTLOADER_BUILD)
|
if(BOOTLOADER_BUILD OR NOT CONFIG_APP_BUILD_BOOTLOADER)
|
||||||
return()
|
return()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|
|
@ -391,7 +391,7 @@ menu "Security features"
|
||||||
config SECURE_BOOT_SIGNING_KEY
|
config SECURE_BOOT_SIGNING_KEY
|
||||||
string "Secure boot private signing key"
|
string "Secure boot private signing key"
|
||||||
depends on SECURE_BOOT_BUILD_SIGNED_BINARIES
|
depends on SECURE_BOOT_BUILD_SIGNED_BINARIES
|
||||||
default secure_boot_signing_key.pem
|
default "secure_boot_signing_key.pem"
|
||||||
help
|
help
|
||||||
Path to the key file used to sign app images.
|
Path to the key file used to sign app images.
|
||||||
|
|
||||||
|
@ -407,7 +407,7 @@ menu "Security features"
|
||||||
config SECURE_BOOT_VERIFICATION_KEY
|
config SECURE_BOOT_VERIFICATION_KEY
|
||||||
string "Secure boot public signature verification key"
|
string "Secure boot public signature verification key"
|
||||||
depends on SECURE_SIGNED_APPS && !SECURE_BOOT_BUILD_SIGNED_BINARIES
|
depends on SECURE_SIGNED_APPS && !SECURE_BOOT_BUILD_SIGNED_BINARIES
|
||||||
default signature_verification_key.bin
|
default "signature_verification_key.bin"
|
||||||
help
|
help
|
||||||
Path to a public key file used to verify signed images. This key is compiled into the bootloader and/or
|
Path to a public key file used to verify signed images. This key is compiled into the bootloader and/or
|
||||||
app, to verify app images.
|
app, to verify app images.
|
||||||
|
@ -421,7 +421,7 @@ menu "Security features"
|
||||||
choice SECURE_BOOTLOADER_KEY_ENCODING
|
choice SECURE_BOOTLOADER_KEY_ENCODING
|
||||||
bool "Hardware Key Encoding"
|
bool "Hardware Key Encoding"
|
||||||
depends on SECURE_BOOTLOADER_REFLASHABLE
|
depends on SECURE_BOOTLOADER_REFLASHABLE
|
||||||
default SECURE_BOOTLOADER_NO_ENCODING
|
default SECURE_BOOTLOADER_KEY_ENCODING_256BIT
|
||||||
help
|
help
|
||||||
|
|
||||||
In reflashable secure bootloader mode, a hardware key is derived from the signing key (with SHA-256) and
|
In reflashable secure bootloader mode, a hardware key is derived from the signing key (with SHA-256) and
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
set(BOOTLOADER_OFFSET 0x1000)
|
set(BOOTLOADER_OFFSET 0x1000)
|
||||||
|
|
||||||
# Do not generate flash file when building bootloader
|
# Do not generate flash file when building bootloader
|
||||||
if(BOOTLOADER_BUILD)
|
if(BOOTLOADER_BUILD OR NOT CONFIG_APP_BUILD_BOOTLOADER)
|
||||||
return()
|
return()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|
|
@ -149,6 +149,13 @@ int bootloader_common_select_otadata(const esp_ota_select_entry_t *two_otadata,
|
||||||
*/
|
*/
|
||||||
esp_err_t bootloader_common_get_partition_description(const esp_partition_pos_t *partition, esp_app_desc_t *app_desc);
|
esp_err_t bootloader_common_get_partition_description(const esp_partition_pos_t *partition, esp_app_desc_t *app_desc);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get chip revision
|
||||||
|
*
|
||||||
|
* @return Chip revision number
|
||||||
|
*/
|
||||||
|
uint8_t bootloader_common_get_chip_revision(void);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Check if the image (bootloader and application) has valid chip ID and revision
|
* @brief Check if the image (bootloader and application) has valid chip ID and revision
|
||||||
*
|
*
|
||||||
|
|
|
@ -32,10 +32,11 @@
|
||||||
#include "bootloader_common.h"
|
#include "bootloader_common.h"
|
||||||
#include "soc/gpio_periph.h"
|
#include "soc/gpio_periph.h"
|
||||||
#include "soc/rtc.h"
|
#include "soc/rtc.h"
|
||||||
|
#include "soc/efuse_reg.h"
|
||||||
|
#include "soc/apb_ctrl_reg.h"
|
||||||
#include "esp_image_format.h"
|
#include "esp_image_format.h"
|
||||||
#include "bootloader_sha.h"
|
#include "bootloader_sha.h"
|
||||||
#include "sys/param.h"
|
#include "sys/param.h"
|
||||||
#include "esp_efuse.h"
|
|
||||||
|
|
||||||
#define ESP_PARTITION_HASH_LEN 32 /* SHA-256 digest length */
|
#define ESP_PARTITION_HASH_LEN 32 /* SHA-256 digest length */
|
||||||
|
|
||||||
|
@ -279,22 +280,50 @@ void bootloader_common_vddsdio_configure(void)
|
||||||
#endif // CONFIG_BOOTLOADER_VDDSDIO_BOOST
|
#endif // CONFIG_BOOTLOADER_VDDSDIO_BOOST
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_IDF_TARGET_ESP32
|
||||||
|
uint8_t bootloader_common_get_chip_revision(void)
|
||||||
|
{
|
||||||
|
uint8_t eco_bit0, eco_bit1, eco_bit2;
|
||||||
|
eco_bit0 = (REG_READ(EFUSE_BLK0_RDATA3_REG) & 0xF000) >> 15;
|
||||||
|
eco_bit1 = (REG_READ(EFUSE_BLK0_RDATA5_REG) & 0x100000) >> 20;
|
||||||
|
eco_bit2 = (REG_READ(APB_CTRL_DATE_REG) & 0x80000000) >> 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;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
esp_err_t bootloader_common_check_chip_validity(const esp_image_header_t* img_hdr)
|
esp_err_t bootloader_common_check_chip_validity(const esp_image_header_t* img_hdr)
|
||||||
{
|
{
|
||||||
esp_err_t err = ESP_OK;
|
esp_err_t err = ESP_OK;
|
||||||
esp_chip_id_t chip_id = CONFIG_IDF_FIRMWARE_CHIP_ID;
|
esp_chip_id_t chip_id = CONFIG_IDF_FIRMWARE_CHIP_ID;
|
||||||
if (chip_id != img_hdr->chip_id) {
|
if (chip_id != img_hdr->chip_id) {
|
||||||
ESP_LOGE(TAG, "image has invalid chip ID, expected at least %d, found %d", chip_id, img_hdr->chip_id);
|
ESP_LOGE(TAG, "mismatch chip ID, expect %d, found %d", chip_id, img_hdr->chip_id);
|
||||||
err = ESP_FAIL;
|
err = ESP_FAIL;
|
||||||
}
|
}
|
||||||
uint8_t revision = esp_efuse_get_chip_ver();
|
uint8_t revision = bootloader_common_get_chip_revision();
|
||||||
if (revision < img_hdr->min_chip_rev) {
|
if (revision < img_hdr->min_chip_rev) {
|
||||||
ESP_LOGE(TAG, "image has invalid chip revision, expected at least %d, found %d", revision, img_hdr->min_chip_rev);
|
ESP_LOGE(TAG, "can't run on lower chip revision, expect %d, found %d", revision, img_hdr->min_chip_rev);
|
||||||
err = ESP_FAIL;
|
err = ESP_FAIL;
|
||||||
} else if (revision != img_hdr->min_chip_rev) {
|
} else if (revision != img_hdr->min_chip_rev) {
|
||||||
ESP_LOGI(TAG, "This chip is revision %d but project was configured for minimum revision %d. "\
|
ESP_LOGI(TAG, "mismatch chip revision, expect %d, found %d", revision, img_hdr->min_chip_rev);
|
||||||
"Suggest setting project minimum revision to %d if safe to do so.",
|
|
||||||
revision, img_hdr->min_chip_rev, revision);
|
|
||||||
}
|
}
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
|
@ -60,7 +60,6 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "sdkconfig.h"
|
#include "sdkconfig.h"
|
||||||
#include "esp_efuse.h"
|
|
||||||
#include "esp_image_format.h"
|
#include "esp_image_format.h"
|
||||||
#include "esp_secure_boot.h"
|
#include "esp_secure_boot.h"
|
||||||
#include "esp_flash_encrypt.h"
|
#include "esp_flash_encrypt.h"
|
||||||
|
@ -171,7 +170,7 @@ static esp_err_t bootloader_main(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check chip ID and minimum chip revision that supported by this image */
|
/* Check chip ID and minimum chip revision that supported by this image */
|
||||||
uint8_t revision = esp_efuse_get_chip_ver();
|
uint8_t revision = bootloader_common_get_chip_revision();
|
||||||
ESP_LOGI(TAG, "Chip Revision: %d", revision);
|
ESP_LOGI(TAG, "Chip Revision: %d", revision);
|
||||||
if (bootloader_common_check_chip_validity(&fhdr) != ESP_OK) {
|
if (bootloader_common_check_chip_validity(&fhdr) != ESP_OK) {
|
||||||
return ESP_FAIL;
|
return ESP_FAIL;
|
||||||
|
|
|
@ -377,9 +377,13 @@ if(CONFIG_BT_ENABLED)
|
||||||
host/nimble/nimble/nimble/host/store/ram/include
|
host/nimble/nimble/nimble/host/store/ram/include
|
||||||
host/nimble/nimble/nimble/host/store/config/include
|
host/nimble/nimble/nimble/host/store/config/include
|
||||||
host/nimble/nimble/porting/npl/freertos/include
|
host/nimble/nimble/porting/npl/freertos/include
|
||||||
host/nimble/nimble/ext/tinycrypt/include
|
|
||||||
host/nimble/esp-hci/include)
|
host/nimble/esp-hci/include)
|
||||||
|
|
||||||
|
if(NOT CONFIG_BT_NIMBLE_CRYPTO_STACK_MBEDTLS)
|
||||||
|
|
||||||
|
list(APPEND include_dirs
|
||||||
|
host/nimble/nimble/ext/tinycrypt/include)
|
||||||
|
|
||||||
list(APPEND srcs "host/nimble/nimble/ext/tinycrypt/src/utils.c"
|
list(APPEND srcs "host/nimble/nimble/ext/tinycrypt/src/utils.c"
|
||||||
"host/nimble/nimble/ext/tinycrypt/src/sha256.c"
|
"host/nimble/nimble/ext/tinycrypt/src/sha256.c"
|
||||||
"host/nimble/nimble/ext/tinycrypt/src/ecc.c"
|
"host/nimble/nimble/ext/tinycrypt/src/ecc.c"
|
||||||
|
@ -394,8 +398,10 @@ if(CONFIG_BT_ENABLED)
|
||||||
"host/nimble/nimble/ext/tinycrypt/src/hmac_prng.c"
|
"host/nimble/nimble/ext/tinycrypt/src/hmac_prng.c"
|
||||||
"host/nimble/nimble/ext/tinycrypt/src/ecc_platform_specific.c"
|
"host/nimble/nimble/ext/tinycrypt/src/ecc_platform_specific.c"
|
||||||
"host/nimble/nimble/ext/tinycrypt/src/hmac.c"
|
"host/nimble/nimble/ext/tinycrypt/src/hmac.c"
|
||||||
"host/nimble/nimble/ext/tinycrypt/src/cbc_mode.c"
|
"host/nimble/nimble/ext/tinycrypt/src/cbc_mode.c")
|
||||||
"host/nimble/nimble/nimble/host/util/src/addr.c"
|
endif()
|
||||||
|
|
||||||
|
list(APPEND srcs "host/nimble/nimble/nimble/host/util/src/addr.c"
|
||||||
"host/nimble/nimble/nimble/host/services/gatt/src/ble_svc_gatt.c"
|
"host/nimble/nimble/nimble/host/services/gatt/src/ble_svc_gatt.c"
|
||||||
"host/nimble/nimble/nimble/host/services/tps/src/ble_svc_tps.c"
|
"host/nimble/nimble/nimble/host/services/tps/src/ble_svc_tps.c"
|
||||||
"host/nimble/nimble/nimble/host/services/ias/src/ble_svc_ias.c"
|
"host/nimble/nimble/nimble/host/services/ias/src/ble_svc_ias.c"
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
menu Bluetooth
|
menu "Bluetooth"
|
||||||
|
|
||||||
config BT_ENABLED
|
config BT_ENABLED
|
||||||
bool "Bluetooth"
|
bool "Bluetooth"
|
||||||
|
@ -359,6 +359,21 @@ menu Bluetooth
|
||||||
If you set `BTDM_BLE_ADV_REPORT_DISCARD_THRSHOLD` to a small value or printf every adv lost event, it
|
If you set `BTDM_BLE_ADV_REPORT_DISCARD_THRSHOLD` to a small value or printf every adv lost event, it
|
||||||
may cause adv packets lost more.
|
may cause adv packets lost more.
|
||||||
|
|
||||||
|
menuconfig BTDM_COEX_BT_OPTIONS
|
||||||
|
bool "Coexistence Bluetooth Side Options"
|
||||||
|
depends on ESP32_WIFI_SW_COEXIST_ENABLE
|
||||||
|
default n
|
||||||
|
help
|
||||||
|
Options of Bluetooth Side of WiFi and bluetooth coexistence.
|
||||||
|
|
||||||
|
config BTDM_COEX_BLE_ADV_HIGH_PRIORITY
|
||||||
|
bool "Improve BLE ADV priority for WiFi & BLE coexistence"
|
||||||
|
depends on BTDM_COEX_BT_OPTIONS
|
||||||
|
default n
|
||||||
|
help
|
||||||
|
Improve BLE ADV coexistence priority to make it better performance.
|
||||||
|
For example, BLE mesh need to enable this option to improve BLE adv performance.
|
||||||
|
|
||||||
endmenu
|
endmenu
|
||||||
|
|
||||||
choice BT_HOST
|
choice BT_HOST
|
||||||
|
|
|
@ -153,6 +153,7 @@ endif
|
||||||
|
|
||||||
|
|
||||||
ifdef CONFIG_BT_NIMBLE_ENABLED
|
ifdef CONFIG_BT_NIMBLE_ENABLED
|
||||||
|
|
||||||
COMPONENT_ADD_INCLUDEDIRS += host/nimble/nimble/nimble/include \
|
COMPONENT_ADD_INCLUDEDIRS += host/nimble/nimble/nimble/include \
|
||||||
host/nimble/nimble/nimble/host/include \
|
host/nimble/nimble/nimble/host/include \
|
||||||
host/nimble/nimble/porting/nimble/include \
|
host/nimble/nimble/porting/nimble/include \
|
||||||
|
@ -167,14 +168,16 @@ COMPONENT_ADD_INCLUDEDIRS += host/nimble/nimble/nimble/include
|
||||||
host/nimble/nimble/nimble/host/util/include \
|
host/nimble/nimble/nimble/host/util/include \
|
||||||
host/nimble/nimble/nimble/host/store/ram/include \
|
host/nimble/nimble/nimble/host/store/ram/include \
|
||||||
host/nimble/nimble/nimble/host/store/config/include \
|
host/nimble/nimble/nimble/host/store/config/include \
|
||||||
host/nimble/nimble/ext/tinycrypt/include \
|
|
||||||
host/nimble/esp-hci/include \
|
host/nimble/esp-hci/include \
|
||||||
host/nimble/port/include
|
host/nimble/port/include
|
||||||
|
|
||||||
|
ifndef CONFIG_BT_NIMBLE_CRYPTO_STACK_MBEDTLS
|
||||||
|
COMPONENT_ADD_INCLUDEDIRS += host/nimble/nimble/ext/tinycrypt/include
|
||||||
|
endif
|
||||||
|
|
||||||
COMPONENT_SRCDIRS += host/nimble/nimble/nimble/host/src \
|
COMPONENT_SRCDIRS += host/nimble/nimble/nimble/host/src \
|
||||||
host/nimble/nimble/porting/nimble/src \
|
host/nimble/nimble/porting/nimble/src \
|
||||||
host/nimble/nimble/porting/npl/freertos/src \
|
host/nimble/nimble/porting/npl/freertos/src \
|
||||||
host/nimble/nimble/ext/tinycrypt/src \
|
|
||||||
host/nimble/nimble/nimble/host/services/ans/src \
|
host/nimble/nimble/nimble/host/services/ans/src \
|
||||||
host/nimble/nimble/nimble/host/services/bas/src \
|
host/nimble/nimble/nimble/host/services/bas/src \
|
||||||
host/nimble/nimble/nimble/host/services/gap/src \
|
host/nimble/nimble/nimble/host/services/gap/src \
|
||||||
|
@ -187,6 +190,10 @@ COMPONENT_SRCDIRS += host/nimble/nimble/nimble/host/src
|
||||||
host/nimble/nimble/nimble/host/store/config/src \
|
host/nimble/nimble/nimble/host/store/config/src \
|
||||||
host/nimble/esp-hci/src
|
host/nimble/esp-hci/src
|
||||||
|
|
||||||
|
ifndef CONFIG_BT_NIMBLE_CRYPTO_STACK_MBEDTLS
|
||||||
|
COMPONENT_SRCDIRS += host/nimble/nimble/ext/tinycrypt/src
|
||||||
|
endif
|
||||||
|
|
||||||
COMPONENT_OBJEXCLUDE += host/nimble/nimble/nimble/host/store/config/src/ble_store_config_conf.o
|
COMPONENT_OBJEXCLUDE += host/nimble/nimble/nimble/host/store/config/src/ble_store_config_conf.o
|
||||||
|
|
||||||
ifdef CONFIG_BT_NIMBLE_MESH
|
ifdef CONFIG_BT_NIMBLE_MESH
|
||||||
|
|
|
@ -226,6 +226,7 @@ extern int coex_bt_release_wrapper(uint32_t event);
|
||||||
extern int coex_register_bt_cb_wrapper(coex_func_cb_t cb);
|
extern int coex_register_bt_cb_wrapper(coex_func_cb_t cb);
|
||||||
extern uint32_t coex_bb_reset_lock_wrapper(void);
|
extern uint32_t coex_bb_reset_lock_wrapper(void);
|
||||||
extern void coex_bb_reset_unlock_wrapper(uint32_t restore);
|
extern void coex_bb_reset_unlock_wrapper(uint32_t restore);
|
||||||
|
extern void coex_ble_adv_priority_high_set(bool high);
|
||||||
|
|
||||||
extern char _bss_start_btdm;
|
extern char _bss_start_btdm;
|
||||||
extern char _bss_end_btdm;
|
extern char _bss_end_btdm;
|
||||||
|
@ -1195,6 +1196,12 @@ esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg)
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_BTDM_COEX_BLE_ADV_HIGH_PRIORITY
|
||||||
|
coex_ble_adv_priority_high_set(true);
|
||||||
|
#else
|
||||||
|
coex_ble_adv_priority_high_set(false);
|
||||||
|
#endif
|
||||||
|
|
||||||
btdm_controller_status = ESP_BT_CONTROLLER_STATUS_INITED;
|
btdm_controller_status = ESP_BT_CONTROLLER_STATUS_INITED;
|
||||||
|
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit d122b080242fdf045bd5a8ba8b5879f2f9c7885e
|
Subproject commit aaadbf2c26002ae85c175cb0e469a3b0bf57bf02
|
|
@ -297,8 +297,6 @@ static void btc_ble_mesh_client_model_op_cb(struct bt_mesh_model *model,
|
||||||
struct net_buf_simple *buf)
|
struct net_buf_simple *buf)
|
||||||
{
|
{
|
||||||
esp_ble_mesh_model_cb_param_t mesh_param = {0};
|
esp_ble_mesh_model_cb_param_t mesh_param = {0};
|
||||||
bt_mesh_client_user_data_t *client_param = NULL;
|
|
||||||
bt_mesh_client_internal_data_t *data = NULL;
|
|
||||||
bt_mesh_client_node_t *node = NULL;
|
bt_mesh_client_node_t *node = NULL;
|
||||||
btc_msg_t msg = {0};
|
btc_msg_t msg = {0};
|
||||||
bt_status_t ret;
|
bt_status_t ret;
|
||||||
|
@ -308,15 +306,11 @@ static void btc_ble_mesh_client_model_op_cb(struct bt_mesh_model *model,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
client_param = (bt_mesh_client_user_data_t *)model->user_data;
|
|
||||||
data = (bt_mesh_client_internal_data_t *)client_param->internal_data;
|
|
||||||
if (!data) {
|
|
||||||
LOG_ERROR("%s, Client internal_data is NULL", __func__);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
bt_mesh_client_model_lock();
|
bt_mesh_client_model_lock();
|
||||||
|
|
||||||
|
msg.sig = BTC_SIG_API_CB;
|
||||||
|
msg.pid = BTC_PID_MODEL;
|
||||||
|
|
||||||
node = bt_mesh_is_client_recv_publish_msg(model, ctx, buf, false);
|
node = bt_mesh_is_client_recv_publish_msg(model, ctx, buf, false);
|
||||||
if (node == NULL) {
|
if (node == NULL) {
|
||||||
msg.act = ESP_BLE_MESH_CLIENT_MODEL_RECV_PUBLISH_MSG_EVT;
|
msg.act = ESP_BLE_MESH_CLIENT_MODEL_RECV_PUBLISH_MSG_EVT;
|
||||||
|
@ -325,6 +319,8 @@ static void btc_ble_mesh_client_model_op_cb(struct bt_mesh_model *model,
|
||||||
mesh_param.client_recv_publish_msg.ctx = (esp_ble_mesh_msg_ctx_t *)ctx;
|
mesh_param.client_recv_publish_msg.ctx = (esp_ble_mesh_msg_ctx_t *)ctx;
|
||||||
mesh_param.client_recv_publish_msg.length = buf->len;
|
mesh_param.client_recv_publish_msg.length = buf->len;
|
||||||
mesh_param.client_recv_publish_msg.msg = buf->data;
|
mesh_param.client_recv_publish_msg.msg = buf->data;
|
||||||
|
ret = btc_transfer_context(&msg, &mesh_param,
|
||||||
|
sizeof(esp_ble_mesh_model_cb_param_t), btc_ble_mesh_model_copy_req_data);
|
||||||
} else {
|
} else {
|
||||||
msg.act = ESP_BLE_MESH_MODEL_OPERATION_EVT;
|
msg.act = ESP_BLE_MESH_MODEL_OPERATION_EVT;
|
||||||
mesh_param.model_operation.opcode = ctx->recv_op;
|
mesh_param.model_operation.opcode = ctx->recv_op;
|
||||||
|
@ -332,19 +328,11 @@ static void btc_ble_mesh_client_model_op_cb(struct bt_mesh_model *model,
|
||||||
mesh_param.model_operation.ctx = (esp_ble_mesh_msg_ctx_t *)ctx;
|
mesh_param.model_operation.ctx = (esp_ble_mesh_msg_ctx_t *)ctx;
|
||||||
mesh_param.model_operation.length = buf->len;
|
mesh_param.model_operation.length = buf->len;
|
||||||
mesh_param.model_operation.msg = buf->data;
|
mesh_param.model_operation.msg = buf->data;
|
||||||
}
|
|
||||||
|
|
||||||
msg.sig = BTC_SIG_API_CB;
|
|
||||||
msg.pid = BTC_PID_MODEL;
|
|
||||||
if (msg.act == ESP_BLE_MESH_CLIENT_MODEL_RECV_PUBLISH_MSG_EVT) {
|
|
||||||
ret = btc_transfer_context(&msg, &mesh_param,
|
|
||||||
sizeof(esp_ble_mesh_model_cb_param_t), btc_ble_mesh_model_copy_req_data);
|
|
||||||
} else {
|
|
||||||
if (!k_delayed_work_free(&node->timer)) {
|
if (!k_delayed_work_free(&node->timer)) {
|
||||||
ret = btc_transfer_context(&msg, &mesh_param,
|
ret = btc_transfer_context(&msg, &mesh_param,
|
||||||
sizeof(esp_ble_mesh_model_cb_param_t), btc_ble_mesh_model_copy_req_data);
|
sizeof(esp_ble_mesh_model_cb_param_t), btc_ble_mesh_model_copy_req_data);
|
||||||
// Don't forget to release the node at the end.
|
// Don't forget to release the node at the end.
|
||||||
bt_mesh_client_free_node(&data->queue, node);
|
bt_mesh_client_free_node(node);
|
||||||
} else {
|
} else {
|
||||||
ret = BT_STATUS_SUCCESS;
|
ret = BT_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -603,28 +591,18 @@ static void btc_ble_mesh_prov_register_complete_cb(int err_code)
|
||||||
static void btc_ble_mesh_client_model_timeout_cb(struct k_work *work)
|
static void btc_ble_mesh_client_model_timeout_cb(struct k_work *work)
|
||||||
{
|
{
|
||||||
esp_ble_mesh_model_cb_param_t mesh_param = {0};
|
esp_ble_mesh_model_cb_param_t mesh_param = {0};
|
||||||
bt_mesh_client_user_data_t *client_param = NULL;
|
struct k_delayed_work *timer = NULL;
|
||||||
bt_mesh_client_internal_data_t *data = NULL;
|
|
||||||
bt_mesh_client_node_t *node = NULL;
|
bt_mesh_client_node_t *node = NULL;
|
||||||
btc_msg_t msg = {0};
|
btc_msg_t msg = {0};
|
||||||
bt_status_t ret;
|
bt_status_t ret;
|
||||||
|
|
||||||
node = CONTAINER_OF(work, bt_mesh_client_node_t, timer.work);
|
|
||||||
if (!node || !node->ctx.model || !node->ctx.model->user_data) {
|
|
||||||
LOG_ERROR("%s, Invalid parameter", __func__);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
client_param = (bt_mesh_client_user_data_t *)node->ctx.model->user_data;
|
|
||||||
data = (bt_mesh_client_internal_data_t *)client_param->internal_data;
|
|
||||||
if (!data) {
|
|
||||||
LOG_ERROR("%s, Client internal_data is NULL", __func__);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
bt_mesh_client_model_lock();
|
bt_mesh_client_model_lock();
|
||||||
|
|
||||||
if (!k_delayed_work_free(&node->timer)) {
|
timer = CONTAINER_OF(work, struct k_delayed_work, work);
|
||||||
|
|
||||||
|
if (timer && !k_delayed_work_free(timer)) {
|
||||||
|
node = CONTAINER_OF(work, bt_mesh_client_node_t, timer.work);
|
||||||
|
if (node) {
|
||||||
mesh_param.client_send_timeout.opcode = node->opcode;
|
mesh_param.client_send_timeout.opcode = node->opcode;
|
||||||
mesh_param.client_send_timeout.model = (esp_ble_mesh_model_t *)node->ctx.model;
|
mesh_param.client_send_timeout.model = (esp_ble_mesh_model_t *)node->ctx.model;
|
||||||
mesh_param.client_send_timeout.ctx = (esp_ble_mesh_msg_ctx_t *)&node->ctx;
|
mesh_param.client_send_timeout.ctx = (esp_ble_mesh_msg_ctx_t *)&node->ctx;
|
||||||
|
@ -640,7 +618,8 @@ static void btc_ble_mesh_client_model_timeout_cb(struct k_work *work)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Don't forget to release the node at the end.
|
// Don't forget to release the node at the end.
|
||||||
bt_mesh_client_free_node(&data->queue, node);
|
bt_mesh_client_free_node(node);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bt_mesh_client_model_unlock();
|
bt_mesh_client_model_unlock();
|
||||||
|
|
|
@ -386,8 +386,10 @@ static void bt_mesh_scan_cb(const bt_mesh_addr_t *addr, s8_t rssi,
|
||||||
void bt_mesh_adv_init(void)
|
void bt_mesh_adv_init(void)
|
||||||
{
|
{
|
||||||
xBleMeshQueue = xQueueCreate(150, sizeof(bt_mesh_msg_t));
|
xBleMeshQueue = xQueueCreate(150, sizeof(bt_mesh_msg_t));
|
||||||
xTaskCreatePinnedToCore(adv_thread, "BLE_Mesh_ADV_Task", 3072, NULL,
|
configASSERT(xBleMeshQueue);
|
||||||
|
int ret = xTaskCreatePinnedToCore(adv_thread, "BLE_Mesh_ADV_Task", 3072, NULL,
|
||||||
configMAX_PRIORITIES - 7, NULL, TASK_PINNED_TO_CORE);
|
configMAX_PRIORITIES - 7, NULL, TASK_PINNED_TO_CORE);
|
||||||
|
configASSERT(ret == pdTRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
int bt_mesh_scan_enable(void)
|
int bt_mesh_scan_enable(void)
|
||||||
|
|
|
@ -107,37 +107,23 @@ static void bt_mesh_cfg_client_unlock(void)
|
||||||
|
|
||||||
static void timeout_handler(struct k_work *work)
|
static void timeout_handler(struct k_work *work)
|
||||||
{
|
{
|
||||||
config_internal_data_t *internal = NULL;
|
struct k_delayed_work *timer = NULL;
|
||||||
bt_mesh_config_client_t *client = NULL;
|
|
||||||
bt_mesh_client_node_t *node = NULL;
|
bt_mesh_client_node_t *node = NULL;
|
||||||
|
|
||||||
BT_WARN("Receive configuration status message timeout");
|
BT_WARN("Receive configuration status message timeout");
|
||||||
|
|
||||||
node = CONTAINER_OF(work, bt_mesh_client_node_t, timer.work);
|
|
||||||
if (!node || !node->ctx.model) {
|
|
||||||
BT_ERR("%s, Invalid parameter", __func__);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
client = (bt_mesh_config_client_t *)node->ctx.model->user_data;
|
|
||||||
if (!client) {
|
|
||||||
BT_ERR("%s, Config Client user_data is NULL", __func__);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal = (config_internal_data_t *)client->internal_data;
|
|
||||||
if (!internal) {
|
|
||||||
BT_ERR("%s, Config Client internal_data is NULL", __func__);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
bt_mesh_cfg_client_lock();
|
bt_mesh_cfg_client_lock();
|
||||||
|
|
||||||
if (!k_delayed_work_free(&node->timer)) {
|
timer = CONTAINER_OF(work, struct k_delayed_work, work);
|
||||||
|
|
||||||
|
if (timer && !k_delayed_work_free(timer)) {
|
||||||
|
node = CONTAINER_OF(work, bt_mesh_client_node_t, timer.work);
|
||||||
|
if (node) {
|
||||||
bt_mesh_config_client_cb_evt_to_btc(node->opcode,
|
bt_mesh_config_client_cb_evt_to_btc(node->opcode,
|
||||||
BTC_BLE_MESH_EVT_CONFIG_CLIENT_TIMEOUT, node->ctx.model, &node->ctx, NULL, 0);
|
BTC_BLE_MESH_EVT_CONFIG_CLIENT_TIMEOUT, node->ctx.model, &node->ctx, NULL, 0);
|
||||||
// Don't forget to release the node at the end.
|
// Don't forget to release the node at the end.
|
||||||
bt_mesh_client_free_node(&internal->queue, node);
|
bt_mesh_client_free_node(node);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bt_mesh_cfg_client_unlock();
|
bt_mesh_cfg_client_unlock();
|
||||||
|
@ -149,7 +135,6 @@ static void cfg_client_cancel(struct bt_mesh_model *model,
|
||||||
struct bt_mesh_msg_ctx *ctx,
|
struct bt_mesh_msg_ctx *ctx,
|
||||||
void *status, size_t len)
|
void *status, size_t len)
|
||||||
{
|
{
|
||||||
config_internal_data_t *data = NULL;
|
|
||||||
bt_mesh_client_node_t *node = NULL;
|
bt_mesh_client_node_t *node = NULL;
|
||||||
struct net_buf_simple buf = {0};
|
struct net_buf_simple buf = {0};
|
||||||
u8_t evt_type = 0xFF;
|
u8_t evt_type = 0xFF;
|
||||||
|
@ -159,12 +144,6 @@ static void cfg_client_cancel(struct bt_mesh_model *model,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
data = (config_internal_data_t *)cli->internal_data;
|
|
||||||
if (!data) {
|
|
||||||
BT_ERR("%s, Config Client internal_data is NULL", __func__);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If it is a publish message, sent to the user directly. */
|
/* If it is a publish message, sent to the user directly. */
|
||||||
buf.data = (u8_t *)status;
|
buf.data = (u8_t *)status;
|
||||||
buf.len = (u16_t)len;
|
buf.len = (u16_t)len;
|
||||||
|
@ -235,7 +214,7 @@ static void cfg_client_cancel(struct bt_mesh_model *model,
|
||||||
bt_mesh_config_client_cb_evt_to_btc(
|
bt_mesh_config_client_cb_evt_to_btc(
|
||||||
node->opcode, evt_type, model, ctx, (const u8_t *)status, len);
|
node->opcode, evt_type, model, ctx, (const u8_t *)status, len);
|
||||||
// Don't forget to release the node at the end.
|
// Don't forget to release the node at the end.
|
||||||
bt_mesh_client_free_node(&data->queue, node);
|
bt_mesh_client_free_node(node);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -63,37 +63,23 @@ static void bt_mesh_health_client_unlock(void)
|
||||||
|
|
||||||
static void timeout_handler(struct k_work *work)
|
static void timeout_handler(struct k_work *work)
|
||||||
{
|
{
|
||||||
health_internal_data_t *internal = NULL;
|
struct k_delayed_work *timer = NULL;
|
||||||
bt_mesh_health_client_t *client = NULL;
|
|
||||||
bt_mesh_client_node_t *node = NULL;
|
bt_mesh_client_node_t *node = NULL;
|
||||||
|
|
||||||
BT_WARN("Receive health status message timeout");
|
BT_WARN("Receive health status message timeout");
|
||||||
|
|
||||||
node = CONTAINER_OF(work, bt_mesh_client_node_t, timer.work);
|
|
||||||
if (!node || !node->ctx.model) {
|
|
||||||
BT_ERR("%s, Invalid parameter", __func__);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
client = (bt_mesh_health_client_t *)node->ctx.model->user_data;
|
|
||||||
if (!client) {
|
|
||||||
BT_ERR("%s, Health Client user_data is NULL", __func__);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal = (health_internal_data_t *)client->internal_data;
|
|
||||||
if (!internal) {
|
|
||||||
BT_ERR("%s, Health Client internal_data is NULL", __func__);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
bt_mesh_health_client_lock();
|
bt_mesh_health_client_lock();
|
||||||
|
|
||||||
if (!k_delayed_work_free(&node->timer)) {
|
timer = CONTAINER_OF(work, struct k_delayed_work, work);
|
||||||
|
|
||||||
|
if (timer && !k_delayed_work_free(timer)) {
|
||||||
|
node = CONTAINER_OF(work, bt_mesh_client_node_t, timer.work);
|
||||||
|
if (node) {
|
||||||
bt_mesh_health_client_cb_evt_to_btc(node->opcode,
|
bt_mesh_health_client_cb_evt_to_btc(node->opcode,
|
||||||
BTC_BLE_MESH_EVT_HEALTH_CLIENT_TIMEOUT, node->ctx.model, &node->ctx, NULL, 0);
|
BTC_BLE_MESH_EVT_HEALTH_CLIENT_TIMEOUT, node->ctx.model, &node->ctx, NULL, 0);
|
||||||
// Don't forget to release the node at the end.
|
// Don't forget to release the node at the end.
|
||||||
bt_mesh_client_free_node(&internal->queue, node);
|
bt_mesh_client_free_node(node);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bt_mesh_health_client_unlock();
|
bt_mesh_health_client_unlock();
|
||||||
|
@ -105,7 +91,6 @@ static void health_client_cancel(struct bt_mesh_model *model,
|
||||||
struct bt_mesh_msg_ctx *ctx,
|
struct bt_mesh_msg_ctx *ctx,
|
||||||
void *status, size_t len)
|
void *status, size_t len)
|
||||||
{
|
{
|
||||||
health_internal_data_t *data = NULL;
|
|
||||||
bt_mesh_client_node_t *node = NULL;
|
bt_mesh_client_node_t *node = NULL;
|
||||||
struct net_buf_simple buf = {0};
|
struct net_buf_simple buf = {0};
|
||||||
u8_t evt_type = 0xFF;
|
u8_t evt_type = 0xFF;
|
||||||
|
@ -115,12 +100,6 @@ static void health_client_cancel(struct bt_mesh_model *model,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
data = (health_internal_data_t *)health_cli->internal_data;
|
|
||||||
if (!data) {
|
|
||||||
BT_ERR("%s, Health Client internal_data is NULL", __func__);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If it is a publish message, sent to the user directly. */
|
/* If it is a publish message, sent to the user directly. */
|
||||||
buf.data = (u8_t *)status;
|
buf.data = (u8_t *)status;
|
||||||
buf.len = (u16_t)len;
|
buf.len = (u16_t)len;
|
||||||
|
@ -151,7 +130,7 @@ static void health_client_cancel(struct bt_mesh_model *model,
|
||||||
bt_mesh_health_client_cb_evt_to_btc(
|
bt_mesh_health_client_cb_evt_to_btc(
|
||||||
node->opcode, evt_type, model, ctx, (const u8_t *)status, len);
|
node->opcode, evt_type, model, ctx, (const u8_t *)status, len);
|
||||||
// Don't forget to release the node at the end.
|
// Don't forget to release the node at the end.
|
||||||
bt_mesh_client_free_node(&data->queue, node);
|
bt_mesh_client_free_node(node);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -103,7 +103,7 @@ void k_delayed_work_init(struct k_delayed_work *work, k_work_handler_t handler)
|
||||||
|
|
||||||
osi_mutex_lock(&bm_alarm_lock, OSI_MUTEX_MAX_TIMEOUT);
|
osi_mutex_lock(&bm_alarm_lock, OSI_MUTEX_MAX_TIMEOUT);
|
||||||
if (!hash_map_has_key(bm_alarm_hash_map, (void *)work)) {
|
if (!hash_map_has_key(bm_alarm_hash_map, (void *)work)) {
|
||||||
alarm = osi_alarm_new("bt_mesh", (osi_alarm_callback_t)handler, (void *)work, 0);
|
alarm = osi_alarm_new("bt_mesh", (osi_alarm_callback_t)handler, (void *)&work->work, 0);
|
||||||
if (alarm == NULL) {
|
if (alarm == NULL) {
|
||||||
BT_ERR("%s, Unable to create alarm", __func__);
|
BT_ERR("%s, Unable to create alarm", __func__);
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -284,15 +284,30 @@ int bt_mesh_client_init(struct bt_mesh_model *model)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int bt_mesh_client_free_node(sys_slist_t *queue, bt_mesh_client_node_t *node)
|
int bt_mesh_client_free_node(bt_mesh_client_node_t *node)
|
||||||
{
|
{
|
||||||
if (!queue || !node) {
|
bt_mesh_client_internal_data_t *internal = NULL;
|
||||||
BT_ERR("%s, Invalid parameter", __func__);
|
bt_mesh_client_user_data_t *client = NULL;
|
||||||
|
|
||||||
|
if (!node || !node->ctx.model) {
|
||||||
|
BT_ERR("%s, Client model list item is NULL", __func__);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
client = (bt_mesh_client_user_data_t *)node->ctx.model->user_data;
|
||||||
|
if (!client) {
|
||||||
|
BT_ERR("%s, Client model user data is NULL", __func__);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal = (bt_mesh_client_internal_data_t *)client->internal_data;
|
||||||
|
if (!internal) {
|
||||||
|
BT_ERR("%s, Client model internal data is NULL", __func__);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Release the client node from the queue
|
// Release the client node from the queue
|
||||||
sys_slist_find_and_remove(queue, &node->client_node);
|
sys_slist_find_and_remove(&internal->queue, &node->client_node);
|
||||||
// Free the node
|
// Free the node
|
||||||
osi_free(node);
|
osi_free(node);
|
||||||
|
|
||||||
|
|
|
@ -144,37 +144,23 @@ static void bt_mesh_generic_client_unlock(void)
|
||||||
|
|
||||||
static void timeout_handler(struct k_work *work)
|
static void timeout_handler(struct k_work *work)
|
||||||
{
|
{
|
||||||
generic_internal_data_t *internal = NULL;
|
struct k_delayed_work *timer = NULL;
|
||||||
bt_mesh_generic_client_t *client = NULL;
|
|
||||||
bt_mesh_client_node_t *node = NULL;
|
bt_mesh_client_node_t *node = NULL;
|
||||||
|
|
||||||
BT_WARN("Receive generic status message timeout");
|
BT_WARN("Receive generic status message timeout");
|
||||||
|
|
||||||
node = CONTAINER_OF(work, bt_mesh_client_node_t, timer.work);
|
|
||||||
if (!node || !node->ctx.model) {
|
|
||||||
BT_ERR("%s, Invalid parameter", __func__);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
client = (bt_mesh_generic_client_t *)node->ctx.model->user_data;
|
|
||||||
if (!client) {
|
|
||||||
BT_ERR("%s, Generic Client user_data is NULL", __func__);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal = (generic_internal_data_t *)client->internal_data;
|
|
||||||
if (!internal) {
|
|
||||||
BT_ERR("%s, Generic Client internal_data is NULL", __func__);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
bt_mesh_generic_client_lock();
|
bt_mesh_generic_client_lock();
|
||||||
|
|
||||||
if (!k_delayed_work_free(&node->timer)) {
|
timer = CONTAINER_OF(work, struct k_delayed_work, work);
|
||||||
|
|
||||||
|
if (timer && !k_delayed_work_free(timer)) {
|
||||||
|
node = CONTAINER_OF(work, bt_mesh_client_node_t, timer.work);
|
||||||
|
if (node) {
|
||||||
bt_mesh_generic_client_cb_evt_to_btc(node->opcode,
|
bt_mesh_generic_client_cb_evt_to_btc(node->opcode,
|
||||||
BTC_BLE_MESH_EVT_GENERIC_CLIENT_TIMEOUT, node->ctx.model, &node->ctx, NULL, 0);
|
BTC_BLE_MESH_EVT_GENERIC_CLIENT_TIMEOUT, node->ctx.model, &node->ctx, NULL, 0);
|
||||||
// Don't forget to release the node at the end.
|
// Don't forget to release the node at the end.
|
||||||
bt_mesh_client_free_node(&internal->queue, node);
|
bt_mesh_client_free_node(node);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bt_mesh_generic_client_unlock();
|
bt_mesh_generic_client_unlock();
|
||||||
|
@ -186,31 +172,14 @@ static void generic_status(struct bt_mesh_model *model,
|
||||||
struct bt_mesh_msg_ctx *ctx,
|
struct bt_mesh_msg_ctx *ctx,
|
||||||
struct net_buf_simple *buf)
|
struct net_buf_simple *buf)
|
||||||
{
|
{
|
||||||
generic_internal_data_t *internal = NULL;
|
|
||||||
bt_mesh_generic_client_t *client = NULL;
|
|
||||||
bt_mesh_client_node_t *node = NULL;
|
bt_mesh_client_node_t *node = NULL;
|
||||||
u8_t *val = NULL;
|
u8_t *val = NULL;
|
||||||
u8_t evt = 0xFF;
|
u8_t evt = 0xFF;
|
||||||
u32_t rsp = 0;
|
|
||||||
size_t len = 0;
|
size_t len = 0;
|
||||||
|
|
||||||
BT_DBG("%s, len %d, bytes %s", __func__, buf->len, bt_hex(buf->data, buf->len));
|
BT_DBG("%s, len %d, bytes %s", __func__, buf->len, bt_hex(buf->data, buf->len));
|
||||||
|
|
||||||
client = (bt_mesh_generic_client_t *)model->user_data;
|
switch (ctx->recv_op) {
|
||||||
if (!client) {
|
|
||||||
BT_ERR("%s, Generic Client user_data is NULL", __func__);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal = (generic_internal_data_t *)client->internal_data;
|
|
||||||
if (!internal) {
|
|
||||||
BT_ERR("%s, Generic Client internal_data is NULL", __func__);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
rsp = ctx->recv_op;
|
|
||||||
|
|
||||||
switch (rsp) {
|
|
||||||
case BLE_MESH_MODEL_OP_GEN_ONOFF_STATUS: {
|
case BLE_MESH_MODEL_OP_GEN_ONOFF_STATUS: {
|
||||||
struct bt_mesh_gen_onoff_status *status = NULL;
|
struct bt_mesh_gen_onoff_status *status = NULL;
|
||||||
if (buf->len != 1 && buf->len != 3) {
|
if (buf->len != 1 && buf->len != 3) {
|
||||||
|
@ -569,7 +538,7 @@ static void generic_status(struct bt_mesh_model *model,
|
||||||
|
|
||||||
node = bt_mesh_is_client_recv_publish_msg(model, ctx, buf, true);
|
node = bt_mesh_is_client_recv_publish_msg(model, ctx, buf, true);
|
||||||
if (!node) {
|
if (!node) {
|
||||||
BT_DBG("Unexpected generic status message 0x%x", rsp);
|
BT_DBG("Unexpected generic status message 0x%x", ctx->recv_op);
|
||||||
} else {
|
} else {
|
||||||
switch (node->opcode) {
|
switch (node->opcode) {
|
||||||
case BLE_MESH_MODEL_OP_GEN_ONOFF_GET:
|
case BLE_MESH_MODEL_OP_GEN_ONOFF_GET:
|
||||||
|
@ -615,13 +584,13 @@ static void generic_status(struct bt_mesh_model *model,
|
||||||
if (!k_delayed_work_free(&node->timer)) {
|
if (!k_delayed_work_free(&node->timer)) {
|
||||||
bt_mesh_generic_client_cb_evt_to_btc(node->opcode, evt, model, ctx, val, len);
|
bt_mesh_generic_client_cb_evt_to_btc(node->opcode, evt, model, ctx, val, len);
|
||||||
// Don't forget to release the node at the end.
|
// Don't forget to release the node at the end.
|
||||||
bt_mesh_client_free_node(&internal->queue, node);
|
bt_mesh_client_free_node(node);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bt_mesh_generic_client_unlock();
|
bt_mesh_generic_client_unlock();
|
||||||
|
|
||||||
switch (rsp) {
|
switch (ctx->recv_op) {
|
||||||
case BLE_MESH_MODEL_OP_GEN_USER_PROPERTIES_STATUS: {
|
case BLE_MESH_MODEL_OP_GEN_USER_PROPERTIES_STATUS: {
|
||||||
struct bt_mesh_gen_user_properties_status *status;
|
struct bt_mesh_gen_user_properties_status *status;
|
||||||
status = (struct bt_mesh_gen_user_properties_status *)val;
|
status = (struct bt_mesh_gen_user_properties_status *)val;
|
||||||
|
|
|
@ -112,7 +112,7 @@ int bt_mesh_client_send_msg(struct bt_mesh_model *model,
|
||||||
s32_t timeout, bool need_ack,
|
s32_t timeout, bool need_ack,
|
||||||
const struct bt_mesh_send_cb *cb, void *cb_data);
|
const struct bt_mesh_send_cb *cb, void *cb_data);
|
||||||
|
|
||||||
int bt_mesh_client_free_node(sys_slist_t *queue, bt_mesh_client_node_t *node);
|
int bt_mesh_client_free_node(bt_mesh_client_node_t *node);
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
NODE = 0,
|
NODE = 0,
|
||||||
|
|
|
@ -153,37 +153,23 @@ static void bt_mesh_light_client_unlock(void)
|
||||||
|
|
||||||
static void timeout_handler(struct k_work *work)
|
static void timeout_handler(struct k_work *work)
|
||||||
{
|
{
|
||||||
light_internal_data_t *internal = NULL;
|
struct k_delayed_work *timer = NULL;
|
||||||
bt_mesh_light_client_t *client = NULL;
|
|
||||||
bt_mesh_client_node_t *node = NULL;
|
bt_mesh_client_node_t *node = NULL;
|
||||||
|
|
||||||
BT_WARN("Receive light status message timeout");
|
BT_WARN("Receive light status message timeout");
|
||||||
|
|
||||||
node = CONTAINER_OF(work, bt_mesh_client_node_t, timer.work);
|
|
||||||
if (!node || !node->ctx.model) {
|
|
||||||
BT_ERR("%s, Invalid parameter", __func__);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
client = (bt_mesh_light_client_t *)node->ctx.model->user_data;
|
|
||||||
if (!client) {
|
|
||||||
BT_ERR("%s, Lighting Client user_data is NULL", __func__);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal = (light_internal_data_t *)client->internal_data;
|
|
||||||
if (!internal) {
|
|
||||||
BT_ERR("%s, Lighting Client internal_data is NULL", __func__);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
bt_mesh_light_client_lock();
|
bt_mesh_light_client_lock();
|
||||||
|
|
||||||
if (!k_delayed_work_free(&node->timer)) {
|
timer = CONTAINER_OF(work, struct k_delayed_work, work);
|
||||||
|
|
||||||
|
if (timer && !k_delayed_work_free(timer)) {
|
||||||
|
node = CONTAINER_OF(work, bt_mesh_client_node_t, timer.work);
|
||||||
|
if (node) {
|
||||||
bt_mesh_lighting_client_cb_evt_to_btc(node->opcode,
|
bt_mesh_lighting_client_cb_evt_to_btc(node->opcode,
|
||||||
BTC_BLE_MESH_EVT_LIGHTING_CLIENT_TIMEOUT, node->ctx.model, &node->ctx, NULL, 0);
|
BTC_BLE_MESH_EVT_LIGHTING_CLIENT_TIMEOUT, node->ctx.model, &node->ctx, NULL, 0);
|
||||||
// Don't forget to release the node at the end.
|
// Don't forget to release the node at the end.
|
||||||
bt_mesh_client_free_node(&internal->queue, node);
|
bt_mesh_client_free_node(node);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bt_mesh_light_client_unlock();
|
bt_mesh_light_client_unlock();
|
||||||
|
@ -195,31 +181,14 @@ static void light_status(struct bt_mesh_model *model,
|
||||||
struct bt_mesh_msg_ctx *ctx,
|
struct bt_mesh_msg_ctx *ctx,
|
||||||
struct net_buf_simple *buf)
|
struct net_buf_simple *buf)
|
||||||
{
|
{
|
||||||
light_internal_data_t *internal = NULL;
|
|
||||||
bt_mesh_light_client_t *client = NULL;
|
|
||||||
bt_mesh_client_node_t *node = NULL;
|
bt_mesh_client_node_t *node = NULL;
|
||||||
u8_t *val = NULL;
|
u8_t *val = NULL;
|
||||||
u8_t evt = 0xFF;
|
u8_t evt = 0xFF;
|
||||||
u32_t rsp = 0;
|
|
||||||
size_t len = 0;
|
size_t len = 0;
|
||||||
|
|
||||||
BT_DBG("%s, len %d, bytes %s", __func__, buf->len, bt_hex(buf->data, buf->len));
|
BT_DBG("%s, len %d, bytes %s", __func__, buf->len, bt_hex(buf->data, buf->len));
|
||||||
|
|
||||||
client = (bt_mesh_light_client_t *)model->user_data;
|
switch (ctx->recv_op) {
|
||||||
if (!client) {
|
|
||||||
BT_ERR("%s, Lighting Client user_data is NULL", __func__);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal = (light_internal_data_t *)client->internal_data;
|
|
||||||
if (!internal) {
|
|
||||||
BT_ERR("%s, Lighting Client internal_data is NULL", __func__);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
rsp = ctx->recv_op;
|
|
||||||
|
|
||||||
switch (rsp) {
|
|
||||||
case BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_STATUS: {
|
case BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_STATUS: {
|
||||||
struct bt_mesh_light_lightness_status *status = NULL;
|
struct bt_mesh_light_lightness_status *status = NULL;
|
||||||
if (buf->len != 2 && buf->len != 5) {
|
if (buf->len != 2 && buf->len != 5) {
|
||||||
|
@ -684,7 +653,7 @@ static void light_status(struct bt_mesh_model *model,
|
||||||
|
|
||||||
node = bt_mesh_is_client_recv_publish_msg(model, ctx, buf, true);
|
node = bt_mesh_is_client_recv_publish_msg(model, ctx, buf, true);
|
||||||
if (!node) {
|
if (!node) {
|
||||||
BT_DBG("Unexpected light status message 0x%x", rsp);
|
BT_DBG("Unexpected light status message 0x%x", ctx->recv_op);
|
||||||
} else {
|
} else {
|
||||||
switch (node->opcode) {
|
switch (node->opcode) {
|
||||||
case BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_GET:
|
case BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_GET:
|
||||||
|
@ -741,13 +710,13 @@ static void light_status(struct bt_mesh_model *model,
|
||||||
if (!k_delayed_work_free(&node->timer)) {
|
if (!k_delayed_work_free(&node->timer)) {
|
||||||
bt_mesh_lighting_client_cb_evt_to_btc(node->opcode, evt, model, ctx, val, len);
|
bt_mesh_lighting_client_cb_evt_to_btc(node->opcode, evt, model, ctx, val, len);
|
||||||
// Don't forget to release the node at the end.
|
// Don't forget to release the node at the end.
|
||||||
bt_mesh_client_free_node(&internal->queue, node);
|
bt_mesh_client_free_node(node);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bt_mesh_light_client_unlock();
|
bt_mesh_light_client_unlock();
|
||||||
|
|
||||||
switch (rsp) {
|
switch (ctx->recv_op) {
|
||||||
case BLE_MESH_MODEL_OP_LIGHT_LC_PROPERTY_STATUS: {
|
case BLE_MESH_MODEL_OP_LIGHT_LC_PROPERTY_STATUS: {
|
||||||
struct bt_mesh_light_lc_property_status *status;
|
struct bt_mesh_light_lc_property_status *status;
|
||||||
status = (struct bt_mesh_light_lc_property_status *)val;
|
status = (struct bt_mesh_light_lc_property_status *)val;
|
||||||
|
|
|
@ -82,37 +82,23 @@ static void bt_mesh_sensor_client_unlock(void)
|
||||||
|
|
||||||
static void timeout_handler(struct k_work *work)
|
static void timeout_handler(struct k_work *work)
|
||||||
{
|
{
|
||||||
sensor_internal_data_t *internal = NULL;
|
struct k_delayed_work *timer = NULL;
|
||||||
bt_mesh_sensor_client_t *client = NULL;
|
|
||||||
bt_mesh_client_node_t *node = NULL;
|
bt_mesh_client_node_t *node = NULL;
|
||||||
|
|
||||||
BT_WARN("Receive sensor status message timeout");
|
BT_WARN("Receive sensor status message timeout");
|
||||||
|
|
||||||
node = CONTAINER_OF(work, bt_mesh_client_node_t, timer.work);
|
|
||||||
if (!node || !node->ctx.model) {
|
|
||||||
BT_ERR("%s, Invalid parameter", __func__);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
client = (bt_mesh_sensor_client_t *)node->ctx.model->user_data;
|
|
||||||
if (!client) {
|
|
||||||
BT_ERR("%s, Sensor Client user_data is NULL", __func__);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal = (sensor_internal_data_t *)client->internal_data;
|
|
||||||
if (!internal) {
|
|
||||||
BT_ERR("%s, Sensor Client internal_data is NULL", __func__);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
bt_mesh_sensor_client_lock();
|
bt_mesh_sensor_client_lock();
|
||||||
|
|
||||||
if (!k_delayed_work_free(&node->timer)) {
|
timer = CONTAINER_OF(work, struct k_delayed_work, work);
|
||||||
|
|
||||||
|
if (timer && !k_delayed_work_free(timer)) {
|
||||||
|
node = CONTAINER_OF(work, bt_mesh_client_node_t, timer.work);
|
||||||
|
if (node) {
|
||||||
bt_mesh_sensor_client_cb_evt_to_btc(node->opcode,
|
bt_mesh_sensor_client_cb_evt_to_btc(node->opcode,
|
||||||
BTC_BLE_MESH_EVT_SENSOR_CLIENT_TIMEOUT, node->ctx.model, &node->ctx, NULL, 0);
|
BTC_BLE_MESH_EVT_SENSOR_CLIENT_TIMEOUT, node->ctx.model, &node->ctx, NULL, 0);
|
||||||
// Don't forget to release the node at the end.
|
// Don't forget to release the node at the end.
|
||||||
bt_mesh_client_free_node(&internal->queue, node);
|
bt_mesh_client_free_node(node);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bt_mesh_sensor_client_unlock();
|
bt_mesh_sensor_client_unlock();
|
||||||
|
@ -124,30 +110,14 @@ static void sensor_status(struct bt_mesh_model *model,
|
||||||
struct bt_mesh_msg_ctx *ctx,
|
struct bt_mesh_msg_ctx *ctx,
|
||||||
struct net_buf_simple *buf)
|
struct net_buf_simple *buf)
|
||||||
{
|
{
|
||||||
sensor_internal_data_t *internal = NULL;
|
|
||||||
bt_mesh_sensor_client_t *client = NULL;
|
|
||||||
bt_mesh_client_node_t *node = NULL;
|
bt_mesh_client_node_t *node = NULL;
|
||||||
u8_t *val = NULL;
|
u8_t *val = NULL;
|
||||||
u8_t evt = 0xFF;
|
u8_t evt = 0xFF;
|
||||||
u32_t rsp = 0;
|
|
||||||
size_t len = 0;
|
size_t len = 0;
|
||||||
|
|
||||||
BT_DBG("%s, len %d, bytes %s", __func__, buf->len, bt_hex(buf->data, buf->len));
|
BT_DBG("%s, len %d, bytes %s", __func__, buf->len, bt_hex(buf->data, buf->len));
|
||||||
|
|
||||||
client = (bt_mesh_sensor_client_t *)model->user_data;
|
switch (ctx->recv_op) {
|
||||||
if (!client) {
|
|
||||||
BT_ERR("%s, Sensor Client user_data is NULL", __func__);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal = (sensor_internal_data_t *)client->internal_data;
|
|
||||||
if (!internal) {
|
|
||||||
BT_ERR("%s, Sensor Client internal_data is NULL", __func__);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
rsp = ctx->recv_op;
|
|
||||||
switch (rsp) {
|
|
||||||
case BLE_MESH_MODEL_OP_SENSOR_DESCRIPTOR_STATUS: {
|
case BLE_MESH_MODEL_OP_SENSOR_DESCRIPTOR_STATUS: {
|
||||||
struct bt_mesh_sensor_descriptor_status *status = NULL;
|
struct bt_mesh_sensor_descriptor_status *status = NULL;
|
||||||
status = osi_calloc(sizeof(struct bt_mesh_sensor_descriptor_status));
|
status = osi_calloc(sizeof(struct bt_mesh_sensor_descriptor_status));
|
||||||
|
@ -296,7 +266,7 @@ static void sensor_status(struct bt_mesh_model *model,
|
||||||
|
|
||||||
node = bt_mesh_is_client_recv_publish_msg(model, ctx, buf, true);
|
node = bt_mesh_is_client_recv_publish_msg(model, ctx, buf, true);
|
||||||
if (!node) {
|
if (!node) {
|
||||||
BT_DBG("Unexpected sensor status message 0x%x", rsp);
|
BT_DBG("Unexpected sensor status message 0x%x", ctx->recv_op);
|
||||||
} else {
|
} else {
|
||||||
switch (node->opcode) {
|
switch (node->opcode) {
|
||||||
case BLE_MESH_MODEL_OP_SENSOR_DESCRIPTOR_GET:
|
case BLE_MESH_MODEL_OP_SENSOR_DESCRIPTOR_GET:
|
||||||
|
@ -319,13 +289,13 @@ static void sensor_status(struct bt_mesh_model *model,
|
||||||
if (!k_delayed_work_free(&node->timer)) {
|
if (!k_delayed_work_free(&node->timer)) {
|
||||||
bt_mesh_sensor_client_cb_evt_to_btc(node->opcode, evt, model, ctx, val, len);
|
bt_mesh_sensor_client_cb_evt_to_btc(node->opcode, evt, model, ctx, val, len);
|
||||||
// Don't forget to release the node at the end.
|
// Don't forget to release the node at the end.
|
||||||
bt_mesh_client_free_node(&internal->queue, node);
|
bt_mesh_client_free_node(node);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bt_mesh_sensor_client_unlock();
|
bt_mesh_sensor_client_unlock();
|
||||||
|
|
||||||
switch (rsp) {
|
switch (ctx->recv_op) {
|
||||||
case BLE_MESH_MODEL_OP_SENSOR_DESCRIPTOR_STATUS: {
|
case BLE_MESH_MODEL_OP_SENSOR_DESCRIPTOR_STATUS: {
|
||||||
struct bt_mesh_sensor_descriptor_status *status;
|
struct bt_mesh_sensor_descriptor_status *status;
|
||||||
status = (struct bt_mesh_sensor_descriptor_status *)val;
|
status = (struct bt_mesh_sensor_descriptor_status *)val;
|
||||||
|
|
|
@ -98,37 +98,23 @@ static void bt_mesh_time_scene_client_unlock(void)
|
||||||
|
|
||||||
static void timeout_handler(struct k_work *work)
|
static void timeout_handler(struct k_work *work)
|
||||||
{
|
{
|
||||||
time_scene_internal_data_t *internal = NULL;
|
struct k_delayed_work *timer = NULL;
|
||||||
bt_mesh_time_scene_client_t *client = NULL;
|
|
||||||
bt_mesh_client_node_t *node = NULL;
|
bt_mesh_client_node_t *node = NULL;
|
||||||
|
|
||||||
BT_WARN("Receive time scene status message timeout");
|
BT_WARN("Receive time scene status message timeout");
|
||||||
|
|
||||||
node = CONTAINER_OF(work, bt_mesh_client_node_t, timer.work);
|
|
||||||
if (!node || !node->ctx.model) {
|
|
||||||
BT_ERR("%s, Invalid parameter", __func__);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
client = (bt_mesh_time_scene_client_t *)node->ctx.model->user_data;
|
|
||||||
if (!client) {
|
|
||||||
BT_ERR("%s, Time Scene Client user_data is NULL", __func__);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal = (time_scene_internal_data_t *)client->internal_data;
|
|
||||||
if (!internal) {
|
|
||||||
BT_ERR("%s, Time Scene Client internal_data is NULL", __func__);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
bt_mesh_time_scene_client_lock();
|
bt_mesh_time_scene_client_lock();
|
||||||
|
|
||||||
if (!k_delayed_work_free(&node->timer)) {
|
timer = CONTAINER_OF(work, struct k_delayed_work, work);
|
||||||
|
|
||||||
|
if (timer && !k_delayed_work_free(timer)) {
|
||||||
|
node = CONTAINER_OF(work, bt_mesh_client_node_t, timer.work);
|
||||||
|
if (node) {
|
||||||
bt_mesh_time_scene_client_cb_evt_to_btc(node->opcode,
|
bt_mesh_time_scene_client_cb_evt_to_btc(node->opcode,
|
||||||
BTC_BLE_MESH_EVT_TIME_SCENE_CLIENT_TIMEOUT, node->ctx.model, &node->ctx, NULL, 0);
|
BTC_BLE_MESH_EVT_TIME_SCENE_CLIENT_TIMEOUT, node->ctx.model, &node->ctx, NULL, 0);
|
||||||
// Don't forget to release the node at the end.
|
// Don't forget to release the node at the end.
|
||||||
bt_mesh_client_free_node(&internal->queue, node);
|
bt_mesh_client_free_node(node);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bt_mesh_time_scene_client_unlock();
|
bt_mesh_time_scene_client_unlock();
|
||||||
|
@ -140,30 +126,14 @@ static void time_scene_status(struct bt_mesh_model *model,
|
||||||
struct bt_mesh_msg_ctx *ctx,
|
struct bt_mesh_msg_ctx *ctx,
|
||||||
struct net_buf_simple *buf)
|
struct net_buf_simple *buf)
|
||||||
{
|
{
|
||||||
time_scene_internal_data_t *internal = NULL;
|
|
||||||
bt_mesh_time_scene_client_t *client = NULL;
|
|
||||||
bt_mesh_client_node_t *node = NULL;
|
bt_mesh_client_node_t *node = NULL;
|
||||||
u8_t *val = NULL;
|
u8_t *val = NULL;
|
||||||
u8_t evt = 0xFF;
|
u8_t evt = 0xFF;
|
||||||
u32_t rsp = 0;
|
|
||||||
size_t len = 0;
|
size_t len = 0;
|
||||||
|
|
||||||
BT_DBG("%s, len %d, bytes %s", __func__, buf->len, bt_hex(buf->data, buf->len));
|
BT_DBG("%s, len %d, bytes %s", __func__, buf->len, bt_hex(buf->data, buf->len));
|
||||||
|
|
||||||
client = (bt_mesh_time_scene_client_t *)model->user_data;
|
switch (ctx->recv_op) {
|
||||||
if (!client) {
|
|
||||||
BT_ERR("%s, Time Scene Client user_data is NULL", __func__);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal = (time_scene_internal_data_t *)client->internal_data;
|
|
||||||
if (!internal) {
|
|
||||||
BT_ERR("%s, Time Scene Client internal_data is NULL", __func__);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
rsp = ctx->recv_op;
|
|
||||||
switch (rsp) {
|
|
||||||
case BLE_MESH_MODEL_OP_TIME_STATUS: {
|
case BLE_MESH_MODEL_OP_TIME_STATUS: {
|
||||||
struct bt_mesh_time_status *status = NULL;
|
struct bt_mesh_time_status *status = NULL;
|
||||||
if (buf->len != 5 && buf->len != 10) {
|
if (buf->len != 5 && buf->len != 10) {
|
||||||
|
@ -333,7 +303,7 @@ static void time_scene_status(struct bt_mesh_model *model,
|
||||||
|
|
||||||
node = bt_mesh_is_client_recv_publish_msg(model, ctx, buf, true);
|
node = bt_mesh_is_client_recv_publish_msg(model, ctx, buf, true);
|
||||||
if (!node) {
|
if (!node) {
|
||||||
BT_DBG("Unexpected time scene status message 0x%x", rsp);
|
BT_DBG("Unexpected time scene status message 0x%x", ctx->recv_op);
|
||||||
} else {
|
} else {
|
||||||
switch (node->opcode) {
|
switch (node->opcode) {
|
||||||
case BLE_MESH_MODEL_OP_TIME_GET:
|
case BLE_MESH_MODEL_OP_TIME_GET:
|
||||||
|
@ -363,13 +333,13 @@ static void time_scene_status(struct bt_mesh_model *model,
|
||||||
if (!k_delayed_work_free(&node->timer)) {
|
if (!k_delayed_work_free(&node->timer)) {
|
||||||
bt_mesh_time_scene_client_cb_evt_to_btc(node->opcode, evt, model, ctx, val, len);
|
bt_mesh_time_scene_client_cb_evt_to_btc(node->opcode, evt, model, ctx, val, len);
|
||||||
// Don't forget to release the node at the end.
|
// Don't forget to release the node at the end.
|
||||||
bt_mesh_client_free_node(&internal->queue, node);
|
bt_mesh_client_free_node(node);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bt_mesh_time_scene_client_unlock();
|
bt_mesh_time_scene_client_unlock();
|
||||||
|
|
||||||
switch (rsp) {
|
switch (ctx->recv_op) {
|
||||||
case BLE_MESH_MODEL_OP_SCENE_REGISTER_STATUS: {
|
case BLE_MESH_MODEL_OP_SCENE_REGISTER_STATUS: {
|
||||||
struct bt_mesh_scene_register_status *status;
|
struct bt_mesh_scene_register_status *status;
|
||||||
status = (struct bt_mesh_scene_register_status *)val;
|
status = (struct bt_mesh_scene_register_status *)val;
|
||||||
|
|
|
@ -267,14 +267,25 @@ typedef enum {
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
ESP_BLE_SM_PASSKEY = 0,
|
ESP_BLE_SM_PASSKEY = 0,
|
||||||
|
/* Authentication requirements of local device */
|
||||||
ESP_BLE_SM_AUTHEN_REQ_MODE,
|
ESP_BLE_SM_AUTHEN_REQ_MODE,
|
||||||
|
/* The IO capability of local device */
|
||||||
ESP_BLE_SM_IOCAP_MODE,
|
ESP_BLE_SM_IOCAP_MODE,
|
||||||
|
/* Initiator Key Distribution/Generation */
|
||||||
ESP_BLE_SM_SET_INIT_KEY,
|
ESP_BLE_SM_SET_INIT_KEY,
|
||||||
|
/* Responder Key Distribution/Generation */
|
||||||
ESP_BLE_SM_SET_RSP_KEY,
|
ESP_BLE_SM_SET_RSP_KEY,
|
||||||
|
/* Maximum Encryption key size to support */
|
||||||
ESP_BLE_SM_MAX_KEY_SIZE,
|
ESP_BLE_SM_MAX_KEY_SIZE,
|
||||||
|
/* Minimum Encryption key size requirement from Peer */
|
||||||
|
ESP_BLE_SM_MIN_KEY_SIZE,
|
||||||
|
/* Set static Passkey */
|
||||||
ESP_BLE_SM_SET_STATIC_PASSKEY,
|
ESP_BLE_SM_SET_STATIC_PASSKEY,
|
||||||
|
/* Reset static Passkey */
|
||||||
ESP_BLE_SM_CLEAR_STATIC_PASSKEY,
|
ESP_BLE_SM_CLEAR_STATIC_PASSKEY,
|
||||||
|
/* Accept only specified SMP Authentication requirement */
|
||||||
ESP_BLE_SM_ONLY_ACCEPT_SPECIFIED_SEC_AUTH,
|
ESP_BLE_SM_ONLY_ACCEPT_SPECIFIED_SEC_AUTH,
|
||||||
|
/* Enable/Disable OOB support */
|
||||||
ESP_BLE_SM_OOB_SUPPORT,
|
ESP_BLE_SM_OOB_SUPPORT,
|
||||||
ESP_BLE_SM_MAX_PARAM,
|
ESP_BLE_SM_MAX_PARAM,
|
||||||
} esp_ble_sm_param_t;
|
} esp_ble_sm_param_t;
|
||||||
|
|
|
@ -48,6 +48,7 @@ tBTE_APPL_CFG bte_appl_cfg = {
|
||||||
BTM_BLE_INITIATOR_KEY_SIZE,
|
BTM_BLE_INITIATOR_KEY_SIZE,
|
||||||
BTM_BLE_RESPONDER_KEY_SIZE,
|
BTM_BLE_RESPONDER_KEY_SIZE,
|
||||||
BTM_BLE_MAX_KEY_SIZE,
|
BTM_BLE_MAX_KEY_SIZE,
|
||||||
|
BTM_BLE_MIN_KEY_SIZE,
|
||||||
BTM_BLE_ONLY_ACCEPT_SPECIFIED_SEC_AUTH_DISABLE,
|
BTM_BLE_ONLY_ACCEPT_SPECIFIED_SEC_AUTH_DISABLE,
|
||||||
BTM_BLE_OOB_DISABLE,
|
BTM_BLE_OOB_DISABLE,
|
||||||
};
|
};
|
||||||
|
@ -407,7 +408,7 @@ void bta_dm_co_ble_set_rsp_key_req(UINT8 rsp_key)
|
||||||
void bta_dm_co_ble_set_max_key_size(UINT8 ble_key_size)
|
void bta_dm_co_ble_set_max_key_size(UINT8 ble_key_size)
|
||||||
{
|
{
|
||||||
#if (SMP_INCLUDED == TRUE)
|
#if (SMP_INCLUDED == TRUE)
|
||||||
if(ble_key_size >= BTM_BLE_MIN_KEY_SIZE && ble_key_size <= BTM_BLE_MAX_KEY_SIZE) {
|
if(ble_key_size >= bte_appl_cfg.ble_min_key_size && ble_key_size <= BTM_BLE_MAX_KEY_SIZE) {
|
||||||
bte_appl_cfg.ble_max_key_size = ble_key_size;
|
bte_appl_cfg.ble_max_key_size = ble_key_size;
|
||||||
} else {
|
} else {
|
||||||
APPL_TRACE_ERROR("%s error:Invalid key size value, key_size =%d",__func__, ble_key_size);
|
APPL_TRACE_ERROR("%s error:Invalid key size value, key_size =%d",__func__, ble_key_size);
|
||||||
|
@ -415,6 +416,17 @@ void bta_dm_co_ble_set_max_key_size(UINT8 ble_key_size)
|
||||||
#endif ///SMP_INCLUDED == TRUE
|
#endif ///SMP_INCLUDED == TRUE
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void bta_dm_co_ble_set_min_key_size(UINT8 ble_key_size)
|
||||||
|
{
|
||||||
|
#if (SMP_INCLUDED == TRUE)
|
||||||
|
if(ble_key_size >= BTM_BLE_MIN_KEY_SIZE && ble_key_size <= bte_appl_cfg.ble_max_key_size) {
|
||||||
|
bte_appl_cfg.ble_min_key_size = ble_key_size;
|
||||||
|
} else {
|
||||||
|
APPL_TRACE_ERROR("%s error:Invalid key size value, key_size =%d",__func__, ble_key_size);
|
||||||
|
}
|
||||||
|
#endif ///SMP_INCLUDED == TRUE
|
||||||
|
}
|
||||||
|
|
||||||
void bta_dm_co_ble_set_accept_auth_enable(UINT8 enable)
|
void bta_dm_co_ble_set_accept_auth_enable(UINT8 enable)
|
||||||
{
|
{
|
||||||
#if (SMP_INCLUDED == TRUE)
|
#if (SMP_INCLUDED == TRUE)
|
||||||
|
|
|
@ -206,6 +206,8 @@ extern void bta_dm_co_ble_set_rsp_key_req(UINT8 rsp_key);
|
||||||
|
|
||||||
extern void bta_dm_co_ble_set_max_key_size(UINT8 ble_key_size);
|
extern void bta_dm_co_ble_set_max_key_size(UINT8 ble_key_size);
|
||||||
|
|
||||||
|
extern void bta_dm_co_ble_set_min_key_size(UINT8 ble_key_size);
|
||||||
|
|
||||||
extern void bta_dm_co_ble_set_accept_auth_enable(UINT8 enable);
|
extern void bta_dm_co_ble_set_accept_auth_enable(UINT8 enable);
|
||||||
|
|
||||||
extern UINT8 bta_dm_co_ble_get_accept_auth_enable(void);
|
extern UINT8 bta_dm_co_ble_get_accept_auth_enable(void);
|
||||||
|
|
|
@ -1196,6 +1196,12 @@ void btc_gap_ble_call_handler(btc_msg_t *msg)
|
||||||
bta_dm_co_ble_set_max_key_size(key_size);
|
bta_dm_co_ble_set_max_key_size(key_size);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case ESP_BLE_SM_MIN_KEY_SIZE: {
|
||||||
|
uint8_t key_size = 0;
|
||||||
|
STREAM_TO_UINT8(key_size, value);
|
||||||
|
bta_dm_co_ble_set_min_key_size(key_size);
|
||||||
|
break;
|
||||||
|
}
|
||||||
case ESP_BLE_SM_SET_STATIC_PASSKEY: {
|
case ESP_BLE_SM_SET_STATIC_PASSKEY: {
|
||||||
uint32_t passkey = 0;
|
uint32_t passkey = 0;
|
||||||
for(uint8_t i = 0; i < arg->set_security_param.len; i++)
|
for(uint8_t i = 0; i < arg->set_security_param.len; i++)
|
||||||
|
|
|
@ -31,6 +31,7 @@ typedef struct {
|
||||||
UINT8 ble_init_key;
|
UINT8 ble_init_key;
|
||||||
UINT8 ble_resp_key;
|
UINT8 ble_resp_key;
|
||||||
UINT8 ble_max_key_size;
|
UINT8 ble_max_key_size;
|
||||||
|
UINT8 ble_min_key_size;
|
||||||
UINT8 ble_accept_auth_enable;
|
UINT8 ble_accept_auth_enable;
|
||||||
UINT8 oob_support;
|
UINT8 oob_support;
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -36,6 +36,7 @@
|
||||||
#include "smp_int.h"
|
#include "smp_int.h"
|
||||||
#include "device/controller.h"
|
#include "device/controller.h"
|
||||||
#include "btm_int.h"
|
#include "btm_int.h"
|
||||||
|
#include "common/bte_appl.h"
|
||||||
|
|
||||||
#define SMP_PAIRING_REQ_SIZE 7
|
#define SMP_PAIRING_REQ_SIZE 7
|
||||||
#define SMP_CONFIRM_CMD_SIZE (BT_OCTET16_LEN + 1)
|
#define SMP_CONFIRM_CMD_SIZE (BT_OCTET16_LEN + 1)
|
||||||
|
@ -1140,9 +1141,27 @@ BOOLEAN smp_pairing_request_response_parameters_are_valid(tSMP_CB *p_cb)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((enc_size < SMP_ENCR_KEY_SIZE_MIN) || (enc_size > SMP_ENCR_KEY_SIZE_MAX)) {
|
/* `bte_appl_cfg.ble_min_enc_key_size` will be `SMP_ENCR_KEY_SIZE_MIN` by
|
||||||
|
* default if not set explicitly */
|
||||||
|
#if (BLE_INCLUDED == TRUE)
|
||||||
|
if (enc_size < bte_appl_cfg.ble_min_key_size) {
|
||||||
SMP_TRACE_WARNING("Rcvd from the peer cmd 0x%02x with Maximum Encryption \
|
SMP_TRACE_WARNING("Rcvd from the peer cmd 0x%02x with Maximum Encryption \
|
||||||
Key value (0x%02x) out of range).\n",
|
Key value (0x%02x) less than minimum required key size).\n",
|
||||||
|
p_cb->rcvd_cmd_code, enc_size);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
if (enc_size < SMP_ENCR_KEY_SIZE_MIN) {
|
||||||
|
SMP_TRACE_WARNING("Rcvd from the peer cmd 0x%02x with Maximum Encryption \
|
||||||
|
Key value (0x%02x) less than minimum required key size).\n",
|
||||||
|
p_cb->rcvd_cmd_code, enc_size);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (enc_size > SMP_ENCR_KEY_SIZE_MAX) {
|
||||||
|
SMP_TRACE_WARNING("Rcvd from the peer cmd 0x%02x with Maximum Encryption \
|
||||||
|
Key value (0x%02x) greater than supported by stack).\n",
|
||||||
p_cb->rcvd_cmd_code, enc_size);
|
p_cb->rcvd_cmd_code, enc_size);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
|
@ -99,11 +99,11 @@ config BT_NIMBLE_SM_SC
|
||||||
Enable security manager secure connections
|
Enable security manager secure connections
|
||||||
|
|
||||||
config BT_NIMBLE_DEBUG
|
config BT_NIMBLE_DEBUG
|
||||||
bool "Enable host debugging"
|
bool "Enable extra runtime asserts and host debugging"
|
||||||
default n
|
default n
|
||||||
depends on BT_NIMBLE_ENABLED
|
depends on BT_NIMBLE_ENABLED
|
||||||
help
|
help
|
||||||
This enables extra runtime assertions
|
This enables extra runtime asserts and host debugging
|
||||||
|
|
||||||
config BT_NIMBLE_SVC_GAP_DEVICE_NAME
|
config BT_NIMBLE_SVC_GAP_DEVICE_NAME
|
||||||
string "BLE GAP default device name"
|
string "BLE GAP default device name"
|
||||||
|
@ -257,3 +257,12 @@ config BT_NIMBLE_MESH_DEVICE_NAME
|
||||||
help
|
help
|
||||||
This value defines Bluetooth Mesh device/node name
|
This value defines Bluetooth Mesh device/node name
|
||||||
|
|
||||||
|
config BT_NIMBLE_CRYPTO_STACK_MBEDTLS
|
||||||
|
bool "Override TinyCrypt with mbedTLS for crypto computations"
|
||||||
|
default y
|
||||||
|
depends on BT_NIMBLE_ENABLED
|
||||||
|
select MBEDTLS_ECP_RESTARTABLE
|
||||||
|
select MBEDTLS_CMAC_C
|
||||||
|
help
|
||||||
|
Enable this option to choose mbedTLS instead of TinyCrypt for crypto
|
||||||
|
computations.
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit adcd9408695cb4f873f117eb8c92007455b2c066
|
Subproject commit 6c91a9a153c421231b686d30c822e53fea7510c0
|
|
@ -567,6 +567,10 @@
|
||||||
#define MYNEWT_VAL_BLE_SM_THEIR_KEY_DIST (0)
|
#define MYNEWT_VAL_BLE_SM_THEIR_KEY_DIST (0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef MYNEWT_VAL_BLE_CRYPTO_STACK_MBEDTLS
|
||||||
|
#define MYNEWT_VAL_BLE_CRYPTO_STACK_MBEDTLS (CONFIG_BT_NIMBLE_CRYPTO_STACK_MBEDTLS)
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef MYNEWT_VAL_BLE_STORE_MAX_BONDS
|
#ifndef MYNEWT_VAL_BLE_STORE_MAX_BONDS
|
||||||
#define MYNEWT_VAL_BLE_STORE_MAX_BONDS CONFIG_BT_NIMBLE_MAX_BONDS
|
#define MYNEWT_VAL_BLE_STORE_MAX_BONDS CONFIG_BT_NIMBLE_MAX_BONDS
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,9 +1,17 @@
|
||||||
idf_component_register(SRCS "cxx_exception_stubs.cpp"
|
idf_component_register(SRCS "cxx_exception_stubs.cpp"
|
||||||
"cxx_guards.cpp")
|
"cxx_guards.cpp"
|
||||||
|
# Make sure that pthread is in component list
|
||||||
|
PRIV_REQUIRES pthread)
|
||||||
|
|
||||||
target_link_libraries(${COMPONENT_LIB} PUBLIC stdc++ gcc)
|
target_link_libraries(${COMPONENT_LIB} PUBLIC stdc++ gcc)
|
||||||
target_link_libraries(${COMPONENT_LIB} INTERFACE "-u __cxa_guard_dummy")
|
target_link_libraries(${COMPONENT_LIB} INTERFACE "-u __cxa_guard_dummy")
|
||||||
|
|
||||||
|
# Force pthread to also appear later than stdc++ in link line
|
||||||
|
add_library(stdcpp_pthread INTERFACE)
|
||||||
|
idf_component_get_property(pthread pthread COMPONENT_LIB)
|
||||||
|
target_link_libraries(stdcpp_pthread INTERFACE stdc++ $<TARGET_FILE:${pthread}>)
|
||||||
|
target_link_libraries(${COMPONENT_LIB} PUBLIC stdcpp_pthread)
|
||||||
|
|
||||||
if(NOT CONFIG_COMPILER_CXX_EXCEPTIONS)
|
if(NOT CONFIG_COMPILER_CXX_EXCEPTIONS)
|
||||||
target_link_libraries(${COMPONENT_LIB} INTERFACE "-u __cxx_fatal_exception")
|
target_link_libraries(${COMPONENT_LIB} INTERFACE "-u __cxx_fatal_exception")
|
||||||
endif()
|
endif()
|
||||||
|
|
|
@ -9,7 +9,7 @@ menu "eFuse Bit Manager"
|
||||||
config EFUSE_CUSTOM_TABLE_FILENAME
|
config EFUSE_CUSTOM_TABLE_FILENAME
|
||||||
string "Custom eFuse CSV file"
|
string "Custom eFuse CSV file"
|
||||||
depends on EFUSE_CUSTOM_TABLE
|
depends on EFUSE_CUSTOM_TABLE
|
||||||
default main/esp_efuse_custom_table.csv
|
default "main/esp_efuse_custom_table.csv"
|
||||||
help
|
help
|
||||||
Name of the custom eFuse CSV filename. This path is evaluated
|
Name of the custom eFuse CSV filename. This path is evaluated
|
||||||
relative to the project root directory.
|
relative to the project root directory.
|
||||||
|
|
|
@ -36,7 +36,7 @@ uint8_t esp_efuse_get_chip_ver(void)
|
||||||
uint8_t eco_bit0, eco_bit1, eco_bit2;
|
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_REV1, &eco_bit0, 1);
|
||||||
esp_efuse_read_field_blob(ESP_EFUSE_CHIP_VER_REV2, &eco_bit1, 1);
|
esp_efuse_read_field_blob(ESP_EFUSE_CHIP_VER_REV2, &eco_bit1, 1);
|
||||||
eco_bit2 = (REG_READ(APB_CTRL_DATE_REG) & 80000000) >> 31;
|
eco_bit2 = (REG_READ(APB_CTRL_DATE_REG) & 0x80000000) >> 31;
|
||||||
uint32_t combine_value = (eco_bit2 << 2) | (eco_bit1 << 1) | eco_bit0;
|
uint32_t combine_value = (eco_bit2 << 2) | (eco_bit1 << 1) | eco_bit0;
|
||||||
uint8_t chip_ver = 0;
|
uint8_t chip_ver = 0;
|
||||||
switch (combine_value) {
|
switch (combine_value) {
|
||||||
|
|
|
@ -89,7 +89,7 @@ menu "ESP32-specific"
|
||||||
|
|
||||||
choice SPIRAM_SPEED
|
choice SPIRAM_SPEED
|
||||||
prompt "Set RAM clock speed"
|
prompt "Set RAM clock speed"
|
||||||
default SPIRAM_CACHE_SPEED_40M
|
default SPIRAM_SPEED_40M
|
||||||
help
|
help
|
||||||
Select the speed for the SPI RAM chip.
|
Select the speed for the SPI RAM chip.
|
||||||
If SPI RAM is enabled, we only support three combinations of SPI speed mode we supported now:
|
If SPI RAM is enabled, we only support three combinations of SPI speed mode we supported now:
|
||||||
|
@ -402,7 +402,7 @@ menu "ESP32-specific"
|
||||||
choice ESP32_BROWNOUT_DET_LVL_SEL
|
choice ESP32_BROWNOUT_DET_LVL_SEL
|
||||||
prompt "Brownout voltage level"
|
prompt "Brownout voltage level"
|
||||||
depends on ESP32_BROWNOUT_DET
|
depends on ESP32_BROWNOUT_DET
|
||||||
default BROWNOUT_DET_LVL_SEL_25
|
default ESP32_BROWNOUT_DET_LVL_SEL_0
|
||||||
help
|
help
|
||||||
The brownout detector will reset the chip when the supply voltage is approximately
|
The brownout detector will reset the chip when the supply voltage is approximately
|
||||||
below this level. Note that there may be some variation of brownout voltage level
|
below this level. Note that there may be some variation of brownout voltage level
|
||||||
|
@ -653,6 +653,11 @@ menu "ESP32-specific"
|
||||||
|
|
||||||
Enabling this setting adds approximately 1KB to the app's IRAM usage.
|
Enabling this setting adds approximately 1KB to the app's IRAM usage.
|
||||||
|
|
||||||
|
config ESP32_APP_INIT_CLK
|
||||||
|
bool
|
||||||
|
default y if ESP32_COMPATIBLE_PRE_V2_1_BOOTLOADERS
|
||||||
|
default y if APP_BUILD_TYPE_ELF_RAM
|
||||||
|
|
||||||
config ESP32_RTCDATA_IN_FAST_MEM
|
config ESP32_RTCDATA_IN_FAST_MEM
|
||||||
bool "Place RTC_DATA_ATTR and RTC_RODATA_ATTR variables into RTC fast memory segment"
|
bool "Place RTC_DATA_ATTR and RTC_RODATA_ATTR variables into RTC fast memory segment"
|
||||||
default n
|
default n
|
||||||
|
|
|
@ -75,7 +75,7 @@ void esp_clk_init(void)
|
||||||
rtc_config_t cfg = RTC_CONFIG_DEFAULT();
|
rtc_config_t cfg = RTC_CONFIG_DEFAULT();
|
||||||
rtc_init(cfg);
|
rtc_init(cfg);
|
||||||
|
|
||||||
#ifdef CONFIG_ESP32_COMPATIBLE_PRE_V2_1_BOOTLOADERS
|
#if (CONFIG_ESP32_COMPATIBLE_PRE_V2_1_BOOTLOADERS || CONFIG_ESP32_APP_INIT_CLK)
|
||||||
/* Check the bootloader set the XTAL frequency.
|
/* Check the bootloader set the XTAL frequency.
|
||||||
|
|
||||||
Bootloaders pre-v2.1 don't do this.
|
Bootloaders pre-v2.1 don't do this.
|
||||||
|
@ -293,6 +293,8 @@ void esp_perip_clk_init(void)
|
||||||
DPORT_I2S1_CLK_EN |
|
DPORT_I2S1_CLK_EN |
|
||||||
DPORT_SPI_DMA_CLK_EN;
|
DPORT_SPI_DMA_CLK_EN;
|
||||||
|
|
||||||
|
common_perip_clk &= ~DPORT_SPI01_CLK_EN;
|
||||||
|
|
||||||
#if CONFIG_SPIRAM_SPEED_80M
|
#if CONFIG_SPIRAM_SPEED_80M
|
||||||
//80MHz SPIRAM uses SPI2/SPI3 as well; it's initialized before this is called. Because it is used in
|
//80MHz SPIRAM uses SPI2/SPI3 as well; it's initialized before this is called. Because it is used in
|
||||||
//a weird mode where clock to the peripheral is disabled but reset is also disabled, it 'hangs'
|
//a weird mode where clock to the peripheral is disabled but reset is also disabled, it 'hangs'
|
||||||
|
|
|
@ -72,6 +72,11 @@
|
||||||
#include "esp_efuse.h"
|
#include "esp_efuse.h"
|
||||||
#include "bootloader_flash_config.h"
|
#include "bootloader_flash_config.h"
|
||||||
|
|
||||||
|
#ifdef CONFIG_APP_BUILD_TYPE_ELF_RAM
|
||||||
|
#include "esp32/rom/efuse.h"
|
||||||
|
#include "esp32/rom/spi_flash.h"
|
||||||
|
#endif // CONFIG_APP_BUILD_TYPE_ELF_RAM
|
||||||
|
|
||||||
#define STRINGIFY(s) STRINGIFY2(s)
|
#define STRINGIFY(s) STRINGIFY2(s)
|
||||||
#define STRINGIFY2(s) #s
|
#define STRINGIFY2(s) #s
|
||||||
|
|
||||||
|
@ -391,6 +396,32 @@ void start_cpu0_default(void)
|
||||||
#ifndef CONFIG_FREERTOS_UNICORE
|
#ifndef CONFIG_FREERTOS_UNICORE
|
||||||
esp_dport_access_int_init();
|
esp_dport_access_int_init();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
bootloader_flash_update_id();
|
||||||
|
#if !CONFIG_SPIRAM_BOOT_INIT
|
||||||
|
// Read the application binary image header. This will also decrypt the header if the image is encrypted.
|
||||||
|
esp_image_header_t fhdr = {0};
|
||||||
|
#ifdef CONFIG_APP_BUILD_TYPE_ELF_RAM
|
||||||
|
fhdr.spi_mode = ESP_IMAGE_SPI_MODE_DIO;
|
||||||
|
fhdr.spi_speed = ESP_IMAGE_SPI_SPEED_40M;
|
||||||
|
fhdr.spi_size = ESP_IMAGE_FLASH_SIZE_4MB;
|
||||||
|
|
||||||
|
extern void esp_rom_spiflash_attach(uint32_t, bool);
|
||||||
|
esp_rom_spiflash_attach(ets_efuse_get_spiconfig(), false);
|
||||||
|
esp_rom_spiflash_unlock();
|
||||||
|
#else
|
||||||
|
// This assumes that DROM is the first segment in the application binary, i.e. that we can read
|
||||||
|
// the binary header through cache by accessing SOC_DROM_LOW address.
|
||||||
|
memcpy(&fhdr, (void*) SOC_DROM_LOW, sizeof(fhdr));
|
||||||
|
#endif // CONFIG_APP_BUILD_TYPE_ELF_RAM
|
||||||
|
|
||||||
|
// If psram is uninitialized, we need to improve some flash configuration.
|
||||||
|
bootloader_flash_clock_config(&fhdr);
|
||||||
|
bootloader_flash_gpio_config(&fhdr);
|
||||||
|
bootloader_flash_dummy_config(&fhdr);
|
||||||
|
bootloader_flash_cs_timing_config();
|
||||||
|
#endif //!CONFIG_SPIRAM_BOOT_INIT
|
||||||
|
|
||||||
spi_flash_init();
|
spi_flash_init();
|
||||||
/* init default OS-aware flash access critical section */
|
/* init default OS-aware flash access critical section */
|
||||||
spi_flash_guard_set(&g_flash_guard_default_ops);
|
spi_flash_guard_set(&g_flash_guard_default_ops);
|
||||||
|
@ -424,20 +455,6 @@ void start_cpu0_default(void)
|
||||||
esp_coex_adapter_register(&g_coex_adapter_funcs);
|
esp_coex_adapter_register(&g_coex_adapter_funcs);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bootloader_flash_update_id();
|
|
||||||
#if !CONFIG_SPIRAM_BOOT_INIT
|
|
||||||
// Read the application binary image header. This will also decrypt the header if the image is encrypted.
|
|
||||||
esp_image_header_t fhdr = {0};
|
|
||||||
// This assumes that DROM is the first segment in the application binary, i.e. that we can read
|
|
||||||
// the binary header through cache by accessing SOC_DROM_LOW address.
|
|
||||||
memcpy(&fhdr, (void*) SOC_DROM_LOW, sizeof(fhdr));
|
|
||||||
// If psram is uninitialized, we need to improve some flash configuration.
|
|
||||||
bootloader_flash_clock_config(&fhdr);
|
|
||||||
bootloader_flash_gpio_config(&fhdr);
|
|
||||||
bootloader_flash_dummy_config(&fhdr);
|
|
||||||
bootloader_flash_cs_timing_config();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
portBASE_TYPE res = xTaskCreatePinnedToCore(&main_task, "main",
|
portBASE_TYPE res = xTaskCreatePinnedToCore(&main_task, "main",
|
||||||
ESP_TASK_MAIN_STACK, NULL,
|
ESP_TASK_MAIN_STACK, NULL,
|
||||||
ESP_TASK_MAIN_PRIO, NULL, 0);
|
ESP_TASK_MAIN_PRIO, NULL, 0);
|
||||||
|
|
|
@ -440,6 +440,13 @@ static uint32_t coex_status_get_wrapper(void)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void coex_condition_set_wrapper(uint32_t type, bool dissatisfy)
|
||||||
|
{
|
||||||
|
#if CONFIG_SW_COEXIST_ENABLE
|
||||||
|
coex_condition_set(type, dissatisfy);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
static int coex_wifi_request_wrapper(uint32_t event, uint32_t latency, uint32_t duration)
|
static int coex_wifi_request_wrapper(uint32_t event, uint32_t latency, uint32_t duration)
|
||||||
{
|
{
|
||||||
#if CONFIG_ESP32_WIFI_SW_COEXIST_ENABLE
|
#if CONFIG_ESP32_WIFI_SW_COEXIST_ENABLE
|
||||||
|
@ -591,6 +598,7 @@ wifi_osi_funcs_t g_wifi_osi_funcs = {
|
||||||
._modem_sleep_register = esp_modem_sleep_register,
|
._modem_sleep_register = esp_modem_sleep_register,
|
||||||
._modem_sleep_deregister = esp_modem_sleep_deregister,
|
._modem_sleep_deregister = esp_modem_sleep_deregister,
|
||||||
._coex_status_get = coex_status_get_wrapper,
|
._coex_status_get = coex_status_get_wrapper,
|
||||||
|
._coex_condition_set = coex_condition_set_wrapper,
|
||||||
._coex_wifi_request = coex_wifi_request_wrapper,
|
._coex_wifi_request = coex_wifi_request_wrapper,
|
||||||
._coex_wifi_release = coex_wifi_release_wrapper,
|
._coex_wifi_release = coex_wifi_release_wrapper,
|
||||||
._magic = ESP_WIFI_OS_ADAPTER_MAGIC,
|
._magic = ESP_WIFI_OS_ADAPTER_MAGIC,
|
||||||
|
|
|
@ -49,6 +49,7 @@ MEMORY
|
||||||
/* IRAM for PRO cpu. Not sure if happy with this, this is MMU area... */
|
/* IRAM for PRO cpu. Not sure if happy with this, this is MMU area... */
|
||||||
iram0_0_seg (RX) : org = 0x40080000, len = 0x20000
|
iram0_0_seg (RX) : org = 0x40080000, len = 0x20000
|
||||||
|
|
||||||
|
#ifdef CONFIG_APP_BUILD_USE_FLASH_SECTIONS
|
||||||
/* Even though the segment name is iram, it is actually mapped to flash
|
/* Even though the segment name is iram, it is actually mapped to flash
|
||||||
*/
|
*/
|
||||||
iram0_2_seg (RX) : org = 0x400D0020, len = 0x330000-0x20
|
iram0_2_seg (RX) : org = 0x400D0020, len = 0x330000-0x20
|
||||||
|
@ -60,6 +61,7 @@ MEMORY
|
||||||
header. Setting this offset makes it simple to meet the flash cache MMU's
|
header. Setting this offset makes it simple to meet the flash cache MMU's
|
||||||
constraint that (paddr % 64KB == vaddr % 64KB).)
|
constraint that (paddr % 64KB == vaddr % 64KB).)
|
||||||
*/
|
*/
|
||||||
|
#endif // CONFIG_APP_BUILD_USE_FLASH_SECTIONS
|
||||||
|
|
||||||
|
|
||||||
/* Shared data RAM, excluding memory reserved for ROM bss/data/stack.
|
/* Shared data RAM, excluding memory reserved for ROM bss/data/stack.
|
||||||
|
@ -74,10 +76,12 @@ MEMORY
|
||||||
dram0_0_seg (RW) : org = 0x3FFB0000 + CONFIG_BT_RESERVE_DRAM,
|
dram0_0_seg (RW) : org = 0x3FFB0000 + CONFIG_BT_RESERVE_DRAM,
|
||||||
len = DRAM0_0_SEG_LEN - CONFIG_BT_RESERVE_DRAM
|
len = DRAM0_0_SEG_LEN - CONFIG_BT_RESERVE_DRAM
|
||||||
|
|
||||||
|
#ifdef CONFIG_APP_BUILD_USE_FLASH_SECTIONS
|
||||||
/* Flash mapped constant data */
|
/* Flash mapped constant data */
|
||||||
drom0_0_seg (R) : org = 0x3F400020, len = 0x400000-0x20
|
drom0_0_seg (R) : org = 0x3F400020, len = 0x400000-0x20
|
||||||
|
|
||||||
/* (See iram0_2_seg for meaning of 0x20 offset in the above.) */
|
/* (See iram0_2_seg for meaning of 0x20 offset in the above.) */
|
||||||
|
#endif // CONFIG_APP_BUILD_USE_FLASH_SECTIONS
|
||||||
|
|
||||||
/* RTC fast memory (executable). Persists over deep sleep.
|
/* RTC fast memory (executable). Persists over deep sleep.
|
||||||
*/
|
*/
|
||||||
|
@ -118,3 +122,15 @@ REGION_ALIAS("rtc_data_location", rtc_slow_seg );
|
||||||
#else
|
#else
|
||||||
REGION_ALIAS("rtc_data_location", rtc_data_seg );
|
REGION_ALIAS("rtc_data_location", rtc_data_seg );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_APP_BUILD_USE_FLASH_SECTIONS
|
||||||
|
REGION_ALIAS("default_code_seg", iram0_2_seg);
|
||||||
|
#else
|
||||||
|
REGION_ALIAS("default_code_seg", iram0_0_seg);
|
||||||
|
#endif // CONFIG_APP_BUILD_USE_FLASH_SECTIONS
|
||||||
|
|
||||||
|
#ifdef CONFIG_APP_BUILD_USE_FLASH_SECTIONS
|
||||||
|
REGION_ALIAS("default_rodata_seg", drom0_0_seg);
|
||||||
|
#else
|
||||||
|
REGION_ALIAS("default_rodata_seg", dram0_0_seg);
|
||||||
|
#endif // CONFIG_APP_BUILD_USE_FLASH_SECTIONS
|
||||||
|
|
|
@ -161,12 +161,8 @@ SECTIONS
|
||||||
mapping[iram0_text]
|
mapping[iram0_text]
|
||||||
|
|
||||||
_iram_text_end = ABSOLUTE(.);
|
_iram_text_end = ABSOLUTE(.);
|
||||||
_iram_end = ABSOLUTE(.);
|
|
||||||
} > iram0_0_seg
|
} > iram0_0_seg
|
||||||
|
|
||||||
ASSERT(((_iram_text_end - ORIGIN(iram0_0_seg)) <= LENGTH(iram0_0_seg)),
|
|
||||||
"IRAM0 segment data does not fit.")
|
|
||||||
|
|
||||||
.dram0.data :
|
.dram0.data :
|
||||||
{
|
{
|
||||||
_data_start = ABSOLUTE(.);
|
_data_start = ABSOLUTE(.);
|
||||||
|
@ -312,7 +308,7 @@ SECTIONS
|
||||||
*(.tbss.*)
|
*(.tbss.*)
|
||||||
_thread_local_end = ABSOLUTE(.);
|
_thread_local_end = ABSOLUTE(.);
|
||||||
. = ALIGN(4);
|
. = ALIGN(4);
|
||||||
} >drom0_0_seg
|
} >default_rodata_seg
|
||||||
|
|
||||||
.flash.text :
|
.flash.text :
|
||||||
{
|
{
|
||||||
|
@ -334,5 +330,25 @@ SECTIONS
|
||||||
the flash.text segment.
|
the flash.text segment.
|
||||||
*/
|
*/
|
||||||
_flash_cache_start = ABSOLUTE(0);
|
_flash_cache_start = ABSOLUTE(0);
|
||||||
} >iram0_2_seg
|
} >default_code_seg
|
||||||
|
|
||||||
|
/* Marks the end of IRAM code segment */
|
||||||
|
.iram0.text_end (NOLOAD) :
|
||||||
|
{
|
||||||
|
. = ALIGN (4);
|
||||||
|
_iram_end = ABSOLUTE(.);
|
||||||
|
} > iram0_0_seg
|
||||||
|
|
||||||
|
/* Marks the end of data, bss and possibly rodata */
|
||||||
|
.dram0.heap_start (NOLOAD) :
|
||||||
|
{
|
||||||
|
. = ALIGN (8);
|
||||||
|
_heap_start = ABSOLUTE(.);
|
||||||
|
} > dram0_0_seg
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ASSERT(((_iram_text_end - ORIGIN(iram0_0_seg)) <= LENGTH(iram0_0_seg)),
|
||||||
|
"IRAM0 segment data does not fit.")
|
||||||
|
|
||||||
|
ASSERT(((_heap_start - ORIGIN(dram0_0_seg)) <= LENGTH(dram0_0_seg)),
|
||||||
|
"DRAM segment data does not fit.")
|
||||||
|
|
|
@ -50,8 +50,12 @@ entries:
|
||||||
|
|
||||||
[scheme:default]
|
[scheme:default]
|
||||||
entries:
|
entries:
|
||||||
|
if APP_BUILD_USE_FLASH_SECTIONS = y:
|
||||||
text -> flash_text
|
text -> flash_text
|
||||||
rodata -> flash_rodata
|
rodata -> flash_rodata
|
||||||
|
else:
|
||||||
|
text -> iram0_text
|
||||||
|
rodata -> dram0_data
|
||||||
data -> dram0_data
|
data -> dram0_data
|
||||||
bss -> dram0_bss
|
bss -> dram0_bss
|
||||||
common -> dram0_bss
|
common -> dram0_bss
|
||||||
|
|
|
@ -450,7 +450,7 @@ static void esp_panic_dig_reset(void)
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif // CONFIG_ESP32_PANIC_PRINT_REBOOT || CONFIG_ESP32_PANIC_SILENT_REBOOT
|
||||||
|
|
||||||
static void putEntry(uint32_t pc, uint32_t sp)
|
static void putEntry(uint32_t pc, uint32_t sp)
|
||||||
{
|
{
|
||||||
|
|
|
@ -247,11 +247,6 @@ typedef struct {
|
||||||
uint32_t sw_reset_timeout_ms; /*!< Software reset timeout value (Unit: ms) */
|
uint32_t sw_reset_timeout_ms; /*!< Software reset timeout value (Unit: ms) */
|
||||||
uint32_t rx_task_stack_size; /*!< Stack size of the receive task */
|
uint32_t rx_task_stack_size; /*!< Stack size of the receive task */
|
||||||
uint32_t rx_task_prio; /*!< Priority of the receive task */
|
uint32_t rx_task_prio; /*!< Priority of the receive task */
|
||||||
uint32_t queue_len; /*!< Length of the transaction queue */
|
|
||||||
#if CONFIG_ETH_USE_SPI_ETHERNET
|
|
||||||
spi_device_handle_t spi_hdl; /*!< Handle of spi device */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
} eth_mac_config_t;
|
} eth_mac_config_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -263,7 +258,6 @@ typedef struct {
|
||||||
.sw_reset_timeout_ms = 100, \
|
.sw_reset_timeout_ms = 100, \
|
||||||
.rx_task_stack_size = 4096, \
|
.rx_task_stack_size = 4096, \
|
||||||
.rx_task_prio = 15, \
|
.rx_task_prio = 15, \
|
||||||
.queue_len = 100, \
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if CONFIG_ETH_USE_ESP32_EMAC
|
#if CONFIG_ETH_USE_ESP32_EMAC
|
||||||
|
@ -280,16 +274,34 @@ esp_eth_mac_t *esp_eth_mac_new_esp32(const eth_mac_config_t *config);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if CONFIG_ETH_SPI_ETHERNET_DM9051
|
#if CONFIG_ETH_SPI_ETHERNET_DM9051
|
||||||
|
/**
|
||||||
|
* @brief DM9051 specific configuration
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
spi_device_handle_t spi_hdl; /*!< Handle of SPI device driver */
|
||||||
|
} eth_dm9051_config_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Default DM9051 specific configuration
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#define ETH_DM9051_DEFAULT_CONFIG(spi_device) \
|
||||||
|
{ \
|
||||||
|
.spi_hdl = spi_device, \
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Create DM9051 Ethernet MAC instance
|
* @brief Create DM9051 Ethernet MAC instance
|
||||||
*
|
*
|
||||||
* @param config: Ethernet MAC configuration
|
* @param dm9051_config: DM9051 specific configuration
|
||||||
|
* @param mac_config: Ethernet MAC configuration
|
||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
* - instance: create MAC instance successfully
|
* - instance: create MAC instance successfully
|
||||||
* - NULL: create MAC instance failed because some error occurred
|
* - NULL: create MAC instance failed because some error occurred
|
||||||
*/
|
*/
|
||||||
esp_eth_mac_t *esp_eth_mac_new_dm9051(const eth_mac_config_t *config);
|
esp_eth_mac_t *esp_eth_mac_new_dm9051(const eth_dm9051_config_t *dm9051_config, const eth_mac_config_t *mac_config);
|
||||||
#endif
|
#endif
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
|
@ -815,16 +815,16 @@ static esp_err_t emac_dm9051_del(esp_eth_mac_t *mac)
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
esp_eth_mac_t *esp_eth_mac_new_dm9051(const eth_mac_config_t *config)
|
esp_eth_mac_t *esp_eth_mac_new_dm9051(const eth_dm9051_config_t *dm9051_config, const eth_mac_config_t *mac_config)
|
||||||
{
|
{
|
||||||
esp_eth_mac_t *ret = NULL;
|
esp_eth_mac_t *ret = NULL;
|
||||||
MAC_CHECK(config, "can't set mac config to null", err, NULL);
|
MAC_CHECK(dm9051_config, "can't set dm9051 specific config to null", err, NULL);
|
||||||
MAC_CHECK(config->spi_hdl, "can't set spi handle to null", err, NULL);
|
MAC_CHECK(mac_config, "can't set mac config to null", err, NULL);
|
||||||
emac_dm9051_t *emac = calloc(1, sizeof(emac_dm9051_t));
|
emac_dm9051_t *emac = calloc(1, sizeof(emac_dm9051_t));
|
||||||
MAC_CHECK(emac, "calloc emac failed", err, NULL);
|
MAC_CHECK(emac, "calloc emac failed", err, NULL);
|
||||||
/* bind methods and attributes */
|
/* bind methods and attributes */
|
||||||
emac->sw_reset_timeout_ms = config->sw_reset_timeout_ms;
|
emac->sw_reset_timeout_ms = mac_config->sw_reset_timeout_ms;
|
||||||
emac->spi_hdl = config->spi_hdl;
|
emac->spi_hdl = dm9051_config->spi_hdl;
|
||||||
emac->parent.set_mediator = emac_dm9051_set_mediator;
|
emac->parent.set_mediator = emac_dm9051_set_mediator;
|
||||||
emac->parent.init = emac_dm9051_init;
|
emac->parent.init = emac_dm9051_init;
|
||||||
emac->parent.deinit = emac_dm9051_deinit;
|
emac->parent.deinit = emac_dm9051_deinit;
|
||||||
|
@ -843,8 +843,8 @@ esp_eth_mac_t *esp_eth_mac_new_dm9051(const eth_mac_config_t *config)
|
||||||
emac->spi_lock = xSemaphoreCreateMutex();
|
emac->spi_lock = xSemaphoreCreateMutex();
|
||||||
MAC_CHECK(emac->spi_lock, "create lock failed", err_lock, NULL);
|
MAC_CHECK(emac->spi_lock, "create lock failed", err_lock, NULL);
|
||||||
/* create dm9051 task */
|
/* create dm9051 task */
|
||||||
BaseType_t xReturned = xTaskCreate(emac_dm9051_task, "dm9051_tsk", config->rx_task_stack_size, emac,
|
BaseType_t xReturned = xTaskCreate(emac_dm9051_task, "dm9051_tsk", mac_config->rx_task_stack_size, emac,
|
||||||
config->rx_task_prio, &emac->rx_task_hdl);
|
mac_config->rx_task_prio, &emac->rx_task_hdl);
|
||||||
MAC_CHECK(xReturned == pdPASS, "create dm9051 task failed", err_tsk, NULL);
|
MAC_CHECK(xReturned == pdPASS, "create dm9051 task failed", err_tsk, NULL);
|
||||||
return &(emac->parent);
|
return &(emac->parent);
|
||||||
err_tsk:
|
err_tsk:
|
||||||
|
|
|
@ -1,31 +1,47 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include "sdkconfig.h"
|
||||||
#include "freertos/FreeRTOS.h"
|
#include "freertos/FreeRTOS.h"
|
||||||
#include "freertos/task.h"
|
#include "freertos/task.h"
|
||||||
|
#include "freertos/event_groups.h"
|
||||||
#include "tcpip_adapter.h"
|
#include "tcpip_adapter.h"
|
||||||
#include "esp_event.h"
|
|
||||||
#include "unity.h"
|
#include "unity.h"
|
||||||
#include "test_utils.h"
|
#include "test_utils.h"
|
||||||
|
#include "esp_event.h"
|
||||||
#include "esp_eth.h"
|
#include "esp_eth.h"
|
||||||
#include "esp_log.h"
|
#include "esp_log.h"
|
||||||
#include "sdkconfig.h"
|
|
||||||
|
|
||||||
static const char *TAG = "esp_eth_test";
|
static const char *TAG = "esp_eth_test";
|
||||||
|
|
||||||
|
#define ETH_START_BIT BIT(0)
|
||||||
|
#define ETH_STOP_BIT BIT(1)
|
||||||
|
#define ETH_CONNECT_BIT BIT(2)
|
||||||
|
#define ETH_GOT_IP_BIT BIT(3)
|
||||||
|
|
||||||
|
#define ETH_START_TIMEOUT_MS (10000)
|
||||||
|
#define ETH_CONNECT_TIMEOUT_MS (40000)
|
||||||
|
#define ETH_STOP_TIMEOUT_MS (10000)
|
||||||
|
#define ETH_GET_IP_TIMEOUT_MS (60000)
|
||||||
|
|
||||||
/** Event handler for Ethernet events */
|
/** Event handler for Ethernet events */
|
||||||
static void eth_event_handler(void *arg, esp_event_base_t event_base,
|
static void eth_event_handler(void *arg, esp_event_base_t event_base,
|
||||||
int32_t event_id, void *event_data)
|
int32_t event_id, void *event_data)
|
||||||
{
|
{
|
||||||
|
EventGroupHandle_t eth_event_group = (EventGroupHandle_t)arg;
|
||||||
switch (event_id) {
|
switch (event_id) {
|
||||||
case ETHERNET_EVENT_CONNECTED:
|
case ETHERNET_EVENT_CONNECTED:
|
||||||
|
xEventGroupSetBits(eth_event_group, ETH_CONNECT_BIT);
|
||||||
ESP_LOGI(TAG, "Ethernet Link Up");
|
ESP_LOGI(TAG, "Ethernet Link Up");
|
||||||
break;
|
break;
|
||||||
case ETHERNET_EVENT_DISCONNECTED:
|
case ETHERNET_EVENT_DISCONNECTED:
|
||||||
ESP_LOGI(TAG, "Ethernet Link Down");
|
ESP_LOGI(TAG, "Ethernet Link Down");
|
||||||
break;
|
break;
|
||||||
case ETHERNET_EVENT_START:
|
case ETHERNET_EVENT_START:
|
||||||
|
xEventGroupSetBits(eth_event_group, ETH_START_BIT);
|
||||||
ESP_LOGI(TAG, "Ethernet Started");
|
ESP_LOGI(TAG, "Ethernet Started");
|
||||||
break;
|
break;
|
||||||
case ETHERNET_EVENT_STOP:
|
case ETHERNET_EVENT_STOP:
|
||||||
|
xEventGroupSetBits(eth_event_group, ETH_STOP_BIT);
|
||||||
ESP_LOGI(TAG, "Ethernet Stopped");
|
ESP_LOGI(TAG, "Ethernet Stopped");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -37,6 +53,7 @@ static void eth_event_handler(void *arg, esp_event_base_t event_base,
|
||||||
static void got_ip_event_handler(void *arg, esp_event_base_t event_base,
|
static void got_ip_event_handler(void *arg, esp_event_base_t event_base,
|
||||||
int32_t event_id, void *event_data)
|
int32_t event_id, void *event_data)
|
||||||
{
|
{
|
||||||
|
EventGroupHandle_t eth_event_group = (EventGroupHandle_t)arg;
|
||||||
ip_event_got_ip_t *event = (ip_event_got_ip_t *)event_data;
|
ip_event_got_ip_t *event = (ip_event_got_ip_t *)event_data;
|
||||||
const tcpip_adapter_ip_info_t *ip_info = &event->ip_info;
|
const tcpip_adapter_ip_info_t *ip_info = &event->ip_info;
|
||||||
|
|
||||||
|
@ -46,27 +63,31 @@ static void got_ip_event_handler(void *arg, esp_event_base_t event_base,
|
||||||
ESP_LOGI(TAG, "ETHMASK:" IPSTR, IP2STR(&ip_info->netmask));
|
ESP_LOGI(TAG, "ETHMASK:" IPSTR, IP2STR(&ip_info->netmask));
|
||||||
ESP_LOGI(TAG, "ETHGW:" IPSTR, IP2STR(&ip_info->gw));
|
ESP_LOGI(TAG, "ETHGW:" IPSTR, IP2STR(&ip_info->gw));
|
||||||
ESP_LOGI(TAG, "~~~~~~~~~~~");
|
ESP_LOGI(TAG, "~~~~~~~~~~~");
|
||||||
|
xEventGroupSetBits(eth_event_group, ETH_GOT_IP_BIT);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("esp32 emac io test", "[ethernet][ignore]")
|
TEST_CASE("esp32 ethernet io test", "[ethernet][test_env=UT_T2_Ethernet]")
|
||||||
{
|
{
|
||||||
TEST_ESP_OK(esp_event_loop_create_default());
|
TEST_ESP_OK(esp_event_loop_create_default());
|
||||||
eth_mac_config_t mac_config = ETH_MAC_DEFAULT_CONFIG();
|
eth_mac_config_t mac_config = ETH_MAC_DEFAULT_CONFIG();
|
||||||
esp_eth_mac_t *mac = esp_eth_mac_new_esp32(&mac_config);
|
esp_eth_mac_t *mac = esp_eth_mac_new_esp32(&mac_config);
|
||||||
eth_phy_config_t phy_config = ETH_PHY_DEFAULT_CONFIG();
|
eth_phy_config_t phy_config = ETH_PHY_DEFAULT_CONFIG();
|
||||||
esp_eth_phy_t *phy = esp_eth_phy_new_ip101(&phy_config);
|
esp_eth_phy_t *phy = esp_eth_phy_new_ip101(&phy_config);
|
||||||
esp_eth_config_t config = ETH_DEFAULT_CONFIG(mac, phy);
|
esp_eth_config_t eth_config = ETH_DEFAULT_CONFIG(mac, phy);
|
||||||
esp_eth_handle_t eth_handle = NULL;
|
esp_eth_handle_t eth_handle = NULL;
|
||||||
TEST_ESP_OK(esp_eth_driver_install(&config, ð_handle));
|
TEST_ESP_OK(esp_eth_driver_install(ð_config, ð_handle));
|
||||||
vTaskDelay(pdMS_TO_TICKS(1000));
|
vTaskDelay(pdMS_TO_TICKS(1000));
|
||||||
/* get MAC address */
|
/* get MAC address */
|
||||||
uint8_t mac_addr[6];
|
uint8_t mac_addr[6];
|
||||||
memset(mac_addr, 0, sizeof(mac_addr));
|
memset(mac_addr, 0, sizeof(mac_addr));
|
||||||
TEST_ESP_OK(esp_eth_ioctl(eth_handle, ETH_CMD_G_MAC_ADDR, mac_addr));
|
TEST_ESP_OK(esp_eth_ioctl(eth_handle, ETH_CMD_G_MAC_ADDR, mac_addr));
|
||||||
|
ESP_LOGI(TAG, "Ethernet MAC Address: %d:%d:%d:%d:%d:%d",
|
||||||
|
mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]);
|
||||||
TEST_ASSERT(mac_addr[0] != 0);
|
TEST_ASSERT(mac_addr[0] != 0);
|
||||||
/* get PHY address */
|
/* get PHY address */
|
||||||
int phy_addr = -1;
|
int phy_addr = -1;
|
||||||
TEST_ESP_OK(esp_eth_ioctl(eth_handle, ETH_CMD_G_PHY_ADDR, &phy_addr));
|
TEST_ESP_OK(esp_eth_ioctl(eth_handle, ETH_CMD_G_PHY_ADDR, &phy_addr));
|
||||||
|
ESP_LOGI(TAG, "Ethernet PHY Address: %d", phy_addr);
|
||||||
TEST_ASSERT(phy_addr >= 0 && phy_addr <= 31);
|
TEST_ASSERT(phy_addr >= 0 && phy_addr <= 31);
|
||||||
TEST_ESP_OK(esp_eth_driver_uninstall(eth_handle));
|
TEST_ESP_OK(esp_eth_driver_uninstall(eth_handle));
|
||||||
TEST_ESP_OK(phy->del(phy));
|
TEST_ESP_OK(phy->del(phy));
|
||||||
|
@ -74,21 +95,65 @@ TEST_CASE("esp32 emac io test", "[ethernet][ignore]")
|
||||||
TEST_ESP_OK(esp_event_loop_delete_default());
|
TEST_ESP_OK(esp_event_loop_delete_default());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("ethernet tcpip_adapter", "[ethernet][ignore]")
|
TEST_CASE("esp32 ethernet event test", "[ethernet][test_env=UT_T2_Ethernet]")
|
||||||
{
|
{
|
||||||
test_case_uses_tcpip();
|
EventBits_t bits = 0;
|
||||||
|
EventGroupHandle_t eth_event_group = xEventGroupCreate();
|
||||||
|
TEST_ASSERT(eth_event_group != NULL);
|
||||||
TEST_ESP_OK(esp_event_loop_create_default());
|
TEST_ESP_OK(esp_event_loop_create_default());
|
||||||
TEST_ESP_OK(tcpip_adapter_set_default_eth_handlers());
|
TEST_ESP_OK(esp_event_handler_register(ETH_EVENT, ESP_EVENT_ANY_ID, ð_event_handler, eth_event_group));
|
||||||
TEST_ESP_OK(esp_event_handler_register(ETH_EVENT, ESP_EVENT_ANY_ID, ð_event_handler, NULL));
|
|
||||||
TEST_ESP_OK(esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, &got_ip_event_handler, NULL));
|
|
||||||
eth_mac_config_t mac_config = ETH_MAC_DEFAULT_CONFIG();
|
eth_mac_config_t mac_config = ETH_MAC_DEFAULT_CONFIG();
|
||||||
esp_eth_mac_t *mac = esp_eth_mac_new_esp32(&mac_config);
|
esp_eth_mac_t *mac = esp_eth_mac_new_esp32(&mac_config);
|
||||||
eth_phy_config_t phy_config = ETH_PHY_DEFAULT_CONFIG();
|
eth_phy_config_t phy_config = ETH_PHY_DEFAULT_CONFIG();
|
||||||
esp_eth_phy_t *phy = esp_eth_phy_new_ip101(&phy_config);
|
esp_eth_phy_t *phy = esp_eth_phy_new_ip101(&phy_config);
|
||||||
esp_eth_config_t config = ETH_DEFAULT_CONFIG(mac, phy);
|
esp_eth_config_t eth_config = ETH_DEFAULT_CONFIG(mac, phy);
|
||||||
esp_eth_handle_t eth_handle = NULL;
|
esp_eth_handle_t eth_handle = NULL;
|
||||||
TEST_ESP_OK(esp_eth_driver_install(&config, ð_handle));
|
TEST_ESP_OK(esp_eth_driver_install(ð_config, ð_handle));
|
||||||
vTaskDelay(portMAX_DELAY);
|
/* wait for connection start */
|
||||||
|
bits = xEventGroupWaitBits(eth_event_group, ETH_START_BIT, true, true, pdMS_TO_TICKS(ETH_START_TIMEOUT_MS));
|
||||||
|
TEST_ASSERT((bits & ETH_START_BIT) == ETH_START_BIT);
|
||||||
|
/* wait for connection establish */
|
||||||
|
bits = xEventGroupWaitBits(eth_event_group, ETH_CONNECT_BIT, true, true, pdMS_TO_TICKS(ETH_CONNECT_TIMEOUT_MS));
|
||||||
|
TEST_ASSERT((bits & ETH_CONNECT_BIT) == ETH_CONNECT_BIT);
|
||||||
|
TEST_ESP_OK(esp_eth_driver_uninstall(eth_handle));
|
||||||
|
/* wait for connection stop */
|
||||||
|
bits = xEventGroupWaitBits(eth_event_group, ETH_STOP_BIT, true, true, pdMS_TO_TICKS(ETH_STOP_TIMEOUT_MS));
|
||||||
|
TEST_ASSERT((bits & ETH_STOP_BIT) == ETH_STOP_BIT);
|
||||||
|
// "check link timer callback" might owned the reference of phy object, make sure it has release it
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(2000));
|
||||||
|
TEST_ESP_OK(phy->del(phy));
|
||||||
|
TEST_ESP_OK(mac->del(mac));
|
||||||
|
TEST_ESP_OK(esp_event_handler_unregister(ETH_EVENT, ESP_EVENT_ANY_ID, eth_event_handler));
|
||||||
|
TEST_ESP_OK(esp_event_loop_delete_default());
|
||||||
|
vEventGroupDelete(eth_event_group);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("esp32 ethernet dhcp test", "[ethernet][test_env=UT_T2_Ethernet]")
|
||||||
|
{
|
||||||
|
EventBits_t bits = 0;
|
||||||
|
EventGroupHandle_t eth_event_group = xEventGroupCreate();
|
||||||
|
TEST_ASSERT(eth_event_group != NULL);
|
||||||
|
test_case_uses_tcpip();
|
||||||
|
TEST_ESP_OK(esp_event_loop_create_default());
|
||||||
|
TEST_ESP_OK(tcpip_adapter_set_default_eth_handlers());
|
||||||
|
TEST_ESP_OK(esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, &got_ip_event_handler, eth_event_group));
|
||||||
|
eth_mac_config_t mac_config = ETH_MAC_DEFAULT_CONFIG();
|
||||||
|
esp_eth_mac_t *mac = esp_eth_mac_new_esp32(&mac_config);
|
||||||
|
eth_phy_config_t phy_config = ETH_PHY_DEFAULT_CONFIG();
|
||||||
|
esp_eth_phy_t *phy = esp_eth_phy_new_ip101(&phy_config);
|
||||||
|
esp_eth_config_t eth_config = ETH_DEFAULT_CONFIG(mac, phy);
|
||||||
|
esp_eth_handle_t eth_handle = NULL;
|
||||||
|
TEST_ESP_OK(esp_eth_driver_install(ð_config, ð_handle));
|
||||||
|
/* wait for IP lease */
|
||||||
|
bits = xEventGroupWaitBits(eth_event_group, ETH_GOT_IP_BIT, true, true, pdMS_TO_TICKS(ETH_GET_IP_TIMEOUT_MS));
|
||||||
|
TEST_ASSERT((bits & ETH_GOT_IP_BIT) == ETH_GOT_IP_BIT);
|
||||||
|
TEST_ESP_OK(esp_eth_driver_uninstall(eth_handle));
|
||||||
|
TEST_ESP_OK(phy->del(phy));
|
||||||
|
TEST_ESP_OK(mac->del(mac));
|
||||||
|
TEST_ESP_OK(esp_event_handler_unregister(IP_EVENT, IP_EVENT_ETH_GOT_IP, got_ip_event_handler));
|
||||||
|
TEST_ESP_OK(tcpip_adapter_clear_default_eth_handlers());
|
||||||
|
TEST_ESP_OK(esp_event_loop_delete_default());
|
||||||
|
vEventGroupDelete(eth_event_group);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if CONFIG_ETH_USE_SPI_ETHERNET
|
#if CONFIG_ETH_USE_SPI_ETHERNET
|
||||||
|
@ -119,8 +184,8 @@ TEST_CASE("dm9051 io test", "[ethernet][ignore]")
|
||||||
TEST_ESP_OK(esp_event_handler_register(ETH_EVENT, ESP_EVENT_ANY_ID, ð_event_handler, NULL));
|
TEST_ESP_OK(esp_event_handler_register(ETH_EVENT, ESP_EVENT_ANY_ID, ð_event_handler, NULL));
|
||||||
TEST_ESP_OK(esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, &got_ip_event_handler, NULL));
|
TEST_ESP_OK(esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, &got_ip_event_handler, NULL));
|
||||||
eth_mac_config_t mac_config = ETH_MAC_DEFAULT_CONFIG();
|
eth_mac_config_t mac_config = ETH_MAC_DEFAULT_CONFIG();
|
||||||
mac_config.spi_hdl = spi_handle;
|
eth_dm9051_config_t dm9051_config = ETH_DM9051_DEFAULT_CONFIG(spi_handle);
|
||||||
esp_eth_mac_t *mac = esp_eth_mac_new_dm9051(&mac_config);
|
esp_eth_mac_t *mac = esp_eth_mac_new_dm9051(&dm9051_config, &mac_config);
|
||||||
eth_phy_config_t phy_config = ETH_PHY_DEFAULT_CONFIG();
|
eth_phy_config_t phy_config = ETH_PHY_DEFAULT_CONFIG();
|
||||||
esp_eth_phy_t *phy = esp_eth_phy_new_dm9051(&phy_config);
|
esp_eth_phy_t *phy = esp_eth_phy_new_dm9051(&phy_config);
|
||||||
esp_eth_config_t config = ETH_DEFAULT_CONFIG(mac, phy);
|
esp_eth_config_t config = ETH_DEFAULT_CONFIG(mac, phy);
|
||||||
|
|
|
@ -8,6 +8,7 @@ PROVIDE ( esp_rom_spiflash_erase_area = 0x400631ac );
|
||||||
PROVIDE ( esp_rom_spiflash_erase_block = 0x40062c4c );
|
PROVIDE ( esp_rom_spiflash_erase_block = 0x40062c4c );
|
||||||
PROVIDE ( esp_rom_spiflash_erase_chip = 0x40062c14 );
|
PROVIDE ( esp_rom_spiflash_erase_chip = 0x40062c14 );
|
||||||
PROVIDE ( esp_rom_spiflash_erase_sector = 0x40062ccc );
|
PROVIDE ( esp_rom_spiflash_erase_sector = 0x40062ccc );
|
||||||
|
PROVIDE ( esp_rom_spiflash_attach = 0x40062a6c );
|
||||||
PROVIDE ( esp_rom_spiflash_lock = 0x400628f0 );
|
PROVIDE ( esp_rom_spiflash_lock = 0x400628f0 );
|
||||||
PROVIDE ( esp_rom_spiflash_read = 0x40062ed8 );
|
PROVIDE ( esp_rom_spiflash_read = 0x40062ed8 );
|
||||||
PROVIDE ( esp_rom_spiflash_config_readmode = 0x40062b64 ); /* SPIMasterReadModeCnfig */
|
PROVIDE ( esp_rom_spiflash_config_readmode = 0x40062b64 ); /* SPIMasterReadModeCnfig */
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
|
|
||||||
menu Wi-Fi
|
menu "Wi-Fi"
|
||||||
|
|
||||||
config ESP32_WIFI_SW_COEXIST_ENABLE
|
config ESP32_WIFI_SW_COEXIST_ENABLE
|
||||||
bool "Software controls WiFi/Bluetooth coexistence"
|
bool "Software controls WiFi/Bluetooth coexistence"
|
||||||
|
@ -240,7 +240,7 @@ menu Wi-Fi
|
||||||
choice ESP32_WIFI_DEBUG_LOG_LEVEL
|
choice ESP32_WIFI_DEBUG_LOG_LEVEL
|
||||||
depends on ESP32_WIFI_DEBUG_LOG_ENABLE
|
depends on ESP32_WIFI_DEBUG_LOG_ENABLE
|
||||||
prompt "WiFi debug log level"
|
prompt "WiFi debug log level"
|
||||||
default ESP32_WIFI_LOG_DEBUG
|
default ESP32_WIFI_DEBUG_LOG_DEBUG
|
||||||
help
|
help
|
||||||
The WiFi log is divided into the following levels: ERROR,WARNING,INFO,DEBUG,VERBOSE.
|
The WiFi log is divided into the following levels: ERROR,WARNING,INFO,DEBUG,VERBOSE.
|
||||||
The ERROR,WARNING,INFO levels are enabled by default, and the DEBUG,VERBOSE levels can be enabled here.
|
The ERROR,WARNING,INFO levels are enabled by default, and the DEBUG,VERBOSE levels can be enabled here.
|
||||||
|
@ -318,7 +318,7 @@ menu Wi-Fi
|
||||||
|
|
||||||
endmenu # Wi-Fi
|
endmenu # Wi-Fi
|
||||||
|
|
||||||
menu PHY
|
menu "PHY"
|
||||||
|
|
||||||
config ESP32_PHY_CALIBRATION_AND_DATA_STORAGE
|
config ESP32_PHY_CALIBRATION_AND_DATA_STORAGE
|
||||||
# ToDo: remove once NVS and PHY partial calibration are supported
|
# ToDo: remove once NVS and PHY partial calibration are supported
|
||||||
|
|
|
@ -79,6 +79,12 @@ esp_err_t coex_preference_set(coex_prefer_t prefer);
|
||||||
*/
|
*/
|
||||||
uint32_t coex_status_get(void);
|
uint32_t coex_status_get(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set software coexist condition.
|
||||||
|
* @return : software coexist condition
|
||||||
|
*/
|
||||||
|
void coex_condition_set(uint32_t type, bool dissatisfy);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief WiFi requests coexistence.
|
* @brief WiFi requests coexistence.
|
||||||
*
|
*
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define ESP_WIFI_OS_ADAPTER_VERSION 0x00000003
|
#define ESP_WIFI_OS_ADAPTER_VERSION 0x00000004
|
||||||
#define ESP_WIFI_OS_ADAPTER_MAGIC 0xDEADBEAF
|
#define ESP_WIFI_OS_ADAPTER_MAGIC 0xDEADBEAF
|
||||||
|
|
||||||
#define OSI_FUNCS_TIME_BLOCKING 0xffffffff
|
#define OSI_FUNCS_TIME_BLOCKING 0xffffffff
|
||||||
|
@ -123,6 +123,7 @@ typedef struct {
|
||||||
int32_t (* _modem_sleep_register)(uint32_t module);
|
int32_t (* _modem_sleep_register)(uint32_t module);
|
||||||
int32_t (* _modem_sleep_deregister)(uint32_t module);
|
int32_t (* _modem_sleep_deregister)(uint32_t module);
|
||||||
uint32_t (* _coex_status_get)(void);
|
uint32_t (* _coex_status_get)(void);
|
||||||
|
void (* _coex_condition_set)(uint32_t type, bool dissatisfy);
|
||||||
int32_t (* _coex_wifi_request)(uint32_t event, uint32_t latency, uint32_t duration);
|
int32_t (* _coex_wifi_request)(uint32_t event, uint32_t latency, uint32_t duration);
|
||||||
int32_t (* _coex_wifi_release)(uint32_t event);
|
int32_t (* _coex_wifi_release)(uint32_t event);
|
||||||
int32_t _magic;
|
int32_t _magic;
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit 3ea3a8f30c6cd5b29ccfb8b9b74d3e6741bdc1c2
|
Subproject commit 1266a879ba57e17c3d55a247b2a95bb9c4217505
|
|
@ -85,7 +85,7 @@ static void sc_ack_send_task(void *pvParameters)
|
||||||
|
|
||||||
bzero(&server_addr, sizeof(struct sockaddr_in));
|
bzero(&server_addr, sizeof(struct sockaddr_in));
|
||||||
server_addr.sin_family = AF_INET;
|
server_addr.sin_family = AF_INET;
|
||||||
server_addr.sin_addr.s_addr = inet_addr((const char*)remote_ip);
|
memcpy(&server_addr.sin_addr.s_addr, remote_ip, sizeof(remote_ip));
|
||||||
server_addr.sin_port = htons(remote_port);
|
server_addr.sin_port = htons(remote_port);
|
||||||
|
|
||||||
esp_wifi_get_mac(WIFI_IF_STA, ack->ctx.mac);
|
esp_wifi_get_mac(WIFI_IF_STA, ack->ctx.mac);
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
idf_component_register(REQUIRES bootloader)
|
idf_component_register(REQUIRES bootloader)
|
||||||
|
|
||||||
if(NOT BOOTLOADER_BUILD)
|
if(NOT BOOTLOADER_BUILD AND CONFIG_APP_BUILD_GENERATE_BINARIES)
|
||||||
string(REPLACE ";" " " ESPTOOLPY_FLASH_PROJECT_OPTIONS "${ESPTOOLPY_FLASH_OPTIONS}")
|
string(REPLACE ";" " " ESPTOOLPY_FLASH_PROJECT_OPTIONS "${ESPTOOLPY_FLASH_OPTIONS}")
|
||||||
set(ESPTOOLPY_FLASH_PROJECT_OPTIONS
|
set(ESPTOOLPY_FLASH_PROJECT_OPTIONS
|
||||||
"${ESPTOOLPY_FLASH_PROJECT_OPTIONS}"
|
"${ESPTOOLPY_FLASH_PROJECT_OPTIONS}"
|
||||||
|
|
|
@ -68,7 +68,11 @@ endif
|
||||||
APP_BIN_UNSIGNED ?= $(APP_BIN)
|
APP_BIN_UNSIGNED ?= $(APP_BIN)
|
||||||
|
|
||||||
$(APP_BIN_UNSIGNED): $(APP_ELF) $(ESPTOOLPY_SRC) | check_python_dependencies
|
$(APP_BIN_UNSIGNED): $(APP_ELF) $(ESPTOOLPY_SRC) | check_python_dependencies
|
||||||
|
ifeq ("$(CONFIG_APP_BUILD_GENERATE_BINARIES)","y")
|
||||||
$(ESPTOOLPY) elf2image $(ESPTOOL_FLASH_OPTIONS) $(ESPTOOL_ELF2IMAGE_OPTIONS) -o $@ $<
|
$(ESPTOOLPY) elf2image $(ESPTOOL_FLASH_OPTIONS) $(ESPTOOL_ELF2IMAGE_OPTIONS) -o $@ $<
|
||||||
|
else
|
||||||
|
@echo "Skipping the BIN generation"
|
||||||
|
endif
|
||||||
|
|
||||||
ifdef CONFIG_SECURE_FLASH_ENCRYPTION_MODE_DEVELOPMENT
|
ifdef CONFIG_SECURE_FLASH_ENCRYPTION_MODE_DEVELOPMENT
|
||||||
encrypted-flash: all_binaries $(ESPTOOLPY_SRC) $(call prereq_if_explicit,erase_flash) partition_table_get_info | check_python_dependencies
|
encrypted-flash: all_binaries $(ESPTOOLPY_SRC) $(call prereq_if_explicit,erase_flash) partition_table_get_info | check_python_dependencies
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit ecc72c54037eeae9b95e442246b8a92696518a3b
|
Subproject commit 6d0d2c8df7fa598c5b42daf94e41fd2783f88730
|
|
@ -78,7 +78,8 @@ set(PROJECT_BIN "${elf_name}.bin")
|
||||||
#
|
#
|
||||||
# Add 'app.bin' target - generates with elf2image
|
# Add 'app.bin' target - generates with elf2image
|
||||||
#
|
#
|
||||||
add_custom_command(OUTPUT "${build_dir}/.bin_timestamp"
|
if(CONFIG_APP_BUILD_GENERATE_BINARIES)
|
||||||
|
add_custom_command(OUTPUT "${build_dir}/.bin_timestamp"
|
||||||
COMMAND ${ESPTOOLPY} elf2image ${ESPTOOLPY_FLASH_OPTIONS} ${ESPTOOLPY_ELF2IMAGE_OPTIONS}
|
COMMAND ${ESPTOOLPY} elf2image ${ESPTOOLPY_FLASH_OPTIONS} ${ESPTOOLPY_ELF2IMAGE_OPTIONS}
|
||||||
-o "${build_dir}/${unsigned_project_binary}" "${elf}"
|
-o "${build_dir}/${unsigned_project_binary}" "${elf}"
|
||||||
COMMAND ${CMAKE_COMMAND} -E echo "Generated ${build_dir}/${unsigned_project_binary}"
|
COMMAND ${CMAKE_COMMAND} -E echo "Generated ${build_dir}/${unsigned_project_binary}"
|
||||||
|
@ -88,14 +89,17 @@ add_custom_command(OUTPUT "${build_dir}/.bin_timestamp"
|
||||||
WORKING_DIRECTORY ${build_dir}
|
WORKING_DIRECTORY ${build_dir}
|
||||||
COMMENT "Generating binary image from built executable"
|
COMMENT "Generating binary image from built executable"
|
||||||
)
|
)
|
||||||
add_custom_target(gen_project_binary DEPENDS "${build_dir}/.bin_timestamp")
|
add_custom_target(gen_project_binary DEPENDS "${build_dir}/.bin_timestamp")
|
||||||
|
endif()
|
||||||
|
|
||||||
set_property(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
|
set_property(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
|
||||||
APPEND PROPERTY ADDITIONAL_MAKE_CLEAN_FILES
|
APPEND PROPERTY ADDITIONAL_MAKE_CLEAN_FILES
|
||||||
"${build_dir}/${unsigned_project_binary}"
|
"${build_dir}/${unsigned_project_binary}"
|
||||||
)
|
)
|
||||||
|
|
||||||
add_custom_target(app ALL DEPENDS gen_project_binary)
|
if(CONFIG_APP_BUILD_GENERATE_BINARIES)
|
||||||
|
add_custom_target(app ALL DEPENDS gen_project_binary)
|
||||||
|
endif()
|
||||||
|
|
||||||
if(NOT BOOTLOADER_BUILD AND CONFIG_SECURE_SIGNED_APPS)
|
if(NOT BOOTLOADER_BUILD AND CONFIG_SECURE_SIGNED_APPS)
|
||||||
if(CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES)
|
if(CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES)
|
||||||
|
|
|
@ -20,7 +20,7 @@ menu "FreeRTOS"
|
||||||
|
|
||||||
choice FREERTOS_CORETIMER
|
choice FREERTOS_CORETIMER
|
||||||
prompt "Xtensa timer to use as the FreeRTOS tick source"
|
prompt "Xtensa timer to use as the FreeRTOS tick source"
|
||||||
default CONFIG_FREERTOS_CORETIMER_0
|
default FREERTOS_CORETIMER_0
|
||||||
help
|
help
|
||||||
FreeRTOS needs a timer with an associated interrupt to use as
|
FreeRTOS needs a timer with an associated interrupt to use as
|
||||||
the main tick source to increase counters, run timers and do
|
the main tick source to increase counters, run timers and do
|
||||||
|
|
|
@ -116,6 +116,19 @@ menu "mbedTLS"
|
||||||
default 3 if MBEDTLS_DEBUG_LEVEL_DEBUG
|
default 3 if MBEDTLS_DEBUG_LEVEL_DEBUG
|
||||||
default 4 if MBEDTLS_DEBUG_LEVEL_VERBOSE
|
default 4 if MBEDTLS_DEBUG_LEVEL_VERBOSE
|
||||||
|
|
||||||
|
config MBEDTLS_ECP_RESTARTABLE
|
||||||
|
bool "Enable mbedTLS ecp restartable"
|
||||||
|
default n
|
||||||
|
help
|
||||||
|
Enable "non-blocking" ECC operations that can return early and be resumed.
|
||||||
|
|
||||||
|
config MBEDTLS_CMAC_C
|
||||||
|
bool "Enable CMAC mode for block ciphers"
|
||||||
|
default n
|
||||||
|
help
|
||||||
|
Enable the CMAC (Cipher-based Message Authentication Code) mode for
|
||||||
|
block ciphers.
|
||||||
|
|
||||||
config MBEDTLS_HARDWARE_AES
|
config MBEDTLS_HARDWARE_AES
|
||||||
bool "Enable hardware AES acceleration"
|
bool "Enable hardware AES acceleration"
|
||||||
depends on IDF_TARGET_ESP32
|
depends on IDF_TARGET_ESP32
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit 97959e77912524bd8db7cbb2e00fc9f6189f7a82
|
Subproject commit f5f2e5926cd294ae7cb579ff6a12ad9303caeb6e
|
|
@ -253,6 +253,47 @@
|
||||||
#define MBEDTLS_REMOVE_ARC4_CIPHERSUITES
|
#define MBEDTLS_REMOVE_ARC4_CIPHERSUITES
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \def MBEDTLS_ECP_RESTARTABLE
|
||||||
|
*
|
||||||
|
* Enable "non-blocking" ECC operations that can return early and be resumed.
|
||||||
|
*
|
||||||
|
* This allows various functions to pause by returning
|
||||||
|
* #MBEDTLS_ERR_ECP_IN_PROGRESS (or, for functions in the SSL module,
|
||||||
|
* #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS) and then be called later again in
|
||||||
|
* order to further progress and eventually complete their operation. This is
|
||||||
|
* controlled through mbedtls_ecp_set_max_ops() which limits the maximum
|
||||||
|
* number of ECC operations a function may perform before pausing; see
|
||||||
|
* mbedtls_ecp_set_max_ops() for more information.
|
||||||
|
*
|
||||||
|
* This is useful in non-threaded environments if you want to avoid blocking
|
||||||
|
* for too long on ECC (and, hence, X.509 or SSL/TLS) operations.
|
||||||
|
*
|
||||||
|
* Uncomment this macro to enable restartable ECC computations.
|
||||||
|
*
|
||||||
|
* \note This option only works with the default software implementation of
|
||||||
|
* elliptic curve functionality. It is incompatible with
|
||||||
|
* MBEDTLS_ECP_ALT, MBEDTLS_ECDH_XXX_ALT and MBEDTLS_ECDSA_XXX_ALT.
|
||||||
|
*/
|
||||||
|
#ifdef CONFIG_MBEDTLS_ECP_RESTARTABLE
|
||||||
|
#define MBEDTLS_ECP_RESTARTABLE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \def MBEDTLS_CMAC_C
|
||||||
|
*
|
||||||
|
* Enable the CMAC (Cipher-based Message Authentication Code) mode for block
|
||||||
|
* ciphers.
|
||||||
|
*
|
||||||
|
* Module: library/cmac.c
|
||||||
|
*
|
||||||
|
* Requires: MBEDTLS_AES_C or MBEDTLS_DES_C
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#ifdef CONFIG_MBEDTLS_CMAC_C
|
||||||
|
#define MBEDTLS_CMAC_C
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \def MBEDTLS_ECP_DP_SECP192R1_ENABLED
|
* \def MBEDTLS_ECP_DP_SECP192R1_ENABLED
|
||||||
*
|
*
|
||||||
|
|
|
@ -24,6 +24,7 @@ set(srcs
|
||||||
"port/http_parser.c")
|
"port/http_parser.c")
|
||||||
|
|
||||||
idf_component_register(SRCS "${srcs}"
|
idf_component_register(SRCS "${srcs}"
|
||||||
INCLUDE_DIRS port/include nghttp2/lib/includes)
|
INCLUDE_DIRS port/include nghttp2/lib/includes
|
||||||
|
PRIV_INCLUDE_DIRS private_include)
|
||||||
|
|
||||||
target_compile_definitions(${COMPONENT_LIB} PUBLIC "-DHAVE_CONFIG_H")
|
target_compile_definitions(${COMPONENT_LIB} PUBLIC "-DHAVE_CONFIG_H")
|
||||||
|
|
|
@ -4,6 +4,8 @@
|
||||||
|
|
||||||
COMPONENT_ADD_INCLUDEDIRS := port/include nghttp2/lib/includes
|
COMPONENT_ADD_INCLUDEDIRS := port/include nghttp2/lib/includes
|
||||||
|
|
||||||
|
COMPONENT_PRIV_INCLUDEDIRS := private_include
|
||||||
|
|
||||||
COMPONENT_SRCDIRS := nghttp2/lib port
|
COMPONENT_SRCDIRS := nghttp2/lib port
|
||||||
|
|
||||||
COMPONENT_SUBMODULES := nghttp2
|
COMPONENT_SUBMODULES := nghttp2
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
menu NVS
|
menu "NVS"
|
||||||
|
|
||||||
config NVS_ENCRYPTION
|
config NVS_ENCRYPTION
|
||||||
bool "Enable NVS encryption"
|
bool "Enable NVS encryption"
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
Non-volatile storage library
|
Non-volatile storage library
|
||||||
============================
|
============================
|
||||||
|
|
||||||
|
:link_to_translation:`zh_CN:[中文]`
|
||||||
|
|
||||||
Introduction
|
Introduction
|
||||||
------------
|
------------
|
||||||
|
|
||||||
|
|
303
components/nvs_flash/README_CN.rst
Normal file
303
components/nvs_flash/README_CN.rst
Normal file
|
@ -0,0 +1,303 @@
|
||||||
|
非易失性存储库
|
||||||
|
============================
|
||||||
|
|
||||||
|
:link_to_translation:`en:[English]`
|
||||||
|
|
||||||
|
简介
|
||||||
|
------------
|
||||||
|
|
||||||
|
非易失性存储 (NVS) 库主要用于在 flash 中存储键值格式的数据。本文档将详细介绍 NVS 常用的一些概念。
|
||||||
|
|
||||||
|
底层存储
|
||||||
|
^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
NVS 通过调用 ``spi_flash_{read|write|erase}`` API 对主 flash 的部分空间进行读、写、擦除操作,包括 ``data`` 类型和 ``nvs`` 子类型的所有分区。应用程序可调用 ``nvs_open`` API 选择使用带有 ``nvs`` 标签的分区,也可以通过调用 ``nvs_open_from_part`` API 选择使用指定名称的任意分区。
|
||||||
|
|
||||||
|
NVS 库后续版本可能会增加其他存储器后端,实现将数据保存至其他 flash 芯片(SPI 或 I2C 接口)、RTC 或 FRAM 中。
|
||||||
|
|
||||||
|
.. note:: 如果 NVS 分区被截断(例如,更改分区表布局时),则应擦除分区内容。可以使用 ESP-IDF 构建系统中的 ``idf.py erase_flash`` 命令擦除 flash 上的所有内容。
|
||||||
|
|
||||||
|
.. note:: NVS 最适合存储一些较小的数据,而非字符串或二进制大对象 (BLOB) 等较大的数据。如需存储较大的 BLOB 或者字符串,请考虑使用基于磨损均衡库的 FAT 文件系统。
|
||||||
|
|
||||||
|
|
||||||
|
键值对
|
||||||
|
^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
NVS 的操作对象为键值对,其中键是 ASCII 字符串,当前支持最大键长为 15 个字符,值可以为以下几种类型:
|
||||||
|
|
||||||
|
- 整数型:``uint8_t``、``int8_t``、``uint16_t``、``int16_t``、``uint32_t``、``int32_t``、``uint64_t`` 和 ``int64_t``;
|
||||||
|
- 以 ``\0`` 结尾的字符串;
|
||||||
|
- 可变长度的二进制数据 (BLOB)
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
字符串值当前上限为 4000 字节,其中包括空终止符。BLOB 值上限为 508,000 字节或分区大小减去 4000 字节的 97.6%,以较低值为准。
|
||||||
|
|
||||||
|
后续可能会增加对 ``float`` 和 ``double`` 等其他类型数据的支持。
|
||||||
|
|
||||||
|
键必须唯一。为现有的键写入新的值可能产生如下结果:
|
||||||
|
|
||||||
|
- 如果新旧值数据类型相同,则更新值;
|
||||||
|
- 如果新旧值数据类型不同,则返回错误。
|
||||||
|
|
||||||
|
读取值时也会执行数据类型检查。如果读取操作的数据类型与该值的数据类型不匹配,则返回错误。
|
||||||
|
|
||||||
|
|
||||||
|
命名空间
|
||||||
|
^^^^^^^^^^
|
||||||
|
|
||||||
|
为了减少不同组件之间键名的潜在冲突,NVS 将每个键值对分配给一个命名空间。命名空间的命名规则遵循键名的命名规则,即最多可占 15 个字符。命名空间的名称在调用 ``nvs_open`` 或 ``nvs_open_from_part`` 中指定,调用后将返回一个不透明句柄,用于后续调用 ``nvs_read_*``、``nvs_write_*`` 和 ``nvs_commit`` 函数。这样,一个句柄关联一个命名空间,键名便不会与其他命名空间中相同键名冲突。请注意,不同 NVS 分区中具有相同名称的命名空间将被视为不同的命名空间。
|
||||||
|
|
||||||
|
|
||||||
|
安全性、篡改性及鲁棒性
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
NVS 与 ESP32 flash 加密系统不直接兼容。但如果 NVS 加密与 ESP32 flash 加密一起使用时,数据仍可以加密形式存储。更多详情请参阅 :ref:`nvs_encryption`。
|
||||||
|
|
||||||
|
如果未启用 NVS 加密,任何对 flash 芯片有物理访问权限的人都可以修改、擦除或添加键值对。NVS 加密启用后,如果不知道相应的 NVS 加密密钥,则无法修改或添加键值对并将其识别为有效键值。但是,针对擦除操作没有相应的防篡改功能。
|
||||||
|
|
||||||
|
当 flash 处于不一致状态时,NVS 库会尝试恢复。在任何时间点关闭设备电源,然后重新打开电源,不会导致数据丢失;但如果关闭设备电源时正在写入新的键值对,这一键值对可能会丢失。该库还应当能对 flash 中的任意数据进行正确初始化。
|
||||||
|
|
||||||
|
|
||||||
|
内部实现
|
||||||
|
---------
|
||||||
|
|
||||||
|
键值对日志
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
NVS 按顺序存储键值对,新的键值对添加在最后。因此,如需更新某一键值对,实际是在日志最后增加一对新的键值对,同时将旧的键值对标记为已擦除。
|
||||||
|
|
||||||
|
页面和条目
|
||||||
|
^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
NVS 库在其操作中主要使用两个实体:页面和条目。页面是一个逻辑结构,用于存储部分的整体日志。逻辑页面对应 flash 的一个物理扇区,正在使用中的页面具有与之相关联的序列号。序列号赋予了页面顺序,较高的序列号对应较晚创建的页面。页面有以下几种状态:
|
||||||
|
|
||||||
|
空或未初始化
|
||||||
|
页面对应的 flash 扇区为空白状态(所有字节均为 ``0xff``)。此时,页面未存储任何数据且没有关联的序列号。
|
||||||
|
|
||||||
|
活跃状态
|
||||||
|
此时 flash 已完成初始化,页头部写入 flash,页面已具备有效序列号。页面中存在一些空条目,可写入数据。任意时刻,至多有一个页面处于活跃状态。
|
||||||
|
|
||||||
|
写满状态
|
||||||
|
Flash 已写满键值对,状态不再改变。用户无法向写满状态下的页面写入新键值对,但仍可将一些键值对标记为已擦除。
|
||||||
|
|
||||||
|
擦除状态
|
||||||
|
未擦除的键值对将移至其他页面,以便擦除当前页面。这一状态仅为暂时性状态,即 API 调用返回时,页面应脱离这一状态。如果设备突然断电,下次开机时,设备将继续把未擦除的键值对移至其他页面,并继续擦除当前页面。
|
||||||
|
|
||||||
|
损坏状态
|
||||||
|
页头部包含无效数据,无法进一步解析该页面中的数据,因此之前写入该页面的所有条目均无法访问。相应的 flash 扇区并不会被立即擦除,而是与其他处于未初始化状态的扇区一起等待后续使用。这一状态可能对调试有用。
|
||||||
|
|
||||||
|
Flash 扇区映射至逻辑页面并没有特定的顺序,NVS 库会检查存储在 flash 扇区的页面序列号,并根据序列号组织页面。
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
+--------+ +--------+ +--------+ +--------+
|
||||||
|
| Page 1 | | Page 2 | | Page 3 | | Page 4 |
|
||||||
|
| Full +---> | Full +---> | Active | | Empty | <- 状态
|
||||||
|
| #11 | | #12 | | #14 | | | <- 序列号
|
||||||
|
+---+----+ +----+---+ +----+---+ +---+----+
|
||||||
|
| | | |
|
||||||
|
| | | |
|
||||||
|
| | | |
|
||||||
|
+---v------+ +-----v----+ +------v---+ +------v---+
|
||||||
|
| Sector 3 | | Sector 0 | | Sector 2 | | Sector 1 | <- 物理扇区
|
||||||
|
+----------+ +----------+ +----------+ +----------+
|
||||||
|
|
||||||
|
页面结构
|
||||||
|
^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
当前,我们假设 flash 扇区大小为 4096 字节,并且 ESP32 flash 加密硬件在 32 字节块上运行。未来有可能引入一些编译时可配置项(可通过 menuconfig 进行配置),以适配具有不同扇区大小的 flash 芯片。但目前尚不清楚 SPI flash 驱动和 SPI flash cache 之类的系统组件是否支持其他扇区大小。
|
||||||
|
|
||||||
|
页面由头部、条目状态位图和条目三部分组成。为了实现与 ESP32 flash 加密功能兼容,条目大小设置为 32 字节。如果键值为整数型,条目则保存一个键值对;如果键值为字符串或 BLOB 类型,则条目仅保存一个键值对的部分内容(更多信息详见条目结构描述)。
|
||||||
|
|
||||||
|
页面结构如下图所示,括号内数字表示该部分的大小(以字节为单位)::
|
||||||
|
|
||||||
|
+-----------+--------------+-------------+-------------------------+
|
||||||
|
| State (4) | Seq. no. (4) | version (1) | Unused (19) | CRC32 (4) | 页头部 (32)
|
||||||
|
+-----------+--------------+-------------+-------------------------+
|
||||||
|
| Entry state bitmap (32) |
|
||||||
|
+------------------------------------------------------------------+
|
||||||
|
| Entry 0 (32) |
|
||||||
|
+------------------------------------------------------------------+
|
||||||
|
| Entry 1 (32) |
|
||||||
|
+------------------------------------------------------------------+
|
||||||
|
/ /
|
||||||
|
/ /
|
||||||
|
+------------------------------------------------------------------+
|
||||||
|
| Entry 125 (32) |
|
||||||
|
+------------------------------------------------------------------+
|
||||||
|
|
||||||
|
头部和条目状态位图写入 flash 时不加密。如果启用了 ESP32 flash 加密功能,则条目写入 flash 时将会加密。
|
||||||
|
|
||||||
|
通过将 0 写入某些位可以定义页面状态值,表示状态改变。因此,如果需要变更页面状态,并不一定要擦除页面,除非要将其变更为擦除状态。
|
||||||
|
|
||||||
|
头部中的 ``version`` 字段反映了所用的 NVS 格式版本。为实现向后兼容,版本升级从 0xff 开始依次递减(例如,version-1 为 0xff,version-2 为 0xfe 等)。
|
||||||
|
|
||||||
|
头部中 CRC32 值是由不包含状态值的条目计算所得(4 到 28 字节)。当前未使用的条目用 ``0xff`` 字节填充。
|
||||||
|
|
||||||
|
条目结构和条目状态位图详细信息见下文描述。
|
||||||
|
|
||||||
|
条目和条目状态位图
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
每个条目可处于以下三种状态之一,每个状态在条目状态位图中用两位表示。位图中的最后四位 (256 - 2 * 126) 未使用。
|
||||||
|
|
||||||
|
空 (2'b11)
|
||||||
|
条目还未写入任何内容,处于未初始化状态(全部字节为 ``0xff``)。
|
||||||
|
|
||||||
|
写入(2'b10)
|
||||||
|
一个键值对(或跨多个条目的键值对的部分内容)已写入条目中。
|
||||||
|
|
||||||
|
擦除(2'b00)
|
||||||
|
条目中的键值对已丢弃,条目内容不再解析。
|
||||||
|
|
||||||
|
.. _structure_of_entry:
|
||||||
|
|
||||||
|
条目结构
|
||||||
|
^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
如果键值类型为基础类型,即 1 - 8 个字节长度的整数型,条目将保存一个键值对;如果键值类型为字符串或 BLOB 类型,条目将保存整个键值对的部分内容。另外,如果键值为字符串类型且跨多个条目,则键值所跨的所有条目均保存在同一页面。BLOB 则可以切分为多个块,实现跨多个页面。BLOB 索引是一个附加的固定长度元数据条目,用于追踪 BLOB 块。目前条目仍支持早期 BLOB 格式(可读取可修改),但这些 BLOB 一经修改,即以新格式储存至条目。
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
+--------+----------+----------+----------------+-----------+---------------+----------+
|
||||||
|
| NS (1) | Type (1) | Span (1) | ChunkIndex (1) | CRC32 (4) | Key (16) | Data (8) |
|
||||||
|
+--------+----------+----------+----------------+-----------+---------------+----------+
|
||||||
|
|
||||||
|
Primitive +--------------------------------+
|
||||||
|
+--------> | Data (8) |
|
||||||
|
| Types +--------------------------------+
|
||||||
|
+-> Fixed length --
|
||||||
|
| | +---------+--------------+---------------+-------+
|
||||||
|
| +--------> | Size(4) | ChunkCount(1)| ChunkStart(1) | Rsv(2)|
|
||||||
|
Data format ---+ BLOB Index +---------+--------------+---------------+-------+
|
||||||
|
|
|
||||||
|
| +----------+---------+-----------+
|
||||||
|
+-> Variable length --> | Size (2) | Rsv (2) | CRC32 (4) |
|
||||||
|
(Strings, BLOB Data) +----------+---------+-----------+
|
||||||
|
|
||||||
|
|
||||||
|
条目结构中各个字段含义如下:
|
||||||
|
|
||||||
|
命名空间 (NS, NameSpace)
|
||||||
|
该条目的命名空间索引,详细信息见命名空间实现章节。
|
||||||
|
|
||||||
|
类型 (Type)
|
||||||
|
一个字节表示的值的数据类型,可能的类型见 ``nvs_types.h`` 中 ``ItemType`` 枚举。
|
||||||
|
|
||||||
|
跨度 (Span)
|
||||||
|
该键值对所用的条目数量。如果键值为整数型,条目数量即为 1。如果键值为字符串或 BLOB,则条目数量取决于值的长度。
|
||||||
|
|
||||||
|
块索引 (ChunkIndex)
|
||||||
|
用于存储 BLOB 类型数据块的索引。如果键值为其他数据类型,则此处索引应写入 ``0xff``。
|
||||||
|
|
||||||
|
CRC32
|
||||||
|
对条目下所有字节进行校验,所得的校验和(CRC32 字段不计算在内)。
|
||||||
|
|
||||||
|
键 (Key)
|
||||||
|
即以零结尾的 ASCII 字符串,字符串最长为 15 字节,不包含最后一个字节的 NULL (``\0``) 终止符。
|
||||||
|
|
||||||
|
数据 (Data)
|
||||||
|
如果键值类型为整数型,则数据字段仅包含键值。如果键值小于八个字节,使用 ``0xff`` 填充未使用的部分(右侧)。
|
||||||
|
|
||||||
|
如果键值类型为 BLOB 索引条目,则该字段的八个字节将保存以下数据块信息:
|
||||||
|
|
||||||
|
- 块大小
|
||||||
|
整个 BLOB 数据的大小(以字节为单位)。该字段仅用于 BLOB 索引类型条目。
|
||||||
|
|
||||||
|
- ChunkCount
|
||||||
|
存储过程中 BLOB 分成的数据块数量。该字段仅用于 BLOB 索引类型条目。
|
||||||
|
|
||||||
|
- ChunkStart
|
||||||
|
BLOB 第一个数据块的块索引,后续数据块索引依次递增,步长为 1。该字段仅用于 BLOB 索引类型条目。
|
||||||
|
|
||||||
|
如果键值类型为字符串或 BLOB 数据块,数据字段的这八个字节将保存该键值的一些附加信息,如下所示:
|
||||||
|
|
||||||
|
- 数据大小
|
||||||
|
实际数据的大小(以字节为单位)。如果键值类型为字符串,此字段也应将零终止符包含在内。此字段仅用于字符串和 BLOB 类型条目。
|
||||||
|
|
||||||
|
- CRC32
|
||||||
|
数据所有字节的校验和,该字段仅用于字符串和 BLOB 类型条目。
|
||||||
|
|
||||||
|
可变长度值(字符串和 BLOB)写入后续条目,每个条目 32 字节。第一个条目的 span 字段将指明使用了多少条目。
|
||||||
|
|
||||||
|
命名空间
|
||||||
|
^^^^^^^^^^
|
||||||
|
|
||||||
|
如上所述,每个键值对属于一个命名空间。命名空间标识符(字符串)也作为键值对的键,存储在索引为 0 的命名空间中。与这些键对应的值就是这些命名空间的索引。
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
+-------------------------------------------+
|
||||||
|
| NS=0 Type=uint8_t Key="wifi" Value=1 | Entry describing namespace "wifi"
|
||||||
|
+-------------------------------------------+
|
||||||
|
| NS=1 Type=uint32_t Key="channel" Value=6 | Key "channel" in namespace "wifi"
|
||||||
|
+-------------------------------------------+
|
||||||
|
| NS=0 Type=uint8_t Key="pwm" Value=2 | Entry describing namespace "pwm"
|
||||||
|
+-------------------------------------------+
|
||||||
|
| NS=2 Type=uint16_t Key="channel" Value=20 | Key "channel" in namespace "pwm"
|
||||||
|
+-------------------------------------------+
|
||||||
|
|
||||||
|
|
||||||
|
条目哈希列表
|
||||||
|
^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
为了减少对 flash 执行的读操作次数,Page 类对象均设有一个列表,包含一对数据:条目索引和条目哈希值。该列表可大大提高检索速度,而无需迭代所有条目并逐个从 flash 中读取。``Page::findItem`` 首先从哈希列表中检索条目哈希值,如果条目存在,则在页面内给出条目索引。由于哈希冲突,在哈希列表中检索条目哈希值可能会得到不同的条目,对 flash 中条目再次迭代可解决这一冲突。
|
||||||
|
|
||||||
|
哈希列表中每个节点均包含一个 24 位哈希值和 8 位条目索引。哈希值根据条目命名空间、键名和块索引由 CRC32 计算所得,计算结果保留 24 位。为减少将 32 位条目存储在链表中的开销,链表采用了数组的双向链表。每个数组占用 128 个字节,包含 29 个条目、两个链表指针和一个 32 位计数字段。因此,每页额外需要的 RAM 最少为 128 字节,最多为 640 字节。
|
||||||
|
|
||||||
|
.. _nvs_encryption:
|
||||||
|
|
||||||
|
NVS 加密
|
||||||
|
--------------
|
||||||
|
|
||||||
|
NVS 分区内存储的数据可使用 AES-XTS 进行加密,类似于 IEEE P1619 磁盘加密标准中提到的加密方式。为了实现加密,每个条目被均视为一个扇区,并将条目相对地址(相对于分区开头)传递给加密算法,用作扇区号。NVS 加密所需的密钥存储于其他分区,并进行了 :doc:`flash 加密 <../../security/flash-encryption>`。因此,在使用 NVS 加密前应先启用 :doc:`flash 加密 <../../security/flash-encryption>`。
|
||||||
|
|
||||||
|
.. _nvs_key_partition:
|
||||||
|
|
||||||
|
NVS 密钥分区
|
||||||
|
^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
应用程序如果想使用 NVS 加密,则需要编译进一个类型为 ``data``,子类型为 ``key`` 的密钥分区。该分区应标记为已加密,且最小为 4096 字节,具体结构见下表。如需了解更多详细信息,请参考 :doc:`分区表 <../../api-guides/partition-tables>`。
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
+-----------+--------------+-------------+----+
|
||||||
|
| XTS encryption key(32) |
|
||||||
|
+---------------------------------------------+
|
||||||
|
| XTS tweak key (32) |
|
||||||
|
+---------------------------------------------+
|
||||||
|
| CRC32(4) |
|
||||||
|
+---------------------------------------------+
|
||||||
|
|
||||||
|
使用 NVS 分区生成程序生成上述分区表,并烧录至设备。由于分区已标记为已加密,而且启用了 :doc:`flash 加密 <../../security/flash-encryption>`,引导程序在首次启动时将使用 flash 加密对密钥分区进行加密。您也可以在设备启动后调用 ``nvs_flash.h`` 提供的 ``nvs_flash_generate_keys`` API 生成加密密钥,然后再将密钥以加密形式写入密钥分区。
|
||||||
|
|
||||||
|
应用程序可以使用不同的密钥对不同的 NVS 分区进行加密,这样就会需要多个加密密钥分区。应用程序应为加解密操作提供正确的密钥或密钥分区。
|
||||||
|
|
||||||
|
加密读取/写入
|
||||||
|
^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
``nvs_read_*`` 和 ``nvs_write_*`` 等 NVS API 函数同样可以对 NVS 加密分区执行读写操作。但用于初始化 NVS 非加密分区和加密分区的 API 则有所不同:初始化 NVS 非加密分区可以使用 ``nvs_flash_init`` 和 ``nvs_flash_init_partition``,但初始化 NVS 加密分区则需调用 ``nvs_flash_secure_init`` 和 ``nvs_flash_secure_init_partition``。上述 API 函数所需的 ``nvs_sec_cfg_t`` 结构可使用 ``nvs_flash_generate_keys`` 或者 ``nvs_flash_read_security_cfg`` 进行填充。
|
||||||
|
|
||||||
|
应用程序如需在加密状态下执行 NVS 读写操作,应遵循以下步骤:
|
||||||
|
|
||||||
|
1. 使用 ``esp_partition_find*`` API 查找密钥分区和 NVS 数据分区;
|
||||||
|
2. 使用 ``nvs_flash_read_security_cfg`` 或 ``nvs_flash_generate_keys`` API 填充 ``nvs_sec_cfg_t`` 结构;
|
||||||
|
3. 使用 ``nvs_flash_secure_init`` 或 ``nvs_flash_secure_init_partition`` API 初始化 NVS flash 分区;
|
||||||
|
4. 使用 ``nvs_open`` 或 ``nvs_open_from_part`` API 打开命名空间;
|
||||||
|
5. 使用 ``nvs_read_*`` 或 ``nvs_write_*`` API 执行 NVS 读取/写入操作;
|
||||||
|
6. 使用 ``nvs_flash_deinit`` API 释放已初始化的 NVS 分区。
|
||||||
|
|
||||||
|
NVS 迭代器
|
||||||
|
^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
迭代器允许根据指定的分区名称、命名空间和数据类型轮询 NVS 中存储的键值对。
|
||||||
|
|
||||||
|
您可以使用以下函数,执行相关操作:
|
||||||
|
|
||||||
|
- ``nvs_entry_find``:返回一个不透明句柄,用于后续调用 ``nvs_entry_next`` 和 ``nvs_entry_info`` 函数;
|
||||||
|
- ``nvs_entry_next``:返回指向下一个键值对的迭代器;
|
||||||
|
- ``nvs_entry_info``:返回每个键值对的信息。
|
||||||
|
|
||||||
|
如果未找到符合标准的键值对,``nvs_entry_find`` 和 ``nvs_entry_next`` 将返回 NULL,此时不必释放迭代器。若不再需要迭代器,可使用 ``nvs_release_iterator`` 释放迭代器。
|
||||||
|
|
|
@ -33,7 +33,7 @@ menu "OpenSSL"
|
||||||
|
|
||||||
choice OPENSSL_ASSERT
|
choice OPENSSL_ASSERT
|
||||||
prompt "Select OpenSSL assert function"
|
prompt "Select OpenSSL assert function"
|
||||||
default CONFIG_OPENSSL_ASSERT_EXIT
|
default OPENSSL_ASSERT_EXIT
|
||||||
help
|
help
|
||||||
OpenSSL function needs "assert" function to check if input parameters are valid.
|
OpenSSL function needs "assert" function to check if input parameters are valid.
|
||||||
|
|
||||||
|
|
|
@ -22,17 +22,17 @@ menu "Partition Table"
|
||||||
|
|
||||||
config PARTITION_TABLE_CUSTOM_FILENAME
|
config PARTITION_TABLE_CUSTOM_FILENAME
|
||||||
string "Custom partition CSV file" if PARTITION_TABLE_CUSTOM
|
string "Custom partition CSV file" if PARTITION_TABLE_CUSTOM
|
||||||
default partitions.csv
|
default "partitions.csv"
|
||||||
help
|
help
|
||||||
Name of the custom partition CSV filename. This path is evaluated
|
Name of the custom partition CSV filename. This path is evaluated
|
||||||
relative to the project root directory.
|
relative to the project root directory.
|
||||||
|
|
||||||
config PARTITION_TABLE_FILENAME
|
config PARTITION_TABLE_FILENAME
|
||||||
string
|
string
|
||||||
default partitions_singleapp.csv if PARTITION_TABLE_SINGLE_APP && !ESP32_ENABLE_COREDUMP_TO_FLASH
|
default "partitions_singleapp.csv" if PARTITION_TABLE_SINGLE_APP && !ESP32_ENABLE_COREDUMP_TO_FLASH
|
||||||
default partitions_singleapp_coredump.csv if PARTITION_TABLE_SINGLE_APP && ESP32_ENABLE_COREDUMP_TO_FLASH
|
default "partitions_singleapp_coredump.csv" if PARTITION_TABLE_SINGLE_APP && ESP32_ENABLE_COREDUMP_TO_FLASH
|
||||||
default partitions_two_ota.csv if PARTITION_TABLE_TWO_OTA && !ESP32_ENABLE_COREDUMP_TO_FLASH
|
default "partitions_two_ota.csv" if PARTITION_TABLE_TWO_OTA && !ESP32_ENABLE_COREDUMP_TO_FLASH
|
||||||
default partitions_two_ota_coredump.csv if PARTITION_TABLE_TWO_OTA && ESP32_ENABLE_COREDUMP_TO_FLASH
|
default "partitions_two_ota_coredump.csv" if PARTITION_TABLE_TWO_OTA && ESP32_ENABLE_COREDUMP_TO_FLASH
|
||||||
default PARTITION_TABLE_CUSTOM_FILENAME if PARTITION_TABLE_CUSTOM
|
default PARTITION_TABLE_CUSTOM_FILENAME if PARTITION_TABLE_CUSTOM
|
||||||
|
|
||||||
config PARTITION_TABLE_OFFSET
|
config PARTITION_TABLE_OFFSET
|
||||||
|
|
|
@ -30,7 +30,7 @@ extern soc_reserved_region_t soc_reserved_memory_region_end;
|
||||||
These variables have the start and end of the data and static IRAM
|
These variables have the start and end of the data and static IRAM
|
||||||
area used by the program. Defined in the linker script.
|
area used by the program. Defined in the linker script.
|
||||||
*/
|
*/
|
||||||
extern int _data_start, _static_data_end, _iram_start, _iram_end;
|
extern int _data_start, _heap_start, _iram_start, _iram_end;
|
||||||
|
|
||||||
/* static DRAM & IRAM chunks */
|
/* static DRAM & IRAM chunks */
|
||||||
static const size_t EXTRA_RESERVED_REGIONS = 2;
|
static const size_t EXTRA_RESERVED_REGIONS = 2;
|
||||||
|
@ -68,8 +68,8 @@ static void s_prepare_reserved_regions(soc_reserved_region_t *reserved, size_t c
|
||||||
(count - EXTRA_RESERVED_REGIONS) * sizeof(soc_reserved_region_t));
|
(count - EXTRA_RESERVED_REGIONS) * sizeof(soc_reserved_region_t));
|
||||||
|
|
||||||
/* Add the EXTRA_RESERVED_REGIONS at the beginning */
|
/* Add the EXTRA_RESERVED_REGIONS at the beginning */
|
||||||
reserved[0].start = (intptr_t)&_data_start; /* DRAM used by data+bss */
|
reserved[0].start = (intptr_t)&_data_start; /* DRAM used by data+bss and possibly rodata */
|
||||||
reserved[0].end = (intptr_t)&_static_data_end;
|
reserved[0].end = (intptr_t)&_heap_start;
|
||||||
#if CONFIG_IDF_TARGET_ESP32
|
#if CONFIG_IDF_TARGET_ESP32
|
||||||
//ESP32 has a IRAM-only region 0x4008_0000 - 0x4009_FFFF, protect the used part
|
//ESP32 has a IRAM-only region 0x4008_0000 - 0x4009_FFFF, protect the used part
|
||||||
reserved[1].start = (intptr_t)&_iram_start; /* IRAM used by code */
|
reserved[1].start = (intptr_t)&_iram_start; /* IRAM used by code */
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
SPI Flash API
|
SPI Flash API
|
||||||
=============
|
=============
|
||||||
|
|
||||||
|
:link_to_translation:`zh_CN:[中文]`
|
||||||
|
|
||||||
Overview
|
Overview
|
||||||
--------
|
--------
|
||||||
The spi_flash component contains API functions related to reading, writing,
|
The spi_flash component contains API functions related to reading, writing,
|
||||||
|
|
188
components/spi_flash/README_CN.rst
Normal file
188
components/spi_flash/README_CN.rst
Normal file
|
@ -0,0 +1,188 @@
|
||||||
|
SPI Flash API
|
||||||
|
=================
|
||||||
|
|
||||||
|
:link_to_translation:`en:[English]`
|
||||||
|
|
||||||
|
概述
|
||||||
|
--------
|
||||||
|
|
||||||
|
SPI Flash 组件提供外部 flash 数据读取、写入、擦除和内存映射相关的 API 函数,同时也提供了更高层级的,面向分区的 API 函数(定义在 :doc:`分区表 </api-guides/partition-tables>` 中)。
|
||||||
|
|
||||||
|
与 ESP-IDF V4.0 之前的 API 不同,这一版 API 功能并不局限于主 SPI Flash 芯片(即运行程序的 SPI Flash 芯片)。使用不同的芯片指针,您可以通过 SPI0/1 或 HSPI/VSPI 总线访问外部 flash。
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
ESP-IDF V4.0 之后的 flash API 不再是原子的。因此,如果 flash 操作地址有重叠,且写操作与读操作同时执行,读操作可能会返回一部分写入之前的数据,返回一部分写入之后的数据。
|
||||||
|
|
||||||
|
Kconfig 选项 :ref:`CONFIG_SPI_FLASH_USE_LEGACY_IMPL` 可将 ``spi_flash_*`` 函数切换至 ESP-IDF V4.0 之前的实现。但是,如果同时使用新旧 API,代码量可能会增多。
|
||||||
|
|
||||||
|
即便未启用 :ref:`CONFIG_SPI_FLASH_USE_LEGACY_IMPL`,加密读取和加密写入操作也均使用旧实现。因此,仅有主 flash 芯片支持加密操作,其他不同片选(经 SPI1 访问的 flash 芯片)则不支持加密操作。
|
||||||
|
|
||||||
|
初始化 Flash 设备
|
||||||
|
---------------------------
|
||||||
|
|
||||||
|
在使用 ``esp_flash_*`` API 之前,您需要在 SPI 总线上初始化芯片。
|
||||||
|
|
||||||
|
1. 调用 :cpp:func:`spi_bus_initialize` 初始化 SPI 总线,此函数将初始化总线上设备间共享的资源,如 I/O、DMA 及中断等。
|
||||||
|
|
||||||
|
2. 调用 :cpp:func:`spi_bus_add_flash_device` 将 flash 设备连接到总线上。然后分配内存,填充 ``esp_flash_t`` 结构体,同时初始化 CS I/O。
|
||||||
|
|
||||||
|
3. 调用 :cpp:func:`esp_flash_init` 与芯片进行通信。后续操作会依据芯片类型不同而有差异。
|
||||||
|
|
||||||
|
.. note:: 目前,多个 flash 芯片可连接到同一总线。但尚不支持在同一个 SPI 总线上使用 ``esp_flash_*`` 和 ``spi_device_*`` 设备。
|
||||||
|
|
||||||
|
SPI Flash 访问 API
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
如下所示为处理 flash 中数据的函数集:
|
||||||
|
|
||||||
|
- :cpp:func:`esp_flash_read`:将数据从 flash 读取到 RAM;
|
||||||
|
- :cpp:func:`esp_flash_write`:将数据从 RAM 写入到 flash;
|
||||||
|
- :cpp:func:`esp_flash_erase_region`:擦除 flash 中指定区域的数据;
|
||||||
|
- :cpp:func:`esp_flash_erase_chip`:擦除整个 flash;
|
||||||
|
- :cpp:func:`esp_flash_get_chip_size`:返回 menuconfig 中设置的 flash 芯片容量(以字节为单位)。
|
||||||
|
|
||||||
|
一般来说,请尽量避免对主 SPI flash 芯片直接使用原始 SPI flash 函数,如需对主 SPI flash 芯片进行操作,请使用 :ref:`分区专用函数 <flash-partition-apis>`。
|
||||||
|
|
||||||
|
SPI Flash 容量
|
||||||
|
--------------
|
||||||
|
|
||||||
|
SPI flash 容量存储于引导程序映像头部(烧录偏移量为 0x1000)的一个字段。
|
||||||
|
|
||||||
|
默认情况下,引导程序写入 flash 时,esptool.py 将引导程序写入 flash 时,会自动检测 SPI flash 容量,同时使用正确容量更新引导程序的头部。您也可以在工程配置中设置 :envvar:`CONFIG_ESPTOOLPY_FLASHSIZE`,生成固定的 flash 容量。
|
||||||
|
|
||||||
|
如需在运行时覆盖已配置的 flash 容量,请配置 ``g_rom_flashchip`` 结构中的 ``chip_size``。``esp_flash_*`` 函数使用此容量(于软件和 ROM 中)进行边界检查。
|
||||||
|
|
||||||
|
SPI1 Flash 并发约束
|
||||||
|
-----------------------------------------
|
||||||
|
|
||||||
|
由于 SPI1 flash 也被用于执行固件(通过指令 cache 或数据 cache ),因此在执行读取、写入及擦除操作时,必须禁用这些 cache。这意味着在执行 flash 写操作时,两个 CPU 必须从 IRAM 运行代码,且只能从 DRAM 中读取数据。
|
||||||
|
|
||||||
|
如果您使用本文档中 API 函数,上述限制将自动生效且透明(无需您额外关注),但这些限制可能会影响系统中的其他任务的性能。
|
||||||
|
|
||||||
|
除 SPI0/1 以外的 SPI 总线上的其它 flash 芯片则不受这种限制。
|
||||||
|
|
||||||
|
请参阅 :ref:`应用程序内存分布 <memory-layout>`,查看 IRAM、DRAM 和 flash cache 的区别。
|
||||||
|
|
||||||
|
为避免意外读取 flash cache,一个 CPU 在启动 flash 写入或擦除操作时,另一个 CPU 将阻塞,并且在 flash 操作完成前,两个 CPU 上的所有的非 IRAM 安全的中断都会被禁用。
|
||||||
|
|
||||||
|
.. _iram-safe-interrupt-handlers:
|
||||||
|
|
||||||
|
IRAM 安全中断处理程序
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
如果您需要在 flash 操作期间运行中断处理程序(比如低延迟操作),请在 :doc:`注册中断处理程序 </api-reference/system/intr_alloc>` 时设置 ``ESP_INTR_FLAG_IRAM``。
|
||||||
|
|
||||||
|
请确保中断处理程序访问的所有数据和函数(包括其调用的数据和函数)都存储在 IRAM 或 DRAM 中。
|
||||||
|
|
||||||
|
为函数添加 ``IRAM_ATTR`` 属性::
|
||||||
|
|
||||||
|
#include "esp_attr.h"
|
||||||
|
|
||||||
|
void IRAM_ATTR gpio_isr_handler(void* arg)
|
||||||
|
{
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
为常量添加 ``DRAM_ATTR`` 和 ``DRAM_STR`` 属性::
|
||||||
|
|
||||||
|
void IRAM_ATTR gpio_isr_handler(void* arg)
|
||||||
|
{
|
||||||
|
const static DRAM_ATTR uint8_t INDEX_DATA[] = { 45, 33, 12, 0 };
|
||||||
|
const static char *MSG = DRAM_STR("I am a string stored in RAM");
|
||||||
|
}
|
||||||
|
|
||||||
|
辨别哪些数据应标记为 ``DRAM_ATTR`` 可能会比较困难,除非明确标记为 ``DRAM_ATTR``,否则编译器依然可能将某些变量或表达式当做常量(即便没有 ``const`` 标记),并将其放入 flash。
|
||||||
|
|
||||||
|
如果函数或符号未被正确放入 IRAM/DRAM 中,当中断处理程序在 flash 操作期间从 flash cache 中读取数据,则会产生非法指令异常(这是因为代码未被正确放入 IRAM)或读取垃圾数据(这是因为常数未被正确放入 DRAM),而导致崩溃。
|
||||||
|
|
||||||
|
.. _flash-partition-apis:
|
||||||
|
|
||||||
|
分区表 API
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
ESP-IDF 工程使用分区表保存 SPI flash 各区信息,包括引导程序、各种应用程序二进制文件、数据及文件系统等。请参考 :doc:`分区表 </api-guides/partition-tables>`,查看详细信息。
|
||||||
|
|
||||||
|
该组件在 ``esp_partition.h`` 中声明了一些 API 函数,用以枚举在分区表中找到的分区,并对这些分区执行操作:
|
||||||
|
|
||||||
|
- :cpp:func:`esp_partition_find`:在分区表中查找特定类型的条目,返回一个不透明迭代器;
|
||||||
|
- :cpp:func:`esp_partition_get`:返回一个结构,描述给定迭代器的分区;
|
||||||
|
- :cpp:func:`esp_partition_next`:将迭代器移至下一个找到的分区;
|
||||||
|
- :cpp:func:`esp_partition_iterator_release`:释放 ``esp_partition_find`` 中返回的迭代器;
|
||||||
|
- :cpp:func:`esp_partition_find_first`:返回一个结构,描述 ``esp_partition_find`` 中找到的第一个分区;
|
||||||
|
- :cpp:func:`esp_partition_read`、:cpp:func:`esp_partition_write` 和 :cpp:func:`esp_partition_erase_range` 在分区边界内执行,等同于 :cpp:func:`spi_flash_read`、:cpp:func:`spi_flash_write` 和 :cpp:func:`spi_flash_erase_range`。
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
请在应用程序代码中使用上述 ``esp_partition_*`` API 函数,而非低层级的 ``spi_flash_*`` API 函数。分区表 API 函数根据存储在分区表中的数据,进行边界检查并计算在 flash 中的正确偏移量。
|
||||||
|
|
||||||
|
SPI Flash 加密
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
您可以对 SPI flash 内容进行加密,并在硬件层对其进行透明解密。
|
||||||
|
|
||||||
|
请参阅 :doc:`Flash 加密 </security/flash-encryption>`,查看详细信息。
|
||||||
|
|
||||||
|
内存映射 API
|
||||||
|
------------------
|
||||||
|
|
||||||
|
ESP32 内存硬件可以将 flash 部分区域映射到指令地址空间和数据地址空间,此映射仅用于读操作。不能通过写入 flash 映射的存储区域来改变 flash 中内容。
|
||||||
|
|
||||||
|
Flash 以 64 KB 页为单位进行地址映射。内存映射硬件最多可将 4 MB flash 映射到数据地址空间,将 16 MB flash 映射到指令地址空间。请参考《ESP32 技术参考手册》查看内存映射硬件的详细信息。
|
||||||
|
|
||||||
|
请注意,有些 64 KB 页还用于将应用程序映射到内存中,因此实际可用的 64 KB 页会更少一些。
|
||||||
|
|
||||||
|
:doc:`Flash 加密 </security/flash-encryption>` 启用时,使用内存映射区域从 flash 读取数据是解密 flash 的唯一方法,解密需在硬件层进行。
|
||||||
|
|
||||||
|
内存映射 API 在 ``esp_spi_flash.h`` 和 ``esp_partition.h`` 中声明:
|
||||||
|
|
||||||
|
- :cpp:func:`spi_flash_mmap`:将 flash 物理地址区域映射到 CPU 指令空间或数据空间;
|
||||||
|
- :cpp:func:`spi_flash_munmap`:取消上述区域的映射;
|
||||||
|
- :cpp:func:`esp_partition_mmap`:将分区的一部分映射至 CPU 指令空间或数据空间;
|
||||||
|
|
||||||
|
:cpp:func:`spi_flash_mmap` 和 :cpp:func:`esp_partition_mmap` 的区别如下:
|
||||||
|
|
||||||
|
- :cpp:func:`spi_flash_mmap`:需要给定一个 64 KB 对齐的物理地址;
|
||||||
|
- :cpp:func:`esp_partition_mmap`:给定分区内任意偏移量即可,此函数根据需要将返回的指针调整至指向映射内存。
|
||||||
|
|
||||||
|
内存映射在 64 KB 块中进行,如果分区已传递给 ``esp_partition_mmap``,则可读取分区外数据。
|
||||||
|
|
||||||
|
实现
|
||||||
|
--------------
|
||||||
|
|
||||||
|
``esp_flash_t`` 结构包含芯片数据和该 API 的三个重要部分:
|
||||||
|
|
||||||
|
1. 主机驱动,为访问芯片提供硬件支持;
|
||||||
|
2. 芯片驱动,为不同芯片提供兼容性服务;
|
||||||
|
3. OS 函数,在不同阶段(一级或二级 Boot 或者应用程序阶段)为部分 OS 函数提供支持(如一些锁、延迟)。
|
||||||
|
|
||||||
|
主机驱动
|
||||||
|
^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
主机驱动依赖 ``soc/include/hal`` 文件夹下 ``spi_flash_host_drv.h`` 定义的 ``spi_flash_host_driver_t`` 接口。该接口提供了一些与芯片通信常用的函数。
|
||||||
|
|
||||||
|
在 SPI HAL 文件中,有些函数是基于现有的 ESP32 memory-spi 来实现的。但是,由于 ESP32 速度限制,HAL 层无法提供某些读命令的高速实现(所以这些命令根本没有在 HAL 的文件中被实现)。``memspi_host_driver.h`` 和 ``.c`` 文件使用 HAL 提供的 ``common_command`` 函数实现上述读命令的高速版本,并将所有它实现的及 HAL 函数封装为 ``spi_flash_host_driver_t`` 供更上层调用。
|
||||||
|
|
||||||
|
您也可以实现自己的主机驱动,甚至只通过简单的 GPIO。只要实现了 ``spi_flash_host_driver_t`` 中所有函数,不管底层硬件是什么,esp_flash API 都可以访问 flash。
|
||||||
|
|
||||||
|
芯片驱动
|
||||||
|
^^^^^^^^^^^
|
||||||
|
|
||||||
|
芯片驱动在 ``spi_flash_chip_driver.h`` 中进行定义,并将主机驱动提供的基本函数进行封装以供 API 层使用。
|
||||||
|
|
||||||
|
有些操作需在执行前先发送命令,或在执行后读取状态,因此有些芯片需要不同的命令或值以及通信方式。
|
||||||
|
|
||||||
|
``generic chip`` 芯片代表了常见的 flash 芯片,其他芯片驱动可以在通用芯片的基础上进行开发。
|
||||||
|
|
||||||
|
芯片驱动依赖主机驱动。
|
||||||
|
|
||||||
|
OS 函数
|
||||||
|
^^^^^^^^^^^^
|
||||||
|
|
||||||
|
OS 函数层提供访问锁和延迟的方法。
|
||||||
|
|
||||||
|
该锁定用于解决 SPI Flash 芯片访问和其他函数之间的冲突。例如,经 SPI0/1 访问 flash 芯片时,应当禁用 cache(平时用于取代码和 PSRAM 数据)。另一种情况是,一些没有 CS 线或者 CS 线受软件控制的设备(如通过 SPI 接口的 SD 卡控制)需要在一段时间内独占总线。
|
||||||
|
|
||||||
|
延时则用于某些长时操作,需要主机处于等待状态或执行轮询。
|
||||||
|
|
||||||
|
顶层 API 将芯片驱动和 OS 函数封装成一个完整的组件,并提供参数检查。
|
|
@ -634,7 +634,7 @@ esp_err_t esp_flash_app_disable_protect(bool disable)
|
||||||
|
|
||||||
#ifndef CONFIG_SPI_FLASH_USE_LEGACY_IMPL
|
#ifndef CONFIG_SPI_FLASH_USE_LEGACY_IMPL
|
||||||
|
|
||||||
static esp_err_t spi_flash_translate_rc(esp_err_t err)
|
static IRAM_ATTR esp_err_t spi_flash_translate_rc(esp_err_t err)
|
||||||
{
|
{
|
||||||
switch (err) {
|
switch (err) {
|
||||||
case ESP_OK:
|
case ESP_OK:
|
||||||
|
@ -657,19 +657,19 @@ static esp_err_t spi_flash_translate_rc(esp_err_t err)
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
esp_err_t spi_flash_erase_range(uint32_t start_addr, uint32_t size)
|
esp_err_t IRAM_ATTR spi_flash_erase_range(uint32_t start_addr, uint32_t size)
|
||||||
{
|
{
|
||||||
esp_err_t err = esp_flash_erase_region(NULL, start_addr, size);
|
esp_err_t err = esp_flash_erase_region(NULL, start_addr, size);
|
||||||
return spi_flash_translate_rc(err);
|
return spi_flash_translate_rc(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
esp_err_t spi_flash_write(size_t dst, const void *srcv, size_t size)
|
esp_err_t IRAM_ATTR spi_flash_write(size_t dst, const void *srcv, size_t size)
|
||||||
{
|
{
|
||||||
esp_err_t err = esp_flash_write(NULL, srcv, dst, size);
|
esp_err_t err = esp_flash_write(NULL, srcv, dst, size);
|
||||||
return spi_flash_translate_rc(err);
|
return spi_flash_translate_rc(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
esp_err_t spi_flash_read(size_t src, void *dstv, size_t size)
|
esp_err_t IRAM_ATTR spi_flash_read(size_t src, void *dstv, size_t size)
|
||||||
{
|
{
|
||||||
esp_err_t err = esp_flash_read(NULL, dstv, src, size);
|
esp_err_t err = esp_flash_read(NULL, dstv, src, size);
|
||||||
return spi_flash_translate_rc(err);
|
return spi_flash_translate_rc(err);
|
||||||
|
|
|
@ -55,27 +55,38 @@ typedef struct esp_partition_iterator_opaque_ {
|
||||||
|
|
||||||
static esp_partition_iterator_opaque_t* iterator_create(esp_partition_type_t type, esp_partition_subtype_t subtype, const char* label);
|
static esp_partition_iterator_opaque_t* iterator_create(esp_partition_type_t type, esp_partition_subtype_t subtype, const char* label);
|
||||||
static esp_err_t load_partitions(void);
|
static esp_err_t load_partitions(void);
|
||||||
|
static esp_err_t ensure_partitions_loaded(void);
|
||||||
|
|
||||||
|
|
||||||
|
static const char* TAG = "partition";
|
||||||
static SLIST_HEAD(partition_list_head_, partition_list_item_) s_partition_list =
|
static SLIST_HEAD(partition_list_head_, partition_list_item_) s_partition_list =
|
||||||
SLIST_HEAD_INITIALIZER(s_partition_list);
|
SLIST_HEAD_INITIALIZER(s_partition_list);
|
||||||
static _lock_t s_partition_list_lock;
|
static _lock_t s_partition_list_lock;
|
||||||
|
|
||||||
|
|
||||||
esp_partition_iterator_t esp_partition_find(esp_partition_type_t type,
|
static esp_err_t ensure_partitions_loaded(void)
|
||||||
esp_partition_subtype_t subtype, const char* label)
|
|
||||||
{
|
{
|
||||||
|
esp_err_t err = ESP_OK;
|
||||||
if (SLIST_EMPTY(&s_partition_list)) {
|
if (SLIST_EMPTY(&s_partition_list)) {
|
||||||
// only lock if list is empty (and check again after acquiring lock)
|
// only lock if list is empty (and check again after acquiring lock)
|
||||||
_lock_acquire(&s_partition_list_lock);
|
_lock_acquire(&s_partition_list_lock);
|
||||||
esp_err_t err = ESP_OK;
|
|
||||||
if (SLIST_EMPTY(&s_partition_list)) {
|
if (SLIST_EMPTY(&s_partition_list)) {
|
||||||
|
ESP_LOGD(TAG, "Loading the partition table");
|
||||||
err = load_partitions();
|
err = load_partitions();
|
||||||
|
if (err != ESP_OK) {
|
||||||
|
ESP_LOGE(TAG, "load_partitions returned 0x%x", err);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
_lock_release(&s_partition_list_lock);
|
_lock_release(&s_partition_list_lock);
|
||||||
if (err != ESP_OK) {
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_partition_iterator_t esp_partition_find(esp_partition_type_t type,
|
||||||
|
esp_partition_subtype_t subtype, const char* label)
|
||||||
|
{
|
||||||
|
if (ensure_partitions_loaded() != ESP_OK) {
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
// create an iterator pointing to the start of the list
|
// create an iterator pointing to the start of the list
|
||||||
// (next item will be the first one)
|
// (next item will be the first one)
|
||||||
|
@ -233,6 +244,11 @@ esp_err_t esp_partition_register_external(esp_flash_t* flash_chip, size_t offset
|
||||||
return ESP_ERR_INVALID_SIZE;
|
return ESP_ERR_INVALID_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
esp_err_t err = ensure_partitions_loaded();
|
||||||
|
if (err != ESP_OK) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
partition_list_item_t* item = (partition_list_item_t*) calloc(sizeof(partition_list_item_t), 1);
|
partition_list_item_t* item = (partition_list_item_t*) calloc(sizeof(partition_list_item_t), 1);
|
||||||
if (item == NULL) {
|
if (item == NULL) {
|
||||||
return ESP_ERR_NO_MEM;
|
return ESP_ERR_NO_MEM;
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
Virtual filesystem component
|
Virtual filesystem component
|
||||||
============================
|
============================
|
||||||
|
|
||||||
|
:link_to_translation:`zh_CN:[中文]`
|
||||||
|
|
||||||
Overview
|
Overview
|
||||||
--------
|
--------
|
||||||
|
|
||||||
|
|
167
components/vfs/README_CN.rst
Normal file
167
components/vfs/README_CN.rst
Normal file
|
@ -0,0 +1,167 @@
|
||||||
|
虚拟文件系统组件
|
||||||
|
============================
|
||||||
|
|
||||||
|
:link_to_translation:`en:[English]`
|
||||||
|
|
||||||
|
概述
|
||||||
|
--------
|
||||||
|
|
||||||
|
虚拟文件系统 (VFS) 组件可为一些驱动提供一个统一接口。有了该接口,用户可像操作普通文件一样操作虚拟文件。这类驱动程序可以是 FAT、SPIFFS 等真实文件系统,也可以是有文件类接口的设备驱动程序。
|
||||||
|
|
||||||
|
VFS 组件支持 C 库函数(如 fopen 和 fprintf 等)与文件系统 (FS) 驱动程序协同工作。在高层级,每个 FS 驱动程序均与某些路径前缀相关联。当一个 C 库函数需要打开文件时,VFS 组件将搜索与该文件所在文件路径相关联的 FS 驱动程序,并将调用传递给该驱动程序。针对该文件的读取、写入等其他操作的调用也将传递给这个驱动程序。
|
||||||
|
|
||||||
|
例如,您可以使用 ``/fat`` 前缀注册 FAT 文件系统驱动,之后即可调用 ``fopen("/fat/file.txt", "w")``。之后,VFS 将调用 FAT 驱动的 ``open`` 函数,并将参数 ``/file.txt`` 和合适的打开模式传递给 ``open`` 函数;后续对返回的 ``FILE*`` 数据流调用 C 库函数也同样会传递给 FAT 驱动。
|
||||||
|
|
||||||
|
注册 FS 驱动程序
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
如需注册 FS 驱动程序,首先要定义一个 :cpp:type:`esp_vfs_t` 结构体实例,并用指向 FS API 的函数指针填充它。
|
||||||
|
|
||||||
|
.. highlight:: c
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
esp_vfs_t myfs = {
|
||||||
|
.flags = ESP_VFS_FLAG_DEFAULT,
|
||||||
|
.write = &myfs_write,
|
||||||
|
.open = &myfs_open,
|
||||||
|
.fstat = &myfs_fstat,
|
||||||
|
.close = &myfs_close,
|
||||||
|
.read = &myfs_read,
|
||||||
|
};
|
||||||
|
|
||||||
|
ESP_ERROR_CHECK(esp_vfs_register("/data", &myfs, NULL));
|
||||||
|
|
||||||
|
在上述代码中需要用到 ``read``、 ``write`` 或 ``read_p``、 ``write_p``,具体使用哪组函数由 FS 驱动程序 API 的声明方式决定。
|
||||||
|
|
||||||
|
示例 1:声明 API 函数时不带额外的上下文指针参数,即 FS 驱动程序为单例模式,此时使用 ``write`` ::
|
||||||
|
|
||||||
|
ssize_t myfs_write(int fd, const void * data, size_t size);
|
||||||
|
|
||||||
|
// In definition of esp_vfs_t:
|
||||||
|
.flags = ESP_VFS_FLAG_DEFAULT,
|
||||||
|
.write = &myfs_write,
|
||||||
|
// ... other members initialized
|
||||||
|
|
||||||
|
// When registering FS, context pointer (third argument) is NULL:
|
||||||
|
ESP_ERROR_CHECK(esp_vfs_register("/data", &myfs, NULL));
|
||||||
|
|
||||||
|
示例 2:声明 API 函数时需要一个额外的上下文指针作为参数,即可支持多个 FS 驱动程序实例,此时使用 ``write_p`` ::
|
||||||
|
|
||||||
|
ssize_t myfs_write(myfs_t* fs, int fd, const void * data, size_t size);
|
||||||
|
|
||||||
|
// In definition of esp_vfs_t:
|
||||||
|
.flags = ESP_VFS_FLAG_CONTEXT_PTR,
|
||||||
|
.write_p = &myfs_write,
|
||||||
|
// ... other members initialized
|
||||||
|
|
||||||
|
// When registering FS, pass the FS context pointer into the third argument
|
||||||
|
// (hypothetical myfs_mount function is used for illustrative purposes)
|
||||||
|
myfs_t* myfs_inst1 = myfs_mount(partition1->offset, partition1->size);
|
||||||
|
ESP_ERROR_CHECK(esp_vfs_register("/data1", &myfs, myfs_inst1));
|
||||||
|
|
||||||
|
// Can register another instance:
|
||||||
|
myfs_t* myfs_inst2 = myfs_mount(partition2->offset, partition2->size);
|
||||||
|
ESP_ERROR_CHECK(esp_vfs_register("/data2", &myfs, myfs_inst2));
|
||||||
|
|
||||||
|
同步输入/输出多路复用
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
如需通过 :cpp:func:`select` 使用同步输入/输出多路复用,首先需要把 :cpp:func:`start_select` 和 :cpp:func:`end_select` 注册到 VFS,如下所示:
|
||||||
|
|
||||||
|
.. highlight:: c
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
// In definition of esp_vfs_t:
|
||||||
|
.start_select = &uart_start_select,
|
||||||
|
.end_select = &uart_end_select,
|
||||||
|
// ... other members initialized
|
||||||
|
|
||||||
|
调用 :cpp:func:`start_select` 设置环境,用以检测某一 VFS 文件描述符的读取/写入/错误条件。调用 :cpp:func:`end_select` 终止、析构或释放 :cpp:func:`start_select` 设置的资源。请在 :component_file:`vfs/vfs_uart.c` 中查看 UART 外设参考实现、:cpp:func:`esp_vfs_dev_uart_register`、:cpp:func:`uart_start_select` 和 :cpp:func:`uart_end_select` 函数。
|
||||||
|
|
||||||
|
请参考以下示例,查看如何使用 VFS 文件描述符调用 :cpp:func:`select`:
|
||||||
|
|
||||||
|
- :example:`peripherals/uart_select`
|
||||||
|
- :example:`system/select`
|
||||||
|
|
||||||
|
如果 :cpp:func:`select` 用于套接字文件描述符,您可以启用 :envvar:`CONFIG_LWIP_USE_ONLY_LWIP_SELECT` 选项来减少代码量,提高性能。
|
||||||
|
|
||||||
|
路径
|
||||||
|
-----
|
||||||
|
|
||||||
|
已注册的 FS 驱动程序均有一个路径前缀与之关联,此路径前缀即为分区的挂载点。
|
||||||
|
|
||||||
|
如果挂载点中嵌套了其他挂载点,则在打开文件时使用具有最长匹配路径前缀的挂载点。例如,假设以下文件系统已在 VFS 中注册:
|
||||||
|
|
||||||
|
- 在 /data 下注册 FS 驱动程序 1
|
||||||
|
- 在 /data/static 下注册 FS 驱动程序 2
|
||||||
|
|
||||||
|
那么:
|
||||||
|
|
||||||
|
- 打开 ``/data/log.txt`` 会调用驱动程序 FS 1;
|
||||||
|
- 打开 ``/data/static/index.html`` 需调用 FS 驱动程序 2;
|
||||||
|
- 即便 FS 驱动程序 2 中没有 ``/index.html``,也不会在 FS 驱动程序 1 中查找 ``/static/index.html``。
|
||||||
|
|
||||||
|
挂载点名称必须以路径分隔符 (``/``) 开头,且分隔符后至少包含一个字符。但在以下情况中,VFS 同样支持空的挂载点名称:1. 应用程序需要提供一个”最后方案“下使用的文件系统;2. 应用程序需要同时覆盖 VFS 功能。如果没有与路径匹配的前缀,就会使用到这种文件系统。
|
||||||
|
|
||||||
|
VFS 不会对路径中的点 (``.``) 进行特殊处理,也不会将 ``..`` 视为对父目录的引用。在上述示例中,使用 ``/data/static/../log.txt`` 路径不会调用 FS 驱动程序 1 打开 ``/log.txt``。特定的 FS 驱动程序(如 FATFS)可能以不同的方式处理文件名中的点。
|
||||||
|
|
||||||
|
执行打开文件操作时,FS 驱动程序仅得到文件的相对路径(挂载点前缀已经被去除):
|
||||||
|
|
||||||
|
1. 以 ``/data`` 为路径前缀注册 ``myfs`` 驱动;
|
||||||
|
2. 应用程序调用 ``fopen("/data/config.json", ...)``;
|
||||||
|
3. VFS 调用 ``myfs_open("/config.json", ...)``;
|
||||||
|
4. ``myfs`` 驱动打开 ``/config.json`` 文件。
|
||||||
|
|
||||||
|
VFS 对文件路径长度没有限制,但文件系统路径前缀受 ``ESP_VFS_PATH_MAX`` 限制,即路径前缀上限为 ``ESP_VFS_PATH_MAX``。各个文件系统驱动则可能会对自己的文件名长度设置一些限制。
|
||||||
|
|
||||||
|
|
||||||
|
文件描述符
|
||||||
|
----------------
|
||||||
|
|
||||||
|
文件描述符是一组很小的正整数,从 ``0`` 到 ``FD_SETSIZE - 1``,``FD_SETSIZE`` 在 newlib ``sys/types.h`` 中定义。最大文件描述符由 ``CONFIG_LWIP_MAX_SOCKETS`` 定义,且为套接字保留。VFS 中包含一个名为 ``s_fd_table`` 的查找表,用于将全局文件描述符映射至 ``s_vfs`` 数组中注册的 VFS 驱动索引。
|
||||||
|
|
||||||
|
|
||||||
|
标准 IO 流 (stdin, stdout, stderr)
|
||||||
|
-------------------------------------------
|
||||||
|
|
||||||
|
如果 menuconfig 中 ``UART for console output`` 选项没有设置为 ``None``,则 ``stdin``、 ``stdout`` 和 ``stderr`` 将默认从 UART 读取或写入。UART0 或 UART1 可用作标准 IO。默认情况下,UART0 使用 115200 波特率,TX 管脚为 GPIO1,RX 管脚为 GPIO3。您可以在 menuconfig 中更改上述参数。
|
||||||
|
|
||||||
|
对 ``stdout`` 或 ``stderr`` 执行写入操作将会向 UART 发送 FIFO 发送字符,对 ``stdin`` 执行读取操作则会从 UART 接收 FIFO 中取出字符。
|
||||||
|
|
||||||
|
默认情况下,VFS 使用简单的函数对 UART 进行读写操作。在所有数据放进 UART FIFO 之前,写操作将处于 busy-wait 状态,读操处于非阻塞状态,仅返回 FIFO 中已有数据。由于读操作为非阻塞,高层级 C 库函数调用(如 ``fscanf("%d\n", &var);``)可能获取不到所需结果。
|
||||||
|
|
||||||
|
如果应用程序使用 UART 驱动,则可以调用 ``esp_vfs_dev_uart_use_driver`` 函数来指导 VFS 使用驱动中断、读写阻塞功能等。您也可以调用 ``esp_vfs_dev_uart_use_nonblocking`` 来恢复非阻塞函数。
|
||||||
|
|
||||||
|
VFS 还为输入和输出提供换行符转换功能(可选)。多数应用程序在程序内部发送或接收以 LF (''\n'') 结尾的行,但不同的终端程序可能需要不同的换行符,比如 CR 或 CRLF。应用程序可以通过 menuconfig 或者调用 ``esp_vfs_dev_uart_set_rx_line_endings`` 和 ``esp_vfs_dev_uart_set_tx_line_endings`` 为输入输出配置换行符。
|
||||||
|
|
||||||
|
|
||||||
|
标准流和 FreeRTOS 任务
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
``stdin``、``stdout`` 和 ``stderr`` 的 ``FILE`` 对象在所有 FreeRTOS 任务之间共享,指向这些对象的指针分别存储在每个任务的 ``struct _reent`` 中。
|
||||||
|
|
||||||
|
预处理器把如下代码:
|
||||||
|
|
||||||
|
.. highlight:: c
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
fprintf(stderr, "42\n");
|
||||||
|
|
||||||
|
解释为:
|
||||||
|
|
||||||
|
.. highlight:: c
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
fprintf(__getreent()->_stderr, "42\n");
|
||||||
|
|
||||||
|
其中 ``__getreent()`` 函数将为每个任务返回一个指向 ``struct _reent`` 的指针 (:component_file:`newlib/include/sys/reent.h#L370-L417`)。每个任务的 TCB 均拥有一个 ``struct _reent`` 结构体,任务初始化后,``struct _reent`` 结构体中的 ``_stdin``、``_stdout`` 和 ``_stderr`` 将会被赋予 ``_GLOBAL_REENT`` 中 ``_stdin``、 ``_stdout`` 和 ``_stderr`` 的值,``_GLOBAL_REENT`` 即为 FreeRTOS 启动之前所用结构体。
|
||||||
|
|
||||||
|
这样设计带来的结果是:
|
||||||
|
|
||||||
|
- 允许重定向给定任务的 ``stdin``、 ``stdout`` 和 ``stderr``,而不影响其他任务,例如通过 ``stdin = fopen("/dev/uart/1", "r")``;
|
||||||
|
- 但使用 ``fclose`` 关闭默认 ``stdin``、 ``stdout`` 或 ``stderr`` 将同时关闭相应的 ``FILE`` 流对象,因此会影响其他任务;
|
||||||
|
- 如需更改新任务的默认 ``stdin``、 ``stdout`` 和 ``stderr`` 流,请在创建新任务之前修改 ``_GLOBAL_REENT->_stdin`` (``_stdout``、``_stderr``)。
|
|
@ -24,7 +24,7 @@ ESP-IDF Tools Installer
|
||||||
|
|
||||||
The easiest way to install ESP-IDF's prerequisites is to download the ESP-IDF Tools installer from this URL:
|
The easiest way to install ESP-IDF's prerequisites is to download the ESP-IDF Tools installer from this URL:
|
||||||
|
|
||||||
https://dl.espressif.com/dl/esp-idf-tools-setup-2.0.exe
|
https://dl.espressif.com/dl/esp-idf-tools-setup-2.1.exe
|
||||||
|
|
||||||
The installer includes the cross-compilers, OpenOCD, cmake_ and Ninja_ build tool, and a configuration tool called mconf-idf_. The installer can also download and run installers for Python_ 3.7 and `Git For Windows`_ if they are not already installed on the computer.
|
The installer includes the cross-compilers, OpenOCD, cmake_ and Ninja_ build tool, and a configuration tool called mconf-idf_. The installer can also download and run installers for Python_ 3.7 and `Git For Windows`_ if they are not already installed on the computer.
|
||||||
|
|
||||||
|
|
|
@ -1 +1,36 @@
|
||||||
.. include:: ../../../en/api-reference/storage/nvs_flash.rst
|
.. include:: ../../../../components/nvs_flash/README_CN.rst
|
||||||
|
|
||||||
|
NVS 分区生成程序
|
||||||
|
------------------
|
||||||
|
|
||||||
|
NVS 分区生成程序帮助生成 NVS 分区二进制文件,可使用烧录程序将二进制文件单独烧录至特定分区。烧录至分区上的键值对由 CSV 文件提供,详情请参考 :doc:`NVS 分区生成程序 <nvs_partition_gen>`。
|
||||||
|
|
||||||
|
应用示例
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
ESP-IDF :example:`storage` 目录下提供了两个代码示例:
|
||||||
|
|
||||||
|
:example:`storage/nvs_rw_value`
|
||||||
|
|
||||||
|
演示如何读取及写入 NVS 单个整数值。
|
||||||
|
|
||||||
|
此示例中的值表示 ESP32 模组重启次数。NVS 中数据不会因为模组重启而丢失,因此只有将这一值存储于 NVS 中,才能起到重启次数计数器的作用。
|
||||||
|
|
||||||
|
该示例也演示了如何检测读取/写入操作是否成功,以及某个特定值是否在 NVS 中尚未初始化。诊断程序以纯文本形式提供,帮助您追踪程序流程,及时发现问题。
|
||||||
|
|
||||||
|
:example:`storage/nvs_rw_blob`
|
||||||
|
|
||||||
|
演示如何读取及写入 NVS 单个整数值和 Blob(二进制大对象),并在 NVS 中存储这一数值,即便 ESP32 模组重启也不会消失。
|
||||||
|
|
||||||
|
* value - 记录 ESP32 模组软重启次数和硬重启次数。
|
||||||
|
* blob - 内含记录模组运行次数的表格。此表格将被从 NVS 读取至动态分配的 RAM 上。每次手动软重启后,表格内运行次数即增加一次,新加的运行次数被写入 NVS。下拉 GPIO0 即可手动软重启。
|
||||||
|
|
||||||
|
该示例也演示了如何执行诊断程序以检测读取/写入操作是否成功。
|
||||||
|
|
||||||
|
|
||||||
|
API 参考
|
||||||
|
-------------
|
||||||
|
|
||||||
|
.. include:: /_build/inc/nvs_flash.inc
|
||||||
|
|
||||||
|
.. include:: /_build/inc/nvs.inc
|
||||||
|
|
|
@ -1 +1,47 @@
|
||||||
.. include:: ../../../en/api-reference/storage/spi_flash.rst
|
.. include:: ../../../../components/spi_flash/README_CN.rst
|
||||||
|
|
||||||
|
另请参考
|
||||||
|
------------
|
||||||
|
|
||||||
|
- :doc:`分区表 <../../api-guides/partition-tables>`
|
||||||
|
- :doc:`OTA API <../system/ota>` 提供了高层 API 用于更新存储在 flash 中的 app 固件。
|
||||||
|
- :doc:`NVS API <nvs_flash>` 提供了结构化 API 用于存储 SPI flash 中的碎片数据。
|
||||||
|
|
||||||
|
.. _spi-flash-implementation-details:
|
||||||
|
|
||||||
|
实现细节
|
||||||
|
------------
|
||||||
|
|
||||||
|
必须确保操作期间,两个 CPU 均未从 flash 运行代码,实现细节如下:
|
||||||
|
|
||||||
|
- 单核模式下,SDK 在执行 flash 操作前将禁用中断或调度算法。
|
||||||
|
- 双核模式下,实现细节更为复杂,SDK 需确保两个 CPU 均未运行 flash 代码。
|
||||||
|
|
||||||
|
如果有 SPI flash API 在 CPU A(PRO 或 APP)上调用,它使用 ``esp_ipc_call`` API 在 CPU B 上运行 ``spi_flash_op_block_func`` 函数。``esp_ipc_call`` API 在 CPU B 上唤醒一个高优先级任务,即运行 ``spi_flash_op_block_func`` 函数。运行该函数将禁用 CPU B 上的 cache,并使用 ``s_flash_op_can_start`` 旗帜来标志 cache 已禁用。然后,CPU A 上的任务也会禁用 cache 并继续执行 flash 操作。
|
||||||
|
|
||||||
|
执行 flash 操作时,CPU A 和 CPU B 仍然可以执行中断操作。默认中断代码均存储于 RAM 中,如果新添加了中断分配 API,则应添加一个标志位以请求在 flash 操作期间禁用该新分配的中断。
|
||||||
|
|
||||||
|
Flash 操作完成后,CPU A 上的函数将设置另一标志位,即 ``s_flash_op_complete``,用以通知 CPU B 上的任务可以重新启用 cache 并释放 CPU。接着,CPU A 上的函数也重新启用 cache,并将控制权返还给调用者。
|
||||||
|
|
||||||
|
另外,所有 API 函数均受互斥量 ``s_flash_op_mutex`` 保护。
|
||||||
|
|
||||||
|
在单核环境中(启用 :ref:`CONFIG_FREERTOS_UNICORE`),您需要禁用上述两个 cache 以防发生 CPU 间通信。
|
||||||
|
|
||||||
|
SPI Flash API 参考
|
||||||
|
-------------------------
|
||||||
|
|
||||||
|
.. include:: /_build/inc/esp_flash_spi_init.inc
|
||||||
|
.. include:: /_build/inc/esp_flash.inc
|
||||||
|
.. include:: /_build/inc/spi_flash_types.inc
|
||||||
|
|
||||||
|
分区表 API 参考
|
||||||
|
-------------------------------
|
||||||
|
|
||||||
|
.. include:: /_build/inc/esp_partition.inc
|
||||||
|
|
||||||
|
Flash 加密 API 参考
|
||||||
|
-----------------------------
|
||||||
|
|
||||||
|
.. include:: /_build/inc/esp_flash_encrypt.inc
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1 +1,15 @@
|
||||||
.. include:: ../../../en/api-reference/storage/vfs.rst
|
.. include:: ../../../../components/vfs/README_CN.rst
|
||||||
|
|
||||||
|
应用示例
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
`指南`_ (未完成)
|
||||||
|
|
||||||
|
.. _指南: ../../template.html
|
||||||
|
|
||||||
|
API 参考
|
||||||
|
-------------
|
||||||
|
|
||||||
|
.. include:: /_build/inc/esp_vfs.inc
|
||||||
|
|
||||||
|
.. include:: /_build/inc/esp_vfs_dev.inc
|
||||||
|
|
|
@ -32,7 +32,7 @@
|
||||||
#include "mesh/mesh.h"
|
#include "mesh/mesh.h"
|
||||||
|
|
||||||
static const char *tag = "NimBLE_MESH";
|
static const char *tag = "NimBLE_MESH";
|
||||||
void ble_store_ram_init(void);
|
void ble_store_config_init(void);
|
||||||
|
|
||||||
#define BT_DBG_ENABLED (MYNEWT_VAL(BLE_MESH_DEBUG))
|
#define BT_DBG_ENABLED (MYNEWT_VAL(BLE_MESH_DEBUG))
|
||||||
|
|
||||||
|
@ -418,6 +418,7 @@ void blemesh_host_task(void *param)
|
||||||
|
|
||||||
health_pub_init();
|
health_pub_init();
|
||||||
nimble_port_run();
|
nimble_port_run();
|
||||||
|
nimble_port_freertos_deinit();
|
||||||
}
|
}
|
||||||
|
|
||||||
void app_main(void)
|
void app_main(void)
|
||||||
|
@ -438,7 +439,7 @@ void app_main(void)
|
||||||
|
|
||||||
bt_mesh_register_gatt();
|
bt_mesh_register_gatt();
|
||||||
/* XXX Need to have template for store */
|
/* XXX Need to have template for store */
|
||||||
ble_store_ram_init();
|
ble_store_config_init();
|
||||||
|
|
||||||
nimble_port_freertos_init(blemesh_host_task);
|
nimble_port_freertos_init(blemesh_host_task);
|
||||||
}
|
}
|
||||||
|
|
|
@ -221,9 +221,9 @@ static void start(void)
|
||||||
.queue_size = 20
|
.queue_size = 20
|
||||||
};
|
};
|
||||||
ESP_ERROR_CHECK(spi_bus_add_device(CONFIG_EXAMPLE_ETH_SPI_HOST, &devcfg, &spi_handle));
|
ESP_ERROR_CHECK(spi_bus_add_device(CONFIG_EXAMPLE_ETH_SPI_HOST, &devcfg, &spi_handle));
|
||||||
/* dm9051 ethernet driver is based on spi driver, so need to specify the spi handle */
|
/* dm9051 ethernet driver is based on spi driver */
|
||||||
mac_config.spi_hdl = spi_handle;
|
eth_dm9051_config_t dm9051_config = ETH_DM9051_DEFAULT_CONFIG(spi_handle);
|
||||||
s_mac = esp_eth_mac_new_dm9051(&mac_config);
|
s_mac = esp_eth_mac_new_dm9051(&dm9051_config, &mac_config);
|
||||||
s_phy = esp_eth_phy_new_dm9051(&phy_config);
|
s_phy = esp_eth_phy_new_dm9051(&phy_config);
|
||||||
#endif
|
#endif
|
||||||
esp_eth_config_t config = ETH_DEFAULT_CONFIG(s_mac, s_phy);
|
esp_eth_config_t config = ETH_DEFAULT_CONFIG(s_mac, s_phy);
|
||||||
|
|
|
@ -104,9 +104,9 @@ void app_main(void)
|
||||||
.queue_size = 20
|
.queue_size = 20
|
||||||
};
|
};
|
||||||
ESP_ERROR_CHECK(spi_bus_add_device(CONFIG_EXAMPLE_ETH_SPI_HOST, &devcfg, &spi_handle));
|
ESP_ERROR_CHECK(spi_bus_add_device(CONFIG_EXAMPLE_ETH_SPI_HOST, &devcfg, &spi_handle));
|
||||||
/* dm9051 ethernet driver is based on spi driver, so need to specify the spi handle */
|
/* dm9051 ethernet driver is based on spi driver */
|
||||||
mac_config.spi_hdl = spi_handle;
|
eth_dm9051_config_t dm9051_config = ETH_DM9051_DEFAULT_CONFIG(spi_handle);
|
||||||
esp_eth_mac_t *mac = esp_eth_mac_new_dm9051(&mac_config);
|
esp_eth_mac_t *mac = esp_eth_mac_new_dm9051(&dm9051_config, &mac_config);
|
||||||
esp_eth_phy_t *phy = esp_eth_phy_new_dm9051(&phy_config);
|
esp_eth_phy_t *phy = esp_eth_phy_new_dm9051(&phy_config);
|
||||||
#endif
|
#endif
|
||||||
esp_eth_config_t config = ETH_DEFAULT_CONFIG(mac, phy);
|
esp_eth_config_t config = ETH_DEFAULT_CONFIG(mac, phy);
|
||||||
|
|
|
@ -176,9 +176,9 @@ static void initialize_ethernet(void)
|
||||||
.queue_size = 20
|
.queue_size = 20
|
||||||
};
|
};
|
||||||
ESP_ERROR_CHECK(spi_bus_add_device(CONFIG_EXAMPLE_ETH_SPI_HOST, &devcfg, &spi_handle));
|
ESP_ERROR_CHECK(spi_bus_add_device(CONFIG_EXAMPLE_ETH_SPI_HOST, &devcfg, &spi_handle));
|
||||||
/* dm9051 ethernet driver is based on spi driver, so need to specify the spi handle */
|
/* dm9051 ethernet driver is based on spi driver */
|
||||||
mac_config.spi_hdl = spi_handle;
|
eth_dm9051_config_t dm9051_config = ETH_DM9051_DEFAULT_CONFIG(spi_handle);
|
||||||
esp_eth_mac_t *mac = esp_eth_mac_new_dm9051(&mac_config);
|
esp_eth_mac_t *mac = esp_eth_mac_new_dm9051(&dm9051_config, &mac_config);
|
||||||
esp_eth_phy_t *phy = esp_eth_phy_new_dm9051(&phy_config);
|
esp_eth_phy_t *phy = esp_eth_phy_new_dm9051(&phy_config);
|
||||||
#endif
|
#endif
|
||||||
esp_eth_config_t config = ETH_DEFAULT_CONFIG(mac, phy);
|
esp_eth_config_t config = ETH_DEFAULT_CONFIG(mac, phy);
|
||||||
|
|
|
@ -215,9 +215,9 @@ void register_ethernet(void)
|
||||||
.queue_size = 20
|
.queue_size = 20
|
||||||
};
|
};
|
||||||
ESP_ERROR_CHECK(spi_bus_add_device(CONFIG_EXAMPLE_ETH_SPI_HOST, &devcfg, &spi_handle));
|
ESP_ERROR_CHECK(spi_bus_add_device(CONFIG_EXAMPLE_ETH_SPI_HOST, &devcfg, &spi_handle));
|
||||||
/* dm9051 ethernet driver is based on spi driver, so need to specify the spi handle */
|
/* dm9051 ethernet driver is based on spi driver */
|
||||||
mac_config.spi_hdl = spi_handle;
|
eth_dm9051_config_t dm9051_config = ETH_DM9051_DEFAULT_CONFIG(spi_handle);
|
||||||
esp_eth_mac_t *mac = esp_eth_mac_new_dm9051(&mac_config);
|
esp_eth_mac_t *mac = esp_eth_mac_new_dm9051(&dm9051_config, &mac_config);
|
||||||
esp_eth_phy_t *phy = esp_eth_phy_new_dm9051(&phy_config);
|
esp_eth_phy_t *phy = esp_eth_phy_new_dm9051(&phy_config);
|
||||||
#endif
|
#endif
|
||||||
esp_eth_config_t config = ETH_DEFAULT_CONFIG(mac, phy);
|
esp_eth_config_t config = ETH_DEFAULT_CONFIG(mac, phy);
|
||||||
|
|
13
examples/get-started/hello_world/.gdbinit.ci
Normal file
13
examples/get-started/hello_world/.gdbinit.ci
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
# Connect to a running instance of OpenOCD
|
||||||
|
target remote 127.0.0.1:3333
|
||||||
|
# Reset and halt the target
|
||||||
|
mon reset halt
|
||||||
|
# Run to a specific point in ROM code,
|
||||||
|
# where most of initialization is complete.
|
||||||
|
thb *0x40007901
|
||||||
|
c
|
||||||
|
# Load the application into RAM
|
||||||
|
load
|
||||||
|
# Run till app_main
|
||||||
|
tb app_main
|
||||||
|
c
|
129
examples/get-started/hello_world/loadable_elf_example_test.py
Normal file
129
examples/get-started/hello_world/loadable_elf_example_test.py
Normal file
|
@ -0,0 +1,129 @@
|
||||||
|
import os
|
||||||
|
import pexpect
|
||||||
|
import serial
|
||||||
|
import sys
|
||||||
|
import threading
|
||||||
|
import time
|
||||||
|
|
||||||
|
try:
|
||||||
|
import IDF
|
||||||
|
except ImportError:
|
||||||
|
test_fw_path = os.getenv('TEST_FW_PATH')
|
||||||
|
if test_fw_path and test_fw_path not in sys.path:
|
||||||
|
sys.path.insert(0, test_fw_path)
|
||||||
|
import IDF
|
||||||
|
|
||||||
|
import Utility
|
||||||
|
|
||||||
|
|
||||||
|
class CustomProcess(object):
|
||||||
|
def __init__(self, cmd, logfile):
|
||||||
|
self.f = open(logfile, 'wb')
|
||||||
|
self.p = pexpect.spawn(cmd, timeout=60, logfile=self.f)
|
||||||
|
|
||||||
|
def __enter__(self):
|
||||||
|
return self
|
||||||
|
|
||||||
|
def close(self):
|
||||||
|
self.p.terminate(force=True)
|
||||||
|
|
||||||
|
def __exit__(self, type, value, traceback):
|
||||||
|
self.close()
|
||||||
|
self.f.close()
|
||||||
|
|
||||||
|
|
||||||
|
class OCDProcess(CustomProcess):
|
||||||
|
def __init__(self, proj_path):
|
||||||
|
cmd = 'openocd -f interface/ftdi/esp32_devkitj_v1.cfg -f board/esp-wroom-32.cfg'
|
||||||
|
log_file = os.path.join(proj_path, 'openocd.log')
|
||||||
|
super(OCDProcess, self).__init__(cmd, log_file)
|
||||||
|
i = self.p.expect_exact(['Info : Listening on port 3333 for gdb connections', 'Error:'])
|
||||||
|
if i == 0:
|
||||||
|
Utility.console_log('openocd is listening for gdb connections')
|
||||||
|
else:
|
||||||
|
raise RuntimeError('openocd initialization has failed')
|
||||||
|
|
||||||
|
def close(self):
|
||||||
|
try:
|
||||||
|
self.p.sendcontrol('c')
|
||||||
|
self.p.expect_exact('shutdown command invoked')
|
||||||
|
except Exception:
|
||||||
|
Utility.console_log('openocd needs to be killed', 'O')
|
||||||
|
super(OCDProcess, self).close()
|
||||||
|
|
||||||
|
|
||||||
|
class GDBProcess(CustomProcess):
|
||||||
|
def __init__(self, proj_path, elf_path):
|
||||||
|
cmd = 'xtensa-esp32-elf-gdb -x {} --directory={} {}'.format(os.path.join(proj_path, '.gdbinit.ci'),
|
||||||
|
os.path.join(proj_path, 'main'),
|
||||||
|
elf_path)
|
||||||
|
log_file = os.path.join(proj_path, 'gdb.log')
|
||||||
|
super(GDBProcess, self).__init__(cmd, log_file)
|
||||||
|
self.p.sendline('') # it is for "---Type <return> to continue, or q <return> to quit---"
|
||||||
|
i = self.p.expect_exact(['Thread 1 hit Temporary breakpoint 2, app_main ()',
|
||||||
|
'Load failed'])
|
||||||
|
if i == 0:
|
||||||
|
Utility.console_log('gdb is at breakpoint')
|
||||||
|
else:
|
||||||
|
raise RuntimeError('Load failed: probably the ELF file was not built for loading with gdb')
|
||||||
|
self.p.expect_exact('(gdb)')
|
||||||
|
|
||||||
|
def close(self):
|
||||||
|
try:
|
||||||
|
self.p.sendline('q')
|
||||||
|
self.p.expect_exact('Quit anyway? (y or n)')
|
||||||
|
self.p.sendline('y')
|
||||||
|
self.p.expect_exact('Ending remote debugging.')
|
||||||
|
except Exception:
|
||||||
|
Utility.console_log('gdb needs to be killed', 'O')
|
||||||
|
super(GDBProcess, self).close()
|
||||||
|
|
||||||
|
def break_till_end(self):
|
||||||
|
self.p.sendline('b esp_restart')
|
||||||
|
self.p.sendline('c')
|
||||||
|
self.p.expect_exact('Thread 1 hit Breakpoint 3, esp_restart ()')
|
||||||
|
|
||||||
|
|
||||||
|
class SerialThread(object):
|
||||||
|
def run(self, log_path, exit_event):
|
||||||
|
with serial.Serial('/dev/ttyUSB1', 115200) as ser, open(log_path, 'wb') as f:
|
||||||
|
while True:
|
||||||
|
f.write(ser.read(ser.in_waiting))
|
||||||
|
if exit_event.is_set():
|
||||||
|
break
|
||||||
|
time.sleep(1)
|
||||||
|
|
||||||
|
def __init__(self, log_path):
|
||||||
|
self.exit_event = threading.Event()
|
||||||
|
self.t = threading.Thread(target=self.run, args=(log_path, self.exit_event,))
|
||||||
|
self.t.start()
|
||||||
|
|
||||||
|
def __enter__(self):
|
||||||
|
return self
|
||||||
|
|
||||||
|
def __exit__(self, type, value, traceback):
|
||||||
|
self.exit_event.set()
|
||||||
|
self.t.join(60)
|
||||||
|
if self.t.is_alive():
|
||||||
|
Utility.console_log('The pyserial thread is still alive', 'O')
|
||||||
|
|
||||||
|
|
||||||
|
@IDF.idf_example_test(env_tag="test_jtag_arm")
|
||||||
|
def test_examples_loadable_elf(env, extra_data):
|
||||||
|
|
||||||
|
idf_path = os.environ['IDF_PATH']
|
||||||
|
rel_project_path = os.path.join('examples', 'get-started', 'hello_world')
|
||||||
|
proj_path = os.path.join(idf_path, rel_project_path)
|
||||||
|
elf_path = os.path.join(IDF.Example(rel_project_path).get_binary_path(rel_project_path), 'hello-world.elf')
|
||||||
|
esp_log_path = os.path.join(proj_path, 'esp.log')
|
||||||
|
|
||||||
|
with SerialThread(esp_log_path):
|
||||||
|
with OCDProcess(proj_path), GDBProcess(proj_path, elf_path) as gdb:
|
||||||
|
gdb.break_till_end()
|
||||||
|
|
||||||
|
if pexpect.run('grep "Restarting now." {}'.format(esp_log_path), withexitstatus=True)[1]:
|
||||||
|
raise RuntimeError('Expected output from ESP was not received')
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
test_examples_loadable_elf()
|
6
examples/get-started/hello_world/sdkconfig.ci
Normal file
6
examples/get-started/hello_world/sdkconfig.ci
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
CONFIG_APP_BUILD_TYPE_ELF_RAM=y
|
||||||
|
CONFIG_VFS_SUPPORT_TERMIOS=
|
||||||
|
CONFIG_NEWLIB_NANO_FORMAT=y
|
||||||
|
CONFIG_ESP32_PANIC_PRINT_HALT=y
|
||||||
|
CONFIG_ESP32_DEBUG_STUBS_ENABLE=
|
||||||
|
CONFIG_ESP_ERR_TO_NAME_LOOKUP=
|
27
examples/storage/ext_flash_fatfs/example_test.py
Normal file
27
examples/storage/ext_flash_fatfs/example_test.py
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
from __future__ import print_function
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
|
||||||
|
try:
|
||||||
|
import IDF
|
||||||
|
except ImportError:
|
||||||
|
test_fw_path = os.getenv('TEST_FW_PATH')
|
||||||
|
if test_fw_path and test_fw_path not in sys.path:
|
||||||
|
sys.path.insert(0, test_fw_path)
|
||||||
|
import IDF
|
||||||
|
|
||||||
|
|
||||||
|
@IDF.idf_example_test(env_tag='Example_ExtFlash')
|
||||||
|
def test_examples_storage_ext_flash_fatfs(env, extra_data):
|
||||||
|
dut = env.get_dut('ext_flash_fatfs', 'examples/storage/ext_flash_fatfs')
|
||||||
|
dut.start_app()
|
||||||
|
|
||||||
|
dut.expect('Initialized external Flash')
|
||||||
|
dut.expect('partition \'nvs\'')
|
||||||
|
dut.expect('partition \'storage\'')
|
||||||
|
dut.expect('File written')
|
||||||
|
dut.expect('Read from file: \'Written using ESP-IDF')
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
test_examples_storage_ext_flash_fatfs()
|
|
@ -30,6 +30,7 @@ const char *base_path = "/extflash";
|
||||||
|
|
||||||
static esp_flash_t* example_init_ext_flash(void);
|
static esp_flash_t* example_init_ext_flash(void);
|
||||||
static const esp_partition_t* example_add_partition(esp_flash_t* ext_flash, const char* partition_label);
|
static const esp_partition_t* example_add_partition(esp_flash_t* ext_flash, const char* partition_label);
|
||||||
|
static void example_list_data_partitions(void);
|
||||||
static bool example_mount_fatfs(const char* partition_label);
|
static bool example_mount_fatfs(const char* partition_label);
|
||||||
static void example_get_fatfs_usage(size_t* out_total_bytes, size_t* out_free_bytes);
|
static void example_get_fatfs_usage(size_t* out_total_bytes, size_t* out_free_bytes);
|
||||||
|
|
||||||
|
@ -45,6 +46,9 @@ void app_main(void)
|
||||||
const char *partition_label = "storage";
|
const char *partition_label = "storage";
|
||||||
example_add_partition(flash, partition_label);
|
example_add_partition(flash, partition_label);
|
||||||
|
|
||||||
|
// List the available partitions
|
||||||
|
example_list_data_partitions();
|
||||||
|
|
||||||
// Initialize FAT FS in the partition
|
// Initialize FAT FS in the partition
|
||||||
if (!example_mount_fatfs(partition_label)) {
|
if (!example_mount_fatfs(partition_label)) {
|
||||||
return;
|
return;
|
||||||
|
@ -139,6 +143,20 @@ static const esp_partition_t* example_add_partition(esp_flash_t* ext_flash, cons
|
||||||
return fat_partition;
|
return fat_partition;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void example_list_data_partitions(void)
|
||||||
|
{
|
||||||
|
ESP_LOGI(TAG, "Listing data partitions:");
|
||||||
|
esp_partition_iterator_t it = esp_partition_find(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_ANY, NULL);
|
||||||
|
|
||||||
|
for (; it != NULL; it = esp_partition_next(it)) {
|
||||||
|
const esp_partition_t *part = esp_partition_get(it);
|
||||||
|
ESP_LOGI(TAG, "- partition '%s', subtype %d, offset 0x%x, size %d kB",
|
||||||
|
part->label, part->subtype, part->address, part->size / 1024);
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_partition_iterator_release(it);
|
||||||
|
}
|
||||||
|
|
||||||
static bool example_mount_fatfs(const char* partition_label)
|
static bool example_mount_fatfs(const char* partition_label)
|
||||||
{
|
{
|
||||||
ESP_LOGI(TAG, "Mounting FAT filesystem");
|
ESP_LOGI(TAG, "Mounting FAT filesystem");
|
||||||
|
|
|
@ -7,7 +7,7 @@ LDGEN_LIBRARIES=$(foreach libcomp,$(COMPONENT_LIBRARIES),$(BUILD_DIR_BASE)/$(lib
|
||||||
ifeq ($(OS),Windows_NT)
|
ifeq ($(OS),Windows_NT)
|
||||||
define ldgen_process_template
|
define ldgen_process_template
|
||||||
$(BUILD_DIR_BASE)/ldgen_libraries: $(LDGEN_LIBRARIES) $(IDF_PATH)/make/ldgen.mk
|
$(BUILD_DIR_BASE)/ldgen_libraries: $(LDGEN_LIBRARIES) $(IDF_PATH)/make/ldgen.mk
|
||||||
printf "$(foreach info,$(LDGEN_LIBRARIES),$(subst \,/,$(shell cygpath -w $(info)))\n)" > $(BUILD_DIR_BASE)/ldgen_libraries
|
printf "$(foreach info,$(LDGEN_LIBRARIES),$(subst \,/,$(shell cygpath -m $(info)))\n)" > $(BUILD_DIR_BASE)/ldgen_libraries
|
||||||
|
|
||||||
$(2): $(1) $(LDGEN_FRAGMENT_FILES) $(SDKCONFIG) $(BUILD_DIR_BASE)/ldgen_libraries
|
$(2): $(1) $(LDGEN_FRAGMENT_FILES) $(SDKCONFIG) $(BUILD_DIR_BASE)/ldgen_libraries
|
||||||
@echo 'Generating $(notdir $(2))'
|
@echo 'Generating $(notdir $(2))'
|
||||||
|
@ -18,8 +18,8 @@ $(2): $(1) $(LDGEN_FRAGMENT_FILES) $(SDKCONFIG) $(BUILD_DIR_BASE)/ldgen_librarie
|
||||||
--libraries-file $(BUILD_DIR_BASE)/ldgen_libraries \
|
--libraries-file $(BUILD_DIR_BASE)/ldgen_libraries \
|
||||||
--output $(2) \
|
--output $(2) \
|
||||||
--kconfig $(IDF_PATH)/Kconfig \
|
--kconfig $(IDF_PATH)/Kconfig \
|
||||||
--env "COMPONENT_KCONFIGS=$(foreach k, $(COMPONENT_KCONFIGS), $(shell cygpath -w $(k)))" \
|
--env "COMPONENT_KCONFIGS=$(foreach k, $(COMPONENT_KCONFIGS), $(shell cygpath -m $(k)))" \
|
||||||
--env "COMPONENT_KCONFIGS_PROJBUILD=$(foreach k, $(COMPONENT_KCONFIGS_PROJBUILD), $(shell cygpath -w $(k)))" \
|
--env "COMPONENT_KCONFIGS_PROJBUILD=$(foreach k, $(COMPONENT_KCONFIGS_PROJBUILD), $(shell cygpath -m $(k)))" \
|
||||||
--env "IDF_CMAKE=n" \
|
--env "IDF_CMAKE=n" \
|
||||||
--objdump $(OBJDUMP)
|
--objdump $(OBJDUMP)
|
||||||
endef
|
endef
|
||||||
|
|
|
@ -320,9 +320,15 @@ ifndef CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES
|
||||||
endif
|
endif
|
||||||
@echo "To flash app & partition table, run 'make flash' or:"
|
@echo "To flash app & partition table, run 'make flash' or:"
|
||||||
else
|
else
|
||||||
|
ifdef CONFIG_APP_BUILD_GENERATE_BINARIES
|
||||||
@echo "To flash all build output, run 'make flash' or:"
|
@echo "To flash all build output, run 'make flash' or:"
|
||||||
endif
|
endif
|
||||||
|
endif
|
||||||
|
ifdef CONFIG_APP_BUILD_GENERATE_BINARIES
|
||||||
@echo $(ESPTOOLPY_WRITE_FLASH) $(ESPTOOL_ALL_FLASH_ARGS)
|
@echo $(ESPTOOLPY_WRITE_FLASH) $(ESPTOOL_ALL_FLASH_ARGS)
|
||||||
|
else
|
||||||
|
@echo "Binary is not available for flashing"
|
||||||
|
endif
|
||||||
|
|
||||||
|
|
||||||
# If we have `version.txt` then prefer that for extracting IDF version
|
# If we have `version.txt` then prefer that for extracting IDF version
|
||||||
|
@ -533,6 +539,7 @@ $(APP_ELF): $(foreach libcomp,$(COMPONENT_LIBRARIES),$(BUILD_DIR_BASE)/$(libcomp
|
||||||
$(CC) $(LDFLAGS) -o $@ -Wl,-Map=$(APP_MAP)
|
$(CC) $(LDFLAGS) -o $@ -Wl,-Map=$(APP_MAP)
|
||||||
|
|
||||||
app: $(APP_BIN) partition_table_get_info
|
app: $(APP_BIN) partition_table_get_info
|
||||||
|
ifeq ("$(CONFIG_APP_BUILD_GENERATE_BINARIES)","y")
|
||||||
ifeq ("$(CONFIG_SECURE_BOOT_ENABLED)$(CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES)","y") # secure boot enabled, but remote sign app image
|
ifeq ("$(CONFIG_SECURE_BOOT_ENABLED)$(CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES)","y") # secure boot enabled, but remote sign app image
|
||||||
@echo "App built but not signed. Signing step via espsecure.py:"
|
@echo "App built but not signed. Signing step via espsecure.py:"
|
||||||
@echo "espsecure.py sign_data --keyfile KEYFILE $(APP_BIN)"
|
@echo "espsecure.py sign_data --keyfile KEYFILE $(APP_BIN)"
|
||||||
|
@ -542,6 +549,9 @@ else
|
||||||
@echo "App built. Default flash app command is:"
|
@echo "App built. Default flash app command is:"
|
||||||
@echo $(ESPTOOLPY_WRITE_FLASH) $(APP_OFFSET) $(APP_BIN)
|
@echo $(ESPTOOLPY_WRITE_FLASH) $(APP_OFFSET) $(APP_BIN)
|
||||||
endif
|
endif
|
||||||
|
else
|
||||||
|
@echo "Application in not built and cannot be flashed."
|
||||||
|
endif
|
||||||
|
|
||||||
all_binaries: $(APP_BIN)
|
all_binaries: $(APP_BIN)
|
||||||
|
|
||||||
|
|
|
@ -7,9 +7,9 @@ COMPONENT_SDKCONFIG_RENAMES := $(foreach component,$(COMPONENT_PATHS),$(wildcard
|
||||||
|
|
||||||
ifeq ($(OS),Windows_NT)
|
ifeq ($(OS),Windows_NT)
|
||||||
# kconfiglib requires Windows-style paths for kconfig files
|
# kconfiglib requires Windows-style paths for kconfig files
|
||||||
COMPONENT_KCONFIGS := $(shell cygpath -w $(COMPONENT_KCONFIGS))
|
COMPONENT_KCONFIGS := $(shell cygpath -m $(COMPONENT_KCONFIGS))
|
||||||
COMPONENT_KCONFIGS_PROJBUILD := $(shell cygpath -w $(COMPONENT_KCONFIGS_PROJBUILD))
|
COMPONENT_KCONFIGS_PROJBUILD := $(shell cygpath -m $(COMPONENT_KCONFIGS_PROJBUILD))
|
||||||
COMPONENT_SDKCONFIG_RENAMES := $(shell cygpath -w $(COMPONENT_SDKCONFIG_RENAMES))
|
COMPONENT_SDKCONFIG_RENAMES := $(shell cygpath -m $(COMPONENT_SDKCONFIG_RENAMES))
|
||||||
endif
|
endif
|
||||||
|
|
||||||
#For doing make menuconfig etc
|
#For doing make menuconfig etc
|
||||||
|
|
|
@ -388,19 +388,5 @@ build_installer:
|
||||||
- build_cmdlinerunner
|
- build_cmdlinerunner
|
||||||
before_script: []
|
before_script: []
|
||||||
script:
|
script:
|
||||||
- mkdir idf_tools_tmp
|
|
||||||
- export IDF_TOOLS_PATH=$PWD/idf_tools_tmp
|
|
||||||
- tools/idf_tools.py --non-interactive download --platform Windows-x86_64 all
|
|
||||||
- tools/idf_tools.py --tools-json tools/windows/tool_setup/tools_fallback.json --non-interactive download --platform Windows-x86_64 all
|
|
||||||
- mkdir tools/windows/tool_setup/dist
|
|
||||||
- mv idf_tools_tmp/dist/* tools/windows/tool_setup/dist/
|
|
||||||
|
|
||||||
- cd tools/windows/tool_setup/
|
- cd tools/windows/tool_setup/
|
||||||
- mkdir unzip
|
- ./build_installer.sh
|
||||||
- cd unzip
|
|
||||||
- wget --no-verbose https://www.7-zip.org/a/7z1900-extra.7z
|
|
||||||
- 7zr e -y 7z1900-extra.7z
|
|
||||||
- cd ..
|
|
||||||
|
|
||||||
- wget --no-verbose https://dl.espressif.com/dl/esp-idf/idf_versions.txt
|
|
||||||
- iscc idf_tool_setup.iss
|
|
||||||
|
|
|
@ -203,6 +203,25 @@ example_test_008:
|
||||||
- ESP32
|
- ESP32
|
||||||
- Example_Flash_Encryption
|
- Example_Flash_Encryption
|
||||||
|
|
||||||
|
example_test_009:
|
||||||
|
extends: .example_test_template
|
||||||
|
tags:
|
||||||
|
- ESP32
|
||||||
|
- test_jtag_arm
|
||||||
|
artifacts:
|
||||||
|
when: always
|
||||||
|
paths:
|
||||||
|
- $CI_PROJECT_DIR/examples/get-started/hello_world/*.log
|
||||||
|
expire_in: 1 week
|
||||||
|
variables:
|
||||||
|
SETUP_TOOLS: "1"
|
||||||
|
|
||||||
|
example_test_010:
|
||||||
|
extends: .example_test_template
|
||||||
|
tags:
|
||||||
|
- ESP32
|
||||||
|
- Example_ExtFlash
|
||||||
|
|
||||||
UT_001:
|
UT_001:
|
||||||
extends: .unit_test_template
|
extends: .unit_test_template
|
||||||
parallel: 50
|
parallel: 50
|
||||||
|
@ -432,6 +451,20 @@ UT_032:
|
||||||
- ESP32_IDF
|
- ESP32_IDF
|
||||||
- UT_T1_FlashEncryption
|
- UT_T1_FlashEncryption
|
||||||
|
|
||||||
|
UT_032:
|
||||||
|
extends: .unit_test_template
|
||||||
|
parallel: 4
|
||||||
|
tags:
|
||||||
|
- ESP32_IDF
|
||||||
|
- UT_T2_Ethernet
|
||||||
|
|
||||||
|
UT_033:
|
||||||
|
extends: .unit_test_template
|
||||||
|
tags:
|
||||||
|
- ESP32_IDF
|
||||||
|
- UT_T2_Ethernet
|
||||||
|
- psram
|
||||||
|
|
||||||
nvs_compatible_test:
|
nvs_compatible_test:
|
||||||
extends: .test_template
|
extends: .test_template
|
||||||
artifacts:
|
artifacts:
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue