kopia lustrzana https://github.com/espressif/esp-idf
Merge branch 'docs/update_format_issues_for_api-guides' into 'master'
docs:update format issues for files under api-guides Closes DOC-5935 See merge request espressif/esp-idf!25210pull/12212/head
commit
3640dc86bb
|
@ -1,5 +1,6 @@
|
|||
Application Level Tracing library
|
||||
Application Level Tracing Library
|
||||
=================================
|
||||
|
||||
:link_to_translation:`zh_CN:[中文]`
|
||||
|
||||
Overview
|
||||
|
@ -56,11 +57,13 @@ There are two additional menuconfig options not mentioned above:
|
|||
|
||||
4. *UART TX message size* (:ref:`CONFIG_APPTRACE_UART_TX_MSG_SIZE`). The maximum size of the single message to transfer.
|
||||
|
||||
|
||||
How to Use This Library
|
||||
-----------------------
|
||||
|
||||
This library provides APIs for transferring arbitrary data between the host and {IDF_TARGET_NAME}. When enabled in menuconfig, the target application tracing module is initialized automatically at the system startup, so all what the user needs to do is to call corresponding APIs to send, receive or flush the data.
|
||||
|
||||
|
||||
.. _app_trace-application-specific-tracing:
|
||||
|
||||
Application Specific Tracing
|
||||
|
@ -216,7 +219,7 @@ Start command syntax:
|
|||
|
||||
Command usage examples:
|
||||
|
||||
.. highlight:: none
|
||||
.. code-block:: none
|
||||
|
||||
1. Collect 2048 bytes of tracing data to the file ``trace.log``. The file will be saved in the ``openocd-esp32`` directory.
|
||||
|
||||
|
@ -257,7 +260,6 @@ Command usage examples:
|
|||
|
||||
.. _app_trace-logging-to-host:
|
||||
|
||||
|
||||
Logging to Host
|
||||
^^^^^^^^^^^^^^^
|
||||
|
||||
|
@ -318,6 +320,7 @@ Optional arguments:
|
|||
``--no-errors``, ``-n``
|
||||
Do not print errors.
|
||||
|
||||
|
||||
.. _app_trace-system-behaviour-analysis-with-segger-systemview:
|
||||
|
||||
System Behavior Analysis with SEGGER SystemView
|
||||
|
@ -393,7 +396,7 @@ Start command syntax:
|
|||
|
||||
Command usage examples:
|
||||
|
||||
.. highlight:: none
|
||||
.. code-block:: none
|
||||
|
||||
1. Collect SystemView tracing data to files ``pro-cpu.SVDat`` and ``app-cpu.SVDat``. The files will be saved in ``openocd-esp32`` directory.
|
||||
|
||||
|
@ -427,7 +430,7 @@ Good instructions on how to install, configure, and visualize data in Impulse fr
|
|||
|
||||
.. note::
|
||||
|
||||
ESP-IDF uses its own mapping for SystemView FreeRTOS events IDs, so users need to replace the original file mapping ``$SYSVIEW_INSTALL_DIR/Description/SYSVIEW_FreeRTOS.txt`` with ``$IDF_PATH/tools/esp_app_trace/SYSVIEW_FreeRTOS.txt``. Also, contents of that IDF-specific file should be used when configuring SystemView serializer using the above link.
|
||||
ESP-IDF uses its own mapping for SystemView FreeRTOS events IDs, so users need to replace the original file mapping ``$SYSVIEW_INSTALL_DIR/Description/SYSVIEW_FreeRTOS.txt`` with ``$IDF_PATH/tools/esp_app_trace/SYSVIEW_FreeRTOS.txt``. Also, contents of that ESP-IDF-specific file should be used when configuring SystemView serializer using the above link.
|
||||
|
||||
.. only:: not CONFIG_FREERTOS_UNICORE
|
||||
|
||||
|
@ -469,6 +472,7 @@ Generally, using Gcov to compile and run programs on the host will undergo these
|
|||
|
||||
3. Gcov or Gcovr can be used to generate a code coverage based on the ``.gcno``, ``.gcda``, and source files. Gcov will generate a text-based coverage report for each source file in the form of a ``.gcov`` file, whilst Gcovr will generate a coverage report in HTML format.
|
||||
|
||||
|
||||
Gcov and Gcovr in ESP-IDF
|
||||
"""""""""""""""""""""""""""
|
||||
|
||||
|
@ -478,6 +482,7 @@ Using Gcov in ESP-IDF is complicated due to the fact that the program is running
|
|||
2. :ref:`app_trace-gcov-dumping-data`
|
||||
3. :ref:`app_trace-gcov-generate-report`
|
||||
|
||||
|
||||
.. _app_trace-gcov-setup-project:
|
||||
|
||||
Setting Up a Project for Gcov
|
||||
|
@ -493,6 +498,7 @@ In order to obtain code coverage data in a project, one or more source files wit
|
|||
|
||||
When a source file is compiled with the ``--coverage`` option (e.g., ``gcov_example.c``), the compiler will generate the ``gcov_example.gcno`` file in the project's build directory.
|
||||
|
||||
|
||||
Project Configuration
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
@ -501,6 +507,7 @@ Before building a project with source code coverage, make sure that the followin
|
|||
- Enable the application tracing module by selecting ``Trace Memory`` for the :ref:`CONFIG_APPTRACE_DESTINATION1` option.
|
||||
- Enable Gcov to the host via the :ref:`CONFIG_APPTRACE_GCOV_ENABLE`.
|
||||
|
||||
|
||||
.. _app_trace-gcov-dumping-data:
|
||||
|
||||
Dumping Code Coverage Data
|
||||
|
@ -519,11 +526,13 @@ ESP-IDF supports two methods of dumping code coverage data form the target to th
|
|||
* Instant Run-Time Dumpgit
|
||||
* Hard-coded Dump
|
||||
|
||||
|
||||
Instant Run-Time Dump
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
An Instant Run-Time Dump is triggered by calling the ``{IDF_TARGET_NAME} gcov`` OpenOCD command (via a telnet session). Once called, OpenOCD will immediately preempt the {IDF_TARGET_NAME}'s current state and execute a built-in ESP-IDF Gcov debug stub function. The debug stub function will handle the dumping of data to the host. Upon completion, the {IDF_TARGET_NAME} will resume its current state.
|
||||
|
||||
|
||||
Hard-coded Dump
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
|
@ -546,6 +555,7 @@ The following GDB script will add a breakpoint at :cpp:func:`esp_gcov_dump`, the
|
|||
.. note::
|
||||
Note that all OpenOCD commands should be invoked in GDB as: ``mon <oocd_command>``.
|
||||
|
||||
|
||||
.. _app_trace-gcov-generate-report:
|
||||
|
||||
Generating Coverage Report
|
||||
|
@ -555,6 +565,7 @@ Once the code coverage data has been dumped, the ``.gcno``, ``.gcda`` and the so
|
|||
|
||||
Both Gcov and Gcovr can be used to generate code coverage reports. Gcov is provided along with the Xtensa toolchain, whilst Gcovr may need to be installed separately. For details on how to use Gcov or Gcovr, refer to `Gcov documentation <https://gcc.gnu.org/onlinedocs/gcc/Gcov.html>`_ and `Gcovr documentation <https://gcovr.com/>`_.
|
||||
|
||||
|
||||
Adding Gcovr Build Target to Project
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
|
|
@ -104,6 +104,7 @@ The table below shows whether the Bluetooth modules are supported in a specific
|
|||
|
||||
The following sections briefly describe each layer and provide quick links to the related documents and application examples.
|
||||
|
||||
|
||||
ESP Bluetooth Controller
|
||||
------------------------
|
||||
|
||||
|
@ -112,6 +113,7 @@ At the bottom layer is ESP Bluetooth Controller, which encompasses various modul
|
|||
- :doc:`API reference <../api-reference/bluetooth/controller_vhci>`
|
||||
- :example:`Application examples <bluetooth/hci>`
|
||||
|
||||
|
||||
Hosts
|
||||
-----
|
||||
|
||||
|
@ -123,10 +125,11 @@ There are two hosts, ESP-Bluedroid and ESP-NimBLE. The major difference between
|
|||
|
||||
- ESP-Bluedroid supports both Classic Bluetooth and Bluetooth LE, while ESP-NimBLE only supports Bluetooth LE.
|
||||
|
||||
|
||||
ESP-Bluedroid
|
||||
^^^^^^^^^^^^^
|
||||
|
||||
ESP-Bluedroid is a modified version of the native Android Bluetooth stack, Bluedroid. It consists of two layers: the Bluetooth Upper Layer (BTU) and the Bluetooth Transport Controller layer (BTC). The BTU layer is responsible for processing bottom layer Bluetooth protocols such as L2CAP, GATT/ATT, SMP, GAP, and other profiles. The BTU layer provides an interface prefixed with "bta". The BTC layer is mainly responsible for providing a supported interface, prefixed with “esp”, to the application layer, processing GATT-based profiles and handling miscellaneous tasks. All the APIs are located in the ESP_API layer. Developers should use the Bluetooth APIs prefixed with “esp".
|
||||
ESP-Bluedroid is a modified version of the native Android Bluetooth stack, Bluedroid. It consists of two layers: the Bluetooth Upper Layer (BTU) and the Bluetooth Transport Controller layer (BTC). The BTU layer is responsible for processing bottom layer Bluetooth protocols such as L2CAP, GATT/ATT, SMP, GAP, and other profiles. The BTU layer provides an interface prefixed with "bta". The BTC layer is mainly responsible for providing a supported interface, prefixed with "esp", to the application layer, processing GATT-based profiles and handling miscellaneous tasks. All the APIs are located in the ESP_API layer. Developers should use the Bluetooth APIs prefixed with "esp".
|
||||
|
||||
.. only:: esp32
|
||||
|
||||
|
@ -147,6 +150,7 @@ ESP-Bluedroid is a modified version of the native Android Bluetooth stack, Blued
|
|||
|
||||
- :example:`Application examples <bluetooth/bluedroid>`
|
||||
|
||||
|
||||
ESP-NimBLE
|
||||
^^^^^^^^^^
|
||||
|
||||
|
@ -162,11 +166,13 @@ ESP-NimBLE supports Bluetooth LE only. Classic Bluetooth is not supported.
|
|||
|
||||
- :example:`Application examples <bluetooth/nimble>`
|
||||
|
||||
|
||||
Profiles
|
||||
--------
|
||||
|
||||
Above the host stacks are the profile implementations by Espressif and some common profiles. Depending on your configuration, these profiles can run on ESP-Bluedroid or ESP-NimBLE.
|
||||
|
||||
|
||||
.. only:: SOC_BLE_MESH_SUPPORTED
|
||||
|
||||
ESP-BLE-MESH
|
||||
|
@ -177,6 +183,7 @@ Above the host stacks are the profile implementations by Espressif and some comm
|
|||
- :doc:`ESP-BLE-MESH documentation <esp-ble-mesh/ble-mesh-index>`: feature list, get started, architecture, description of application examples, frequently asked questions, etc.
|
||||
- :example:`Application examples <bluetooth/esp_ble_mesh>`
|
||||
|
||||
|
||||
.. only:: SOC_BLUFI_SUPPORTED
|
||||
|
||||
BluFi
|
||||
|
@ -187,6 +194,7 @@ Above the host stacks are the profile implementations by Espressif and some comm
|
|||
- :doc:`BluFi documentation <blufi>`
|
||||
- :example:`Application examples <bluetooth/blufi>`
|
||||
|
||||
|
||||
Applications
|
||||
------------
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
BluFi
|
||||
^^^^^
|
||||
|
||||
:link_to_translation:`zh_CN:[中文]`
|
||||
|
||||
Overview
|
||||
|
@ -32,7 +33,7 @@ The following uses Station as an example to illustrate the core parts of the pro
|
|||
|
||||
7. When receiving this control frame, {IDF_TARGET_NAME} will be able to encrypt and decrypt the communication data using the shared key and the security configuration.
|
||||
|
||||
8. The mobile phone sends the data frame defined in the section of :ref:`frame_formats`,with the Wi-Fi configuration information to {IDF_TARGET_NAME}, including SSID, password, etc.
|
||||
8. The mobile phone sends the data frame defined in the section of :ref:`frame_formats`,with the Wi-Fi configuration information to {IDF_TARGET_NAME}, including SSID, password, etc.
|
||||
|
||||
9. The mobile phone sends a control frame of Wi-Fi connection request to {IDF_TARGET_NAME}. When receiving this control frame, {IDF_TARGET_NAME} will regard the communication of essential information as done and get ready to connect to the Wi-Fi.
|
||||
|
||||
|
@ -155,7 +156,7 @@ The format of ACK Frame:
|
|||
|
||||
* The data frame supports to be encrypted and verified.
|
||||
|
||||
1.1 Control Frame (Binary: 0x0 b’00)
|
||||
1.1 Control Frame (Binary: 0x0 b'00)
|
||||
|
||||
.. list-table::
|
||||
:header-rows: 1
|
||||
|
@ -233,7 +234,7 @@ The format of ACK Frame:
|
|||
|
||||
|
||||
|
||||
1.2 Data Frame (Binary: 0x1 b’01)
|
||||
1.2 Data Frame (Binary: 0x1 b'01)
|
||||
|
||||
.. list-table::
|
||||
:header-rows: 1
|
||||
|
@ -488,6 +489,6 @@ UUID
|
|||
|
||||
BluFi Service UUID: 0xFFFF, 16 bit
|
||||
|
||||
BluFi (the mobile -> {IDF_TARGET_NAME}): 0xFF01, writable
|
||||
BluFi (the mobile > {IDF_TARGET_NAME}): 0xFF01, writable
|
||||
|
||||
Blufi ({IDF_TARGET_NAME} -> the mobile phone): 0xFF02, readable and callable
|
||||
Blufi ({IDF_TARGET_NAME} > the mobile phone): 0xFF02, readable and callable
|
||||
|
|
|
@ -61,7 +61,7 @@ The :ref:`first-stage-bootloader` in ROM reads the :ref:`second-stage-bootloader
|
|||
Log Level
|
||||
---------
|
||||
|
||||
The default bootloader log level is "Info". By setting the :ref:`CONFIG_BOOTLOADER_LOG_LEVEL` option, it's possible to increase or decrease this level. This log level is separate from the log level used in the app (see :doc:`/api-reference/system/log`).
|
||||
The default bootloader log level is "Info". By setting the :ref:`CONFIG_BOOTLOADER_LOG_LEVEL` option, it is possible to increase or decrease this level. This log level is separate from the log level used in the app (see :doc:`/api-reference/system/log`).
|
||||
|
||||
Reducing bootloader log verbosity can improve the overall project boot time by a small amount.
|
||||
|
||||
|
@ -110,7 +110,7 @@ In addition, the following configuration options control the reset condition:
|
|||
Boot from Test Firmware
|
||||
------------------------
|
||||
|
||||
It's possible to write a special firmware app for testing in production, and boot this firmware when needed. The project partition table will need a dedicated app partition entry for this testing app, type ``app`` and subtype ``test`` (see :doc:`/api-guides/partition-tables`).
|
||||
It is possible to write a special firmware app for testing in production, and boot this firmware when needed. The project partition table will need a dedicated app partition entry for this testing app, type ``app`` and subtype ``test`` (see :doc:`/api-guides/partition-tables`).
|
||||
|
||||
Implementing a dedicated test app firmware requires creating a totally separate ESP-IDF project for the test app (each project in ESP-IDF only builds one app). The test app can be developed and tested independently of the main project, and then integrated at production testing time as a pre-compiled .bin file which is flashed to the address of the main project's test app partition.
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@ Build System
|
|||
|
||||
This document explains the implementation of the ESP-IDF build system and the concept of "components". Read this document if you want to know how to organize and build a new ESP-IDF project or component.
|
||||
|
||||
|
||||
Overview
|
||||
========
|
||||
|
||||
|
@ -20,6 +21,7 @@ An ESP-IDF project can be seen as an amalgamation of a number of components. For
|
|||
|
||||
ESP-IDF makes these components explicit and configurable. To do that, when a project is compiled, the build system will look up all the components in the ESP-IDF directories, the project directories and (optionally) in additional custom component directories. It then allows the user to configure the ESP-IDF project using a text-based menu system to customize each component. After the components in the project are configured, the build system will compile the project.
|
||||
|
||||
|
||||
Concepts
|
||||
--------
|
||||
|
||||
|
@ -35,17 +37,18 @@ Concepts
|
|||
|
||||
Some things are not part of the project:
|
||||
|
||||
- "ESP-IDF" is not part of the project. Instead, it is standalone, and linked to the project via the ``IDF_PATH`` environment variable which holds the path of the ``esp-idf`` directory. This allows the IDF framework to be decoupled from your project.
|
||||
- "ESP-IDF" is not part of the project. Instead, it is standalone, and linked to the project via the ``IDF_PATH`` environment variable which holds the path of the ``esp-idf`` directory. This allows the ESP-IDF framework to be decoupled from your project.
|
||||
|
||||
- The toolchain for compilation is not part of the project. The toolchain should be installed in the system command line PATH.
|
||||
|
||||
|
||||
Using the Build System
|
||||
======================
|
||||
|
||||
.. _idf.py:
|
||||
|
||||
idf.py
|
||||
------
|
||||
``idf.py``
|
||||
----------
|
||||
|
||||
The ``idf.py`` command-line tool provides a front-end for easily managing your project builds. It manages the following tools:
|
||||
|
||||
|
@ -55,12 +58,13 @@ The ``idf.py`` command-line tool provides a front-end for easily managing your p
|
|||
|
||||
You can read more about configuring the build system using ``idf.py`` :doc:`here <tools/idf-py>`.
|
||||
|
||||
|
||||
Using CMake Directly
|
||||
--------------------
|
||||
|
||||
:ref:`idf.py` is a wrapper around CMake_ for convenience. However, you can also invoke CMake directly if you prefer.
|
||||
|
||||
.. highlight:: bash
|
||||
.. code-block:: bash
|
||||
|
||||
When ``idf.py`` does something, it prints each command that it runs for easy reference. For example, the ``idf.py build`` command is the same as running these commands in a bash shell (or similar commands for Windows Command Prompt)::
|
||||
|
||||
|
@ -76,8 +80,10 @@ It's not necessary to run ``cmake`` more than once. After the first build, you o
|
|||
If using CMake with ``ninja`` or ``make``, there are also targets for more of the ``idf.py`` sub-commands. For example, running ``make menuconfig`` or ``ninja menuconfig`` in the build directory will work the same as ``idf.py menuconfig``.
|
||||
|
||||
.. note::
|
||||
|
||||
If you're already familiar with CMake_, you may find the ESP-IDF CMake-based build system unusual because it wraps a lot of CMake's functionality to reduce boilerplate. See `writing pure CMake components`_ for some information about writing more "CMake style" components.
|
||||
|
||||
|
||||
.. _flash-with-ninja-or-make:
|
||||
|
||||
Flashing with Ninja or Make
|
||||
|
@ -97,13 +103,18 @@ When flashing this way, optionally set the ``ESPPORT`` and ``ESPBAUD`` environme
|
|||
|
||||
ESPPORT=/dev/ttyUSB0 ninja flash
|
||||
|
||||
.. note:: Providing environment variables at the start of the command like this is Bash shell Syntax. It will work on Linux and macOS. It won't work when using Windows Command Prompt, but it will work when using Bash-like shells on Windows.
|
||||
.. note::
|
||||
|
||||
Providing environment variables at the start of the command like this is Bash shell Syntax. It will work on Linux and macOS. It won't work when using Windows Command Prompt, but it will work when using Bash-like shells on Windows.
|
||||
|
||||
Or::
|
||||
|
||||
make -j3 app-flash ESPPORT=COM4 ESPBAUD=2000000
|
||||
|
||||
.. note:: Providing variables at the end of the command line is ``make`` syntax, and works for ``make`` on all platforms.
|
||||
.. note::
|
||||
|
||||
Providing variables at the end of the command line is ``make`` syntax, and works for ``make`` on all platforms.
|
||||
|
||||
|
||||
Using CMake in an IDE
|
||||
---------------------
|
||||
|
@ -114,6 +125,7 @@ When adding custom non-build steps like "flash" to the IDE, it is recommended to
|
|||
|
||||
For more detailed information about integrating ESP-IDF with CMake into an IDE, see `Build System Metadata`_.
|
||||
|
||||
|
||||
.. _setting-python-interpreter:
|
||||
|
||||
Setting up the Python Interpreter
|
||||
|
@ -121,7 +133,7 @@ Setting up the Python Interpreter
|
|||
|
||||
ESP-IDF works well with Python version 3.8+.
|
||||
|
||||
``idf.py`` and other Python scripts will run with the default Python interpreter, i.e. ``python``. You can switch to a different one like ``python3 $IDF_PATH/tools/idf.py ...``, or you can set up a shell alias or another script to simplify the command.
|
||||
``idf.py`` and other Python scripts will run with the default Python interpreter, i.e., ``python``. You can switch to a different one like ``python3 $IDF_PATH/tools/idf.py ...``, or you can set up a shell alias or another script to simplify the command.
|
||||
|
||||
If using CMake directly, running ``cmake -D PYTHON=python3 ...`` will cause CMake to override the default Python interpreter.
|
||||
|
||||
|
@ -129,12 +141,13 @@ If using an IDE with CMake, setting the ``PYTHON`` value as a CMake cache overri
|
|||
|
||||
To manage the Python version more generally via the command line, check out the tools pyenv_ or virtualenv_. These let you change the default Python version.
|
||||
|
||||
|
||||
.. _example-project-structure:
|
||||
|
||||
Example Project
|
||||
===============
|
||||
|
||||
.. highlight:: none
|
||||
.. code-block:: none
|
||||
|
||||
An example project directory tree might look like this::
|
||||
|
||||
|
@ -175,15 +188,17 @@ Component directories each contain a component ``CMakeLists.txt`` file. This fil
|
|||
|
||||
Each component may also include a ``Kconfig`` file defining the `component configuration`_ options that can be set via ``menuconfig``. Some components may also include ``Kconfig.projbuild`` and ``project_include.cmake`` files, which are special files for `overriding parts of the project`_.
|
||||
|
||||
|
||||
Project CMakeLists File
|
||||
=======================
|
||||
|
||||
Each project has a single top-level ``CMakeLists.txt`` file that contains build settings for the entire project. By default, the project CMakeLists can be quite minimal.
|
||||
|
||||
|
||||
Minimal Example CMakeLists
|
||||
--------------------------
|
||||
|
||||
.. highlight:: cmake
|
||||
.. code-block:: cmake
|
||||
|
||||
Minimal project::
|
||||
|
||||
|
@ -191,6 +206,7 @@ Minimal project::
|
|||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||
project(myProject)
|
||||
|
||||
|
||||
.. _project-mandatory-parts:
|
||||
|
||||
Mandatory Parts
|
||||
|
@ -202,6 +218,7 @@ The inclusion of these three lines, in the order shown above, is necessary for e
|
|||
- ``include($ENV{IDF_PATH}/tools/cmake/project.cmake)`` pulls in the rest of the CMake functionality to configure the project, discover all the components, etc.
|
||||
- ``project(myProject)`` creates the project itself, and specifies the project name. The project name is used for the final binary output files of the app - ie ``myProject.elf``, ``myProject.bin``. Only one project can be defined per CMakeLists file.
|
||||
|
||||
|
||||
.. _optional_project_variable:
|
||||
|
||||
Optional Project Variables
|
||||
|
@ -221,6 +238,7 @@ Any paths in these variables can be absolute paths, or set relative to the proje
|
|||
|
||||
To set these variables, use the `cmake set command <cmake set_>`_ ie ``set(VARIABLE "VALUE")``. The ``set()`` commands should be placed after the ``cmake_minimum(...)`` line but before the ``include(...)`` line.
|
||||
|
||||
|
||||
.. _rename-main:
|
||||
|
||||
Renaming ``main`` Component
|
||||
|
@ -230,7 +248,7 @@ The build system provides special treatment to the ``main`` component. It is a c
|
|||
|
||||
1. Rename ``main`` directory.
|
||||
2. Set ``EXTRA_COMPONENT_DIRS`` in the project CMakeLists.txt to include the renamed ``main`` directory.
|
||||
3. Specify the dependencies in the renamed component's CMakeLists.txt file via REQUIRES or PRIV_REQUIRES arguments :ref:`on component registration<cmake_minimal_component_cmakelists>`.
|
||||
3. Specify the dependencies in the renamed component's CMakeLists.txt file via REQUIRES or PRIV_REQUIRES arguments :ref:`on component registration <cmake_minimal_component_cmakelists>`.
|
||||
|
||||
|
||||
Overriding Default Build Specifications
|
||||
|
@ -238,7 +256,7 @@ Overriding Default Build Specifications
|
|||
|
||||
The build sets some global build specifications (compile flags, definitions, etc.) that gets used in compiling all sources from all components.
|
||||
|
||||
.. highlight:: cmake
|
||||
.. code-block:: cmake
|
||||
|
||||
For example, one of the default build specifications set is the compile option ``-Wextra``. Suppose a user wants to use override this with ``-Wno-extra``,
|
||||
it should be done after ``project()``::
|
||||
|
@ -252,6 +270,7 @@ it should be done after ``project()``::
|
|||
|
||||
This ensures that the compile options set by the user won't be overridden by the default build specifications, since the latter are set inside ``project()``.
|
||||
|
||||
|
||||
.. _component-directories:
|
||||
|
||||
Component CMakeLists Files
|
||||
|
@ -261,6 +280,7 @@ Each project contains one or more components. Components can be part of ESP-IDF,
|
|||
|
||||
A component is any directory in the ``COMPONENT_DIRS`` list which contains a ``CMakeLists.txt`` file.
|
||||
|
||||
|
||||
Searching for Components
|
||||
------------------------
|
||||
|
||||
|
@ -268,6 +288,7 @@ The list of directories in ``COMPONENT_DIRS`` is searched for the project's comp
|
|||
|
||||
When CMake runs to configure the project, it logs the components included in the build. This list can be useful for debugging the inclusion/exclusion of certain components.
|
||||
|
||||
|
||||
.. _cmake-components-same-name:
|
||||
|
||||
Multiple Components with the Same Name
|
||||
|
@ -277,12 +298,13 @@ When ESP-IDF is collecting all the components to compile, it will do this in the
|
|||
|
||||
.. note:: If a component is overridden in an existing project by moving it to a new location, the project will not automatically see the new component path. Run ``idf.py reconfigure`` (or delete the project build folder) and then build again.
|
||||
|
||||
|
||||
.. _cmake_minimal_component_cmakelists:
|
||||
|
||||
Minimal Component CMakeLists
|
||||
----------------------------
|
||||
|
||||
.. highlight:: cmake
|
||||
.. code-block:: cmake
|
||||
|
||||
The minimal component ``CMakeLists.txt`` file simply registers the component to the build system using ``idf_component_register``::
|
||||
|
||||
|
@ -298,10 +320,11 @@ A library with the name of the component will be built and linked to the final a
|
|||
|
||||
Directories are usually specified relative to the ``CMakeLists.txt`` file itself, although they can be absolute.
|
||||
|
||||
There are other arguments that can be passed to ``idf_component_register``. These arguments are discussed :ref:`here<cmake-component-register>`.
|
||||
There are other arguments that can be passed to ``idf_component_register``. These arguments are discussed :ref:`here <cmake-component-register>`.
|
||||
|
||||
See `example component requirements`_ and `example component CMakeLists`_ for more complete component ``CMakeLists.txt`` examples.
|
||||
|
||||
|
||||
.. _preset_component_variables:
|
||||
|
||||
Preset Component Variables
|
||||
|
@ -319,6 +342,7 @@ The following variables are set at the project level, but available for use in c
|
|||
- ``CONFIG_*``: Each value in the project configuration has a corresponding variable available in cmake. All names begin with ``CONFIG_``. :doc:`More information here </api-reference/kconfig>`.
|
||||
- ``ESP_PLATFORM``: Set to 1 when the CMake file is processed within the ESP-IDF build system.
|
||||
|
||||
|
||||
Build/Project Variables
|
||||
-----------------------
|
||||
|
||||
|
@ -339,14 +363,15 @@ The following are some project/build variables that are available as build prope
|
|||
* Otherwise, ``PROJECT_VER`` will be "1".
|
||||
- ``EXTRA_PARTITION_SUBTYPES``: CMake list of extra partition subtypes. Each subtype description is a comma-separated string with ``type_name, subtype_name, numeric_value`` format. Components may add new subtypes by appending them to this list.
|
||||
|
||||
Other build properties are listed :ref:`here<cmake-build-properties>`.
|
||||
Other build properties are listed :ref:`here <cmake-build-properties>`.
|
||||
|
||||
|
||||
.. _component_build_control:
|
||||
|
||||
Controlling Component Compilation
|
||||
---------------------------------
|
||||
|
||||
.. highlight:: cmake
|
||||
.. code-block:: cmake
|
||||
|
||||
To pass compiler options when compiling source files belonging to a particular component, use the `target_compile_options`_ function::
|
||||
|
||||
|
@ -367,6 +392,7 @@ This can be useful if there is upstream code that emits warnings.
|
|||
|
||||
When using these commands, place them after the call to ``idf_component_register`` in the component CMakeLists file.
|
||||
|
||||
|
||||
.. _component-configuration:
|
||||
|
||||
Component Configuration
|
||||
|
@ -380,6 +406,7 @@ To create a component Kconfig file, it is easiest to start with one of the Kconf
|
|||
|
||||
For an example, see `Adding conditional configuration`_.
|
||||
|
||||
|
||||
Preprocessor Definitions
|
||||
========================
|
||||
|
||||
|
@ -388,6 +415,7 @@ The ESP-IDF build system adds the following C preprocessor definitions on the co
|
|||
- ``ESP_PLATFORM`` : Can be used to detect that build happens within ESP-IDF.
|
||||
- ``IDF_VER`` : Defined to a git version string. E.g. ``v2.0`` for a tagged release or ``v1.0-275-g0efaa4f`` for an arbitrary commit.
|
||||
|
||||
|
||||
.. _component-requirements:
|
||||
|
||||
Component Requirements
|
||||
|
@ -395,6 +423,7 @@ Component Requirements
|
|||
|
||||
When compiling each component, the ESP-IDF build system recursively evaluates its dependencies. This means each component needs to declare the components that it depends on ("requires").
|
||||
|
||||
|
||||
When Writing a Component
|
||||
------------------------
|
||||
|
||||
|
@ -418,6 +447,7 @@ If a component only supports some target chips (values of ``IDF_TARGET``) then i
|
|||
|
||||
.. _example component requirements:
|
||||
|
||||
|
||||
Example of Component Requirements
|
||||
---------------------------------
|
||||
|
||||
|
@ -437,10 +467,11 @@ Imagine there is a ``car`` component, which uses the ``engine`` component, which
|
|||
- spark_plug.c
|
||||
- spark_plug.h
|
||||
|
||||
|
||||
Car Component
|
||||
^^^^^^^^^^^^^
|
||||
|
||||
.. highlight:: c
|
||||
.. code-block:: c
|
||||
|
||||
The ``car.h`` header file is the public interface for the ``car`` component. This header includes ``engine.h`` directly because it uses some declarations from this header::
|
||||
|
||||
|
@ -468,10 +499,11 @@ This means the ``car/CMakeLists.txt`` file needs to declare that ``car`` require
|
|||
- ``INCLUDE_DIRS`` gives the list of public include directories for this component. Because the public interface is ``car.h``, the directory containing ``car.h`` is listed here.
|
||||
- ``REQUIRES`` gives the list of components required by the public interface of this component. Because ``car.h`` is a public header and includes a header from ``engine``, we include ``engine`` here. This makes sure that any other component which includes ``car.h`` will be able to recursively include the required ``engine.h`` also.
|
||||
|
||||
|
||||
Engine Component
|
||||
^^^^^^^^^^^^^^^^
|
||||
|
||||
.. highlight:: c
|
||||
.. code-block:: c
|
||||
|
||||
The ``engine`` component also has a public header file ``include/engine.h``, but this header is simpler::
|
||||
|
||||
|
@ -500,6 +532,7 @@ This means that the ``engine/CMakeLists.txt`` file can use ``PRIV_REQUIRES``:
|
|||
|
||||
As a result, source files in the ``car`` component don't need the ``spark_plug`` include directories added to their compiler search path. This can speed up compilation, and stops compiler command lines from becoming longer than necessary.
|
||||
|
||||
|
||||
Spark Plug Component
|
||||
^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
|
@ -529,11 +562,13 @@ Each component's source file is compiled with these include path directories, as
|
|||
- The ``INCLUDE_DIRS`` belonging to all other components listed in the ``REQUIRES`` and ``PRIV_REQUIRES`` parameters (ie all the current component's public and private dependencies).
|
||||
- Recursively, all of the ``INCLUDE_DIRS`` of those components ``REQUIRES`` lists (ie all public dependencies of this component's dependencies, recursively expanded).
|
||||
|
||||
|
||||
Main Component Requirements
|
||||
---------------------------
|
||||
|
||||
The component named ``main`` is special because it automatically requires all other components in the build. So it's not necessary to pass ``REQUIRES`` or ``PRIV_REQUIRES`` to this component. See :ref:`renaming main <rename-main>` for a description of what needs to be changed if no longer using the ``main`` component.
|
||||
|
||||
|
||||
.. _component-common-requirements:
|
||||
|
||||
Common Component Requirements
|
||||
|
@ -543,6 +578,7 @@ To avoid duplication, every component automatically requires some "common" IDF c
|
|||
|
||||
The list of common components is: cxx, newlib, freertos, esp_hw_support, heap, log, soc, hal, esp_rom, esp_common, esp_system, xtensa/riscv.
|
||||
|
||||
|
||||
Including Components in the Build
|
||||
---------------------------------
|
||||
|
||||
|
@ -555,6 +591,7 @@ Including Components in the Build
|
|||
|
||||
- Setting ``COMPONENTS`` to the minimal list of required components can significantly reduce compile times.
|
||||
|
||||
|
||||
.. _component-circular-dependencies:
|
||||
|
||||
Circular Dependencies
|
||||
|
@ -562,7 +599,7 @@ Circular Dependencies
|
|||
|
||||
It's possible for a project to contain Component A that requires (``REQUIRES`` or ``PRIV_REQUIRES``) Component B, and Component B that requires Component A. This is known as a dependency cycle or a circular dependency.
|
||||
|
||||
CMake will usually handle circular dependencies automatically by repeating the component library names twice on the linker command line. However this strategy doesn't always work, and the build may fail with a linker error about "Undefined reference to ...", referencing a symbol defined by one of the components inside the circular dependency. This is particularly likely if there is a large circular dependency, i.e. A->B->C->D->A.
|
||||
CMake will usually handle circular dependencies automatically by repeating the component library names twice on the linker command line. However this strategy doesn't always work, and the build may fail with a linker error about "Undefined reference to ...", referencing a symbol defined by one of the components inside the circular dependency. This is particularly likely if there is a large circular dependency, i.e., A > B > C > D > A.
|
||||
|
||||
The best solution is to restructure the components to remove the circular dependency. In most cases, a software architecture without circular dependencies has desirable properties of modularity and clean layering and will be more maintainable in the long term. However, removing circular dependencies is not always possible.
|
||||
|
||||
|
@ -579,6 +616,7 @@ For example:
|
|||
- Usually increasing the value to 3 (default is 2) is enough, but if this doesn't work then try increasing the number further.
|
||||
- Adding this option will make the linker command line longer, and the linking stage slower.
|
||||
|
||||
|
||||
Advanced Workaround: Undefined Symbols
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
|
@ -597,6 +635,7 @@ For example, if component A depends on component B but component B also needs to
|
|||
|
||||
See the `target_link_libraries`_ documentation for more information about this CMake function.
|
||||
|
||||
|
||||
.. _component-requirements-implementation:
|
||||
|
||||
Requirements in the Build System Implementation
|
||||
|
@ -608,6 +647,7 @@ Requirements in the Build System Implementation
|
|||
- Configuration is then evaluated for the components included in the build.
|
||||
- Each component is included in the build normally and the CMakeLists.txt file is evaluated again to add the component libraries to the build.
|
||||
|
||||
|
||||
Component Dependency Order
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
|
@ -616,10 +656,11 @@ The order of components in the ``BUILD_COMPONENTS`` variable determines other or
|
|||
- Order that :ref:`project_include.cmake` files are included in the project.
|
||||
- Order that the list of header paths is generated for compilation (via ``-I`` argument). (Note that for a given component's source files, only that component's dependency's header paths are passed to the compiler.)
|
||||
|
||||
|
||||
Adding Link-Time Dependencies
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. highlight:: cmake
|
||||
.. code-block:: cmake
|
||||
|
||||
The ESP-IDF CMake helper function ``idf_component_add_link_dependency`` adds a link-only dependency between one component and another. In almost all cases, it is better to use the ``PRIV_REQUIRES`` feature in ``idf_component_register`` to create a dependency. However, in some cases, it's necessary to add the link-time dependency of another component to this component, i.e., the reverse order to ``PRIV_REQUIRES`` (for example: :doc:`/api-reference/peripherals/spi_flash/spi_flash_override_driver`).
|
||||
|
||||
|
@ -633,6 +674,7 @@ It's also possible to specify both components by name::
|
|||
|
||||
idf_component_add_link_dependency(FROM other_component TO that_component)
|
||||
|
||||
|
||||
.. _override_project_config:
|
||||
|
||||
Overriding Parts of the Project
|
||||
|
@ -640,7 +682,7 @@ Overriding Parts of the Project
|
|||
|
||||
.. _project_include.cmake:
|
||||
|
||||
project_include.cmake
|
||||
Project_include.cmake
|
||||
---------------------
|
||||
|
||||
For components that have build requirements that must be evaluated before any component CMakeLists files are evaluated, you can create a file called ``project_include.cmake`` in the component directory. This CMake file is included when ``project.cmake`` is evaluating the entire project.
|
||||
|
@ -651,10 +693,11 @@ Unlike component ``CMakeLists.txt`` files, when including a ``project_include.cm
|
|||
|
||||
Note that ``project_include.cmake`` isn't necessary for the most common component uses, such as adding include directories to the project, or ``LDFLAGS`` to the final linking step. These values can be customized via the ``CMakeLists.txt`` file itself. See `Optional Project Variables`_ for details.
|
||||
|
||||
``project_include.cmake`` files are included in the order given in ``BUILD_COMPONENTS`` variable (as logged by CMake). This means that a component's ``project_include.cmake`` file will be included after it's all dependencies' ``project_include.cmake`` files, unless both components are part of a dependency cycle. This is important if a ``project_include.cmake`` file relies on variables set by another component. See also :ref:`above<component-requirements-implementation>`.
|
||||
``project_include.cmake`` files are included in the order given in ``BUILD_COMPONENTS`` variable (as logged by CMake). This means that a component's ``project_include.cmake`` file will be included after it's all dependencies' ``project_include.cmake`` files, unless both components are part of a dependency cycle. This is important if a ``project_include.cmake`` file relies on variables set by another component. See also :ref:`above <component-requirements-implementation>`.
|
||||
|
||||
Take great care when setting variables or targets in a ``project_include.cmake`` file. As the values are included in the top-level project CMake pass, they can influence or break functionality across all components!
|
||||
|
||||
|
||||
KConfig.projbuild
|
||||
-----------------
|
||||
|
||||
|
@ -664,6 +707,7 @@ Take care when adding configuration values in this file, as they will be include
|
|||
|
||||
``project_include.cmake`` files are used inside ESP-IDF, for defining project-wide build features such as ``esptool.py`` command line arguments and the ``bootloader`` "special app".
|
||||
|
||||
|
||||
Wrappers to Redefine or Extend Existing Functions
|
||||
-------------------------------------------------
|
||||
|
||||
|
@ -679,7 +723,8 @@ The linker will provide a new symbol named ``__real_function_to_redefine`` which
|
|||
|
||||
This mechanism is shown in the example :example:`build_system/wrappers`. Check :idf_file:`examples/build_system/wrappers/README.md` for more details.
|
||||
|
||||
Override the default Bootloader
|
||||
|
||||
Override the Default Bootloader
|
||||
-------------------------------
|
||||
|
||||
Thanks to the optional ``bootloader_components`` directory present in your ESP-IDf project, it is possible to override the default ESP-IDF bootloader. To do so, a new ``bootloader_components/main`` component should be defined, which will make the project directory tree look like the following:
|
||||
|
@ -712,6 +757,7 @@ It is important to note that this can also be used for any other bootloader comp
|
|||
|
||||
See :example:`custom_bootloader/bootloader_override` for an example of overriding the default bootloader.
|
||||
|
||||
|
||||
.. _config_only_component:
|
||||
|
||||
Configuration-Only Components
|
||||
|
@ -719,6 +765,7 @@ Configuration-Only Components
|
|||
|
||||
Special components which contain no source files, only ``Kconfig.projbuild`` and ``KConfig``, can have a one-line ``CMakeLists.txt`` file which calls the function ``idf_component_register()`` with no arguments specified. This function will include the component in the project build, but no library will be built *and* no header files will be added to any included paths.
|
||||
|
||||
|
||||
Debugging CMake
|
||||
===============
|
||||
|
||||
|
@ -734,6 +781,7 @@ When included from a project CMakeLists file, the ``project.cmake`` file defines
|
|||
|
||||
It also defines an overridden custom version of the built-in CMake_ ``project`` function. This function is overridden to add all of the ESP-IDF specific project functionality.
|
||||
|
||||
|
||||
.. _warn-undefined-variables:
|
||||
|
||||
Warning On Undefined Variables
|
||||
|
@ -745,6 +793,7 @@ To enable this function, we can pass the ``--warn-uninitialized`` flag to CMake_
|
|||
|
||||
Browse the :idf_file:`/tools/cmake/project.cmake` file and supporting functions in :idf:`/tools/cmake/` for more details.
|
||||
|
||||
|
||||
.. _component_cmakelists_example:
|
||||
|
||||
Example Component CMakeLists
|
||||
|
@ -754,6 +803,7 @@ Because the build environment tries to set reasonable defaults that will work mo
|
|||
|
||||
Here are some more advanced examples of component CMakeLists files.
|
||||
|
||||
|
||||
.. _add_conditional_config:
|
||||
|
||||
Adding Conditional Configuration
|
||||
|
@ -761,7 +811,7 @@ Adding Conditional Configuration
|
|||
|
||||
The configuration system can be used to conditionally compile some files depending on the options selected in the project configuration.
|
||||
|
||||
.. highlight:: none
|
||||
.. code-block:: none
|
||||
|
||||
``Kconfig``::
|
||||
|
||||
|
@ -804,7 +854,7 @@ This can also be used to select or stub out an implementation, as such:
|
|||
help
|
||||
Select this to output temperature plots
|
||||
|
||||
.. highlight:: cmake
|
||||
.. code-block:: cmake
|
||||
|
||||
``CMakeLists.txt``::
|
||||
|
||||
|
@ -822,6 +872,7 @@ This can also be used to select or stub out an implementation, as such:
|
|||
idf_component_register(SRCS "${srcs}"
|
||||
...)
|
||||
|
||||
|
||||
Conditions Which Depend on the Target
|
||||
-------------------------------------
|
||||
|
||||
|
@ -858,6 +909,7 @@ In this example, logo.h will be generated in the current directory (the build di
|
|||
|
||||
If a a source file from another component included ``logo.h``, then ``add_dependencies`` would need to be called to add a dependency between the two components, to ensure that the component source files were always compiled in the correct order.
|
||||
|
||||
|
||||
.. _cmake_embed_data:
|
||||
|
||||
Embedding Binary Data
|
||||
|
@ -875,7 +927,7 @@ Or if the file is a string, you can use the variable ``EMBED_TXTFILES``. This wi
|
|||
idf_component_register(...
|
||||
EMBED_TXTFILES server_root_cert.pem)
|
||||
|
||||
.. highlight:: c
|
||||
.. code-block:: c
|
||||
|
||||
The file's contents will be added to the .rodata section in flash, and are available via symbol names as follows::
|
||||
|
||||
|
@ -884,7 +936,7 @@ The file's contents will be added to the .rodata section in flash, and are avail
|
|||
|
||||
The names are generated from the full name of the file, as given in ``EMBED_FILES``. Characters /, ., etc. are replaced with underscores. The _binary prefix in the symbol name is added by objcopy and is the same for both text and binary files.
|
||||
|
||||
.. highlight:: cmake
|
||||
.. code-block:: cmake
|
||||
|
||||
To embed a file into a project, rather than a component, you can call the function ``target_add_binary_data`` like this::
|
||||
|
||||
|
@ -894,7 +946,7 @@ Place this line after the ``project()`` line in your project CMakeLists.txt file
|
|||
|
||||
For an example of using this technique, see the "main" component of the file_serving example :example_file:`protocols/http_server/file_serving/main/CMakeLists.txt` - two files are loaded at build time and linked into the firmware.
|
||||
|
||||
.. highlight:: cmake
|
||||
.. code-block:: cmake
|
||||
|
||||
It is also possible to embed a generated file::
|
||||
|
||||
|
@ -911,17 +963,19 @@ To specify a dependence on a target, use the ``DEPENDS`` argument::
|
|||
|
||||
The ``DEPENDS`` argument to ``target_add_binary_data`` ensures that the target executes first.
|
||||
|
||||
|
||||
Code and Data Placements
|
||||
------------------------
|
||||
|
||||
ESP-IDF has a feature called linker script generation that enables components to define where its code and data will be placed in memory through linker fragment files. These files are processed by the build system, and is used to augment the linker script used for linking app binary. See :doc:`Linker Script Generation <linker-script-generation>` for a quick start guide as well as a detailed discussion of the mechanism.
|
||||
|
||||
|
||||
.. _component-build-full-override:
|
||||
|
||||
Fully Overriding the Component Build Process
|
||||
--------------------------------------------
|
||||
|
||||
.. highlight:: cmake
|
||||
.. code-block:: cmake
|
||||
|
||||
Obviously, there are cases where all these recipes are insufficient for a certain component, for example when the component is basically a wrapper around another third-party component not originally intended to be compiled under this build system. In that case, it's possible to forego the ESP-IDF build system entirely by using a CMake feature called ExternalProject_. Example component CMakeLists::
|
||||
|
||||
|
@ -963,6 +1017,7 @@ Obviously, there are cases where all these recipes are insufficient for a certai
|
|||
|
||||
.. note:: When using an external build process with PSRAM, remember to add ``-mfix-esp32-psram-cache-issue`` to the C compiler arguments. See :ref:`CONFIG_SPIRAM_CACHE_WORKAROUND` for details of this flag.
|
||||
|
||||
|
||||
.. _ADDITIONAL_CLEAN_FILES_note:
|
||||
|
||||
ExternalProject Dependencies and Clean Builds
|
||||
|
@ -979,6 +1034,7 @@ CMake has some unusual behavior around external project builds:
|
|||
|
||||
The best of these approaches for building an external project will depend on the project itself, its build system, and whether you anticipate needing to frequently recompile the project.
|
||||
|
||||
|
||||
.. _custom-sdkconfig-defaults:
|
||||
|
||||
Custom Sdkconfig Defaults
|
||||
|
@ -992,6 +1048,7 @@ When specifying multiple files, use a semicolon as the list separator. Files lis
|
|||
|
||||
Some of the IDF examples include a ``sdkconfig.ci`` file. This is part of the continuous integration (CI) test framework and is ignored by the normal build process.
|
||||
|
||||
|
||||
Target-dependent Sdkconfig Defaults
|
||||
-----------------------------------
|
||||
|
||||
|
@ -1001,6 +1058,7 @@ If ``SDKCONFIG_DEFAULTS`` is used to override the name of defaults file/files, t
|
|||
|
||||
For example, if ``SDKCONFIG_DEFAULTS="sdkconfig.defaults;sdkconfig_devkit1"``, and there is a file ``sdkconfig.defaults.esp32`` in the same folder, then the files will be applied in the following order: (1) sdkconfig.defaults (2) sdkconfig.defaults.esp32 (3) sdkconfig_devkit1.
|
||||
|
||||
|
||||
.. _flash_parameters:
|
||||
|
||||
Flash Arguments
|
||||
|
@ -1014,7 +1072,7 @@ After running a project build, the build directory contains binary output files
|
|||
- ``flash_app_args`` contains arguments to flash only the app.
|
||||
- ``flash_bootloader_args`` contains arguments to flash only the bootloader.
|
||||
|
||||
.. highlight:: bash
|
||||
.. code-block:: bash
|
||||
|
||||
You can pass any of these flasher argument files to ``esptool.py`` as follows::
|
||||
|
||||
|
@ -1024,6 +1082,7 @@ Alternatively, it is possible to manually copy the parameters from the argument
|
|||
|
||||
The build directory also contains a generated file ``flasher_args.json`` which contains project flash information, in JSON format. This file is used by ``idf.py`` and can also be used by other tools which need information about the project build.
|
||||
|
||||
|
||||
Building the Bootloader
|
||||
=======================
|
||||
|
||||
|
@ -1031,6 +1090,7 @@ The bootloader is a special "subproject" inside :idf:`/components/bootloader/sub
|
|||
|
||||
The subproject is inserted as an external project from the top-level project, by the file :idf_file:`/components/bootloader/project_include.cmake`. The main build process runs CMake for the subproject, which includes discovering components (a subset of the main components) and generating a bootloader-specific config (derived from the main ``sdkconfig``).
|
||||
|
||||
|
||||
.. _write-pure-component:
|
||||
|
||||
Writing Pure CMake Components
|
||||
|
@ -1040,7 +1100,7 @@ The ESP-IDF build system "wraps" CMake with the concept of "components", and hel
|
|||
|
||||
However, underneath the concept of "components" is a full CMake build system. It is also possible to make a component which is pure CMake.
|
||||
|
||||
.. highlight:: cmake
|
||||
.. code-block:: cmake
|
||||
|
||||
Here is an example minimal "pure CMake" component CMakeLists file for a component named ``json``::
|
||||
|
||||
|
@ -1054,12 +1114,13 @@ Here is an example minimal "pure CMake" component CMakeLists file for a componen
|
|||
- This file is quite simple as there are not a lot of source files. For components with a large number of files, the globbing behavior of ESP-IDF's component logic can make the component CMakeLists style simpler.)
|
||||
- Any time a component adds a library target with the component name, the ESP-IDF build system will automatically add this to the build, expose public include directories, etc. If a component wants to add a library target with a different name, dependencies will need to be added manually via CMake commands.
|
||||
|
||||
|
||||
Using Third-Party CMake Projects with Components
|
||||
================================================
|
||||
|
||||
CMake is used for a lot of open-source C and C++ projects — code that users can tap into for their applications. One of the benefits of having a CMake build system is the ability to import these third-party projects, sometimes even without modification! This allows for users to be able to get functionality that may not yet be provided by a component, or use another library for the same functionality.
|
||||
|
||||
.. highlight:: cmake
|
||||
.. code-block:: cmake
|
||||
|
||||
Importing a library might look like this for a hypothetical library ``foo`` to be used in the ``main`` component::
|
||||
|
||||
|
@ -1082,6 +1143,7 @@ It is also possible to wrap a third-party library to be used as a component in t
|
|||
|
||||
The CMake variable ``ESP_PLATFORM`` is set to 1 whenever the ESP-IDF build system is being used. Tests such as ``if (ESP_PLATFORM)`` can be used in generic CMake code if special IDF-specific logic is required.
|
||||
|
||||
|
||||
Using ESP-IDF Components from External Libraries
|
||||
------------------------------------------------
|
||||
|
||||
|
@ -1100,7 +1162,7 @@ For example, in the ``foo/CMakeLists.txt`` file::
|
|||
Using Prebuilt Libraries with Components
|
||||
========================================
|
||||
|
||||
.. highlight:: cmake
|
||||
.. code-block:: cmake
|
||||
|
||||
Another possibility is that you have a prebuilt static library (``.a`` file), built by some other build process.
|
||||
|
||||
|
@ -1119,12 +1181,13 @@ Take note that the prebuilt library must have been compiled for the same target
|
|||
|
||||
For an example, take a look at :example:`build_system/cmake/import_prebuilt`.
|
||||
|
||||
|
||||
Using ESP-IDF in Custom CMake Projects
|
||||
======================================
|
||||
|
||||
ESP-IDF provides a template CMake project for easily creating an application. However, in some instances the user might already have an existing CMake project or may want to create a custom one. In these cases it is desirable to be able to consume IDF components as libraries to be linked to the user's targets (libraries/executables).
|
||||
|
||||
It is possible to do so by using the :ref:`build system APIs provided<cmake_buildsystem_api>` by :idf_file:`tools/cmake/idf.cmake`. For example:
|
||||
It is possible to do so by using the :ref:`build system APIs provided <cmake_buildsystem_api>` by :idf_file:`tools/cmake/idf.cmake`. For example:
|
||||
|
||||
.. code-block:: cmake
|
||||
|
||||
|
@ -1153,25 +1216,26 @@ The example in :example:`build_system/cmake/idf_as_lib` demonstrates the creatio
|
|||
|
||||
.. note:: The IDF build system can only set compiler flags for source files that it builds. When an external CMakeLists.txt file is used and PSRAM is enabled, remember to add ``-mfix-esp32-psram-cache-issue`` to the C compiler arguments. See :ref:`CONFIG_SPIRAM_CACHE_WORKAROUND` for details of this flag.
|
||||
|
||||
|
||||
.. _cmake_buildsystem_api:
|
||||
|
||||
ESP-IDF CMake Build System API
|
||||
==============================
|
||||
|
||||
idf-build-commands
|
||||
Idf-build-commands
|
||||
------------------
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
idf_build_get_property(var property [GENERATOR_EXPRESSION])
|
||||
|
||||
Retrieve a :ref:`build property<cmake-build-properties>` *property* and store it in *var* accessible from the current scope. Specifying *GENERATOR_EXPRESSION* will retrieve the generator expression string for that property, instead of the actual value, which can be used with CMake commands that support generator expressions.
|
||||
Retrieve a :ref:`build property <cmake-build-properties>` *property* and store it in *var* accessible from the current scope. Specifying *GENERATOR_EXPRESSION* will retrieve the generator expression string for that property, instead of the actual value, which can be used with CMake commands that support generator expressions.
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
idf_build_set_property(property val [APPEND])
|
||||
|
||||
Set a :ref:`build property<cmake-build-properties>` *property* with value *val*. Specifying *APPEND* will append the specified value to the current value of the property. If the property does not previously exist or it is currently empty, the specified value becomes the first element/member instead.
|
||||
Set a :ref:`build property <cmake-build-properties>` *property* with value *val*. Specifying *APPEND* will append the specified value to the current value of the property. If the property does not previously exist or it is currently empty, the specified value becomes the first element/member instead.
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
|
@ -1205,7 +1269,7 @@ The call requires the target chip to be specified with *target* argument. Option
|
|||
- SDKCONFIG_DEFAULTS - list of files containing default config to use in the build (list must contain full paths); defaults to empty. For each value *filename* in the list, the config from file *filename.target*, if it exists, is also loaded.
|
||||
- BUILD_DIR - directory to place ESP-IDF build-related artifacts, such as generated binaries, text files, components; defaults to CMAKE_BINARY_DIR
|
||||
- COMPONENTS - select components to process among the components known by the build system (added via `idf_build_component`). This argument is used to trim the build.
|
||||
Other components are automatically added if they are required in the dependency chain, i.e. the public and private requirements of the components in this list are automatically added, and in turn the public and private requirements of those requirements, so on and so forth. If not specified, all components known to the build system are processed.
|
||||
Other components are automatically added if they are required in the dependency chain, i.e., the public and private requirements of the components in this list are automatically added, and in turn the public and private requirements of those requirements, so on and so forth. If not specified, all components known to the build system are processed.
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
|
@ -1219,9 +1283,10 @@ Specify the executable *executable* for ESP-IDF build. This attaches additional
|
|||
|
||||
Get the value of the specified config. Much like build properties, specifying *GENERATOR_EXPRESSION* will retrieve the generator expression string for that config, instead of the actual value, which can be used with CMake commands that support generator expressions. Actual config values are only known after call to ``idf_build_process``, however.
|
||||
|
||||
|
||||
.. _cmake-build-properties:
|
||||
|
||||
idf-build-properties
|
||||
Idf-build-properties
|
||||
--------------------
|
||||
|
||||
These are properties that describe the build. Values of build properties can be retrieved by using the build command ``idf_build_get_property``. For example, to get the Python interpreter used for the build:
|
||||
|
@ -1260,20 +1325,21 @@ These are properties that describe the build. Values of build properties can be
|
|||
- SDKCONFIG_JSON - full path to JSON file containing component configuration; set by ``idf_build_process``
|
||||
- SDKCONFIG_JSON_MENUS - full path to JSON file containing config menus; set by ``idf_build_process``
|
||||
|
||||
idf-component-commands
|
||||
|
||||
Idf-component-commands
|
||||
----------------------
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
idf_component_get_property(var component property [GENERATOR_EXPRESSION])
|
||||
|
||||
Retrieve a specified *component*'s :ref:`component property<cmake-component-properties>`, *property* and store it in *var* accessible from the current scope. Specifying *GENERATOR_EXPRESSION* will retrieve the generator expression string for that property, instead of the actual value, which can be used with CMake commands that support generator expressions.
|
||||
Retrieve a specified *component*'s :ref:`component property <cmake-component-properties>`, *property* and store it in *var* accessible from the current scope. Specifying *GENERATOR_EXPRESSION* will retrieve the generator expression string for that property, instead of the actual value, which can be used with CMake commands that support generator expressions.
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
idf_component_set_property(component property val [APPEND])
|
||||
|
||||
Set a specified *component*'s :ref:`component property<cmake-component-properties>`, *property* with value *val*. Specifying *APPEND* will append the specified value to the current value of the property. If the property does not previously exist or it is currently empty, the specified value becomes the first element/member instead.
|
||||
Set a specified *component*'s :ref:`component property <cmake-component-properties>`, *property* with value *val*. Specifying *APPEND* will append the specified value to the current value of the property. If the property does not previously exist or it is currently empty, the specified value becomes the first element/member instead.
|
||||
|
||||
.. _cmake-component-register:
|
||||
|
||||
|
@ -1303,7 +1369,7 @@ Commands that set and operate on variables are generally okay to call before ``i
|
|||
The arguments for ``idf_component_register`` include:
|
||||
|
||||
- SRCS - component source files used for creating a static library for the component; if not specified, component is a treated as a config-only component and an interface library is created instead.
|
||||
- SRC_DIRS, EXCLUDE_SRCS - used to glob source files (.c, .cpp, .S) by specifying directories, instead of specifying source files manually via SRCS. Note that this is subject to the :ref:`limitations of globbing in CMake<cmake-file-globbing>`. Source files specified in EXCLUDE_SRCS are removed from the globbed files.
|
||||
- SRC_DIRS, EXCLUDE_SRCS - used to glob source files (.c, .cpp, .S) by specifying directories, instead of specifying source files manually via SRCS. Note that this is subject to the :ref:`limitations of globbing in CMake <cmake-file-globbing>`. Source files specified in EXCLUDE_SRCS are removed from the globbed files.
|
||||
- INCLUDE_DIRS - paths, relative to the component directory, which will be added to the include search path for all other components which require the current component
|
||||
- PRIV_INCLUDE_DIRS - directory paths, must be relative to the component directory, which will be added to the include search path for this component's source files only
|
||||
- REQUIRES - public component requirements for the component
|
||||
|
@ -1314,14 +1380,15 @@ The arguments for ``idf_component_register`` include:
|
|||
- KCONFIG_PROJBUILD - override the default Kconfig.projbuild file
|
||||
- WHOLE_ARCHIVE - if specified, the component library is surrounded by ``-Wl,--whole-archive``, ``-Wl,--no-whole-archive`` when linked. This has the same effect as setting ``WHOLE_ARCHIVE`` component property.
|
||||
|
||||
The following are used for :ref:`embedding data into the component<cmake_embed_data>`, and is considered as source files when determining if a component is config-only. This means that even if the component does not specify source files, a static library is still created internally for the component if it specifies either:
|
||||
The following are used for :ref:`embedding data into the component <cmake_embed_data>`, and is considered as source files when determining if a component is config-only. This means that even if the component does not specify source files, a static library is still created internally for the component if it specifies either:
|
||||
|
||||
- EMBED_FILES - binary files to be embedded in the component
|
||||
- EMBED_TXTFILES - text files to be embedded in the component
|
||||
|
||||
|
||||
.. _cmake-component-properties:
|
||||
|
||||
idf-component-properties
|
||||
Idf-component-properties
|
||||
------------------------
|
||||
|
||||
These are properties that describe a component. Values of component properties can be retrieved by using the build command ``idf_component_get_property``. For example, to get the directory of the ``freertos`` component:
|
||||
|
@ -1333,7 +1400,7 @@ These are properties that describe a component. Values of component properties c
|
|||
|
||||
- COMPONENT_ALIAS - alias for COMPONENT_LIB used for linking the component to external targets; set by ``idf_build_component`` and alias library itself is created by ``idf_component_register``
|
||||
- COMPONENT_DIR - component directory; set by ``idf_build_component``
|
||||
- COMPONENT_OVERRIDEN_DIR - contains the directory of the original component if :ref:`this component overrides another component<cmake-components-same-name>`
|
||||
- COMPONENT_OVERRIDEN_DIR - contains the directory of the original component if :ref:`this component overrides another component <cmake-components-same-name>`
|
||||
- COMPONENT_LIB - name for created component static/interface library; set by ``idf_build_component`` and library itself is created by ``idf_component_register``
|
||||
- COMPONENT_NAME - name of the component; set by ``idf_build_component`` based on the component directory name
|
||||
- COMPONENT_TYPE - type of the component, whether LIBRARY or CONFIG_ONLY. A component is of type LIBRARY if it specifies source files or embeds a file
|
||||
|
@ -1352,12 +1419,13 @@ These are properties that describe a component. Values of component properties c
|
|||
- SRCS - list of component source files; set from SRCS or SRC_DIRS/EXCLUDE_SRCS argument of ``idf_component_register``
|
||||
- WHOLE_ARCHIVE - if this property is set to ``TRUE`` (or any boolean "true" CMake value: 1, ``ON``, ``YES``, ``Y``), the component library is surrounded by ``-Wl,--whole-archive``, ``-Wl,--no-whole-archive`` when linked. This can be used to force the linker to include every object file into the executable, even if the object file doesn't resolve any references from the rest of the application. This is commonly used when a component contains plugins or modules which rely on link-time registration. This property is ``FALSE`` by default. It can be set to ``TRUE`` from the component CMakeLists.txt file.
|
||||
|
||||
|
||||
.. _cmake-file-globbing:
|
||||
|
||||
File Globbing & Incremental Builds
|
||||
==================================
|
||||
|
||||
.. highlight:: cmake
|
||||
.. code-block:: cmake
|
||||
|
||||
The preferred way to include source files in an ESP-IDF component is to list them manually via SRCS argument to ``idf_component_register``::
|
||||
|
||||
|
@ -1384,6 +1452,7 @@ For project components (not part of ESP-IDF), there are a few different options:
|
|||
|
||||
The best option will depend on your particular project and its users.
|
||||
|
||||
|
||||
.. _build_system_metadata:
|
||||
|
||||
Build System Metadata
|
||||
|
@ -1398,6 +1467,7 @@ For integration into IDEs and other build systems, when CMake runs the build pro
|
|||
- ``config/sdkconfig.json`` is a JSON-formatted version of the project configuration values.
|
||||
- ``config/kconfig_menus.json`` is a JSON-formatted version of the menus shown in menuconfig, for use in external IDE UIs.
|
||||
|
||||
|
||||
JSON Configuration Server
|
||||
-------------------------
|
||||
|
||||
|
@ -1407,6 +1477,7 @@ You can run ``kconfserver`` from a project via ``idf.py confserver`` or ``ninja
|
|||
|
||||
For more information about ``kconfserver``, see the `esp-idf-kconfig documentation <https://github.com/espressif/esp-idf-kconfig/blob/master/docs/DOCUMENTATION.md>`_.
|
||||
|
||||
|
||||
Build System Internals
|
||||
======================
|
||||
|
||||
|
@ -1415,8 +1486,8 @@ Build Scripts
|
|||
|
||||
The listfiles for the ESP-IDF build system reside in :idf:`/tools/cmake`. The modules which implement core build system functionality are as follows:
|
||||
|
||||
- build.cmake - Build related commands i.e. build initialization, retrieving/setting build properties, build processing.
|
||||
- component.cmake - Component related commands i.e. adding components, retrieving/setting component properties, registering components.
|
||||
- build.cmake - Build related commands i.e., build initialization, retrieving/setting build properties, build processing.
|
||||
- component.cmake - Component related commands i.e., adding components, retrieving/setting component properties, registering components.
|
||||
- kconfig.cmake - Generation of configuration files (sdkconfig, sdkconfig.h, sdkconfig.cmake, etc.) from Kconfig files.
|
||||
- ldgen.cmake - Generation of final linker script from linker fragment files.
|
||||
- target.cmake - Setting build target and toolchain file.
|
||||
|
@ -1429,6 +1500,7 @@ The listfiles for the ESP-IDF build system reside in :idf:`/tools/cmake`. The mo
|
|||
|
||||
The rest of the files in :idf:`/tools/cmake` are support or third-party scripts used in the build process.
|
||||
|
||||
|
||||
Build Process
|
||||
-------------
|
||||
|
||||
|
@ -1445,6 +1517,7 @@ This section describes the standard ESP-IDF application build process. The build
|
|||
Processing -> Finalization
|
||||
}
|
||||
|
||||
|
||||
Initialization
|
||||
^^^^^^^^^^^^^^
|
||||
|
||||
|
@ -1455,7 +1528,7 @@ This phase sets up necessary parameters for the build.
|
|||
- Add :idf:`/tools/cmake` to ``CMAKE_MODULE_PATH`` and include core modules plus the various helper/third-party scripts.
|
||||
- Set build tools/executables such as default Python interpreter.
|
||||
- Get ESP-IDF git revision and store as ``IDF_VER``.
|
||||
- Set global build specifications i.e. compile options, compile definitions, include directories for all components in the build.
|
||||
- Set global build specifications i.e., compile options, compile definitions, include directories for all components in the build.
|
||||
- Add components in :idf:`components` to the build.
|
||||
- The initial part of the custom ``project()`` command performs the following steps:
|
||||
- Set ``IDF_TARGET`` from environment variable or CMake cache and the corresponding ``CMAKE_TOOLCHAIN_FILE`` to be used.
|
||||
|
@ -1464,6 +1537,7 @@ This phase sets up necessary parameters for the build.
|
|||
|
||||
The call to ``idf_build_process()`` command marks the end of this phase.
|
||||
|
||||
|
||||
Enumeration
|
||||
^^^^^^^^^^^
|
||||
This phase builds a final list of components to be processed in the build, and is performed in the first half of ``idf_build_process()``.
|
||||
|
@ -1471,6 +1545,7 @@ Enumeration
|
|||
- Retrieve each component's public and private requirements. A child process is created which executes each component's CMakeLists.txt in script mode. The values of ``idf_component_register`` REQUIRES and PRIV_REQUIRES argument is returned to the parent build process. This is called early expansion. The variable ``CMAKE_BUILD_EARLY_EXPANSION`` is defined during this step.
|
||||
- Recursively include components based on public and private requirements.
|
||||
|
||||
|
||||
Processing
|
||||
^^^^^^^^^^
|
||||
|
||||
|
@ -1480,6 +1555,7 @@ Processing
|
|||
- Include each component's ``project_include.cmake``.
|
||||
- Add each component as a subdirectory, processing its CMakeLists.txt. The component CMakeLists.txt calls the registration command, ``idf_component_register`` which adds source files, include directories, creates component library, links dependencies, etc.
|
||||
|
||||
|
||||
Finalization
|
||||
^^^^^^^^^^^^
|
||||
This phase is everything after ``idf_build_process()``.
|
||||
|
@ -1497,11 +1573,13 @@ Migrating from ESP-IDF GNU Make System
|
|||
|
||||
Some aspects of the CMake-based ESP-IDF build system are very similar to the older GNU Make-based system. The developer needs to provide values the include directories, source files etc. There is a syntactical difference, however, as the developer needs to pass these as arguments to the registration command, ``idf_component_register``.
|
||||
|
||||
|
||||
Automatic Conversion Tool
|
||||
-------------------------
|
||||
|
||||
An automatic project conversion tool is available in `tools/cmake/convert_to_cmake.py` in ESP-IDF v4.x releases. The script was removed in v5.0 because of its `make` build system dependency.
|
||||
|
||||
|
||||
No Longer Available in CMake
|
||||
----------------------------
|
||||
|
||||
|
@ -1522,6 +1600,7 @@ Some features are significantly different or removed in the CMake-based system.
|
|||
- ``COMPONENT_CONFIG_ONLY``: Call ``idf_component_register`` without any arguments instead. See `Configuration-Only Components`_.
|
||||
- ``CFLAGS``, ``CPPFLAGS``, ``CXXFLAGS``: Use equivalent CMake commands instead. See `Controlling Component Compilation`_.
|
||||
|
||||
|
||||
No Default Values
|
||||
-----------------
|
||||
|
||||
|
@ -1530,10 +1609,11 @@ Unlike in the legacy Make-based build system, the following have no default valu
|
|||
- Source directories (``COMPONENT_SRCDIRS`` variable in Make, ``SRC_DIRS`` argument to ``idf_component_register`` in CMake)
|
||||
- Include directories (``COMPONENT_ADD_INCLUDEDIRS`` variable in Make, ``INCLUDE_DIRS`` argument to ``idf_component_register`` in CMake)
|
||||
|
||||
|
||||
No Longer Necessary
|
||||
-------------------
|
||||
|
||||
- In the legacy Make-based build system, it is required to also set ``COMPONENT_SRCDIRS`` if ``COMPONENT_SRCS`` is set. In CMake, the equivalent is not necessary i.e. specifying ``SRC_DIRS`` to ``idf_component_register`` if ``SRCS`` is also specified (in fact, ``SRCS`` is ignored if ``SRC_DIRS`` is specified).
|
||||
- In the legacy Make-based build system, it is required to also set ``COMPONENT_SRCDIRS`` if ``COMPONENT_SRCS`` is set. In CMake, the equivalent is not necessary i.e., specifying ``SRC_DIRS`` to ``idf_component_register`` if ``SRCS`` is also specified (in fact, ``SRCS`` is ignored if ``SRC_DIRS`` is specified).
|
||||
|
||||
|
||||
Flashing from Make
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
RF Coexistence
|
||||
==================
|
||||
|
||||
:link_to_translation:`zh_CN:[中文]`
|
||||
|
||||
Overview
|
||||
|
@ -10,6 +11,7 @@ Overview
|
|||
|
||||
Supported Coexistence Scenario for {IDF_TARGET_NAME}
|
||||
---------------------------------------------------------------------
|
||||
|
||||
.. only:: esp32c3 or esp32s3 or esp32 or esp32c6
|
||||
|
||||
.. table:: Supported Features of Wi-Fi and BLE Coexistence
|
||||
|
@ -75,6 +77,7 @@ Supported Coexistence Scenario for {IDF_TARGET_NAME}
|
|||
X: not supported
|
||||
S: supported and performance is stable in STA mode, otherwise not supported
|
||||
|
||||
|
||||
Coexistence Mechanism and Policy
|
||||
------------------------------------------------
|
||||
|
||||
|
@ -153,6 +156,7 @@ Dynamic Priority
|
|||
|
||||
The coexistence module assigns different priorities to different status of Wi-Fi and Bluetooth. And the priority for each status is dynamic. For example, in every N BLE Advertising events, there is always one event with high priority. If a high-priority BLE Advertising event occurs within the Wi-Fi time slice, the right to use the RF may be preempted by BLE.
|
||||
|
||||
|
||||
.. only:: SOC_WIFI_SUPPORTED
|
||||
|
||||
Wi-Fi Connectionless Modules Coexistence
|
||||
|
@ -164,6 +168,7 @@ The coexistence module assigns different priorities to different status of Wi-Fi
|
|||
|
||||
Please refer to :ref:`connectionless module power save <connectionless-module-power-save>` to get more detail.
|
||||
|
||||
|
||||
How to Use the Coexistence Feature
|
||||
--------------------------------------
|
||||
|
||||
|
@ -172,6 +177,7 @@ Coexistence API
|
|||
|
||||
For most coexistence cases, {IDF_TARGET_NAME} will switch the coexistence status automatically without calling API. However, {IDF_TARGET_NAME} provides two APIs for the coexistence of BLE MESH and Wi-Fi. When the status of BLE MESH changes, call :code:`esp_coex_status_bit_clear` to clear the previous status first and then call :code:`esp_coex_status_bit_set` to set the current status.
|
||||
|
||||
|
||||
BLE MESH Coexistence Status
|
||||
""""""""""""""""""""""""""""""""""
|
||||
|
||||
|
@ -185,7 +191,7 @@ As the firmware of Wi-Fi and Bluetooth are not aware of the current scenario of
|
|||
Coexistence API Error Codes
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
All coexistence APIs have custom return values, i.e. error codes. These error codes can be categorized as:
|
||||
All coexistence APIs have custom return values, i.e., error codes. These error codes can be categorized as:
|
||||
|
||||
- No error. For example, the return value ESP_OK siginifies the API returned successfully.
|
||||
- Recoverable errors. For example, the return value ESP_ERR_INVALID_ARG signifies API parameter errors.
|
||||
|
|
|
@ -12,6 +12,7 @@ A core dump contains snapshots of all tasks in the system at the moment of failu
|
|||
|
||||
Core dump data is saved to a core dump file according to a particular format, see :doc:`Core dump internals <core_dump_internals>` for more details. However, ESP-IDF's ``idf.py`` command provides special subcommands to decode and analyze the core dump file.
|
||||
|
||||
|
||||
Configurations
|
||||
--------------
|
||||
|
||||
|
@ -20,6 +21,7 @@ Destination
|
|||
|
||||
The :ref:`CONFIG_ESP_COREDUMP_TO_FLASH_OR_UART` option enables or disables core dump, and selects the core dump destination if enabled. When a crash occurs, the generated core dump file can either be saved to flash, or output to a connected host over UART.
|
||||
|
||||
|
||||
Format & Size
|
||||
^^^^^^^^^^^^^
|
||||
|
||||
|
@ -44,6 +46,7 @@ Core dump data integrity checking is supported via the ``Components`` > ``Core d
|
|||
|
||||
The SHA256 hash algorithm provides a greater probability of detecting corruption than a CRC32 with multiple-bit errors.
|
||||
|
||||
|
||||
Reserved Stack Size
|
||||
^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
|
@ -55,6 +58,7 @@ Setting this option to 0 bytes will cause the core dump routines to run from the
|
|||
|
||||
If a separate stack is used, the recommended stack size should be larger than 800 bytes to ensure that the core dump routines themselves do not cause a stack overflow.
|
||||
|
||||
|
||||
Core Dump to Flash
|
||||
------------------
|
||||
|
||||
|
@ -93,11 +97,13 @@ or
|
|||
|
||||
idf.py coredump-debug
|
||||
|
||||
|
||||
Core Dump to UART
|
||||
-----------------
|
||||
|
||||
When the core dump file is output to UART, the output file is Base64-encoded. The :ref:`CONFIG_ESP_COREDUMP_DECODE` option allows for selecting whether the output file is automatically decoded by the ESP-IDF monitor or kept encoded for manual decoding.
|
||||
|
||||
|
||||
Automatic Decoding
|
||||
^^^^^^^^^^^^^^^^^^
|
||||
|
||||
|
@ -144,6 +150,7 @@ The :ref:`CONFIG_ESP_COREDUMP_UART_DELAY` allows for an optional delay to be add
|
|||
===================== ESP32 CORE DUMP END =====================
|
||||
===============================================================
|
||||
|
||||
|
||||
Manual Decoding
|
||||
^^^^^^^^^^^^^^^
|
||||
|
||||
|
@ -200,6 +207,7 @@ Supported Notations and RAM Regions
|
|||
:SOC_RTC_FAST_MEM_SUPPORTED or SOC_RTC_SLOW_MEM_SUPPORTED: * ``COREDUMP_RTC_ATTR`` places the variable into the RTC area, which is included in the dump.
|
||||
:SOC_RTC_FAST_MEM_SUPPORTED: * ``COREDUMP_RTC_FAST_ATTR`` places the variable into the RTC_FAST area, which is included in the dump.
|
||||
|
||||
|
||||
Example
|
||||
^^^^^^^
|
||||
|
||||
|
@ -234,11 +242,13 @@ Example
|
|||
(gdb) p global_var
|
||||
$1 = 25 '\031'
|
||||
|
||||
|
||||
Running ``idf.py coredump-info`` and ``idf.py coredump-debug``
|
||||
--------------------------------------------------------------
|
||||
|
||||
``idf.py coredump-info --help`` and ``idf.py coredump-debug --help`` commands can be used to get more details on usage.
|
||||
|
||||
|
||||
Related Documents
|
||||
^^^^^^^^^^^^^^^^^
|
||||
|
||||
|
|
|
@ -29,6 +29,7 @@ Here is an overview of the core dump layout:
|
|||
|
||||
The format of the image file shown in the above pictures represents the current version of the image and can be changed in future releases.
|
||||
|
||||
|
||||
Overview of Implementation
|
||||
--------------------------
|
||||
|
||||
|
|
|
@ -15,11 +15,13 @@ The following C++ features are supported:
|
|||
- :doc:`thread-local-storage` (``thread_local`` keyword)
|
||||
- All C++ features implemented by GCC, except for some :ref:`cplusplus_limitations`. See `GCC documentation <https://gcc.gnu.org/projects/cxx-status.html>`_ for details on features implemented by GCC.
|
||||
|
||||
|
||||
``esp-idf-cxx`` Component
|
||||
-------------------------
|
||||
|
||||
`esp-idf-cxx <https://github.com/espressif/esp-idf-cxx>`_ component provides higher-level C++ APIs for some of the ESP-IDF features. This component is available from the `ESP-IDF Component Registry <https://components.espressif.com/components/espressif/esp-idf-cxx>`_.
|
||||
|
||||
|
||||
C++ Language Standard
|
||||
---------------------
|
||||
|
||||
|
@ -34,6 +36,7 @@ To compile the source code of a certain component using a different language sta
|
|||
|
||||
Use ``PUBLIC`` instead of ``PRIVATE`` if the public header files of the component also need to be compiled with the same language standard.
|
||||
|
||||
|
||||
.. _cplusplus_multithreading:
|
||||
|
||||
Multithreading
|
||||
|
@ -47,6 +50,7 @@ See :example:`cxx/pthread` for an example of creating threads in C++.
|
|||
|
||||
The destructor of `std::jthread <https://en.cppreference.com/w/cpp/thread/jthread>`_ can only safely be called from a task that has been created by :ref:`posix_thread_api` or by the `C++ threading library API <https://en.cppreference.com/w/cpp/thread>`_.
|
||||
|
||||
|
||||
.. _cplusplus_exceptions:
|
||||
|
||||
Exception Handling
|
||||
|
@ -60,6 +64,7 @@ C++ Exceptions should **only** be used for exceptional cases, i.e., something ha
|
|||
|
||||
See :example:`cxx/exceptions` for an example of C++ exception handling.
|
||||
|
||||
|
||||
C++ Exception Handling and Resource Usage
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
|
@ -78,6 +83,7 @@ The run time of code using C++ exceptions depends on what actually happens at ru
|
|||
|
||||
If an exception is thrown, the run time of the code that unwinds the stack is orders of magnitude slower than code returning an error code. The significance of the increased run time will depend on the application's requirements and implementation of error handling (e.g., requiring user input or messaging to a cloud). As a result, exception-throwing code should never be used in real-time critical code paths.
|
||||
|
||||
|
||||
.. _cplusplus_rtti:
|
||||
|
||||
Runtime Type Information (RTTI)
|
||||
|
@ -95,6 +101,7 @@ Developing in C++
|
|||
|
||||
The following sections provide tips on developing ESP-IDF applications in C++.
|
||||
|
||||
|
||||
Combining C and C++ Code
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
|
@ -153,6 +160,7 @@ ESP-IDF expects the application entry point, ``app_main``, to be defined with C
|
|||
{
|
||||
}
|
||||
|
||||
|
||||
.. _cplusplus_designated_initializers:
|
||||
|
||||
Designated Initializers
|
||||
|
@ -171,6 +179,7 @@ iostream
|
|||
1. Normally, ESP-IDF build process eliminates the unused code. However, in the case of iostreams, simply including ``<iostream>`` header in one of the source files significantly increases the binary size by about 200 kB.
|
||||
2. By default, ESP-IDF uses a simple non-blocking implementation of the standard input stream (``stdin``). To get the usual behavior of ``std::cin``, the application has to initialize the UART driver and enable the blocking mode as shown in :example_file:`common_components/protocol_examples_common/stdin_out.c`.
|
||||
|
||||
|
||||
.. _cplusplus_limitations:
|
||||
|
||||
Limitations
|
||||
|
@ -181,6 +190,7 @@ Limitations
|
|||
- Vtables are placed into Flash and are not accessible when the flash cache is disabled. Therefore, virtual function calls should be avoided in :ref:`iram-safe-interrupt-handlers`. Placement of Vtables cannot be adjusted using the linker script generator, yet.
|
||||
- C++ filesystem (``std::filesystem``) features are not supported.
|
||||
|
||||
|
||||
What to Avoid
|
||||
-------------
|
||||
|
||||
|
|
|
@ -5,10 +5,11 @@ Current Consumption Measurement of Modules
|
|||
|
||||
You may want to know the current consumption of a `module <https://www.espressif.com/en/products/modules>`__ in deep-sleep mode, :doc:`other power-saving modes </api-reference/system/sleep_modes>`, and active mode to develop some applications sensitive to power consumption. This section introduces how to measure the current consumption of a module running such an application.
|
||||
|
||||
|
||||
Notes to Measurement
|
||||
--------------------
|
||||
|
||||
Can we use a Development Board?
|
||||
Can We Use a Development Board?
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. only:: esp32c6
|
||||
|
@ -27,6 +28,7 @@ Can we use a Development Board?
|
|||
|
||||
For {IDF_TARGET_NAME}, using a development board directly to measure current consumption of the corresponding module is not recommended, as some circuits still consume power on the board even when you flash the chip with the :example:`deep_sleep <system/deep_sleep>` example. Therefore, you need to cut off the power supply circuit to the module to measure the module's current. This method is inconvenient and increases measurement costs.
|
||||
|
||||
|
||||
How to Choose an Appropriate Ammeter?
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
|
@ -36,6 +38,7 @@ Additionally, ordinary ammeters have a relatively high internal resistance, resu
|
|||
|
||||
Therefore, an ammeter suitable for measuring current in deep-sleep mode should have low internal resistance and, ideally, switch current ranges dynamically. We recommend two options: the `Joulescope ammeter <https://www.joulescope.com/>`__ and the `Power Profiler Kit II from Nordic <https://www.nordicsemi.com/Products/Development-hardware/Power-Profiler-Kit-2.?lang=en>`__.
|
||||
|
||||
|
||||
Joulescope Ammeter
|
||||
""""""""""""""""""
|
||||
|
||||
|
@ -43,11 +46,13 @@ The Joulescope ammeter combines high-speed sampling and rapid dynamic current ra
|
|||
|
||||
Joulescope has no display screen. You need to connect it to a PC to visualize the current waveforms of the measured module. For specific instructions, please follow the documentation provided by the manufacturer.
|
||||
|
||||
|
||||
Nordic Power Profiler Kit II
|
||||
""""""""""""""""""""""""""""
|
||||
|
||||
The Nordic Power Profiler Kit II has an advanced analog measurement unit with a high dynamic measurement range. This allows for accurate power consumption measurements for the entire range typically seen in low-power embedded applications, all the way from single μAs to 1 A. The resolution varies between 100 nA and 1 mA, depending on the measurement range, and is high enough to detect small spikes often seen in low-power optimized systems.
|
||||
|
||||
|
||||
Hardware Connection
|
||||
-------------------
|
||||
|
||||
|
@ -102,6 +107,7 @@ Please connect the pins of **UART TX**, **UART RX**, **SPI Boot**, **Enable**, a
|
|||
|
||||
For details of the pin names, please refer to the `datasheet of specific module <https://www.espressif.com/en/support/download/documents/modules>`__.
|
||||
|
||||
|
||||
Measurement Steps
|
||||
-----------------
|
||||
|
||||
|
@ -119,7 +125,7 @@ You can refer to the following steps to measure the current in deep-sleep mode.
|
|||
|
||||
.. only:: esp32
|
||||
|
||||
For modules with an external resistor on GPIO12 (such as ESP32-WROVER-E/IE), you should call :cpp:func:`rtc_gpio_isolate` before going into deep sleep. This is to isolate the GPIO12 pin from external circuits to further minimize current consumption. Please note, for other modules, you don't have to call this function, otherwise, you may get abnormal results.
|
||||
For modules with an external resistor on GPIO12 (such as ESP32-WROVER-E/IE), you should call :cpp:func:`rtc_gpio_isolate` before going into deep sleep. This is to isolate the GPIO12 pin from external circuits to further minimize current consumption. Please note, for other modules, you do not have to call this function, otherwise, you may get abnormal results.
|
||||
|
||||
- By default, the module will be woken up every 20 seconds (you can change the timing by modifying the code of this example). To check if the example runs as expected, you can monitor the module operation by running ``idf.py -p PORT monitor`` (please replace PORT with your serial port name).
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@ Deep Sleep Wake Stubs
|
|||
|
||||
Deep sleep wake stub code is loaded into "RTC Fast Memory" and any data which it uses must also be loaded into RTC memory. RTC memory regions hold their contents during deep sleep.
|
||||
|
||||
|
||||
Rules for Wake Stubs
|
||||
--------------------
|
||||
|
||||
|
@ -22,6 +23,7 @@ Wake stub code must be carefully written:
|
|||
|
||||
* Wake stub code is a part of the main esp-idf app. During normal running of esp-idf, functions can call the wake stub functions or access RTC memory. It is as if these were regular parts of the app.
|
||||
|
||||
|
||||
Implementing A Stub
|
||||
-------------------
|
||||
|
||||
|
@ -35,6 +37,7 @@ If you want to swap between different deep sleep stubs at runtime, it is also po
|
|||
|
||||
All of these functions are declared in the ``esp_sleep.h`` header under components/{IDF_TARGET_PATH_NAME}.
|
||||
|
||||
|
||||
Loading Code Into RTC Memory
|
||||
----------------------------
|
||||
|
||||
|
@ -101,6 +104,7 @@ The second way is a better option if you need to use strings, or write other mor
|
|||
|
||||
To reduce wake-up time use the `CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP` Kconfig option, see more information in :doc:`Fast boot from Deep Sleep <bootloader>`.
|
||||
|
||||
|
||||
CRC Check For Wake Stubs
|
||||
------------------------
|
||||
|
||||
|
@ -116,6 +120,7 @@ CRC Check For Wake Stubs
|
|||
|
||||
When the `CONFIG_ESP_SYSTEM_ALLOW_RTC_FAST_MEM_AS_HEAP` option is enabled, all the RTC fast memory except the wake stubs area is added to the heap.
|
||||
|
||||
|
||||
Example
|
||||
-------
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@ Device Firmware Upgrade (DFU) is a mechanism for upgrading the firmware of the {
|
|||
- Section :ref:`api_guide_dfu_build` describes how to build firmware for DFU with ESP-IDF.
|
||||
- Section :ref:`api_guide_dfu_flash` deals with flashing the firmware.
|
||||
|
||||
|
||||
USB Connection
|
||||
--------------
|
||||
|
||||
|
@ -41,7 +42,7 @@ The necessary connections for the {IDF_TARGET_NAME}'s internal USB PHY (transcei
|
|||
|
||||
.. only:: esp32s3
|
||||
|
||||
By default, the :doc:`USB_SERIAL_JTAG<usb-serial-jtag-console>` module is connected to the {IDF_TARGET_NAME}'s internal USB PHY, while the USB OTG peripheral can be used only if an external USB PHY is connected. Since DFU is provided via the USB OTG peripheral, it cannot be used through the internal PHY in this configuration.
|
||||
By default, the :doc:`USB_SERIAL_JTAG <usb-serial-jtag-console>` module is connected to the {IDF_TARGET_NAME}'s internal USB PHY, while the USB OTG peripheral can be used only if an external USB PHY is connected. Since DFU is provided via the USB OTG peripheral, it cannot be used through the internal PHY in this configuration.
|
||||
|
||||
However, users can permanently switch the internal USB PHY to work with USB OTG peripheral instead of USB_SERIAL_JTAG by burning the ``USB_PHY_SEL`` eFuse. See *{IDF_TARGET_NAME} Technical Reference Manual* [`PDF <{IDF_TARGET_TRM_EN_URL}>`__] for more details about USB_SERIAL_JTAG and USB OTG.
|
||||
|
||||
|
@ -60,8 +61,10 @@ The command below will create a DFU image named ``dfu.bin`` that is placed in th
|
|||
idf.py dfu
|
||||
|
||||
.. note::
|
||||
|
||||
Do not forget to set the target chip by ``idf.py set-target`` before running ``idf.py dfu``. Otherwise, you might create an image for a different chip or receive an error message like ``unknown target 'dfu'``.
|
||||
|
||||
|
||||
.. _api_guide_dfu_flash:
|
||||
|
||||
Flashing the DFU Image
|
||||
|
@ -84,10 +87,12 @@ Consequently, the desired device can be selected for flashing by the ``--path``
|
|||
idf.py dfu-flash --path 1-2
|
||||
|
||||
.. note::
|
||||
|
||||
The vendor and product identificators are set based on the selected chip target by the ``idf.py set-target`` command and they are not selectable during the ``idf.py dfu-flash`` call.
|
||||
|
||||
See :ref:`api_guide_dfu_flash_errors` and their solutions.
|
||||
|
||||
|
||||
.. _api_guide_dfu_flash_udev:
|
||||
|
||||
Udev Rule (Linux Only)
|
||||
|
@ -100,10 +105,12 @@ Create file ``/etc/udev/rules.d/40-dfuse.rules`` with the following content::
|
|||
SUBSYSTEMS=="usb", ATTRS{idVendor}=="303a", ATTRS{idProduct}=="00??", GROUP="plugdev", MODE="0666"
|
||||
|
||||
.. note::
|
||||
|
||||
Please check the output of the command ``groups``. The user has to be a member of the `GROUP` specified above. You may use some other existing groups for this purpose (e.g., `uucp` on some systems instead of `plugdev`) or create a new group for this purpose.
|
||||
|
||||
Restart your computer so the previous setting could take into affect or run ``sudo udevadm trigger`` to force manually udev to trigger your new rule.
|
||||
|
||||
|
||||
.. _api_guide_dfu_flash_win:
|
||||
|
||||
USB Drivers (Windows Only)
|
||||
|
@ -116,19 +123,22 @@ Please see the `libusb wiki <https://github.com/libusb/libusb/wiki/Windows#How_t
|
|||
The drivers can be installed by the `Zadig tool <https://zadig.akeo.ie/>`_. Please make sure that the device is in download mode before you run the tool and that it detects the {IDF_TARGET_NAME} device before you install the drivers. The Zadig tool might detect several USB interfaces of {IDF_TARGET_NAME}. Please install the WinUSB driver only for the interface where there is no driver installed (probably it is Interface 2) and do not re-install the driver for the other interface.
|
||||
|
||||
.. warning::
|
||||
|
||||
The manual installation of the driver in Device Manager of Windows is not recommended because the flashing might not work properly.
|
||||
|
||||
|
||||
.. _api_guide_dfu_flash_errors:
|
||||
|
||||
Common Errors and Known Issues
|
||||
------------------------------
|
||||
|
||||
- ``dfu-util: command not found`` might indicate that the tool hasn't been installed or is not available from the terminal. An easy way of checking the tool is running ``dfu-util --version``. Please see :ref:`get-started-get-prerequisites` for installing ``dfu-util``.
|
||||
- ``dfu-util: command not found`` might indicate that the tool has not been installed or is not available from the terminal. An easy way of checking the tool is running ``dfu-util --version``. Please see :ref:`get-started-get-prerequisites` for installing ``dfu-util``.
|
||||
|
||||
- The reason for ``No DFU capable USB device available`` could be that the USB driver wasn't properly installed on Windows (see :ref:`api_guide_dfu_flash_win`), udev rule was not setup on Linux (see :ref:`api_guide_dfu_flash_udev`) or the device isn't in bootloader mode.
|
||||
- The reason for ``No DFU capable USB device available`` could be that the USB driver was not properly installed on Windows (see :ref:`api_guide_dfu_flash_win`), udev rule was not setup on Linux (see :ref:`api_guide_dfu_flash_udev`) or the device is not in bootloader mode.
|
||||
|
||||
- Flashing with ``dfu-util`` on Windows fails on the first attempt with error ``Lost device after RESET?``. Please retry the flashing and it should succeed the next time.
|
||||
|
||||
|
||||
.. only:: SOC_SUPPORTS_SECURE_DL_MODE
|
||||
|
||||
Secure Download Mode
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
.. highlight:: c
|
||||
.. code-block:: c
|
||||
|
||||
Error Handling
|
||||
==============
|
||||
|
||||
:link_to_translation:`zh_CN:[中文]`
|
||||
|
||||
Overview
|
||||
|
@ -24,7 +25,8 @@ This guide explains ESP-IDF error handling mechanisms related to recoverable err
|
|||
|
||||
For instructions on diagnosing unrecoverable errors, see :doc:`Fatal Errors <fatal-errors>`.
|
||||
|
||||
Error codes
|
||||
|
||||
Error Codes
|
||||
-----------
|
||||
|
||||
The majority of ESP-IDF-specific functions use :cpp:type:`esp_err_t` type to return error codes. :cpp:type:`esp_err_t` is a signed integer type. Success (no error) is indicated with ``ESP_OK`` code, which is defined as zero.
|
||||
|
@ -34,7 +36,7 @@ Various ESP-IDF header files define possible error codes using preprocessor defi
|
|||
For the complete list of error codes, see :doc:`Error Code Reference <../api-reference/error-codes>`.
|
||||
|
||||
|
||||
Converting error codes to error messages
|
||||
Converting Error Codes to Error Messages
|
||||
----------------------------------------
|
||||
|
||||
For each error code defined in ESP-IDF components, :cpp:type:`esp_err_t` value can be converted to an error code name using :cpp:func:`esp_err_to_name` or :cpp:func:`esp_err_to_name_r` functions. For example, passing ``0x101`` to :cpp:func:`esp_err_to_name` will return "ESP_ERR_NO_MEM" string. Such strings can be used in log output to make it easier to understand which error has happened.
|
||||
|
@ -43,9 +45,10 @@ Additionally, :cpp:func:`esp_err_to_name_r` function will attempt to interpret t
|
|||
|
||||
This feature is enabled by default, but can be disabled to reduce application binary size. See :ref:`CONFIG_ESP_ERR_TO_NAME_LOOKUP`. When this feature is disabled, :cpp:func:`esp_err_to_name` and :cpp:func:`esp_err_to_name_r` are still defined and can be called. In this case, :cpp:func:`esp_err_to_name` will return ``UNKNOWN ERROR``, and :cpp:func:`esp_err_to_name_r` will return ``Unknown error 0xXXXX(YYYYY)``, where ``0xXXXX`` and ``YYYYY`` are the hexadecimal and decimal representations of the error code, respectively.
|
||||
|
||||
|
||||
.. _esp-error-check-macro:
|
||||
|
||||
``ESP_ERROR_CHECK`` macro
|
||||
``ESP_ERROR_CHECK`` Macro
|
||||
-------------------------
|
||||
|
||||
:c:macro:`ESP_ERROR_CHECK` macro serves similar purpose as ``assert``, except that it checks :cpp:type:`esp_err_t` value rather than a ``bool`` condition. If the argument of :c:macro:`ESP_ERROR_CHECK` is not equal :c:macro:`ESP_OK`, then an error message is printed on the console, and ``abort()`` is called.
|
||||
|
@ -60,7 +63,7 @@ Error message will typically look like this::
|
|||
|
||||
Backtrace: 0x40086e7c:0x3ffb4ff0 0x40087328:0x3ffb5010 0x400d1fdf:0x3ffb5030 0x400d0816:0x3ffb5050
|
||||
|
||||
.. note:: If :doc:`IDF monitor <tools/idf-monitor>` is used, addresses in the backtrace will be converted to file names and line numbers.
|
||||
.. note:: If :doc:`ESP-IDF monitor <tools/idf-monitor>` is used, addresses in the backtrace will be converted to file names and line numbers.
|
||||
|
||||
- The first line mentions the error code as a hexadecimal value, and the identifier used for this error in source code. The latter depends on :ref:`CONFIG_ESP_ERR_TO_NAME_LOOKUP` option being set. Address in the program where error has occured is printed as well.
|
||||
|
||||
|
@ -71,39 +74,44 @@ Error message will typically look like this::
|
|||
|
||||
.. _esp-error-check-without-abort-macro:
|
||||
|
||||
``ESP_ERROR_CHECK_WITHOUT_ABORT`` macro
|
||||
``ESP_ERROR_CHECK_WITHOUT_ABORT`` Macro
|
||||
---------------------------------------
|
||||
|
||||
:c:macro:`ESP_ERROR_CHECK_WITHOUT_ABORT` macro serves similar purpose as ``ESP_ERROR_CHECK``, except that it won't call ``abort()``.
|
||||
:c:macro:`ESP_ERROR_CHECK_WITHOUT_ABORT` macro serves similar purpose as ``ESP_ERROR_CHECK``, except that it will not call ``abort()``.
|
||||
|
||||
|
||||
.. _esp-return-on-error-macro:
|
||||
|
||||
``ESP_RETURN_ON_ERROR`` macro
|
||||
``ESP_RETURN_ON_ERROR`` Macro
|
||||
-----------------------------
|
||||
|
||||
:c:macro:`ESP_RETURN_ON_ERROR` macro checks the error code, if the error code is not equal :c:macro:`ESP_OK`, it prints the message and returns.
|
||||
|
||||
|
||||
.. _esp-goto-on-error-macro:
|
||||
|
||||
``ESP_GOTO_ON_ERROR`` macro
|
||||
``ESP_GOTO_ON_ERROR`` Macro
|
||||
---------------------------
|
||||
|
||||
:c:macro:`ESP_GOTO_ON_ERROR` macro checks the error code, if the error code is not equal :c:macro:`ESP_OK`, it prints the message, sets the local variable `ret` to the code, and then exits by jumping to `goto_tag`.
|
||||
|
||||
|
||||
.. _esp-return-on-false-macro:
|
||||
|
||||
``ESP_RETURN_ON_FALSE`` macro
|
||||
``ESP_RETURN_ON_FALSE`` Macro
|
||||
-----------------------------
|
||||
|
||||
:c:macro:`ESP_RETURN_ON_FALSE` macro checks the condition, if the condition is not equal `true`, it prints the message and returns with the supplied `err_code`.
|
||||
|
||||
|
||||
.. _esp-goto-on-false-macro:
|
||||
|
||||
``ESP_GOTO_ON_FALSE`` macro
|
||||
``ESP_GOTO_ON_FALSE`` Macro
|
||||
---------------------------
|
||||
|
||||
:c:macro:`ESP_GOTO_ON_FALSE` macro checks the condition, if the condition is not equal `true`, it prints the message, sets the local variable `ret` to the supplied `err_code`, and then exits by jumping to `goto_tag`.
|
||||
|
||||
|
||||
.. _check_macros_examples:
|
||||
|
||||
``CHECK MACROS Examples``
|
||||
|
@ -133,9 +141,10 @@ Some examples::
|
|||
|
||||
If the option :ref:`CONFIG_COMPILER_OPTIMIZATION_CHECKS_SILENT` in Kconfig is enabled, the err message will be discarded, while the other action works as is.
|
||||
|
||||
The ``ESP_RETURN_XX`` and ``ESP_GOTO_xx`` macros can't be called from ISR. While there are ``xx_ISR`` versions for each of them, e.g., `ESP_RETURN_ON_ERROR_ISR`, these macros could be used in ISR.
|
||||
The ``ESP_RETURN_XX`` and ``ESP_GOTO_xx`` macros cannot be called from ISR. While there are ``xx_ISR`` versions for each of them, e.g., `ESP_RETURN_ON_ERROR_ISR`, these macros could be used in ISR.
|
||||
|
||||
Error handling patterns
|
||||
|
||||
Error Handling Patterns
|
||||
-----------------------
|
||||
|
||||
1. Attempt to recover. Depending on the situation, we may try the following methods:
|
||||
|
@ -167,7 +176,7 @@ Error handling patterns
|
|||
if (err != ESP_OK) {
|
||||
// Clean up
|
||||
free(card);
|
||||
// Propagate the error to the upper layer (e.g. to notify the user).
|
||||
// Propagate the error to the upper layer (e.g., to notify the user).
|
||||
// Alternatively, application can define and return custom error code.
|
||||
return err;
|
||||
}
|
||||
|
|
|
@ -41,7 +41,7 @@ ESP-BLE-MESH architecture includes five key parts:
|
|||
|
||||
- ``Features``
|
||||
|
||||
- Include several ESP-BLE-MESH features, e.g. Low Power feature, Friend feature, Relay feature, etc.
|
||||
- Include several ESP-BLE-MESH features, e.g., Low Power feature, Friend feature, Relay feature, etc.
|
||||
|
||||
- ``Mesh Bearer Layer``
|
||||
|
||||
|
@ -182,7 +182,7 @@ Functions of each layer are shown in Table 1.3:
|
|||
|
||||
The ``Applications`` in the protocol stack architecture implement the corresponding functions by calling the API provided by the ESP-BLE-MESH protocol stack and processing the Event reported by the protocol stack. There are some common applications, such as gateway, lighting and etc.
|
||||
|
||||
Interaction between application layer(``Applications``)and ``API / Event``
|
||||
Interaction between application layer (``Applications``) and ``API/Event``
|
||||
|
||||
- Application layer calls API
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@ Users could refer to the sections for quick answer to their questions. This docu
|
|||
|
||||
Generally, a Provisioner is used to provision unprovisioned devices and form a mesh network. And after provisioning, roles of the unprovisioned devices will be changed to those of a node.
|
||||
|
||||
1.1 What is the flow for an unprovisioned device to join ESP-BLE-MESH network?
|
||||
1.1 What Is the Flow for an Unprovisioned Device to Join ESP-BLE-MESH Network?
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
There are two phases for a device to join ESP-BLE-MESH network via a Provisioner, namely, provisioning and configuration.
|
||||
|
@ -32,76 +32,76 @@ Generally, a Provisioner is used to provision unprovisioned devices and form a m
|
|||
|
||||
- The phase of configuration is to add AppKeys to the node and bind AppKeys to corresponding models. And some items are optional during configuration, including adding subscription addresses to the node, set publication information, etc. By configuration, the node can actually transmit messages to a Provisioner and receive messages from it.
|
||||
|
||||
1.2 If a Provisioner wants to change states of a node, what requirements should be met for a Provisioner?
|
||||
1.2 If a Provisioner Wants to Change States of a Node, What Requirements Should Be Met for a Provisioner?
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
- Client model that corresponds to server model of the node is required.
|
||||
- NetKey and AppKey used to encrypt messages shall be owned by both the node and the Provisioner.
|
||||
- The address owned by the node shall be known, which could be its unicast address or subscription address.
|
||||
|
||||
1.3 How can NetKey and AppKey be used?
|
||||
1.3 How Can NetKey and AppKey Be Used?
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
- NetKey is used for encryption of messages in Network Layer. Nodes with the same NetKey are assumed to be in the same subnet while those with different NetKeys cannot communicate with each other.
|
||||
- AppKey is used for encryption of messages in Upper Transport Layer. If client model and server model are bound to different AppKeys, the communication cannot be achieved.
|
||||
|
||||
1.4 How to generate a NetKey or AppKey for Provisioner? Can we use a fixed NetKey or AppKey?
|
||||
1.4 How to Generate a NetKey or AppKey for Provisioner? Can We Use a Fixed NetKey or AppKey?
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
- The API :cpp:func:`esp_ble_mesh_provisioner_add_local_net_key` can be used to add a NetKey with a fixed or random value.
|
||||
- The API :cpp:func:`esp_ble_mesh_provisioner_add_local_app_key` can be used to add an AppKey with a fixed or random value.
|
||||
|
||||
1.5 Is the unicast address of Provisioner fixed?
|
||||
1.5 Is the Unicast Address of Provisioner Fixed?
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
The value of :code:`prov_unicast_addr` in :cpp:type:`esp_ble_mesh_prov_t` is used to set the unicast address of Provisioner, it can be set only once during initialization and can't be changed afterwards.
|
||||
The value of :code:`prov_unicast_addr` in :cpp:type:`esp_ble_mesh_prov_t` is used to set the unicast address of Provisioner, it can be set only once during initialization and cannot be changed afterwards.
|
||||
|
||||
1.6 Can the address of Provisioner serve as destination address of the node-reporting-status message?
|
||||
1.6 Can the Address of Provisioner Serve as Destination Address of the Node-reporting-status Message?
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
The unicast address of Provisioner can be set only once during initialization and can't be changed afterwards. In theory, it can serve as the destination address of the node-reporting-status message, provided that the unicast address of the Provisioner is known by nodes. Nodes can know the unicast address of Provisioner during configuration since Provisioner sends messages to them with its unicast address used as the source address.
|
||||
The unicast address of Provisioner can be set only once during initialization and cannot be changed afterwards. In theory, it can serve as the destination address of the node-reporting-status message, provided that the unicast address of the Provisioner is known by nodes. Nodes can know the unicast address of Provisioner during configuration since Provisioner sends messages to them with its unicast address used as the source address.
|
||||
|
||||
Subscription address can also be used. Provisioner subscribes to a group address or virtual address, and nodes send messages to the subscription address.
|
||||
|
||||
1.7 Is the unicast address of the node that is firstly provisioned by Provisioner to ESP-BLE-MESH network fixed?
|
||||
1.7 Is the Unicast Address of the Node That Is Firstly Provisioned by ProvIsioner to ESP-BLE-MESH Network Fixed?
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
The value of :code:`prov_start_address` in :cpp:type:`esp_ble_mesh_prov_t` is used to set the starting address when the Provisioner provisions unprovisioned devices, i.e. the unicast address of the node it firstly provisioned. It can be set only once during initialization and can't be changed afterwards.
|
||||
The value of :code:`prov_start_address` in :cpp:type:`esp_ble_mesh_prov_t` is used to set the starting address when the Provisioner provisions unprovisioned devices, i.e., the unicast address of the node it firstly provisioned. It can be set only once during initialization and cannot be changed afterwards.
|
||||
|
||||
1.8 Is the unicast address of the node that mobile App firstly provisioned fixed?
|
||||
1.8 Is the Unicast Address of the Node That Mobile App Firstly Provisioned Fixed?
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
The App will decide the unicast address, and currently most of them are fixed.
|
||||
|
||||
1.9 How to know which unprovisioned device is the Provisioner that is provisioning currently?
|
||||
1.9 How to Know Which Unprovisioned Device Is the ProvIsioner That Is Provisioning Currently?
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
The value of :code:`prov_attention` in :cpp:type:`esp_ble_mesh_prov_t` is used by Provisioner set to unprovisioned device during provisioning. It can be set only once during initialization and can't be changed afterwards. When the unprovisioned device is joining the mesh network, it can display in a specific way like flashing light to notify Provisioner that it is being provisioned.
|
||||
The value of :code:`prov_attention` in :cpp:type:`esp_ble_mesh_prov_t` is used by Provisioner set to unprovisioned device during provisioning. It can be set only once during initialization and cannot be changed afterwards. When the unprovisioned device is joining the mesh network, it can display in a specific way like flashing light to notify Provisioner that it is being provisioned.
|
||||
|
||||
1.10 How many ways to authenticate the devices during provisioning? Which way was used in the :example:`provided examples <bluetooth/esp_ble_mesh>`?
|
||||
1.10 How Many Ways to Authenticate the Devices During Provisioning? Which Way Was Used in the :example:`provided examples <bluetooth/esp_ble_mesh>`?
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
There are four authentication methods, i.e. No OOB, Static OOB, Output OOB and Input OOB. In the provided examples, No OOB is used.
|
||||
There are four authentication methods, i.e., No OOB, Static OOB, Output OOB and Input OOB. In the provided examples, No OOB is used.
|
||||
|
||||
1.11 What information can be carried by the advertising packets of the unprovisioned device before provisioning into the network?
|
||||
1.11 What Information Can Be Carried by the Advertising Packets of the Unprovisioned Device Before Provisioning into the Network?
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
- Device UUID
|
||||
- OOB Info
|
||||
- URL Hash (optional)
|
||||
|
||||
1.12 Can such information be used for device identification?
|
||||
1.12 Can Such Information Be Used for Device Identification?
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
For example, each unprovisioned device contains a unique Device UUID, which can be used for device identification.
|
||||
|
||||
1.13 How is the unicast address assigned when the node provisioned by Provisioner contains multiple elements?
|
||||
1.13 How Is the Unicast Address Assigned When the Node Provisioned by ProvIsioner Contains Multiple Elements?
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
- Provisioner will assign an unicast address for the primary element of the node, and unicast address of the remaining elements are incremented one by one.
|
||||
- For example: If an unprovisioned device has three elements, i.e. the primary element, the second element and the third element. After provisioning, the primary element address of the node is 0x0002 while the second element address is 0x0003, and the third element address is 0x0004.
|
||||
- For example: If an unprovisioned device has three elements, i.e., the primary element, the second element and the third element. After provisioning, the primary element address of the node is 0x0002 while the second element address is 0x0003, and the third element address is 0x0004.
|
||||
|
||||
1.14 How can Provisioner get and parse the :ref:`Composition Data <ble-mesh-terminology-composition>` of nodes through Configuration Client Model?
|
||||
1.14 How Can Provisioner Get and Parse the :ref:`Composition Data <ble-mesh-terminology-composition>` of Nodes Through Configuration Client Model?
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
- Provisioner can get the Composition Data of nodes using the :ref:`Configuration Client Model <ble-mesh-terminology-foundation-models>` API :cpp:func:`esp_ble_mesh_config_client_set_state` with :code:`comp_data_get` in the parameter :cpp:type:`esp_ble_mesh_cfg_client_get_state_t` set properly.
|
||||
|
@ -204,7 +204,7 @@ Generally, a Provisioner is used to provision unprovisioned devices and form a m
|
|||
}
|
||||
}
|
||||
|
||||
1.15 How can Provisioner further configure nodes through obtained Composition Data?
|
||||
1.15 How Can Provisioner Further Configure Nodes Through Obtained Composition Data?
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Provisioner do the following configuration by calling the :ref:`Configuration Client Model <ble-mesh-terminology-foundation-models>` API :cpp:func:`esp_ble_mesh_config_client_set_state`.
|
||||
|
@ -213,7 +213,7 @@ Generally, a Provisioner is used to provision unprovisioned devices and form a m
|
|||
- Add subscription address to the models of nodes with :code:`model_sub_add` in the parameter :cpp:type:`esp_ble_mesh_cfg_client_set_state_t` set properly.
|
||||
- Set publication information to the models of nodes with :code:`model_pub_set` in the parameter :cpp:type:`esp_ble_mesh_cfg_client_set_state_t` set properly.
|
||||
|
||||
1.16 Can nodes add corresponding configurations for themselves?
|
||||
1.16 Can Nodes Add Corresponding Configurations for Themselves?
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
This method can be used in special cases like testing period.
|
||||
|
@ -271,7 +271,7 @@ Generally, a Provisioner is used to provision unprovisioned devices and form a m
|
|||
|
||||
When the NVS storage of the node is enabled, group address added and AppKey bound by this method will not be saved in the NVS when the device is powered off currently. These configuration information can only be saved if they are configured by Configuration Client Model.
|
||||
|
||||
1.17 How does Provisioner control nodes by grouping?
|
||||
1.17 How Does Provisioner Control Nodes by Grouping?
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Generally there are two approaches to implement group control in ESP-BLE-MESH network, group address approach and virtual address approach. And supposing there are 10 devices, i.e., five devices with blue lights and five devices with red lights.
|
||||
|
@ -280,12 +280,12 @@ Generally, a Provisioner is used to provision unprovisioned devices and form a m
|
|||
|
||||
- Method 2: 5 blue lights can subscribe to a virtual address, 5 red lights subscribe to another one. By sending messages to different virtual addresses, Provisioner can realize group control.
|
||||
|
||||
1.18 How does Provisioner add nodes to multiple subnets?
|
||||
1.18 How Does Provisioner Add Nodes to Multiple Subnets?
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Provisioner can add multiple NetKeys to nodes during configuration, and nodes sharing the same NetKey belong to the same subnet. Provisioner can communicate with nodes on different subnets by using different NetKeys.
|
||||
|
||||
1.19 How does Provisioner know if a node in the mesh network is offline?
|
||||
1.19 How Does ProvIsioner Know If a Node in the Mesh Network Is Offline?
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Node offline is usually defined as: the condition that the node cannot be properly communicated with other nodes in the mesh network due to power failure or some other reasons.
|
||||
|
@ -300,7 +300,7 @@ Generally, a Provisioner is used to provision unprovisioned devices and form a m
|
|||
|
||||
The heartbeat message should be designed into a single package (less than 11 bytes), so the transmission and reception of it can be more efficient.
|
||||
|
||||
1.20 What operations should be performed when Provisioner removes nodes from the network?
|
||||
1.20 What Operations Should Be Performed When Provisioner Removes Nodes from the Network?
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Usually when Provisioner tries to remove node from the mesh network, the procedure includes three main steps:
|
||||
|
@ -311,19 +311,19 @@ Generally, a Provisioner is used to provision unprovisioned devices and form a m
|
|||
|
||||
- Lastly, the node performs node reset procedure, and switches itself to an unprovisioned device.
|
||||
|
||||
1.21 In the Key Refresh procedure, how does Provisioner update the Netkey owned by nodes?
|
||||
1.21 In the Key Refresh Procedure, How Does Provisioner Update the Netkey Owned by Nodes?
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
- Provisioner updates the NetKey of nodes using the :ref:`Configuration Client Model <ble-mesh-terminology-foundation-models>` API :cpp:func:`esp_ble_mesh_config_client_set_state` with :code:`net_key_update` in the parameter :cpp:type:`esp_ble_mesh_cfg_client_set_state_t` set properly.
|
||||
|
||||
- Provisioner updates the AppKey of nodes using the :ref:`Configuration Client Model <ble-mesh-terminology-foundation-models>` API :cpp:func:`esp_ble_mesh_config_client_set_state` with :code:`app_key_update` in the parameter :cpp:type:`esp_ble_mesh_cfg_client_set_state_t` set properly.
|
||||
|
||||
1.22 How does Provisioner manage nodes in the mesh network?
|
||||
1.22 How Does Provisioner Manage Nodes in the Mesh Network?
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
ESP-BLE-MESH implements several functions related to basic node management in the example, such as :cpp:func:`esp_ble_mesh_store_node_info`. And ESP-BLE-MESH also provides the API :cpp:func:`esp_ble_mesh_provisioner_set_node_name` which can be used to set the node's local name and the API :cpp:func:`esp_ble_mesh_provisioner_get_node_name` which can be used to get the node's local name.
|
||||
|
||||
1.23 What does Provisioner need when trying to control the server model of nodes?
|
||||
1.23 What Does Provisioner Need When Trying to Control the Server Model of Nodes?
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Provisioner must include corresponding client model before controlling the server model of nodes.
|
||||
|
@ -338,7 +338,7 @@ Generally, a Provisioner is used to provision unprovisioned devices and form a m
|
|||
|
||||
- Provisioner bind AppKey to its own client model by calling the API :cpp:func:`esp_ble_mesh_provisioner_bind_app_key_to_local_model`.
|
||||
|
||||
1.24 How does Provisoner control the server model of nodes?
|
||||
1.24 How Does Provisoner Control the Server Model of Nodes?
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
ESP-BLE-MESH supports all SIG-defined client models. Provisioner can use these client models to control the server models of nodes. And the client models are divided into 6 categories with each category has the corresponding functions.
|
||||
|
@ -378,7 +378,7 @@ Generally, a Provisioner is used to provision unprovisioned devices and form a m
|
|||
2. Node Development
|
||||
-------------------
|
||||
|
||||
2.1 What kind of models are included by nodes?
|
||||
2.1 What Kind of Models Are Included by Nodes?
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
- In ESP-BLE-MESH, nodes are all composed of a series of models with each model implements some functions of the node.
|
||||
|
@ -387,14 +387,14 @@ Generally, a Provisioner is used to provision unprovisioned devices and form a m
|
|||
|
||||
- Model can also be divided into SIG model and vendor model. All behaviors of SIG models are officially defined while behaviors of vendor models are defined by users.
|
||||
|
||||
2.2 Is the format of messages corresponding to each model fixed?
|
||||
2.2 Is the Format of Messages Corresponding to Each Model Fixed?
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
- Messages, which consist of opcode and payload, are divided by opcode.
|
||||
|
||||
- The type and the format of the messages corresponding to models are both fixed, which means the messages transmitted between models are fixed.
|
||||
|
||||
2.3 Which functions can be used to send messages with the models of nodes?
|
||||
2.3 Which Functions Can Be Used to Send Messages with the Models of Nodes?
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
- For client models, users can use the API :cpp:func:`esp_ble_mesh_client_model_send_msg` to send messages.
|
||||
|
@ -403,7 +403,7 @@ Generally, a Provisioner is used to provision unprovisioned devices and form a m
|
|||
|
||||
- For publication, users call the API :cpp:func:`esp_ble_mesh_model_publish` to publish messages.
|
||||
|
||||
2.4 How to achieve the transmission of messages without packet loss?
|
||||
2.4 How to Achieve the Transmission of Messages Without Packet Loss?
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Acknowledegd message is needed if users want to transmit messages without packet loss. The default time to wait for corresponding response is set in :ref:`CONFIG_BLE_MESH_CLIENT_MSG_TIMEOUT`. If the sender waits for the response until the timer expires, the corresponding timeout event would be triggered.
|
||||
|
@ -412,31 +412,31 @@ Generally, a Provisioner is used to provision unprovisioned devices and form a m
|
|||
|
||||
Response timeout can be set in the API :cpp:func:`esp_ble_mesh_client_model_send_msg`. The default value (4 seconds) would be applied if the parameter :code:`msg_timeout` is set to **0**.
|
||||
|
||||
2.5 How to send unacknowledged messages?
|
||||
2.5 How to Send Unacknowledged Messages?
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
For client models, users can use the API :cpp:func:`esp_ble_mesh_client_model_send_msg` with the parameter :code:`need_rsp` set to :code:`false` to send unacknowledged messages.
|
||||
|
||||
For server models, the messages sent by using the API :cpp:func:`esp_ble_mesh_server_model_send_msg` are always unacknowledged messages.
|
||||
|
||||
2.6 How to add subscription address to models?
|
||||
2.6 How to Add Subscription Address to Models?
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Subscription address can be added through Configuration Client Model.
|
||||
|
||||
2.7 What is the difference between messages sent and published by models?
|
||||
2.7 What Is the Difference Between Messages Sent and Published by Models?
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Messages sent by calling the API :cpp:func:`esp_ble_mesh_client_model_send_msg` or :cpp:func:`esp_ble_mesh_server_model_send_msg` will be sent in the duration determined by the Network Transmit state.
|
||||
|
||||
Messages published by calling the API :cpp:func:`esp_ble_mesh_model_publish` will be published determined by the Model Publication state. And the publication of messages is generally periodic or with a fixed number of counts. The publication period and publication count are controlled by the Model Publication state, and can be configured through Configuration Client Model.
|
||||
|
||||
2.8 How many bytes can be carried when sending unsegmented messages?
|
||||
2.8 How Many Bytes Can Be Carried When Sending Unsegmented Messages?
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
The total payload length (which can be set by users) of unsegmented message is 11 octets, so if the opcode of the message is 2 octets, then the message can carry 9-octets of valid information. For vendor messages, due to the 3-octets opcode, the remaining payload length is 8 octets.
|
||||
|
||||
2.9 When should the :ref:`Relay <ble-mesh-terminology-features>` feature of nodes be enabled?
|
||||
2.9 When Should the :ref:`Relay <ble-mesh-terminology-Features>` Feature of Nodes Be Enabled?
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Users can enable the Relay feature of all nodes when nodes detected in the mesh network are sparse.
|
||||
|
@ -445,17 +445,17 @@ Generally, a Provisioner is used to provision unprovisioned devices and form a m
|
|||
|
||||
And users can enable the Relay feature by default if the mesh network size is unknown.
|
||||
|
||||
2.10 When should the :ref:`Proxy <ble-mesh-terminology-features>` feature of node be enabled?
|
||||
2.10 When Should the :ref:`Proxy <ble-mesh-terminology-Features>` Feature of Node Be Enabled?
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
If the unprovisioned device is expected to be provisioned by a phone, then it should enable the Proxy feature since almost all the phones do not support sending ESP-BLE-MESH packets through advertising bearer currently. And after the unprovisioned device is provisioned successfully and becoming a Proxy node, it will communicate with the phone using GATT bearer and using advertising bearer to communicate with other nodes in the mesh network.
|
||||
|
||||
2.11 How to use the Proxy filter?
|
||||
2.11 How to Use the Proxy Filter?
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
The Proxy filter is used to reduce the number of Network PDUs exchanged between a Proxy Client (e.g. the phone) and a Proxy Server (e.g. the node). And with the Proxy filter, Proxy Client can explicitly request to receive only mesh messages with certain destination addresses from Proxy Server.
|
||||
The Proxy filter is used to reduce the number of Network PDUs exchanged between a Proxy Client (e.g., the phone) and a Proxy Server (e.g., the node). And with the Proxy filter, Proxy Client can explicitly request to receive only mesh messages with certain destination addresses from Proxy Server.
|
||||
|
||||
2.12 When a message can be relayed by a Relay node?
|
||||
2.12 When a Message Can Be Relayed by a Relay Node?
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
If a message need to be relayed, the following conditions should be met.
|
||||
|
@ -466,12 +466,12 @@ Generally, a Provisioner is used to provision unprovisioned devices and form a m
|
|||
|
||||
- The value of TTL in the message is greater than 1.
|
||||
|
||||
2.13 If a message is segmented into several segments, should the other Relay nodes just relay when one of these segments is received or wait until the message is received completely?
|
||||
2.13 If a Message Is Segmented into Several Segments, Should the Other Relay Nodes Just Relay When One of These Segments Is Received or Wait Until the Message Is Received Completely?
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Relay nodes will forward segments when one of them are received rather than keeping waiting until all the segments are received.
|
||||
|
||||
2.14 What is the principle of reducing power consumption using :ref:`Low Power <ble-mesh-terminology-features>` feature?
|
||||
2.14 What Is the Principle of Reducing Power Consumption Using :ref:`Low Power <ble-mesh-terminology-Features>` Feature?
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
- When the radio is turned on for listening, the device is consuming energy. When low power feature of the node is enabled, it will turn off its radio in the most of the time.
|
||||
|
@ -480,17 +480,17 @@ Generally, a Provisioner is used to provision unprovisioned devices and form a m
|
|||
|
||||
- When there are some new messages for low power node, its friend node will store the messages for it. And low power node can poll friend nodes to see if there are new messages at a fixed interval.
|
||||
|
||||
2.15 How to continue the communication on the network after powering-down and powering-up again?
|
||||
2.15 How to Continue the Communication on the Network After Powering-down and Powering-up Again?
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Enable the configuration :code:`Store ESP-BLE-MESH Node configuration persistently` in `menuconfig`.
|
||||
|
||||
2.16 How to send out the self-test results of nodes?
|
||||
2.16 How to Send out the Self-test Results of Nodes?
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
It is recommended that nodes can publish its self-test results periodically through Health Server Model.
|
||||
|
||||
2.17 How to transmit information between nodes?
|
||||
2.17 How to Transmit Information Between Nodes?
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
One possible application scenario for transmitting information between nodes is that spray nodes would be triggered once smoke alarm detected high smoke concentration. There are two approaches in implementation.
|
||||
|
@ -499,19 +499,19 @@ Generally, a Provisioner is used to provision unprovisioned devices and form a m
|
|||
|
||||
- Approach 2 is that Provisioner can configure the unicast address of spray node to the smoke alarm. When high smoke concentration is detected, smoke alarm can use send messages to the spray node with the spray node's unicast address as the destination address.
|
||||
|
||||
2.18 Is gateway a must for nodes communication?
|
||||
2.18 Is Gateway a Must for Nodes Communication?
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
- Situation 1: nodes only communicate within the mesh network. In this situation, no gateway is need. ESP-BLE-MESH network is a flooded network, messages in the network have no fixed paths, and nodes can communicate with each other freely.
|
||||
|
||||
- Situation 2: if users want to control the nodes remotely, for example turn on some nodes before getting home, then a gateway is needed.
|
||||
|
||||
2.19 When will the IV Update procedure be performed?
|
||||
2.19 When Will the IV Update Procedure Be Performed?
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
IV Update procedure would be performed once sequence number of messages sent detected by the bottom layer of node reached a critical value.
|
||||
|
||||
2.20 How to perform IV Update procedure?
|
||||
2.20 How to Perform IV Update Procedure?
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Nodes can perform IV Update procedure with Secure Network Beacon.
|
||||
|
@ -522,25 +522,25 @@ Generally, a Provisioner is used to provision unprovisioned devices and form a m
|
|||
3. ESP-BLE-MESH and Wi-Fi Coexistence
|
||||
-------------------------------------
|
||||
|
||||
3.1 Which modes does Wi-Fi support when it coexists with ESP-BLE-MESH?
|
||||
3.1 Which Modes Does Wi-Fi Support When it Coexists with ESP-BLE-MESH?
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Currently only Wi-Fi station mode supports the coexistence.
|
||||
|
||||
3.2 Why is the Wi-Fi throughput so low when Wi-Fi and ESP-BLE-MESH coexist?
|
||||
3.2 Why Is the Wi-Fi Throughput So Low When Wi-Fi and ESP-BLE-MESH Coexist?
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. only:: esp32
|
||||
|
||||
The :doc:`ESP32-DevKitC <../../hw-reference/esp32/get-started-devkitc>` board without PSRAM can run properly but the throughput of it is low since it has no PSRAM. When Bluetooth and Wi-Fi coexist, the throughput of ESP32-DevKitC with PSRAM can be stabilized to more than 1Mbps.
|
||||
The :doc:`ESP32-DevKitC <../../hw-reference/esp32/get-started-devkitc>` board without PSRAM can run properly but the throughput of it is low since it has no PSRAM. When Bluetooth and Wi-Fi coexist, the throughput of ESP32-DevKitC with PSRAM can be stabilized to more than 1 Mbps.
|
||||
|
||||
Some configurations in menuconfig shall be enabled to support PSRAM.
|
||||
|
||||
- :code:`{IDF_TARGET_NAME}-specific --> Support for external,SPI-connected RAM --> Try to allocate memories of Wi-Fi and LWIP...`
|
||||
- :code:`Bluetooth --> Bluedroid Enable --> BT/BLE will first malloc the memory from the PSRAM`
|
||||
- :code:`Bluetooth --> Bluedroid Enable --> Use dynamic memory allocation in BT/BLE stack.`
|
||||
- :code:`Bluetooth --> Bluetooth controller --> BLE full scan feature supported.`
|
||||
- :code:`Wi-Fi --> Software controls Wi-Fi/Bluetooth coexistence --> Wi-Fi`
|
||||
- ``{IDF_TARGET_NAME}-specific`` > ``Support for external,SPI-connected RAM`` > ``Try to allocate memories of Wi-Fi and LWIP...``
|
||||
- ``Bluetooth`` > ``Bluedroid Enable`` > ``BT/BLE will first malloc the memory from the PSRAM``
|
||||
- ``Bluetooth`` > ``Bluedroid Enable`` > ``Use dynamic memory allocation in BT/BLE stack``
|
||||
- ``Bluetooth`` > ``Bluetooth controller`` > ``BLE full scan feature supported``
|
||||
- ``Wi-Fi`` > ``Software controls Wi-Fi/Bluetooth coexistence`` > ``Wi-Fi``
|
||||
|
||||
|
||||
.. _ble-mesh-faq-fast-provisioning:
|
||||
|
@ -548,32 +548,32 @@ Generally, a Provisioner is used to provision unprovisioned devices and form a m
|
|||
4. Fast Provisioning
|
||||
--------------------
|
||||
|
||||
4.1 Why is fast provisioning needed?
|
||||
4.1 Why Is Fast Provisioning Needed?
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Normally when they are several unprovisioned devices, users can provision them one by one. But when it comes to a large number of unprovisioned devices (e.g. 100), provisioning them one by one will take huge amount of time. With fast provisioning, users can provision 100 unprovisioned devices in about 50 seconds.
|
||||
Normally when they are several unprovisioned devices, users can provision them one by one. But when it comes to a large number of unprovisioned devices (e.g., 100), provisioning them one by one will take huge amount of time. With fast provisioning, users can provision 100 unprovisioned devices in about 50 seconds.
|
||||
|
||||
4.2 Why EspBleMesh App would wait for a long time during fast provisioning?
|
||||
4.2 Why EspBleMesh App Would Wait for a Long Time During Fast Provisioning?
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
After the App provisioned one Proxy node, it will disconnect from the App during fast provisioning, and reconnect with the App when all the nodes are provisioned.
|
||||
|
||||
4.3 Why is the number of node addresses displayed in the App is more than that of existing node addresses?
|
||||
4.3 Why Is the Number of Node Addresses Displayed in the App Is More than That of Existing Node Addresses?
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Each time after a fast provisioning process, and before starting a new one, the node addresses in the App should be cleared, otherwise the number of the node address will be incorrect.
|
||||
|
||||
4.4 What is the usage of the **count** value which was input in EspBleMesh App?
|
||||
4.4 What Is the Usage of the **count** Value Which Was Input in EspBleMesh App?
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
The **count** value is provided to the Proxy node which is provisioned by the App so as to determine when to start Proxy advertising in advance.
|
||||
|
||||
4.5 When will Configuration Client Model of the node running :example:`fast_prov_server <bluetooth/esp_ble_mesh/ble_mesh_fast_provision/fast_prov_server>` example start to work?
|
||||
4.5 When Will Configuration Client Model of the Node Running :Example:`fast_prov_server <bluetooth/esp_ble_mesh/ble_mesh_fast_provision/fast_prov_server>` Example Start to Work?
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Configuration Client Model will start to work after the Temporary Provisioner functionality is enabled.
|
||||
|
||||
4.6 Will the Temporary Provisioner functionality be enabled all the time?
|
||||
4.6 Will the Temporary Provisioner Functionality Be Enabled All the Time?
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
After the nodes receive messages used to turn on/off lights, all the nodes will disable its Temporary Provisioner functionality and become nodes.
|
||||
|
@ -586,37 +586,37 @@ Generally, a Provisioner is used to provision unprovisioned devices and form a m
|
|||
|
||||
You can find meaning of errors or warnings when they appear at the bottom of ESP-BLE-MESH stack.
|
||||
|
||||
5.1 What is the meaning of warning :code:`ran out of retransmit attempts`?
|
||||
5.1 What Is the Meaning of Warning ``ran out of retransmit attempts``?
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
When the node transmits a segmented message, and due to some reasons, the receiver doesn't receive the complete message. Then the node will retransmit the message. When the retransmission count reaches the maximum number, which is 4 currently, then this warning will appear.
|
||||
When the node transmits a segmented message, and due to some reasons, the receiver does not receive the complete message. Then the node will retransmit the message. When the retransmission count reaches the maximum number, which is 4 currently, then this warning will appear.
|
||||
|
||||
5.2 What is the meaning of warning :code:`Duplicate found in Network Message Cache`?
|
||||
5.2 What Is the Meaning of Warning ``Duplicate found in Network Message Cache``?
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
When the node receives a message, it will compare the message with the ones stored in the network cache. If the same has been found in the cache, which means it has been received before, then the message will be dropped.
|
||||
|
||||
5.3 What is the meaning of warning :code:`Incomplete timer expired`?
|
||||
5.3 What Is the Meaning of Warning ``Incomplete timer expired``?
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
When the node doesn't receive all the segments of a segmented message during a certain period (e.g. 10 seconds), then the Incomplete timer will expire and this warning will appear.
|
||||
When the node does not receive all the segments of a segmented message during a certain period (e.g., 10 seconds), then the Incomplete timer will expire and this warning will appear.
|
||||
|
||||
5.4 What is the meaning of warning :code:`No matching TX context for ack`?
|
||||
5.4 What Is the Meaning of Warning ``No matching TX context for ack``?
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
When the node receives a segment ack and it doesn't find any self-send segmented message related with this ack, then this warning will appear.
|
||||
When the node receives a segment ack and it does not find any self-send segmented message related with this ack, then this warning will appear.
|
||||
|
||||
5.5 What is the meaning of warning :code:`No free slots for new incoming segmented messages`?
|
||||
5.5 What Is the Meaning of Warning ``No free dlots for new incoming segmented messages``?
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
When the node has no space for receiving new segmented message, this warning will appear. Users can make the space larger through the configuration :ref:`CONFIG_BLE_MESH_RX_SEG_MSG_COUNT`.
|
||||
|
||||
5.6 What is the meaning of error :code:`Model not bound to Appkey 0x0000`?
|
||||
5.6 What Is the Meaning of Error ``Model not bound to Appkey 0x0000``?
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
When the node sends messages with a model and the model has not been bound to the AppKey with AppKey Index 0x000, then this error will appear.
|
||||
|
||||
5.7 What is the meaning of error :code:`Busy sending message to DST xxxx`?
|
||||
5.7 What Is the Meaning of Error ``Busy sending message to DST xxxx``?
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
This error means client model of the node has transmitted a message to the target node and now is waiting for a response, users can not send messages to the same node with the same unicast address. After the corresponding response is received or timer is expired, then another message can be sent.
|
||||
|
@ -627,7 +627,7 @@ You can find meaning of errors or warnings when they appear at the bottom of ESP
|
|||
6. Example Help
|
||||
---------------
|
||||
|
||||
6.1 How are the ESP-BLE-MESH callback functions classified?
|
||||
6.1 How Are the ESP-BLE-MESH Callback Functions Classified?
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
- The API :cpp:func:`esp_ble_mesh_register_prov_callback` is used to register callback function used to handle provisioning and networking related events.
|
||||
|
@ -647,22 +647,22 @@ You can find meaning of errors or warnings when they appear at the bottom of ESP
|
|||
7. Others
|
||||
---------
|
||||
|
||||
7.1 How to print the message context?
|
||||
7.1 How to Print the Message Context?
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
The examples use :cpp:func:`ESP_LOG_BUFFER_HEX` to print the message context while the ESP-BLE-MESH protocol stack uses :cpp:func:`bt_hex`.
|
||||
|
||||
7.2 Which API can be used to restart {IDF_TARGET_NAME}?
|
||||
7.2 Which API Can Be Used to Restart {IDF_TARGET_NAME}?
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
The API :cpp:func:`esp_restart`.
|
||||
|
||||
7.3 How to monitor the remaining space of the stack of a task?
|
||||
7.3 How to Monitor the Remaining Space of the Stack of a Task?
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
The API :cpp:func:`vTaskList` can be used to print the remaining space of the task stack periodically.
|
||||
|
||||
7.4 How to change the level of log without changing the menuconfig output level?
|
||||
7.4 How to Change the Level of Log Without Changing the Menuconfig Output Level?
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
The API :cpp:func:`esp_log_level_set` can be used to change the log output level rather than using menuconfig to change it.
|
||||
|
|
|
@ -107,7 +107,7 @@ The Scanner is App's functionality to search for unprovisioned devices in range.
|
|||
4.2 Identify
|
||||
^^^^^^^^^^^^
|
||||
|
||||
Users can select any unprovisioned device, then the App will try to set up a connection with the selected device. After the BLE connection is established successfully (sometimes users need to try multiple times to get connected), and proper ESP-BLE-MESH GATT Service is discovered, users can see the **IDENTIFY** interface button on the screen. The IDENTIFY operation can be used to tell users which device is going to be provisioned.
|
||||
Users can select any unprovisioned device, then the App will try to set up a connection with the selected device. After the Bluetooth LE connection is established successfully (sometimes users need to try multiple times to get connected), and proper ESP-BLE-MESH GATT Service is discovered, users can see the **IDENTIFY** interface button on the screen. The IDENTIFY operation can be used to tell users which device is going to be provisioned.
|
||||
|
||||
.. note::
|
||||
The IDENTIFY operation also needs some cooperation on the device side, then users can see which device is in the provisioning process. Currently when pressing the **IDENTIFY** interface button, no signs can been seen from the device except from the log on the serial monitor.
|
||||
|
|
|
@ -95,7 +95,7 @@ ESP-BLE-MESH Terminology
|
|||
- PB-ADV transfers packets generated during the provisioning process over the advertising channels. This way can only be used for provisioning when provisioner and unprovisioned device both support PB-ADV.
|
||||
* - PB-GATT
|
||||
- PB-GATT is a provisioning bearer used to provision a device using Proxy PDUs to encapsulate Provisioning PDUs within the Mesh Provisioning Service.
|
||||
- PB-GATT uses connection channels to transfer packets generated during the provisioning process. If an unprovisioned device wants to be provisioned through this method, it needs to implement the related Mesh Provisioning Service. Unprovisioned devices which don't implement such service cannot be provisioned into mesh network through PB-GATT bearer.
|
||||
- PB-GATT uses connection channels to transfer packets generated during the provisioning process. If an unprovisioned device wants to be provisioned through this method, it needs to implement the related Mesh Provisioning Service. Unprovisioned devices which do not implement such service cannot be provisioned into mesh network through PB-GATT bearer.
|
||||
* - Provisioning
|
||||
- Provisioning is a process of adding an unprovisioned device to a mesh network, managed by a Provisioner.
|
||||
- The process of provisioning turns the "unprovisioned device" into a "node", making it a member of the ESP-BLE-MESH network.
|
||||
|
@ -150,7 +150,7 @@ ESP-BLE-MESH Terminology
|
|||
- Detailed Explanation
|
||||
* - Device Key (DevKey)
|
||||
- There is also a device key, which is a special application key that is unique to each node, is known only to the node and a Configuration Client, and is used to secure communications between the node and a Configuration Client.
|
||||
- The device key enables you to provision the devices, configure the nodes. The device key is used to encrypt Configuration Messages, i.e. the message transferred between the Provisioner and the node when the device is configured.
|
||||
- The device key enables you to provision the devices, configure the nodes. The device key is used to encrypt Configuration Messages, i.e., the message transferred between the Provisioner and the node when the device is configured.
|
||||
* - Application Key (AppKey)
|
||||
- Application keys are used to secure communications at the upper transport layer.
|
||||
- Application key is used for decryption of application data before delivering application data to application layer and encryption of them during the delivery of application layer. Some nodes in the network have a specific purpose and can restrict access to potentially sensitive data based on the needs of the application. With specific application keys, these nodes are associated with specific applications. Generally speaking, the fields using different application keys include security (access control of buildings, machine rooms and CEO offices), lighting (plant, exterior building and sidewalks) and HVAC systems. Application keys are bound to Network keys. This means application keys are only used in a context of a Network key they are bound to. An application key shall only be bound to a single Network key.
|
||||
|
@ -168,10 +168,10 @@ ESP-BLE-MESH Terminology
|
|||
* - Term
|
||||
- Official Definition
|
||||
- Detailed Explanation
|
||||
* - Reassembly / Segmentation
|
||||
* - Reassembly/Segmentation
|
||||
- Segmentation and reassembly (SAR) is a method of communication network, which is divided into small units before transmitting packets and reassembled in a proper order at the communication receiving end.
|
||||
- The lower transport layer will automatically segment the message whose size is too big. The receiving end will return a response message, and the transmitting end will send the data packet again that the receiving end does not receive according to the response message. This is automatically completed by the lower transport layer. Unsegmented messages have at most 15 bytes, of which 4 bytes are transMIC, so the remaining is 11 bytes; in the case of segmentation, there are 12 valid bytes in the first several packets, and 8 in the last one. Special case: A shorter packet requires mandatory segmentation from lower transport layer, in which case the valid byte is 8 bytes.
|
||||
* - Unacknowledged / Acknowledged
|
||||
* - Unacknowledged/Acknowledged
|
||||
- There are two types of messages: Unacknowledged or Acknowledged
|
||||
- Based on the whether or not the receiving end needs to send the response message, the messages sent are divided into two kinds. The sending end should set the maximum number of retransmission.
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@ ESP-WIFI-MESH
|
|||
|
||||
:link_to_translation:`zh_CN:[中文]`
|
||||
|
||||
This guide provides information regarding the ESP-WIFI-MESH protocol. Please see the :doc:`ESP-WIFI-MESH API Reference<../api-reference/network/esp-wifi-mesh>` for more information about API usage.
|
||||
This guide provides information regarding the ESP-WIFI-MESH protocol. Please see the :doc:`ESP-WIFI-MESH API Reference <../api-reference/network/esp-wifi-mesh>` for more information about API usage.
|
||||
|
||||
.. ------------------------------- Overview -----------------------------------
|
||||
|
||||
|
@ -115,6 +115,7 @@ ESP-WIFI-MESH is built atop the infrastructure Wi-Fi protocol and can be thought
|
|||
ESP-WIFI-MESH is a multiple hop (multi-hop) network meaning nodes can transmit packets to other nodes in the network through one or more wireless hops. Therefore, nodes in ESP-WIFI-MESH not only transmit their own packets, but simultaneously serve as relays for other nodes. Provided that a path exists between any two nodes on the physical layer (via one or more wireless hops), any pair of nodes within an ESP-WIFI-MESH network can communicate.
|
||||
|
||||
.. note::
|
||||
|
||||
The size (total number of nodes) in an ESP-WIFI-MESH network is dependent on the maximum number of layers permitted in the network, and the maximum number of downstream connections each node can have. Both of these variables can be configured to limit the size of the network.
|
||||
|
||||
Node Types
|
||||
|
@ -138,7 +139,7 @@ Node Types
|
|||
Beacon Frames & RSSI Thresholding
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Every node in ESP-WIFI-MESH that is able to form downstream connections (i.e. has a softAP interface) will periodically transmit Wi-Fi beacon frames. A node uses beacon frames to allow other nodes to detect its presence and know of its status. Idle nodes will listen for beacon frames to generate a list of potential parent nodes, one of which the idle node will form an upstream connection with. ESP-WIFI-MESH uses the Vendor Information Element to store metadata such as:
|
||||
Every node in ESP-WIFI-MESH that is able to form downstream connections (i.e., has a softAP interface) will periodically transmit Wi-Fi beacon frames. A node uses beacon frames to allow other nodes to detect its presence and know of its status. Idle nodes will listen for beacon frames to generate a list of potential parent nodes, one of which the idle node will form an upstream connection with. ESP-WIFI-MESH uses the Vendor Information Element to store metadata such as:
|
||||
|
||||
- Node Type (Root, Intermediate Parent, Leaf, Idle)
|
||||
- Current layer of Node
|
||||
|
@ -160,6 +161,7 @@ The signal strength of a potential upstream connection is represented by RSSI (R
|
|||
**Panel B** of the illustration above demonstrates how an RF shielding object can lower the RSSI of a potential parent node. Due to the RF shielding object, the area in which the RSSI of node X is above the threshold is significantly reduced. This causes the idle node to disregard node X even though node X is physically adjacent. The idle node will instead form an upstream connection with the physically distant node Y due to a stronger RSSI.
|
||||
|
||||
.. note::
|
||||
|
||||
Nodes technically still receive all beacon frames on the MAC layer. The RSSI threshold is an ESP-WIFI-MESH feature that simply filters out all received beacon frames that are below the preconfigured threshold.
|
||||
|
||||
Preferred Parent Node
|
||||
|
@ -186,7 +188,8 @@ If there are multiple parent node candidates within the same layer, the parent n
|
|||
**Panel B** of the illustration above demonstrates the case where the root node is within range of the idle node G. In other words, the root node's beacon frames are above the RSSI threshold when received by node G. The root node is always the shallowest node in an ESP-WIFI-MESH network hence is always the preferred parent node given multiple parent node candidates.
|
||||
|
||||
.. note::
|
||||
Users may also define their own algorithm for selecting a preferred parent node, or force a node to only connect with a specific parent node (see the :example:`Mesh Manual Networking Example<mesh/manual_networking>`).
|
||||
|
||||
Users may also define their own algorithm for selecting a preferred parent node, or force a node to only connect with a specific parent node (see the :example:`Mesh Manual Networking Example <mesh/manual_networking>`).
|
||||
|
||||
Routing Tables
|
||||
^^^^^^^^^^^^^^
|
||||
|
@ -200,7 +203,7 @@ Each node within an ESP-WIFI-MESH network will maintain its individual routing t
|
|||
|
||||
ESP-WIFI-MESH Routing Tables Example
|
||||
|
||||
Using the diagram above as an example, the routing table of node B would consist of the MAC addresses of nodes B to I (i.e. equivalent to the subnetwork of node B). Node B's routing table is internally partitioned into two subtables containing of nodes C to F and nodes G to I (i.e. equivalent to the subnetworks of nodes C and G respectively).
|
||||
Using the diagram above as an example, the routing table of node B would consist of the MAC addresses of nodes B to I (i.e., equivalent to the subnetwork of node B). Node B's routing table is internally partitioned into two subtables containing of nodes C to F and nodes G to I (i.e., equivalent to the subnetworks of nodes C and G respectively).
|
||||
|
||||
**ESP-WIFI-MESH utilizes routing tables to determine whether an ESP-WIFI-MESH packet should be forwarded upstream or downstream based on the following rules.**
|
||||
|
||||
|
@ -209,6 +212,7 @@ Using the diagram above as an example, the routing table of node B would consist
|
|||
**2.** If the destination MAC address is not within the current node's routing table, forward the data packet upstream to the current node's parent node. Doing so repeatedly will result in the packet arriving at the root node where the routing table should contain all nodes within the network.
|
||||
|
||||
.. note::
|
||||
|
||||
Users can call :cpp:func:`esp_mesh_get_routing_table` to obtain a node's routing table, or :cpp:func:`esp_mesh_get_routing_table_size` to obtain the size of a node's routing table. :cpp:func:`esp_mesh_get_subnet_nodes_list` can be used to obtain the corresponding subtable of a specific child node. Likewise :cpp:func:`esp_mesh_get_subnet_nodes_num` can be used to obtain the size of the subtable.
|
||||
|
||||
|
||||
|
@ -223,6 +227,7 @@ General Process
|
|||
^^^^^^^^^^^^^^^
|
||||
|
||||
.. warning::
|
||||
|
||||
Before the ESP-WIFI-MESH network building process can begin, certain parts of the configuration must be uniform across each node in the network (see :cpp:type:`mesh_cfg_t`). Each node must be configured with **the same Mesh Network ID, router configuration, and softAP configuration**.
|
||||
|
||||
An ESP-WIFI-MESH network building process involves selecting a root node, then forming downstream connections layer by layer until all nodes have joined the network. The exact layout of the network can be dependent on factors such as root node selection, parent node selection, and asynchronous power-on reset. However, the ESP-WIFI-MESH network building process can be generalized into the following steps:
|
||||
|
@ -242,7 +247,7 @@ The root node can be designated during configuration (see section on `User Desig
|
|||
"""""""""""""""""""""""""
|
||||
Once the root node has connected to the router, idle nodes in range of the root node will begin connecting with the root node thereby forming the second layer of the network. Once connected, the second layer nodes become intermediate parent nodes (assuming maximum permitted layers > 2) hence the next layer to form. Referring to the figure above, nodes B to D are in range of the root node. Therefore nodes B to D form upstream connections with the root node and become intermediate parent nodes.
|
||||
|
||||
3. Formation of remaining layers
|
||||
3. Formation of Remaining Layers
|
||||
""""""""""""""""""""""""""""""""
|
||||
The remaining idle nodes will connect with intermediate parent nodes within range thereby forming a new layer in the network. Once connected, the idles nodes become intermediate parent node or leaf nodes depending on the networks maximum permitted layers. This step is repeated until there are no more idle nodes within the network or until the maximum permitted layer of the network has been reached. Referring to the figure above, nodes E/F/G connect with nodes B/C/D respectively and become intermediate parent nodes themselves.
|
||||
|
||||
|
@ -255,7 +260,7 @@ Automatic Root Node Selection
|
|||
|
||||
The automatic selection of a root node involves an election process amongst all idle nodes based on their signal strengths with the router. Each idle node will transmit their MAC addresses and router RSSI values via Wi-Fi beacon frames. **The MAC address is used to uniquely identify each node in the network** whilst the **router RSSI** is used to indicate a node's signal strength with reference to the router.
|
||||
|
||||
Each node will then simultaneously scan for the beacon frames from other idle nodes. If a node detects a beacon frame with a stronger router RSSI, the node will begin transmitting the contents of that beacon frame (i.e. voting for the node with the stronger router RSSI). The process of transmission and scanning will repeat for a preconfigured minimum number of iterations (10 iterations by default) and result in the beacon frame with the strongest router RSSI being propagated throughout the network.
|
||||
Each node will then simultaneously scan for the beacon frames from other idle nodes. If a node detects a beacon frame with a stronger router RSSI, the node will begin transmitting the contents of that beacon frame (i.e., voting for the node with the stronger router RSSI). The process of transmission and scanning will repeat for a preconfigured minimum number of iterations (10 iterations by default) and result in the beacon frame with the strongest router RSSI being propagated throughout the network.
|
||||
|
||||
After all iterations, each node will individually check for its **vote percentage** (``number of votes/number of nodes participating in election``) to determine if it should become the root node. **If a node has a vote percentage larger than a preconfigured threshold (90% by default), the node will become a root node**.
|
||||
|
||||
|
@ -272,14 +277,16 @@ The following diagram demonstrates how an ESP-WIFI-MESH network is built when th
|
|||
|
||||
**2.** Over multiple iterations of transmission and scanning, the beacon frame with the strongest router RSSI is propagated throughout the network. Node C has the strongest router RSSI (-10 dB) hence its beacon frame is propagated throughout the network. All nodes participating in the election vote for node C thus giving node C a vote percentage of 100%. Therefore node C becomes a root node and connects with the router.
|
||||
|
||||
**3.** Once Node C has connected with the router, nodes A/B/D/E connectwith node C as it is the preferred parent node (i.e. the shallowest node). Nodes A/B/D/E form the second layer of the network.
|
||||
**3.** Once Node C has connected with the router, nodes A/B/D/E connectwith node C as it is the preferred parent node (i.e., the shallowest node). Nodes A/B/D/E form the second layer of the network.
|
||||
|
||||
**4.** Node F and G connect with nodes D and E respectively and the network building process is complete.
|
||||
|
||||
.. note::
|
||||
The minimum number of iterations for the election process can be configured using :cpp:func:`esp_mesh_set_attempts`. Users should adjust the number of iterations based on the number of nodes within the network (i.e. the larger the network the larger number of scan iterations required).
|
||||
|
||||
The minimum number of iterations for the election process can be configured using :cpp:func:`esp_mesh_set_attempts`. Users should adjust the number of iterations based on the number of nodes within the network (i.e., the larger the network the larger number of scan iterations required).
|
||||
|
||||
.. warning::
|
||||
|
||||
**Vote percentage threshold** can also be configured using :cpp:func:`esp_mesh_set_vote_percentage`. Setting a low vote percentage threshold **can result in two or more nodes becoming root nodes** within the same ESP-WIFI-MESH network leading to the building of multiple networks. If such is the case, ESP-WIFI-MESH has internal mechanisms to autonomously resolve the **root node conflict**. The networks of the multiple root nodes will be combined into a single network with a single root node. However, root node conflicts where two or more root nodes have the same router SSID but different router BSSID are not handled.
|
||||
|
||||
User Designated Root Node
|
||||
|
@ -303,6 +310,7 @@ The root node can also be designated by user which will entail the designated ro
|
|||
**4.** Node G connects with node E, forming the fourth layer of the network. However the maximum permitted number of layers in this network is configured as four, therefore node G becomes a leaf node to prevent any new layers from forming.
|
||||
|
||||
.. note::
|
||||
|
||||
When designating a root node, the root node should call :cpp:func:`esp_mesh_set_parent` in order to directly connect with the router. Likewise, all other nodes should call :cpp:func:`esp_mesh_fix_root` to forgo the election process.
|
||||
|
||||
Parent Node Selection
|
||||
|
@ -310,16 +318,16 @@ Parent Node Selection
|
|||
|
||||
By default, ESP-WIFI-MESH is self organizing meaning that each node will autonomously select which potential parent node to form an upstream connection with. The autonomously selected parent node is known as the preferred parent node. The criteria used for selecting the preferred parent node is designed to reduce the number of layers in the ESP-WIFI-MESH network and to balance the number of downstream connections between potential parent nodes (see section on `Preferred Parent Node`_).
|
||||
|
||||
However ESP-WIFI-MESH also allows users to disable self-organizing behavior which will allow users to define their own criteria for parent node selection, or to configure nodes to have designated parent nodes (see the :example:`Mesh Manual Networking Example<mesh/manual_networking>`).
|
||||
However ESP-WIFI-MESH also allows users to disable self-organizing behavior which will allow users to define their own criteria for parent node selection, or to configure nodes to have designated parent nodes (see the :example:`Mesh Manual Networking Example <mesh/manual_networking>`).
|
||||
|
||||
Asynchronous Power-on Reset
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
ESP-WIFI-MESH network building can be affected by the order in which nodes power-on. If certain nodes within the network power-on asynchronously (i.e. separated by several minutes), **the final structure of the network could differ from the ideal case where all nodes are powered on synchronously**. Nodes that are delayed in powering on will adhere to the following rules:
|
||||
ESP-WIFI-MESH network building can be affected by the order in which nodes power-on. If certain nodes within the network power-on asynchronously (i.e., separated by several minutes), **the final structure of the network could differ from the ideal case where all nodes are powered on synchronously**. Nodes that are delayed in powering on will adhere to the following rules:
|
||||
|
||||
**Rule 1:** If a root node already exists in the network, the delayed node will not attempt to elect a new root node, even if it has a stronger RSSI with the router. The delayed node will instead join the network like any other idle node by connecting with a preferred parent node. If the delayed node is the designated root node, all other nodes in the network will remain idle until the delayed node powers-on.
|
||||
|
||||
**Rule 2:** If a delayed node forms an upstream connection and becomes an intermediate parent node, it may also become the new preferred parent of other nodes (i.e. being a shallower node). This will cause the other nodes to switch their upstream connections to connect with the delayed node (see `Parent Node Switching`_).
|
||||
**Rule 2:** If a delayed node forms an upstream connection and becomes an intermediate parent node, it may also become the new preferred parent of other nodes (i.e., being a shallower node). This will cause the other nodes to switch their upstream connections to connect with the delayed node (see `Parent Node Switching`_).
|
||||
|
||||
**Rule 3:** If an idle node has a designated parent node which is delayed in powering-on, the idle node will not attempt to form any upstream connections in the absence of its designated parent node. The idle node will remain idle indefinitely until its designated parent node powers-on.
|
||||
|
||||
|
@ -343,6 +351,7 @@ The following example demonstrates the effects of asynchronous power-on with reg
|
|||
**Synchronous Power-On:** Had all nodes powered-on synchronously, node E would have become the root node as it has the strongest router RSSI (-10 dB). This would result in a significantly different network layout compared to the network formed under the conditions of asynchronous power-on. **However the synchronous power-on network layout can still be reached if the user manually switches the root node** (see :cpp:func:`esp_mesh_waive_root`).
|
||||
|
||||
.. note::
|
||||
|
||||
Differences in parent node selection caused by asynchronous power-on are autonomously corrected for to some extent in ESP-WIFI-MESH (see `Parent Node Switching`_)
|
||||
|
||||
Loop-back Avoidance, Detection, and Handling
|
||||
|
@ -366,7 +375,7 @@ Root Node Failure
|
|||
|
||||
If the root node breaks down, the nodes connected with it (second layer nodes) will promptly detect the failure of the root node. The second layer nodes will initially attempt to reconnect with the root node. However after multiple failed attempts, the second layer nodes will initialize a new round of root node election. **The second layer node with the strongest router RSSI will be elected as the new root node** whilst the remaining second layer nodes will form an upstream connection with the new root node (or a neighboring parent node if not in range).
|
||||
|
||||
If the root node and multiple downstream layers simultaneously break down (e.g. root node, second layer, and third layer), the shallowest layer that is still functioning will initialize the root node election. The following example illustrates an example of self healing from a root node break down.
|
||||
If the root node and multiple downstream layers simultaneously break down (e.g., root node, second layer, and third layer), the shallowest layer that is still functioning will initialize the root node election. The following example illustrates an example of self healing from a root node break down.
|
||||
|
||||
.. figure:: ../../_static/mesh-root-node-failure.png
|
||||
:align: center
|
||||
|
@ -382,6 +391,7 @@ If the root node and multiple downstream layers simultaneously break down (e.g.
|
|||
**3.** Node B is elected as the root node and begins accepting downstream connections. The remaining second layer nodes A/D/E form upstream connections with node B thus the network is healed and can continue operating normally.
|
||||
|
||||
.. note::
|
||||
|
||||
If a designated root node breaks down, the remaining nodes **will not autonomously attempt to elect a new root node** as an election process will never be attempted whilst a designated root node is used.
|
||||
|
||||
Intermediate Parent Node Failure
|
||||
|
@ -407,6 +417,7 @@ The following diagram illustrates an example of self healing from an Intermediat
|
|||
**3.** Node G is out of range from any other parent node hence remains idle for the time being. Node F is in range of nodes B/E, however node B is selected as it is the shallower node. Node F becomes an intermediate parent node after connecting with Node B thus node G can connect with node F. The network is healed, however the network routing as been affected and an extra layer has been added.
|
||||
|
||||
.. note::
|
||||
|
||||
If a child node has a designated parent node that breaks down, the child node will make no attempt to connect with a new parent node. The child node will remain idle indefinitely.
|
||||
|
||||
Root Node Switching
|
||||
|
@ -414,7 +425,7 @@ Root Node Switching
|
|||
|
||||
ESP-WIFI-MESH does not automatically switch the root node unless the root node breaks down. Even if the root node's router RSSI degrades to the point of disconnection, the root node will remain unchanged. Root node switching is the act of explicitly starting a new election such that a node with a stronger router RSSI will be elected as the new root node. This can be a useful method of adapting to degrading root node performance.
|
||||
|
||||
To trigger a root node switch, the current root node must explicitly call :cpp:func:`esp_mesh_waive_root` to trigger a new election. The current root node will signal all nodes within the network to begin transmitting and scanning for beacon frames (see `Automatic Root Node Selection`_) **whilst remaining connected to the network (i.e. not idle)**. If another node receives more votes than the current root node, a root node switch will be initiated. **The root node will remain unchanged otherwise**.
|
||||
To trigger a root node switch, the current root node must explicitly call :cpp:func:`esp_mesh_waive_root` to trigger a new election. The current root node will signal all nodes within the network to begin transmitting and scanning for beacon frames (see `Automatic Root Node Selection`_) **whilst remaining connected to the network (i.e., not idle)**. If another node receives more votes than the current root node, a root node switch will be initiated. **The root node will remain unchanged otherwise**.
|
||||
|
||||
A newly elected root node sends a **switch request** to the current root node which in turn will respond with an acknowledgment signifying both nodes are ready to switch. Once the acknowledgment is received, the newly elected root node will disconnect from its parent and promptly form an upstream connection with the router thereby becoming the new root node of the network. The previous root node will disconnect from the router **whilst maintaining all of its downstream connections** and enter the idle state. The previous root node will then begin scanning for potential parent nodes and selecting a preferred parent.
|
||||
|
||||
|
@ -436,12 +447,13 @@ The following diagram illustrates an example of a root node switch.
|
|||
**4.** Node C selects node B as its preferred parent node, forms an upstream connection, and becomes a second layer node. The network layout is similar after the switch as node C still maintains the same subnetwork. However each node in node C's subnetwork has been placed one layer deeper as a result of the switch. `Parent Node Switching`_ may adjust the network layout afterwards if any nodes have a new preferred parent node as a result of the root node switch.
|
||||
|
||||
.. note::
|
||||
|
||||
Root node switching must require an election hence is only supported when using a self-organized ESP-WIFI-MESH network. In other words, root node switching cannot occur if a designated root node is used.
|
||||
|
||||
Parent Node Switching
|
||||
^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Parent Node Switching entails a child node switching its upstream connection to another parent node of a shallower layer. **Parent Node Switching occurs autonomously** meaning that a child node will change its upstream connection automatically if a potential parent node of a shallower layer becomes available (i.e. due to a `Asynchronous Power-on Reset`_).
|
||||
Parent Node Switching entails a child node switching its upstream connection to another parent node of a shallower layer. **Parent Node Switching occurs autonomously** meaning that a child node will change its upstream connection automatically if a potential parent node of a shallower layer becomes available (i.e., due to a `Asynchronous Power-on Reset`_).
|
||||
|
||||
All potential parent nodes periodically transmit beacon frames (see `Beacon Frames & RSSI Thresholding`_) allowing for a child node to scan for the availability of a shallower parent node. Due to parent node switching, a self-organized ESP-WIFI-MESH network can dynamically adjust its network layout to ensure each connection has a good RSSI and that the number of layers in the network is minimized.
|
||||
|
||||
|
@ -472,6 +484,7 @@ The following diagram shows the structure of an ESP-WIFI-MESH packet and its rel
|
|||
**The payload** of an ESP-WIFI-MESH packet contains the actual application data. This data can be raw binary data, or encoded under an application layer protocol such as HTTP, MQTT, and JSON (see :cpp:type:`mesh_proto_t`).
|
||||
|
||||
.. note::
|
||||
|
||||
When sending an ESP-WIFI-MESH packet to the external IP network, the destination address field of the header will contain the IP address and port of the target server rather than the MAC address of a node (see :cpp:type:`mesh_addr_t`). Furthermore the root node will handle the formation of the outgoing TCP/IP packet.
|
||||
|
||||
Group Control & Multicasting
|
||||
|
@ -484,6 +497,7 @@ To multicast by specifying a list of target nodes, users must first set the ESP-
|
|||
Multicasting by group allows a ESP-WIFI-MESH packet to be transmitted to a preconfigured group of nodes. Each grouping is identified by a unique ID, and a node can be placed into a group via :cpp:func:`esp_mesh_set_group_id`. Multicasting to a group involves setting the destination address of the ESP-WIFI-MESH packet to the target group ID. Furthermore, the :c:macro:`MESH_DATA_GROUP` flag must set. Using groups to multicast incurs less overhead, but requires nodes to previously added into groups.
|
||||
|
||||
.. note::
|
||||
|
||||
During a multicast, all nodes within the network still receive the ESP-WIFI-MESH packet on the MAC layer. However, nodes not included in the MAC address list or the target group will simply filter out the packet.
|
||||
|
||||
Broadcasting
|
||||
|
@ -519,9 +533,11 @@ ESP-WIFI-MESH relies on parent nodes to control the upstream data flow of their
|
|||
**3.** The child node transmits the data packet in accordance with the window size specified by the parent node. If the child node depletes its receiving window, it must obtain another receiving windows by sending a request before it is permitted to continue transmitting.
|
||||
|
||||
.. note::
|
||||
|
||||
ESP-WIFI-MESH does not support any downstream flow control.
|
||||
|
||||
.. warning::
|
||||
|
||||
Due to `Parent Node Switching`_, packet loss may occur during upstream transmissions.
|
||||
|
||||
Due to the fact that the root node acts as the sole interface to an external IP network, it is critical that downstream nodes are aware of the root node's connection status with the external IP network. Failing to do so can lead to nodes attempting to pass data upstream to the root node whilst it is disconnected from the IP network. This results in unnecessary transmissions and packet loss. ESP-WIFI-MESH address this issue by providing a mechanism to stabilize the throughput of outgoing data based on the connection status between the root node and the external IP network. The root node can broadcast its external IP network connection status to all other nodes by calling :cpp:func:`esp_mesh_post_toDS_state`.
|
||||
|
@ -562,9 +578,9 @@ A CSA element contains information regarding the **New Channel Number** and a **
|
|||
ESP-WIFI-MESH Network Channel Switching
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
ESP-WIFI-MESH Network Channel Switching also utilize beacon frames that contain a CSA element. However, being a multi-hop network makes the switching process in ESP-WIFI-MESH is more complex due to the fact that a beacon frame might not be able to reach all nodes within the network (i.e. in a single hop). Therefore, an ESP-WIFI-MESH network relies on nodes to forward the CSA element so that it is propagated throughout the network.
|
||||
ESP-WIFI-MESH Network Channel Switching also utilize beacon frames that contain a CSA element. However, being a multi-hop network makes the switching process in ESP-WIFI-MESH is more complex due to the fact that a beacon frame might not be able to reach all nodes within the network (i.e., in a single hop). Therefore, an ESP-WIFI-MESH network relies on nodes to forward the CSA element so that it is propagated throughout the network.
|
||||
|
||||
When an intermediate parent node with one or more child nodes receives a beacon frame containing a CSA, the node will forward the CSA element by including the element in its next transmitted beacon frame (i.e. with the same **New Channel Number** and **Channel Switch Count**). Given that all nodes within an ESP-WIFI-MESH network receive the same CSA, the nodes can synchronize their channel switches using the Channel Switch Count, albeit with a short delay due to CSA element forwarding.
|
||||
When an intermediate parent node with one or more child nodes receives a beacon frame containing a CSA, the node will forward the CSA element by including the element in its next transmitted beacon frame (i.e., with the same **New Channel Number** and **Channel Switch Count**). Given that all nodes within an ESP-WIFI-MESH network receive the same CSA, the nodes can synchronize their channel switches using the Channel Switch Count, albeit with a short delay due to CSA element forwarding.
|
||||
|
||||
An ESP-WIFI-MESH network channel switch can be triggered by either the router or the root node.
|
||||
|
||||
|
@ -587,24 +603,25 @@ Impact of Network Channel Switching
|
|||
- The ESP-WIFI-MESH network's channel switch time is dependent on the ESP-WIFI-MESH network's beacon interval and the root node's custom Channel Switch Count value.
|
||||
- The channel discrepancy prevents any data exchange between the root node and the router during that ESP-WIFI-MESH network's switch.
|
||||
- In the ESP-WIFI-MESH network, the root node and intermediate parent nodes will request their connected child nodes to stop transmissions until the channel switch takes place by setting the **Channel Switch Mode** field in the CSA element to 1.
|
||||
- Frequent router triggered network channel switches can degrade the ESP-WIFI-MESH network's performance. Note that this can be caused by the ESP-WIFI-MESH network itself (e.g. due to wireless medium contention with ESP-WIFI-MESH network). If this is the case, users should disable the automatic channel switching on the router and use a specified channel instead.
|
||||
- Frequent router triggered network channel switches can degrade the ESP-WIFI-MESH network's performance. Note that this can be caused by the ESP-WIFI-MESH network itself (e.g., due to wireless medium contention with ESP-WIFI-MESH network). If this is the case, users should disable the automatic channel switching on the router and use a specified channel instead.
|
||||
|
||||
- When there is a **temporary channel discrepancy**, the root node remains technically connected to the router.
|
||||
- Disconnection occurs after the root node fails to receive any beacon frames or probe responses from the router over a fixed number of router beacon intervals.
|
||||
- Upon disconnection, the root node will automatically re-scan all channels for the presence of a router.
|
||||
|
||||
- If the root node is unable to receive any of the router's CSA beacon frames (e.g. due to short switch time given by the router), the router will switch channels without the ESP-WIFI-MESH network's knowledge.
|
||||
- If the root node is unable to receive any of the router's CSA beacon frames (e.g., due to short switch time given by the router), the router will switch channels without the ESP-WIFI-MESH network's knowledge.
|
||||
- After the router switches channels, the root node will no longer be able to receive the router's beacon frames and probe responses and result in a disconnection after a fixed number of beacon intervals.
|
||||
- The root node will re-scan all channels for the router after disconnection.
|
||||
- The root node will maintain downstream connections throughout this process.
|
||||
|
||||
.. note::
|
||||
Although ESP-WIFI-MESH network channel switching aims to move all nodes within the network to a new operating channel, it should be recognized that a channel switch might not successfully move all nodes (e.g. due to reasons such as node failures).
|
||||
|
||||
Although ESP-WIFI-MESH network channel switching aims to move all nodes within the network to a new operating channel, it should be recognized that a channel switch might not successfully move all nodes (e.g., due to reasons such as node failures).
|
||||
|
||||
Channel and Router Switching Configuration
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
ESP-WIFI-MESH allows for autonomous channel switching to be enabled/disabled via configuration. Likewise, autonomous router switching (i.e. when a root node autonomously connects to another router) can also be enabled/disabled by configuration. Autonomous channel switching and router switching is dependent on the following configuration parameters and run-time conditions.
|
||||
ESP-WIFI-MESH allows for autonomous channel switching to be enabled/disabled via configuration. Likewise, autonomous router switching (i.e., when a root node autonomously connects to another router) can also be enabled/disabled by configuration. Autonomous channel switching and router switching is dependent on the following configuration parameters and run-time conditions.
|
||||
|
||||
**Allow Channel Switch:** This parameter is set via the ``allow_channel_switch`` field of the :cpp:type:`mesh_cfg_t` structure and permits an ESP-WIFI-MESH network to dynamically switch channels when set.
|
||||
|
||||
|
@ -617,7 +634,7 @@ BSSID of the desired router. If this field is unset, the ``allow_router_switch``
|
|||
|
||||
**Root Node Present:** The presence of a root node will can also affect whether or a channel or router switch is permitted.
|
||||
|
||||
The following table illustrates how the different combinations of parameters/conditions affect whether channel switching and/or router switching is permitted. Note that `X` represents a "don't care" for the parameter.
|
||||
The following table illustrates how the different combinations of parameters/conditions affect whether channel switching and/or router switching is permitted. Note that `X` represents a "do not care" for the parameter.
|
||||
|
||||
.. list-table::
|
||||
:widths: 15 15 15 15 15 15
|
||||
|
@ -728,6 +745,7 @@ The following table lists the common performance figures of an ESP-WIFI-MESH net
|
|||
* Per-hop latency: 10 to 30 milliseconds
|
||||
|
||||
.. note::
|
||||
|
||||
The following test conditions were used to generate the performance figures above.
|
||||
|
||||
- Number of test devices: **100**
|
||||
|
@ -735,12 +753,15 @@ The following table lists the common performance figures of an ESP-WIFI-MESH net
|
|||
- Maximum Permissible Layers: **6**
|
||||
|
||||
.. note::
|
||||
|
||||
Throughput depends on packet error rate and hop count.
|
||||
|
||||
.. note::
|
||||
|
||||
The throughput of root node's access to the external IP network is directly affected by the number of nodes in the ESP-WIFI-MESH network and the bandwidth of the router.
|
||||
|
||||
.. note::
|
||||
|
||||
The performance figures can vary greatly between installations based on network configuration and operating environment.
|
||||
|
||||
.. ----------------------------- Further Notes --------------------------------
|
||||
|
|
|
@ -8,6 +8,7 @@ Support for External RAM
|
|||
|
||||
Introduction
|
||||
============
|
||||
|
||||
{IDF_TARGET_PSRAM_VADDR_SIZE:default="Value not updated", esp32="4 MB", esp32s2="10.5 MB", esp32s3="32 MB"}
|
||||
|
||||
{IDF_TARGET_NAME} has a few hundred kilobytes of internal RAM, residing on the same die as the rest of the chip components. It can be insufficient for some purposes, so {IDF_TARGET_NAME} has the ability to use up to {IDF_TARGET_PSRAM_VADDR_SIZE} of virtual addresses for external PSRAM (Psuedostatic RAM) memory. The external memory is incorporated in the memory map and, with certain restrictions, is usable in the same way as internal data RAM.
|
||||
|
@ -27,7 +28,7 @@ Hardware
|
|||
|
||||
.. note::
|
||||
|
||||
Espressif produces both modules and system-in-package chips that integrate compatible PSRAM and flash and are ready to mount on a product PCB. Consult the Espressif website for more information. If you're using a custom PSRAM chip, ESP-IDF SDK might not be compatible with it.
|
||||
Espressif produces both modules and system-in-package chips that integrate compatible PSRAM and flash and are ready to mount on a product PCB. Consult the Espressif website for more information. If you are using a custom PSRAM chip, ESP-IDF SDK might not be compatible with it.
|
||||
|
||||
For specific details about connecting the SoC or module pins to an external PSRAM chip, consult the SoC or module datasheet.
|
||||
|
||||
|
@ -141,7 +142,7 @@ Remaining external RAM can also be added to the capability heap allocator using
|
|||
|
||||
- The corresponding virtual memory range of those instructions will also be re-mapped to PSRAM.
|
||||
|
||||
If :ref:`CONFIG_SPIRAM_RODATA` is also enabled, the cache won't be disabled during an SPI1 flash operation. You don't need to make sure ISRs, ISR callbacks and involved data are placed in internal RAM, thus internal RAM usage can be optimized.
|
||||
If :ref:`CONFIG_SPIRAM_RODATA` is also enabled, the cache will not be disabled during an SPI1 flash operation. You do not need to make sure ISRs, ISR callbacks and involved data are placed in internal RAM, thus internal RAM usage can be optimized.
|
||||
|
||||
.. _external_ram_config_rodata:
|
||||
|
||||
|
@ -156,7 +157,7 @@ Remaining external RAM can also be added to the capability heap allocator using
|
|||
|
||||
- The corresponding virtual memory range of those rodata will also be re-mapped to PSRAM.
|
||||
|
||||
If :ref:`CONFIG_SPIRAM_FETCH_INSTRUCTIONS` is also enabled, the cache won't be disabled during an SPI1 flash operation. You don't need to make sure ISRs, ISR callbacks and involved data are placed in internal RAM, thus internal RAM usage can be optimized.
|
||||
If :ref:`CONFIG_SPIRAM_FETCH_INSTRUCTIONS` is also enabled, the cache will not be disabled during an SPI1 flash operation. You do not need to make sure ISRs, ISR callbacks and involved data are placed in internal RAM, thus internal RAM usage can be optimized.
|
||||
|
||||
Restrictions
|
||||
============
|
||||
|
@ -176,7 +177,7 @@ External RAM use has the following restrictions:
|
|||
- The bandwidth that DMA accesses external RAM is very limited, especially when CPU is trying to access the external RAM at the same time.
|
||||
- You can configure :ref:`CONFIG_SPIRAM_SPEED` as 120 MHz for an octal PSRAM. The bandwidth will be improved. However there are still restrictions for this option. See :ref:`All Supported PSRAM Modes and Speeds <flash-psram-combination>` for more details.
|
||||
|
||||
* External RAM uses the same cache region as the external flash. This means that frequently accessed variables in external RAM can be read and modified almost as quickly as in internal ram. However, when accessing large chunks of data (>32 KB), the cache can be insufficient, and speeds will fall back to the access speed of the external RAM. Moreover, accessing large chunks of data can "push out" cached flash, possibly making the execution of code slower afterwards.
|
||||
* External RAM uses the same cache region as the external flash. This means that frequently accessed variables in external RAM can be read and modified almost as quickly as in internal ram. However, when accessing large chunks of data (> 32 KB), the cache can be insufficient, and speeds will fall back to the access speed of the external RAM. Moreover, accessing large chunks of data can "push out" cached flash, possibly making the execution of code slower afterwards.
|
||||
|
||||
* In general, external RAM will not be used as task stack memory. :cpp:func:`xTaskCreate` and similar functions will always allocate internal memory for stack and task TCBs.
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
Fatal Errors
|
||||
============
|
||||
|
||||
:link_to_translation:`zh_CN:[中文]`
|
||||
|
||||
.. _Overview:
|
||||
|
@ -59,7 +60,7 @@ Subsequent behavior of the panic handler can be set using :ref:`CONFIG_ESP_SYSTE
|
|||
|
||||
- Silent reboot (``CONFIG_ESP_SYSTEM_PANIC_SILENT_REBOOT``)
|
||||
|
||||
Don't print registers or backtrace, restart the chip immediately.
|
||||
Do not print registers or backtrace, restart the chip immediately.
|
||||
|
||||
- Invoke GDB Stub (``CONFIG_ESP_SYSTEM_PANIC_GDBSTUB``)
|
||||
|
||||
|
@ -303,7 +304,9 @@ Guru Meditation Errors
|
|||
|
||||
This section explains the meaning of different error causes, printed in parens after the ``Guru Meditation Error: Core panic'ed`` message.
|
||||
|
||||
.. note:: See the `Guru Meditation Wikipedia article <https://en.wikipedia.org/wiki/Guru_Meditation>`_ for historical origins of "Guru Meditation".
|
||||
.. note::
|
||||
|
||||
See the `Guru Meditation Wikipedia article <https://en.wikipedia.org/wiki/Guru_Meditation>`_ for historical origins of "Guru Meditation".
|
||||
|
||||
|
||||
|ILLEGAL_INSTR_MSG|
|
||||
|
@ -354,19 +357,19 @@ This CPU exception indicates that the instruction which was executed was not a v
|
|||
|
||||
- If the application has attempted to write to a read-only memory region, such as IROM or DROM.
|
||||
|
||||
Unhandled debug exception
|
||||
Unhandled Debug Exception
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
This CPU exception happens when the instruction ``BREAK`` is executed.
|
||||
|
||||
.. only:: CONFIG_IDF_TARGET_ARCH_RISCV
|
||||
|
||||
Instruction address misaligned
|
||||
Instruction Address Misaligned
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
This CPU exception indicates that the address of the instruction to execute is not 2-byte aligned.
|
||||
|
||||
Instruction access fault, Load access fault, Store access fault
|
||||
Instruction Access Fault, Load Access Fault, Store Access Fault
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
This CPU exception happens when application attempts to execute, read from or write to an invalid memory location. The address which was written/read is found in ``MTVAL`` register in the register dump. If this address is zero, it usually means that application attempted to dereference a NULL pointer. If this address is close to zero, it usually means that application attempted to access member of a structure, but the pointer to the structure was NULL. If this address is something else (garbage value, not in ``0x3fxxxxxx`` - ``0x6xxxxxxx`` range), it likely means that the pointer used to access the data was either not initialized or was corrupted.
|
||||
|
@ -376,7 +379,7 @@ This CPU exception indicates that the instruction which was executed was not a v
|
|||
|
||||
This CPU exception happens when the instruction ``EBREAK`` is executed. See also :ref:`FreeRTOS-End-Of-Stack-Watchpoint`.
|
||||
|
||||
Load address misaligned, Store address misaligned
|
||||
Load Address Misaligned, Store Address Misaligned
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Application has attempted to read or write memory location, and address alignment did not match load/store size. For example, 32-bit load can only be done from 4-byte aligned address, and 16-bit load can only be done from a 2-byte aligned address.
|
||||
|
@ -393,7 +396,7 @@ In some situations, ESP-IDF will temporarily disable access to external SPI Flas
|
|||
|
||||
.. only:: SOC_MEMPROT_SUPPORTED
|
||||
|
||||
Memory protection fault
|
||||
Memory Protection Fault
|
||||
^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
{IDF_TARGET_NAME} Permission Control feature is used in ESP-IDF to prevent the following types of memory access:
|
||||
|
@ -527,7 +530,7 @@ Undefined Behavior Sanitizer (UBSAN) Checks
|
|||
Undefined behavior sanitizer (UBSAN) is a compiler feature which adds run-time checks for potentially incorrect operations, such as:
|
||||
|
||||
- overflows (multiplication overflow, signed integer overflow)
|
||||
- shift base or exponent errors (e.g. shift by more than 32 bits)
|
||||
- shift base or exponent errors (e.g., shift by more than 32 bits)
|
||||
- integer conversion errors
|
||||
|
||||
See `GCC documentation <https://gcc.gnu.org/onlinedocs/gcc/Instrumentation-Options.html>`_ of ``-fsanitize=undefined`` option for the complete list of supported checks.
|
||||
|
@ -552,7 +555,9 @@ To enable UBSAN for a specific component (``component_name``) from the project's
|
|||
idf_component_get_property(lib component_name COMPONENT_LIB)
|
||||
target_compile_options(${lib} PRIVATE "-fsanitize=undefined" "-fno-sanitize=shift-base")
|
||||
|
||||
.. note:: See the build system documentation for more information about :ref:`build properties<cmake-build-properties>` and :ref:`component properties<cmake-component-properties>`.
|
||||
.. note::
|
||||
|
||||
See the build system documentation for more information about :ref:`build properties <cmake-build-properties>` and :ref:`component properties <cmake-component-properties>`.
|
||||
|
||||
To enable UBSAN for a specific component (``component_name``) from ``CMakeLists.txt`` of the same component, add the following at the end of the file::
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ Term Definition
|
|||
**SDR** Single Data Rate
|
||||
**DDR** Double Data Rate
|
||||
**line mode** Number of signals used to transfer data in the data phase of SPI transactions. e.g., for 4-bit-mode, the speed of the data phase would be 4 bit per clock cycle.
|
||||
**FxRx** F stands for Flash, R stands for PSRAM, x stands for line mode. e.g. F4R4 stands for an {IDF_TARGET_NAME} with Quad Flash and Quad PSRAM
|
||||
**FxRx** F stands for Flash, R stands for PSRAM, x stands for line mode. e.g., F4R4 stands for an {IDF_TARGET_NAME} with Quad Flash and Quad PSRAM
|
||||
============= ===========================
|
||||
|
||||
.. note::
|
||||
|
@ -24,7 +24,7 @@ Term Definition
|
|||
|
||||
.. _flash-psram-configuration:
|
||||
|
||||
How to configure Flash and PSRAM
|
||||
How to Configure Flash and PSRAM
|
||||
--------------------------------
|
||||
|
||||
``idf.py menuconfig`` is used to open the configuration menu.
|
||||
|
@ -72,7 +72,7 @@ All Supported Modes and Speeds
|
|||
|
||||
.. note::
|
||||
|
||||
For MSPI DDR mode, the data are sampled on both the positive edge and the negative edge. e.g.: if a Flash is set to 80 MHz and DDR mode, then the final speed of the Flash is 160 MHz. This is faster than the Flash setting to 120 Mhz and STR mode.
|
||||
For MSPI DDR mode, the data are sampled on both the positive edge and the negative edge. e.g., if a Flash is set to 80 MHz and DDR mode, then the final speed of the Flash is 160 MHz. This is faster than the Flash setting to 120 Mhz and STR mode.
|
||||
|
||||
.. important::
|
||||
|
||||
|
@ -84,7 +84,7 @@ All Supported Modes and Speeds
|
|||
|
||||
Risks:
|
||||
|
||||
If your chip powers on at a certain temperature, then after the temperature increases or decreases over 20 celsius degree, the accesses to / from PSRAM / Flash will crash randomly. Flash access crash will lead to program crash.
|
||||
If your chip powers on at a certain temperature, then after the temperature increases or decreases over 20 celsius degree, the accesses to/from PSRAM/Flash will crash randomly. Flash access crash will lead to program crash.
|
||||
|
||||
Note 20 celsius degree is not a totally correct number. This value may changes among chips.
|
||||
|
||||
|
@ -113,9 +113,9 @@ F4R8 Hardware
|
|||
======= =============== ======= ============
|
||||
Group Flash mode Group PSRAM mode
|
||||
======= =============== ======= ============
|
||||
A 120 MHz SDR A 120MHz DDR
|
||||
B 80 MHz SDR B 80MHz DDR
|
||||
C 40 MHz SDR C 40MHz DDR
|
||||
A 120 MHz SDR A 120 MHz DDR
|
||||
B 80 MHz SDR B 80 MHz DDR
|
||||
C 40 MHz SDR C 40 MHz DDR
|
||||
C 20 MHz SDR C
|
||||
D D disable
|
||||
======= =============== ======= ============
|
||||
|
@ -130,9 +130,9 @@ F4R4 Hardware
|
|||
====== =============== ====== ============
|
||||
Type Flash Type PSRAM
|
||||
====== =============== ====== ============
|
||||
A 120 MHz A 120MHz
|
||||
B 80 MHz B 80MHz
|
||||
C 40 MHz C 40MHz
|
||||
A 120 MHz A 120 MHz
|
||||
B 80 MHz B 80 MHz
|
||||
C 40 MHz C 40 MHz
|
||||
C 20 MHz C
|
||||
D D disable
|
||||
====== =============== ====== ============
|
||||
|
@ -144,7 +144,7 @@ F4R4 Hardware
|
|||
|
||||
.. _flash-psram-error:
|
||||
|
||||
Error handling
|
||||
Error Handling
|
||||
--------------
|
||||
|
||||
1. If a board with Octal Flash resets before the second-stage bootloader:
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
***************************************
|
||||
Building OpenOCD from Sources for Linux
|
||||
***************************************
|
||||
|
||||
:link_to_translation:`zh_CN:[中文]`
|
||||
|
||||
The following instructions are alternative to downloading binary OpenOCD from `Espressif GitHub <https://github.com/espressif/openocd-esp32/releases>`_. To quickly setup the binary OpenOCD, instead of compiling it yourself, backup and proceed to section :ref:`jtag-debugging-setup-openocd`.
|
||||
|
||||
|
||||
.. highlight:: bash
|
||||
.. code-block:: bash
|
||||
|
||||
Download Sources of OpenOCD
|
||||
===========================
|
||||
|
@ -57,7 +58,7 @@ Proceed with configuring and building OpenOCD::
|
|||
./configure
|
||||
make
|
||||
|
||||
Optionally you can add ``sudo make install`` step at the end. Skip it, if you have an existing OpenOCD (from e.g. another development platform), as it may get overwritten.
|
||||
Optionally you can add ``sudo make install`` step at the end. Skip it, if you have an existing OpenOCD (from e.g., another development platform), as it may get overwritten.
|
||||
|
||||
.. note::
|
||||
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
***************************************
|
||||
Building OpenOCD from Sources for MacOS
|
||||
***************************************
|
||||
|
||||
:link_to_translation:`zh_CN:[中文]`
|
||||
|
||||
The following instructions are alternative to downloading binary OpenOCD from `Espressif GitHub <https://github.com/espressif/openocd-esp32/releases>`_. To quickly setup the binary OpenOCD, instead of compiling it yourself, backup and proceed to section :ref:`jtag-debugging-setup-openocd`.
|
||||
|
||||
.. highlight:: bash
|
||||
.. code-block:: bash
|
||||
|
||||
Download Sources of OpenOCD
|
||||
===========================
|
||||
|
@ -36,7 +37,7 @@ Proceed with configuring and building OpenOCD::
|
|||
./configure
|
||||
make
|
||||
|
||||
Optionally you can add ``sudo make install`` step at the end. Skip it, if you have an existing OpenOCD (from e.g. another development platform), as it may get overwritten.
|
||||
Optionally you can add ``sudo make install`` step at the end. Skip it, if you have an existing OpenOCD (from e.g., another development platform), as it may get overwritten.
|
||||
|
||||
.. note::
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
*****************************************
|
||||
Building OpenOCD from Sources for Windows
|
||||
*****************************************
|
||||
|
||||
:link_to_translation:`zh_CN:[中文]`
|
||||
|
||||
.. note::
|
||||
|
@ -80,7 +81,7 @@ Once the build is completed, the OpenOCD binary will be placed in ``~/esp/openoc
|
|||
You can then optionally call ``make install``. This will copy the OpenOCD binary to a user specified location.
|
||||
|
||||
- This location can be specified when OpenOCD is configured, or by setting ``export DESTDIR="/custom/install/dir"`` before calling ``make install``.
|
||||
- If you have an existing OpenOCD (from e.g. another development platform), you may want to skip this call as your existing OpenOCD may get overwritten.
|
||||
- If you have an existing OpenOCD (from e.g., another development platform), you may want to skip this call as your existing OpenOCD may get overwritten.
|
||||
|
||||
.. note::
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
:end-before: ---
|
||||
|
||||
|
||||
Configure {IDF_TARGET_NAME} built-in JTAG Interface
|
||||
Configure {IDF_TARGET_NAME} Built-in JTAG Interface
|
||||
===================================================
|
||||
|
||||
{IDF_TARGET_JTAG_PIN_Dneg:default="Not Updated!", esp32c3="GPIO18", esp32c6="GPIO12", esp32s3="GPIO19", esp32h2="GPIO26"}
|
||||
|
@ -34,7 +34,7 @@ Please verify that the {IDF_TARGET_NAME} pins used for USB communication are not
|
|||
Configure USB Drivers
|
||||
^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
JTAG communication should work on all supported platforms. Windows users might get `LIBUSB_ERROR_NOT_FOUND` errors. Please use version 2.8 (or newer) of the :ref:`get-started-windows-tools-installer` and select the driver "Espressif - WinUSB support for JTAG (ESP32-C3/S3)" in order to resolve this issue. If you don't want to re-run the installer then the same can be achieved with `idf-env <https://github.com/espressif/idf-env>`_ by running the following command from PowerShell::
|
||||
JTAG communication should work on all supported platforms. Windows users might get `LIBUSB_ERROR_NOT_FOUND` errors. Please use version 2.8 (or newer) of the :ref:`get-started-windows-tools-installer` and select the driver "Espressif - WinUSB support for JTAG (ESP32-C3/S3)" in order to resolve this issue. If you do not want to re-run the installer then the same can be achieved with `idf-env <https://github.com/espressif/idf-env>`_ by running the following command from PowerShell::
|
||||
|
||||
Invoke-WebRequest 'https://dl.espressif.com/dl/idf-env/idf-env.exe' -OutFile .\idf-env.exe; .\idf-env.exe driver install --espressif
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
Configure |devkit-name| JTAG Interface
|
||||
======================================
|
||||
|
||||
:link_to_translation:`zh_CN:[中文]`
|
||||
|
||||
All versions of |devkit-name| boards have built-in JTAG functionality. Putting it to work requires setting jumpers or DIP switches to enable JTAG functionality, and configuring USB drivers. Please refer to step by step instructions below.
|
||||
|
@ -32,7 +33,7 @@ Install and configure USB drivers, so OpenOCD is able to communicate with JTAG i
|
|||
Windows
|
||||
"""""""
|
||||
|
||||
1. Using standard USB A / micro USB B cable connect |devkit-name| to the computer. Switch the |devkit-name| on.
|
||||
1. Using standard USB A/micro USB B cable connect |devkit-name| to the computer. Switch the |devkit-name| on.
|
||||
|
||||
2. Wait until USB ports of |devkit-name| are recognized by Windows and drives are installed. If they do not install automatically, then download them from https://ftdichip.com/drivers/d2xx-drivers/ and install manually.
|
||||
|
||||
|
@ -61,7 +62,7 @@ Now |devkit-name|'s JTAG interface should be available to the OpenOCD. To carry
|
|||
Linux
|
||||
"""""
|
||||
|
||||
1. Using standard USB A / micro USB B cable connect |devkit-name| board to the computer. Power on the board.
|
||||
1. Using standard USB A/micro USB B cable connect |devkit-name| board to the computer. Power on the board.
|
||||
|
||||
.. highlight:: none
|
||||
|
||||
|
@ -98,7 +99,7 @@ On macOS, using FT2232 for JTAG and serial port at the same time needs some addi
|
|||
|
||||
1. Manually unload the FTDI serial port driver before starting OpenOCD, start OpenOCD, then load the serial port driver.
|
||||
|
||||
2. Modify FTDI driver configuration so that it doesn't load itself for channel A of FT2232 chip, which is the channel used for JTAG on |devkit-name|.
|
||||
2. Modify FTDI driver configuration so that it does not load itself for channel A of FT2232 chip, which is the channel used for JTAG on |devkit-name|.
|
||||
|
||||
Manually unloading the driver
|
||||
.............................
|
||||
|
@ -146,9 +147,13 @@ Modifying FTDI driver
|
|||
|
||||
In a nutshell, this approach requires modification to FTDI driver configuration file, which prevents the driver from being loaded for channel B of FT2232H.
|
||||
|
||||
.. note:: Other boards may use channel A for JTAG, so use this option with caution.
|
||||
.. note::
|
||||
|
||||
.. warning:: This approach also needs signature verification of drivers to be disabled, so may not be acceptable for all users.
|
||||
Other boards may use channel A for JTAG, so use this option with caution.
|
||||
|
||||
.. warning::
|
||||
|
||||
This approach also needs signature verification of drivers to be disabled, so may not be acceptable for all users.
|
||||
|
||||
|
||||
1. Open FTDI driver configuration file using a text editor (note ``sudo``)::
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
Configure Other JTAG Interfaces
|
||||
===============================
|
||||
|
||||
:link_to_translation:`zh_CN:[中文]`
|
||||
|
||||
{IDF_TARGET_JTAG_SEL_EFUSE:default="Not Updated!", esp32s3="STRAP_JTAG_SEL", esp32c6="JTAG_SEL_ENABLE", esp32h2="JTAG_SEL_ENABLE"}
|
||||
|
|
|
@ -1,17 +1,19 @@
|
|||
Debugging Examples
|
||||
==================
|
||||
|
||||
:link_to_translation:`zh_CN:[中文]`
|
||||
|
||||
This section describes debugging with GDB from :ref:`jtag-debugging-examples-eclipse` as well as from :ref:`jtag-debugging-examples-command-line`.
|
||||
|
||||
.. highlight:: none
|
||||
.. code-block:: none
|
||||
|
||||
|
||||
.. _jtag-debugging-examples-eclipse:
|
||||
|
||||
Eclipse
|
||||
-------
|
||||
|
||||
Verify if your target is ready and loaded with :example:`get-started/blink` example. Configure and start debugger following steps in section :ref:`jtag-debugging-using-debugger-eclipse`. Pick up where target was left by debugger, i.e. having the application halted at breakpoint established at ``app_main()``.
|
||||
Verify if your target is ready and loaded with :example:`get-started/blink` example. Configure and start debugger following steps in section :ref:`jtag-debugging-using-debugger-eclipse`. Pick up where target was left by debugger, i.e., having the application halted at breakpoint established at ``app_main()``.
|
||||
|
||||
.. figure:: ../../../_static/debug-perspective.jpg
|
||||
:align: center
|
||||
|
@ -21,7 +23,7 @@ Verify if your target is ready and loaded with :example:`get-started/blink` exam
|
|||
Debug Perspective in Eclipse
|
||||
|
||||
|
||||
Examples in this section
|
||||
Examples in This Section
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
1. :ref:`jtag-debugging-examples-eclipse-01`
|
||||
|
@ -35,7 +37,7 @@ Examples in this section
|
|||
|
||||
.. _jtag-debugging-examples-eclipse-01:
|
||||
|
||||
Navigating through the code, call stack and threads
|
||||
Navigating Through the Code, Call Stack and Threads
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
When the target is halted, debugger shows the list of threads in "Debug" window. The line of code where program halted is highlighted in another window below, as shown on the following picture. The LED stops blinking.
|
||||
|
@ -47,7 +49,7 @@ When the target is halted, debugger shows the list of threads in "Debug" window.
|
|||
|
||||
Target halted during debugging
|
||||
|
||||
Specific thread where the program halted is expanded showing the call stack. It represents function calls that lead up to the highlighted line of code, where the target halted. The first line of call stack under Thread #1 contains the last called function ``app_main()``, that in turn was called from function ``main_task()`` shown in a line below. Each line of the stack also contains the file name and line number where the function was called. By clicking / highlighting the stack entries, in window below, you will see contents of this file.
|
||||
Specific thread where the program halted is expanded showing the call stack. It represents function calls that lead up to the highlighted line of code, where the target halted. The first line of call stack under Thread #1 contains the last called function ``app_main()``, that in turn was called from function ``main_task()`` shown in a line below. Each line of the stack also contains the file name and line number where the function was called. By clicking/highlighting the stack entries, in window below, you will see contents of this file.
|
||||
|
||||
By expanding threads you can navigate throughout the application. Expand Thread #5 that contains much longer call stack. You will see there, besides function calls, numbers like ``0x4000000c``. They represent addresses of binary code not provided in source form.
|
||||
|
||||
|
@ -65,10 +67,10 @@ Go back to the ``app_main()`` in Thread #1 to familiar code of ``blink.c`` file
|
|||
|
||||
.. _jtag-debugging-examples-eclipse-02:
|
||||
|
||||
Setting and clearing breakpoints
|
||||
Setting and Clearing Breakpoints
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
When debugging, we would like to be able to stop the application at critical lines of code and then examine the state of specific variables, memory and registers / peripherals. To do so we are using breakpoints. They provide a convenient way to quickly get to and halt the application at specific line.
|
||||
When debugging, we would like to be able to stop the application at critical lines of code and then examine the state of specific variables, memory and registers/peripherals. To do so we are using breakpoints. They provide a convenient way to quickly get to and halt the application at specific line.
|
||||
|
||||
Let's establish two breakpoints when the state of LED changes. Basing on code listing above, this happens at lines 33 and 36. To do so, hold the "Control" on the keyboard and double clink on number ``33`` in file ``blink.c`` file. A dialog will open where you can confirm your selection by pressing "OK" button. If you do not like to see the dialog just double click the line number. Set another breakpoint in line 36.
|
||||
|
||||
|
@ -97,7 +99,7 @@ Read more about breakpoints under :ref:`jtag-debugging-tip-breakpoints` and :ref
|
|||
|
||||
.. _jtag-debugging-examples-eclipse-03:
|
||||
|
||||
Halting the target manually
|
||||
Halting the Target Manually
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
When debugging, you may resume application and enter code waiting for some event or staying in infinite loop without any break points defined. In such case, to go back to debugging mode, you can break program execution manually by pressing "Suspend" button.
|
||||
|
@ -116,7 +118,7 @@ In particular case above, the application has been halted in line 52 of code in
|
|||
|
||||
.. _jtag-debugging-examples-eclipse-04:
|
||||
|
||||
Stepping through the code
|
||||
Stepping Through the Code
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
It is also possible to step through the code using "Step Into (F5)" and "Step Over (F6)" commands. The difference is that "Step Into (F5)" is entering inside subroutines calls, while "Step Over (F6)" steps over the call, treating it as a single source line.
|
||||
|
@ -148,7 +150,7 @@ See :ref:`jtag-debugging-tip-why-next-works-as-step` for potential limitation of
|
|||
|
||||
.. _jtag-debugging-examples-eclipse-05:
|
||||
|
||||
Checking and setting memory
|
||||
Checking and Setting Memory
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
To display or set contents of memory use "Memory" tab at the bottom of "Debug" perspective.
|
||||
|
@ -179,9 +181,10 @@ You should see one bit being flipped over at memory location ``0x3FF44004`` (and
|
|||
|
||||
To set memory use the same "Monitor" tab and the same memory location. Type in alternate bit pattern as previously observed. Immediately after pressing enter you will see LED changing the state.
|
||||
|
||||
|
||||
.. _jtag-debugging-examples-eclipse-06:
|
||||
|
||||
Watching and setting program variables
|
||||
Watching and Setting Program Variables
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
A common debugging tasks is checking the value of a program variable as the program runs. To be able to demonstrate this functionality, update file ``blink.c`` by adding a declaration of a global variable ``int i`` above definition of function ``blink_task``. Then add ``i++`` inside ``while(1)`` of this function to get ``i`` incremented on each blink.
|
||||
|
@ -207,7 +210,7 @@ To modify ``i`` enter a new number in "Value" column. After pressing "Resume (F8
|
|||
|
||||
.. _jtag-debugging-examples-eclipse-07:
|
||||
|
||||
Setting conditional breakpoints
|
||||
Setting Conditional Breakpoints
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Here comes more interesting part. You may set a breakpoint to halt the program execution, if certain condition is satisfied. Right click on the breakpoint to open a context menu and select "Breakpoint Properties". Change the selection under "Type:" to "Hardware" and enter a "Condition:" like ``i == 2``.
|
||||
|
@ -234,8 +237,7 @@ Verify if your target is ready and loaded with :example:`get-started/blink` exam
|
|||
(gdb)
|
||||
|
||||
|
||||
|
||||
Examples in this section
|
||||
Examples in This Section
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
1. :ref:`jtag-debugging-examples-command-line-01`
|
||||
|
@ -250,7 +252,7 @@ Examples in this section
|
|||
|
||||
.. _jtag-debugging-examples-command-line-01:
|
||||
|
||||
Navigating through the code, call stack and threads
|
||||
Navigating Through the Code, Call Stack and Threads
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
When you see the ``(gdb)`` prompt, the application is halted. LED should not be blinking.
|
||||
|
@ -268,7 +270,7 @@ To find out where exactly the code is halted, enter ``l`` or ``list``, and debug
|
|||
(gdb)
|
||||
|
||||
|
||||
Check how code listing works by entering, e.g. ``l 30, 40`` to see particular range of lines of code.
|
||||
Check how code listing works by entering, e.g., ``l 30, 40`` to see particular range of lines of code.
|
||||
|
||||
You can use ``bt`` or ``backtrace`` to see what function calls lead up to this code::
|
||||
|
||||
|
@ -277,7 +279,7 @@ You can use ``bt`` or ``backtrace`` to see what function calls lead up to this c
|
|||
#1 0x400d057e in main_task (args=0x0) at /home/user-name/esp/esp-idf/components/{IDF_TARGET_PATH_NAME}/./cpu_start.c:339
|
||||
(gdb)
|
||||
|
||||
Line #0 of output provides the last function call before the application halted, i.e. ``app_main ()`` we have listed previously. The ``app_main ()`` was in turn called by function ``main_task`` from line 339 of code located in file ``cpu_start.c``.
|
||||
Line #0 of output provides the last function call before the application halted, i.e., ``app_main ()`` we have listed previously. The ``app_main ()`` was in turn called by function ``main_task`` from line 339 of code located in file ``cpu_start.c``.
|
||||
|
||||
To get to the context of ``main_task`` in file ``cpu_start.c``, enter ``frame N``, where N = 1, because the ``main_task`` is listed under #1)::
|
||||
|
||||
|
@ -371,10 +373,10 @@ Using ``bt``, ``i threads``, ``thread N`` and ``list`` commands we are now able
|
|||
|
||||
.. _jtag-debugging-examples-command-line-02:
|
||||
|
||||
Setting and clearing breakpoints
|
||||
Setting and Clearing Breakpoints
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
When debugging, we would like to be able to stop the application at critical lines of code and then examine the state of specific variables, memory and registers / peripherals. To do so we are using breakpoints. They provide a convenient way to quickly get to and halt the application at specific line.
|
||||
When debugging, we would like to be able to stop the application at critical lines of code and then examine the state of specific variables, memory and registers/peripherals. To do so we are using breakpoints. They provide a convenient way to quickly get to and halt the application at specific line.
|
||||
|
||||
Let's establish two breakpoints when the state of LED changes. Basing on code listing above this happens at lines 33 and 36. Breakpoints may be established using command ``break M`` where M is the code line number::
|
||||
|
||||
|
@ -426,7 +428,7 @@ Read more about breakpoints under :ref:`jtag-debugging-tip-breakpoints` and :ref
|
|||
|
||||
.. _jtag-debugging-examples-command-line-03:
|
||||
|
||||
Halting and resuming the application
|
||||
Halting and Resuming the Application
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
When debugging, you may resume application and enter code waiting for some event or staying in infinite loop without any break points defined. In such case, to go back to debugging mode, you can break program execution manually by entering Ctrl+C.
|
||||
|
@ -449,7 +451,7 @@ In particular case above, the application has been halted in line 52 of code in
|
|||
|
||||
.. _jtag-debugging-examples-command-line-04:
|
||||
|
||||
Stepping through the code
|
||||
Stepping Through the Code
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
It is also possible to step through the code using ``step`` and ``next`` commands (in short ``s`` and ``n``). The difference is that ``step`` is entering inside subroutines calls, while ``next`` steps over the call, treating it as a single source line.
|
||||
|
@ -506,7 +508,7 @@ See :ref:`jtag-debugging-tip-why-next-works-as-step` for potential limitation of
|
|||
|
||||
.. _jtag-debugging-examples-command-line-05:
|
||||
|
||||
Checking and setting memory
|
||||
Checking and Setting Memory
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Displaying the contents of memory is done with command ``x``. With additional parameters you may vary the format and count of memory locations displayed. Run ``help x`` to see more details. Companion command to ``x`` is ``set`` that let you write values to the memory.
|
||||
|
@ -554,7 +556,7 @@ You should see the LED to turn on immediately after entering ``set {unsigned int
|
|||
|
||||
.. _jtag-debugging-examples-command-line-06:
|
||||
|
||||
Watching and setting program variables
|
||||
Watching and Setting Program Variables
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
A common debugging tasks is checking the value of a program variable as the program runs. To be able to demonstrate this functionality, update file ``blink.c`` by adding a declaration of a global variable ``int i`` above definition of function ``blink_task``. Then add ``i++`` inside ``while(1)`` of this function to get ``i`` incremented on each blink.
|
||||
|
@ -598,7 +600,7 @@ You may have up to two watchpoints, see :ref:`jtag-debugging-tip-breakpoints`.
|
|||
|
||||
.. _jtag-debugging-examples-command-line-07:
|
||||
|
||||
Setting conditional breakpoints
|
||||
Setting Conditional Breakpoints
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Here comes more interesting part. You may set a breakpoint to halt the program execution, if certain condition is satisfied. Delete existing breakpoints and try this::
|
||||
|
@ -630,6 +632,7 @@ Debugging FreeRTOS Objects
|
|||
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
This part might be interesting when you are debugging FreeRTOS tasks interactions.
|
||||
|
||||
Users that need to use the FreeRTOS task interactions can use the GDB ``freertos`` command. The ``freertos`` command is not native to GDB and comes from the `freertos-gdb <https://pypi.org/project/freertos-gdb>`_ Python extension module. The ``freertos`` command contains a series of sub-commands as demonstrated in the code snippet::
|
||||
|
||||
(gdb) freertos
|
||||
|
@ -652,7 +655,7 @@ For a more detailed description of this extension, please refer to https://pypi.
|
|||
Users only need to have Python 3.6 (or above) that contains a Python shared library.
|
||||
|
||||
|
||||
Obtaining help on commands
|
||||
Obtaining Help on Commands
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Commands presented so for should provide are very basis and intended to let you quickly get started with JTAG debugging. Check help what are the other commands at you disposal. To obtain help on syntax and functionality of particular command, being at ``(gdb)`` prompt type ``help`` and command name::
|
||||
|
@ -668,7 +671,7 @@ Commands presented so for should provide are very basis and intended to let you
|
|||
By typing just ``help``, you will get top level list of command classes, to aid you drilling down to more details. Optionally refer to available GDB cheat sheets, for instance https://darkdust.net/files/GDB%20Cheat%20Sheet.pdf. Good to have as a reference (even if not all commands are applicable in an embedded environment).
|
||||
|
||||
|
||||
Ending debugger session
|
||||
Ending Debugger Session
|
||||
^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
To quit debugger enter ``q``::
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
JTAG Debugging
|
||||
==============
|
||||
|
||||
:link_to_translation:`zh_CN:[中文]`
|
||||
|
||||
This document provides a guide to installing OpenOCD for {IDF_TARGET_NAME} and debugging using GDB. The document is structured as follows:
|
||||
|
@ -40,13 +41,13 @@ Introduction
|
|||
|
||||
The downside of the ease of programming is that debugging without the right tools is harder: figuring out a bug that is caused by two threads, running even simultaneously on two different CPU cores, can take a long time when all you have are ``printf()`` statements. A better (and in many cases quicker) way to debug such problems is by using a debugger, connected to the processors over a debug port.
|
||||
|
||||
Espressif has ported OpenOCD to support the {IDF_TARGET_NAME} processor and the multi-core FreeRTOS (which is the foundation of most {IDF_TARGET_NAME} apps). Additionally, some extra tools have been written to provide extra features that OpenOCD does not support natively.
|
||||
Espressif has ported OpenOCD to support the {IDF_TARGET_NAME} processor and the multi-core FreeRTOS (which is the foundation of most {IDF_TARGET_NAME} apps). Additionally, some extra tools have been written to provide extra features that OpenOCD does not support natively.
|
||||
|
||||
This document provides a guide to installing OpenOCD for {IDF_TARGET_NAME} and debugging using GDB under Linux, Windows and macOS. Except for OS specific installation procedures, the s/w user interface and use procedures are the same across all supported operating systems.
|
||||
|
||||
.. note::
|
||||
|
||||
Screenshots presented in this document have been made for Eclipse Neon 3 running on Ubuntu 16.04 LTS. There may be some small differences in what a particular user interface looks like, depending on whether you are using Windows, macOS or Linux and / or a different release of Eclipse.
|
||||
Screenshots presented in this document have been made for Eclipse Neon 3 running on Ubuntu 16.04 LTS. There may be some small differences in what a particular user interface looks like, depending on whether you are using Windows, macOS or Linux and/or a different release of Eclipse.
|
||||
|
||||
.. _jtag-debugging-how-it-works:
|
||||
|
||||
|
@ -78,7 +79,7 @@ Likewise, the "Application Loading and Monitoring" label indicates the key softw
|
|||
|
||||
.. note::
|
||||
|
||||
Debugging through the USB interface implemented in {IDF_TARGET_NAME} requires to have a chip with revision 0.3 or newer. Please use other debugging options (e.g. with ESP-Prog) for chip revisions 0.1 and 0.2. The easiest way to determine the chip revision is to look for the ``boot: chip revision: v0.3`` message at the beginning of the boot log. See `SoC errata <https://www.espressif.com/sites/default/files/documentation/esp32-c3_errata_en.pdf>`_ for more details.
|
||||
Debugging through the USB interface implemented in {IDF_TARGET_NAME} requires to have a chip with revision 0.3 or newer. Please use other debugging options (e.g., with ESP-Prog) for chip revisions 0.1 and 0.2. The easiest way to determine the chip revision is to look for the ``boot: chip revision: v0.3`` message at the beginning of the boot log. See `SoC errata <https://www.espressif.com/sites/default/files/documentation/esp32-c3_errata_en.pdf>`_ for more details.
|
||||
|
||||
.. _jtag-debugging-selecting-jtag-adapter:
|
||||
|
||||
|
@ -87,17 +88,17 @@ Selecting JTAG Adapter
|
|||
|
||||
.. only:: esp32 or esp32s2
|
||||
|
||||
The quickest and most convenient way to start with JTAG debugging is by using |devkit-name-with-link|. Each version of this development board has JTAG interface already built in. No need for an external JTAG adapter and extra wiring / cable to connect JTAG to {IDF_TARGET_NAME}. |devkit-name| is using FT2232H JTAG interface operating at 20 MHz clock speed, which is difficult to achieve with an external adapter.
|
||||
The quickest and most convenient way to start with JTAG debugging is by using |devkit-name-with-link|. Each version of this development board has JTAG interface already built in. No need for an external JTAG adapter and extra wiring/cable to connect JTAG to {IDF_TARGET_NAME}. |devkit-name| is using FT2232H JTAG interface operating at 20 MHz clock speed, which is difficult to achieve with an external adapter.
|
||||
|
||||
.. only:: SOC_USB_SERIAL_JTAG_SUPPORTED
|
||||
|
||||
The quickest and most convenient way to start with JTAG debugging is through a USB cable connected to the D+/D- USB pins of {IDF_TARGET_NAME}. No need for an external JTAG adapter and extra wiring / cable to connect JTAG to {IDF_TARGET_NAME}.
|
||||
The quickest and most convenient way to start with JTAG debugging is through a USB cable connected to the D+/D- USB pins of {IDF_TARGET_NAME}. No need for an external JTAG adapter and extra wiring/cable to connect JTAG to {IDF_TARGET_NAME}.
|
||||
|
||||
If you decide to use separate JTAG adapter, look for one that is compatible with both the voltage levels on the {IDF_TARGET_NAME} as well as with the OpenOCD software. The JTAG port on the {IDF_TARGET_NAME} is an industry-standard JTAG port which lacks (and does not need) the TRST pin. The JTAG I/O pins all are powered from the VDD_3P3_RTC pin (which normally would be powered by a 3.3 V rail) so the JTAG adapter needs to be able to work with JTAG pins in that voltage range.
|
||||
|
||||
On the software side, OpenOCD supports a fair amount of JTAG adapters. See https://openocd.org/doc/html/Debug-Adapter-Hardware.html for an (unfortunately slightly incomplete) list of the adapters OpenOCD works with. This page lists SWD-compatible adapters as well; take note that the {IDF_TARGET_NAME} does not support SWD. JTAG adapters that are hardcoded to a specific product line, e.g. ST-LINK debugging adapters for STM32 families, will not work.
|
||||
On the software side, OpenOCD supports a fair amount of JTAG adapters. See https://openocd.org/doc/html/Debug-Adapter-Hardware.html for an (unfortunately slightly incomplete) list of the adapters OpenOCD works with. This page lists SWD-compatible adapters as well; take note that the {IDF_TARGET_NAME} does not support SWD. JTAG adapters that are hardcoded to a specific product line, e.g., ST-LINK debugging adapters for STM32 families, will not work.
|
||||
|
||||
The minimal signalling to get a working JTAG connection are TDI, TDO, TCK, TMS and GND. Some JTAG debuggers also need a connection from the {IDF_TARGET_NAME} power line to a line called e.g. Vtar to set the working voltage. SRST can optionally be connected to the CH_PD of the {IDF_TARGET_NAME}, although for now, support in OpenOCD for that line is pretty minimal.
|
||||
The minimal signalling to get a working JTAG connection are TDI, TDO, TCK, TMS and GND. Some JTAG debuggers also need a connection from the {IDF_TARGET_NAME} power line to a line called e.g., Vtar to set the working voltage. SRST can optionally be connected to the CH_PD of the {IDF_TARGET_NAME}, although for now, support in OpenOCD for that line is pretty minimal.
|
||||
|
||||
`ESP-Prog <https://docs.espressif.com/projects/espressif-esp-iot-solution/en/latest/hw-reference/ESP-Prog_guide.html>`_ is an example for using an external board for debugging by connecting it to the JTAG pins of {IDF_TARGET_NAME}.
|
||||
|
||||
|
@ -142,7 +143,7 @@ Once OpenOCD is installed, you can proceed to configuring the {IDF_TARGET_NAME}
|
|||
|
||||
.. _jtag-debugging-configure-and-connect-JTAG-interface:
|
||||
|
||||
Configure and connect JTAG interface
|
||||
Configure and Connect JTAG Interface
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
This step depends on the JTAG and {IDF_TARGET_NAME} board you are using (see the two cases described below).
|
||||
|
@ -190,12 +191,12 @@ You should now see similar output (this log is for |run-openocd-device-name|):
|
|||
:end-before: ---
|
||||
|
||||
* If there is an error indicating permission problems, please see section on "Permissions delegation" in the OpenOCD README file located in the ``~/esp/openocd-esp32`` directory.
|
||||
* In case there is an error in finding the configuration files, e.g. |run-openocd-cfg-file-err|, check if the ``OPENOCD_SCRIPTS`` environment variable is set correctly. This variable is used by OpenOCD to look for the files specified after the ``-f`` option. See :ref:`jtag-debugging-setup-openocd` section for details. Also check if the file is indeed under the provided path.
|
||||
* In case there is an error in finding the configuration files, e.g., |run-openocd-cfg-file-err|, check if the ``OPENOCD_SCRIPTS`` environment variable is set correctly. This variable is used by OpenOCD to look for the files specified after the ``-f`` option. See :ref:`jtag-debugging-setup-openocd` section for details. Also check if the file is indeed under the provided path.
|
||||
* If you see JTAG errors (e.g., ``...all ones`` or ``...all zeroes``), please check your JTAG connections, whether other signals are connected to JTAG besides {IDF_TARGET_NAME}'s pins, and see if everything is powered on correctly.
|
||||
|
||||
.. _jtag-upload-app-debug:
|
||||
|
||||
Upload application for debugging
|
||||
Upload Application for Debugging
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Build and upload your application to {IDF_TARGET_NAME} as usual, see :ref:`get-started-build`.
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
Tips and Quirks
|
||||
---------------
|
||||
|
||||
:link_to_translation:`zh_CN:[中文]`
|
||||
|
||||
This section provides collection of all tips and quirks referred to from various parts of this guide.
|
||||
|
@ -25,7 +26,7 @@ Emulating part of hardware breakpoints using software flash ones means that the
|
|||
Flash Mappings vs SW Flash Breakpoints
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
In order to set/clear software breakpoints in flash, OpenOCD needs to know their flash addresses. To accomplish conversion from the {IDF_TARGET_NAME} address space to the flash one, OpenOCD uses mappings of program's code regions resided in flash. Those mappings are kept in the image header which is prepended to program binary data (code and data segments) and is specific to every application image written to the flash. So to support software flash breakpoints OpenOCD should know where application image under debugging is resided in the flash. By default OpenOCD reads partition table at 0x8000 and uses mappings from the first found application image, but there can be the cases when it will not work, e.g. partition table is not at standard flash location or even there can be multiple images: one factory and two OTA and you may want to debbug any of them. To cover all possible debugging scenarios OpenOCD supports special command which can be used to set arbitrary location of application image to debug. The command has the following format:
|
||||
In order to set/clear software breakpoints in flash, OpenOCD needs to know their flash addresses. To accomplish conversion from the {IDF_TARGET_NAME} address space to the flash one, OpenOCD uses mappings of program's code regions resided in flash. Those mappings are kept in the image header which is prepended to program binary data (code and data segments) and is specific to every application image written to the flash. So to support software flash breakpoints OpenOCD should know where application image under debugging is resided in the flash. By default OpenOCD reads partition table at 0x8000 and uses mappings from the first found application image, but there can be the cases when it will not work, e.g., partition table is not at standard flash location or even there can be multiple images: one factory and two OTA and you may want to debbug any of them. To cover all possible debugging scenarios OpenOCD supports special command which can be used to set arbitrary location of application image to debug. The command has the following format:
|
||||
|
||||
``esp appimage_offset <offset>``
|
||||
|
||||
|
@ -105,7 +106,7 @@ In order to achieve higher data rates and minimize number of dropped packets it
|
|||
|
||||
.. _jtag-debugging-tip-debugger-startup-commands:
|
||||
|
||||
What is the Meaning of Debugger's Startup Commands?
|
||||
What Is the Meaning of Debugger's Startup Commands?
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
On startup, debugger is issuing sequence of commands to reset the chip and halt it at specific line of code. This sequence (shown below) is user defined to pick up at most convenient/appropriate line and start debugging.
|
||||
|
@ -192,7 +193,7 @@ The board can be reset by entering ``mon reset`` or ``mon reset halt`` into GDB.
|
|||
|
||||
.. _jtag-debugging-tip-jtag-pins-reconfigured:
|
||||
|
||||
Can JTAG Pins be Used for Other Purposes?
|
||||
Can JTAG Pins Be Used for Other Purposes?
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. only:: SOC_USB_SERIAL_JTAG_SUPPORTED
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
Using Debugger
|
||||
--------------
|
||||
|
||||
:link_to_translation:`zh_CN:[中文]`
|
||||
|
||||
This section covers the steps to configure and run a debugger using various methods, including:
|
||||
|
@ -42,7 +43,7 @@ After installation is complete, follow these steps to configure the debugging se
|
|||
|
||||
1. In Eclipse, go to ``Run`` > ``Debug Configuration``. A new window will open. In the left pane of the window, double-click ``GDB Hardware Debugging`` (or select ``GDB Hardware Debugging`` and press the ``New`` button) to create a new configuration.
|
||||
|
||||
2. In a form that will show up on the right, enter the ``Name:`` of this configuration, e.g. "Blink checking".
|
||||
2. In a form that will show up on the right, enter the ``Name:`` of this configuration, e.g., "Blink checking".
|
||||
|
||||
3. On the ``Main`` tab below, under ``Project:``, press the ``Browse`` button and select the ``blink`` project.
|
||||
|
||||
|
@ -128,7 +129,7 @@ Command Line
|
|||
|
||||
.. highlight:: bash
|
||||
|
||||
2. Open a new terminal session and go to the directory that contains the project for debugging, e.g.
|
||||
2. Open a new terminal session and go to the directory that contains the project for debugging, e.g.,
|
||||
|
||||
::
|
||||
|
||||
|
@ -149,7 +150,7 @@ Command Line
|
|||
|
||||
Save this file in the current directory.
|
||||
|
||||
For more details on what's inside ``gdbinit`` file, see :ref:`jtag-debugging-tip-debugger-startup-commands`
|
||||
For more details on what is inside ``gdbinit`` file, see :ref:`jtag-debugging-tip-debugger-startup-commands`
|
||||
|
||||
.. highlight:: bash
|
||||
|
||||
|
@ -216,7 +217,7 @@ If you are not sure how to use GDB, check :ref:`jtag-debugging-examples-command-
|
|||
|
||||
.. _jtag-debugging-with-idf-py:
|
||||
|
||||
idf.py debug targets
|
||||
Idf.py Debug Targets
|
||||
^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
It is also possible to execute the described debugging tools conveniently from ``idf.py``. These commands are supported:
|
||||
|
@ -245,7 +246,7 @@ It is also possible to execute the described debugging tools conveniently from `
|
|||
|
||||
4. ``idf.py gdbgui``
|
||||
|
||||
Starts `gdbgui <https://www.gdbgui.com>`_ debugger frontend enabling out-of-the-box debugging in a browser window. To enable this option, run the install script with the "--enable-gdbgui" argument, e.g. ``install.sh --enable-gdbgui``.
|
||||
Starts `gdbgui <https://www.gdbgui.com>`_ debugger frontend enabling out-of-the-box debugging in a browser window. To enable this option, run the install script with the "--enable-gdbgui" argument, e.g., ``install.sh --enable-gdbgui``.
|
||||
|
||||
|
||||
You can combine these debugging actions on a single command line, allowing for convenient setup of blocking and non-blocking actions in one step. ``idf.py`` implements a simple logic to move the background actions (such as openocd) to the beginning and the interactive ones (such as gdb, monitor) to the end of the action list.
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
Linker Script Generation
|
||||
========================
|
||||
|
||||
:link_to_translation:`zh_CN:[中文]`
|
||||
|
||||
Overview
|
||||
--------
|
||||
|
||||
There are several :ref:`memory regions<memory-layout>` where code and data can be placed. Code and read-only data are placed by default in flash, writable data in RAM, etc. However, it is sometimes necessary to change these default placements.
|
||||
There are several :ref:`memory regions <memory-layout>` where code and data can be placed. Code and read-only data are placed by default in flash, writable data in RAM, etc. However, it is sometimes necessary to change these default placements.
|
||||
|
||||
For example, it may be necessary to place:
|
||||
|
||||
|
@ -56,7 +57,7 @@ In the component's ``CMakeLists.txt`` file, specify argument ``LDFRAGMENTS`` in
|
|||
)
|
||||
|
||||
|
||||
Specifying placements
|
||||
Specifying Placements
|
||||
^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
It is possible to specify placements at the following levels of granularity:
|
||||
|
@ -67,7 +68,7 @@ It is possible to specify placements at the following levels of granularity:
|
|||
|
||||
.. _ldgen-placing-object-files :
|
||||
|
||||
Placing object files
|
||||
Placing Object Files
|
||||
""""""""""""""""""""
|
||||
|
||||
Suppose the entirety of ``my_src1.o`` is performance-critical, so it is desirable to place it in RAM. On the other hand, the entirety of ``my_src2.o`` contains symbols needed coming out of deep sleep, so it needs to be put under RTC memory.
|
||||
|
@ -82,9 +83,9 @@ In the linker fragment file, we can write:
|
|||
my_src1 (noflash) # places all my_src1 code/read-only data under IRAM/DRAM
|
||||
my_src2 (rtc) # places all my_src2 code/ data and read-only data under RTC fast memory/RTC slow memory
|
||||
|
||||
What happens to ``my_src3.o``? Since it is not specified, default placements are used for ``my_src3.o``. More on default placements :ref:`here<ldgen-default-placements>`.
|
||||
What happens to ``my_src3.o``? Since it is not specified, default placements are used for ``my_src3.o``. More on default placements :ref:`here <ldgen-default-placements>`.
|
||||
|
||||
Placing symbols
|
||||
Placing Symbols
|
||||
""""""""""""""""
|
||||
|
||||
Continuing our example, suppose that among functions defined under ``object1.o``, only ``my_function1`` is performance-critical; and under ``object2.o``, only ``my_function2`` needs to execute after the chip comes out of deep sleep. This could be accomplished by writing:
|
||||
|
@ -105,7 +106,7 @@ The default placements are used for the rest of the functions in ``my_src1.o`` a
|
|||
|
||||
There are :ref:`limitations<ldgen-symbol-granularity-placements>` in placing code/data at symbol granularity. In order to ensure proper placements, an alternative would be to group relevant code and data into source files, and :ref:`use object-granularity placements<ldgen-placing-object-files>`.
|
||||
|
||||
Placing entire archive
|
||||
Placing Entire Archive
|
||||
"""""""""""""""""""""""
|
||||
|
||||
In this example, suppose that the entire component archive needs to be placed in RAM. This can be written as:
|
||||
|
@ -129,7 +130,7 @@ Similarly, this places the entire component in RTC memory:
|
|||
|
||||
.. _ldgen-conditional-placements:
|
||||
|
||||
Configuration-dependent placements
|
||||
Configuration-Dependent Placements
|
||||
""""""""""""""""""""""""""""""""""
|
||||
|
||||
Suppose that the entire component library should only have special placement when a certain condition is true; for example, when ``CONFIG_PERFORMANCE_MODE == y``. This could be written as:
|
||||
|
@ -182,14 +183,15 @@ Nesting condition-checking is also possible. The following is equivalent to the
|
|||
|
||||
.. _ldgen-default-placements:
|
||||
|
||||
The 'default' placements
|
||||
The 'default' Placements
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Up until this point, the term 'default placements' has been mentioned as fallback placements when the placement rules ``rtc`` and ``noflash`` are not specified. It is important to note that the tokens ``noflash`` or ``rtc`` are not merely keywords, but are actually entities called fragments, specifically :ref:`schemes<ldgen-scheme-fragment>`.
|
||||
Up until this point, the term 'default placements' has been mentioned as fallback placements when the placement rules ``rtc`` and ``noflash`` are not specified. It is important to note that the tokens ``noflash`` or ``rtc`` are not merely keywords, but are actually entities called fragments, specifically :ref:`schemes <ldgen-scheme-fragment>`.
|
||||
|
||||
In the same manner as ``rtc`` and ``noflash`` are schemes, there exists a ``default`` scheme which defines what the default placement rules should be. As the name suggests, it is where code and data are usually placed, i.e. code/constants is placed in flash, variables placed in RAM, etc. More on the default scheme :ref:`here<ldgen-default-scheme>`.
|
||||
In the same manner as ``rtc`` and ``noflash`` are schemes, there exists a ``default`` scheme which defines what the default placement rules should be. As the name suggests, it is where code and data are usually placed, i.e., code/constants is placed in flash, variables placed in RAM, etc. More on the default scheme :ref:`here <ldgen-default-scheme>`.
|
||||
|
||||
.. note::
|
||||
|
||||
For an example of an ESP-IDF component using the linker script generation mechanism, see :component_file:`freertos/CMakeLists.txt`. ``freertos`` uses this to place its object files to the instruction RAM for performance reasons.
|
||||
|
||||
This marks the end of the quick start guide. The following text discusses the internals of the mechanism in a little bit more detail. The following sections should be helpful in creating custom placements or modifying default behavior.
|
||||
|
@ -197,7 +199,7 @@ This marks the end of the quick start guide. The following text discusses the in
|
|||
Linker Script Generation Internals
|
||||
----------------------------------
|
||||
|
||||
Linking is the last step in the process of turning C/C++ source files into an executable. It is performed by the toolchain's linker, and accepts linker scripts which specify code/data placements, among other things. With the linker script generation mechanism, this process is no different, except that the linker script passed to the linker is dynamically generated from: (1) the collected :ref:`linker fragment files<ldgen-linker-fragment-files>` and (2) :ref:`linker script template<ldgen-linker-script-template>`.
|
||||
Linking is the last step in the process of turning C/C++ source files into an executable. It is performed by the toolchain's linker, and accepts linker scripts which specify code/data placements, among other things. With the linker script generation mechanism, this process is no different, except that the linker script passed to the linker is dynamically generated from: (1) the collected :ref:`linker fragment files <ldgen-linker-fragment-files>` and (2) :ref:`linker script template <ldgen-linker-script-template>`.
|
||||
|
||||
.. note::
|
||||
|
||||
|
@ -208,7 +210,7 @@ Linking is the last step in the process of turning C/C++ source files into an ex
|
|||
Linker Fragment Files
|
||||
^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
As mentioned in the quick start guide, fragment files are simple text files with the ``.lf`` extension containing the desired placements. This is a simplified description of what fragment files contain, however. What fragment files actually contain are 'fragments'. Fragments are entities which contain pieces of information which, when put together, form placement rules that tell where to place sections of object files in the output binary. There are three types of fragments: :ref:`sections<ldgen-sections-fragment>`, :ref:`scheme<ldgen-scheme-fragment>` and :ref:`mapping<ldgen-mapping-fragment>`.
|
||||
As mentioned in the quick start guide, fragment files are simple text files with the ``.lf`` extension containing the desired placements. This is a simplified description of what fragment files contain, however. What fragment files actually contain are 'fragments'. Fragments are entities which contain pieces of information which, when put together, form placement rules that tell where to place sections of object files in the output binary. There are three types of fragments: :ref:`sections <ldgen-sections-fragment>`, :ref:`scheme <ldgen-scheme-fragment>` and :ref:`mapping <ldgen-mapping-fragment>`.
|
||||
|
||||
Grammar
|
||||
"""""""
|
||||
|
@ -229,8 +231,8 @@ The three fragment types share a common grammar:
|
|||
- name: The name of the fragment, should be unique for the specified fragment type.
|
||||
- key, value: Contents of the fragment; each fragment type may support different keys and different grammars for the key values.
|
||||
|
||||
- For :ref:`sections<ldgen-sections-fragment>` and :ref:`scheme<ldgen-scheme-fragment>`, the only supported key is ``entries``
|
||||
- For :ref:`mappings<ldgen-mapping-fragment>`, both ``archive`` and ``entries`` are supported.
|
||||
- For :ref:`sections <ldgen-sections-fragment>` and :ref:`scheme <ldgen-scheme-fragment>`, the only supported key is ``entries``
|
||||
- For :ref:`mappings <ldgen-mapping-fragment>`, both ``archive`` and ``entries`` are supported.
|
||||
|
||||
.. note::
|
||||
|
||||
|
@ -304,7 +306,7 @@ Types
|
|||
|
||||
**Sections**
|
||||
|
||||
Sections fragments defines a list of object file sections that the GCC compiler emits. It may be a default section (e.g. ``.text``, ``.data``) or it may be user defined section through the ``__attribute__`` keyword.
|
||||
Sections fragments defines a list of object file sections that the GCC compiler emits. It may be a default section (e.g., ``.text``, ``.data``) or it may be user defined section through the ``__attribute__`` keyword.
|
||||
|
||||
The use of an optional '+' indicates the inclusion of the section in the list, as well as sections that start with it. This is the preferred method over listing both explicitly.
|
||||
|
||||
|
@ -378,12 +380,12 @@ built-in schemes referenced in the quick start guide are also defined in this fi
|
|||
|
||||
**Mapping**
|
||||
|
||||
Mapping fragments define what scheme fragment to use for mappable entities, i.e. object files, function names, variable names, archives.
|
||||
Mapping fragments define what scheme fragment to use for mappable entities, i.e., object files, function names, variable names, archives.
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
[mapping:name]
|
||||
archive: archive # output archive file name, as built (i.e. libxxx.a)
|
||||
archive: archive # output archive file name, as built (i.e., libxxx.a)
|
||||
entries:
|
||||
object:symbol (scheme) # symbol granularity
|
||||
object (scheme) # object granularity
|
||||
|
@ -516,7 +518,7 @@ On Symbol-Granularity Placements
|
|||
Symbol granularity placements is possible due to compiler flags ``-ffunction-sections`` and ``-ffdata-sections``. ESP-IDF compiles with these flags by default.
|
||||
If the user opts to remove these flags, then the symbol-granularity placements will not work. Furthermore, even with the presence of these flags, there are still other limitations to keep in mind due to the dependence on the compiler's emitted output sections.
|
||||
|
||||
For example, with ``-ffunction-sections``, separate sections are emitted for each function; with section names predictably constructed i.e. ``.text.{func_name}`` and ``.literal.{func_name}``. This is not the case for string literals within the function, as they go to pooled or generated section names.
|
||||
For example, with ``-ffunction-sections``, separate sections are emitted for each function; with section names predictably constructed i.e., ``.text.{func_name}`` and ``.literal.{func_name}``. This is not the case for string literals within the function, as they go to pooled or generated section names.
|
||||
|
||||
With ``-fdata-sections``, for global scope data the compiler predictably emits either ``.data.{var_name}``, ``.rodata.{var_name}`` or ``.bss.{var_name}``; and so ``Type I`` mapping entry works for these.
|
||||
However, this is not the case for static data declared in function scope, as the generated section name is a result of mangling the variable name with some other information.
|
||||
|
@ -610,5 +612,5 @@ Migrate to ESP-IDF v5.0 Linker Script Fragment Files Grammar
|
|||
The old grammar supported in ESP-IDF v3.x would be dropped in ESP-IDF v5.0. Here are a few notes on how to migrate properly:
|
||||
|
||||
1. Now indentation is enforced and improperly indented fragment files would generate a runtime parse exception. This was not enforced in the old version but previous documentation and examples demonstrate properly indented grammar.
|
||||
2. Migrate the old condition entry to the ``if...elif...else`` structure for conditionals. You can refer to the :ref:`earlier chapter<ldgen-conditional-placements>` for detailed grammar.
|
||||
2. Migrate the old condition entry to the ``if...elif...else`` structure for conditionals. You can refer to the :ref:`earlier chapter <ldgen-conditional-placements>` for detailed grammar.
|
||||
3. mapping fragments now requires a name like other fragment types.
|
||||
|
|
|
@ -58,7 +58,7 @@ IRAM (Instruction RAM)
|
|||
|
||||
.. only:: esp32
|
||||
|
||||
ESP-IDF allocates part of the Internal SRAM0 region for instruction RAM. The region is defined in *{IDF_TARGET_NAME} Technical Reference Manual* > *System and Memory* > *Embedded Memory* [`PDF <{IDF_TARGET_TRM_EN_URL}#sysmem>`__]. Except for the first 64 KB block which is used for PRO and APP MMU caches, the rest of this memory range (i.e. from ``0x40080000`` to ``0x400A0000``) is used to store parts of the application which need to run from RAM.
|
||||
ESP-IDF allocates part of the Internal SRAM0 region for instruction RAM. The region is defined in *{IDF_TARGET_NAME} Technical Reference Manual* > *System and Memory* > *Embedded Memory* [`PDF <{IDF_TARGET_TRM_EN_URL}#sysmem>`__]. Except for the first 64 KB block which is used for PRO and APP MMU caches, the rest of this memory range (i.e., from ``0x40080000`` to ``0x400A0000``) is used to store parts of the application which need to run from RAM.
|
||||
|
||||
.. only:: esp32s2
|
||||
|
||||
|
@ -90,7 +90,7 @@ Some code is automatically placed into the IRAM region using the linker script.
|
|||
|
||||
If some specific application code needs to be placed into IRAM, it can be done by using the :doc:`linker-script-generation` feature and adding a linker script fragment file to your component that targets at the entire source files or functions with the ``noflash`` placement. See the :doc:`linker-script-generation` docs for more information.
|
||||
|
||||
Alternatively, it's possible to specify IRAM placement in the source code using the ``IRAM_ATTR`` macro::
|
||||
Alternatively, it is possible to specify IRAM placement in the source code using the ``IRAM_ATTR`` macro::
|
||||
|
||||
#include "esp_attr.h"
|
||||
|
||||
|
@ -101,7 +101,7 @@ Alternatively, it's possible to specify IRAM placement in the source code using
|
|||
|
||||
There are some possible issues with placement in IRAM, that may cause problems with IRAM-safe interrupt handlers:
|
||||
|
||||
* Strings or constants inside an ``IRAM_ATTR`` function may not be placed in RAM automatically. It's possible to use ``DRAM_ATTR`` attributes to mark these, or using the linker script method will cause these to be automatically placed correctly.
|
||||
* Strings or constants inside an ``IRAM_ATTR`` function may not be placed in RAM automatically. It is possible to use ``DRAM_ATTR`` attributes to mark these, or using the linker script method will cause these to be automatically placed correctly.
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
|
@ -115,7 +115,7 @@ Note that knowing which data should be marked with ``DRAM_ATTR`` can be hard, th
|
|||
|
||||
* GCC optimizations that automatically generate jump tables or switch/case lookup tables place these tables in flash. IDF by default builds all files with ``-fno-jump-tables -fno-tree-switch-conversion`` flags to avoid this.
|
||||
|
||||
Jump table optimizations can be re-enabled for individual source files that don't need to be placed in IRAM. For instructions on how to add the ``-fno-jump-tables -fno-tree-switch-conversion`` options when compiling individual source files, see :ref:`component_build_control`.
|
||||
Jump table optimizations can be re-enabled for individual source files that do not need to be placed in IRAM. For instructions on how to add the ``-fno-jump-tables -fno-tree-switch-conversion`` options when compiling individual source files, see :ref:`component_build_control`.
|
||||
|
||||
|
||||
.. _irom:
|
||||
|
@ -134,7 +134,7 @@ During :doc:`startup`, the bootloader (which runs from IRAM) configures the MMU
|
|||
|
||||
.. _drom:
|
||||
|
||||
DROM (data stored in flash)
|
||||
DROM (Data Stored in flash)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. highlight:: c
|
||||
|
@ -147,7 +147,7 @@ The ``DRAM_ATTR`` attribute can be used to force constants from DROM into the :r
|
|||
|
||||
.. only:: SOC_RTC_SLOW_MEM_SUPPORTED
|
||||
|
||||
RTC Slow memory
|
||||
RTC Slow Memory
|
||||
^^^^^^^^^^^^^^^
|
||||
|
||||
Global and static variables used by code which runs from RTC memory must be placed into RTC Slow memory. For example :doc:`deep sleep <deep-sleep-stub>` variables can be placed here instead of RTC FAST memory, or code and variables accessed by the :doc:`/api-reference/system/ulp`.
|
||||
|
@ -161,7 +161,7 @@ The ``DRAM_ATTR`` attribute can be used to force constants from DROM into the :r
|
|||
|
||||
.. only:: SOC_RTC_FAST_MEM_SUPPORTED
|
||||
|
||||
RTC FAST memory
|
||||
RTC FAST Memory
|
||||
^^^^^^^^^^^^^^^
|
||||
|
||||
.. only:: esp32c6 or esp32h2
|
||||
|
@ -189,7 +189,7 @@ DMA-Capable Requirement
|
|||
|
||||
.. highlight:: c
|
||||
|
||||
Most peripheral DMA controllers (e.g. SPI, sdmmc, etc.) have requirements that sending/receiving buffers should be placed in DRAM and word-aligned. We suggest to place DMA buffers in static variables rather than in the stack. Use macro ``DMA_ATTR`` to declare global/local static variables like::
|
||||
Most peripheral DMA controllers (e.g., SPI, sdmmc, etc.) have requirements that sending/receiving buffers should be placed in DRAM and word-aligned. We suggest to place DMA buffers in static variables rather than in the stack. Use macro ``DMA_ATTR`` to declare global/local static variables like::
|
||||
|
||||
DMA_ATTR uint8_t buffer[]="I want to send something";
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@ OpenThread
|
|||
|
||||
`OpenThread <https://github.com/openthread/openthread>`_ is an IP stack running on the 802.15.4 MAC layer which features mesh network and low power consumption.
|
||||
|
||||
Modes of the OpenThread stack
|
||||
Modes of the OpenThread Stack
|
||||
-----------------------------
|
||||
|
||||
OpenThread can run under the following modes on Espressif chips:
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
Partition Tables
|
||||
================
|
||||
|
||||
:link_to_translation:`zh_CN:[中文]`
|
||||
|
||||
Overview
|
||||
|
@ -142,7 +143,7 @@ See enum :cpp:type:`esp_partition_subtype_t` for the full list of subtypes defin
|
|||
|
||||
* If the partition type is any application-defined value (range 0x40-0xFE), then ``subtype`` field can be any value chosen by the application (range 0x00-0xFE).
|
||||
|
||||
Note that when writing in C++, an application-defined subtype value requires casting to type :cpp:type:`esp_partition_subtype_t` in order to use it with the :ref:`partition API<api-reference-partition-table>`.
|
||||
Note that when writing in C++, an application-defined subtype value requires casting to type :cpp:type:`esp_partition_subtype_t` in order to use it with the :ref:`partition API <api-reference-partition-table>`.
|
||||
|
||||
Extra Partition SubTypes
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
@ -198,7 +199,7 @@ The ESP-IDF build system will automatically check if generated binaries fit in t
|
|||
Currently these checks are performed for the following binaries:
|
||||
|
||||
* Bootloader binary must fit in space before partition table (see :ref:`bootloader-size`).
|
||||
* App binary should fit in at least one partition of type "app". If the app binary doesn't fit in any app partition, the build will fail. If it only fits in some of the app partitions, a warning is printed about this.
|
||||
* App binary should fit in at least one partition of type "app". If the app binary does not fit in any app partition, the build will fail. If it only fits in some of the app partitions, a warning is printed about this.
|
||||
|
||||
.. note::
|
||||
|
||||
|
@ -228,13 +229,13 @@ A manual flashing command is also printed as part of ``idf.py partition-table``
|
|||
|
||||
.. note::
|
||||
|
||||
Note that updating the partition table doesn't erase data that may have been stored according to the old partition table. You can use ``idf.py erase-flash`` (or ``esptool.py erase_flash``) to erase the entire flash contents.
|
||||
Note that updating the partition table does not erase data that may have been stored according to the old partition table. You can use ``idf.py erase-flash`` (or ``esptool.py erase_flash``) to erase the entire flash contents.
|
||||
|
||||
|
||||
Partition Tool (parttool.py)
|
||||
----------------------------
|
||||
Partition Tool (``parttool.py``)
|
||||
--------------------------------
|
||||
|
||||
The component `partition_table` provides a tool :component_file:`parttool.py<partition_table/parttool.py>` for performing partition-related operations on a target device. The following operations can be performed using the tool:
|
||||
The component `partition_table` provides a tool :component_file:`parttool.py <partition_table/parttool.py>` for performing partition-related operations on a target device. The following operations can be performed using the tool:
|
||||
|
||||
- reading a partition and saving the contents to a file (read_partition)
|
||||
- writing the contents of a file to a partition (write_partition)
|
||||
|
|
|
@ -449,7 +449,7 @@ lwIP IPv4
|
|||
|
||||
.. note::
|
||||
|
||||
Before disabling IPv4 support, please note that IPv6 only network environments are not ubiquitous and must be supported in the local network, e.g. by your internet service provider or using constrained local network settings.
|
||||
Before disabling IPv4 support, please note that IPv6 only network environments are not ubiquitous and must be supported in the local network, e.g., by your internet service provider or using constrained local network settings.
|
||||
|
||||
.. _newlib-nano-formatting:
|
||||
|
||||
|
@ -460,7 +460,7 @@ By default, ESP-IDF uses Newlib "full" formatting for I/O functions (``printf()`
|
|||
|
||||
.. only:: CONFIG_ESP_ROM_HAS_NEWLIB_NANO_FORMAT
|
||||
|
||||
Enabling the config option :ref:`CONFIG_NEWLIB_NANO_FORMAT` will switch Newlib to the “Nano” formatting mode. This is smaller in code size, and a large part of the implementation is compiled into the {IDF_TARGET_NAME} ROM, so it does not need to be included in the binary at all.
|
||||
Enabling the config option :ref:`CONFIG_NEWLIB_NANO_FORMAT` will switch Newlib to the "Nano" formatting mode. This is smaller in code size, and a large part of the implementation is compiled into the {IDF_TARGET_NAME} ROM, so it does not need to be included in the binary at all.
|
||||
|
||||
The exact difference in binary size depends on which features the firmware uses, but 25 KB ~ 50 KB is typical.
|
||||
|
||||
|
@ -505,7 +505,7 @@ These include:
|
|||
- :ref:`CONFIG_MBEDTLS_ECP_NIST_OPTIM`
|
||||
- :ref:`CONFIG_MBEDTLS_ECP_FIXED_POINT_OPTIM`
|
||||
- Change :ref:`CONFIG_MBEDTLS_TLS_MODE` if both server & client functionalities are not needed
|
||||
- Consider disabling some cipher suites listed in the ``TLS Key Exchange Methods`` sub-menu (i.e. :ref:`CONFIG_MBEDTLS_KEY_EXCHANGE_RSA`)
|
||||
- Consider disabling some cipher suites listed in the ``TLS Key Exchange Methods`` sub-menu (i.e., :ref:`CONFIG_MBEDTLS_KEY_EXCHANGE_RSA`)
|
||||
|
||||
The help text for each option has some more information for reference.
|
||||
|
||||
|
|
|
@ -6,13 +6,13 @@ Introduction
|
|||
|
||||
ESP-IDF build system has support for `reproducible builds`_.
|
||||
|
||||
When reproducible builds are enabled, the application built with ESP-IDF doesn't depend on the build environment. Both the .elf file and .bin files of the application remains exactly the same, even if the following variables change:
|
||||
When reproducible builds are enabled, the application built with ESP-IDF does not depend on the build environment. Both the .elf file and .bin files of the application remains exactly the same, even if the following variables change:
|
||||
|
||||
- Directory where the project is located
|
||||
- Directory where ESP-IDF is located (``IDF_PATH``)
|
||||
- Build time
|
||||
|
||||
Reasons for non-reproducible builds
|
||||
Reasons for Non-Reproducible Builds
|
||||
-----------------------------------
|
||||
|
||||
There are several reasons why an application may depend on the build environment, even when the same source code and tools versions are used.
|
||||
|
@ -23,7 +23,7 @@ There are several reasons why an application may depend on the build environment
|
|||
|
||||
There are also other possible reasons, such as unstable order of inputs and non-determinism in the build system.
|
||||
|
||||
Enabling reproducible builds in ESP-IDF
|
||||
Enabling Reproducible Builds in ESP-IDF
|
||||
---------------------------------------
|
||||
|
||||
Reproducible builds can be enabled in ESP-IDF using :ref:`CONFIG_APP_REPRODUCIBLE_BUILD` option.
|
||||
|
@ -32,7 +32,7 @@ This option is disabled by default. It can be enabled in ``menuconfig``.
|
|||
|
||||
The option may also be added into ``sdkconfig.defaults``. If adding the option into ``sdkconfig.defaults``, delete the ``sdkconfig`` file and run the build again. See :ref:`custom-sdkconfig-defaults` for more information.
|
||||
|
||||
How reproducible builds are achieved
|
||||
How Reproducible Builds Are Achieved
|
||||
------------------------------------
|
||||
|
||||
ESP-IDF achieves reproducible builds using the following measures:
|
||||
|
@ -45,10 +45,10 @@ ESP-IDF achieves reproducible builds using the following measures:
|
|||
- Path to the build directory is replaced with ``/IDF_BUILD``
|
||||
- Paths to components are replaced with ``/COMPONENT_NAME_DIR`` (where ``NAME`` is the name of the component)
|
||||
|
||||
- Build date and time are not included into the :ref:`application metadata structure<app-image-format-application-description>` and :ref:`bootloader metadata structure<image-format-bootloader-description>` if :ref:`CONFIG_APP_REPRODUCIBLE_BUILD` is enabled.
|
||||
- Build date and time are not included into the :ref:`application metadata structure <app-image-format-application-description>` and :ref:`bootloader metadata structure <image-format-bootloader-description>` if :ref:`CONFIG_APP_REPRODUCIBLE_BUILD` is enabled.
|
||||
- ESP-IDF build system ensures that source file lists, component lists and other sequences are sorted before passing them to CMake. Various other parts of the build system, such as the linker script generator also perform sorting to ensure that same output is produced regardless of the environment.
|
||||
|
||||
Reproducible builds and debugging
|
||||
Reproducible Builds and Debugging
|
||||
---------------------------------
|
||||
|
||||
When reproducible builds are enabled, file names included in debug information sections are altered as shown in the previous section. Due to this fact, the debugger (GDB) is not able to locate the source files for the given code location.
|
||||
|
@ -59,9 +59,9 @@ This issue can be solved using GDB ``set substitute-path`` command. For example,
|
|||
|
||||
ESP-IDF build system generates a file with the list of such ``set substitute-path`` commands automatically during the build process. The file is called ``prefix_map_gdbinit`` and is located in the project ``build`` directory.
|
||||
|
||||
When :ref:`idf.py gdb<jtag-debugging-with-idf-py>` is used to start debugging, this additional gdbinit file is automatically passed to GDB. When launching GDB manually or from and IDE, please pass this additional gdbinit script to GDB using ``-x build/prefix_map_gdbinit`` argument.
|
||||
When :ref:`idf.py gdb <jtag-debugging-with-idf-py>` is used to start debugging, this additional gdbinit file is automatically passed to GDB. When launching GDB manually or from and IDE, please pass this additional gdbinit script to GDB using ``-x build/prefix_map_gdbinit`` argument.
|
||||
|
||||
Factors which still affect reproducible builds
|
||||
Factors Which Still Affect Reproducible Builds
|
||||
----------------------------------------------
|
||||
|
||||
Note that the built application still depends on:
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
Application Startup Flow
|
||||
========================
|
||||
|
||||
:link_to_translation:`zh_CN:[中文]`
|
||||
|
||||
{IDF_TARGET_BOOTLOADER_OFFSET:default="0x0", esp32="0x1000", esp32s2="0x1000"}
|
||||
|
@ -18,7 +19,7 @@ This process is explained in detail in the following sections.
|
|||
|
||||
.. _first-stage-bootloader:
|
||||
|
||||
First stage bootloader
|
||||
First Stage Bootloader
|
||||
^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. only:: not CONFIG_FREERTOS_UNICORE
|
||||
|
@ -59,7 +60,7 @@ Startup code called from the reset vector determines the boot mode by checking `
|
|||
|
||||
.. _second-stage-bootloader:
|
||||
|
||||
Second stage bootloader
|
||||
Second Stage Bootloader
|
||||
^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
In ESP-IDF, the binary image which resides at offset {IDF_TARGET_BOOTLOADER_OFFSET} in flash is the second stage bootloader. Second stage bootloader source code is available in :idf:`components/bootloader` directory of ESP-IDF. Second stage bootloader is used in ESP-IDF to add flexibility to flash layout (using partition tables), and allow for various flows associated with flash encryption, secure boot, and over-the-air updates (OTA) to take place.
|
||||
|
@ -83,7 +84,7 @@ Once all segments are processed - meaning code is loaded and flash MMU is set up
|
|||
|
||||
.. _application-startup:
|
||||
|
||||
Application startup
|
||||
Application Startup
|
||||
^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Application startup covers everything that happens after the app starts executing and before the ``app_main`` function starts running inside the main task. This is split into three stages:
|
||||
|
@ -126,7 +127,7 @@ This port-layer initialization function initializes the basic C Runtime Environm
|
|||
System Initialization
|
||||
---------------------
|
||||
|
||||
The main system initialization function is ``start_cpu0``. By default, this function is weak-linked to the function ``start_cpu0_default``. This means that it's possible to override this function to add some additional initialization steps.
|
||||
The main system initialization function is ``start_cpu0``. By default, this function is weak-linked to the function ``start_cpu0_default``. This means that it is possible to override this function to add some additional initialization steps.
|
||||
|
||||
The primary system initialization stage includes:
|
||||
|
||||
|
@ -146,7 +147,7 @@ Secondary system initialization allows individual components to be initialized.
|
|||
|
||||
.. _app-main-task:
|
||||
|
||||
Running the main task
|
||||
Running the Main Task
|
||||
---------------------
|
||||
|
||||
After all other components are initialized, the main task is created and the FreeRTOS scheduler starts running.
|
||||
|
@ -163,7 +164,7 @@ Unlike normal FreeRTOS tasks (or embedded C ``main`` functions), the ``app_main`
|
|||
|
||||
.. only:: not CONFIG_FREERTOS_UNICORE
|
||||
|
||||
Second core startup
|
||||
Second Core Startup
|
||||
-------------------
|
||||
|
||||
A similar but simpler startup process happens on the APP CPU:
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
******************
|
||||
ESP-IDF Clang-Tidy
|
||||
IDF Clang-Tidy
|
||||
******************
|
||||
|
||||
:link_to_translation:`zh_CN:[中文]`
|
||||
|
||||
The ESP-IDF Clang Tidy is a tool that uses `clang-tidy <https://clang.llvm.org/extra/clang-tidy/>`__ to run static analysis on your current app.
|
||||
The IDF Clang Tidy is a tool that uses `clang-tidy <https://clang.llvm.org/extra/clang-tidy/>`__ to run static analysis on your current app.
|
||||
|
||||
.. warning::
|
||||
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
*************************
|
||||
ESP-IDF Component Manager
|
||||
*************************
|
||||
*********************
|
||||
IDF Component Manager
|
||||
*********************
|
||||
|
||||
:link_to_translation:`zh_CN:[中文]`
|
||||
|
||||
The ESP-IDF Component Manager is a tool that downloads dependencies for any ESP-IDF CMake project. The download happens automatically during a run of CMake. It can source components either from the `component registry <https://components.espressif.com>`__ or from a Git repository.
|
||||
The IDF Component Manager is a tool that downloads dependencies for any ESP-IDF CMake project. The download happens automatically during a run of CMake. It can source components either from the `component registry <https://components.espressif.com>`__ or from a Git repository.
|
||||
|
||||
A list of components can be found on `<https://components.espressif.com/>`__.
|
||||
|
||||
For detailed information about the ESP-IDF Component Manager, see the `ESP-IDF Component Manager and ESP Component Registry Documentation <https://docs.espressif.com/projects/idf-component-manager/en/latest/>`__.
|
||||
For detailed information about the IDF Component Manager, see the `IDF Component Manager and ESP Component Registry Documentation <https://docs.espressif.com/projects/idf-component-manager/en/latest/>`__.
|
||||
|
||||
Using with a Project
|
||||
====================
|
||||
|
@ -21,7 +21,7 @@ Dependencies for each component in the project are defined in a separate manifes
|
|||
|
||||
When a new manifest is added to one of the components in the project, it is necessary to reconfigure the project manually by running ``idf.py reconfigure``. The build will then track changes in ``idf_component.yml`` manifests and automatically trigger CMake when necessary.
|
||||
|
||||
To add a dependency to a component (e.g., ``my_component``) in your ESP-IDF project, you can run the command ``idf.py add-dependency DEPENDENCY``. The ``DEPENDENCY`` argument represents an additional component managed by the ESP-IDF Component Manager that ``my_component`` depends on. It is defined in the format ``namespace/name=1.0.0``, where `namespace/name` is the name of the component and `=1.0.0` is a version range of the component, see the `Versioning Documentation <https://docs.espressif.com/projects/idf-component-manager/en/latest/reference/versioning.html>`__. By default, dependencies are added to the main component. You can either explicitly specify a directory where the manifest is located using the ``--path`` option, or specify the component in your ``components`` folder using ``--component=my_component``. The ``add-dependency`` command can be run in the following ways:
|
||||
To add a dependency to a component (e.g., ``my_component``) in your ESP-IDF project, you can run the command ``idf.py add-dependency DEPENDENCY``. The ``DEPENDENCY`` argument represents an additional component managed by the IDF Component Manager that ``my_component`` depends on. It is defined in the format ``namespace/name=1.0.0``, where `namespace/name` is the name of the component and `=1.0.0` is a version range of the component, see the `Versioning Documentation <https://docs.espressif.com/projects/idf-component-manager/en/latest/reference/versioning.html>`__. By default, dependencies are added to the main component. You can either explicitly specify a directory where the manifest is located using the ``--path`` option, or specify the component in your ``components`` folder using ``--component=my_component``. The ``add-dependency`` command can be run in the following ways:
|
||||
|
||||
- ``idf.py add-dependency example/cmp`` adds a dependency on the most recent version of ``example/cmp`` to the main component
|
||||
- ``idf.py add-dependency --component=my_component example/cmp<=3.3.3`` adds a dependency on the version ``<=3.3.3`` of ``example/cmp`` to the component ``my_component`` in the ``components`` directory
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
********************
|
||||
ESP-IDF Docker Image
|
||||
********************
|
||||
****************
|
||||
IDF Docker Image
|
||||
****************
|
||||
|
||||
:link_to_translation:`zh_CN:[中文]`
|
||||
|
||||
|
@ -9,7 +9,7 @@ ESP-IDF Docker Image
|
|||
|
||||
.. highlight:: bash
|
||||
|
||||
ESP-IDF Docker image (``espressif/idf``) is intended for building applications and libraries with specific versions of ESP-IDF when doing automated builds.
|
||||
IDF Docker image (``espressif/idf``) is intended for building applications and libraries with specific versions of ESP-IDF when doing automated builds.
|
||||
|
||||
The image contains:
|
||||
|
||||
|
@ -142,7 +142,7 @@ The Docker file in ESP-IDF repository provides several build arguments which can
|
|||
- ``IDF_CLONE_SHALLOW``: If this argument is set to a non-empty value, ``--depth=1 --shallow-submodules`` arguments are be used when performing ``git clone``. This significantly reduces the amount of data downloaded and the size of the resulting Docker image. However, if switching to a different branch in such a "shallow" repository is necessary, an additional ``git fetch origin <branch>`` command must be executed first.
|
||||
- ``IDF_INSTALL_TARGETS``: Comma-separated list of ESP-IDF targets to install toolchains for, or ``all`` to install toolchains for all targets. Selecting specific targets reduces the amount of data downloaded and the size of the resulting Docker image. The default is ``all``.
|
||||
|
||||
To use these arguments, pass them via the ``--build-arg`` command line option. For example, the following command builds a Docker image with a shallow clone of ESP-IDF v4.4.1 and tools for ESP32-C3 only:
|
||||
To use these arguments, pass them via the ``--build-arg`` command line option. For example, the following command builds a Docker image with a shallow clone of ESP-IDF v4.4.1 and tools for ESP32-C3 only:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
|
|
|
@ -4,9 +4,9 @@ IDF Monitor
|
|||
|
||||
:link_to_translation:`zh_CN:[中文]`
|
||||
|
||||
IDF Monitor uses the esp-idf-monitor_ package as a serial terminal program which relays serial data to and from the target device's serial port. It also provides some IDF-specific features.
|
||||
IDF Monitor uses the esp-idf-monitor_ package as a serial terminal program which relays serial data to and from the target device's serial port. It also provides some ESP-IDF-specific features.
|
||||
|
||||
IDF Monitor can be launched from an IDF project by running ``idf.py monitor``.
|
||||
IDF Monitor can be launched from an ESP-IDF project by running ``idf.py monitor``.
|
||||
|
||||
Keyboard Shortcuts
|
||||
==================
|
||||
|
@ -20,61 +20,61 @@ For easy interaction with IDF Monitor, use the keyboard shortcuts given in the t
|
|||
* - Keyboard Shortcut
|
||||
- Action
|
||||
- Description
|
||||
* - Ctrl+]
|
||||
* - Ctrl + ]
|
||||
- Exit the program
|
||||
-
|
||||
* - Ctrl+T
|
||||
* - Ctrl + T
|
||||
- Menu escape key
|
||||
- Press and follow it by one of the keys given below.
|
||||
* - * Ctrl+T
|
||||
* - * Ctrl + T
|
||||
- Send the menu character itself to remote
|
||||
-
|
||||
* - * Ctrl+]
|
||||
* - * Ctrl + ]
|
||||
- Send the exit character itself to remote
|
||||
-
|
||||
* - * Ctrl+P
|
||||
* - * Ctrl + P
|
||||
- Reset target into bootloader to pause app via RTS line
|
||||
- Resets the target, into bootloader via the RTS line (if connected), so that the board runs nothing. Useful when you need to wait for another device to startup.
|
||||
* - * Ctrl+R
|
||||
* - * Ctrl + R
|
||||
- Reset target board via RTS
|
||||
- Resets the target board and re-starts the application via the RTS line (if connected).
|
||||
* - * Ctrl+F
|
||||
* - * Ctrl + F
|
||||
- Build and flash the project
|
||||
- Pauses idf_monitor to run the project ``flash`` target, then resumes idf_monitor. Any changed source files are recompiled and then re-flashed. Target ``encrypted-flash`` is run if idf_monitor was started with argument ``-E``.
|
||||
* - * Ctrl+A (or A)
|
||||
* - * Ctrl + A (or A)
|
||||
- Build and flash the app only
|
||||
- Pauses idf_monitor to run the ``app-flash`` target, then resumes idf_monitor. Similar to the ``flash`` target, but only the main app is built and re-flashed. Target ``encrypted-app-flash`` is run if idf_monitor was started with argument ``-E``.
|
||||
* - * Ctrl+Y
|
||||
* - * Ctrl + Y
|
||||
- Stop/resume log output printing on screen
|
||||
- Discards all incoming serial data while activated. Allows to quickly pause and examine log output without quitting the monitor.
|
||||
* - * Ctrl+L
|
||||
* - * Ctrl + L
|
||||
- Stop/resume log output saved to file
|
||||
- Creates a file in the project directory and the output is written to that file until this is disabled with the same keyboard shortcut (or IDF Monitor exits).
|
||||
* - * Ctrl+I (or I)
|
||||
* - * Ctrl + I (or I)
|
||||
- Stop/resume printing timestamps
|
||||
- IDF Monitor can print a timestamp in the beginning of each line. The timestamp format can be changed by the ``--timestamp-format`` command line argument.
|
||||
* - * Ctrl+H (or H)
|
||||
* - * Ctrl + H (or H)
|
||||
- Display all keyboard shortcuts
|
||||
-
|
||||
* - * Ctrl+X (or X)
|
||||
* - * Ctrl + X (or X)
|
||||
- Exit the program
|
||||
-
|
||||
* - Ctrl+C
|
||||
* - Ctrl + C
|
||||
- Interrupt running application
|
||||
- Pauses IDF Monitor and runs GDB_ project debugger to debug the application at runtime. This requires :ref:CONFIG_ESP_SYSTEM_GDBSTUB_RUNTIME option to be enabled.
|
||||
|
||||
Any keys pressed, other than ``Ctrl-]`` and ``Ctrl-T``, will be sent through the serial port.
|
||||
|
||||
|
||||
IDF-specific features
|
||||
=====================
|
||||
ESP-IDF-specific Features
|
||||
=========================
|
||||
|
||||
Automatic Address Decoding
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Whenever the chip outputs a hexadecimal address that points to executable code, IDF monitor looks up the location in the source code (file name and line number) and prints the location on the next line in yellow.
|
||||
|
||||
.. highlight:: none
|
||||
.. code-block:: none
|
||||
|
||||
.. only:: CONFIG_IDF_TARGET_ARCH_XTENSA
|
||||
|
||||
|
@ -226,7 +226,7 @@ The ROM ELF file is automatically loaded from a location based on the ``IDF_PATH
|
|||
Set environment variable ``ESP_MONITOR_DECODE`` to ``0`` or call esp_idf_monitor with specific command line option: ``python -m esp_idf_monitor --disable-address-decoding`` to disable address decoding.
|
||||
|
||||
Target Reset on Connection
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
By default, IDF Monitor will reset the target when connecting to it. The reset of the target chip is performed using the DTR and RTS serial lines. To prevent IDF Monitor from automatically resetting the target on connection, call IDF Monitor with the ``--no-reset`` option (e.g., ``idf.py monitor --no-reset``).
|
||||
|
||||
|
@ -247,6 +247,7 @@ Furthermore, the panic handler can be configured to run GDBStub on a crash by se
|
|||
In both cases (i.e., sending the ``Ctrl+C`` message, or receiving the special string pattern), IDF Monitor will automatically launch GDB in order to allow the user to send debugging commands. After GDB exits, the target is reset via the RTS serial line. If this line is not connected, users can reset their target (by pressing the board's Reset button).
|
||||
|
||||
.. note::
|
||||
|
||||
In the background, IDF Monitor runs the following command to launch GDB::
|
||||
|
||||
{IDF_TARGET_TOOLCHAIN_PREFIX}-gdb -ex "set serial baud BAUD" -ex "target remote PORT" -ex interrupt build/PROJECT.elf :idf_target:`Hello NAME chip`
|
||||
|
@ -259,10 +260,11 @@ IDF monitor can be invoked as ``idf.py monitor --print-filter="xyz"``, where ``-
|
|||
|
||||
Restrictions on what to print can be specified as a series of ``<tag>:<log_level>`` items where ``<tag>`` is the tag string and ``<log_level>`` is a character from the set ``{N, E, W, I, D, V, *}`` referring to a level for :doc:`logging <../../api-reference/system/log>`.
|
||||
|
||||
For example, ``PRINT_FILTER="tag1:W"`` matches and prints only the outputs written with ``ESP_LOGW("tag1", ...)`` or at lower verbosity level, i.e. ``ESP_LOGE("tag1", ...)``. Not specifying a ``<log_level>`` or using ``*`` defaults to Verbose level.
|
||||
For example, ``PRINT_FILTER="tag1:W"`` matches and prints only the outputs written with ``ESP_LOGW("tag1", ...)`` or at lower verbosity level, i.e., ``ESP_LOGE("tag1", ...)``. Not specifying a ``<log_level>`` or using ``*`` defaults to Verbose level.
|
||||
|
||||
.. note::
|
||||
Use primary logging to disable at compilation the outputs you do not need through the :doc:`logging library<../../api-reference/system/log>`. Output filtering with IDF monitor is a secondary solution which can be useful for adjusting the filtering options without recompiling the application.
|
||||
|
||||
Use primary logging to disable at compilation the outputs you do not need through the :doc:`logging library <../../api-reference/system/log>`. Output filtering with ESP- monitor is a secondary solution which can be useful for adjusting the filtering options without recompiling the application.
|
||||
|
||||
Your app tags must not contain spaces, asterisks ``*``, or colons ``:`` to be compatible with the output filtering feature.
|
||||
|
||||
|
@ -315,7 +317,7 @@ Known Issues with IDF Monitor
|
|||
=============================
|
||||
|
||||
Issues Observed on Windows
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
- Arrow keys, as well as some other keys, do not work in GDB due to Windows Console limitations.
|
||||
- Occasionally, when "idf.py" exits, it might stall for up to 30 seconds before IDF Monitor resumes.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
ESP-IDF Frontend - idf.py
|
||||
IDF Frontend - ``idf.py``
|
||||
*************************
|
||||
|
||||
:link_to_translation:`zh_CN:[中文]`
|
||||
|
@ -19,7 +19,7 @@ Commands
|
|||
========
|
||||
|
||||
Start a New Project: ``create-project``
|
||||
------------------------------------------
|
||||
---------------------------------------
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
|
@ -28,7 +28,7 @@ Start a New Project: ``create-project``
|
|||
This command creates a new ESP-IDF project. Additionally, the folder where the project will be created in can be specified by the ``--path`` option.
|
||||
|
||||
Create a New Component: ``create-component``
|
||||
-----------------------------------------------
|
||||
--------------------------------------------
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
|
@ -39,7 +39,7 @@ This command creates a new component, which will have a minimum set of files nec
|
|||
.. _selecting-idf-target:
|
||||
|
||||
Select the Target Chip: ``set-target``
|
||||
-----------------------------------------
|
||||
--------------------------------------
|
||||
|
||||
ESP-IDF supports multiple targets (chips). A full list of supported targets in your version of ESP-IDF can be seen by running ``idf.py --list-targets``.
|
||||
|
||||
|
@ -68,14 +68,14 @@ To specify the default value of ``IDF_TARGET`` for a given project, please add t
|
|||
If the target has not been set by any of these methods, the build system will default to ``esp32`` target.
|
||||
|
||||
Start the Graphical Configuration Tool: ``menuconfig``
|
||||
--------------------------------------------------------
|
||||
------------------------------------------------------
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
idf.py menuconfig
|
||||
|
||||
Build the Project: ``build``
|
||||
-------------------------------
|
||||
----------------------------
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
|
@ -92,7 +92,7 @@ Building is incremental, so if no source files or configuration has changed sinc
|
|||
Additionally, the command can be run with ``app``, ``bootloader`` and ``partition-table`` arguments to build only the app, bootloader or partition table as applicable.
|
||||
|
||||
Remove the Build Output: ``clean``
|
||||
-------------------------------------
|
||||
----------------------------------
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
|
@ -101,7 +101,7 @@ Remove the Build Output: ``clean``
|
|||
This command removes the project build output files from the build directory, and the project will be fully rebuilt on next build. Using this command does not remove the CMake configuration output inside the build folder.
|
||||
|
||||
Delete the Entire Build Contents: ``fullclean``
|
||||
--------------------------------------------------
|
||||
-----------------------------------------------
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
|
@ -110,7 +110,7 @@ Delete the Entire Build Contents: ``fullclean``
|
|||
This command deletes the entire "build" directory contents, which includes all CMake configuration output. The next time the project is built, CMake will configure it from scratch. Note that this option recursively deletes **all** files in the build directory, so use with care. Project configuration is not deleted.
|
||||
|
||||
Flash the Project: ``flash``
|
||||
-------------------------------
|
||||
----------------------------
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
|
@ -150,7 +150,7 @@ Advanced Commands
|
|||
=================
|
||||
|
||||
Open the Documentation: ``docs``
|
||||
-----------------------------------
|
||||
--------------------------------
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
|
@ -159,7 +159,7 @@ Open the Documentation: ``docs``
|
|||
This command opens the documentation for the projects target and ESP-IDF version in the browser.
|
||||
|
||||
Show Size: ``size``
|
||||
-----------------------
|
||||
-------------------
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
|
@ -186,16 +186,16 @@ Options
|
|||
- ``--output-file`` optionally specifies the name of the file to print the command output to instead of the standard output.
|
||||
|
||||
Reconfigure the Project: ``reconfigure``
|
||||
-------------------------------------------
|
||||
----------------------------------------
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
idf.py reconfigure
|
||||
|
||||
This command forces CMake_ to be rerun regardless of whether it is necessary. It's unnecessary during normal usage, but can be useful after adding/removing files from the source tree, or when modifying CMake cache variables. For example, ``idf.py -DNAME='VALUE' reconfigure`` can be used to set variable ``NAME`` in CMake cache to value ``VALUE``.
|
||||
This command forces CMake_ to be rerun regardless of whether it is necessary. It is unnecessary during normal usage, but can be useful after adding/removing files from the source tree, or when modifying CMake cache variables. For example, ``idf.py -DNAME='VALUE' reconfigure`` can be used to set variable ``NAME`` in CMake cache to value ``VALUE``.
|
||||
|
||||
Clean the Python Byte Code: ``python-clean``
|
||||
-----------------------------------------------
|
||||
--------------------------------------------
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
|
@ -204,7 +204,7 @@ Clean the Python Byte Code: ``python-clean``
|
|||
This command deletes generated python byte code from the ESP-IDF directory. The byte code may cause issues when switching between ESP-IDF and Python versions. It is advised to run this target after switching versions of Python.
|
||||
|
||||
Generate a UF2 Binary: ``uf2``
|
||||
---------------------------------
|
||||
------------------------------
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
Downloadable ESP-IDF Tools
|
||||
Downloadable IDF Tools
|
||||
==========================
|
||||
|
||||
:link_to_translation:`zh_CN:[中文]`
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
ESP-IDF Windows Installer
|
||||
IDF Windows Installer
|
||||
=========================
|
||||
|
||||
:link_to_translation:`zh_CN:[中文]`
|
||||
|
@ -45,7 +45,7 @@ When running the installer from the command line, it detaches its process from t
|
|||
Custom Python and Custom Location of Python Wheels
|
||||
--------------------------------------------------
|
||||
|
||||
The ESP-IDF installer is using by default embedded Python with reference to the Python Wheel mirror.
|
||||
The IDF installer is using by default embedded Python with reference to the Python Wheel mirror.
|
||||
|
||||
The following parameters allow to select custom Python and custom location of Python wheels:
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
Unit Testing in {IDF_TARGET_NAME}
|
||||
=================================
|
||||
|
||||
:link_to_translation:`zh_CN:[中文]`
|
||||
|
||||
ESP-IDF provides the following methods to test software.
|
||||
|
@ -141,7 +142,7 @@ Once you need one of the tests to be compiled on a specified target, just modify
|
|||
#endif //!TEMPORARY_DISABLED_FOR_TARGETS(ESP64)
|
||||
#endif //SOC_SDIO_SLAVE_SUPPORTED
|
||||
|
||||
2. For test code that you are 100% for sure that will not be supported (e.g. no peripheral at all), use ``DISABLED_FOR_TARGETS``; for test code that should be disabled temporarily, or due to lack of runners, etc., use ``TEMPORARY_DISABLED_FOR_TARGETS``.
|
||||
2. For test code that you are 100% for sure that will not be supported (e.g., no peripheral at all), use ``DISABLED_FOR_TARGETS``; for test code that should be disabled temporarily, or due to lack of runners, etc., use ``TEMPORARY_DISABLED_FOR_TARGETS``.
|
||||
|
||||
Some old ways of disabling unit tests for targets, that have obvious disadvantages, are deprecated:
|
||||
|
||||
|
@ -249,7 +250,7 @@ First time you execute this case, input ``1`` to run first stage (trigger deepsl
|
|||
Timing Code with Cache Compensated Timer
|
||||
----------------------------------------
|
||||
|
||||
Instructions and data stored in external memory (e.g. SPI Flash and SPI RAM) are accessed through the CPU's unified instruction and data cache. When code or data is in cache, access is very fast (i.e., a cache hit).
|
||||
Instructions and data stored in external memory (e.g., SPI Flash and SPI RAM) are accessed through the CPU's unified instruction and data cache. When code or data is in cache, access is very fast (i.e., a cache hit).
|
||||
|
||||
However, if the instruction or data is not in cache, it needs to be fetched from external memory (i.e., a cache miss). Access to external memory is significantly slower, as the CPU must execute stall cycles whilst waiting for the instruction or data to be retrieved from external memory. This can cause the overall code execution speed to vary depending on the number of cache hits or misses.
|
||||
|
||||
|
@ -290,7 +291,7 @@ One of the biggest problems regarding unit testing on embedded systems are the s
|
|||
|
||||
When testing a particular component, (i.e., the component under test), mocking allows the dependencies of the component under test to be substituted (i.e., mocked) entirely in software. Through mocking, hardware details are emulated and specified at run time, but only if necessary. To allow mocking, ESP-IDF integrates the `CMock <https://www.throwtheswitch.org/cmock>`_ mocking framework as a component. With the addition of some CMake functions in the ESP-IDF build system, it is possible to conveniently mock the entirety (or a part) of an IDF component.
|
||||
|
||||
Ideally, all components that the component under test is dependent on should be mocked, thus allowing the test environment complete control over all interactions with the component under test. However, if mocking all dependent components becomes too complex or too tedious (e.g. because you need to mock too many function calls) you have the following options:
|
||||
Ideally, all components that the component under test is dependent on should be mocked, thus allowing the test environment complete control over all interactions with the component under test. However, if mocking all dependent components becomes too complex or too tedious (e.g., because you need to mock too many function calls) you have the following options:
|
||||
|
||||
.. list::
|
||||
- Include more "real" IDF code in the tests. This may work but increases the dependency on the "real" code's behavior. Furthermore, once a test fails, you may not know if the failure is in your actual code under test or the "real" IDF code.
|
||||
|
|
|
@ -33,11 +33,11 @@ Some development boards may offer a USB connector for the internal USB periphera
|
|||
|
||||
.. only:: esp32s3
|
||||
|
||||
By default, :doc:`USB_SERIAL_JTAG<usb-serial-jtag-console>` module is connected to the internal PHY of the ESP32-S3, while USB_OTG peripheral can be used only if the external USB PHY is connected. Since CDC console is provided via USB_OTG peripheral, it cannot be used through the internal PHY in this configuration.
|
||||
By default, :doc:`USB_SERIAL_JTAG <usb-serial-jtag-console>` module is connected to the internal PHY of the ESP32-S3, while USB_OTG peripheral can be used only if the external USB PHY is connected. Since CDC console is provided via USB_OTG peripheral, it cannot be used through the internal PHY in this configuration.
|
||||
|
||||
You can permanently switch the internal USB PHY to work with USB_OTG peripheral instead of USB_SERIAL_JTAG by burning ``USB_PHY_SEL`` eFuse. See ESP32-S3 Technical Reference Manual for more details about USB_SERIAL_JTAG and USB_OTG.
|
||||
|
||||
Note however that USB_SERIAL_JTAG also provides a CDC console, so enabling the CDC console shouldn't be the primary reason for switching from USB_SERIAL_JTAG to USB_CDC.
|
||||
Note however that USB_SERIAL_JTAG also provides a CDC console, so enabling the CDC console should not be the primary reason for switching from USB_SERIAL_JTAG to USB_CDC.
|
||||
|
||||
|
||||
Software Configuration
|
||||
|
@ -64,14 +64,14 @@ Once the initial upload is done, the application will start up and a USB CDC por
|
|||
The port name may change after the initial upload, so check the port list again before running ``idf.py monitor``.
|
||||
|
||||
|
||||
Initial upload using the ROM download mode, over USB CDC
|
||||
Initial Upload Using the ROM Download Mode, over USB CDC
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
* Place {IDF_TARGET_NAME} into download mode. To do this, keep GPIO0 low while toggling reset. On many development boards, the "Boot" button is connected to GPIO0, and you can press "Reset" button while holding "Boot".
|
||||
* A serial port will appear in the system. On most operating systems (Windows 8 and later, Linux, macOS) driver installation is not required. Find the port name using Device Manager (Windows) or by listing ``/dev/ttyACM*`` devices on Linux or ``/dev/cu*`` devices on macOS.
|
||||
* Run ``idf.py flash -p PORT`` to upload the application, with ``PORT`` determined in the previous step.
|
||||
|
||||
Initial upload using the ROM download mode, over USB DFU
|
||||
Initial Upload Using the ROM Download Mode, over USB DFU
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
* Place {IDF_TARGET_NAME} into download mode. To do this, keep GPIO0 low while toggling reset. On many development boards, the "Boot" button is connected to GPIO0, and you can press "Reset" button while holding "Boot".
|
||||
|
@ -79,7 +79,7 @@ Initial upload using the ROM download mode, over USB DFU
|
|||
|
||||
See :ref:`api_guide_dfu_flash` for details about DFU flashing.
|
||||
|
||||
Initial upload using UART
|
||||
Initial Upload Using UART
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
On development boards with a USB-UART bridge, upload the application over UART: ``idf.py flash -p PORT`` where ``PORT`` is the name of the serial port provided by the USB-UART bridge.
|
||||
|
@ -110,5 +110,5 @@ There are several limitations to the USB console feature. These may or may not b
|
|||
* USB descriptors used by the ROM CDC stack may be different from the descriptors used by TinyUSB.
|
||||
* When developing applications which use USB peripheral, it is very likely that USB functionality will not work or will not fully work at some moments during development. This can be due to misconfigured USB descriptors, errors in the USB stack usage, or other reasons. In this case, using the UART console for flashing and monitoring provides a much better development experience.
|
||||
|
||||
7. When debugging the application using JTAG, USB CDC may stop working if the CPU is stopped on a breakpoint. USB CDC operation relies on interrupts from the USB peripheral being serviced periodically. If the host computer doesn't receive valid responses from the USB device side for some time, it may decide to disconnect the device. The actual time depends on the OS and the driver, and ranges from a few hundred milliseconds to a few seconds.
|
||||
7. When debugging the application using JTAG, USB CDC may stop working if the CPU is stopped on a breakpoint. USB CDC operation relies on interrupts from the USB peripheral being serviced periodically. If the host computer does not receive valid responses from the USB device side for some time, it may decide to disconnect the device. The actual time depends on the OS and the driver, and ranges from a few hundred milliseconds to a few seconds.
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@ Wi-Fi Driver
|
|||
|
||||
{IDF_TARGET_NAME} Wi-Fi Feature List
|
||||
------------------------------------
|
||||
|
||||
The following features are supported:
|
||||
|
||||
.. only:: esp32 or esp32s2 or esp32c3 or esp32s3
|
||||
|
@ -68,33 +69,40 @@ How To Write a Wi-Fi Application
|
|||
|
||||
Preparation
|
||||
+++++++++++
|
||||
|
||||
Generally, the most effective way to begin your own Wi-Fi application is to select an example which is similar to your own application, and port the useful part into your project. It is not a MUST, but it is strongly recommended that you take some time to read this article first, especially if you want to program a robust Wi-Fi application.
|
||||
|
||||
This article is supplementary to the Wi-Fi APIs/Examples. It describes the principles of using the Wi-Fi APIs, the limitations of the current Wi-Fi API implementation, and the most common pitfalls in using Wi-Fi. This article also reveals some design details of the Wi-Fi driver. We recommend you to select an :example:`example <wifi>`.
|
||||
|
||||
Setting Wi-Fi Compile-time Options
|
||||
++++++++++++++++++++++++++++++++++++
|
||||
|
||||
Refer to `Wi-Fi Menuconfig`_.
|
||||
|
||||
Init Wi-Fi
|
||||
+++++++++++
|
||||
|
||||
Refer to `{IDF_TARGET_NAME} Wi-Fi station General Scenario`_ and `{IDF_TARGET_NAME} Wi-Fi AP General Scenario`_.
|
||||
|
||||
Start/Connect Wi-Fi
|
||||
++++++++++++++++++++
|
||||
|
||||
Refer to `{IDF_TARGET_NAME} Wi-Fi station General Scenario`_ and `{IDF_TARGET_NAME} Wi-Fi AP General Scenario`_.
|
||||
|
||||
Event-Handling
|
||||
++++++++++++++
|
||||
Generally, it is easy to write code in "sunny-day" scenarios, such as `WIFI_EVENT_STA_START`_ and `WIFI_EVENT_STA_CONNECTED`_. The hard part is to write routines in "rainy-day" scenarios, such as `WIFI_EVENT_STA_DISCONNECTED`_. Good handling of "rainy-day" scenarios is fundamental to robust Wi-Fi applications. Refer to `{IDF_TARGET_NAME} Wi-Fi Event Description`_, `{IDF_TARGET_NAME} Wi-Fi station General Scenario`_, and `{IDF_TARGET_NAME} Wi-Fi AP General Scenario`_. See also the :doc:`overview of the Event Loop Library in ESP-IDF<../api-reference/system/esp_event>`.
|
||||
|
||||
Generally, it is easy to write code in "sunny-day" scenarios, such as `WIFI_EVENT_STA_START`_ and `WIFI_EVENT_STA_CONNECTED`_. The hard part is to write routines in "rainy-day" scenarios, such as `WIFI_EVENT_STA_DISCONNECTED`_. Good handling of "rainy-day" scenarios is fundamental to robust Wi-Fi applications. Refer to `{IDF_TARGET_NAME} Wi-Fi Event Description`_, `{IDF_TARGET_NAME} Wi-Fi station General Scenario`_, and `{IDF_TARGET_NAME} Wi-Fi AP General Scenario`_. See also the :doc:`overview of the Event Loop Library in ESP-IDF <../api-reference/system/esp_event>`.
|
||||
|
||||
Write Error-Recovery Routines Correctly at All Times
|
||||
++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
Just like the handling of "rainy-day" scenarios, a good error-recovery routine is also fundamental to robust Wi-Fi applications. Refer to `{IDF_TARGET_NAME} Wi-Fi API Error Code`_.
|
||||
|
||||
|
||||
{IDF_TARGET_NAME} Wi-Fi API Error Code
|
||||
--------------------------------------
|
||||
|
||||
All of the {IDF_TARGET_NAME} Wi-Fi APIs have well-defined return values, namely, the error code. The error code can be categorized into:
|
||||
|
||||
- No errors, e.g., :c:macro:`ESP_OK` means that the API returns successfully.
|
||||
|
@ -126,6 +134,7 @@ Initializing or getting the entire structure is very important, because most of
|
|||
|
||||
{IDF_TARGET_NAME} Wi-Fi Programming Model
|
||||
-----------------------------------------
|
||||
|
||||
The {IDF_TARGET_NAME} Wi-Fi programming model is depicted as follows:
|
||||
|
||||
.. blockdiag::
|
||||
|
@ -180,10 +189,12 @@ Wi-Fi event handling is based on the :doc:`esp_event library <../api-reference/s
|
|||
|
||||
WIFI_EVENT_WIFI_READY
|
||||
++++++++++++++++++++++++++++++++++++
|
||||
|
||||
The Wi-Fi driver will never generate this event, which, as a result, can be ignored by the application event callback. This event may be removed in future releases.
|
||||
|
||||
WIFI_EVENT_SCAN_DONE
|
||||
++++++++++++++++++++++++++++++++++++
|
||||
|
||||
The scan-done event is triggered by :cpp:func:`esp_wifi_scan_start()` and will arise in the following scenarios:
|
||||
|
||||
- The scan is completed, e.g., the target AP is found successfully, or all channels have been scanned.
|
||||
|
@ -200,18 +211,22 @@ Refer to `{IDF_TARGET_NAME} Wi-Fi Scan`_ for a more detailed description.
|
|||
|
||||
WIFI_EVENT_STA_START
|
||||
++++++++++++++++++++++++++++++++++++
|
||||
|
||||
If :cpp:func:`esp_wifi_start()` returns :c:macro:`ESP_OK` and the current Wi-Fi mode is station or station/AP, then this event will arise. Upon receiving this event, the event task will initialize the LwIP network interface (netif). Generally, the application event callback needs to call :cpp:func:`esp_wifi_connect()` to connect to the configured AP.
|
||||
|
||||
WIFI_EVENT_STA_STOP
|
||||
++++++++++++++++++++++++++++++++++++
|
||||
|
||||
If :cpp:func:`esp_wifi_stop()` returns :c:macro:`ESP_OK` and the current Wi-Fi mode is station or station/AP, then this event will arise. Upon receiving this event, the event task will release the station's IP address, stop the DHCP client, remove TCP/UDP-related connections, and clear the LwIP station netif, etc. The application event callback generally does not need to do anything.
|
||||
|
||||
WIFI_EVENT_STA_CONNECTED
|
||||
++++++++++++++++++++++++++++++++++++
|
||||
|
||||
If :cpp:func:`esp_wifi_connect()` returns :c:macro:`ESP_OK` and the station successfully connects to the target AP, the connection event will arise. Upon receiving this event, the event task starts the DHCP client and begins the DHCP process of getting the IP address. Then, the Wi-Fi driver is ready for sending and receiving data. This moment is good for beginning the application work, provided that the application does not depend on LwIP, namely the IP address. However, if the application is LwIP-based, then you need to wait until the *got ip* event comes in.
|
||||
|
||||
WIFI_EVENT_STA_DISCONNECTED
|
||||
++++++++++++++++++++++++++++++++++++
|
||||
|
||||
This event can be generated in the following scenarios:
|
||||
|
||||
- When :cpp:func:`esp_wifi_disconnect()` or :cpp:func:`esp_wifi_stop()` is called and the station is already connected to the AP.
|
||||
|
@ -236,6 +251,7 @@ In above scenarios, ideally, the application sockets and the network layer shoul
|
|||
|
||||
IP_EVENT_STA_GOT_IP
|
||||
++++++++++++++++++++++++++++++++++++
|
||||
|
||||
This event arises when the DHCP client successfully gets the IPV4 address from the DHCP server, or when the IPV4 address is changed. The event means that everything is ready and the application can begin its tasks (e.g., creating sockets).
|
||||
|
||||
The IPV4 may be changed because of the following reasons:
|
||||
|
@ -250,10 +266,12 @@ The socket is based on the IPV4 address, which means that, if the IPV4 changes,
|
|||
|
||||
IP_EVENT_GOT_IP6
|
||||
++++++++++++++++++++++++++++++++++++
|
||||
|
||||
This event arises when the IPV6 SLAAC support auto-configures an address for the {IDF_TARGET_NAME}, or when this address changes. The event means that everything is ready and the application can begin its tasks, e.g., creating sockets.
|
||||
|
||||
IP_EVENT_STA_LOST_IP
|
||||
++++++++++++++++++++++++++++++++++++
|
||||
|
||||
This event arises when the IPV4 address becomes invalid.
|
||||
|
||||
IP_EVENT_STA_LOST_IP does not arise immediately after the Wi-Fi disconnects. Instead, it starts an IPV4 address lost timer. If the IPV4 address is got before ip lost timer expires, IP_EVENT_STA_LOST_IP does not happen. Otherwise, the event arises when the IPV4 address lost timer expires.
|
||||
|
@ -262,18 +280,22 @@ Generally, the application can ignore this event, because it is just a debug eve
|
|||
|
||||
WIFI_EVENT_AP_START
|
||||
++++++++++++++++++++++++++++++++++++
|
||||
|
||||
Similar to `WIFI_EVENT_STA_START`_.
|
||||
|
||||
WIFI_EVENT_AP_STOP
|
||||
++++++++++++++++++++++++++++++++++++
|
||||
|
||||
Similar to `WIFI_EVENT_STA_STOP`_.
|
||||
|
||||
WIFI_EVENT_AP_STACONNECTED
|
||||
++++++++++++++++++++++++++++++++++++
|
||||
|
||||
Every time a station is connected to {IDF_TARGET_NAME} AP, the `WIFI_EVENT_AP_STACONNECTED`_ will arise. Upon receiving this event, the event task will do nothing, and the application callback can also ignore it. However, you may want to do something, for example, to get the info of the connected STA.
|
||||
|
||||
WIFI_EVENT_AP_STADISCONNECTED
|
||||
++++++++++++++++++++++++++++++++++++
|
||||
|
||||
This event can happen in the following scenarios:
|
||||
|
||||
- The application calls :cpp:func:`esp_wifi_disconnect()`, or :cpp:func:`esp_wifi_deauth_sta()`, to manually disconnect the station.
|
||||
|
@ -300,6 +322,7 @@ The `WIFI_EVENT_CONNECTIONLESS_MODULE_WAKE_INTERVAL_START`_ will arise at the st
|
|||
|
||||
{IDF_TARGET_NAME} Wi-Fi Station General Scenario
|
||||
------------------------------------------------
|
||||
|
||||
Below is a "big scenario" which describes some small scenarios in station mode:
|
||||
|
||||
.. seqdiag::
|
||||
|
@ -358,6 +381,7 @@ Below is a "big scenario" which describes some small scenarios in station mode:
|
|||
|
||||
1. Wi-Fi/LwIP Init Phase
|
||||
++++++++++++++++++++++++++++++
|
||||
|
||||
- s1.1: The main task calls :cpp:func:`esp_netif_init()` to create an LwIP core task and initialize LwIP-related work.
|
||||
|
||||
- s1.2: The main task calls :cpp:func:`esp_event_loop_create()` to create a system Event task and initialize an application event's callback function. In the scenario above, the application event's callback function does nothing but relaying the event to the application task.
|
||||
|
@ -372,6 +396,7 @@ Step 1.1 ~ 1.5 is a recommended sequence that initializes a Wi-Fi-/LwIP-based ap
|
|||
|
||||
2. Wi-Fi Configuration Phase
|
||||
+++++++++++++++++++++++++++++++
|
||||
|
||||
Once the Wi-Fi driver is initialized, you can start configuring the Wi-Fi driver. In this scenario, the mode is station, so you may need to call :cpp:func:`esp_wifi_set_mode` (WIFI_MODE_STA) to configure the Wi-Fi mode as station. You can call other `esp_wifi_set_xxx` APIs to configure more settings, such as the protocol mode, the country code, and the bandwidth. Refer to `{IDF_TARGET_NAME} Wi-Fi Configuration`_.
|
||||
|
||||
Generally, the Wi-Fi driver should be configured before the Wi-Fi connection is set up. But this is **NOT** mandatory, which means that you can configure the Wi-Fi connection anytime, provided that the Wi-Fi driver is initialized successfully. However, if the configuration does not need to change after the Wi-Fi connection is set up, you should configure the Wi-Fi driver at this stage, because the configuration APIs (such as :cpp:func:`esp_wifi_set_protocol()`) will cause the Wi-Fi to reconnect, which may not be desirable.
|
||||
|
@ -380,12 +405,14 @@ If the Wi-Fi NVS flash is enabled by menuconfig, all Wi-Fi configuration in this
|
|||
|
||||
3. Wi-Fi Start Phase
|
||||
++++++++++++++++++++++++++++++++
|
||||
|
||||
- s3.1: Call :cpp:func:`esp_wifi_start()` to start the Wi-Fi driver.
|
||||
- s3.2: The Wi-Fi driver posts `WIFI_EVENT_STA_START`_ to the event task; then, the event task will do some common things and will call the application event callback function.
|
||||
- s3.3: The application event callback function relays the `WIFI_EVENT_STA_START`_ to the application task. We recommend that you call :cpp:func:`esp_wifi_connect()`. However, you can also call :cpp:func:`esp_wifi_connect()` in other phrases after the `WIFI_EVENT_STA_START`_ arises.
|
||||
|
||||
4. Wi-Fi Connect Phase
|
||||
+++++++++++++++++++++++++++++++++
|
||||
|
||||
- s4.1: Once :cpp:func:`esp_wifi_connect()` is called, the Wi-Fi driver will start the internal scan/connection process.
|
||||
|
||||
- s4.2: If the internal scan/connection process is successful, the `WIFI_EVENT_STA_CONNECTED`_ will be generated. In the event task, it starts the DHCP client, which will finally trigger the DHCP process.
|
||||
|
@ -403,6 +430,7 @@ In step 4.2, the Wi-Fi connection may fail because, for example, the password is
|
|||
|
||||
6. Wi-Fi Disconnect Phase
|
||||
+++++++++++++++++++++++++++++++++
|
||||
|
||||
- s6.1: When the Wi-Fi connection is disrupted, e.g., the AP is powered off or the RSSI is poor, `WIFI_EVENT_STA_DISCONNECTED`_ will arise. This event may also arise in phase 3. Here, the event task will notify the LwIP task to clear/remove all UDP/TCP connections. Then, all application sockets will be in a wrong status. In other words, no socket can work properly when this event happens.
|
||||
- s6.2: In the scenario described above, the application event callback function relays `WIFI_EVENT_STA_DISCONNECTED`_ to the application task. The recommended actions are: 1) call :cpp:func:`esp_wifi_connect()` to reconnect the Wi-Fi, 2) close all sockets, and 3) re-create them if necessary. For details, please refer to `WIFI_EVENT_STA_DISCONNECTED`_.
|
||||
|
||||
|
@ -423,6 +451,7 @@ In step 4.2, the Wi-Fi connection may fail because, for example, the password is
|
|||
|
||||
{IDF_TARGET_NAME} Wi-Fi AP General Scenario
|
||||
---------------------------------------------
|
||||
|
||||
Below is a "big scenario" which describes some small scenarios in AP mode:
|
||||
|
||||
.. seqdiag::
|
||||
|
@ -604,6 +633,7 @@ Scan-Done Event Handling Phase
|
|||
|
||||
Scan All APs on All Channels (Background)
|
||||
++++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
Scenario:
|
||||
|
||||
.. seqdiag::
|
||||
|
@ -640,6 +670,7 @@ The scenario above is an all-channel background scan. Compared to `Scan All APs
|
|||
|
||||
Scan for Specific AP on All Channels
|
||||
+++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
Scenario:
|
||||
|
||||
.. seqdiag::
|
||||
|
@ -690,6 +721,7 @@ If the block parameter of :cpp:func:`esp_wifi_scan_start()` is true, then the sc
|
|||
|
||||
Parallel Scan
|
||||
+++++++++++++
|
||||
|
||||
Two application tasks may call :cpp:func:`esp_wifi_scan_start()` at the same time, or the same application task calls :cpp:func:`esp_wifi_scan_start()` before it gets a scan-done event. Both scenarios can happen. **However, the Wi-Fi driver does not support multiple concurrent scans adequately. As a result, concurrent scans should be avoided.** Support for concurrent scan will be enhanced in future releases, as the {IDF_TARGET_NAME}'s Wi-Fi functionality improves continuously.
|
||||
|
||||
Scan When Wi-Fi Is Connecting
|
||||
|
@ -1170,7 +1202,7 @@ The table below shows the Wi-Fi reason-code may related to wrong password.
|
|||
- This may related to wrong password in the two scenarios:
|
||||
|
||||
- Setting password when STA connecting to an unencrypted AP.
|
||||
- Doesn't setting password when STA connecting to an encrypted AP.
|
||||
- Does not set password when STA connecting to an encrypted AP.
|
||||
* - HANDSHAKE_TIMEOUT
|
||||
- 204
|
||||
- Four-way handshake fails.
|
||||
|
@ -1664,7 +1696,7 @@ Detailed information on creating certificates and how to run wpa2_enterprise exa
|
|||
|
||||
Multiple NAN devices in the vicinity will form a NAN cluster which allows them to communicate with each other. NAN devices in a cluster synchronise their clocks and listen to each other periodically on Channel 6. Devices can advertise (Publish) or seek for (Subscribe) services within their NAN Cluster using Service Discovery protocols. Matching of services is done by service name and optionally matching filters. Once a Subscriber gets a match with a Publisher, it can either send a message (Follow-up) or establish a datapath (NDP) with the Publisher. After NDP is setup both devices will obtain an IPv6 address and can use it for communication.
|
||||
|
||||
Please note that NAN Datapath security is not supported i.e. the data packets will go out unencrypted. NAN uses a separate interface for Discovery and Datapath, which is other than that used for STA and AP. NAN operates in standalone mode, which means co-existence with STA or AP interface is not supported.
|
||||
Please note that NAN Datapath security is not supported i.e., the data packets will go out unencrypted. NAN uses a separate interface for Discovery and Datapath, which is other than that used for STA and AP. NAN operates in standalone mode, which means co-existence with STA or AP interface is not supported.
|
||||
|
||||
Refer to ESP-IDF examples :idf_file:`examples/wifi/wifi_aware/nan_publisher/README.md` and :idf_file:`examples/wifi/wifi_aware/nan_subscriber/README.md` to setup a NAN Publisher and Subscriber.
|
||||
|
||||
|
@ -1810,14 +1842,14 @@ At the start of `Interval` time, RF, PHY, BB would be turned on and kept for `Wi
|
|||
| | 1 - maximum | default mode | used periodically (Window < Interval) / used all time (Window ≥ Interval) |
|
||||
+--------+-------------+-----------------------------------------------------+---------------------------------------------------------------------------+
|
||||
|
||||
Default mode
|
||||
Default Mode
|
||||
*******************************
|
||||
|
||||
If `Interval` is ``ESP_WIFI_CONNECTIONLESS_INTERVAL_DEFAULT_MODE`` with non-zero `Window`, Connectionless Modules Power-saving would work in default mode.
|
||||
|
||||
In default mode, RF, PHY, BB would be kept on if no coexistence with non-Wi-Fi protocol.
|
||||
|
||||
With coexistence, RF, PHY, BB resources are allocated by coexistence module to Wi-Fi connectionless module and non-Wi-Fi module, using time-division method. In default mode, Wi-Fi connectionless module is allowed to use RF, BB, PHY periodically under a stable performance.
|
||||
With coexistence, RF, PHY, BB resources are allocated by coexistence module to Wi-Fi connectionless module and non-Wi-Fi module, using time-division method. In default mode, Wi-Fi connectionless module is allowed to use RF, BB, PHY periodically under a stable performance.
|
||||
|
||||
Its recommended to configure Connectionless Modules Power-saving to default mode if there is Wi-Fi connectionless module coexists with non-Wi-Fi module.
|
||||
|
||||
|
@ -2236,15 +2268,15 @@ Generally, following steps can be taken to configure the multiple antennas:
|
|||
|
||||
When imaginary part and real part data of sub-carrier are used, please refer to the table below.
|
||||
|
||||
+----------------+-------------------+------------------------------+-------------------------+
|
||||
| PHY standard | Sub-carrier range | Pilot sub-carrier | Sub-carrier(total/data) |
|
||||
+================+===================+==============================+=========================+
|
||||
| 802.11a/g | -26 to +26 | -21, -7, +7, +21 | 52 total, 48 usable |
|
||||
+----------------+-------------------+------------------------------+-------------------------+
|
||||
| 802.11n, 20MHz | -28 to +28 | -21, -7, +7, +21 | 56 total, 52 usable |
|
||||
+----------------+-------------------+------------------------------+-------------------------+
|
||||
| 802.11n, 40MHz | -57 to +57 | -53, -25, -11, +11, +25, +53 | 114 total, 108 usable |
|
||||
+----------------+-------------------+------------------------------+-------------------------+
|
||||
+-----------------+-------------------+------------------------------+--------------------------+
|
||||
| PHY standard | Sub-carrier range | Pilot sub-carrier | Sub-carrier (total/data) |
|
||||
+=================+===================+==============================+==========================+
|
||||
| 802.11a/g | -26 to +26 | -21, -7, +7, +21 | 52 total, 48 usable |
|
||||
+-----------------+-------------------+------------------------------+--------------------------+
|
||||
| 802.11n, 20 MHz | -28 to +28 | -21, -7, +7, +21 | 56 total, 52 usable |
|
||||
+-----------------+-------------------+------------------------------+--------------------------+
|
||||
| 802.11n, 40 MHz | -57 to +57 | -53, -25, -11, +11, +25, +53 | 114 total, 108 usable |
|
||||
+-----------------+-------------------+------------------------------+--------------------------+
|
||||
|
||||
.. note::
|
||||
|
||||
|
@ -3657,6 +3689,7 @@ The diagram shows the configuration of the Wi-Fi internal buffer.
|
|||
|
||||
Wi-Fi NVS Flash
|
||||
+++++++++++++++++++++
|
||||
|
||||
If the Wi-Fi NVS flash is enabled, all Wi-Fi configurations set via the Wi-Fi APIs will be stored into flash, and the Wi-Fi driver will start up with these configurations the next time it powers on/reboots. However, the application can choose to disable the Wi-Fi NVS flash if it does not need to store the configurations into persistent memory, or has its own persistent storage, or simply due to debugging reasons, etc.
|
||||
|
||||
Wi-Fi Aggregate MAC Protocol Data Unit (AMPDU)
|
||||
|
|
|
@ -1,13 +1,14 @@
|
|||
******************************
|
||||
Espressif Wireshark User Guide
|
||||
******************************
|
||||
|
||||
:link_to_translation:`zh_CN:[中文]`
|
||||
|
||||
===========
|
||||
1. Overview
|
||||
===========
|
||||
|
||||
1.1 What is Wireshark?
|
||||
1.1 What Is Wireshark?
|
||||
======================
|
||||
|
||||
`Wireshark <https://www.wireshark.org>`_ (originally named "Ethereal") is a network packet analyzer that captures network packets and displays the packet data as detailed as possible. It uses WinPcap as its interface to directly capture network traffic going through a network interface controller (NIC).
|
||||
|
@ -60,13 +61,13 @@ The main features of Wireshark are as follows:
|
|||
|
||||
* Calculates statistics
|
||||
|
||||
* … and a lot more!
|
||||
* ... and a lot more!
|
||||
|
||||
|
||||
1.4 Wireshark Can or Can't Do
|
||||
1.4 Wireshark Can or Cannot Do
|
||||
==============================
|
||||
|
||||
* **Live capture from different network media**.
|
||||
* **Live capture from different network media**.
|
||||
|
||||
Wireshark can capture traffic from different network media, including wireless LAN.
|
||||
|
||||
|
@ -92,7 +93,7 @@ The main features of Wireshark are as follows:
|
|||
|
||||
|
||||
==========================
|
||||
2. Where to Get Wireshark
|
||||
1. Where to Get Wireshark
|
||||
==========================
|
||||
|
||||
You can get Wireshark from the official website: https://www.wireshark.org/download.html
|
||||
|
@ -109,7 +110,7 @@ Wireshark can run on various operating systems. Please download the correct vers
|
|||
|
||||
**a) Start Wireshark**
|
||||
|
||||
On Linux, you can run the shell script provided below. It starts Wireshark, then configures NIC and the channel for packet capture.
|
||||
On Linux, you can run the shell script provided below. It starts Wireshark, then configures NIC and the channel for packet capture.
|
||||
|
||||
::
|
||||
|
||||
|
@ -242,5 +243,5 @@ On Linux, go to *File* -> *Export Packet Dissections* -> *As Plain Text File* to
|
|||
|
||||
Please note that *All packets*, *Displayed* and *All expanded* must be selected.
|
||||
|
||||
By default, Wireshark saves the captured packet in a libpcap file. You can also save the file in other formats, e.g. txt, to analyze it in other tools.
|
||||
By default, Wireshark saves the captured packet in a libpcap file. You can also save the file in other formats, e.g., txt, to analyze it in other tools.
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
应用层跟踪库
|
||||
============
|
||||
|
||||
:link_to_translation:`en:[English]`
|
||||
|
||||
概述
|
||||
|
@ -56,11 +57,13 @@ ESP-IDF 中提供了应用层跟踪功能,用于分析应用程序的行为。
|
|||
|
||||
4. *UART TX message size* (:ref:`CONFIG_APPTRACE_UART_TX_MSG_size`)。要传输的单条消息的最大尺寸。
|
||||
|
||||
|
||||
如何使用此库
|
||||
--------------
|
||||
|
||||
该库提供了用于在主机和 {IDF_TARGET_NAME} 之间传输任意数据的 API。在 menuconfig 中启用该库后,目标应用程序的跟踪模块会在系统启动时自动初始化。因此,用户需要做的就是调用相应的 API 来发送、接收或者刷新数据。
|
||||
|
||||
|
||||
.. _app_trace-application-specific-tracing:
|
||||
|
||||
特定应用程序的跟踪
|
||||
|
@ -257,7 +260,6 @@ Start 子命令的语法:
|
|||
|
||||
.. _app_trace-logging-to-host:
|
||||
|
||||
|
||||
记录日志到主机
|
||||
^^^^^^^^^^^^^^
|
||||
|
||||
|
@ -318,6 +320,7 @@ Log Trace Processor 命令选项
|
|||
``--no-errors``, ``-n``
|
||||
不打印错误信息。
|
||||
|
||||
|
||||
.. _app_trace-system-behaviour-analysis-with-segger-systemview:
|
||||
|
||||
基于 SEGGER SystemView 的系统行为分析
|
||||
|
@ -335,7 +338,7 @@ ESP-IDF 中另一个基于应用层跟踪库的实用功能是系统级跟踪,
|
|||
|
||||
2. *{IDF_TARGET_NAME} timer to use as SystemView timestamp source* (:ref:`CONFIG_APPTRACE_SV_TS_SOURCE`)。选择 SystemView 事件使用的时间戳来源。在单核模式下,使用 {IDF_TARGET_NAME} 内部的循环计数器生成时间戳,其最大的工作频率是 240 MHz(时间戳粒度大约为 4 ns)。在双核模式下,使用工作在 40 MHz 的外部定时器,因此时间戳粒度为 25 ns。
|
||||
|
||||
3. 可以单独启用或禁用的 SystemView 事件集合(``CONFIG_APPTRACE_SV_EVT_XXX``):
|
||||
3. 可以单独启用或禁用的 SystemView 事件集合 (``CONFIG_APPTRACE_SV_EVT_XXX``):
|
||||
|
||||
- Trace Buffer Overflow Event
|
||||
- ISR Enter Event
|
||||
|
@ -383,13 +386,13 @@ Start 子命令语法:
|
|||
``poll_period``
|
||||
跟踪数据的轮询周期(单位:毫秒)。如果该值大于 0,则命令以非阻塞的模式运行。默认为 1 毫秒。
|
||||
``trace_size``
|
||||
最多要收集的数据量(单位:字节)。当收到指定数量的数据后,将停止跟踪。默认值是 -1 (禁用跟踪大小停止触发器)。
|
||||
最多要收集的数据量(单位:字节)。当收到指定数量的数据后,将停止跟踪。默认值是 -1(禁用跟踪大小停止触发器)。
|
||||
``stop_tmo``
|
||||
空闲超时(单位:秒)。如果指定的时间内没有数据,将停止跟踪。默认值是 -1(禁用跟踪超时停止触发器)。
|
||||
|
||||
.. note::
|
||||
|
||||
如果 ``poll_period`` 为 0,则在跟踪停止之前,OpenOCD 的 telnet 命令行将不可用。您需要复位板卡或者在 OpenOCD 的窗口(非 telnet 会话窗口)输入 Ctrl+C 命令来手动停止跟踪。另一个办法是设置 ``trace_size``,等到收集满指定数量的数据后自动停止跟踪。
|
||||
如果 ``poll_period`` 为 0,则在跟踪停止之前,OpenOCD 的 telnet 命令行将不可用。你需要复位板卡,或者在 OpenOCD 的窗口(非 telnet 会话窗口)输入 Ctrl+C 命令,手动停止跟踪。另一个办法是设置 ``trace_size``,等到收集满指定数量的数据后自动停止跟踪。
|
||||
|
||||
命令使用示例:
|
||||
|
||||
|
@ -448,7 +451,7 @@ Start 子命令语法:
|
|||
|
||||
.. note::
|
||||
|
||||
如果您在可视化方面遇到了问题(未显示数据或者缩放操作异常),您可以尝试删除当前的信号层次结构,再双击必要的文件或端口。Eclipse 会请求您创建新的信号层次结构。
|
||||
如果你在可视化方面遇到了问题(未显示数据或者缩放操作异常),可以尝试删除当前的信号层次结构,再双击必要的文件或端口。Eclipse 会请求创建新的信号层次结构。
|
||||
|
||||
|
||||
.. _app_trace-gcov-source-code-coverage:
|
||||
|
@ -469,6 +472,7 @@ Gcov 和 Gcovr 简介
|
|||
|
||||
3. Gcov 或 Gcovr 可用于生成基于 ``.gcno``、``.gcda`` 和源文件的代码覆盖。Gcov 将以 ``.gcov`` 文件的形式为每个源文件生成基于文本的覆盖报告,而 Gcovr 将以 HTML 格式生成覆盖报告。
|
||||
|
||||
|
||||
ESP-IDF 中的 Gcov 和 Gcovr 应用
|
||||
"""""""""""""""""""""""""""""""""
|
||||
|
||||
|
@ -478,6 +482,7 @@ ESP-IDF 中的 Gcov 和 Gcovr 应用
|
|||
2. :ref:`app_trace-gcov-dumping-data`
|
||||
3. :ref:`app_trace-gcov-generate-report`
|
||||
|
||||
|
||||
.. _app_trace-gcov-setup-project:
|
||||
|
||||
为 Gcov 设置项目
|
||||
|
@ -493,6 +498,7 @@ ESP-IDF 中的 Gcov 和 Gcovr 应用
|
|||
|
||||
当一个源文件用 ``--coverage`` 选项编译时(例如 ``gcov_example.c``),编译器会在项目的构建目录下生成 ``gcov_example.gcno`` 文件。
|
||||
|
||||
|
||||
项目配置
|
||||
~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
@ -501,6 +507,7 @@ ESP-IDF 中的 Gcov 和 Gcovr 应用
|
|||
- 通过 :ref:`CONFIG_APPTRACE_DESTINATION1` 选项选择 ``Trace Memory`` 来启用应用程序跟踪模块。
|
||||
- 通过 :ref:`CONFIG_APPTRACE_GCOV_ENABLE` 选项启用 Gcov 主机。
|
||||
|
||||
|
||||
.. _app_trace-gcov-dumping-data:
|
||||
|
||||
转储代码覆盖数据
|
||||
|
@ -508,7 +515,7 @@ ESP-IDF 中的 Gcov 和 Gcovr 应用
|
|||
|
||||
一旦项目使用 ``--coverage`` 选项编译并烧录到目标机上,在应用程序运行时,代码覆盖数据将存储在目标机内部(即在跟踪存储器中)。将代码覆盖率数据从目标机转移到主机上的过程称为转储。
|
||||
|
||||
覆盖率数据的转储通过 OpenOCD 进行(关于如何设置和运行 OpenOCD,请参考 :doc:`JTAG调试 <../api-guides/jtag-debugging/index>`)。由于该过程需要通过向 OpenOCD 发出命令来触发转储,因此必须打开 telnet 会话,以向 OpenOCD 发出这些命令(运行 ``telnet localhost 4444``)。GDB 也可以代替 telnet 来向 OpenOCD 发出命令,但是所有从 GDB 发出的命令都需要以 ``mon <oocd_command>`` 为前缀。
|
||||
覆盖率数据的转储通过 OpenOCD 进行(关于如何设置和运行 OpenOCD,请参考 :doc:`JTAG 调试 <../api-guides/jtag-debugging/index>`)。由于该过程需要通过向 OpenOCD 发出命令来触发转储,因此必须打开 telnet 会话,以向 OpenOCD 发出这些命令(运行 ``telnet localhost 4444``)。GDB 也可以代替 telnet 来向 OpenOCD 发出命令,但是所有从 GDB 发出的命令都需要以 ``mon <oocd_command>`` 为前缀。
|
||||
|
||||
当目标机转储代码覆盖数据时,``.gcda`` 文件存储在项目的构建目录中。例如,如果 ``main`` 组件的 ``gcov_example_main.c`` 在编译时使用了 ``--coverage`` 选项,那么转储代码覆盖数据将在 ``build/esp-idf/main/CMakeFiles/__idf_main.dir/gcov_example_main.c.gcda`` 中生成 ``gcov_example_main.gcda`` 文件。注意,编译过程中产生的 ``.gcno`` 文件也放在同一目录下。
|
||||
|
||||
|
@ -519,11 +526,13 @@ ESP-IDF 支持两种将代码覆盖数据从目标机转储到主机的方法:
|
|||
* 运行中实时转储
|
||||
* 硬编码转储
|
||||
|
||||
|
||||
运行中实时转储
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
通过 telnet 会话调用 OpenOCD 命令 ``{IDF_TARGET_NAME} gcov`` 来触发运行时的实时转储。一旦被调用,OpenOCD 将立即抢占 {IDF_TARGET_NAME} 的当前状态,并执行内置的 ESP-IDF Gcov 调试存根函数。调试存根函数将数据转储到主机。完成后,{IDF_TARGET_NAME} 将恢复当前状态。
|
||||
|
||||
|
||||
硬编码转储
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
|
@ -546,6 +555,7 @@ GDB 可以用来在 :cpp:func:`esp_gcov_dump` 上设置断点,然后使用 ``g
|
|||
.. note::
|
||||
注意,所有的 OpenOCD 命令都应该在 GDB 中以 ``mon <oocd_command>`` 方式调用。
|
||||
|
||||
|
||||
.. _app_trace-gcov-generate-report:
|
||||
|
||||
生成代码覆盖报告
|
||||
|
@ -555,12 +565,13 @@ GDB 可以用来在 :cpp:func:`esp_gcov_dump` 上设置断点,然后使用 ``g
|
|||
|
||||
Gcov 和 Gcovr 都可以用来生成代码覆盖报告。安装 Xtensa 工具链时会一起安装 Gcov,但 Gcovr 可能需要单独安装。关于如何使用 Gcov 或 Gcovr,请参考 `Gcov 文档 <https://gcc.gnu.org/onlinedocs/gcc/Gcov.html>`_ 和 `Gcovr 文档 <https://gcovr.com/>`_。
|
||||
|
||||
|
||||
在工程中添加 Gcovr 构建目标
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
用户可以在自己的工程中定义额外的构建目标,从而通过一个简单的构建命令即可更方便地生成报告。
|
||||
|
||||
请在您工程的 ``CMakeLists.txt`` 文件中添加以下内容:
|
||||
请在工程的 ``CMakeLists.txt`` 文件中添加以下内容:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
|
@ -568,7 +579,7 @@ Gcov 和 Gcovr 都可以用来生成代码覆盖报告。安装 Xtensa 工具链
|
|||
idf_create_coverage_report(${CMAKE_CURRENT_BINARY_DIR}/coverage_report)
|
||||
idf_clean_coverage_report(${CMAKE_CURRENT_BINARY_DIR}/coverage_report)
|
||||
|
||||
您可使用以下命令:
|
||||
可使用以下命令:
|
||||
|
||||
* ``cmake --build build/ --target gcovr-report``:在 ``$(BUILD_DIR_BASE)/coverage_report/html`` 目录下生成 HTML 格式代码覆盖报告。
|
||||
* ``cmake --build build/ --target cov-data-clean``:删除所有代码覆盖数据文件。
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
BluFi
|
||||
^^^^^
|
||||
|
||||
:link_to_translation:`en:[English]`
|
||||
|
||||
概览
|
||||
|
@ -18,13 +19,13 @@ BluFi 配网流程包含配置 SoftAP 和配置 Station 两部分。
|
|||
|
||||
下面以配置 Station 为例,介绍了广播、连接、服务发现、协商共享密钥、传输数据、回传连接状态等关键步骤。
|
||||
|
||||
1. {IDF_TARGET_NAME} 开启 GATT Server 模式,发送带有特定 *advertising data* 的广播。该广播不属于 BluFi Profile,您可以按需对其进行自定义。
|
||||
1. {IDF_TARGET_NAME} 开启 GATT Server 模式,发送带有特定 *advertising data* 的广播。该广播不属于 BluFi Profile,可以按需对其进行自定义。
|
||||
|
||||
2. 使用手机应用程序搜索到该广播后,手机将作为 GATT Client 连接 {IDF_TARGET_NAME}。该步骤对具体使用哪款手机应用程序并无特殊要求。
|
||||
|
||||
3. 成功建立 GATT 连接后,手机会向 {IDF_TARGET_NAME} 发送数据帧进行密钥协商(详见 :ref:`frame_formats` )。
|
||||
|
||||
4. {IDF_TARGET_NAME} 收到密钥协商的数据帧后,会按照您自定义的协商方法进行解析。
|
||||
4. {IDF_TARGET_NAME} 收到密钥协商的数据帧后,会按照自定义的协商方法进行解析。
|
||||
|
||||
5. 手机与 {IDF_TARGET_NAME} 进行密钥协商。协商过程可使用 DH/RSA/ECC 等加密算法。
|
||||
|
||||
|
@ -125,7 +126,7 @@ BluFi 中定义的帧格式
|
|||
|
||||
通常情况下,控制帧不包含数据位,ACK 帧类型除外。
|
||||
|
||||
ACK 帧格式(8 bit):
|
||||
ACK 帧格式 (8 bit):
|
||||
|
||||
.. list-table::
|
||||
:header-rows: 1
|
||||
|
@ -233,7 +234,7 @@ ACK 帧格式(8 bit):
|
|||
|
||||
|
||||
|
||||
1.2 数据帧 (二进制:0x1 b’01)
|
||||
1.2 数据帧(二进制:0x1 b’01)
|
||||
|
||||
.. list-table::
|
||||
:header-rows: 1
|
||||
|
@ -488,6 +489,6 @@ UUID
|
|||
|
||||
BluFi Service UUID: 0xFFFF,16 bit
|
||||
|
||||
BluFi (手机 -> {IDF_TARGET_NAME})特性:0xFF01,主要权限:可写
|
||||
BluFi(手机 > {IDF_TARGET_NAME}) 特性:0xFF01,主要权限:可写
|
||||
|
||||
BluFi ({IDF_TARGET_NAME} -> 手机)特性:0xFF02,主要权限:可读可通知
|
||||
BluFi ({IDF_TARGET_NAME} > 手机)特性:0xFF02,主要权限:可读可通知
|
||||
|
|
|
@ -47,7 +47,7 @@ ESP-IDF 软件引导加载程序 (Bootloader) 主要执行以下任务:
|
|||
ESP-IDF V5.1 之前的版本构建的引导加载程序不支持 :ref:`CONFIG_ESP_SYSTEM_ESP32_SRAM1_REGION_AS_IRAM`。使用这些 ESP-IDF 版本的引导加载程序并构建新应用程序时,不应使用该选项。
|
||||
|
||||
|
||||
配置 SPI Flash
|
||||
配置 SPI flash
|
||||
^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
每个 ESP-IDF 应用程序或引导加载程序的二进制文件中都包含一个文件头,其中内置了 :ref:`CONFIG_ESPTOOLPY_FLASHMODE`、:ref:`CONFIG_ESPTOOLPY_FLASHFREQ`、和 :ref:`CONFIG_ESPTOOLPY_FLASHSIZE`。这些是用于在启动时配置 SPI flash。
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
本文档主要介绍 ESP-IDF 构建系统的实现原理以及 ``组件`` 等相关概念。如需了解如何组织和构建新的 ESP-IDF 项目或组件,请阅读本文档。
|
||||
|
||||
|
||||
概述
|
||||
====
|
||||
|
||||
|
@ -20,6 +21,7 @@
|
|||
|
||||
ESP-IDF 可以显式地指定和配置每个组件。在构建项目的时候,构建系统会前往 ESP-IDF 目录、项目目录和用户自定义组件目录(可选)中查找所有组件,允许用户通过文本菜单系统配置 ESP-IDF 项目中用到的每个组件。在所有组件配置结束后,构建系统开始编译整个项目。
|
||||
|
||||
|
||||
概念
|
||||
----
|
||||
|
||||
|
@ -39,6 +41,7 @@ ESP-IDF 可以显式地指定和配置每个组件。在构建项目的时候,
|
|||
|
||||
- 交叉编译工具链并不是项目的组成部分,它应该被安装在系统 PATH 环境变量中。
|
||||
|
||||
|
||||
使用构建系统
|
||||
============
|
||||
|
||||
|
@ -55,12 +58,13 @@ idf.py
|
|||
|
||||
可通过 ``idf.py`` 配置构建系统,具体可参考 :doc:`相关文档 <tools/idf-py>`。
|
||||
|
||||
|
||||
直接使用 CMake
|
||||
--------------
|
||||
|
||||
为了方便,:ref:`idf.py` 已经封装了 CMake_ 命令,但是你愿意,也可以直接调用 CMake。
|
||||
|
||||
.. highlight:: bash
|
||||
.. code-block:: bash
|
||||
|
||||
当 ``idf.py`` 在执行某些操作时,它会打印出其运行的每条命令以便参考。例如运行 ``idf.py build`` 命令与在 bash shell(或者 Windows Command Prompt)中运行以下命令是相同的::
|
||||
|
||||
|
@ -76,8 +80,10 @@ idf.py
|
|||
若在 CMake 中使用 ``ninja`` 或 ``make``,则多数 ``idf.py`` 子命令也会有其对应的目标,例如在构建目录下运行 ``make menuconfig`` 或 ``ninja menuconfig`` 与运行 ``idf.py menuconfig`` 是相同的。
|
||||
|
||||
.. Note::
|
||||
|
||||
如果你已经熟悉了 CMake_,那么可能会发现 ESP-IDF 的 CMake 构建系统不同寻常,为了减少样板文件,该系统封装了 CMake 的许多功能。请参考 :ref:`write-pure-component` 以编写更多 “CMake 风格”的组件。
|
||||
|
||||
|
||||
.. _flash-with-ninja-or-make:
|
||||
|
||||
使用 Ninja/Make 来烧录
|
||||
|
@ -97,13 +103,18 @@ idf.py
|
|||
|
||||
ESPPORT=/dev/ttyUSB0 ninja flash
|
||||
|
||||
.. Note:: 在命令的开头为环境变量赋值属于 Bash shell 的语法,可在 Linux 、macOS 和 Windows 的类 Bash shell 中运行,但在 Windows Command Prompt 中无法运行。
|
||||
.. Note::
|
||||
|
||||
在命令的开头为环境变量赋值属于 Bash shell 的语法,可在 Linux 、macOS 和 Windows 的类 Bash shell 中运行,但在 Windows Command Prompt 中无法运行。
|
||||
|
||||
或::
|
||||
|
||||
make -j3 app-flash ESPPORT=COM4 ESPBAUD=2000000
|
||||
|
||||
.. Note:: 在命令末尾为变量赋值属于 ``make`` 的语法,适用于所有平台的 ``make``。
|
||||
.. Note::
|
||||
|
||||
在命令末尾为变量赋值属于 ``make`` 的语法,适用于所有平台的 ``make``。
|
||||
|
||||
|
||||
在 IDE 中使用 CMake
|
||||
-------------------
|
||||
|
@ -116,6 +127,7 @@ idf.py
|
|||
|
||||
.. _setting-python-interpreter:
|
||||
|
||||
|
||||
设置 Python 解释器
|
||||
------------------
|
||||
|
||||
|
@ -129,12 +141,13 @@ ESP-IDF 适用于 Python 3.8 以上版本。
|
|||
|
||||
如果想在命令行中更优雅地管理 Python 的各个版本,请查看 pyenv_ 或 virtualenv_ 工具,它们会帮助你更改默认的 python 版本。
|
||||
|
||||
|
||||
.. _example-project-structure:
|
||||
|
||||
示例项目
|
||||
========
|
||||
|
||||
.. highlight:: none
|
||||
.. code-block:: none
|
||||
|
||||
示例项目的目录树结构可能如下所示::
|
||||
|
||||
|
@ -170,15 +183,17 @@ ESP-IDF 适用于 Python 3.8 以上版本。
|
|||
|
||||
每个组件还可以包含一个 ``Kconfig`` 文件,它用于定义 ``menuconfig`` 时展示的 :ref:`component-configuration` 选项。某些组件可能还会包含 ``Kconfig.projbuild`` 和 ``project_include.cmake`` 特殊文件,它们用于 :ref:`override_project_config`。
|
||||
|
||||
|
||||
项目 CMakeLists 文件
|
||||
====================
|
||||
|
||||
每个项目都有一个顶层 ``CMakeLists.txt`` 文件,包含整个项目的构建设置。默认情况下,项目 CMakeLists 文件会非常小。
|
||||
|
||||
|
||||
最小 CMakeLists 文件示例
|
||||
------------------------
|
||||
|
||||
.. highlight:: cmake
|
||||
.. code-block:: cmake
|
||||
|
||||
最小项目::
|
||||
|
||||
|
@ -186,6 +201,7 @@ ESP-IDF 适用于 Python 3.8 以上版本。
|
|||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||
project(myProject)
|
||||
|
||||
|
||||
.. _project-mandatory-parts:
|
||||
|
||||
必要部分
|
||||
|
@ -197,6 +213,7 @@ ESP-IDF 适用于 Python 3.8 以上版本。
|
|||
- ``include($ENV{IDF_PATH}/tools/cmake/project.cmake)`` 会导入 CMake 的其余功能来完成配置项目、检索组件等任务。
|
||||
- ``project(myProject)`` 会创建项目本身,并指定项目名称。该名称会作为最终输出的二进制文件的名字,即 ``myProject.elf`` 和 ``myProject.bin``。每个 CMakeLists 文件只能定义一个项目。
|
||||
|
||||
|
||||
.. _optional_project_variable:
|
||||
|
||||
可选的项目变量
|
||||
|
@ -214,6 +231,7 @@ ESP-IDF 适用于 Python 3.8 以上版本。
|
|||
|
||||
请使用 `cmake 中的 set 命令 <cmake set_>`_ 来设置这些变量,如 ``set(VARIABLE "VALUE")``。请注意,``set()`` 命令需放在 ``include(...)`` 之前,``cmake_minimum(...)`` 之后。
|
||||
|
||||
|
||||
.. _rename-main:
|
||||
|
||||
重命名 ``main`` 组件
|
||||
|
@ -231,7 +249,7 @@ ESP-IDF 适用于 Python 3.8 以上版本。
|
|||
|
||||
构建系统设置了一些全局的构建规范(编译标志、定义等),这些规范可用于编译来自所有组件的所有源文件。
|
||||
|
||||
.. highlight:: cmake
|
||||
.. code-block:: cmake
|
||||
|
||||
例如,其中一个默认的构建规范是编译选项 ``Wextra``。假设一个用户想用 ``Wno-extra`` 来覆盖这个选项,
|
||||
应在 ``project()`` 之后进行::
|
||||
|
@ -245,6 +263,7 @@ ESP-IDF 适用于 Python 3.8 以上版本。
|
|||
|
||||
这确保了用户设置的编译选项不会被默认的构建规范所覆盖,因为默认的构建规范是在 ``project()`` 内设置的。
|
||||
|
||||
|
||||
.. _component-directories:
|
||||
|
||||
组件 CMakeLists 文件
|
||||
|
@ -254,6 +273,7 @@ ESP-IDF 适用于 Python 3.8 以上版本。
|
|||
|
||||
组件是 ``COMPONENT_DIRS`` 列表中包含 ``CMakeLists.txt`` 文件的任何目录。
|
||||
|
||||
|
||||
搜索组件
|
||||
--------
|
||||
|
||||
|
@ -261,6 +281,7 @@ ESP-IDF 适用于 Python 3.8 以上版本。
|
|||
|
||||
当 CMake 运行项目配置时,它会记录本次构建包含的组件列表,它可用于调试某些组件的添加/排除。
|
||||
|
||||
|
||||
.. _cmake-components-same-name:
|
||||
|
||||
同名组件
|
||||
|
@ -268,14 +289,17 @@ ESP-IDF 适用于 Python 3.8 以上版本。
|
|||
|
||||
ESP-IDF 在搜索所有待构建的组件时,会按照 ``COMPONENT_DIRS`` 指定的顺序依次进行,这意味着在默认情况下,首先搜索 ESP-IDF 内部组件(``IDF_PATH/components``),然后是 ``EXTRA_COMPONENT_DIRS`` 中的组件,最后是项目组件(``PROJECT_DIR/components``)。如果这些目录中的两个或者多个包含具有相同名字的组件,则使用搜索到的最后一个位置的组件。这就允许将组件复制到项目目录中再修改以覆盖 ESP-IDF 组件,如果使用这种方式,ESP-IDF 目录本身可以保持不变。
|
||||
|
||||
.. 注解:: 如果在现有项目中通过将组件移动到一个新位置来覆盖它,项目不会自动看到新组件的路径。请运行 ``idf.py reconfigure`` 命令后(或删除项目构建文件夹)再重新构建。
|
||||
.. 注解::
|
||||
|
||||
如果在现有项目中通过将组件移动到一个新位置来覆盖它,项目不会自动看到新组件的路径。请运行 ``idf.py reconfigure`` 命令后(或删除项目构建文件夹)再重新构建。
|
||||
|
||||
|
||||
.. _minimum_cmakelists:
|
||||
|
||||
最小组件 CMakeLists 文件
|
||||
--------------------------
|
||||
|
||||
.. highlight:: cmake
|
||||
.. code-block:: cmake
|
||||
|
||||
最小组件 ``CMakeLists.txt`` 文件通过使用 ``idf_component_register`` 将组件添加到构建系统中。
|
||||
|
||||
|
@ -295,6 +319,7 @@ ESP-IDF 在搜索所有待构建的组件时,会按照 ``COMPONENT_DIRS`` 指
|
|||
|
||||
有关更完整的 ``CMakeLists.txt`` 示例,请参阅 `组件依赖示例`_ 和 `组件 CMakeLists 示例`_。
|
||||
|
||||
|
||||
.. _preset_component_variables:
|
||||
|
||||
预设的组件变量
|
||||
|
@ -312,6 +337,7 @@ ESP-IDF 在搜索所有待构建的组件时,会按照 ``COMPONENT_DIRS`` 指
|
|||
- ``CONFIG_*``:项目配置中的每个值在 cmake 中都对应一个以 ``CONFIG_`` 开头的变量。更多详细信息请参阅 :doc:`Kconfig </api-reference/kconfig>`。
|
||||
- ``ESP_PLATFORM``:ESP-IDF 构建系统处理 CMake 文件时,其值设为 1。
|
||||
|
||||
|
||||
构建/项目变量
|
||||
-----------------
|
||||
|
||||
|
@ -334,12 +360,13 @@ ESP-IDF 在搜索所有待构建的组件时,会按照 ``COMPONENT_DIRS`` 指
|
|||
|
||||
其它与构建属性有关的信息请参考 :ref:`这里<cmake-build-properties>`。
|
||||
|
||||
|
||||
.. _component_build_control:
|
||||
|
||||
组件编译控制
|
||||
------------------
|
||||
|
||||
.. highlight:: cmake
|
||||
.. code-block:: cmake
|
||||
|
||||
在编译特定组件的源文件时,可以使用 `target_compile_options`_ 函数来传递编译器选项::
|
||||
|
||||
|
@ -360,6 +387,7 @@ ESP-IDF 在搜索所有待构建的组件时,会按照 ``COMPONENT_DIRS`` 指
|
|||
|
||||
请注意,上述两条命令只能在组件 CMakeLists 文件的 ``idf_component_register`` 命令之后调用。
|
||||
|
||||
|
||||
.. _component-configuration:
|
||||
|
||||
组件配置
|
||||
|
@ -373,6 +401,7 @@ ESP-IDF 在搜索所有待构建的组件时,会按照 ``COMPONENT_DIRS`` 指
|
|||
|
||||
有关示例请参阅 :ref:`add_conditional_config`。
|
||||
|
||||
|
||||
预处理器定义
|
||||
============
|
||||
|
||||
|
@ -381,6 +410,7 @@ ESP-IDF 构建系统会在命令行中添加以下 C 预处理器定义:
|
|||
- ``ESP_PLATFORM``:可以用来检测在 ESP-IDF 内发生了构建行为。
|
||||
- ``IDF_VER``:定义 git 版本字符串,例如:``v2.0`` 用于标记已发布的版本,``v1.0-275-g0efaa4f`` 则用于标记任意某次的提交记录。
|
||||
|
||||
|
||||
.. _component-requirements:
|
||||
|
||||
组件依赖
|
||||
|
@ -388,6 +418,7 @@ ESP-IDF 构建系统会在命令行中添加以下 C 预处理器定义:
|
|||
|
||||
编译各个组件时,ESP-IDF 系统会递归评估其依赖项。这意味着每个组件都需要声明它所依赖的组件,即 “requires”。
|
||||
|
||||
|
||||
编写组件
|
||||
--------
|
||||
|
||||
|
@ -409,6 +440,7 @@ ESP-IDF 构建系统会在命令行中添加以下 C 预处理器定义:
|
|||
|
||||
.. 注解:: 在 CMake 中,``REQUIRES`` 和 ``PRIV_REQUIRES`` 是 CMake 函数 ``target_link_libraries(... PUBLIC ...)`` 和 ``target_link_libraries(... PRIVATE ...)`` 的近似包装。
|
||||
|
||||
|
||||
.. _example component requirements:
|
||||
|
||||
组件依赖示例
|
||||
|
@ -430,10 +462,11 @@ ESP-IDF 构建系统会在命令行中添加以下 C 预处理器定义:
|
|||
- spark_plug.c
|
||||
- spark_plug.h
|
||||
|
||||
|
||||
Car 组件
|
||||
^^^^^^^^^
|
||||
|
||||
.. highlight:: c
|
||||
.. code-block:: c
|
||||
|
||||
``car.h`` 头文件是 ``car`` 组件的公共接口。该头文件直接包含了 ``engine.h``,这是因为它需要使用 ``engine.h`` 中的一些声明::
|
||||
|
||||
|
@ -461,10 +494,11 @@ Car 组件
|
|||
- ``INCLUDE_DIRS`` 提供该组件公共头文件目录列表,由于 ``car.h`` 是公共接口,所以这里列出了所有包含了 ``car.h`` 的目录。
|
||||
- ``REQUIRES`` 给出该组件的公共接口所需的组件列表。由于 ``car.h`` 是一个公共头文件并且包含了来自 ``engine`` 的头文件,所以我们这里包含 ``engine``。这样可以确保任何包含 ``car.h`` 的其他组件也能递归地包含所需的 ``engine.h``。
|
||||
|
||||
|
||||
Engine 组件
|
||||
^^^^^^^^^^^^^^^^
|
||||
|
||||
.. highlight:: c
|
||||
.. code-block:: c
|
||||
|
||||
``engine`` 组件也有一个公共头文件 ``include/engine.h``,但这个头文件更为简单::
|
||||
|
||||
|
@ -493,6 +527,7 @@ Engine 组件
|
|||
|
||||
因此,``car`` 组件中的源文件不需要在编译器搜索路径中添加 ``spark_plug`` include 目录。这可以加快编译速度,避免编译器命令行过于的冗长。
|
||||
|
||||
|
||||
Spark Plug 组件
|
||||
^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
|
@ -522,20 +557,23 @@ Spark Plug 组件
|
|||
- ``REQUIRES`` 和 ``PRIV_REQUIRES`` 参数指定的所有其他组件(即当前组件的所有公共和私有依赖项)所设置的 ``INCLUDE_DIRS``。
|
||||
- 递归列出所有组件 ``REQUIRES`` 列表中 ``INCLUDE_DIRS`` 目录(如递归展开这个组件的所有公共依赖项)。
|
||||
|
||||
|
||||
主要组件依赖项
|
||||
-----------------------
|
||||
|
||||
``main`` 组件比较特别,因为它在构建过程中自动依赖所有其他组件。所以不需要向这个组件传递 ``REQUIRES`` 或 ``PRIV_REQUIRES``。有关不再使用 ``main`` 组件时需要更改哪些内容,请参考 :ref:`重命名 main 组件<rename-main>`。
|
||||
|
||||
|
||||
.. _component-common-requirements:
|
||||
|
||||
通用组件依赖项
|
||||
--------------
|
||||
|
||||
为避免重复性工作,各组件都用自动依赖一些“通用” IDF 组件,即使它们没有被明确提及。这些组件的头文件会一直包含在构建系统中。
|
||||
为避免重复性工作,各组件都用自动依赖一些“通用”IDF 组件,即使它们没有被明确提及。这些组件的头文件会一直包含在构建系统中。
|
||||
|
||||
通用组件包括:cxx、newlib、freertos、esp_hw_support、heap、log、soc、hal、esp_rom、esp_common、esp_system。
|
||||
|
||||
|
||||
在构建中导入组件
|
||||
-----------------
|
||||
|
||||
|
@ -548,6 +586,7 @@ Spark Plug 组件
|
|||
|
||||
- 将 ``COMPONENTS`` 设置为所需组件的最小列表,可以显著减少项目的构建时间。
|
||||
|
||||
|
||||
.. _component-circular-dependencies:
|
||||
|
||||
循环依赖
|
||||
|
@ -572,6 +611,7 @@ CMake 通常会在链接器命令行上重复两次组件库名称来自动处
|
|||
- 通常将值增加到 3(默认值是 2)就足够了,但如果不起作用,可以尝试逐步增加这个数字。
|
||||
- 注意,增加这个选项会使链接器的命令行变长,链接阶段变慢。
|
||||
|
||||
|
||||
高级解决方法:未定义符号
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
|
@ -590,6 +630,7 @@ CMake 通常会在链接器命令行上重复两次组件库名称来自动处
|
|||
|
||||
请参考 `target_link_libraries`_ 文档以了解更多关于此 CMake 函数的信息。
|
||||
|
||||
|
||||
.. _component-requirements-implementation:
|
||||
|
||||
构建系统中依赖处理的实现细节
|
||||
|
@ -601,6 +642,7 @@ CMake 通常会在链接器命令行上重复两次组件库名称来自动处
|
|||
- 然后执行构建系统中包含的每个组件的配置。
|
||||
- 每个组件都被正常包含在构建系统中,然后再次执行 CMakeLists.txt 文件,将组件库加入构建系统。
|
||||
|
||||
|
||||
组件依赖顺序
|
||||
^^^^^^^^^^^^
|
||||
|
||||
|
@ -609,10 +651,11 @@ CMake 通常会在链接器命令行上重复两次组件库名称来自动处
|
|||
- 项目导入 :ref:`project_include.cmake` 文件的顺序。
|
||||
- 生成用于编译(通过 ``-I`` 参数)的头文件路径列表的顺序。请注意,对于给定组件的源文件,仅需将该组件的依赖组件的头文件路径告知编译器。
|
||||
|
||||
|
||||
添加链接时依赖项
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. highlight:: cmake
|
||||
.. code-block:: cmake
|
||||
|
||||
ESP-IDF 的 CMake 辅助函数 ``idf_component_add_link_dependency`` 可以在组件之间添加仅作用于链接时的依赖关系。绝大多数情况下,我们都建议你使用 ``idf_component_register`` 中的 ``PRIV_REQUIRES`` 功能来构建依赖关系。然而在某些情况下,还是有必要添加另一个组件对当前组件的链接时依赖,即反转 ``PRIV_REQUIRES`` 中的依赖关系(参考示例::doc:`/api-reference/peripherals/spi_flash/spi_flash_override_driver`)。
|
||||
|
||||
|
@ -626,6 +669,7 @@ ESP-IDF 的 CMake 辅助函数 ``idf_component_add_link_dependency`` 可以在
|
|||
|
||||
idf_component_add_link_dependency(FROM other_component TO that_component)
|
||||
|
||||
|
||||
.. _override_project_config:
|
||||
|
||||
覆盖项目的部分设置
|
||||
|
@ -648,6 +692,7 @@ project_include.cmake
|
|||
|
||||
在 ``project_include.cmake`` 文件中设置变量或目标时要格外小心,这些值被包含在项目的顶层 CMake 文件中,因此他们会影响或破坏所有组件的功能。
|
||||
|
||||
|
||||
KConfig.projbuild
|
||||
-----------------
|
||||
|
||||
|
@ -657,6 +702,7 @@ KConfig.projbuild
|
|||
|
||||
``project_include.cmake`` 文件在 ESP-IDF 内部使用,以定义项目范围内的构建功能,比如 ``esptool.py`` 的命令行参数和 ``bootloader`` 这个特殊的应用程序。
|
||||
|
||||
|
||||
通过封装对现有函数进行重新定义或扩展
|
||||
-------------------------------------
|
||||
|
||||
|
@ -672,6 +718,7 @@ KConfig.projbuild
|
|||
|
||||
请参考 :example:`build_system/wrappers` 示例,了解其详细原理。更多细节请参阅 :idf_file:`examples/build_system/wrappers/README.md`。
|
||||
|
||||
|
||||
.. _config_only_component:
|
||||
|
||||
仅配置组件
|
||||
|
@ -679,6 +726,7 @@ KConfig.projbuild
|
|||
|
||||
仅配置组件是一类不包含源文件的特殊组件,仅包含 ``Kconfig.projbuild``、``KConfig`` 和 ``CMakeLists.txt`` 文件,该 ``CMakeLists.txt`` 文件仅有一行代码,调用了 ``idf_component_register()`` 函数。此函数会将组件导入到项目构建中,但不会构建任何库,也不会将头文件添加到任何 include 搜索路径中。
|
||||
|
||||
|
||||
CMake 调试
|
||||
===========
|
||||
|
||||
|
@ -694,6 +742,7 @@ CMake 调试
|
|||
|
||||
同时还定义了一个自定义版本的内置 CMake_ ``project`` 函数, 这个函数被覆盖,以添加所有 ESP-IDF 特定的项目功能。
|
||||
|
||||
|
||||
.. _warn-undefined-variables:
|
||||
|
||||
警告未定义的变量
|
||||
|
@ -705,6 +754,7 @@ CMake 调试
|
|||
|
||||
更多信息,请参考文件 :idf_file:`/tools/cmake/project.cmake` 以及 :idf:`/tools/cmake/` 中支持的函数。
|
||||
|
||||
|
||||
.. _component_cmakelists_example:
|
||||
|
||||
组件 CMakeLists 示例
|
||||
|
@ -714,6 +764,7 @@ CMake 调试
|
|||
|
||||
以下是组件 CMakeLists 文件的更高级的示例。
|
||||
|
||||
|
||||
.. _add_conditional_config:
|
||||
|
||||
添加条件配置
|
||||
|
@ -721,7 +772,7 @@ CMake 调试
|
|||
|
||||
配置系统可用于根据项目配置中选择的选项有条件地编译某些文件。
|
||||
|
||||
.. highlight:: none
|
||||
.. code-block:: none
|
||||
|
||||
``Kconfig``::
|
||||
|
||||
|
@ -764,7 +815,7 @@ CMake 调试
|
|||
help
|
||||
Select this to output temperature plots
|
||||
|
||||
.. highlight:: cmake
|
||||
.. code-block:: cmake
|
||||
|
||||
``CMakeLists.txt``::
|
||||
|
||||
|
@ -782,6 +833,7 @@ CMake 调试
|
|||
idf_component_register(SRCS "${srcs}"
|
||||
...)
|
||||
|
||||
|
||||
硬件目标的条件判断
|
||||
--------------------
|
||||
|
||||
|
@ -818,6 +870,7 @@ CMake 文件可以使用 ``IDF_TARGET`` 变量来获取当前的硬件目标。
|
|||
|
||||
如果某个源文件是从其他组件中生成,且包含 ``logo.h`` 文件,则需要调用 ``add_dependencies``, 在这两个组件之间添加一个依赖项,以确保组件源文件按照正确顺序进行编译。
|
||||
|
||||
|
||||
.. _cmake_embed_data:
|
||||
|
||||
嵌入二进制数据
|
||||
|
@ -835,7 +888,7 @@ CMake 文件可以使用 ``IDF_TARGET`` 变量来获取当前的硬件目标。
|
|||
idf_component_register(...
|
||||
EMBED_TXTFILES server_root_cert.pem)
|
||||
|
||||
.. highlight:: c
|
||||
.. code-block:: c
|
||||
|
||||
文件的内容会被添加到 flash 的 .rodata 段,用户可以通过符号名来访问,如下所示::
|
||||
|
||||
|
@ -844,7 +897,7 @@ CMake 文件可以使用 ``IDF_TARGET`` 变量来获取当前的硬件目标。
|
|||
|
||||
符号名会根据文件全名生成,如 ``EMBED_FILES`` 中所示,字符 ``/``、``.`` 等都会被下划线替代。符号名称中的 _binary 前缀由 objcopy 命令添加,对文本文件和二进制文件都是如此。
|
||||
|
||||
.. highlight:: cmake
|
||||
.. code-block:: cmake
|
||||
|
||||
如果要将文件嵌入到项目中,而非组件中,可以调用 ``target_add_binary_data`` 函数::
|
||||
|
||||
|
@ -854,7 +907,7 @@ CMake 文件可以使用 ``IDF_TARGET`` 变量来获取当前的硬件目标。
|
|||
|
||||
有关使用此技术的示例,请查看 file_serving 示例 :example_file:`protocols/http_server/file_serving/main/CMakeLists.txt` 中的 main 组件,两个文件会在编译时加载并链接到固件中。
|
||||
|
||||
.. highlight:: cmake
|
||||
.. code-block:: cmake
|
||||
|
||||
也可以嵌入生成的文件::
|
||||
|
||||
|
@ -871,17 +924,19 @@ CMake 文件可以使用 ``IDF_TARGET`` 变量来获取当前的硬件目标。
|
|||
|
||||
``target_add_binary_data`` 的 ``DEPENDS`` 参数确保目标首先执行。
|
||||
|
||||
|
||||
代码和数据的存放
|
||||
----------------
|
||||
|
||||
ESP-IDF 还支持自动生成链接脚本,它允许组件通过链接片段文件定义其代码和数据在内存中的存放位置。构建系统会处理这些链接片段文件,并将处理后的结果扩充进链接脚本,从而指导应用程序二进制文件的链接过程。更多详细信息与快速上手指南,请参阅 :doc:`链接脚本生成机制 <linker-script-generation>`。
|
||||
|
||||
|
||||
.. _component-build-full-override:
|
||||
|
||||
完全覆盖组件的构建过程
|
||||
----------------------
|
||||
|
||||
.. highlight:: cmake
|
||||
.. code-block:: cmake
|
||||
|
||||
当然,在有些情况下,上面提到的方法不一定够用。如果组件封装了另一个第三方组件,而这个第三方组件并不能直接在 ESP-IDF 的构建系统中工作,在这种情况下,就需要放弃 ESP-IDF 的构建系统,改为使用 CMake 的 ExternalProject_ 功能。组件 CMakeLists 示例如下::
|
||||
|
||||
|
@ -923,6 +978,7 @@ ESP-IDF 还支持自动生成链接脚本,它允许组件通过链接片段文
|
|||
|
||||
.. note:: 当外部构建系统使用 PSRAM 时,请记得将 ``-mfix-esp32-psram-cache-issue`` 添加到 C 编译器的参数中。关于该标志的更多详细信息,请参考 :ref:`CONFIG_SPIRAM_CACHE_WORKAROUND`。
|
||||
|
||||
|
||||
.. _ADDITIONAL_MAKE_CLEAN_FILES_note:
|
||||
|
||||
ExternalProject 的依赖与构建清理
|
||||
|
@ -939,6 +995,7 @@ ExternalProject 的依赖与构建清理
|
|||
|
||||
构建外部项目的最佳方法取决于项目本身、其构建系统,以及是否需要频繁重新编译项目。
|
||||
|
||||
|
||||
.. _custom-sdkconfig-defaults:
|
||||
|
||||
自定义 sdkconfig 的默认值
|
||||
|
@ -952,6 +1009,7 @@ ExternalProject 的依赖与构建清理
|
|||
|
||||
一些 IDF 示例中包含了 ``sdkconfig.ci`` 文件。该文件是 CI(持续集成)测试框架的一部分,在正常构建过程中会被忽略。
|
||||
|
||||
|
||||
依赖于硬件目标的 sdkconfig 默认值
|
||||
---------------------------------
|
||||
|
||||
|
@ -961,6 +1019,7 @@ ExternalProject 的依赖与构建清理
|
|||
|
||||
例如,如果 ``SDKCONFIG_DEFAULTS="sdkconfig.defaults;sdkconfig_devkit1"``,并且在同一文件夹中有一个 ``sdkconfig.defaults.esp32`` 文件,那么这些文件将按以下顺序应用:(1) sdkconfig.defaults (2) sdkconfig.defaults.esp32 (3) sdkconfig_devkit1。
|
||||
|
||||
|
||||
.. _flash_parameters:
|
||||
|
||||
flash 参数
|
||||
|
@ -974,7 +1033,7 @@ flash 参数
|
|||
- ``flash_app_args`` 只包含烧录应用程序的参数。
|
||||
- ``flash_bootloader_args`` 只包含烧录引导程序的参数。
|
||||
|
||||
.. highlight:: bash
|
||||
.. code-block:: bash
|
||||
|
||||
你可以参照如下命令将任意烧录参数文件传递给 ``esptool.py``::
|
||||
|
||||
|
@ -984,6 +1043,7 @@ flash 参数
|
|||
|
||||
构建目录中还包含生成的 ``flasher_args.json`` 文件,此文件包含 JSON 格式的项目烧录信息,可用于 ``idf.py`` 和其它需要项目构建信息的工具。
|
||||
|
||||
|
||||
构建 Bootloader
|
||||
===============
|
||||
|
||||
|
@ -991,6 +1051,7 @@ flash 参数
|
|||
|
||||
子项目通过 :idf_file:`/components/bootloader/project_include.cmake` 文件作为外部项目插入到项目的顶层,主构建进程会运行子项目的 CMake,包括查找组件(主项目使用的组件的子集),生成引导程序专用的配置文件(从主 ``sdkconfig`` 文件中派生)。
|
||||
|
||||
|
||||
.. _write-pure-component:
|
||||
|
||||
编写纯 CMake 组件
|
||||
|
@ -1000,7 +1061,7 @@ ESP-IDF 构建系统用“组件”的概念“封装”了 CMake,并提供了
|
|||
|
||||
然而,“组件”概念的背后是一个完整的 CMake 构建系统,因此可以制作纯 CMake 组件。
|
||||
|
||||
.. highlight:: cmake
|
||||
.. code-block:: cmake
|
||||
|
||||
下面是使用纯 CMake 语法为 ``json`` 组件编写的最小 CMakeLists 文件的示例::
|
||||
|
||||
|
@ -1014,12 +1075,13 @@ ESP-IDF 构建系统用“组件”的概念“封装”了 CMake,并提供了
|
|||
- 因为组件中的源文件不多,所以这个 CMakeLists 文件非常简单。对于具有大量源文件的组件而言,ESP-IDF 支持的组件通配符,可以简化组件 CMakeLists 的样式。
|
||||
- 每当组件中新增一个与组件同名的库目标时,ESP-IDF 构建系统会自动将其添加到构建中,并公开公共的 include 目录。如果组件想要添加一个与组件不同名的库目标,就需要使用 CMake 命令手动添加依赖关系。
|
||||
|
||||
|
||||
组件中使用第三方 CMake 项目
|
||||
===========================
|
||||
|
||||
CMake 在许多开源的 C/C++ 项目中广泛使用,用户可以在自己的应用程序中使用开源代码。CMake 构建系统的一大好处就是可以导入这些第三方的项目,有时候甚至不用做任何改动。这就允许用户使用当前 ESP-IDF 组件尚未提供的功能,或者使用其它库来实现相同的功能。
|
||||
|
||||
.. highlight:: cmake
|
||||
.. code-block:: cmake
|
||||
|
||||
假设 ``main`` 组件需要导入一个假想库 ``foo``,相应的组件 CMakeLists 文件如下所示::
|
||||
|
||||
|
@ -1042,6 +1104,7 @@ CMake 在许多开源的 C/C++ 项目中广泛使用,用户可以在自己的
|
|||
|
||||
每当使用 ESP-IDF 构建系统时,CMake 变量 ``ESP_PLATFORM`` 都会被设置为 1。如果要在通用的 CMake 代码加入 IDF 特定的代码时,可以采用 ``if (ESP_PLATFORM)`` 的形式加以分隔。
|
||||
|
||||
|
||||
外部库中使用 ESP-IDF 组件
|
||||
--------------------------
|
||||
|
||||
|
@ -1052,7 +1115,7 @@ CMake 在许多开源的 C/C++ 项目中广泛使用,用户可以在自己的
|
|||
add_library(foo bar.c fizz.cpp buzz.cpp)
|
||||
|
||||
if(ESP_PLATFORM)
|
||||
# 在 ESP-IDF 中、 bar.c 需要包含 spi_flash 组件中的 esp_flash.h
|
||||
# 在 ESP-IDF 中、bar.c 需要包含 spi_flash 组件中的 esp_flash.h
|
||||
target_link_libraries(foo PRIVATE idf::spi_flash)
|
||||
endif()
|
||||
|
||||
|
@ -1060,7 +1123,7 @@ CMake 在许多开源的 C/C++ 项目中广泛使用,用户可以在自己的
|
|||
组件中使用预建库
|
||||
=================
|
||||
|
||||
.. highlight:: cmake
|
||||
.. code-block:: cmake
|
||||
|
||||
还有一种情况是你有一个由其它构建过程生成预建静态库(``.a`` 文件)。
|
||||
|
||||
|
@ -1079,6 +1142,7 @@ ESP-IDF 构建系统为用户提供了一个实用函数 ``add_prebuilt_library`
|
|||
|
||||
请查看示例 :example:`build_system/cmake/import_prebuilt`。
|
||||
|
||||
|
||||
在自定义 CMake 项目中使用 ESP-IDF
|
||||
=================================
|
||||
|
||||
|
@ -1113,6 +1177,7 @@ ESP-IDF 提供了一个模板 CMake 项目,可以基于此轻松创建应用
|
|||
|
||||
.. note:: IDF 构建系统只能为其构建的源文件设置编译器标志。当使用外部 CMakeLists.txt 文件并启用 PSRAM 时,记得在 C 编译器参数中添加 ``mfix-esp32-psram-cache-issue``。参见:ref:`CONFIG_SPIRAM_CACHE_WORKAROUND` 了解更多信息。
|
||||
|
||||
|
||||
.. _cmake_buildsystem_api:
|
||||
|
||||
ESP-IDF CMake 构建系统 API
|
||||
|
@ -1179,6 +1244,7 @@ ESP-IDF 构建命令
|
|||
|
||||
获取指定配置的值。就像构建属性一样,特定 *GENERATOR_EXPRESSION* 将检索该配置的生成器表达式字符串,而不是实际值,即可以与支持生成器表达式的 CMake 命令一起使用。然而,实际的配置值只有在调用 ``idf_build_process`` 后才能知道。
|
||||
|
||||
|
||||
.. _cmake-build-properties:
|
||||
|
||||
ESP-IDF 构建属性
|
||||
|
@ -1220,6 +1286,7 @@ ESP-IDF 构建属性
|
|||
- SDKCONFIG_JSON - 包含组件配置的 JSON 文件的完整路径;由 ``idf_build_process`` 设置。
|
||||
- SDKCONFIG_JSON_MENUS - 包含配置菜单的 JSON 文件的完整路径;由 ``idf_build_process`` 设置。
|
||||
|
||||
|
||||
ESP-IDF 组件命令
|
||||
----------------------
|
||||
|
||||
|
@ -1263,7 +1330,7 @@ ESP-IDF 组件命令
|
|||
``idf_component_register`` 的参数包括:
|
||||
|
||||
- SRCS - 组件的源文件,用于为组件创建静态库;如果没有指定,组件将被视为仅配置组件,从而创建接口库。
|
||||
- SRC_DIRS、 EXCLUDE_SRCS - 用于通过指定目录来 glob 源文件 (.c、.cpp、.S),而不是通过 SRCS 手动指定源文件。请注意,这受 :ref:`CMake 中通配符的限制<cmake-file-globbing>`。在 EXCLUDE_SRCS 中指定的源文件会从被 glob 的文件中移除。
|
||||
- SRC_DIRS、EXCLUDE_SRCS - 用于通过指定目录来 glob 源文件 (.c、.cpp、.S),而不是通过 SRCS 手动指定源文件。请注意,这受 :ref:`CMake 中通配符的限制<cmake-file-globbing>`。在 EXCLUDE_SRCS 中指定的源文件会从被 glob 的文件中移除。
|
||||
- INCLUDE_DIRS - 相对于组件目录的路径,该路径将被添加到需要当前组件的所有其他组件的 include 搜索路径中。
|
||||
- PRIV_INCLUDE_DIRS - 必须是相对于组件目录的目录路径,它仅被添加到这个组件源文件的 include 搜索路径中。
|
||||
- REQUIRES - 组件的公共组件依赖项。
|
||||
|
@ -1279,6 +1346,7 @@ ESP-IDF 组件命令
|
|||
- EMBED_FILES - 嵌入组件的二进制文件
|
||||
- EMBED_TXTFILES - 嵌入组件的文本文件
|
||||
|
||||
|
||||
.. _cmake-component-properties:
|
||||
|
||||
ESP-IDF 组件属性
|
||||
|
@ -1312,12 +1380,13 @@ ESP-IDF 组件属性
|
|||
- SRCS - 组件源文件列表;由 ``idf_component_register`` 的 SRCS 或 SRC_DIRS/EXCLUDE_SRCS 参数设置。
|
||||
- WHOLE_ARCHIVE - 如果该属性被设置为 ``TRUE`` (或是其他 CMake 布尔“真”值:1、``ON``、``YES``、``Y`` 等),链接时会在组件库的前后分别添加 ``-Wl,--whole-archive`` 和 ``-Wl,--no-whole-archive`` 选项。这可以强制链接器将每个目标文件包含到可执行文件中,即使该目标文件没有解析来自应用程序其余部分的任何引用。当组件中包含依赖链接时注册的插件或模块时,通常会使用该方法。默认情况下,此属性为 ``FALSE``。可以从组件的 CMakeLists.txt 文件中将其设置为 ``TRUE``。
|
||||
|
||||
|
||||
.. _cmake-file-globbing:
|
||||
|
||||
文件通配 & 增量构建
|
||||
=====================
|
||||
|
||||
.. highlight:: cmake
|
||||
.. code-block:: cmake
|
||||
|
||||
在 ESP-IDF 组件中添加源文件的首选方法是在 ``COMPONENT_SRCS`` 中手动列出它们::
|
||||
|
||||
|
@ -1344,6 +1413,7 @@ ESP-IDF 中的组件使用了第三方的 Git CMake 集成模块(:idf_file:`/t
|
|||
|
||||
具体选择哪一方式,就要取决于项目本身,以及项目用户。
|
||||
|
||||
|
||||
.. _build_system_metadata:
|
||||
|
||||
构建系统的元数据
|
||||
|
@ -1358,6 +1428,7 @@ ESP-IDF 中的组件使用了第三方的 Git CMake 集成模块(:idf_file:`/t
|
|||
- ``config/sdkconfig.json`` 包含 JSON 格式的项目配置结果。
|
||||
- ``config/kconfig_menus.json`` 是在 menuconfig 中显示菜单的 JSON 格式版本,用于外部 IDE 的 UI。
|
||||
|
||||
|
||||
JSON 配置服务器
|
||||
---------------
|
||||
|
||||
|
@ -1367,6 +1438,7 @@ JSON 配置服务器
|
|||
|
||||
有关 kconfserver 的更多信息,请参阅 `esp-idf-kconfig 文档 <https://github.com/espressif/esp-idf-kconfig/blob/master/docs/DOCUMENTATION.md>`_。
|
||||
|
||||
|
||||
构建系统内部
|
||||
=======================
|
||||
|
||||
|
@ -1389,6 +1461,7 @@ ESP-IDF 构建系统的列表文件位于 :idf:`/tools/cmake` 中。实现构建
|
|||
|
||||
:idf:`/tools/cmake` 中的其它文件都是构建过程中的支持性文件或第三方脚本。
|
||||
|
||||
|
||||
构建过程
|
||||
-------------
|
||||
|
||||
|
@ -1405,6 +1478,7 @@ ESP-IDF 构建系统的列表文件位于 :idf:`/tools/cmake` 中。实现构建
|
|||
处理 -> 完成
|
||||
}
|
||||
|
||||
|
||||
初始化
|
||||
^^^^^^^
|
||||
|
||||
|
@ -1424,6 +1498,7 @@ ESP-IDF 构建系统的列表文件位于 :idf:`/tools/cmake` 中。实现构建
|
|||
|
||||
调用 ``idf_build_process()`` 命令标志着这个阶段的结束。
|
||||
|
||||
|
||||
枚举
|
||||
^^^^^^^^^^^
|
||||
这个阶段会建立一个需要在构建过程中处理的组件列表,该阶段在 ``idf_build_process()`` 的前半部分进行。
|
||||
|
@ -1431,6 +1506,7 @@ ESP-IDF 构建系统的列表文件位于 :idf:`/tools/cmake` 中。实现构建
|
|||
- 检索每个组件的公共和私有依赖。创建一个子进程,以脚本模式执行每个组件的 CMakeLists.txt。``idf_component_register`` REQUIRES 和 PRIV_REQUIRES 参数的值会返回给父进程。这就是所谓的早期扩展。在这一步中定义变量 ``CMAKE_BUILD_EARLY_EXPANSION``。
|
||||
- 根据公共和私有的依赖关系,递归地导入各个组件。
|
||||
|
||||
|
||||
处理
|
||||
^^^^^^^
|
||||
|
||||
|
@ -1440,6 +1516,7 @@ ESP-IDF 构建系统的列表文件位于 :idf:`/tools/cmake` 中。实现构建
|
|||
- 导入各组件的 ``project_include.cmake``。
|
||||
- 将每个组件添加为一个子目录,处理其 CMakeLists.txt。组件 CMakeLists.txt 调用注册命令 ``idf_component_register`` 添加源文件、导入目录、创建组件库、链接依赖关系等。
|
||||
|
||||
|
||||
完成
|
||||
^^^^^^^
|
||||
该阶段是 ``idf_build_process()`` 剩余的步骤。
|
||||
|
@ -1457,11 +1534,13 @@ ESP-IDF 构建系统的列表文件位于 :idf:`/tools/cmake` 中。实现构建
|
|||
|
||||
ESP-IDF CMake 构建系统与旧版的 GNU Make 构建系统在某些方面非常相似,开发者都需要提供 include 目录、源文件等。然而,有一个语法上的区别,即对于 ESP-IDF CMake 构建系统,开发者需要将这些作为参数传递给注册命令 ``idf_component_register``。
|
||||
|
||||
|
||||
自动转换工具
|
||||
-------------------------
|
||||
|
||||
在 ESP-IDF v4.x 版本中,`tools/cmake/convert_to_cmake.py` 提供了项目自动转换工具。由于该脚本依赖于 `make` 构建系统,所以 v5.0 版本中不包含该脚本。
|
||||
|
||||
|
||||
CMake 中不可用的功能
|
||||
--------------------
|
||||
|
||||
|
@ -1482,6 +1561,7 @@ CMake 中不可用的功能
|
|||
- ``COMPONENT_CONFIG_ONLY``:已被 ``register_config_only_component()`` 函数替代,请参阅 :ref:`config_only_component`。
|
||||
- ``CFLAGS``、``CPPFLAGS``、``CXXFLAGS``:已被相应的 CMake 命令替代,请参阅 :ref:`component_build_control`。
|
||||
|
||||
|
||||
无默认值的变量
|
||||
--------------
|
||||
|
||||
|
@ -1490,6 +1570,7 @@ CMake 中不可用的功能
|
|||
- 源目录(Make 中的 ``COMPONENT_SRCDIRS`` 变量,CMake 中 ``idf_component_register`` 的 ``SRC_DIRS`` 参数)
|
||||
- include 目录(Make 中的 ``COMPONENT_ADD_INCLUDEDIRS`` 变量,CMake 中 ``idf_component_register`` 的 ``INCLUDE_DIRS`` 参数)
|
||||
|
||||
|
||||
不再需要的变量
|
||||
--------------
|
||||
|
||||
|
|
|
@ -1,15 +1,17 @@
|
|||
RF 共存
|
||||
==================
|
||||
|
||||
:link_to_translation:`en:[English]`
|
||||
|
||||
概览
|
||||
-----
|
||||
|
||||
{IDF_TARGET_NAME} 只支持一路 RF,Bluetooth (BT 和 BLE)和 Wi-Fi 共享这一路 RF,无法同时收发数据,因此采用时分复用的方法进行收发数据包。
|
||||
{IDF_TARGET_NAME} 只支持一路 RF,Bluetooth(BT 和 BLE)和 Wi-Fi 共享这一路 RF,无法同时收发数据,因此采用时分复用的方法进行收发数据包。
|
||||
|
||||
|
||||
{IDF_TARGET_NAME} 支持的共存场景
|
||||
------------------------------------
|
||||
|
||||
.. only:: esp32c3 or esp32s3 or esp32 or esp32c6
|
||||
|
||||
.. table:: 表 1 Wi-Fi 和 BLE 共存支持功能
|
||||
|
@ -73,7 +75,8 @@ RF 共存
|
|||
Y:支持且性能稳定。
|
||||
C1:不能保证性能处于稳定状态。
|
||||
X:不支持。
|
||||
S:在STA模式下支持且性能稳定,否则不支持。
|
||||
S:在 STA 模式下支持且性能稳定,否则不支持。
|
||||
|
||||
|
||||
共存机制与策略
|
||||
----------------------------------
|
||||
|
@ -110,6 +113,7 @@ RF 共存
|
|||
Coexistence -> RF;
|
||||
}
|
||||
|
||||
|
||||
.. _coexist_policy-cn:
|
||||
|
||||
共存策略
|
||||
|
@ -152,6 +156,7 @@ RF 共存
|
|||
|
||||
共存模块对 Wi-Fi 和 Bluetooth 不同的状态赋予其不同的优先级。每种状态下的优先级并不是一成不变的,例如每 N 个广播事件 (Advertising event) 中会有一个广播事件使用高优先级。如果高优先级的广播事件发生在 Wi-Fi 时间片内,RF 的使用权可能会被 BLE 抢占。
|
||||
|
||||
|
||||
.. only:: SOC_WIFI_SUPPORTED
|
||||
|
||||
Wi-Fi 非连接模块的共存
|
||||
|
@ -159,10 +164,11 @@ RF 共存
|
|||
|
||||
在一定程度上,某些 Wi-Fi 非连接模块功耗参数 Window 与 Interval 的组合会导致共存模块在 Wi-Fi 时间片外申请共存优先级。这是为了按设定的功耗参数在共存时获取 RF 资源,但这会影响既定的蓝牙性能。
|
||||
|
||||
如果 Wi-Fi 非连接模块功耗参数为默认值时,上述动作不会发生,共存模块会按照性能稳定的模式运行。因此,除非您对特定非连接功耗参数下的共存性能有足够的测试,请在共存场景下将 Wi-Fi 非连接模块功耗参数配置为默认参数。
|
||||
如果 Wi-Fi 非连接模块功耗参数为默认值时,上述动作不会发生,共存模块会按照性能稳定的模式运行。因此,除非你对特定非连接功耗参数下的共存性能有足够的测试,请在共存场景下将 Wi-Fi 非连接模块功耗参数配置为默认参数。
|
||||
|
||||
请参考 :ref:`非连接模块功耗管理 <connectionless-module-power-save-cn>` 获取更多信息。
|
||||
|
||||
|
||||
如何使用共存功能
|
||||
----------------------------------
|
||||
|
||||
|
@ -171,6 +177,7 @@ RF 共存
|
|||
|
||||
在大多数共存情况下,{IDF_TARGET_NAME} 会自动进行共存状态切换,无需调用 API 对其进行干预。但是对于 BLE MESH 和 Wi-Fi 的共存,{IDF_TARGET_NAME} 对其提供了两个 API。当 BLE MESH 的状态发生变化时,应先调用 :code:`esp_coex_status_bit_clear` 对上一个状态进行清除,然后调用 :code:`esp_coex_status_bit_set` 设置当前状态。
|
||||
|
||||
|
||||
BLE MESH 共存状态描述
|
||||
""""""""""""""""""""""""""""
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
|
||||
核心转储数据会按照特定格式保存在核心转储文件中,详情请参阅 :doc:`core_dump_internals`。然而,ESP-IDF 的 ``idf.py`` 命令提供了专门的子命令,用于解码和分析核心转储文件。
|
||||
|
||||
|
||||
配置
|
||||
--------------
|
||||
|
||||
|
@ -20,6 +21,7 @@
|
|||
|
||||
选项 :ref:`CONFIG_ESP_COREDUMP_TO_FLASH_OR_UART` 可以启用或禁用核心转储,并在启用时选择核心转储的目标。发生崩溃时,生成的核心转储文件可以保存到 flash 中,也可以通过 UART 输出到连接的主机上。
|
||||
|
||||
|
||||
格式和大小
|
||||
^^^^^^^^^^^^^
|
||||
|
||||
|
@ -44,6 +46,7 @@ ELF 格式具备扩展特性,支持在发生崩溃时保存更多关于错误
|
|||
|
||||
SHA256 哈希算法检测到损坏的概率高于具有多位错误的 CRC32。
|
||||
|
||||
|
||||
保留栈大小
|
||||
^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
|
@ -55,6 +58,7 @@ ELF 格式具备扩展特性,支持在发生崩溃时保存更多关于错误
|
|||
|
||||
如果使用了独立的栈,建议栈大小应大于 800 字节,确保核心转储例程本身不会导致栈溢出。
|
||||
|
||||
|
||||
将核心转储保存到 flash
|
||||
-----------------------
|
||||
|
||||
|
@ -93,11 +97,13 @@ ELF 格式具备扩展特性,支持在发生崩溃时保存更多关于错误
|
|||
|
||||
idf.py coredump-debug
|
||||
|
||||
|
||||
将核心转储保存到 UART
|
||||
-----------------------
|
||||
|
||||
当核心转储文件输出到 UART 时,输出文件会以 Base64 编码方式呈现。通过 :ref:`CONFIG_ESP_COREDUMP_DECODE` 选项,可以选择 ESP-IDF 监视器对输出文件自动解码,或保持编码状态等待手动解码。
|
||||
|
||||
|
||||
自动解码
|
||||
^^^^^^^^^^^^^^^^^^
|
||||
|
||||
|
@ -144,6 +150,7 @@ ELF 格式具备扩展特性,支持在发生崩溃时保存更多关于错误
|
|||
===================== ESP32 CORE DUMP END =====================
|
||||
===============================================================
|
||||
|
||||
|
||||
手动解码
|
||||
^^^^^^^^^^^^^^^
|
||||
|
||||
|
@ -200,6 +207,7 @@ ESP-IDF 提供了一些特殊命令,有助于检索和分析核心转储:
|
|||
:SOC_RTC_FAST_MEM_SUPPORTED or SOC_RTC_SLOW_MEM_SUPPORTED: * ``COREDUMP_RTC_ATTR`` 将变量放置在 RTC 区域,该区域包含在转储中。
|
||||
:SOC_RTC_FAST_MEM_SUPPORTED: * ``COREDUMP_RTC_FAST_ATTR`` 将变量放置在 RTC_FAST 区域,该区域包含在转储中。
|
||||
|
||||
|
||||
示例
|
||||
^^^^^^^
|
||||
|
||||
|
@ -234,11 +242,13 @@ ESP-IDF 提供了一些特殊命令,有助于检索和分析核心转储:
|
|||
(gdb) p global_var
|
||||
$1 = 25 '\031'
|
||||
|
||||
|
||||
运行 ``idf.py coredump-info`` 和 ``idf.py coredump-debug``
|
||||
--------------------------------------------------------------
|
||||
|
||||
要获取更多有关使用方法的详情,请运行 ``idf.py coredump-info --help`` 和 ``idf.py coredump-debug --help`` 命令。
|
||||
|
||||
|
||||
相关文档
|
||||
^^^^^^^^^^^^^^^^^
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
核心转储图像文件详解
|
||||
核心转储镜像文件详解
|
||||
--------------------------
|
||||
|
||||
:link_to_translation:`en:[English]`
|
||||
|
@ -13,21 +13,22 @@
|
|||
|
||||
.. figure:: ../../_static/core_dump_format_elf.png
|
||||
:align: center
|
||||
:alt: 核心转储 ELF 图像文件格式
|
||||
:alt: 核心转储 ELF 镜像文件格式
|
||||
:figclass: align-center
|
||||
|
||||
核心转储 ELF 图像文件格式
|
||||
核心转储 ELF 镜像文件格式
|
||||
|
||||
.. figure:: ../../_static/core_dump_format_bin.png
|
||||
:align: center
|
||||
:alt: 核心转储二进制图像文件格式
|
||||
:alt: 核心转储二进制镜像文件格式
|
||||
:figclass: align-center
|
||||
|
||||
核心转储二进制图像文件格式
|
||||
核心转储二进制镜像文件格式
|
||||
|
||||
.. note::
|
||||
|
||||
上图仅展示当前版本图像的文件格式,在未来的发布版本中可能会发生变化。
|
||||
上图仅展示当前版本镜像的文件格式,在未来的发布版本中可能会发生变化。
|
||||
|
||||
|
||||
核心转储实现
|
||||
--------------------------
|
||||
|
|
|
@ -15,11 +15,13 @@ ESP-IDF 支持以下 C++ 功能:
|
|||
- :doc:`thread-local-storage` (``thread_local`` 关键字)
|
||||
- 除部分 :ref:`cplusplus_limitations`,所有由 GCC 实现的 C++ 功能均受支持。有关由 GCC 所实现功能的详细信息,请参阅 `GCC 文档 <https://gcc.gnu.org/projects/cxx-status.html>`_。
|
||||
|
||||
|
||||
``esp-idf-cxx`` 组件
|
||||
-------------------------
|
||||
|
||||
`esp-idf-cxx <https://github.com/espressif/esp-idf-cxx>`_ 组件为一些 ESP-IDF 中的功能提供了更高级别的 C++ API,该组件可以从 `ESP-IDF 组件注册表 <https://components.espressif.com/components/espressif/esp-idf-cxx>`_ 中获取。
|
||||
|
||||
|
||||
C++ 语言标准
|
||||
---------------------
|
||||
|
||||
|
@ -34,6 +36,7 @@ C++ 语言标准
|
|||
|
||||
如果组件的公共头文件也需要以该语言标准编译,请使用 ``PUBLIC`` 而非 ``PRIVATE``。
|
||||
|
||||
|
||||
.. _cplusplus_multithreading:
|
||||
|
||||
多线程
|
||||
|
@ -47,6 +50,7 @@ C++ 语言标准
|
|||
|
||||
`std::jthread <https://en.cppreference.com/w/cpp/thread/jthread>`_ 的析构函数只能从 :ref:`posix_thread_api` 或 `C++ 线程库 API <https://en.cppreference.com/w/cpp/thread>`_ 创建的任务中安全地调用。
|
||||
|
||||
|
||||
.. _cplusplus_exceptions:
|
||||
|
||||
异常处理
|
||||
|
@ -60,6 +64,7 @@ C++ 异常处理应 **仅** 应用于异常情况,即意外情况及罕见情
|
|||
|
||||
有关 C++ 异常处理的示例,请参阅 :example:`cxx/exceptions`。
|
||||
|
||||
|
||||
C++ 异常处理及所需资源
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
|
@ -78,6 +83,7 @@ C++ 异常处理及所需资源
|
|||
|
||||
如果抛出异常,解开栈代码的速度要比返回错误代码慢好几个数量级。所增加的运行时长取决于应用程序的要求和错误处理的实现方式(例如,是否需要用户输入或发送消息到云端)。因此,在实时关键的代码路径中,不应使用会抛出异常的代码。
|
||||
|
||||
|
||||
.. _cplusplus_rtti:
|
||||
|
||||
运行时类型信息 (RTTI)
|
||||
|
@ -95,6 +101,7 @@ ESP-IDF 默认禁用对 RTTI 的支持,可以用 :ref:`CONFIG_COMPILER_CXX_RTT
|
|||
|
||||
以下部分提供了在 C++ 中开发 ESP-IDF 应用程序的一些技巧。
|
||||
|
||||
|
||||
组合 C 和 C++ 代码
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
|
@ -153,6 +160,7 @@ ESP-IDF 希望应用程序入口点 ``app_main`` 以 C 链接定义。当 ``app_
|
|||
{
|
||||
}
|
||||
|
||||
|
||||
.. _cplusplus_designated_initializers:
|
||||
|
||||
指定初始化器
|
||||
|
@ -171,6 +179,7 @@ ESP-IDF 支持 ``iostream`` 功能,但应注意:
|
|||
1. ESP-IDF 在构建过程中通常会删除未使用的代码。然而,在使用 iostreams 的情况下,仅在其中一个源文件包含 ``<iostream>`` 头文件就会使二进制文件增加大约 200 kB。
|
||||
2. ESP-IDF 默认使用简单的非阻塞机制来处理标准输入流 (``stdin``)。要获得 ``std::cin`` 的常规行为,应用程序必须初始化 UART 驱动程序,并启用阻塞模式,详情请参阅 :example_file:`common_components/protocol_examples_common/stdin_out.c`。
|
||||
|
||||
|
||||
.. _cplusplus_limitations:
|
||||
|
||||
限制
|
||||
|
@ -181,6 +190,7 @@ ESP-IDF 支持 ``iostream`` 功能,但应注意:
|
|||
- vtable 位于 flash 中,在禁用 flash 缓存时无法访问。因此,在 :ref:`iram-safe-interrupt-handlers` 中应避免调用虚拟函数。目前尚无法使用链接器脚本生成器调整 vtable 的放置位置。
|
||||
- 不支持 C++ 文件系统 (``std::filesystem``) 功能。
|
||||
|
||||
|
||||
注意事项
|
||||
-------------
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
- :ref:`api_guide_dfu_build` 章节介绍了如何使用 ESP-IDF 构建固件。
|
||||
- :ref:`api_guide_dfu_flash` 章节介绍了如何烧录固件。
|
||||
|
||||
|
||||
USB 连接
|
||||
--------------
|
||||
|
||||
|
@ -37,7 +38,7 @@ USB 连接
|
|||
|
||||
.. warning::
|
||||
|
||||
一些连接线采用非标准颜色连接,有时调换下 D+ 和 D- 的连接,驱动程序就能正常工作。如果无法检测到您的设备,请尝试下调换 D+ 和 D- 的连接线。
|
||||
一些连接线采用非标准颜色连接,有时调换下 D+ 和 D- 的连接,驱动程序就能正常工作。如果无法检测到你的设备,请尝试下调换 D+ 和 D- 的连接线。
|
||||
|
||||
.. only:: esp32s3
|
||||
|
||||
|
@ -60,7 +61,9 @@ USB 连接
|
|||
idf.py dfu
|
||||
|
||||
.. note::
|
||||
在运行 ``idf.py dfu`` 命令前,请记得通过 ``idf.py set-target`` 命令设置目标芯片。否则,您创建的镜像可能不是针对目标芯片,或者收到类似 ``unknown target 'dfu'`` 的错误消息。
|
||||
|
||||
在运行 ``idf.py dfu`` 命令前,请记得通过 ``idf.py set-target`` 命令设置目标芯片。否则,你创建的镜像可能不是针对目标芯片,或者收到类似 ``unknown target 'dfu'`` 的错误消息。
|
||||
|
||||
|
||||
.. _api_guide_dfu_flash:
|
||||
|
||||
|
@ -84,10 +87,12 @@ USB 连接
|
|||
idf.py dfu-flash --path 1-2
|
||||
|
||||
.. note::
|
||||
|
||||
供应商和产品标识符的设置是基于使用 ``idf.py set-target`` 命令时所选的目标芯片,在调用 ``idf.py dfu-flash`` 时无法选择。
|
||||
|
||||
请参考 :ref:`api_guide_dfu_flash_errors` 及其解决方案。
|
||||
|
||||
|
||||
.. _api_guide_dfu_flash_udev:
|
||||
|
||||
Udev 规则(仅限 Linux)
|
||||
|
@ -100,24 +105,28 @@ Udev 是 Linux 内核的设备管理器,允许用户在没有 ``sudo`` 的情
|
|||
SUBSYSTEMS=="usb", ATTRS{idVendor}=="303a", ATTRS{idProduct}=="00??", GROUP="plugdev", MODE="0666"
|
||||
|
||||
.. note::
|
||||
请检查 ``groups`` 命令的输出。用户必须是上面指定的 `GROUP` 的成员。您可以为此使用其他现有的组(例如,在某些系统上使用 `uucp` 而不是 `plugdev`)或为此创建一个新的组。
|
||||
|
||||
您可以选择重启计算机使之前的设置生效,或者手动运行 ``sudo udevadm trigger``,强制 Udev 触发新规则。
|
||||
请检查 ``groups`` 命令的输出。用户必须是上面指定的 `GROUP` 的成员。你可以为此使用其他现有的组(例如,在某些系统上使用 `uucp` 而不是 `plugdev`)或为此创建一个新的组。
|
||||
|
||||
你可以选择重启计算机使之前的设置生效,或者手动运行 ``sudo udevadm trigger``,强制 Udev 触发新规则。
|
||||
|
||||
|
||||
.. _api_guide_dfu_flash_win:
|
||||
|
||||
USB 驱动(仅限 Windows)
|
||||
-------------------------------
|
||||
|
||||
``dfu-util`` 使用 `libusb` 来访问设备。您需要在 Windows 上使用 `WinUSB` 驱动程序注册设备。
|
||||
``dfu-util`` 使用 `libusb` 来访问设备。你需要在 Windows 上使用 `WinUSB` 驱动程序注册设备。
|
||||
|
||||
更多详细信息,请参考 `libusb wiki <https://github.com/libusb/libusb/wiki/Windows#How_to_use_libusb_on_Windows>`_。
|
||||
|
||||
可以通过 `Zadig 工具 <https://zadig.akeo.ie/>`_ 安装驱动程序。请确保在运行该工具之前设备处于下载模式,并确保在安装驱动程序之前检测到 {IDF_TARGET_NAME} 设备。Zadig 工具可能会检测到 {IDF_TARGET_NAME} 的多个 USB 接口。请只为没有安装驱动的接口(可能是接口 2)安装 WinUSB 驱动,不要重新安装其他接口驱动。
|
||||
|
||||
.. warning::
|
||||
|
||||
不建议在 Windows 的设备管理器中手动安装驱动程序,可能会造成无法正常烧录。
|
||||
|
||||
|
||||
.. _api_guide_dfu_flash_errors:
|
||||
|
||||
常见错误及已知问题
|
||||
|
@ -125,13 +134,14 @@ USB 驱动(仅限 Windows)
|
|||
|
||||
- 出现 ``dfu-util: command not found`` 错误可能是因为该工具尚未安装或是无法在终端使用。检查是否已经安装该工具的一种简单方法是运行 ``dfu-util --version`` 命令。请参考 :ref:`get-started-get-prerequisites` 安装 ``dfu-util``。
|
||||
|
||||
- 出现 ``No DFU capable USB device available`` 错误的原因可能是在 Windows 上没有正确安装 USB 驱动程序(请参考 :ref:`api_guide_dfu_flash_win`),或是未在 Linux 上设置 Udev 规则(请参考 :ref:`api_guide_dfu_flash_udev`),或是设备未处于引导加载程序模式。
|
||||
- 出现 ``No DFU capable USB device available`` 错误的原因可能是在 Windows 上没有正确安装 USB 驱动程序(请参考 :ref:`api_guide_dfu_flash_win`),或是未在 Linux 上设置 Udev 规则(请参考 :ref:`api_guide_dfu_flash_udev`),或是设备未处于引导加载程序模式。
|
||||
|
||||
- 在 Windows 上使用 ``dfu-util`` 第一次烧录失败,并出现 ``Lost device after RESET?`` 错误信息。出现此问题时,请重新烧录一次,再次烧录应该会成功。
|
||||
|
||||
|
||||
.. only:: SOC_SUPPORTS_SECURE_DL_MODE
|
||||
|
||||
安全下载模式
|
||||
--------------------
|
||||
|
||||
启用安全下载模式后,DFU 不再可用。请参见 :doc:`Flash 加密 <../security/flash-encryption>`,了解详细信息。
|
||||
启用安全下载模式后,DFU 不再可用。请参见 :doc:`../security/flash-encryption`,了解详细信息。
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
错误处理
|
||||
========
|
||||
|
||||
:link_to_translation:`en:[English]`
|
||||
|
||||
概述
|
||||
|
@ -24,6 +25,7 @@
|
|||
|
||||
关于如何处理不可恢复的错误,请查阅 :doc:`不可恢复错误 <fatal-errors>`。
|
||||
|
||||
|
||||
错误码
|
||||
------
|
||||
|
||||
|
@ -43,6 +45,7 @@ ESP-IDF 中大多数函数会返回 :cpp:type:`esp_err_t` 类型的错误码,
|
|||
|
||||
该功能(即在无法匹配 ``ESP_ERR_`` 值时,尝试用标准 POSIX 解释错误码)默认启用。用户也可以禁用该功能,从而减小应用程序的二进制文件大小,详情可见 :ref:`CONFIG_ESP_ERR_TO_NAME_LOOKUP`。注意,该功能对禁用并不影响 :cpp:func:`esp_err_to_name` 和 :cpp:func:`esp_err_to_name_r` 函数的定义,用户仍可调用这两个函数转化错误码。在这种情况下, :cpp:func:`esp_err_to_name` 函数在遇到无法匹配错误码的情况会返回 ``UNKNOWN ERROR``,而 :cpp:func:`esp_err_to_name_r` 函数会返回 ``Unknown error 0xXXXX(YYYYY)``,其中 ``0xXXXX`` 和 ``YYYYY`` 分别代表错误代码的十六进制和十进制表示。
|
||||
|
||||
|
||||
.. _esp-error-check-macro:
|
||||
|
||||
``ESP_ERROR_CHECK`` 宏
|
||||
|
@ -76,6 +79,7 @@ ESP-IDF 中大多数函数会返回 :cpp:type:`esp_err_t` 类型的错误码,
|
|||
|
||||
宏 :c:macro:`ESP_ERROR_CHECK_WITHOUT_ABORT` 的功能和 ``ESP_ERROR_CHECK`` 类似, 不同之处在于它不会调用 ``abort()``.
|
||||
|
||||
|
||||
.. _esp-return-on-error-macro:
|
||||
|
||||
``ESP_RETURN_ON_ERROR`` 宏
|
||||
|
@ -83,6 +87,7 @@ ESP-IDF 中大多数函数会返回 :cpp:type:`esp_err_t` 类型的错误码,
|
|||
|
||||
宏 :c:macro:`ESP_RETURN_ON_ERROR` 用于错误码检查, 如果错误码不等于 :c:macro:`ESP_OK`, 该宏会打印错误信息,并使原函数立刻返回。
|
||||
|
||||
|
||||
.. _esp-goto-on-error-macro:
|
||||
|
||||
``ESP_GOTO_ON_ERROR`` 宏
|
||||
|
@ -90,6 +95,7 @@ ESP-IDF 中大多数函数会返回 :cpp:type:`esp_err_t` 类型的错误码,
|
|||
|
||||
宏 :c:macro:`ESP_GOTO_ON_ERROR` 用于错误码检查, 如果错误码不等于 :c:macro:`ESP_OK`, 该宏会打印错误信息,将局部变量 `ret` 赋值为该错误码, 并使原函数跳转至给定的 `goto_tag`.
|
||||
|
||||
|
||||
.. _esp-return-on-false-macro:
|
||||
|
||||
``ESP_RETURN_ON_FALSE`` 宏
|
||||
|
@ -97,6 +103,7 @@ ESP-IDF 中大多数函数会返回 :cpp:type:`esp_err_t` 类型的错误码,
|
|||
|
||||
宏 :c:macro:`ESP_RETURN_ON_FALSE` 用于条件检查, 如果给定条件不等于 `true`, 该宏会打印错误信息,并使原函数立刻返回,返回值为给定的 `err_code`.
|
||||
|
||||
|
||||
.. _esp-goto-on-false-macro:
|
||||
|
||||
``ESP_GOTO_ON_FALSE`` 宏
|
||||
|
@ -104,6 +111,7 @@ ESP-IDF 中大多数函数会返回 :cpp:type:`esp_err_t` 类型的错误码,
|
|||
|
||||
宏 :c:macro:`ESP_GOTO_ON_FALSE` 用于条件检查, 如果给定条件不等于 `true`, 该宏会打印错误信息,将局部变量 `ret` 赋值为给定的 `err_code`, 并使原函数跳转至给定的 `goto_tag`.
|
||||
|
||||
|
||||
.. _check_macros_examples:
|
||||
|
||||
``CHECK 宏使用示例``
|
||||
|
@ -135,6 +143,7 @@ ESP-IDF 中大多数函数会返回 :cpp:type:`esp_err_t` 类型的错误码,
|
|||
|
||||
``ESP_RETURN_xx`` 和 ``ESP_GOTO_xx`` 宏不可以在中断服务程序里被调用。如需要在中断中使用类似功能,请使用 ``xx_ISR`` 宏,如 ``ESP_RETURN_ON_ERROR_ISR`` 等。
|
||||
|
||||
|
||||
错误处理模式
|
||||
------------
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ ESP-BLE-MESH 架构
|
|||
1. ESP-BLE-MESH 架构概览
|
||||
------------------------
|
||||
|
||||
目前,ESP-BLE-MESH 已经实现了 Mesh Profile 的大多数功能及 Mesh Model 规范中定义的所有 Client Model。未支持的功能/模型尚在开发中,会尽快提供。 ESP-BLE-MESH 已通过 Bluetooth SIG 蓝牙技术联盟的 `认证 <https://launchstudio.bluetooth.com/ListingDetails/76255>`__。
|
||||
目前,ESP-BLE-MESH 已经实现了 Mesh Profile 的大多数功能及 Mesh Model 规范中定义的所有 Client Model。未支持的功能/模型尚在开发中,会尽快提供。ESP-BLE-MESH 已通过 Bluetooth SIG 蓝牙技术联盟的 `认证 <https://launchstudio.bluetooth.com/ListingDetails/76255>`__。
|
||||
|
||||
.. figure:: ../../../_static/esp-ble-mesh-architecture.png
|
||||
:align: center
|
||||
|
@ -91,7 +91,7 @@ ESP-BLE-MESH 架构主要由以下 5 大部分组成:
|
|||
协议栈架构中的 ``Mesh Provisioning`` 实现了如下功能:
|
||||
|
||||
- 对未配网设备的配网。
|
||||
- Mesh 网络资源的分配 (单播地址、网络索引和网络秘钥)。
|
||||
- Mesh 网络资源的分配(单播地址、网络索引和网络秘钥)。
|
||||
- 配网期间对 4 种验证方法的支持。
|
||||
- 更多功能,请参见 :doc:`ble-mesh-feature-list`。
|
||||
|
||||
|
|
|
@ -88,7 +88,7 @@ ESP-BLE-MESH 常见问题手册
|
|||
|
||||
- Device UUID
|
||||
- OOB Info
|
||||
- URL Hash (可选的)
|
||||
- URL Hash(可选的)
|
||||
|
||||
1.12 这些信息可以用于设备识别吗?
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
@ -385,7 +385,7 @@ ESP-BLE-MESH 常见问题手册
|
|||
|
||||
- 模型分为两种,客户端模型和服务器模型。客户端模型可以获取并设置服务器模型的状态。
|
||||
|
||||
- 模型也可以分为 SIG 模型和自定义模型。 SIG 模型的所有行为都由官方定义,而自定义模型的行为均由用户定义。
|
||||
- 模型也可以分为 SIG 模型和自定义模型。SIG 模型的所有行为都由官方定义,而自定义模型的行为均由用户定义。
|
||||
|
||||
2.2 每个模型对应的消息格式是不是固定的?
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
@ -536,11 +536,11 @@ ESP-BLE-MESH 常见问题手册
|
|||
|
||||
应使能 menuconfig 中的一些配置来支持 PSRAM。
|
||||
|
||||
- :code:`{IDF_TARGET_NAME}-specific --> Support for external,SPI-connected RAM --> Try to allocate memories of Wi-Fi and LWIP...`
|
||||
- :code:`Bluetooth --> Bluedriod Enable --> BT/BLE will first malloc the memory from the PSRAM`
|
||||
- :code:`Bluetooth --> Bluedriod Enable --> Use dynamic memory allocation in BT/BLE stack.`
|
||||
- :code:`Bluetooth --> Blutooth controller --> BLE full scan feature supported.`
|
||||
- :code:`Wi-Fi --> Software controls Wi-Fi/Bluetooth coexistence --> Wi-Fi`
|
||||
- ``{IDF_TARGET_NAME}-specific`` > ``Support for external,SPI-connected RAM`` > ``Try to allocate memories of Wi-Fi and LWIP...``
|
||||
- ``Bluetooth`` > ``Bluedroid Enable`` > ``BT/BLE will first malloc the memory from the PSRAM``
|
||||
- ``Bluetooth`` > ``Bluedroid Enable`` > ``Use dynamic memory allocation in BT/BLE stack``
|
||||
- ``Bluetooth`` > ``Bluetooth controller`` > ``BLE full scan feature supported``
|
||||
- ``Wi-Fi`` > ``Software controls Wi-Fi/Bluetooth coexistence`` > ``Wi-Fi``
|
||||
|
||||
|
||||
.. _ble-mesh-faq-fast-provisioning:
|
||||
|
@ -563,7 +563,7 @@ ESP-BLE-MESH 常见问题手册
|
|||
|
||||
每完成一次快速配网后、开始新一次快速配网前,APP 会存有上次配网的数据,因此 APP 中显示的节点地址的数量比现有的节点地址更多。
|
||||
|
||||
4.4 在 EspBleMesh App 中输入的 ** count ** 值有什么用途?
|
||||
4.4 在 EspBleMesh App 中输入的 **count** 值有什么用途?
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
此 **count** 值提供给 App 配置的代理节点,以决定何时提前开始 Proxy 广播信息。
|
||||
|
@ -584,39 +584,39 @@ ESP-BLE-MESH 常见问题手册
|
|||
5. Log 帮助
|
||||
-----------
|
||||
|
||||
当 ESP-BLE-MESH 协议栈底层出现错误或者警告时,您可以在这儿找到这些错误和警告的含义。
|
||||
当 ESP-BLE-MESH 协议栈底层出现错误或者警告时,可以在这儿找到这些错误和警告的含义。
|
||||
|
||||
5.1 :code:`ran out of retransmit attempts` 代表什么?
|
||||
5.1 ``ran out of retransmit attempts`` 代表什么?
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
节点发送分段消息时,由于某些原因,接收端未收到完整的消息。节点会重传消息。当重传次数达到最大重传数时,会出现该警告,当前最大重传数为 4。
|
||||
|
||||
5.2 :code:`Duplicate found in Network Message Cache` 代表什么?
|
||||
5.2 ``Duplicate found in Network Message Cache`` 代表什么?
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
当节点收到一条消息时,它会把该消息与网络缓存中存储的消息进行比较。如果在缓存中找到相同的消息,这意味着之前已接受过该消息,则该消息会被丢弃。
|
||||
|
||||
5.3 :code:`Incomplete timer expired` 代表什么?
|
||||
5.3 ``Incomplete timer expired`` 代表什么?
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
当节点在一定时间段(比如 10 秒)内未收到分段消息的所有段时,则 Incomplete 计时器到时,并且出现该警告。
|
||||
|
||||
5.4 :code:`No matching TX context for ack` 代表什么?
|
||||
5.4 ``No matching TX context for ack`` 代表什么?
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
当节点收到一个分段 ack 且不能找到任何自己发送的与该 ack 相关的消息时,会出现该警告。
|
||||
|
||||
5.5 :code:`No free slots for new incoming segmented messages` 代表什么?
|
||||
5.5 ``No free slots for new incoming segmented messages`` 代表什么?
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
当节点没有空间来接收新的分段消息时,会出现该警告。用户可以通过配置 :ref:`CONFIG_BLE_MESH_RX_SEG_MSG_COUNT` 扩大空间。
|
||||
|
||||
5.6 :code:`Model not bound to AppKey 0x0000` 代表什么?
|
||||
5.6 ``Model not bound to AppKey 0x0000`` 代表什么?
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
当节点发送带有模型的消息且该模型尚未绑定到索引为 0x000 的应用密钥时,会出现该报错。
|
||||
|
||||
5.7 :code:`Busy sending message to DST xxxx` 代表什么?
|
||||
5.7 ``Busy sending message to DST xxxx`` 代表什么?
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
该错误表示节点的客户端模型已将消息发送给目标节点,并且正在等待响应,用户无法将消息发送到单播地址相同的同一节点。接收到相应的响应或计时器到时后,可以发送另一条消息。
|
||||
|
|
|
@ -20,7 +20,7 @@ ESP-BLE-MESH 的实现和认证基于最新的 `Mesh Profile v1.0.1 <https://www
|
|||
|
||||
.. note::
|
||||
|
||||
如果您在寻找 ESP32 基于 Wi-Fi 的 mesh 方案,请查阅乐鑫的另一款产品 ESP-WIFI-MESH。更多相关信息及文档,请参见 :doc:`ESP-WIFI-MESH <../../api-reference/network/esp-wifi-mesh>`。
|
||||
如果你在寻找 ESP32 基于 Wi-Fi 的 mesh 方案,请查阅乐鑫的另一款产品 ESP-WIFI-MESH。更多相关信息及文档,请参见 :doc:`ESP-WIFI-MESH <../../api-reference/network/esp-wifi-mesh>`。
|
||||
|
||||
|
||||
.. _getting-started-with-ble-mesh:
|
||||
|
@ -28,11 +28,11 @@ ESP-BLE-MESH 的实现和认证基于最新的 `Mesh Profile v1.0.1 <https://www
|
|||
ESP-BLE-MESH 快速入门
|
||||
=====================
|
||||
|
||||
该章节旨在帮助您基于乐鑫的 ESP32 开发板搭建 ESP-BLE-MESH 网络。
|
||||
该章节旨在帮助你基于乐鑫的 ESP32 开发板搭建 ESP-BLE-MESH 网络。
|
||||
|
||||
我们将会展示如何搭建并运行一个包含 3 个节点的小型 ESP-BLE-MESH 网络,其中包含设备配网、节点配置,以及向特定节点上的 Generic OnOff Server Model 发送开关灯命令。
|
||||
|
||||
如果您是第一次接触 ESP-IDF,请参见 esp-idf :doc:`../../get-started/index` 来设置开发环境,编译、烧写和运行示例应用程序。
|
||||
如果你是第一次接触 ESP-IDF,请参见 esp-idf :doc:`../../get-started/index` 来设置开发环境,编译、烧写和运行示例应用程序。
|
||||
|
||||
|
||||
硬件及软件准备
|
||||
|
@ -56,7 +56,7 @@ ESP-BLE-MESH 快速入门
|
|||
安装
|
||||
----
|
||||
|
||||
以下详细步骤可指导您完成安装过程。
|
||||
以下详细步骤可指导你完成安装过程。
|
||||
|
||||
|
||||
.. _get-started-ble-mesh-check-hardware:
|
||||
|
@ -64,11 +64,11 @@ ESP-BLE-MESH 快速入门
|
|||
步骤 1. 检查硬件
|
||||
"""""""""""""""""
|
||||
|
||||
`ESP32-DevKitC`_ 和 `ESP-WROVER-KIT`_ 开发板均支持 ESP-BLE-MESH。您可以通过 menuconfig: :code:`idf.py menuconfig` > ``Example Configuration`` > ``Board selection for ESP-BLE-MESH`` 选择特定的开发板。
|
||||
`ESP32-DevKitC`_ 和 `ESP-WROVER-KIT`_ 开发板均支持 ESP-BLE-MESH。你可以通过 menuconfig: :code:`idf.py menuconfig` > ``Example Configuration`` > ``Board selection for ESP-BLE-MESH`` 选择特定的开发板。
|
||||
|
||||
.. note::
|
||||
|
||||
如果您打算使用 `ESP32-DevKitC`_ 开发板,请将 RGB 灯焊接至 GPIO 管脚 25、26 和 27。
|
||||
如果你打算使用 `ESP32-DevKitC`_ 开发板,请将 RGB 灯焊接至 GPIO 管脚 25、26 和 27。
|
||||
|
||||
|
||||
步骤 2. 配置软件
|
||||
|
|
|
@ -115,6 +115,7 @@ ESP-WIFI-MESH 建立在传统 Wi-Fi 协议之上,可被视为一种将多个
|
|||
ESP-WIFI-MESH 是一个多跳网络,也就是说网络中的节点可以通过单跳或多跳向网络中的其他节点传送数据包。因此,ESP-WIFI-MESH 中的节点不仅传输自己的数据包,而且同时充当其他节点的中继。假设 ESP-WIFI-MESH 网络中的任意两个节点存在物理层上连接(通过单跳或多跳),则这两个节点可以进行通信。
|
||||
|
||||
.. note::
|
||||
|
||||
ESP-WIFI-MESH 网络中的大小(节点总数)取决于网络中允许的最大层级,以及每个节点可以具有的最大下行连接数。因此,这两个变量可用于配置 ESP-WIFI-MESH 网络的大小。
|
||||
|
||||
节点类型
|
||||
|
@ -140,7 +141,7 @@ ESP-WIFI-MESH 是一个多跳网络,也就是说网络中的节点可以通过
|
|||
|
||||
ESP-WIFI-MESH 中能够形成下行连接的每个节点(即具有 SoftAP 接口)都会定期传输 Wi-Fi 信标帧。节点可以通过信标帧让其他节点检测自己的存在和状态。空闲节点将侦听信标帧以生成一个潜在父节点列表,并与其中一个潜在父节点形成上行连接。ESP-WIFI-MESH 使用“供应商信息元素”来存储元数据,例如:
|
||||
|
||||
- 节点类型(根节点、中间父节点、叶子节点、空闲节点)
|
||||
- 节点类型(根节点、中间父节点、叶子节点、空闲节点)
|
||||
- 节点当前所处的层级
|
||||
- 网络中允许的最大层级
|
||||
- 当前子节点数量
|
||||
|
@ -160,6 +161,7 @@ ESP-WIFI-MESH 中能够形成下行连接的每个节点(即具有 SoftAP 接
|
|||
**上图(B 侧)** 展示了 RF 屏蔽物将如何降低潜在父节点的 RSSI。由于存在 RF 屏蔽物,节点 X 的 RSSI 高于阈值的区域显著减小。这会导致空闲节点忽略节点 X,即使从地理位置上看 X 就在空闲节点附近。相反,该空闲节点将从更远的地方找到一个 RSSI 更强的节点 Y 形成上行连接。
|
||||
|
||||
.. note::
|
||||
|
||||
事实上,ESP-WIFI-MESH 网络中的节点在 MAC 层仍可以接收所有的信标帧,但 RSSI 阈值控制功能可以过滤掉所有 RSSI 低于预设阈值的信标帧。
|
||||
|
||||
首选父节点
|
||||
|
@ -186,6 +188,7 @@ ESP-WIFI-MESH 中能够形成下行连接的每个节点(即具有 SoftAP 接
|
|||
**上图(B 侧)** 展示了空闲节点 G 如何在根节点 A 和其他候选父节点中选择首选父节点,此时根节点 A 处于空闲节点 G 范围之内(即空闲节点 G 接收到的根节点 A 信标帧 RSSI 强度高于预设阈值):由于根节点 A 处于网络中最浅的层,因此将成为首选父节点。
|
||||
|
||||
.. note::
|
||||
|
||||
用户还可以自行定义首选父节点的选择规则,也可以直接指定某个节点为首选父节点(见 :example:`Mesh 手动配网示例 <mesh/manual_networking>`)。
|
||||
|
||||
路由表
|
||||
|
@ -209,6 +212,7 @@ ESP-WIFI-MESH 网络中的每个节点均会维护自己的路由表,并按路
|
|||
**2.** 如果数据包的目标 MAC 地址不在当前节点的路由表内,则将数据包向上转发给当前节点的父节点,并重复执行该操作直至数据包达到目标地址。此步骤可重复至根节点(根节点包含整个网络的全部节点)。
|
||||
|
||||
.. note::
|
||||
|
||||
用户可以通过调用 :cpp:func:`esp_mesh_get_routing_table` 获取一个节点的路由表,调用 :cpp:func:`esp_mesh_get_routing_table_size` 获取一个路由表的大小,也可通过调用 :cpp:func:`esp_mesh_get_subnet_nodes_list` 获取某个子节点的子路由表,调用 :cpp:func:`esp_mesh_get_subnet_nodes_num` 获取子路由表的大小。
|
||||
|
||||
|
||||
|
@ -223,6 +227,7 @@ ESP-WIFI-MESH 网络中的每个节点均会维护自己的路由表,并按路
|
|||
^^^^^^^^^^^^^^^
|
||||
|
||||
.. warning::
|
||||
|
||||
ESP-WIFI-MESH 正式开始构建网络前,必须确保网络中所有节点具有相同的配置(见 :cpp:type:`mesh_cfg_t`)。每个节点必须配置 **相同 MESH 网络 ID、路由器配置和 SoftAP 配置**。
|
||||
|
||||
ESP-WIFI-MESH 网络将首先选择根节点,然后逐层形成下行连接,直到所有节点均加入网络。网络的布局可能取决于诸如根节点选择、父节点选择和异步上电复位等因素。但简单来说,一个 ESP-WIFI-MESH 网络的构建过程可以概括为以下步骤:
|
||||
|
@ -270,16 +275,18 @@ ESP-WIFI-MESH 网络将首先选择根节点,然后逐层形成下行连接,
|
|||
|
||||
**1.** 上电复位时,每个节点开始传输自己的信标帧(包括 MAC 地址和路由器 RSSI 值)。
|
||||
|
||||
**2.** 在多次传输和扫描迭代中,路由器 RSSI 最强的信标帧将在整个网络中传播。节点 C 具有最强的路由器 RSSI 值(-10 dB),因此它的信标帧将在整个网络中传播。所有参与选举的节点均给节点 C 投票,因此节点 C 的得票百分比为 100%。因此,节点 C 成为根节点,并与路由器连接。
|
||||
**2.** 在多次传输和扫描迭代中,路由器 RSSI 最强的信标帧将在整个网络中传播。节点 C 具有最强的路由器 RSSI 值 (-10 dB),因此它的信标帧将在整个网络中传播。所有参与选举的节点均给节点 C 投票,因此节点 C 的得票百分比为 100%。因此,节点 C 成为根节点,并与路由器连接。
|
||||
|
||||
**3.** 一旦节点 C 与路由器连接,节点 C 将成为节点 A/B/D/E 的首选父节点(即最浅的节点),并与这些节点连接。节点 A/B/D/E 将形成网络的第二层。
|
||||
|
||||
**4.** 节点 F 和节点 G 分别连接节点 D 和节点 E,并完成网络构建过程。
|
||||
|
||||
.. note::
|
||||
|
||||
用户可以通过 :cpp:func:`esp_mesh_set_attempts` 配置选举的最小迭代次数。用户应根据网络内的节点数量配置迭代次数(即 mesh 网络越大,所需的迭代次数越高)。
|
||||
|
||||
.. warning::
|
||||
|
||||
**得票百分比阈值** 也可以使用 :cpp:func:`esp_mesh_set_vote_percentage` 进行配置。得票百分比阈值过低 **可能导致同一 mesh 网络中两个或多个节点成为根节点**,进而分化为多个 mesh 网络。如果发生这种情况,ESP-WIFI-MESH 具有内部机制,可自主解决 **根节点冲突**。这些具有多个根节点的网络将围绕一个根节点形成一个网络。然而,两个或多个路由器 SSID 相同但路由器 BSSID 不同的根节点冲突尚无法解决。
|
||||
|
||||
用户指定根节点
|
||||
|
@ -303,6 +310,7 @@ ESP-WIFI-MESH 网络将首先选择根节点,然后逐层形成下行连接,
|
|||
**4.** 节点 G 将与节点 E 连接,形成网络的第四层。然而,由于该网络的最大允许层级已配置为 4,因此节点 G 将成为叶子节点,以防止形成任何新层。
|
||||
|
||||
.. note::
|
||||
|
||||
一旦指定根节点,该根节点应调用 :cpp:func:`esp_mesh_set_parent` 使其直接与路由器连接。类似地,所有其他节点都应该调用 :cpp:func:`esp_mesh_fix_root` 放弃选举过程。
|
||||
|
||||
选择父节点
|
||||
|
@ -340,10 +348,11 @@ ESP-WIFI-MESH 网络构建可能会受到节点上电顺序的影响。如果网
|
|||
|
||||
**4.** 节点 B 由于所处层级变化(现为第二层)而成为新的首选父节点,因此节点 D/G 将切换其上行连接从而选择新的首选父节点。由于切换的发生,最终的网络层级从原来的五层减少至三层。
|
||||
|
||||
**同步上电**:如果所有节点均同步上电,节点 E (-10 dB)由于路由器 RSSI 最强而成为根节点。此时形成的网络结构将与异步上电的情况截然不同。**但是,如果用户手动切换根节点,则仍可以达到同步上电的网络结构** (请见 :cpp:func:`esp_mesh_waive_root`)。
|
||||
**同步上电**:如果所有节点均同步上电,节点 E (-10 dB) 由于路由器 RSSI 最强而成为根节点。此时形成的网络结构将与异步上电的情况截然不同。**但是,如果用户手动切换根节点,则仍可以达到同步上电的网络结构** (请见 :cpp:func:`esp_mesh_waive_root`)。
|
||||
|
||||
.. note::
|
||||
从某种程度上,ESP-WIFI-MESH 可以自动修复部分因异步上电引起的父节点选择的偏差(请见 `父节点切换`_)
|
||||
|
||||
从某种程度上,ESP-WIFI-MESH 可以自动修复部分因异步上电引起的父节点选择的偏差(请见 `父节点切换`_)
|
||||
|
||||
环路避免、检测和处理
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
@ -382,6 +391,7 @@ ESP-WIFI-MESH 网络构建可能会受到节点上电顺序的影响。如果网
|
|||
**3.** 节点 B 被选为根节点,并开始接受下行连接。剩余的第二层节点 A/D/E 形成与节点 B 的上行连接,因此网络已经恢复,并且可以继续正常运行。
|
||||
|
||||
.. note::
|
||||
|
||||
如果是手动指定的根节点断开,则无法进行自动修复。**任何节点不会在存在指定根节点的情况下开始选举过程**。
|
||||
|
||||
中间父节点故障
|
||||
|
@ -407,6 +417,7 @@ ESP-WIFI-MESH 网络构建可能会受到节点上电顺序的影响。如果网
|
|||
**3.** 节点 G 因其范围内不存在任何父节点而暂时保持空闲。节点 F 的范围中有 B 和 E 两个节点,但节点 B 因为所处层级更浅而当选新的父节点。节点 F 将与节点 B 连接后,并成为一个中间父节点,节点 G 将于节点 F 相连。这样一来,网络已经恢复了,但结构发生了变化(网络层级增加了 1 层)。
|
||||
|
||||
.. note::
|
||||
|
||||
如果子节点的父节点已被指定,则子节点不会尝试与其他潜在父节点连接。此时,该子节点将无限期地保持空闲状态。
|
||||
|
||||
根节点切换
|
||||
|
@ -436,6 +447,7 @@ ESP-WIFI-MESH 网络构建可能会受到节点上电顺序的影响。如果网
|
|||
**4.** 节点 C 选择节点 B 作为其的首选父节点,与之形成上行连接,并成为一个第二层节点。由于节点 C 仍保持相同的子网,因此根节点切换后的网络结构没有变化。然后,由于切换的发生,节点 C 子网中每个节点的所处层级均增加了一层。如果根节点切换过程中产生了新的根节点,则 `父节点切换`_ 可以随后调整网络结构。
|
||||
|
||||
.. note::
|
||||
|
||||
根节点切换必须要求选举,因此只有在使用自组网 ESP-WIFI-MESH 网络时才支持。换句话说,如果使用指定的根节点,则不能进行根节点切换。
|
||||
|
||||
父节点切换
|
||||
|
@ -472,6 +484,7 @@ ESP-WIFI-MESH 数据包的 **报头** 包含源节点和目标节点的 MAC 地
|
|||
ESP-WIFI-MESH 数据包的 **有效载荷** 包含实际的应用数据。该数据可以为原始二进制数据,也可以是使用 HTTP、MQTT 和 JSON 等应用层协议的编码数据(请见::cpp:type:`mesh_proto_t`)。
|
||||
|
||||
.. note::
|
||||
|
||||
当向外部 IP 网络发送 ESP-WIFI-MESH 数据包时,报头的目标地址字段将包含目标服务器的 IP 地址和端口号,而不是节点的 MAC 地址(请见::cpp:type:`mesh_addr_t`)。此外,根节点将处理外发 TCP/IP 数据包的形成。
|
||||
|
||||
组控制和组播
|
||||
|
@ -484,6 +497,7 @@ ESP-WIFI-MESH 数据包的 **有效载荷** 包含实际的应用数据。该数
|
|||
分组组播允许 ESP-WIFI-MESH 数据包被发送到一个预先配置的节点组。每个分组都有一个具有唯一性的 ID 标识。用户可通过 :cpp:func:`esp_mesh_set_group_id` 将节点加入一个组。分组组播需要将 ESP-WIFI-MESH 数据包的目标地址设置为目标组的 ID,还必须设置 :c:macro:`MESH_DATA_GROUP` 标志位。分组组播产生的开销更小,但必须提前将节点加入分组中。
|
||||
|
||||
.. note::
|
||||
|
||||
在组播期间,网络中的所有节点在 MAC 层都会收到 ESP-WIFI-MESH 数据包。然而,不包括在 MAC 地址列表或目标组中的节点将简单地过滤掉这些数据包。
|
||||
|
||||
广播
|
||||
|
@ -519,9 +533,11 @@ ESP-WIFI-MESH 依赖父节点来控制其直接子节点的上行数据流。为
|
|||
**3.** 子节点根据父节点指定的窗口大小发送数据包。如果子节点的接收窗口耗尽,它必须通过发送请求获得另一个接收窗口,然后才允许继续发送。
|
||||
|
||||
.. note::
|
||||
|
||||
ESP-WIFI-MESH 不支持任何下行流量控制。
|
||||
|
||||
.. warning::
|
||||
|
||||
由于 `父节点切换`_,数据包可能会在上行传输期间丢失。
|
||||
|
||||
由于根节点是通向外部 IP 网络的唯一接口,因此下行节点必须了解根节点与外部 IP 网络的连接状态。否则,节点可能会尝试向一个已经与 IP 网络断开连接的根节点发送数据,从而造成不必要的传输和数据包丢失。ESP-WIFI-MESH 可以基于监测根节点和外部 IP 网络的连接状态,提供一种稳定外发数据吞吐量的机制。根节点可以通过调用 :cpp:func:`esp_mesh_post_toDS_state` 将自身与外部 IP 网络的连接状态广播给所有其他节点。
|
||||
|
@ -599,6 +615,7 @@ ESP-WIFI-MESH 网络及其路由器可能具有不同且变化的信标间隔,
|
|||
- 根节点将在整个过程中维护与之相连的下行连接。
|
||||
|
||||
.. note::
|
||||
|
||||
虽然 ESP-WIFI-MESH 网络信道切换的目的是将网络内的所有节点移动到新的工作信道,但也应该认识到,信道切换可能无法成功移动所有节点(比如由于节点故障等原因)。
|
||||
|
||||
信道和路由器切换配置
|
||||
|
@ -728,6 +745,7 @@ ESP-WIFI-MESH 网络的常见性能指标如下表所示:
|
|||
* 每条延迟:10 到 30 毫秒
|
||||
|
||||
.. note::
|
||||
|
||||
上述性能指标的测试条件见下。
|
||||
|
||||
- 测试设备数量:**100**
|
||||
|
@ -735,12 +753,15 @@ ESP-WIFI-MESH 网络的常见性能指标如下表所示:
|
|||
- 最大允许层级:**6**
|
||||
|
||||
.. note::
|
||||
|
||||
吞吐量取决于数据包错误率和 hop 数量。
|
||||
|
||||
.. note::
|
||||
|
||||
根节点访问外部 IP 网络的吞吐量直接受到 ESP-WIFI-MESH 网络中节点数量和路由器带宽的影响。
|
||||
|
||||
.. note::
|
||||
|
||||
用户应注意,ESP-WIFI-MESH 网络的性能与网络配置和工作环境密切相关。
|
||||
|
||||
.. -----------------------------更多注意事项 --------------------------------
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
简介
|
||||
============
|
||||
|
||||
{IDF_TARGET_PSRAM_VADDR_SIZE:default="Value not updated", esp32="4 MB", esp32s2="10.5 MB", esp32s3="32 MB"}
|
||||
|
||||
{IDF_TARGET_NAME} 提供了好几百 KB 的片上 RAM,可以满足大部分需求。但有些场景可能需要更多 RAM,因此 {IDF_TARGET_NAME} 另外提供了高达 {IDF_TARGET_PSRAM_VADDR_SIZE} 的虚拟地址,供片外 PSRAM(伪静态随机存储器)存储器使用。片外 RAM 已经集成到内存映射中,在某些范围内与片上 RAM 使用方式相同。
|
||||
|
@ -37,7 +38,7 @@
|
|||
配置片外 RAM
|
||||
========================
|
||||
|
||||
ESP-IDF 完全支持将片外 RAM 集成到您的应用程序中。在启动并完成片外 RAM 初始化后,可以将 ESP-IDF 配置为用多种方式处理片外 RAM:
|
||||
ESP-IDF 完全支持将片外 RAM 集成到你的应用程序中。在启动并完成片外 RAM 初始化后,可以将 ESP-IDF 配置为用多种方式处理片外 RAM:
|
||||
|
||||
.. list::
|
||||
|
||||
|
@ -200,7 +201,7 @@ ESP-IDF 启动过程中,片外 RAM 被映射到数据虚拟地址空间,该
|
|||
|
||||
可以为存储在外部 RAM 中的数据启用自动加密功能。启用该功能后,通过缓存读写的任何数据将被外部存储器加密硬件自动加密/解密。
|
||||
|
||||
只要启用了 flash 加密功能,就会启用这个功能。关于如何启用 flash 加密以及其工作原理,请参考 :doc:`Flash 加密 </security/flash-encryption>`。
|
||||
只要启用了 flash 加密功能,就会启用这个功能。关于如何启用 flash 加密以及其工作原理,请参考 :doc:`/security/flash-encryption`。
|
||||
|
||||
|
||||
.. only:: esp32
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
严重错误
|
||||
========
|
||||
|
||||
:link_to_translation:`en:[English]`
|
||||
|
||||
.. _Overview:
|
||||
|
@ -31,7 +32,7 @@
|
|||
紧急处理程序
|
||||
------------
|
||||
|
||||
:ref:`Overview` 中列举的所有错误都会由 *紧急处理程序(Panic Handler)* 负责处理。
|
||||
:ref:`Overview` 中列举的所有错误都会由 *紧急处理程序 (Panic Handler)* 负责处理。
|
||||
|
||||
紧急处理程序首先会将出错原因打印到控制台,例如 CPU 异常的错误信息通常会类似于
|
||||
|
||||
|
@ -163,7 +164,7 @@
|
|||
|
||||
.. only:: CONFIG_IDF_TARGET_ARCH_XTENSA
|
||||
|
||||
在某些情况下,例如中断看门狗超时,紧急处理程序会额外打印 CPU 寄存器(EPC1-EPC4)的值,以及另一个 CPU 的寄存器值和代码回溯。
|
||||
在某些情况下,例如中断看门狗超时,紧急处理程序会额外打印 CPU 寄存器 (EPC1-EPC4) 的值,以及另一个 CPU 的寄存器值和代码回溯。
|
||||
|
||||
回溯行包含了当前任务中每个堆栈帧的 PC:SP 对(PC 是程序计数器,SP 是堆栈指针)。如果在 ISR 中发生了严重错误,回溯会同时包括被中断任务的 PC:SP 对,以及 ISR 中的 PC:SP 对。
|
||||
|
||||
|
@ -237,10 +238,10 @@
|
|||
|
||||
Backtrace: 0x42009e9a:0x3fc92120 0x42009ea6:0x3fc92120 0x42009ec2:0x3fc92130 0x42024620:0x3fc92150 0x40387d7c:0x3fc92160 0xfffffffe:0x3fc92170
|
||||
|
||||
这些 ``PC:SP`` 对代表当前任务每一个栈帧的程序计数器值(Program Counter)和栈顶地址(Stack Pointer)。
|
||||
这些 ``PC:SP`` 对代表当前任务每一个栈帧的程序计数器值 (Program Counter) 和栈顶地址 (Stack Pointer)。
|
||||
|
||||
|
||||
:ref:`CONFIG_ESP_SYSTEM_USE_EH_FRAME` 选项的主要优点是,回溯信息可以由程序自己解析生成并打印 (而不依靠 :doc:`IDF 监视器 <tools/idf-monitor>`)。但是该选项会导致编译后的二进制文件更大(增幅可达 20% 甚至 100%)。此外,该选项会将调试信息也保存在二进制文件里。因此,强烈不建议用户在量产/生产版本中启用该选项。
|
||||
:ref:`CONFIG_ESP_SYSTEM_USE_EH_FRAME` 选项的主要优点是,回溯信息可以由程序自己解析生成并打印(而不依靠 :doc:`tools/idf-monitor`)。但是该选项会导致编译后的二进制文件更大(增幅可达 20% 甚至 100%)。此外,该选项会将调试信息也保存在二进制文件里。因此,强烈不建议用户在量产/生产版本中启用该选项。
|
||||
|
||||
若要查找发生严重错误的代码位置,请查看 "Backtrace" 的后面几行,发生严重错误的代码显示在顶行,后续几行显示的是调用堆栈。
|
||||
|
||||
|
@ -303,7 +304,9 @@ Guru Meditation 错误
|
|||
|
||||
本节将对打印在 ``Guru Meditation Error: Core panic'ed`` 后面括号中的致错原因进行逐一解释。
|
||||
|
||||
.. note:: 想要了解 "Guru Meditation" 的历史渊源,请参阅 `维基百科 <https://en.wikipedia.org/wiki/Guru_Meditation>`_ 。
|
||||
.. note::
|
||||
|
||||
想要了解 "Guru Meditation" 的历史渊源,请参阅 `维基百科 <https://en.wikipedia.org/wiki/Guru_Meditation>`_ 。
|
||||
|
||||
|
||||
|ILLEGAL_INSTR_MSG|
|
||||
|
@ -399,7 +402,7 @@ Interrupt wdt timeout on CPU0 / CPU1
|
|||
ESP-IDF 中使用 {IDF_TARGET_NAME} 的权限控制功能来防止以下类型的内存访问:
|
||||
|
||||
* 程序加载后向指令 RAM 写入代码
|
||||
* 从数据 RAM (用于堆、静态 .data 和 .bss 区域)执行代码
|
||||
* 从数据 RAM(用于堆、静态 .data 和 .bss 区域)执行代码
|
||||
|
||||
该类操作对于大多数程序来说并不必要,禁止此类操作往往使软件漏洞更难被利用。依赖动态加载或自修改代码的应用程序可以使用 :ref:`CONFIG_ESP_SYSTEM_MEMPROT_FEATURE` 选项来禁用此项保护。
|
||||
|
||||
|
@ -552,7 +555,9 @@ FreeRTOS 堆栈检查
|
|||
idf_component_get_property(lib component_name COMPONENT_LIB)
|
||||
target_compile_options(${lib} PRIVATE "-fsanitize=undefined" "-fno-sanitize=shift-base")
|
||||
|
||||
.. 注意:: 关于 :ref:`构建属性 <cmake-build-properties>` 和 :ref:`组件属性 <cmake-component-properties>` 的更多信息,请查看构建系统文档。
|
||||
.. 注意::
|
||||
|
||||
关于 :ref:`构建属性 <cmake-build-properties>` 和 :ref:`组件属性 <cmake-component-properties>` 的更多信息,请查看构建系统文档。
|
||||
|
||||
要为同一组件的 CMakeLists.txt 中的特定组件(``component_name``)使能 UBSAN,在文件末尾添加以下内容::
|
||||
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
******************************
|
||||
Linux 环境下从源码编译 OpenOCD
|
||||
******************************
|
||||
|
||||
:link_to_translation:`en:[English]`
|
||||
|
||||
除了从 `Espressif 官方 <https://github.com/espressif/openocd-esp32/releases>`_ 直接下载 OpenOCD 可执行文件,你还可以选择从源码编译得到 OpenOCD。如果想要快速设置 OpenOCD 而不是自行编译,请备份好当前文件,前往 :ref:`jtag-debugging-setup-openocd` 章节查阅。
|
||||
|
||||
|
||||
.. highlight:: bash
|
||||
.. code-block:: bash
|
||||
|
||||
下载 OpenOCD 源码
|
||||
=================
|
||||
|
@ -64,7 +65,7 @@ Linux 环境下从源码编译 OpenOCD
|
|||
* 如果发生错误,请解决后再次尝试编译,直到 ``make`` 成功为止。
|
||||
* 如果 OpenOCD 存在子模块问题,请 ``cd`` 到 ``openocd-esp32`` 目录,并输入 ``git submodule update --init`` 命令。
|
||||
* 如果 ``./configure`` 成功运行,JTAG 被使能的信息会被打印在 ``OpenOCD configuration summary`` 下面。
|
||||
* 如果您的设备信息未显示在日志中,请根据 ``../openocd-esp32/doc/INSTALL.txt`` 文中的描述使用 ``./configure`` 启用它。
|
||||
* 如果你的设备信息未显示在日志中,请根据 ``../openocd-esp32/doc/INSTALL.txt`` 文中的描述使用 ``./configure`` 启用它。
|
||||
* 有关编译 OpenOCD 的详细信息,请参阅 ``openocd-esp32/README``。
|
||||
|
||||
一旦 ``make`` 过程成功结束,OpenOCD 的可执行文件会被保存到 ``~/openocd-esp32/bin`` 目录中。
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
******************************
|
||||
MacOS 环境下从源码编译 OpenOCD
|
||||
******************************
|
||||
|
||||
:link_to_translation:`en:[English]`
|
||||
|
||||
除了从 `Espressif 官方 <https://github.com/espressif/openocd-esp32/releases>`_ 直接下载 OpenOCD 可执行文件,你还可以选择从源码编译得到 OpenOCD。如果想要快速设置 OpenOCD 而不是自行编译,请备份好当前文件,前往 :ref:`jtag-debugging-setup-openocd` 章节查阅。
|
||||
|
||||
.. highlight:: bash
|
||||
.. code-block:: bash
|
||||
|
||||
下载 OpenOCD 源码
|
||||
=================
|
||||
|
@ -48,7 +49,7 @@ MacOS 环境下从源码编译 OpenOCD
|
|||
|
||||
* 如果 OpenOCD 存在子模块问题,请 ``cd`` 到 ``openocd-esp32`` 目录,并输入 ``git submodule update --init`` 命令。
|
||||
* 如果 ``./configure`` 成功运行,JTAG 被使能的信息会被打印在 ``OpenOCD configuration summary`` 下面。
|
||||
* 如果您的设备信息未显示在日志中,请根据 ``../openocd-esp32/doc/INSTALL.txt`` 文中的描述使用 ``./configure`` 启用它。
|
||||
* 如果你的设备信息未显示在日志中,请根据 ``../openocd-esp32/doc/INSTALL.txt`` 文中的描述使用 ``./configure`` 启用它。
|
||||
* 有关编译 OpenOCD 的详细信息,请参阅 ``openocd-esp32/README.OSX``。
|
||||
|
||||
一旦 ``make`` 过程成功结束,OpenOCD 的可执行文件会被保存到 ``~/esp/openocd-esp32/src/openocd`` 目录中。
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
********************************
|
||||
Windows 环境下从源码编译 OpenOCD
|
||||
********************************
|
||||
|
||||
:link_to_translation:`en:[English]`
|
||||
|
||||
.. note::
|
||||
|
||||
本文介绍了如何从 OpenOCD 源文件构建二进制文件。如果您想要更快速地构建,也可以从 `乐鑫 GitHub <https://github.com/espressif/openocd-esp32/releases>`_ 直接下载 OpenOCD 的预构建二进制文件,而无需自己编译(详细信息,请参阅 :ref:`jtag-debugging-setup-openocd`)。
|
||||
本文介绍了如何从 OpenOCD 源文件构建二进制文件。如果你想要更快速地构建,也可以从 `乐鑫 GitHub <https://github.com/espressif/openocd-esp32/releases>`_ 直接下载 OpenOCD 的预构建二进制文件,而无需自己编译(详细信息,请参阅 :ref:`jtag-debugging-setup-openocd`)。
|
||||
|
||||
.. note::
|
||||
|
||||
|
@ -31,7 +32,7 @@ Windows 环境下从源码编译 OpenOCD
|
|||
下载 OpenOCD 源码
|
||||
=================
|
||||
|
||||
支持 {IDF_TARGET_NAME} 的 OpenOCD 源码可以从乐鑫官方 GitHub 获取,网址为 https://github.com/espressif/openocd-esp32。您可以在 Git 中使用以下命令来拉取源代码:
|
||||
支持 {IDF_TARGET_NAME} 的 OpenOCD 源码可以从乐鑫官方 GitHub 获取,网址为 https://github.com/espressif/openocd-esp32。你可以在 Git 中使用以下命令来拉取源代码:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
|
@ -77,17 +78,17 @@ Windows 环境下从源码编译 OpenOCD
|
|||
|
||||
构建完成后,OpenOCD 的二进制文件将被保存于 ``~/esp/openocd-esp32/src/`` 目录下。
|
||||
|
||||
您也可以调用 ``make install``,将其复制到指定位置。
|
||||
你也可以调用 ``make install``,将其复制到指定位置。
|
||||
|
||||
- 您可以在配置 OpenOCD 时指定这一位置,也可以在调用 ``make install`` 前设置 ``export DESTDIR="/custom/install/dir"``。
|
||||
- 如果您已经安装过其他开发平台的 OpenOCD,请跳过此步骤,否则原来的 OpenOCD 可能会被覆盖。
|
||||
- 你可以在配置 OpenOCD 时指定这一位置,也可以在调用 ``make install`` 前设置 ``export DESTDIR="/custom/install/dir"``。
|
||||
- 如果你已经安装过其他开发平台的 OpenOCD,请跳过此步骤,否则原来的 OpenOCD 可能会被覆盖。
|
||||
|
||||
.. note::
|
||||
|
||||
* 如果发生错误,请解决后再次尝试编译,直到 ``make`` 成功为止。
|
||||
* 如果 OpenOCD 存在子模块问题,请 ``cd`` 到 ``openocd-esp32`` 目录,并输入 ``git submodule update --init`` 命令。
|
||||
* 如果 ``./configure`` 成功运行,JTAG 被使能的信息会被打印在 ``OpenOCD configuration summary`` 下面。
|
||||
* 如果您的设备信息未显示在日志中,请根据 ``../openocd-esp32/doc/INSTALL.txt`` 文中的描述使用 ``./configure`` 启用它。
|
||||
* 如果你的设备信息未显示在日志中,请根据 ``../openocd-esp32/doc/INSTALL.txt`` 文中的描述使用 ``./configure`` 启用它。
|
||||
* 有关编译 OpenOCD 的详细信息,请参阅 ``openocd-esp32/README.Windows``。
|
||||
* 请记得将 `libusb-1.0.dll` 和 `libwinpthread-1.dll` 从 ``~/esp/openocd-esp32/src`` 复制到 `OOCD_INSTALLDIR/bin`。
|
||||
|
||||
|
@ -97,7 +98,7 @@ Windows 环境下从源码编译 OpenOCD
|
|||
完整编译过程
|
||||
==============
|
||||
|
||||
OpenOCD 编译过程中所调用的所有命令都已包含在以下代码片段中,您可以将其复制到 shell 脚本中,以便快速执行:
|
||||
OpenOCD 编译过程中所调用的所有命令都已包含在以下代码片段中,你可以将其复制到 shell 脚本中,以便快速执行:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
配置 |devkit-name| 上的 JTAG 接口
|
||||
=====================================
|
||||
|
||||
:link_to_translation:`en:[English]`
|
||||
|
||||
所有版本的 |devkit-name| 板子都内置了 JTAG 调试功能,要使其正常工作,还需要设置相关跳帽来启用 JTAG 功能,设置 SPI 闪存电压和配置 USB 驱动程序。具体步骤请参考以下说明。
|
||||
|
@ -32,7 +33,7 @@
|
|||
Windows
|
||||
"""""""
|
||||
|
||||
1. 使用标准 USB A / micro USB B 线将 |devkit-name| 与计算机相连接,并打开板子的电源。
|
||||
1. 使用标准 USB A/micro USB B 线将 |devkit-name| 与计算机相连接,并打开板子的电源。
|
||||
|
||||
2. 等待 Windows 识别出 |devkit-name| 并且为其安装驱动。如果驱动没有被自动安装,请前往 `官网 <https://ftdichip.com/drivers/d2xx-drivers/>`_ 下载并手动安装。
|
||||
|
||||
|
@ -49,11 +50,11 @@ Windows
|
|||
|
||||
在 Zadig 工具中配置 JTAG USB 驱动
|
||||
|
||||
6. 第一个设备 “Dual RS232-HS(Interface 0)” 连接到了 {IDF_TARGET_NAME} 的 JTAG 端口,此设备原来的 “FTDIBUS (vxxxx)” 驱动需要替换成 "WinUSB (v6xxxxx)"。为此,请选择 “Dual RS232-HS (Interface 0)” 并将驱动重新安装为 “WinUSB (v6xxxxx)”,具体可以参考上图。
|
||||
6. 第一个设备 “Dual RS232-HS (Interface 0)” 连接到了 {IDF_TARGET_NAME} 的 JTAG 端口,此设备原来的 “FTDIBUS (vxxxx)” 驱动需要替换成 "WinUSB (v6xxxxx)"。为此,请选择 “Dual RS232-HS (Interface 0)” 并将驱动重新安装为 “WinUSB (v6xxxxx)”,具体可以参考上图。
|
||||
|
||||
.. note::
|
||||
|
||||
请勿更改第二个设备 “Dual RS232-HS(Interface 1)” 的驱动,它被连接到 {IDF_TARGET_NAME} 的串口(UART),用于上传应用程序映像给 {IDF_TARGET_NAME} 进行烧写。
|
||||
请勿更改第二个设备 “Dual RS232-HS (Interface 1)” 的驱动,它被连接到 {IDF_TARGET_NAME} 的串口 (UART),用于上传应用程序映像给 {IDF_TARGET_NAME} 进行烧写。
|
||||
|
||||
现在,|devkit-name| 的 JTAG 接口应该可以被 OpenOCD 使用了,想要进一步设置调试环境,请前往 :ref:`jtag-debugging-run-openocd` 章节。
|
||||
|
||||
|
@ -61,7 +62,7 @@ Windows
|
|||
Linux
|
||||
"""""
|
||||
|
||||
1. 使用标准 USB A / micro USB B 线将 |devkit-name| 与计算机相连接,并打开板子的电源。
|
||||
1. 使用标准 USB A/micro USB B 线将 |devkit-name| 与计算机相连接,并打开板子的电源。
|
||||
|
||||
.. highlight:: none
|
||||
|
||||
|
@ -86,7 +87,7 @@ Linux
|
|||
|
||||
如果看到类似的输出结果,并且你也是 ``plugdev`` 组的成员, 那么设置工作就完成了。
|
||||
|
||||
具有较低编号的 ``/dev/ttyUSBn`` 接口用于 JTAG 通信,另一路接口被连接到 {IDF_TARGET_NAME} 的串口(UART),用于上传应用程序映像给 {IDF_TARGET_NAME} 进行烧写。
|
||||
具有较低编号的 ``/dev/ttyUSBn`` 接口用于 JTAG 通信,另一路接口被连接到 {IDF_TARGET_NAME} 的串口 (UART),用于上传应用程序映像给 {IDF_TARGET_NAME} 进行烧写。
|
||||
|
||||
现在,|devkit-name| 的 JTAG 接口应该可以被 OpenOCD 使用了,想要进一步设置调试环境,请前往 :ref:`jtag-debugging-run-openocd` 章节。
|
||||
|
||||
|
@ -111,7 +112,7 @@ MacOS
|
|||
|
||||
sudo kextunload -b com.FTDI.driver.FTDIUSBSerialDriver
|
||||
|
||||
有时,您可能还需要卸载苹果的 FTDI 驱动:
|
||||
有时,你可能还需要卸载苹果的 FTDI 驱动:
|
||||
|
||||
* macOS < 10.15::
|
||||
|
||||
|
@ -146,9 +147,13 @@ MacOS
|
|||
|
||||
简而言之,这种方法需要修改 FTDI 驱动程序的配置文件,这样可以防止为 FT2232H 的通道 B 自动加载串口驱动。
|
||||
|
||||
.. note:: 其他板子可能将通道 A 用于 JTAG,因此请谨慎使用此选项。
|
||||
.. note::
|
||||
|
||||
.. warning:: 此方法还需要操作系统禁止对驱动进行签名验证,因此可能无法被所有的用户所接受。
|
||||
其他板子可能将通道 A 用于 JTAG,因此请谨慎使用此选项。
|
||||
|
||||
.. warning::
|
||||
|
||||
此方法还需要操作系统禁止对驱动进行签名验证,因此可能无法被所有的用户所接受。
|
||||
|
||||
|
||||
1. 使用文本编辑器打开 FTDI 驱动的配置文件(注意 ``sudo``)::
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
配置其他 JTAG 接口
|
||||
==================
|
||||
|
||||
:link_to_translation:`en:[English]`
|
||||
|
||||
{IDF_TARGET_JTAG_SEL_EFUSE:default="Not Updated!", esp32s3="STRAP_JTAG_SEL", esp32c6="JTAG_SEL_ENABLE", esp32h2="JTAG_SEL_ENABLE"}
|
||||
|
@ -11,15 +12,15 @@
|
|||
配置 eFuse
|
||||
^^^^^^^^^^^^^^^^
|
||||
|
||||
{IDF_TARGET_NAME} JTAG 接口默认连接至 :doc:`内置 USB_SERIAL_JTAG 外设 <configure-builtin-jtag>`。要使用外部 JTAG 适配器,需将 JTAG 接口切换至 GPIO 管脚。您可以使用 ``espefuse.py`` 工具来烧录 eFuse,以完成接口转换。
|
||||
{IDF_TARGET_NAME} JTAG 接口默认连接至 :doc:`内置 USB_SERIAL_JTAG 外设 <configure-builtin-jtag>`。要使用外部 JTAG 适配器,需将 JTAG 接口切换至 GPIO 管脚。你可以使用 ``espefuse.py`` 工具来烧录 eFuse,以完成接口转换。
|
||||
|
||||
.. only:: esp32c3
|
||||
|
||||
烧录 ``DIS_USB_JTAG`` eFuse 后,USB_SERIAL_JTAG 和 {IDF_TARGET_NAME} 的 JTAG 接口之间的连接将被永久禁用,此后您可以将 JTAG 接口连接到 |jtag-gpio-list|。注意,烧录后,USB_SERIAL_JTAG 的 USB CDC 功能仍然可用,即仍然可以通过 USB CDC 进行烧录和查看日志。
|
||||
烧录 ``DIS_USB_JTAG`` eFuse 后,USB_SERIAL_JTAG 和 {IDF_TARGET_NAME} 的 JTAG 接口之间的连接将被永久禁用,此后你可以将 JTAG 接口连接到 |jtag-gpio-list|。注意,烧录后,USB_SERIAL_JTAG 的 USB CDC 功能仍然可用,即仍然可以通过 USB CDC 进行烧录和查看日志。
|
||||
|
||||
.. only:: not esp32c3
|
||||
|
||||
- 烧录 ``DIS_USB_JTAG`` eFuse 后,USB_SERIAL_JTAG 和 {IDF_TARGET_NAME} 的 JTAG 接口之间的连接将被永久禁用,此后您可以将 JTAG 接口连接到 |jtag-gpio-list|。注意,烧录后,USB_SERIAL_JTAG 的 USB CDC 功能仍然可用,即仍然可以通过 USB CDC 进行烧录和查看日志。
|
||||
- 烧录 ``DIS_USB_JTAG`` eFuse 后,USB_SERIAL_JTAG 和 {IDF_TARGET_NAME} 的 JTAG 接口之间的连接将被永久禁用,此后你可以将 JTAG 接口连接到 |jtag-gpio-list|。注意,烧录后,USB_SERIAL_JTAG 的 USB CDC 功能仍然可用,即仍然可以通过 USB CDC 进行烧录和查看日志。
|
||||
- 烧录 ``{IDF_TARGET_JTAG_SEL_EFUSE}`` eFuse 后,JTAG 接口的选择将由 strapping 管脚 |jtag-sel-gpio| 来决定。{IDF_TARGET_NAME} 复位时,如果该 strapping 管脚为低电平,JTAG 接口将使用 |jtag-gpio-list|;如果为高电平,USB_SERIAL_JTAG 将被用作 JTAG 接口。
|
||||
|
||||
.. warning::
|
||||
|
@ -42,7 +43,7 @@
|
|||
配置驱动
|
||||
^^^^^^^^
|
||||
|
||||
您可能还需要安装软件驱动,才能使 JTAG 在计算机上正常工作,请参阅您所使用的 JTAG 适配器的有关文档,获取相关详细信息。
|
||||
你可能还需要安装软件驱动,才能使 JTAG 在计算机上正常工作,请参阅你所使用的 JTAG 适配器的有关文档,获取相关详细信息。
|
||||
|
||||
在 Linux 中,请务必将 `udev 规则文件 <https://github.com/espressif/openocd-esp32/blob/master/contrib/60-openocd.rules>`_ 复制到 ``/etc/udev/rules.d`` 目录中,以添加 OpenOCD udev 规则。
|
||||
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
调试示例
|
||||
========
|
||||
|
||||
:link_to_translation:`en:[English]`
|
||||
|
||||
本节将介绍如何在 :ref:`Eclipse <jtag-debugging-examples-eclipse>` 和 :ref:`命令行 <jtag-debugging-examples-command-line>` 中使用 GDB 进行调试的示例。
|
||||
|
||||
.. highlight:: none
|
||||
.. code-block:: none
|
||||
|
||||
|
||||
.. _jtag-debugging-examples-eclipse:
|
||||
|
||||
|
@ -179,6 +181,7 @@
|
|||
|
||||
要修改内存的数值,请在 “Monitor” 选项卡中找到待修改的内存地址,如前面观察的结果一样,输入特定比特翻转后的值。当按下回车键后,将立即看到 LED 的状态发生了改变。
|
||||
|
||||
|
||||
.. _jtag-debugging-examples-eclipse-06:
|
||||
|
||||
观察和设置程序变量
|
||||
|
@ -227,14 +230,13 @@
|
|||
使用命令行的调试示例
|
||||
--------------------
|
||||
|
||||
请检查您的目标板是否已经准备好,并加载了 :example:`get-started/blink` 示例代码,然后按照 :ref:`jtag-debugging-using-debugger-command-line` 中介绍的步骤配置和启动调试器,最后选择让应用程序在 ``app_main()`` 建立的断点处停止运行 ::
|
||||
请检查你的目标板是否已经准备好,并加载了 :example:`get-started/blink` 示例代码,然后按照 :ref:`jtag-debugging-using-debugger-command-line` 中介绍的步骤配置和启动调试器,最后选择让应用程序在 ``app_main()`` 建立的断点处停止运行 ::
|
||||
|
||||
Temporary breakpoint 1, app_main () at /home/user-name/esp/blink/main/./blink.c:43
|
||||
43 xTaskCreate(&blink_task, "blink_task", configMINIMAL_STACK_SIZE, NULL, 5, NULL);
|
||||
(gdb)
|
||||
|
||||
|
||||
|
||||
本小节的示例
|
||||
^^^^^^^^^^^^
|
||||
|
||||
|
@ -343,7 +345,7 @@
|
|||
|
||||
线程列表显示了每个线程最后一个被调用的函数以及所在的 C 源文件名(如果存在的话)。
|
||||
|
||||
您可以通过输入 ``thread N`` 进入特定的线程,其中 ``N`` 是线程 ID。我们进入 5 号线程来看一下它是如何工作的::
|
||||
你可以通过输入 ``thread N`` 进入特定的线程,其中 ``N`` 是线程 ID。我们进入 5 号线程来看一下它是如何工作的::
|
||||
|
||||
(gdb) thread 5
|
||||
[Switching to thread 5 (Thread 1073410208)]
|
||||
|
@ -444,7 +446,7 @@
|
|||
52 asm("waiti 0");
|
||||
(gdb)
|
||||
|
||||
在上图所示的情况下,应用程序已经在 ``freertos_hooks.c`` 文件的第 52 行暂停运行,现在您可以通过输入 ``c`` 再次将其恢复运行或者进行如下所述的一些调试工作。
|
||||
在上图所示的情况下,应用程序已经在 ``freertos_hooks.c`` 文件的第 52 行暂停运行,现在你可以通过输入 ``c`` 再次将其恢复运行或者进行如下所述的一些调试工作。
|
||||
|
||||
|
||||
.. _jtag-debugging-examples-command-line-04:
|
||||
|
@ -629,7 +631,8 @@
|
|||
调试 FreeRTOS 对象
|
||||
^^^^^^^^^^^^^^^^^^
|
||||
|
||||
该部分内容或许可以帮助您调试 FreeRTOS 任务交互。
|
||||
该部分内容或许可以帮助你调试 FreeRTOS 任务交互。
|
||||
|
||||
需要调试 FreeRTOS 任务交互的用户可使用 GDB 命令 ``freertos``。该命令并非 GDB 原生命令,而是来自于 Python 扩展模块 `freertos-gdb <https://pypi.org/project/freertos-gdb>`_,其包含一系列子命令::
|
||||
|
||||
(gdb) freertos
|
||||
|
@ -655,7 +658,7 @@
|
|||
获得命令的帮助信息
|
||||
^^^^^^^^^^^^^^^^^^
|
||||
|
||||
目前所介绍的都是些非常基础的命令,目的在于让您快速上手 JTAG 调试。如果想获得特定命令的语法和功能相关的信息,请在 ``(gdb)`` 提示符下输入 ``help`` 和命令名::
|
||||
目前所介绍的都是些非常基础的命令,目的在于让你快速上手 JTAG 调试。如果想获得特定命令的语法和功能相关的信息,请在 ``(gdb)`` 提示符下输入 ``help`` 和命令名::
|
||||
|
||||
(gdb) help next
|
||||
Step program, proceeding through subroutine calls.
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
JTAG 调试
|
||||
=========
|
||||
|
||||
:link_to_translation:`en:[English]`
|
||||
|
||||
本文将介绍如何安装 {IDF_TARGET_NAME} 的 OpenOCD 调试环境,以及如何使用 GDB 来调试 {IDF_TARGET_NAME} 的应用程序。本文结构如下:
|
||||
|
@ -7,7 +8,7 @@ JTAG 调试
|
|||
:ref:`jtag-debugging-introduction`
|
||||
介绍本指南主旨。
|
||||
:ref:`jtag-debugging-how-it-works`
|
||||
介绍 {IDF_TARGET_NAME}、JTAG(Joint Test Action Group)接口、OpenOCD 和 GDB 如何相互连接,从而实现 {IDF_TARGET_NAME} 的调试功能。
|
||||
介绍 {IDF_TARGET_NAME}、JTAG (Joint Test Action Group) 接口、OpenOCD 和 GDB 如何相互连接,从而实现 {IDF_TARGET_NAME} 的调试功能。
|
||||
:ref:`jtag-debugging-selecting-jtag-adapter`
|
||||
介绍有关 JTAG 硬件适配器的选择及参照标准。
|
||||
:ref:`jtag-debugging-setup-openocd`
|
||||
|
@ -17,7 +18,7 @@ JTAG 调试
|
|||
:ref:`jtag-debugging-launching-debugger`
|
||||
介绍如何从 :ref:`Eclipse 集成开发环境 <jtag-debugging-using-debugger-eclipse>` 和 :ref:`命令行终端 <jtag-debugging-using-debugger-command-line>` 启动 GDB 调试会话。
|
||||
:ref:`jtag-debugging-examples`
|
||||
如果您不熟悉 GDB,请查看此小节以获取 :ref:`Eclipse 集成开发环境 <jtag-debugging-examples-eclipse>` 以及 :ref:`命令行终端 <jtag-debugging-examples-command-line>` 提供的调试示例。
|
||||
如果你不熟悉 GDB,请查看此小节以获取 :ref:`Eclipse 集成开发环境 <jtag-debugging-examples-eclipse>` 以及 :ref:`命令行终端 <jtag-debugging-examples-command-line>` 提供的调试示例。
|
||||
:ref:`jtag-debugging-building-openocd`
|
||||
介绍如何在 :doc:`Windows <building-openocd-windows>`,:doc:`Linux <building-openocd-linux>` 和 :doc:`macOS <building-openocd-macos>` 操作系统上从源码构建 OpenOCD。
|
||||
:ref:`jtag-debugging-tips-and-quirks`
|
||||
|
@ -38,7 +39,7 @@ JTAG 调试
|
|||
|
||||
ESP32 具有两个强大的 Xtensa 内核,支持多种程序架构。ESP-IDF 自带的 FreeRTOS 操作系统支持多核抢占式调度,允许用户以更加直观的方式编写软件。
|
||||
|
||||
与此相对地,由于缺乏合适的工具,简便的编程方式也会给程序的调试带来困难,比如找出由两个线程引起的错误,并且这两个线程在单独的 CPU 核上同时运行,那么仅凭 ``printf`` 语句会花费很长时间来定位该错误。调试此类问题更好(往往也更快)的方法是使用调试器,将其连接到处理器的调试端口。
|
||||
与此相对地,由于缺乏合适的工具,简便的编程方式也会给程序的调试带来困难,比如找出由两个线程引起的错误,并且这两个线程在单独的 CPU 核上同时运行,那么仅凭 ``printf`` 语句会花费很长时间来定位该错误。调试此类问题更好(往往也更快)的方法是使用调试器,将其连接到处理器的调试端口。
|
||||
|
||||
乐鑫已完成 OpenOCD 移植,以支持 {IDF_TARGET_NAME} 处理器和多核 FreeRTOS 架构(大多数 {IDF_TARGET_NAME} 应用程序的基础)。此外,乐鑫还提供了一些 OpenOCD 本身并不支持的工具,以进一步丰富调试功能。
|
||||
|
||||
|
@ -53,7 +54,7 @@ JTAG 调试
|
|||
工作原理
|
||||
--------
|
||||
|
||||
通过 JTAG(Joint Test Action Group)接口使用 OpenOCD 调试 {IDF_TARGET_NAME} 时所需要的关键软件和硬件包括 **{IDF_TARGET_TOOLCHAIN_PREFIX}-gdb 调试器**、**OpenOCD 片上调试器** 和连接到 **{IDF_TARGET_NAME}** 目标的 **JTAG 适配器**,如下图 “Application Loading and Monitoring” 标志所示。
|
||||
通过 JTAG (Joint Test Action Group) 接口使用 OpenOCD 调试 {IDF_TARGET_NAME} 时所需要的关键软件和硬件包括 **{IDF_TARGET_TOOLCHAIN_PREFIX}-gdb 调试器**、**OpenOCD 片上调试器** 和连接到 **{IDF_TARGET_NAME}** 目标的 **JTAG 适配器**,如下图 “Application Loading and Monitoring” 标志所示。
|
||||
|
||||
.. figure:: ../../../_static/jtag-debugging-overview_zh.jpg
|
||||
:align: center
|
||||
|
@ -93,11 +94,11 @@ JTAG 调试
|
|||
|
||||
上手 JTAG 最快速便捷的方式是将一根 USB 线连接到 {IDF_TARGET_NAME} 的 D+/D- USB 管脚,无需使用外部 JTAG 适配器和额外线缆。
|
||||
|
||||
如果您想使用单独的 JTAG 适配器,请确保其与 {IDF_TARGET_NAME} 的电平电压和 OpenOCD 软件都兼容。{IDF_TARGET_NAME} 使用的是业界标准的 JTAG 接口,它未使用(实际上也并不需要)TRST 信号脚。JTAG 使用的 IO 管脚由 VDD_3P3_RTC 电源管脚供电(通常连接到外部 3.3 V 的电源轨),因此 JTAG 硬件适配器的管脚需要能够在该电压范围内正常工作。
|
||||
如果想使用单独的 JTAG 适配器,请确保其与 {IDF_TARGET_NAME} 的电平电压和 OpenOCD 软件都兼容。{IDF_TARGET_NAME} 使用的是业界标准的 JTAG 接口,它未使用(实际上也并不需要)TRST 信号脚。JTAG 使用的 IO 管脚由 VDD_3P3_RTC 电源管脚供电(通常连接到外部 3.3 V 的电源轨),因此 JTAG 硬件适配器的管脚需要能够在该电压范围内正常工作。
|
||||
|
||||
在软件方面,OpenOCD 支持相当多数量的 JTAG 适配器,请参阅 `OpenOCD 支持的适配器列表 <https://openocd.org/doc/html/Debug-Adapter-Hardware.html>`_ (请注意这一列表并不完整),其中还列出了兼容 SWD 接口的适配器,但请注意,{IDF_TARGET_NAME} 目前并不支持 SWD。此外,硬编码为只支持特定产品线的 JTAG 适配器也无法在 {IDF_TARGET_NAME} 上工作,例如仅针对 STM32 系列产品的 ST-LINK 适配器。
|
||||
|
||||
保证 JTAG 正常工作需要连接的信号线包括:TDI、TDO、TCK、TMS 和 GND。一些 JTAG 适配器还需要 {IDF_TARGET_NAME} 提供一路电源到适配器的某个管脚上(比如 Vtar),用于设置适配器的工作电压。您也可以选择将 SRST 信号线连接到 {IDF_TARGET_NAME} 的 CH_PD 管脚上,但请注意,目前 OpenOCD 对该信号线提供的支持相当有限。
|
||||
保证 JTAG 正常工作需要连接的信号线包括:TDI、TDO、TCK、TMS 和 GND。一些 JTAG 适配器还需要 {IDF_TARGET_NAME} 提供一路电源到适配器的某个管脚上(比如 Vtar),用于设置适配器的工作电压。也可以选择将 SRST 信号线连接到 {IDF_TARGET_NAME} 的 CH_PD 管脚上,但请注意,目前 OpenOCD 对该信号线提供的支持相当有限。
|
||||
|
||||
`ESP-Prog <https://docs.espressif.com/projects/espressif-esp-iot-solution/en/latest/hw-reference/ESP-Prog_guide.html>`_ 中展示了使用外部电路板进行调试的实例,方法是将其连接到 {IDF_TARGET_NAME} 的 JTAG 管脚上。
|
||||
|
||||
|
@ -108,7 +109,7 @@ JTAG 调试
|
|||
|
||||
.. highlight:: bash
|
||||
|
||||
如果您已经按照 :doc:`快速入门 <../../get-started/index>` 完成了 ESP-IDF 及其 CMake 构建系统的安装,那么 OpenOCD 已经被默认安装到了您的开发系统中。在 :ref:`设置开发环境 <get-started-set-up-env>` 结束后,您应该能够在终端中运行如下 OpenOCD 命令::
|
||||
如果已经按照 :doc:`快速入门 <../../get-started/index>` 完成了 ESP-IDF 及其 CMake 构建系统的安装,那么 OpenOCD 已经被默认安装到了你的开发系统中。在 :ref:`设置开发环境 <get-started-set-up-env>` 结束后,应该能够在终端中运行如下 OpenOCD 命令::
|
||||
|
||||
openocd --version
|
||||
|
||||
|
@ -121,7 +122,7 @@ JTAG 调试
|
|||
For bug reports, read
|
||||
https://openocd.org/doc/doxygen/bugs.html
|
||||
|
||||
您还可以检查 ``OPENOCD_SCRIPTS`` 环境变量的值,以确认 OpenOCD 配置文件的路径,Linux 和 macOS 用户可以在终端输入 ``echo $OPENOCD_SCRIPTS``,Windows 用户需要输入 ``echo %OPENOCD_SCRIPTS%``。如果终端输出了有效路径,则表明您已经正确安装 OpenOCD。
|
||||
你还可以检查 ``OPENOCD_SCRIPTS`` 环境变量的值,以确认 OpenOCD 配置文件的路径,Linux 和 macOS 用户可以在终端输入 ``echo $OPENOCD_SCRIPTS``,Windows 用户需要输入 ``echo %OPENOCD_SCRIPTS%``。如果终端输出了有效路径,则表明已经正确安装 OpenOCD。
|
||||
|
||||
如果无法执行上述步骤,请再次阅读快速入门手册,参考 :ref:`设置安装工具 <get-started-set-up-tools>` 章节。
|
||||
|
||||
|
@ -175,7 +176,7 @@ OpenOCD 安装完成后就可以配置 {IDF_TARGET_NAME} 目标(即带 JTAG
|
|||
|
||||
.. note::
|
||||
|
||||
上述命令中 ``-f`` 选项后跟的配置文件专用于 |run-openocd-device-name|。基于具体使用的硬件,您可能需要选择不同的配置文件,具体内容请参阅 :ref:`jtag-debugging-tip-openocd-configure-target`。
|
||||
上述命令中 ``-f`` 选项后跟的配置文件专用于 |run-openocd-device-name|。基于具体使用的硬件,你可能需要选择不同的配置文件,具体内容请参阅 :ref:`jtag-debugging-tip-openocd-configure-target`。
|
||||
|
||||
.. only:: SOC_USB_SERIAL_JTAG_SUPPORTED
|
||||
|
||||
|
@ -183,7 +184,7 @@ OpenOCD 安装完成后就可以配置 {IDF_TARGET_NAME} 目标(即带 JTAG
|
|||
|
||||
.. highlight:: none
|
||||
|
||||
现在您应该可以看到如下输出(此日志来自 |run-openocd-device-name|):
|
||||
现在应该可以看到如下输出(此日志来自 |run-openocd-device-name|):
|
||||
|
||||
.. include:: {IDF_TARGET_PATH_NAME}.inc
|
||||
:start-after: run-openocd-output
|
||||
|
@ -200,7 +201,7 @@ OpenOCD 安装完成后就可以配置 {IDF_TARGET_NAME} 目标(即带 JTAG
|
|||
|
||||
按照正常步骤构建并上传 {IDF_TARGET_NAME} 应用程序,具体请参阅 :ref:`get-started-build` 章节。
|
||||
|
||||
除此以外,您还可以使用 OpenOCD 通过 JTAG 接口将应用程序镜像烧写到 flash 中,命令如下:
|
||||
除此以外,还可以使用 OpenOCD 通过 JTAG 接口将应用程序镜像烧写到 flash 中,命令如下:
|
||||
|
||||
.. include:: {IDF_TARGET_PATH_NAME}.inc
|
||||
:start-after: run-openocd-upload
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
注意事项和补充内容
|
||||
------------------
|
||||
|
||||
:link_to_translation:`en:[English]`
|
||||
|
||||
本节提供了本指南中各部分提到的一些注意事项和补充内容。
|
||||
|
@ -48,7 +49,7 @@ flash 映射 vs 软件 flash 断点
|
|||
“next” 命令无法跳过子程序的原因
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
当使用 ``next`` 命令单步执行代码时, GDB 会在子程序的前面设置一个断点(两个中可用的一个),这样就可以跳过进入子程序内部的细节。如果这两个断点已经用在代码的其它位置,那么 ``next`` 命令将不起作用。在这种情况下,请删掉一个断点以使其中一个变得可用。当两个断点都已经被使用时,``next`` 命令会像 ``step`` 命令一样工作,调试器就会进入子程序内部。
|
||||
当使用 ``next`` 命令单步执行代码时,GDB 会在子程序的前面设置一个断点(两个中可用的一个),这样就可以跳过进入子程序内部的细节。如果这两个断点已经用在代码的其它位置,那么 ``next`` 命令将不起作用。在这种情况下,请删掉一个断点以使其中一个变得可用。当两个断点都已经被使用时,``next`` 命令会像 ``step`` 命令一样工作,调试器就会进入子程序内部。
|
||||
|
||||
|
||||
.. _jtag-debugging-tip-code-options:
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
使用调试器
|
||||
----------
|
||||
|
||||
:link_to_translation:`en:[English]`
|
||||
|
||||
本节介绍以下几种配置和运行调试器的方法:
|
||||
|
@ -40,7 +41,7 @@
|
|||
|
||||
安装完成后,按照以下步骤配置调试会话。请注意,一些配置参数是通用的,有些则针对特定项目。我们会通过配置 "blink" 示例项目的调试环境来进行展示,请先按照 `Eclipse Plugin <https://github.com/espressif/idf-eclipse-plugin/blob/master/README_CN.md>`_ 介绍的方法将该示例项目添加到 Eclipse 的工作空间。示例项目 :example:`get-started/blink` 的源代码可以在 ESP-IDF 仓库的 :idf:`examples` 目录下找到。
|
||||
|
||||
1. 在 Eclipse 中,进入 ``Run`` > ``Debug Configuration``,会出现一个新的窗口。在窗口的左侧窗格中,双击 ``GDB Hardware Debugging``(或者选择 ``GDB Hardware Debugging`` 然后按下 ``New`` 按钮)来新建一个配置。
|
||||
1. 在 Eclipse 中,进入 ``Run`` > ``Debug Configuration``,会出现一个新的窗口。在窗口的左侧窗格中,双击 ``GDB Hardware Debugging`` (或者选择 ``GDB Hardware Debugging`` 然后按下 ``New`` 按钮)来新建一个配置。
|
||||
|
||||
2. 在右边显示的表单中,``Name:`` 一栏中输入配置的名称,例如: “Blink checking”。
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
链接器脚本生成机制
|
||||
======================
|
||||
|
||||
:link_to_translation:`en:[English]`
|
||||
|
||||
概述
|
||||
|
@ -190,6 +191,7 @@
|
|||
与 ``rtc`` 和 ``noflash`` 类似,还有一个 ``默认`` 协议,定义了默认存放规则。顾名思义,该协议规定了代码和数据通常存放的区域,即代码和恒量存放在 flash 中,变量存放在 RAM 中。更多关于默认协议的信息,请见 :ref:`这里<ldgen-default-scheme>`。
|
||||
|
||||
.. note::
|
||||
|
||||
使用链接器脚本生成机制的 IDF 组件示例,请参阅 :component_file:`freertos/CMakeLists.txt`。为了提高性能,``freertos`` 使用链接器脚本生成机制,将其目标文件存放到 RAM 中。
|
||||
|
||||
快速入门指南到此结束,下文将详述这个机制的内核,有助于创建自定义存放区域或修改默认方式。
|
||||
|
@ -197,7 +199,7 @@
|
|||
链接器脚本生成机制内核
|
||||
---------------------------
|
||||
|
||||
链接是将 C/C++ 源文件转换成可执行文件的最后一步。链接由工具链的链接器完成,接受指定代码和数据存放区域等信息的链接脚本。链接器脚本生成机制的转换过程类似,区别在于传输给链接器的链接脚本根据(1) 收集的 :ref:`链接器片段文件<ldgen-linker-fragment-files>` 和 (2) :ref:`链接器脚本模板<ldgen-linker-script-template>` 动态生成。
|
||||
链接是将 C/C++ 源文件转换成可执行文件的最后一步。链接由工具链的链接器完成,接受指定代码和数据存放区域等信息的链接脚本。链接器脚本生成机制的转换过程类似,区别在于传输给链接器的链接脚本根据 (1) 收集的 :ref:`链接器片段文件<ldgen-linker-fragment-files>` 和 (2) :ref:`链接器脚本模板<ldgen-linker-script-template>` 动态生成。
|
||||
|
||||
.. note::
|
||||
|
||||
|
|
|
@ -127,7 +127,7 @@ IROM(代码从 flash 中运行)
|
|||
|
||||
.. only:: esp32
|
||||
|
||||
允许从 flash 中执行代码的 Flash MMU 机制可参考 {IDF_TARGET_NAME} 技术参考手册* > *存储器管理和保护单元 (MMU, MPU)* [`PDF <{IDF_TARGET_TRM_CN_URL}#mpummu>`__]。
|
||||
允许从 flash 中执行代码的 flash MMU 机制可参考 {IDF_TARGET_NAME} 技术参考手册* > *存储器管理和保护单元 (MMU, MPU)* [`PDF <{IDF_TARGET_TRM_CN_URL}#mpummu>`__]。
|
||||
|
||||
在 :doc:`启动 <startup>` 过程中,从 IRAM 中运行的引导加载程序配置 MMU flash 缓存,将应用程序的指令代码区域映射到指令空间。通过 MMU 访问的 flash 使用一些内部 SRAM 进行缓存,访问缓存的 flash 数据与访问其他类型的内部存储器一样快。
|
||||
|
||||
|
@ -168,7 +168,7 @@ DROM(数据存储在 flash 中)
|
|||
|
||||
.. note::
|
||||
|
||||
对于 {IDF_TARGET_NAME}, RTC 存储器已被重新重命名为 LP(低功耗)存储器。在与 {IDF_TARGET_NAME} 相关的 IDF 代码、文档以及技术参考手册中,可能会出现这两个术语混用的情况。
|
||||
对于 {IDF_TARGET_NAME},RTC 存储器已被重新重命名为 LP(低功耗)存储器。在与 {IDF_TARGET_NAME} 相关的 IDF 代码、文档以及技术参考手册中,可能会出现这两个术语混用的情况。
|
||||
|
||||
|
||||
RTC FAST memory 的同一区域既可以作为指令存储器也可以作为数据存储器进行访问。从深度睡眠模式唤醒后必须要运行的代码要放在 RTC 存储器中,更多信息请查阅文档 :doc:`深度睡眠 <deep-sleep-stub>`。
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
分区表
|
||||
======
|
||||
|
||||
:link_to_translation:`en:[English]`
|
||||
|
||||
概述
|
||||
|
@ -76,9 +77,9 @@ Type 字段
|
|||
|
||||
Type 字段可以指定为 app (0x00) 或者 data (0x01),也可以直接使用数字 0-254(或者十六进制 0x00-0xFE)。注意,0x00-0x3F 不得使用(预留给 esp-idf 的核心功能)。
|
||||
|
||||
如果您的应用程序需要以 ESP-IDF 尚未支持的格式存储数据,请在 0x40-0xFE 内添加一个自定义分区类型。
|
||||
如果你的应用程序需要以 ESP-IDF 尚未支持的格式存储数据,请在 0x40-0xFE 内添加一个自定义分区类型。
|
||||
|
||||
参考 :cpp:type:`esp_partition_type_t` 关于 ``app``和 ``data`` 分区的枚举定义。
|
||||
参考 :cpp:type:`esp_partition_type_t` 关于 ``app`` 和 ``data`` 分区的枚举定义。
|
||||
|
||||
如果用 C++ 编写,那么指定一个应用程序定义的分区类型,需要在 :cpp:type:`esp_partition_type_t` 中使用整数,从而与 :ref:`分区 API<api-reference-partition-table>` 一起使用。例如::
|
||||
|
||||
|
@ -99,7 +100,7 @@ SubType 字段长度为 8 bit,内容与具体分区 Type 有关。目前,esp
|
|||
- ``factory`` (0x00) 是默认的 app 分区。启动加载器将默认加载该应用程序。但如果存在类型为 data/ota 分区,则启动加载器将加载 data/ota 分区中的数据,进而判断启动哪个 OTA 镜像文件。
|
||||
|
||||
- OTA 升级永远都不会更新 factory 分区中的内容。
|
||||
- 如果您希望在 OTA 项目中预留更多 flash,可以删除 factory 分区,转而使用 ota_0 分区。
|
||||
- 如果你希望在 OTA 项目中预留更多 flash,可以删除 factory 分区,转而使用 ota_0 分区。
|
||||
|
||||
- ota_0 (0x10) … ota_15 (0x1F) 为 OTA 应用程序分区,启动加载器将根据 OTA 数据分区中的数据来决定加载哪个 OTA 应用程序分区中的程序。在使用 OTA 功能时,应用程序应至少拥有 2 个 OTA 应用程序分区(``ota_0`` 和 ``ota_1``)。更多详细信息,请参考 :doc:`OTA 文档 </api-reference/system/ota>` 。
|
||||
- ``test`` (0x20) 为预留的子类型,用于工厂测试流程。如果没有其他有效 app 分区,test 将作为备选启动分区使用。也可以配置启动加载器在每次启动时读取 GPIO,如果 GPIO 被拉低则启动该分区。详细信息请查阅 :ref:`bootloader_boot_from_test_firmware`。
|
||||
|
@ -110,7 +111,7 @@ SubType 字段长度为 8 bit,内容与具体分区 Type 有关。目前,esp
|
|||
- ``phy`` (1) 分区用于存放 PHY 初始化数据,从而保证可以为每个设备单独配置 PHY,而非必须采用固件中的统一 PHY 初始化数据。
|
||||
|
||||
- 默认配置下,phy 分区并不启用,而是直接将 phy 初始化数据编译至应用程序中,从而节省分区表空间(直接将此分区删掉)。
|
||||
- 如果需要从此分区加载 phy 初始化数据,请打开项目配置菜单(``idf.py menuconfig``),并且使能 {IDF_TARGET_ESP_PHY_REF} 选项。此时,您还需要手动将 phy 初始化数据烧至设备 flash(esp-idf 编译系统并不会自动完成该操作)。
|
||||
- 如果需要从此分区加载 phy 初始化数据,请打开项目配置菜单(``idf.py menuconfig``),并且使能 {IDF_TARGET_ESP_PHY_REF} 选项。此时,还需要手动将 phy 初始化数据烧至设备 flash(esp-idf 编译系统并不会自动完成该操作)。
|
||||
- ``nvs`` (2) 是专门给 :doc:`非易失性存储 (NVS) API <../api-reference/storage/nvs_flash>` 使用的分区。
|
||||
|
||||
- 用于存储每台设备的 PHY 校准数据(注意,并不是 PHY 初始化数据)。
|
||||
|
@ -120,7 +121,7 @@ SubType 字段长度为 8 bit,内容与具体分区 Type 有关。目前,esp
|
|||
- 用于存储 Wi-Fi 数据(如果使用了 :doc:`esp_wifi_set_storage(WIFI_STORAGE_FLASH) <../api-reference/network/esp_wifi>` 初始化函数)。
|
||||
|
||||
- NVS API 还可以用于其他应用程序数据。
|
||||
- 强烈建议您应为 NVS 分区分配至少 0x3000 字节空间。
|
||||
- 强烈建议为 NVS 分区分配至少 0x3000 字节空间。
|
||||
- 如果使用 NVS API 存储大量数据,请增加 NVS 分区的大小(默认是 0x6000 字节)。
|
||||
- ``nvs_keys`` (4) 是 NVS 秘钥分区。详细信息,请参考 :doc:`非易失性存储 (NVS) API <../api-reference/storage/nvs_flash>` 文档。
|
||||
|
||||
|
@ -128,7 +129,7 @@ SubType 字段长度为 8 bit,内容与具体分区 Type 有关。目前,esp
|
|||
- 此分区应至少设定为 4096 字节。
|
||||
|
||||
- ESP-IDF 还支持其他用于数据存储的预定义子类型,包括:
|
||||
|
||||
|
||||
- ``coredump`` (0x03) 用于在使用自定义分区表 CSV 文件时存储核心转储,详情请参阅 :doc:`/api-guides/core_dump`。
|
||||
- ``efuse`` (0x05) 使用 :ref:`虚拟 eFuse <virtual-efuses>` 模拟 eFuse 位。
|
||||
- ``undefined`` (0x06) 隐式用于未指定子类型(即子类型为空)的数据分区,但也可显式将其标记为未定义。
|
||||
|
@ -160,12 +161,12 @@ app 分区的偏移地址必须要与 0x10000 (64 K) 对齐,如果将偏移字
|
|||
|
||||
app 分区的大小和偏移地址可以采用十进制数、以 0x 为前缀的十六进制数,且支持 K 或 M 的倍数单位(分别代表 1024 和 1024*1024 字节)。
|
||||
|
||||
如果您希望允许分区表中的分区采用任意起始偏移量 (:ref:`CONFIG_PARTITION_TABLE_OFFSET`),请将分区表(CSV 文件)中所有分区的偏移字段都留空。注意,此时,如果您更改了分区表中任意分区的偏移地址,则其他分区的偏移地址也会跟着改变。这种情况下,如果您之前还曾设定某个分区采用固定偏移地址,则可能造成分区表冲突,从而导致报错。
|
||||
如果你希望允许分区表中的分区采用任意起始偏移量 (:ref:`CONFIG_PARTITION_TABLE_OFFSET`),请将分区表(CSV 文件)中所有分区的偏移字段都留空。注意,此时,如果你更改了分区表中任意分区的偏移地址,则其他分区的偏移地址也会跟着改变。这种情况下,如果你之前还曾设定某个分区采用固定偏移地址,则可能造成分区表冲突,从而导致报错。
|
||||
|
||||
Flags 字段
|
||||
~~~~~~~~~~
|
||||
|
||||
当前仅支持 ``encrypted`` 标记。如果 Flags 字段设置为 ``encrypted``,且已启用 :doc:`Flash 加密 </security/flash-encryption>` 功能,则该分区将会被加密。
|
||||
当前仅支持 ``encrypted`` 标记。如果 Flags 字段设置为 ``encrypted``,且已启用 :doc:`/security/flash-encryption` 功能,则该分区将会被加密。
|
||||
|
||||
.. note::
|
||||
|
||||
|
@ -176,7 +177,7 @@ Flags 字段
|
|||
|
||||
烧写到 {IDF_TARGET_NAME} 中的分区表采用二进制格式,而不是 CSV 文件本身。此时,:component_file:`partition_table/gen_esp32part.py` 工具可以实现 CSV 和二进制文件之间的转换。
|
||||
|
||||
如果您在项目配置菜单(``idf.py menuconfig``)中设置了分区表 CSV 文件的名称,然后构建项目或执行 ``idf.py partition-table``。这时,转换将在编译过程中自动完成。
|
||||
如果你在项目配置菜单(``idf.py menuconfig``)中设置了分区表 CSV 文件的名称,然后构建项目或执行 ``idf.py partition-table``。这时,转换将在编译过程中自动完成。
|
||||
|
||||
手动将 CSV 文件转换为二进制文件::
|
||||
|
||||
|
@ -186,7 +187,7 @@ Flags 字段
|
|||
|
||||
python gen_esp32part.py binary_partitions.bin input_partitions.csv
|
||||
|
||||
在标准输出(stdout)上,打印二进制分区表的内容(运行 ``idf.py partition-table`` 时展示的信息摘要也是这样生成的)::
|
||||
在标准输出 (stdout) 上,打印二进制分区表的内容(运行 ``idf.py partition-table`` 时展示的信息摘要也是这样生成的)::
|
||||
|
||||
python gen_esp32part.py binary_partitions.bin
|
||||
|
||||
|
@ -228,18 +229,18 @@ MD5 校验和
|
|||
|
||||
.. note::
|
||||
|
||||
分区表的更新并不会擦除根据旧分区表存储的数据。此时,您可以使用 ``idf.py erase-flash`` 命令或者 ``esptool.py erase_flash`` 命令来擦除 flash 中的所有内容。
|
||||
分区表的更新并不会擦除根据旧分区表存储的数据。此时,可以使用 ``idf.py erase-flash`` 命令或者 ``esptool.py erase_flash`` 命令来擦除 flash 中的所有内容。
|
||||
|
||||
|
||||
分区工具 (parttool.py)
|
||||
----------------------
|
||||
分区工具 (``parttool.py``)
|
||||
---------------------------
|
||||
|
||||
`partition_table` 组件中有分区工具 :component_file:`parttool.py<partition_table/parttool.py>`,可以在目标设备上完成分区相关操作。该工具有如下用途:
|
||||
|
||||
- 读取分区,将内容存储到文件中 (read_partition)
|
||||
- 将文件中的内容写至分区 (write_partition)
|
||||
- 擦除分区 (erase_partition)
|
||||
- 检索特定分区的名称、偏移、大小和 flag(“加密”) 标志等信息 (get_partition_info)
|
||||
- 检索特定分区的名称、偏移、大小和 flag(“加密”)标志等信息 (get_partition_info)
|
||||
|
||||
用户若想通过编程方式完成相关操作,可从另一个 Python 脚本导入并使用分区工具,或者从 Shell 脚本调用分区工具。前者可使用工具的 Python API,后者可使用命令行界面。
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
应用程序的启动流程
|
||||
===================
|
||||
|
||||
:link_to_translation:`en:[English]`
|
||||
|
||||
{IDF_TARGET_BOOTLOADER_OFFSET:default="0x0", esp32="0x1000", esp32s2="0x1000"}
|
||||
|
@ -62,7 +63,7 @@
|
|||
二级引导程序
|
||||
~~~~~~~~~~~~
|
||||
|
||||
在 ESP-IDF 中,存放在 flash 的 {IDF_TARGET_BOOTLOADER_OFFSET} 偏移地址处的二进制镜像就是二级引导程序。二级引导程序的源码可以在 ESP-IDF 的 :idf:`components/bootloader` 目录下找到。ESP-IDF 使用二级引导程序可以增加 flash 分区的灵活性(使用分区表),并且方便实现 flash 加密,安全引导和空中升级(OTA)等功能。
|
||||
在 ESP-IDF 中,存放在 flash 的 {IDF_TARGET_BOOTLOADER_OFFSET} 偏移地址处的二进制镜像就是二级引导程序。二级引导程序的源码可以在 ESP-IDF 的 :idf:`components/bootloader` 目录下找到。ESP-IDF 使用二级引导程序可以增加 flash 分区的灵活性(使用分区表),并且方便实现 flash 加密,安全引导和空中升级 (OTA) 等功能。
|
||||
|
||||
当一级引导程序校验并加载完二级引导程序后,它会从二进制镜像的头部找到二级引导程序的入口点,并跳转过去运行。
|
||||
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
******************
|
||||
ESP-IDF clang-tidy
|
||||
IDF clang-tidy
|
||||
******************
|
||||
|
||||
:link_to_translation:`en:[English]`
|
||||
|
||||
ESP-IDF clang-tidy 是使用 `clang-tidy <https://clang.llvm.org/extra/clang-tidy/>`__ 对当前应用程序进行静态分析的工具。
|
||||
IDF clang-tidy 是使用 `clang-tidy <https://clang.llvm.org/extra/clang-tidy/>`__ 对当前应用程序进行静态分析的工具。
|
||||
|
||||
.. warning::
|
||||
|
||||
ESP-IDF clang-tidy 的功能及其依赖的工具链尚在开发中,最终版本发布前可能有重大变更。
|
||||
IDF clang-tidy 的功能及其依赖的工具链尚在开发中,最终版本发布前可能有重大变更。
|
||||
|
||||
.. only:: CONFIG_IDF_TARGET_ARCH_RISCV
|
||||
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
*************************
|
||||
ESP-IDF 组件管理器
|
||||
IDF 组件管理器
|
||||
*************************
|
||||
|
||||
:link_to_translation:`en:[English]`
|
||||
|
||||
ESP-IDF 组件管理器工具用于下载 ESP-IDF CMake 项目的依赖项,该下载在 CMake 运行期间自动完成。ESP-IDF 组件管理器可以从 `组件注册表 <https://components.espressif.com>`__ 或 Git 仓库获取组件。
|
||||
IDF 组件管理器工具用于下载 ESP-IDF CMake 项目的依赖项,该下载在 CMake 运行期间自动完成。IDF 组件管理器可以从 `组件注册表 <https://components.espressif.com>`__ 或 Git 仓库获取组件。
|
||||
|
||||
要获取组件列表,请参阅 `<https://components.espressif.com/>`__.
|
||||
|
||||
有关 ESP-IDF 组件管理器的详细信息,请参阅 `ESP-IDF 组件管理器及 ESP 组件注册表文档 <https://docs.espressif.com/projects/idf-component-manager/en/latest/>`__。
|
||||
有关 IDF 组件管理器的详细信息,请参阅 `IDF 组件管理器及 ESP 组件注册表文档 <https://docs.espressif.com/projects/idf-component-manager/en/latest/>`__。
|
||||
|
||||
在项目中使用 ESP-IDF 组件管理器
|
||||
在项目中使用 IDF 组件管理器
|
||||
===================================
|
||||
|
||||
项目中各组件的依赖项定义在单独的清单文件中,命名为 ``idf_component.yml``,位于组件根目录。运行 ``idf.py create-manifest`` 可以为组件创建清单文件模板。默认情况下将为 main 组件创建清单文件。使用 ``--path`` 选项,可以显式指定创建清单文件的目录路径。使用 ``--component=my_component`` 选项可以指定组件名称,这样系统将会在 ``components`` 文件夹下为该组件创建清单文件。``create-manifest`` 命令支持以下运行方式:
|
||||
|
@ -21,7 +21,7 @@ ESP-IDF 组件管理器工具用于下载 ESP-IDF CMake 项目的依赖项,该
|
|||
|
||||
在向项目的某个组件添加新的清单时,必须先运行 ``idf.py reconfigure``,手动重新配置项目。随后,构建过程将跟踪 ``idf_component.yml`` 清单的变更,并在必要时自动触发 CMake。
|
||||
|
||||
要为 ESP-IDF 项目中的组件(如 ``my_component``)添加依赖项,可以运行命令 ``idf.py add-dependency DEPENDENCY``。``DEPENDENCY`` 参数代表一个由 ESP-IDF 组件管理器管理的额外组件,而 ``my_component`` 也依赖于这个组件。``DEPENDENCY`` 参数的格式为 ``namespace/name=1.0.0``,`namespace/name` 代表组件名称,`=1.0.0` 是组件的版本范围,详情请参阅 `版本文档 <https://docs.espressif.com/projects/idf-component-manager/en/latest/reference/versioning.html>`__。默认情况下,依赖项会添加到 main 组件。通过使用 ``--path`` 选项,可以显式指定包含清单的目录,也可以使用 ``--component=my_component``,在 ``components`` 文件夹中指定组件。``add-dependency`` 命令支持以下运行方式:
|
||||
要为 ESP-IDF 项目中的组件(如 ``my_component``)添加依赖项,可以运行命令 ``idf.py add-dependency DEPENDENCY``。``DEPENDENCY`` 参数代表一个由 IDF 组件管理器管理的额外组件,而 ``my_component`` 也依赖于这个组件。``DEPENDENCY`` 参数的格式为 ``namespace/name=1.0.0``,`namespace/name` 代表组件名称,`=1.0.0` 是组件的版本范围,详情请参阅 `版本文档 <https://docs.espressif.com/projects/idf-component-manager/en/latest/reference/versioning.html>`__。默认情况下,依赖项会添加到 main 组件。通过使用 ``--path`` 选项,可以显式指定包含清单的目录,也可以使用 ``--component=my_component``,在 ``components`` 文件夹中指定组件。``add-dependency`` 命令支持以下运行方式:
|
||||
|
||||
- ``idf.py add-dependency example/cmp`` 为 main 组件添加依赖项,依赖项为 ``example/cmp`` 的最新版本
|
||||
- ``idf.py add-dependency --component=my_component example/cmp<=3.3.3`` 将依赖项添加到位于 ``components`` 目录下名为 ``my_component`` 的组件中,依赖项为版本号 ``<=3.3.3`` 的 ``example/cmp``
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
********************
|
||||
ESP-IDF Docker 镜像
|
||||
IDF Docker 镜像
|
||||
********************
|
||||
|
||||
:link_to_translation:`en:[English]`
|
||||
|
@ -9,7 +9,7 @@ ESP-IDF Docker 镜像
|
|||
|
||||
.. highlight:: bash
|
||||
|
||||
ESP-IDF Docker 镜像 (``espressif/idf``) 为使用特定版本的 ESP-IDF 自动化构建应用程序和库而设计。
|
||||
IDF Docker 镜像 (``espressif/idf``) 为使用特定版本的 ESP-IDF 自动化构建应用程序和库而设计。
|
||||
|
||||
该镜像包含以下内容:
|
||||
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
*******************
|
||||
***********************
|
||||
IDF 监视器
|
||||
*******************
|
||||
***********************
|
||||
|
||||
:link_to_translation:`en:[English]`
|
||||
|
||||
IDF 监视器是一个串行终端程序,使用了 esp-idf-monitor_ 包,用于收发目标设备串口的串行数据,IDF 监视器同时还兼具 IDF 的其他特性。
|
||||
IDF 监视器是一个串行终端程序,使用了 esp-idf-monitor_ 包,用于收发目标设备串口的串行数据,IDF 监视器同时还兼具 ESP-IDF 的其他特性。
|
||||
|
||||
在 IDF 中调用 ``idf.py monitor`` 可以启用此监视器。
|
||||
在 ESP-IDF 中调用 ``idf.py monitor`` 可以启用此监视器。
|
||||
|
||||
操作快捷键
|
||||
==================
|
||||
|
@ -20,54 +20,54 @@ IDF 监视器是一个串行终端程序,使用了 esp-idf-monitor_ 包,用
|
|||
* - 快捷键
|
||||
- 操作
|
||||
- 描述
|
||||
* - Ctrl+]
|
||||
* - Ctrl + ]
|
||||
- 退出监视器程序
|
||||
-
|
||||
* - Ctrl+T
|
||||
* - Ctrl + T
|
||||
- 菜单退出键
|
||||
- 按下如下给出的任意键之一,并按指示操作。
|
||||
* - * Ctrl+T
|
||||
* - * Ctrl + T
|
||||
- 将菜单字符发送至远程
|
||||
-
|
||||
* - * Ctrl+]
|
||||
* - * Ctrl + ]
|
||||
- 将 exit 字符发送至远程
|
||||
-
|
||||
* - * Ctrl+P
|
||||
* - * Ctrl + P
|
||||
- 重置目标设备,进入引导加载程序,通过 RTS 线暂停应用程序
|
||||
- 重置目标设备,通过 RTS 线(如已连接)进入引导加载程序,此时开发板不运行任何程序。等待其他设备启动时可以使用此操作。
|
||||
* - * Ctrl+R
|
||||
* - * Ctrl + R
|
||||
- 通过 RTS 线重置目标设备
|
||||
- 重置设备,并通过 RTS 线(如已连接)重新启动应用程序。
|
||||
* - * Ctrl+F
|
||||
* - * Ctrl + F
|
||||
- 编译并烧录此项目
|
||||
- 暂停 idf_monitor,运行 ``flash`` 目标,然后恢复 idf_monitor。任何改动的源文件都会被重新编译,然后重新烧录。如果 idf_monitor 是以参数 ``-E`` 启动的,则会运行目标 ``encrypted-flash``。
|
||||
* - * Ctrl+A (或者 A)
|
||||
* - * Ctrl + A (或者 A)
|
||||
- 仅编译及烧录应用程序
|
||||
- 暂停 idf_monitor,运行 ``app-flash`` 目标,然后恢复 idf_monitor。 这与 ``flash`` 类似,但只有主应用程序被编译并被重新烧录。如果 idf_monitor 是以参数 ``-E`` 启动的,则会运行目标 ``encrypted-flash``。
|
||||
* - * Ctrl+Y
|
||||
* - * Ctrl + Y
|
||||
- 停止/恢复在屏幕上打印日志输出
|
||||
- 激活时,会丢弃所有传入的串行数据。允许在不退出监视器的情况下快速暂停和检查日志输出。
|
||||
* - * Ctrl+L
|
||||
* - * Ctrl + L
|
||||
- 停止/恢复向文件写入日志输出
|
||||
- 在工程目录下创建一个文件,用于写入日志输出。可使用快捷键停止/恢复该功能(退出 IDF 监视器也会终止该功能)。
|
||||
* - * Ctrl+I (或者 I)
|
||||
* - * Ctrl + I (或者 I)
|
||||
- 停止/恢复打印时间标记
|
||||
- IDF 监视器可以在每一行的开头打印一个时间标记。时间标记的格式可以通过 ``--timestamp-format`` 命令行参数来改变。
|
||||
* - * Ctrl+H (或者 H)
|
||||
* - * Ctrl + H (或者 H)
|
||||
- 显示所有快捷键
|
||||
-
|
||||
* - * Ctrl+X (或者 X)
|
||||
* - * Ctrl + X (或者 X)
|
||||
- 退出监视器程序
|
||||
-
|
||||
* - Ctrl+C
|
||||
* - Ctrl + C
|
||||
- 中断正在运行的应用程序
|
||||
- 暂停 IDF 监视器并运行 GDB_ 项目调试器,从而在运行时调试应用程序。这需要启用 :ref:CONFIG_ESP_SYSTEM_GDBSTUB_RUNTIME 选项。
|
||||
|
||||
除了 ``Ctrl-]`` 和 ``Ctrl-T``,其他快捷键信号会通过串口发送到目标设备。
|
||||
|
||||
|
||||
兼具 IDF 特性
|
||||
=====================
|
||||
兼具 ESP-IDF 特性
|
||||
=========================
|
||||
|
||||
自动解码地址
|
||||
~~~~~~~~~~~~~~~~
|
||||
|
@ -247,6 +247,7 @@ GDBStub 支持在运行时进行调试。GDBStub 在目标上运行,并通过
|
|||
无论是通过发送 ``Ctrl+C`` 还是收到特殊字符串模式,IDF 监视器都会自动启动 GDB,从而让用户发送调试命令。GDB 退出后,通过 RTS 串口线复位目标。如果未连接 RTS 串口线,请按复位键,手动复位开发板。
|
||||
|
||||
.. note::
|
||||
|
||||
IDF 监视器在后台运行如下命令启用 GDB::
|
||||
|
||||
{IDF_TARGET_TOOLCHAIN_PREFIX}-gdb -ex "set serial baud BAUD" -ex "target remote PORT" -ex interrupt build/PROJECT.elf :idf_target:`Hello NAME chip`
|
||||
|
@ -262,6 +263,7 @@ GDBStub 支持在运行时进行调试。GDBStub 在目标上运行,并通过
|
|||
例如,``PRINT_FILTER="tag1:W"`` 只匹配并打印 ``ESP_LOGW("tag1", ...)`` 所写的输出,或者写在较低日志详细度级别的输出,即 ``ESP_LOGE("tag1", ...)``。请勿指定 ``<log_level>`` 或使用详细级别默认值 ``*``。
|
||||
|
||||
.. note::
|
||||
|
||||
编译时,可以使用主日志在 :doc:`日志库 <../../api-reference/system/log>` 中禁用不需要的输出。也可以使用 IDF 监视器筛选输出来调整筛选设置,且无需重新编译应用程序。
|
||||
|
||||
应用程序标签不能包含空格、星号 ``*``、冒号 ``:``,以便兼容输出筛选功能。
|
||||
|
@ -312,7 +314,7 @@ GDBStub 支持在运行时进行调试。GDBStub 在目标上运行,并通过
|
|||
|
||||
|
||||
IDF 监视器已知问题
|
||||
=============================
|
||||
=================================
|
||||
|
||||
Windows 环境下已知问题
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
ESP-IDF 前端工具 - idf.py
|
||||
**********************************
|
||||
IDF 前端工具 - ``idf.py``
|
||||
**************************************
|
||||
|
||||
:link_to_translation:`en:[English]`
|
||||
|
||||
|
@ -107,7 +107,7 @@ ESP-IDF 支持多个目标芯片,运行 ``idf.py --list-targets`` 查看当前
|
|||
|
||||
idf.py fullclean
|
||||
|
||||
此命令将删除所有 ``build`` 子目录内容,包括 CMake 配置输出。下次构建时, CMake 将重新配置其输出。注意,此命令将递归删除构建目录下的 *所有* 文件(工程配置将保留),请谨慎使用。
|
||||
此命令将删除所有 ``build`` 子目录内容,包括 CMake 配置输出。下次构建时,CMake 将重新配置其输出。注意,此命令将递归删除构建目录下的 *所有* 文件(工程配置将保留),请谨慎使用。
|
||||
|
||||
烧录工程:``flash``
|
||||
------------------------
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
ESP-IDF Windows 安装程序
|
||||
IDF Windows 安装程序
|
||||
===========================
|
||||
|
||||
:link_to_translation:`en:[English]`
|
||||
|
@ -6,7 +6,7 @@ ESP-IDF Windows 安装程序
|
|||
命令行参数
|
||||
----------
|
||||
|
||||
ESP-IDF Windows 安装程序 ``esp-idf-tools-setup`` 提供以下命令行参数:
|
||||
IDF Windows 安装程序 ``esp-idf-tools-setup`` 提供以下命令行参数:
|
||||
|
||||
* ``/CONFIG=[PATH]`` - 指定 ``ini`` 配置文件的路径,覆盖安装程序的默认配置。默认值:``config.ini``。
|
||||
* ``/GITCLEAN=[yes|no]`` - 在以离线模式安装时,执行 ``git clean`` 命令,并删除未跟踪的目录。默认值:``yes``。
|
||||
|
@ -45,7 +45,7 @@ ESP-IDF Windows 安装程序 ``esp-idf-tools-setup`` 提供以下命令行参数
|
|||
自定义 Python 版本及 Python Wheel 位置
|
||||
--------------------------------------------------
|
||||
|
||||
ESP-IDF 安装程序默认使用嵌入的 Python 版本,并参考预定义的 Python Wheel 镜像获取所需软件包。
|
||||
IDF 安装程序默认使用嵌入的 Python 版本,并参考预定义的 Python Wheel 镜像获取所需软件包。
|
||||
|
||||
以下参数支持自定义 Python 版本及 Python Wheel 位置:
|
||||
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
{IDF_TARGET_NAME} 中的单元测试
|
||||
============================
|
||||
|
||||
:link_to_translation:`en:[English]`
|
||||
|
||||
ESP-IDF 提供以下方法测试软件。
|
||||
|
||||
- 一种是基于目标的测试,该测试使用运行在 {IDF_TARGET_PATH_NAME} 上的中央单元测试应用程序。这些测试使用的是基于 `Unity <https://www.throwtheswitch.org/unity>`_ 的单元测试框架。通过把测试用例放在组件的 ``test`` 子目录,可以将其集成到 ESP-IDF 组件中。本文档主要介绍这种基于目标的测试方法。
|
||||
|
||||
- 另一种是基于 Linux 主机的单元测试,其中所有硬件行为都通过 Mock 组件进行模拟。此测试方法目前仍在开发中,暂且只有一小部分 IDF 组件支持 Mock,具体请参考 :doc:`基于 Linux 主机的单元测试 <host-apps>`。
|
||||
- 另一种是基于 Linux 主机的单元测试,其中所有硬件行为都通过 Mock 组件进行模拟。此测试方法目前仍在开发中,暂且只有一小部分 ESP-IDF 组件支持 Mock,具体请参考 :doc:`基于 Linux 主机的单元测试 <host-apps>`。
|
||||
|
||||
添加常规测试用例
|
||||
----------------
|
||||
|
@ -84,16 +85,16 @@ ESP-IDF 提供以下方法测试软件。
|
|||
|
||||
在不同的 DUT 上运行的测试用例需要相互之间进行同步。可以通过 ``unity_wait_for_signal`` 和 ``unity_send_signal`` 这两个函数使用 UART 进行同步操作。上例的场景中,slave 应该在 master 设置好 GPIO 电平后再去读取 GPIO 电平,DUT 的 UART 终端会打印提示信息,并要求用户进行交互。
|
||||
|
||||
DUT1(master)终端::
|
||||
DUT1 (master) 终端::
|
||||
|
||||
Waiting for signal: [output high level]!
|
||||
Please press "Enter" key once any board send this signal.
|
||||
|
||||
DUT2(slave)终端::
|
||||
DUT2 (slave) 终端::
|
||||
|
||||
Send signal: [output high level]!
|
||||
|
||||
一旦 DUT2 发送了该信号,您需要在 DUT1 的终端按回车键,然后 DUT1 会从 ``unity_wait_for_signal`` 函数中解除阻塞,并开始更改 GPIO 的电平。
|
||||
一旦 DUT2 发送了该信号,你需要在 DUT1 的终端按回车键,然后 DUT1 会从 ``unity_wait_for_signal`` 函数中解除阻塞,并开始更改 GPIO 的电平。
|
||||
|
||||
|
||||
添加多阶段测试用例
|
||||
|
@ -120,9 +121,9 @@ DUT2(slave)终端::
|
|||
应用于不同芯片的单元测试
|
||||
------------------------
|
||||
|
||||
某些测试(尤其与硬件相关的)不支持在所有的芯片上执行。请参照本节,让您的单元测试只在其中一部分芯片上执行。
|
||||
某些测试(尤其与硬件相关的)不支持在所有的芯片上执行。请参照本节,让你的单元测试只在其中一部分芯片上执行。
|
||||
|
||||
1. 使用宏 ``!(TEMPORARY_)DISABLED_FOR_TARGETS()`` 包装您的测试代码,并将其放于原始的测试文件中,或将代码分成按功能分组的文件。但请确保所有这些文件都会由编译器处理。例::
|
||||
1. 使用宏 ``!(TEMPORARY_)DISABLED_FOR_TARGETS()`` 包装你的测试代码,并将其放于原始的测试文件中,或将代码分成按功能分组的文件。但请确保所有这些文件都会由编译器处理。例::
|
||||
|
||||
#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32, ESP8266)
|
||||
TEST_CASE("a test that is not ready for esp32 and esp8266 yet", "[]")
|
||||
|
@ -130,7 +131,7 @@ DUT2(slave)终端::
|
|||
}
|
||||
#endif //!TEMPORARY_DISABLED_FOR_TARGETS(ESP32, ESP8266)
|
||||
|
||||
如果您需要将其中某个测试在特定芯片上编译,只需要修改禁止的芯片列表。推荐使用一些能在 ``soc_caps.h`` 中被清楚描述的通用概念来禁止某些单元测试。如果您已经进行上述操作,但一些测试在芯片中的调试暂未通过,请同时使用上述两种方法,当调试完成后再移除 ``!(TEMPORARY_)DISABLED_FOR_TARGETS()`` 。例: ::
|
||||
如果需要将其中某个测试在特定芯片上编译,只需要修改禁止的芯片列表。推荐使用一些能在 ``soc_caps.h`` 中被清楚描述的通用概念来禁止某些单元测试。如果已经进行上述操作,但一些测试在芯片中的调试暂未通过,请同时使用上述两种方法,当调试完成后再移除 ``!(TEMPORARY_)DISABLED_FOR_TARGETS()`` 。例: ::
|
||||
|
||||
#if SOC_SDIO_SLAVE_SUPPORTED
|
||||
#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP64)
|
||||
|
@ -141,11 +142,11 @@ DUT2(slave)终端::
|
|||
#endif //!TEMPORARY_DISABLED_FOR_TARGETS(ESP64)
|
||||
#endif //SOC_SDIO_SLAVE_SUPPORTED
|
||||
|
||||
2. 对于某些您确定不会支持的测试(例如,芯片根本没有该外设),使用 ``DISABLED_FOR_TARGETS`` 来禁止该测试;对于其他只是临时性需要关闭的(例如,没有 runner 资源等),使用 ``TEMPORARY_DISABLED_FOR_TARGETS`` 来暂时关闭该测试。
|
||||
2. 对于某些你确定不会支持的测试(例如,芯片根本没有该外设),使用 ``DISABLED_FOR_TARGETS`` 来禁止该测试;对于其他只是临时性需要关闭的(例如,没有 runner 资源等),使用 ``TEMPORARY_DISABLED_FOR_TARGETS`` 来暂时关闭该测试。
|
||||
|
||||
一些禁用目标芯片测试用例的旧方法,由于它们具有明显的缺陷,已经被废弃,请勿继续使用:
|
||||
|
||||
- 请勿将测试代码放在 ``test/target`` 目录下并用 CMakeLists.txt 来选择其中一个进行编译。这是因为测试代码比实现代码更容易被复用。如果您将一些代码放在 ``test/esp32`` 目录下来避免 esp32s2 芯片执行它,一旦您需要在新的芯片(比如 esp32s3)中启用该测试,这种结构很难保持代码整洁。
|
||||
- 请勿将测试代码放在 ``test/target`` 目录下并用 CMakeLists.txt 来选择其中一个进行编译。这是因为测试代码比实现代码更容易被复用。如果你将一些代码放在 ``test/esp32`` 目录下来避免 esp32s2 芯片执行它,一旦你需要在新的芯片(比如 esp32s3)中启用该测试,这种结构很难保持代码整洁。
|
||||
|
||||
- 请勿继续使用 ``CONFIG_IDF_TARGET_xxx`` 宏来禁用测试。这种方法会让被禁用的测试项目难以追踪和重新打开。并且,相比于白名单式的 ``#if CONFIG_IDF_TARGET_xxx``,黑名单式的 ``#if !disabled`` 不会导致在新芯片引入时这些测试被自动禁用。但对于测试实现,仍可使用 ``#if CONFIG_IDF_TARGET_xxx`` 给不同芯片版本选择实现代码。测试项目和测试实现区分如下:
|
||||
|
||||
|
@ -155,7 +156,7 @@ DUT2(slave)终端::
|
|||
|
||||
- 测试实现:一些始终会发生的代码,但采取的实现方式不同。例如:
|
||||
|
||||
ESP8266 芯片没有 SDIO_PKT_LEN 寄存器。如果在测试过程中需要从 slave 设备的数据长度,您可以用不同方式读取的 ``#if CONFIG_IDF_TARGET_`` 宏来保护不同的实现代码。
|
||||
ESP8266 芯片没有 SDIO_PKT_LEN 寄存器。如果在测试过程中需要从 slave 设备的数据长度,你可以用不同方式读取的 ``#if CONFIG_IDF_TARGET_`` 宏来保护不同的实现代码。
|
||||
|
||||
但请注意避免使用 ``#else`` 宏。这样当新芯片被引入时,测试就会在编译阶段失败,提示维护者去显示选择一个正确的测试实现。
|
||||
|
||||
|
@ -175,9 +176,9 @@ DUT2(slave)终端::
|
|||
|
||||
由于 Windows 命令提示符固有限制,需使用以下语法来编译多个组件的单元测试程序:``idf.py -T xxx -T yyy build`` 或者在 PowerShell 中使用 ``idf.py -T \`"xxx yyy\`" build``,在 Windows 命令提示符中使用 ``idf.py -T \^"ssd1306 hts221\^" build``。
|
||||
|
||||
当编译完成时,它会打印出烧写芯片的指令。您只需要运行 ``idf.py flash`` 即可烧写所有编译输出的文件。
|
||||
当编译完成时,它会打印出烧写芯片的指令。你只需要运行 ``idf.py flash`` 即可烧写所有编译输出的文件。
|
||||
|
||||
您还可以运行 ``idf.py -T all flash`` 或者 ``idf.py -T xxx flash`` 来编译并烧写,所有需要的文件都会在烧写之前自动重新编译。
|
||||
你还可以运行 ``idf.py -T all flash`` 或者 ``idf.py -T xxx flash`` 来编译并烧写,所有需要的文件都会在烧写之前自动重新编译。
|
||||
|
||||
使用 ``menuconfig`` 可以设置烧写测试程序所使用的串口。更多信息,见 :idf_file:`tools/unit-test-app/README.md`。
|
||||
|
||||
|
@ -188,7 +189,7 @@ DUT2(slave)终端::
|
|||
|
||||
当单元测试应用程序空闲时,输入回车键,它会打印出测试菜单,其中包含所有的测试项目::
|
||||
|
||||
Here's the test menu, pick your combo:
|
||||
Here is the test menu, pick your combo:
|
||||
(1) "esp_ota_begin() verifies arguments" [ota]
|
||||
(2) "esp_ota_get_next_update_partition logic" [ota]
|
||||
(3) "Verify bootloader image in flash" [bootloader_support]
|
||||
|
@ -232,7 +233,7 @@ DUT2(slave)终端::
|
|||
(1) "gpio_master_test"
|
||||
(2) "gpio_slave_test"
|
||||
|
||||
您需要输入数字以选择在 DUT 上运行的测试。
|
||||
你需要输入数字以选择在 DUT 上运行的测试。
|
||||
|
||||
与多设备测试用例相似,多阶段测试用例也会打印子菜单::
|
||||
|
||||
|
@ -249,13 +250,13 @@ DUT2(slave)终端::
|
|||
带缓存补偿定时器的定时代码
|
||||
-----------------------------------------
|
||||
|
||||
存储在外部存储器(如 SPI Flash 和 SPI RAM)中的指令和数据是通过 CPU 的统一指令和数据缓存来访问的。当代码或数据在缓存中时,访问速度会非常快(即缓存命中)。
|
||||
存储在外部存储器(如 SPI flash 和 SPI RAM)中的指令和数据是通过 CPU 的统一指令和数据缓存来访问的。当代码或数据在缓存中时,访问速度会非常快(即缓存命中)。
|
||||
|
||||
然而,如果指令或数据不在缓存中,则需要从外部存储器中获取(即缓存缺失)。访问外部存储器的速度明显较慢,因为 CPU 在等待从外部存储器获取指令或数据时会陷入停滞,从而导致整体代码执行速度会依据缓存命中或缓存缺失的次数而变化。
|
||||
|
||||
在不同的编译中,代码和数据的位置可能会有所不同,一些可能会更有利于缓存访问(即最大限度地减少缓存缺失)。理论上,这会影响执行速度,但这些因素通常无关紧要,因为它们的影响会在设备的运行过程中“平均化”。
|
||||
|
||||
然而,高速缓存对执行速度的影响可能与基准测试场景(尤其是微基准测试)有关。每次运行时间和构建时的测量时间可能会有所差异,减少差异的方法之一是将代码和数据分别放在指令或数据 RAM(IRAM/DRAM)中。CPU 可以直接访问 IRAM 和 DRAM,从而消除了高速缓存的影响因素。然而,由于 IRAM 和 DRAM 容量有限,该方法并不总是可行。
|
||||
然而,高速缓存对执行速度的影响可能与基准测试场景(尤其是微基准测试)有关。每次运行时间和构建时的测量时间可能会有所差异,减少差异的方法之一是将代码和数据分别放在指令或数据 RAM (IRAM/DRAM) 中。CPU 可以直接访问 IRAM 和 DRAM,从而消除了高速缓存的影响因素。然而,由于 IRAM 和 DRAM 容量有限,该方法并不总是可行。
|
||||
|
||||
缓存补偿定时器是上述方法的替代方法,该计时器使用处理器的内部事件计数器来确定在发生高速缓存未命中时等待代码/数据所花费的时间,然后从记录的实时时间中减去该时间。
|
||||
|
||||
|
@ -280,7 +281,7 @@ Mocks
|
|||
----------
|
||||
|
||||
.. note::
|
||||
目前,只有一些特定的组件在 Linux 主机上运行时才能 Mock。未来我们计划,无论是在 Linux 主机上运行还是在目标芯片 {IDF_TARGET_NAME} 上运行,IDF 所有重要的组件都可以实现 Mock。
|
||||
目前,只有一些特定的组件在 Linux 主机上运行时才能 Mock。未来我们计划,无论是在 Linux 主机上运行还是在目标芯片 {IDF_TARGET_NAME} 上运行,ESP-IDF 所有重要的组件都可以实现 Mock。
|
||||
|
||||
嵌入式系统中单元测试的最大问题之一是对硬件依赖性极强。直接在 {IDF_TARGET_NAME} 上运行单元测试对于上层组件来说存在极大的困难,原因如下:
|
||||
|
||||
|
@ -288,12 +289,12 @@ Mocks
|
|||
- 由于下层组件和/或硬件设置的限制,测试边缘案例的难度提高。
|
||||
- 由于数量庞大的依赖关系影响了行为,识别根本原因的难度提高。
|
||||
|
||||
当测试一个特定的组件(即被测组件)时,通过软件进行 Mock 能让所有被测组件的依赖在软件中被完全替换(即 Mock)。为了实现该功能,ESP-IDF 集成了 `CMock <https://www.throwtheswitch.org/cmock>`_ 的 Mock 框架作为组件。通过在 ESP-IDF 的构建系统中添加一些 CMake 函数,可以方便地 Mock 整个(或部分)IDF 组件。
|
||||
当测试一个特定的组件(即被测组件)时,通过软件进行 Mock 能让所有被测组件的依赖在软件中被完全替换(即 Mock)。为了实现该功能,ESP-IDF 集成了 `CMock <https://www.throwtheswitch.org/cmock>`_ 的 Mock 框架作为组件。通过在 ESP-IDF 的构建系统中添加一些 CMake 函数,可以方便地 Mock 整个(或部分)ESP-IDF 组件。
|
||||
|
||||
理想情况下,被测组件所依赖的所有组件都应该被 Mock,从而让测试环境完全控制与被测组件之间的所有交互。然而,如果 Mock 所有的组件过于复杂或冗长(例如需要模拟过多的函数调用),以下做法可能会有帮助:
|
||||
|
||||
.. list::
|
||||
- 在测试代码中包含更多“真正”(非模拟)代码。这样做可能有效,但同时也会增加对“真正”代码行为的依赖。此外,一旦测试失败,很难判断失败原因是因为实际测试代码还是“真正”地 IDF 代码。
|
||||
- 在测试代码中包含更多“真正”(非模拟)代码。这样做可能有效,但同时也会增加对“真正”代码行为的依赖。此外,一旦测试失败,很难判断失败原因是因为实际测试代码还是“真正”的 ESP-IDF 代码。
|
||||
- 重新评估被测代码的设计,尝试将被测代码划分为更易于管理的组件来减少其依赖性。这可能看起来很麻烦,但众所周知,单元测试经常暴露软件设计的弱点。修复设计上的弱点不仅在短期内有助于进行单元测试,而且还有助于长期的代码维护。
|
||||
|
||||
请参考 :component_file:`cmock/CMock/docs/CMock_Summary.md` 了解 CMock 工作原理以及如何创建和使用 Mock。
|
||||
|
@ -319,7 +320,7 @@ Mocks
|
|||
- 上述头文件的路径
|
||||
- 模拟组件的依赖(如果头文件中包含了其他组件的文件,那么这点非常必要)
|
||||
|
||||
以上这些部分都需要使用 IDF 构建系统函数 ``idf_component_mock`` 指定。您可以使用 IDF 构建系统函数 ``idf_component_get_property``,并加上标签 ``COMPONENT_OVERRIDEN_DIR`` 来访问原始组件的组件目录,然后使用 ``idf_component_mock`` 注册模拟组件。
|
||||
以上这些部分都需要使用 ESP-IDF 构建系统函数 ``idf_component_mock`` 指定。你可以使用 ESP-IDF 构建系统函数 ``idf_component_get_property``,并加上标签 ``COMPONENT_OVERRIDEN_DIR`` 来访问原始组件的组件目录,然后使用 ``idf_component_mock`` 注册模拟组件。
|
||||
|
||||
.. code:: none
|
||||
|
||||
|
@ -340,9 +341,9 @@ Mocks
|
|||
|
||||
更多关于 CMock yaml 类型配置文件的详细信息,请查看 :component_file:`cmock/CMock/docs/CMock_Summary.md`。
|
||||
|
||||
请注意,组件模拟不一定要对原始组件进行整体模拟。只要组件模拟满足测试项目的依赖以及其他代码对原始组件的依赖,部分模拟就足够了。事实上,IDF 中 ``tools/mocks`` 中的大多数组件模拟都只是部分地模拟了原始组件。
|
||||
请注意,组件模拟不一定要对原始组件进行整体模拟。只要组件模拟满足测试项目的依赖以及其他代码对原始组件的依赖,部分模拟就足够了。事实上,ESP-IDF 中 ``tools/mocks`` 中的大多数组件模拟都只是部分地模拟了原始组件。
|
||||
|
||||
可在 IDF 目录的 :idf:`tools/mocks` 下找到组件模拟的示例。有关如何 *覆盖 IDF 组件*,可查看 :ref:`同名组件 <cmake-components-same-name>`。
|
||||
可在 ESP-IDF 目录的 :idf:`tools/mocks` 下找到组件模拟的示例。有关如何 *覆盖 ESP-IDF 组件*,可查看 :ref:`同名组件 <cmake-components-same-name>`。
|
||||
|
||||
- :component_file:`NVS 页面类的单元测试 <nvs_flash/host_test/nvs_page_test/README.md>`。
|
||||
- :component_file:`esp_event 的单元测试 <esp_event/host_test/esp_event_unit_test/main/esp_event_test.cpp>`。
|
||||
|
@ -359,6 +360,6 @@ Mocks
|
|||
|
||||
list(APPEND EXTRA_COMPONENT_DIRS "<mock_component_dir>")
|
||||
|
||||
这两种方法都会让组件模拟覆盖 ESP-IDF 中的现有组件。如果您使用的是 IDF 提供的组件模拟,则第二个方法更加方便。
|
||||
这两种方法都会让组件模拟覆盖 ESP-IDF 中的现有组件。如果你使用的是 ESP-IDF 提供的组件模拟,则第二个方法更加方便。
|
||||
|
||||
您可参考 ``esp_event`` 基于主机的单元测试及其 :component_file:`esp_event/host_test/esp_event_unit_test/CMakeLists.txt` 作为组件模拟的示例。
|
||||
可参考 ``esp_event`` 基于主机的单元测试及其 :component_file:`esp_event/host_test/esp_event_unit_test/CMakeLists.txt` 作为组件模拟的示例。
|
||||
|
|
|
@ -9,6 +9,7 @@ Wi-Fi 驱动程序
|
|||
|
||||
{IDF_TARGET_NAME} Wi-Fi 功能列表
|
||||
------------------------------------
|
||||
|
||||
{IDF_TARGET_NAME} 支持以下 Wi-Fi 功能:
|
||||
|
||||
.. only:: esp32 or esp32s2 or esp32c3 or esp32s3
|
||||
|
@ -47,7 +48,7 @@ Wi-Fi 驱动程序
|
|||
|
||||
.. only:: esp32c2
|
||||
|
||||
- 支持 3 个虚拟接口,即STA、AP 和 Sniffer。
|
||||
- 支持 3 个虚拟接口,即 STA、AP 和 Sniffer。
|
||||
- 支持仅 station 模式、仅 AP 模式、station/AP 共存模式
|
||||
- 支持使用 IEEE 802.11b、IEEE 802.11g、IEEE 802.11n 和 API 配置协议模式
|
||||
- 支持 WPA/WPA2/WPA3/WPA2-企业版/WPA3-企业版/WPS 和 DPP
|
||||
|
@ -64,33 +65,40 @@ Wi-Fi 驱动程序
|
|||
|
||||
准备工作
|
||||
+++++++++++
|
||||
一般来说,要编写自己的 Wi-Fi 应用程序,最高效的方式是先选择一个相似的应用程序示例,然后将其中可用的部分移植到自己的项目中。如果您希望编写一个强健的 Wi-Fi 应用程序,强烈建议您在开始之前先阅读本文。**非强制要求,请依个人情况而定。**
|
||||
|
||||
本文将补充说明 Wi-Fi API 和 Wi-Fi 示例的相关信息,重点描述使用 Wi-Fi API 的原则、当前 Wi-Fi API 实现的限制以及使用 Wi-Fi 时的常见错误。同时,本文还介绍了 Wi-Fi 驱动程序的一些设计细节。建议您选择一个示例 :example:`example <wifi>` 进行参考。
|
||||
一般来说,要编写自己的 Wi-Fi 应用程序,最高效的方式是先选择一个相似的应用程序示例,然后将其中可用的部分移植到自己的项目中。如果你希望编写一个强健的 Wi-Fi 应用程序,强烈建议在开始之前先阅读本文。**非强制要求,请依个人情况而定。**
|
||||
|
||||
本文将补充说明 Wi-Fi API 和 Wi-Fi 示例的相关信息,重点描述使用 Wi-Fi API 的原则、当前 Wi-Fi API 实现的限制以及使用 Wi-Fi 时的常见错误。同时,本文还介绍了 Wi-Fi 驱动程序的一些设计细节。建议选择一个示例 :example:`example <wifi>` 进行参考。
|
||||
|
||||
设置 Wi-Fi 编译时选项
|
||||
++++++++++++++++++++++++++++++++++++
|
||||
|
||||
请参阅 `Wi-Fi menuconfig`_。
|
||||
|
||||
Wi-Fi 初始化
|
||||
+++++++++++++++
|
||||
|
||||
请参阅 `{IDF_TARGET_NAME} Wi-Fi station 一般情况`_、`{IDF_TARGET_NAME} Wi-Fi AP 一般情况`_。
|
||||
|
||||
启动/连接 Wi-Fi
|
||||
++++++++++++++++++++
|
||||
|
||||
请参阅 `{IDF_TARGET_NAME} Wi-Fi station 一般情况`_、`{IDF_TARGET_NAME} Wi-Fi AP 一般情况`_。
|
||||
|
||||
事件处理
|
||||
++++++++++++++
|
||||
|
||||
通常,在理想环境下编写代码难度并不大,如 `WIFI_EVENT_STA_START`_、`WIFI_EVENT_STA_CONNECTED`_ 中所述。难度在于如何在现实的困难环境下编写代码,如 `WIFI_EVENT_STA_DISCONNECTED`_ 中所述。能否在后者情况下完美地解决各类事件冲突,是编写一个强健的 Wi-Fi 应用程序的根本。请参阅 `{IDF_TARGET_NAME} Wi-Fi 事件描述`_, `{IDF_TARGET_NAME} Wi-Fi station 一般情况`_, `{IDF_TARGET_NAME} Wi-Fi AP 一般情况`_。另可参阅 ESP-IDF 中的 :doc:`事件处理概述 <../api-reference/system/esp_event>`。
|
||||
|
||||
编写错误恢复程序
|
||||
++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
除了能在比较差的环境下工作,错误恢复能力也对一个强健的 Wi-Fi 应用程序至关重要。请参阅 `{IDF_TARGET_NAME} Wi-Fi API 错误代码`_。
|
||||
|
||||
|
||||
{IDF_TARGET_NAME} Wi-Fi API 错误代码
|
||||
--------------------------------------
|
||||
|
||||
所有 {IDF_TARGET_NAME} Wi-Fi API 都有定义好的返回值,即错误代码。这些错误代码可分类为:
|
||||
|
||||
- 无错误,例如:返回值 :c:macro:`ESP_OK` 代表 API 成功返回
|
||||
|
@ -102,9 +110,9 @@ Wi-Fi 初始化
|
|||
|
||||
**要使用 Wi-Fi API 编写一个强健的应用程序,根本原则便是要时刻检查错误代码并编写相应的错误处理代码。** 一般来说,错误处理代码可用于解决:
|
||||
|
||||
- 可恢复错误,您可以编写一个可恢复错误处理代码解决该类错误。例如,当 :cpp:func:`esp_wifi_start()` 返回 :c:macro:`ESP_ERR_NO_MEM` 时,调用可恢复错误处理代码 vTaskDelay 可以获取几微秒的重试时间。
|
||||
- 不可恢复非关键性错误,打印错误代码可以帮助您更好地处理该类错误。
|
||||
- 不可恢复关键性错误,可使用 "assert" 语句处理该类错误。例如,如果 :cpp:func:`esp_wifi_set_mode()` 返回 ``ESP_ERR_WIFI_NOT_INIT`` :cpp:func:`esp_wifi_init()` 未成功初始化 Wi-Fi 驱动程序。您可以在应用程序开发阶段非常快速地检测到此类错误。
|
||||
- 可恢复错误,你可以编写一个可恢复错误处理代码解决该类错误。例如,当 :cpp:func:`esp_wifi_start()` 返回 :c:macro:`ESP_ERR_NO_MEM` 时,调用可恢复错误处理代码 vTaskDelay 可以获取几微秒的重试时间。
|
||||
- 不可恢复非关键性错误,打印错误代码可以帮助你更好地处理该类错误。
|
||||
- 不可恢复关键性错误,可使用 "assert" 语句处理该类错误。例如,如果 :cpp:func:`esp_wifi_set_mode()` 返回 ``ESP_ERR_WIFI_NOT_INIT`` :cpp:func:`esp_wifi_init()` 未成功初始化 Wi-Fi 驱动程序。你可以在应用程序开发阶段非常快速地检测到此类错误。
|
||||
|
||||
在 :component_file:`esp_common/include/esp_err.h` 中, ``ESP_ERROR_CHECK`` 负责检查返回值。这是一个较为常见的错误处理代码,可在应用程序开发阶段作为默认的错误处理代码。但是,我们强烈建议 API 的使用者编写自己的错误处理代码。
|
||||
|
||||
|
@ -116,12 +124,13 @@ Wi-Fi 初始化
|
|||
- 设置该参数的所有字段
|
||||
- 先使用 get API 获取当前配置,然后只设置特定于应用程序的字段
|
||||
|
||||
初始化或获取整个结构这一步至关重要,因为大多数情况下,返回值 0 意味着程序使用了默认值。未来,我们将会在该结构中加入更多字段,并将这些字段初始化为 0,确保即使 IDF 版本升级后您的应用程序依然能够正常运行。
|
||||
初始化或获取整个结构这一步至关重要,因为大多数情况下,返回值 0 意味着程序使用了默认值。未来,我们将会在该结构中加入更多字段,并将这些字段初始化为 0,确保即使 ESP-IDF 版本升级后,你的应用程序依然能够正常运行。
|
||||
|
||||
.. _wifi-programming-model:
|
||||
|
||||
{IDF_TARGET_NAME} Wi-Fi 编程模型
|
||||
-----------------------------------------
|
||||
|
||||
{IDF_TARGET_NAME} Wi-Fi 编程模型如下图所示:
|
||||
|
||||
.. blockdiag::
|
||||
|
@ -176,10 +185,12 @@ Wi-Fi 事件处理是在 :doc:`esp_event 库 <../api-reference/system/esp_event>
|
|||
|
||||
WIFI_EVENT_WIFI_READY
|
||||
++++++++++++++++++++++++++++++++++++
|
||||
|
||||
Wi-Fi 驱动程序永远不会生成此事件,因此,应用程序的事件回调函数可忽略此事件。在未来的版本中,此事件可能会被移除。
|
||||
|
||||
WIFI_EVENT_SCAN_DONE
|
||||
++++++++++++++++++++++++++++++++++++
|
||||
|
||||
扫描完成事件,由 :cpp:func:`esp_wifi_scan_start()` 函数触发,将在以下情况下产生:
|
||||
|
||||
- 扫描已完成,例如:Wi-Fi 已成功找到目标 AP 或已扫描所有信道。
|
||||
|
@ -196,18 +207,22 @@ WIFI_EVENT_SCAN_DONE
|
|||
|
||||
WIFI_EVENT_STA_START
|
||||
++++++++++++++++++++++++++++++++++++
|
||||
|
||||
如果调用函数 :cpp:func:`esp_wifi_start()` 后接收到返回值 :c:macro:`ESP_OK`,且当前 Wi-Fi 处于 station 或 station/AP 共存模式,则将产生此事件。接收到此事件后,事件任务将初始化 LwIP 网络接口 (netif)。通常,应用程序的事件回调函数需调用 :cpp:func:`esp_wifi_connect()` 来连接已配置的 AP。
|
||||
|
||||
WIFI_EVENT_STA_STOP
|
||||
++++++++++++++++++++++++++++++++++++
|
||||
|
||||
如果调用函数 :cpp:func:`esp_wifi_stop()` 后接收到返回值 :c:macro:`ESP_OK`,且当前 Wi-Fi 处于 station 或 station/AP 共存模式,则将产生此事件。接收到此事件后,事件任务将进行释放 station IP 地址、终止 DHCP 客户端服务、移除 TCP/UDP 相关连接并清除 LwIP station netif 等动作。此时,应用程序的事件回调函数通常不需做任何响应。
|
||||
|
||||
WIFI_EVENT_STA_CONNECTED
|
||||
++++++++++++++++++++++++++++++++++++
|
||||
如果调用函数 :cpp:func:`esp_wifi_connect()` 后接收到返回值 :c:macro:`ESP_OK`,且 station 已成功连接目标 AP,则将产生此连接事件。接收到此事件后,事件任务将启动 DHCP 客户端服务并开始获取 IP 地址。此时,Wi-Fi 驱动程序已准备就绪,可发送和接收数据。如果您的应用程序不依赖于 LwIP(即 IP 地址),则此刻便可以开始应用程序开发工作。但是,如果您的应用程序需基于 LwIP 进行,则还需等待 *got ip* 事件发生后才可开始。
|
||||
|
||||
如果调用函数 :cpp:func:`esp_wifi_connect()` 后接收到返回值 :c:macro:`ESP_OK`,且 station 已成功连接目标 AP,则将产生此连接事件。接收到此事件后,事件任务将启动 DHCP 客户端服务并开始获取 IP 地址。此时,Wi-Fi 驱动程序已准备就绪,可发送和接收数据。如果你的应用程序不依赖于 LwIP(即 IP 地址),则此刻便可以开始应用程序开发工作。但是,如果你的应用程序需基于 LwIP 进行,则还需等待 *got ip* 事件发生后才可开始。
|
||||
|
||||
WIFI_EVENT_STA_DISCONNECTED
|
||||
++++++++++++++++++++++++++++++++++++
|
||||
|
||||
此事件将在以下情况下产生:
|
||||
|
||||
- 调用了函数 :cpp:func:`esp_wifi_disconnect()` 或 :cpp:func:`esp_wifi_stop()`,且 Wi-Fi station 已成功连接至 AP。
|
||||
|
@ -232,6 +247,7 @@ WIFI_EVENT_STA_DISCONNECTED
|
|||
|
||||
IP_EVENT_STA_GOT_IP
|
||||
++++++++++++++++++++++++++++++++++++
|
||||
|
||||
当 DHCP 客户端成功从 DHCP 服务器获取 IPV4 地址或 IPV4 地址发生改变时,将引发此事件。此事件意味着应用程序一切就绪,可以开始任务(如:创建套接字)。
|
||||
|
||||
IPV4 地址可能由于以下原因而发生改变:
|
||||
|
@ -246,10 +262,12 @@ IPV4 地址可能由于以下原因而发生改变:
|
|||
|
||||
IP_EVENT_GOT_IP6
|
||||
++++++++++++++++++++++++++++++++++++
|
||||
|
||||
当 IPV6 SLAAC 支持自动为 {IDF_TARGET_NAME} 配置一个地址,或 {IDF_TARGET_NAME} 地址发生改变时,将引发此事件。此事件意味着应用程序一切就绪,可以开始任务(如:创建套接字)。
|
||||
|
||||
IP_EVENT_STA_LOST_IP
|
||||
++++++++++++++++++++++++++++++++++++
|
||||
|
||||
当 IPV4 地址失效时,将引发此事件。
|
||||
|
||||
此事件不会在 Wi-Fi 断连后立刻出现。Wi-Fi 连接断开后,首先将启动一个 IPV4 地址丢失计时器,如果 station 在该计时器超时之前成功获取了 IPV4 地址,则不会发生此事件。否则,此事件将在计时器超时时发生。
|
||||
|
@ -258,18 +276,22 @@ IP_EVENT_STA_LOST_IP
|
|||
|
||||
WIFI_EVENT_AP_START
|
||||
++++++++++++++++++++++++++++++++++++
|
||||
|
||||
与 `WIFI_EVENT_STA_START`_ 事件相似。
|
||||
|
||||
WIFI_EVENT_AP_STOP
|
||||
++++++++++++++++++++++++++++++++++++
|
||||
|
||||
与 `WIFI_EVENT_STA_STOP`_ 事件相似。
|
||||
|
||||
WIFI_EVENT_AP_STACONNECTED
|
||||
++++++++++++++++++++++++++++++++++++
|
||||
每当有一个 station 成功连接 {IDF_TARGET_NAME} AP 时,将引发此事件。接收到此事件后,事件任务将不做任何响应,应用程序的回调函数也可忽略这一事件。但是,您可以在此时进行一些操作,例如:获取已连接 station 的信息等。
|
||||
|
||||
每当有一个 station 成功连接 {IDF_TARGET_NAME} AP 时,将引发此事件。接收到此事件后,事件任务将不做任何响应,应用程序的回调函数也可忽略这一事件。但是,你可以在此时进行一些操作,例如:获取已连接 station 的信息等。
|
||||
|
||||
WIFI_EVENT_AP_STADISCONNECTED
|
||||
++++++++++++++++++++++++++++++++++++
|
||||
|
||||
此事件将在以下情况下发生:
|
||||
|
||||
- 应用程序通过调用函数 :cpp:func:`esp_wifi_disconnect()` 或 :cpp:func:`esp_wifi_deauth_sta()` 手动断开 station 连接。
|
||||
|
@ -296,6 +318,7 @@ WIFI_EVENT_CONNECTIONLESS_MODULE_WAKE_INTERVAL_START
|
|||
|
||||
{IDF_TARGET_NAME} Wi-Fi station 一般情况
|
||||
------------------------------------------------
|
||||
|
||||
下图为 station 模式下的宏观场景,其中包含不同阶段的具体描述:
|
||||
|
||||
.. seqdiag::
|
||||
|
@ -354,6 +377,7 @@ WIFI_EVENT_CONNECTIONLESS_MODULE_WAKE_INTERVAL_START
|
|||
|
||||
1. Wi-Fi/LwIP 初始化阶段
|
||||
++++++++++++++++++++++++++++++
|
||||
|
||||
- s1.1:主任务通过调用函数 :cpp:func:`esp_netif_init()` 创建一个 LwIP 核心任务,并初始化 LwIP 相关工作。
|
||||
|
||||
- s1.2:主任务通过调用函数 :cpp:func:`esp_event_loop_create()` 创建一个系统事件任务,并初始化应用程序事件的回调函数。在此情况下,该回调函数唯一的动作就是将事件中继到应用程序任务中。
|
||||
|
@ -364,29 +388,32 @@ WIFI_EVENT_CONNECTIONLESS_MODULE_WAKE_INTERVAL_START
|
|||
|
||||
- s1.5:主任务通过调用 OS API 创建应用程序任务。
|
||||
|
||||
推荐按照 s1.1 ~ s1.5 的步骤顺序针对基于 Wi-Fi/LwIP 的应用程序进行初始化。但这一顺序 **并非** 强制,您可以在第 s1.1 步创建应用程序任务,然后在该应用程序任务中进行所有其它初始化操作。不过,如果您的应用程序任务依赖套接字,那么在初始化阶段创建应用程序任务可能并不适用。此时,您可以在接收到 IP 后再进行任务创建。
|
||||
推荐按照 s1.1 ~ s1.5 的步骤顺序针对基于 Wi-Fi/LwIP 的应用程序进行初始化。但这一顺序 **并非** 强制,你可以在第 s1.1 步创建应用程序任务,然后在该应用程序任务中进行所有其它初始化操作。不过,如果你的应用程序任务依赖套接字,那么在初始化阶段创建应用程序任务可能并不适用。此时,你可以在接收到 IP 后再进行任务创建。
|
||||
|
||||
2. Wi-Fi 配置阶段
|
||||
+++++++++++++++++++++++++++++++
|
||||
Wi-Fi 驱动程序初始化成功后,可以进入到配置阶段。该场景下,Wi-Fi 驱动程序处于 station 模式。因此,首先您需调用函数 :cpp:func:`esp_wifi_set_mode` (WIFI_MODE_STA) 将 Wi-Fi 模式配置为 station 模式。可通过调用其它 esp_wifi_set_xxx API 进行更多设置,例如:协议模式、国家代码、带宽等。请参阅 `{IDF_TARGET_NAME} Wi-Fi 配置`_。
|
||||
|
||||
一般情况下,我们会在建立 Wi-Fi 连接之前配置 Wi-Fi 驱动程序,但这 **并非** 强制要求。也就是说,只要 Wi-Fi 驱动程序已成功初始化,您可以在任意阶段进行配置。但是,如果您的 Wi-Fi 在建立连接后不需要更改配置,则应先在此阶段完成配置。因为调用配置 API(例如 :cpp:func:`esp_wifi_set_protocol()`)将会导致 Wi-Fi 连接断开,为您的操作带来不便。
|
||||
Wi-Fi 驱动程序初始化成功后,可以进入到配置阶段。该场景下,Wi-Fi 驱动程序处于 station 模式。因此,首先你需调用函数 :cpp:func:`esp_wifi_set_mode` (WIFI_MODE_STA) 将 Wi-Fi 模式配置为 station 模式。可通过调用其它 esp_wifi_set_xxx API 进行更多设置,例如:协议模式、国家代码、带宽等。请参阅 `{IDF_TARGET_NAME} Wi-Fi 配置`_。
|
||||
|
||||
如果 menuconfig 已使能 Wi-Fi NVS flash,则不论当前阶段还是后续的 Wi-Fi 配置信息都将被存储至该 flash 中。那么,当主板上电/重新启动时,就不需从头开始配置 Wi-Fi 驱动程序。您只需调用函数 esp_wifi_get_xxx API 获取之前存储的配置信息。当然,如果不想使用之前的配置,您依然可以重新配置 Wi-Fi 驱动程序。
|
||||
一般情况下,我们会在建立 Wi-Fi 连接之前配置 Wi-Fi 驱动程序,但这 **并非** 强制要求。也就是说,只要 Wi-Fi 驱动程序已成功初始化,你可以在任意阶段进行配置。但是,如果你的 Wi-Fi 在建立连接后不需要更改配置,则应先在此阶段完成配置。因为调用配置 API(例如 :cpp:func:`esp_wifi_set_protocol()`)将会导致 Wi-Fi 连接断开,为操作带来不便。
|
||||
|
||||
如果 menuconfig 已使能 Wi-Fi NVS flash,则不论当前阶段还是后续的 Wi-Fi 配置信息都将被存储至该 flash 中。那么,当主板上电/重新启动时,就不需从头开始配置 Wi-Fi 驱动程序,只需调用函数 esp_wifi_get_xxx API 获取之前存储的配置信息。当然,如果不想使用之前的配置,你也可以重新配置 Wi-Fi 驱动程序。
|
||||
|
||||
3. Wi-Fi 启动阶段
|
||||
++++++++++++++++++++++++++++++++
|
||||
|
||||
- s3.1:调用函数 :cpp:func:`esp_wifi_start()` 启动 Wi-Fi 驱动程序。
|
||||
- s3.2:Wi-Fi 驱动程序将事件 `WIFI_EVENT_STA_START`_ 发布到事件任务中,然后,事件任务将执行一些正常操作并调用应用程序的事件回调函数。
|
||||
- s3.3:应用程序的事件回调函数将事件 `WIFI_EVENT_STA_START`_ 中继到应用程序任务中。推荐您此时调用函数 :cpp:func:`esp_wifi_connect()` 进行 Wi-Fi 连接。当然,您也可以等待在 `WIFI_EVENT_STA_START`_ 事件发生后的其它阶段再调用此函数。
|
||||
- s3.3:应用程序的事件回调函数将事件 `WIFI_EVENT_STA_START`_ 中继到应用程序任务中。此时,推荐调用函数 :cpp:func:`esp_wifi_connect()` 进行 Wi-Fi 连接。当然,你也可以等待在 `WIFI_EVENT_STA_START`_ 事件发生后的其它阶段再调用此函数。
|
||||
|
||||
4. Wi-Fi 连接阶段
|
||||
+++++++++++++++++++++++++++++++++
|
||||
|
||||
- s4.1:调用函数 :cpp:func:`esp_wifi_connect()` 后,Wi-Fi 驱动程序将启动内部扫描/连接过程。
|
||||
|
||||
- s4.2:如果内部扫描/连接过程成功,将产生 `WIFI_EVENT_STA_CONNECTED`_ 事件。然后,事件任务将启动 DHCP 客户端服务,最终触发 DHCP 程序。
|
||||
|
||||
- s4.3:在此情况下,应用程序的事件回调函数会将 `WIFI_EVENT_STA_CONNECTED`_ 事件中继到应用程序任务中。通常,应用程序不需进行操作,而您可以执行任何动作,例如:打印日志等。
|
||||
- s4.3:在此情况下,应用程序的事件回调函数会将 `WIFI_EVENT_STA_CONNECTED`_ 事件中继到应用程序任务中。通常,应用程序不需进行操作,而你可以执行任何动作,例如:打印日志等。
|
||||
|
||||
步骤 s4.2 中 Wi-Fi 连接可能会由于某些原因而失败,例如:密码错误、未找到 AP 等。这种情况下,将引发 `WIFI_EVENT_STA_DISCONNECTED`_ 事件并提示连接错误原因。有关如何处理中断 Wi-Fi 连接的事件,请参阅下文阶段 6 的描述。
|
||||
|
||||
|
@ -399,8 +426,9 @@ Wi-Fi 驱动程序初始化成功后,可以进入到配置阶段。该场景
|
|||
|
||||
6. Wi-Fi 断开阶段
|
||||
+++++++++++++++++++++++++++++++++
|
||||
|
||||
- s6.1:当 Wi-Fi 因为某些原因(例如:AP 掉电、RSSI 较弱等)连接中断时,将产生 `WIFI_EVENT_STA_DISCONNECTED`_ 事件。此事件也可能在上文阶段 3 中发生。在这里,事件任务将通知 LwIP 任务清除/移除所有 UDP/TCP 连接。然后,所有应用程序套接字都将处于错误状态。也就是说,`WIFI_EVENT_STA_DISCONNECTED`_ 事件发生时,任何套接字都无法正常工作。
|
||||
- s6.2:上述情况下,应用程序的事件回调函数会将 `WIFI_EVENT_STA_DISCONNECTED`_ 事件中继到应用程序任务中。推荐您调用函数 :cpp:func:`esp_wifi_connect()` 重新连接 Wi-Fi,关闭所有套接字,并在必要时重新创建套接字。请参阅 `WIFI_EVENT_STA_DISCONNECTED`_。
|
||||
- s6.2:上述情况下,应用程序的事件回调函数会将 `WIFI_EVENT_STA_DISCONNECTED`_ 事件中继到应用程序任务中。推荐调用函数 :cpp:func:`esp_wifi_connect()` 重新连接 Wi-Fi,关闭所有套接字,并在必要时重新创建套接字。请参阅 `WIFI_EVENT_STA_DISCONNECTED`_。
|
||||
|
||||
7. Wi-Fi IP 更改阶段
|
||||
++++++++++++++++++++++++++++++++++
|
||||
|
@ -419,6 +447,7 @@ Wi-Fi 驱动程序初始化成功后,可以进入到配置阶段。该场景
|
|||
|
||||
{IDF_TARGET_NAME} Wi-Fi AP 一般情况
|
||||
---------------------------------------------
|
||||
|
||||
下图为 AP 模式下的宏观场景,其中包含不同阶段的具体描述:
|
||||
|
||||
.. seqdiag::
|
||||
|
@ -600,6 +629,7 @@ Wi-Fi 驱动程序内部扫描阶段
|
|||
|
||||
在所有信道上扫描全部 AP(后端)
|
||||
++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
场景:
|
||||
|
||||
.. seqdiag::
|
||||
|
@ -636,6 +666,7 @@ Wi-Fi 驱动程序内部扫描阶段
|
|||
|
||||
在所有信道中扫描特定 AP
|
||||
+++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
场景:
|
||||
|
||||
.. seqdiag::
|
||||
|
@ -672,7 +703,7 @@ Wi-Fi 驱动程序内部扫描阶段
|
|||
|
||||
如果有多个匹配目标 AP 信息的 AP,例如:碰巧扫描到两个 SSID 为 "ap" 的 AP。如果本次扫描类型为 ``WIFI_FAST_SCAN``,则仅可找到第一个扫描到的 "ap";如果本次扫描类型为 ``WIFI_ALL_CHANNEL_SCAN``,则两个 "ap“ 都将被找到,且 station 将根据配置规则连接至其需要连接的 "ap",请参阅 `station 基本配置`_。
|
||||
|
||||
您可以在任意信道中扫描某个特定的 AP,或扫描该信道中的所有 AP。这两种扫描过程也较为相似。
|
||||
你可以在任意信道中扫描某个特定的 AP,或扫描该信道中的所有 AP。这两种扫描过程也较为相似。
|
||||
|
||||
在 Wi-Fi 连接模式下扫描
|
||||
+++++++++++++++++++++++++
|
||||
|
@ -686,6 +717,7 @@ Wi-Fi 驱动程序内部扫描阶段
|
|||
|
||||
并行扫描
|
||||
+++++++++++++
|
||||
|
||||
有时,可能会有两个应用程序任务同时调用函数 :cpp:func:`esp_wifi_scan_start()`,或者某个应用程序任务在获取扫描完成事件之前再次调用了函数 :cpp:func:`esp_wifi_scan_start()`。这两种情况都有可能会发生。**但是,Wi-Fi 驱动程序并不足以支持多个并行的扫描。因此,应避免上述并行扫描**。随着 {IDF_TARGET_NAME} 的 Wi-Fi 功能不断提升,未来的版本中可能会增加并行扫描支持。
|
||||
|
||||
连接 Wi-Fi 时扫描
|
||||
|
@ -700,7 +732,7 @@ Wi-Fi 驱动程序内部扫描阶段
|
|||
- 而另一个应用程序任务(如,控制任务)调用了函数 :cpp:func:`esp_wifi_scan_start()` 进行扫描。这种情况下,每一次扫描都会立即失败,因为 station 一直处于正在连接状态。
|
||||
- 扫描失败后,应用程序将等待一段时间后进行重新扫描。
|
||||
|
||||
上述场景中的扫描永远不会成功,因为 Wi-Fi 一直处于正在连接过程中。因此,如果您的应用程序也可能发生相似的场景,那么就需要为其配置一个更佳的重新连接策略。例如:
|
||||
上述场景中的扫描永远不会成功,因为 Wi-Fi 一直处于正在连接过程中。因此,如果你的应用程序也可能发生相似的场景,那么就需要为其配置一个更佳的重新连接策略。例如:
|
||||
|
||||
- 应用程序可以定义一个连续重新连接次数的最大值,当重新连接的次数达到这个最大值时,立刻停止重新连接。
|
||||
- 应用程序可以在首轮连续重新连接 N 次后立即进行重新连接,然后延时一段时间后再进行下一次重新连接。
|
||||
|
@ -1233,7 +1265,7 @@ Wi-Fi 模式
|
|||
* - 模式
|
||||
- 描述
|
||||
* - ``WIFI_MODE_NULL``
|
||||
- NULL 模式:此模式下,内部数据结构不分配给 station 和 AP,同时,station 和 AP 接口不会为发送/接收 Wi-Fi 数据进行初始化。通常,此模式用于 Sniffer,或者您不想通过调用函数 :cpp:func:`esp_wifi_deinit()` 卸载整个 Wi-Fi 驱动程序来同时停止 station 和 AP。
|
||||
- NULL 模式:此模式下,内部数据结构不分配给 station 和 AP,同时,station 和 AP 接口不会为发送/接收 Wi-Fi 数据进行初始化。通常,此模式用于 Sniffer,或者你不想通过调用函数 :cpp:func:`esp_wifi_deinit()` 卸载整个 Wi-Fi 驱动程序来同时停止 station 和 AP。
|
||||
* - ``WIFI_MODE_STA``
|
||||
- station 模式:此模式下,:cpp:func:`esp_wifi_start()` 将初始化内部 station 数据,同时 station 接口准备发送/接收 Wi-Fi 数据。调用函数 :cpp:func:`esp_wifi_connect()` 后,station 将连接到目标 AP。
|
||||
* - ``WIFI_MODE_AP``
|
||||
|
@ -1264,7 +1296,7 @@ API :cpp:func:`esp_wifi_set_config()` 可用于配置 station。配置的参数
|
|||
* - bssid
|
||||
- 只有当 bssid_set 为 1 时有效。见字段 “bssid_set”。
|
||||
* - channel
|
||||
- 该字段为 0 时,station 扫描信道 1 ~ N 寻找目标 AP;否则,station 首先扫描值与 “channel” 字段相同的信道,再扫描其他信道。比如,当该字段设置为 3 时,扫描顺序为 3,1,2,...,N 。如果您不知道目标 AP 在哪个信道,请将该字段设置为 0。
|
||||
- 该字段为 0 时,station 扫描信道 1 ~ N 寻找目标 AP;否则,station 首先扫描值与 “channel” 字段相同的信道,再扫描其他信道。比如,当该字段设置为 3 时,扫描顺序为 3,1,2,...,N 。如果你不知道目标 AP 在哪个信道,请将该字段设置为 0。
|
||||
* - sort_method
|
||||
- 该字段仅用于 ``WIFI_ALL_CHANNEL_SCAN`` 模式。
|
||||
|
||||
|
@ -1428,7 +1460,7 @@ Wi-Fi 协议模式
|
|||
LR 兼容性
|
||||
*************************
|
||||
|
||||
由于 LR 是乐鑫的独有 Wi-Fi 模式,只有 ESP32 芯片系列设备(除了ESP32-C2)才能传输和接收 LR 数据。也就是说,如果连接的设备不支持 LR, ESP32 芯片系列设备(除了ESP32-C2)则不会以 LR 数据速率传输数据。可通过配置适当的 Wi-Fi 模式使您的应用程序实现这一功能。如果协商的模式支持 LR, ESP32 芯片系列设备(除了ESP32-C2)可能会以 LR 速率传输数据,否则, ESP32 芯片系列设备(除了ESP32-C2)将以传统 Wi-Fi 数据速率传输所有数据。
|
||||
由于 LR 是乐鑫的独有 Wi-Fi 模式,只有 ESP32 芯片系列设备(ESP32-C2 除外)才能传输和接收 LR 数据。也就是说,如果连接的设备不支持 LR,ESP32 芯片系列设备(ESP32-C2 除外)则不会以 LR 数据速率传输数据。可通过配置适当的 Wi-Fi 模式使你的应用程序实现这一功能。如果协商的模式支持 LR,ESP32 芯片系列设备(ESP32-C2 除外)可能会以 LR 速率传输数据,否则,ESP32 芯片系列设备(ESP32-C2 除外)将以传统 Wi-Fi 数据速率传输所有数据。
|
||||
|
||||
下表是 Wi-Fi 模式协商:
|
||||
|
||||
|
@ -1482,7 +1514,7 @@ Wi-Fi 协议模式
|
|||
|
||||
- 对于已使能 LR 的 {IDF_TARGET_NAME} AP,由于以 LR 模式发送 beacon,因此与传统的 802.11 模式不兼容。
|
||||
- 对于已使能 LR 且并非仅 LR 模式的 {IDF_TARGET_NAME} station,与传统 802.11 模式兼容。
|
||||
- 如果 station 和 AP 都是 ESP32 芯片系列设备(除了ESP32-C2),并且两者都使能 LR 模式,则协商的模式支持 LR。
|
||||
- 如果 station 和 AP 都是 ESP32 芯片系列设备(ESP32-C2 除外),并且两者都使能 LR 模式,则协商的模式支持 LR。
|
||||
|
||||
如果协商的 Wi-Fi 模式同时支持传统的 802.11 模式和 LR 模式,则 Wi-Fi 驱动程序会在不同的 Wi-Fi 模式下自动选择最佳数据速率,应用程序无需任何操作。
|
||||
|
||||
|
@ -1688,9 +1720,9 @@ WPA2-Enterprise 是企业无线网络的安全认证机制。在连接到接入
|
|||
- {IDF_TARGET_NAME} 在 station 模式下为 FTM 发起方。
|
||||
- {IDF_TARGET_NAME} 在 AP 模式下为 FTM 响应方。
|
||||
|
||||
使用 RTT 的距离测量并不准确,RF 干扰、多径传播、天线方向和缺乏校准等因素会增加这些不准确度。为了获得更好的结果,建议在两个 ESP32 芯片系列设备(除了ESP32-C2)之间执行 FTM,这两个设备可分别设置为 station 和 AP 模式。
|
||||
使用 RTT 的距离测量并不准确,RF 干扰、多径传播、天线方向和缺乏校准等因素会增加这些不准确度。为了获得更好的结果,建议在两个 ESP32 芯片系列设备(ESP32-C2 除外)之间执行 FTM,这两个设备可分别设置为 station 和 AP 模式。
|
||||
|
||||
请参考 IDF 示例 :idf_file:`examples/wifi/ftm/README.md` 了解设置和执行 FTM 的详细步骤。
|
||||
请参考 ESP-IDF 示例 :idf_file:`examples/wifi/ftm/README.md`,了解设置和执行 FTM 的详细步骤。
|
||||
|
||||
{IDF_TARGET_NAME} Wi-Fi 节能模式
|
||||
-----------------------------------------
|
||||
|
@ -1737,7 +1769,7 @@ AP 睡眠
|
|||
非连接模块功耗管理
|
||||
+++++++++++++++++++++++++++++++
|
||||
|
||||
非连接模块指的是一些不依赖于 Wi-Fi 连接的 Wi-Fi 模块,例如 ESP-NOW, DPP, FTM。这些模块从 :cpp:func:`esp_wifi_start` 开始工作至 :cpp:func:`esp_wifi_stop` 结束。
|
||||
非连接模块指的是一些不依赖于 Wi-Fi 连接的 Wi-Fi 模块,例如 ESP-NOW,DPP,FTM。这些模块从 :cpp:func:`esp_wifi_start` 开始工作至 :cpp:func:`esp_wifi_stop` 结束。
|
||||
|
||||
目前,ESP-NOW 以 station 模式工作时,既支持在连接状态下休眠,也支持在非连接状态下休眠。
|
||||
|
||||
|
@ -1790,9 +1822,9 @@ AP 睡眠
|
|||
|
||||
当 `Interval` 参数被配置为 `ESP_WIFI_CONNECTIONLESS_INTERVAL_DEFAULT_MODE` ,且有非零的 `Window` 参数时,非连接模块功耗管理将会按默认模式运行。
|
||||
|
||||
在没有与非 Wi-Fi 协议共存时,RF, PHY and BB 将会在默认模式下被一直打开。
|
||||
在没有与非 Wi-Fi 协议共存时,RF、PHY 和 BB 将会在默认模式下被一直打开。
|
||||
|
||||
在与非 Wi-Fi 协议共存时,RF, PHY and BB 资源被共存模块分时划给 Wi-Fi 非连接模块和非 Wi-Fi 协议使用。在默认模式下, Wi-Fi 非连接模块被允许周期性使用 RF, PHY and BB ,并且具有稳定性能。
|
||||
在与非 Wi-Fi 协议共存时,RF、PHY 和 BB 资源被共存模块分时划给 Wi-Fi 非连接模块和非 Wi-Fi 协议使用。在默认模式下,Wi-Fi 非连接模块被允许周期性使用 RF、PHY 和 BB ,并且具有稳定性能。
|
||||
|
||||
推荐在与非 Wi-Fi 协议共存时将非连接模块功耗管理配置为默认模式。
|
||||
|
||||
|
@ -2123,7 +2155,7 @@ Wi-Fi 多根天线
|
|||
|__________|
|
||||
|
||||
|
||||
{IDF_TARGET_NAME} 通过外部天线开关,最多支持 16 根天线。天线开关最多可由四个地址管脚控制 - antenna_select[0:3]。向 antenna_select[0:3] 输入不同的值,以选择不同的天线。例如,输入值 '0b1011' 表示选中天线 11 。antenna_select[3:0] 的默认值为 "0b0000",表示默认选择了天线 0。
|
||||
{IDF_TARGET_NAME} 通过外部天线开关,最多支持 16 根天线。天线开关最多可由四个地址管脚控制 - antenna_select[0:3]。向 antenna_select[0:3] 输入不同的值,以选择不同的天线。例如,输入值 '0b1011' 表示选中天线 11。antenna_select[3:0] 的默认值为 "0b0000",表示默认选择了天线 0。
|
||||
|
||||
四个高电平有效 antenna_select 管脚有多达四个 GPIO 连接。{IDF_TARGET_NAME} 可以通过控制 GPIO[0:3] 选择天线。API :cpp:func:`esp_wifi_set_ant_gpio()` 用于配置 antenna_selects 连接哪些 GPIO。如果 GPIO[x] 连接到 antenna_select[x],gpio_config->gpio_cfg[x].gpio_select 应设置为 1,且要提供 gpio_config->gpio_cfg[x].gpio_num 的值。
|
||||
|
||||
|
@ -2178,7 +2210,7 @@ Wi-Fi 多根天线配置
|
|||
Wi-Fi 信道状态信息
|
||||
------------------------------------
|
||||
|
||||
信道状态信息 (CSI) 是指 Wi-Fi 连接的信道信息。{IDF_TARGET_NAME} 中,CSI由子载波的信道频率响应组成,CSI从发送端接收数据包时开始估计。每个子载波信道频率响由两个字节的有符号字符记录,第一个字节是虚部,第二个字节是实部。根据接收数据包的类型,信道频率响应最多有三个字段。分别是 LLTF、HT-LTF 和 STBC-HT-LTF。对于在不同状态的信道上接收到的不同类型的数据包,CSI 的子载波索引和总字节数如下表所示。
|
||||
信道状态信息 (CSI) 是指 Wi-Fi 连接的信道信息。{IDF_TARGET_NAME} 中,CSI 由子载波的信道频率响应组成,CSI 从发送端接收数据包时开始估计。每个子载波信道频率响由两个字节的有符号字符记录,第一个字节是虚部,第二个字节是实部。根据接收数据包的类型,信道频率响应最多有三个字段。分别是 LLTF、HT-LTF 和 STBC-HT-LTF。对于在不同状态的信道上接收到的不同类型的数据包,CSI 的子载波索引和总字节数如下表所示。
|
||||
|
||||
+------------+-------------+-----------------------------------------+-----------------------------------------------------+--------------------------------------------------------+
|
||||
| 信道 | 辅助信道 | | 下 | 上 |
|
||||
|
@ -2232,7 +2264,7 @@ Wi-Fi 多根天线配置
|
|||
|
||||
要使用 Wi-Fi CSI,需要执行以下步骤。
|
||||
|
||||
- 在菜单配置中选择 Wi-Fi CSI。方法是“菜单配置 - > 组件配置 -- > Wi-Fi -- > Wi-Fi CSI(信道状态信息)”。
|
||||
- 在菜单配置中选择 Wi-Fi CSI。方法是 ``Menuconfig`` > ``Components config`` > ``Wi-Fi`` > ``Wi-Fi CSI (Channel State Information)``。
|
||||
- 调用 API :cpp:func:`esp_wifi_set_csi_rx_cb()` 设置 CSI 接收回调函数。
|
||||
- 调用 API :cpp:func:`esp_wifi_set_csi_config()` 配置 CSI。
|
||||
- 调用 API :cpp:func:`esp_wifi_set_csi()` 使能 CSI。
|
||||
|
@ -2263,7 +2295,7 @@ Wi-Fi QoS
|
|||
|
||||
{IDF_TARGET_NAME} 支持 WFA Wi-Fi QoS 认证所要求的所有必备功能。
|
||||
|
||||
Wi-Fi 协议中定义了四个 AC (访问类别),每个 AC 有各自的优先级访问 Wi-Fi 信道。此外,还定义了映射规则以映射其他协议的 QoS 优先级,例如 802.11D 或 TCP/IP 到 Wi-Fi AC。
|
||||
Wi-Fi 协议中定义了四个 AC(访问类别),每个 AC 有各自的优先级访问 Wi-Fi 信道。此外,还定义了映射规则以映射其他协议的 QoS 优先级,例如 802.11D 或 TCP/IP 到 Wi-Fi AC。
|
||||
|
||||
下表描述 {IDF_TARGET_NAME} 中 IP 优先级如何映射到 Wi-Fi AC,还指明此 AC 是否支持 AMPDU。该表按优先级降序排列,即 AC_VO 拥有最高优先级。
|
||||
|
||||
|
@ -2373,7 +2405,7 @@ Wi-Fi 使用的堆内存峰值是 Wi-Fi 驱动程序 **理论上消耗的最大
|
|||
|
||||
{IDF_TARGET_NAME} Wi-Fi 的性能受许多参数的影响,各参数之间存在相互制约。如果配置地合理,不仅可以提高性能,还可以增加应用程序的可用内存,提高稳定性。
|
||||
|
||||
在本节中,我们将简单介绍 Wi-Fi/LWIP 协议栈的工作模式,并说明各个参数的作用。我们将推荐几种配置等级,您可以根据使用场景选择合适的等级。
|
||||
在本节中,我们将简单介绍 Wi-Fi/LWIP 协议栈的工作模式,并说明各个参数的作用。我们将推荐几种配置等级,你可以根据使用场景选择合适的等级。
|
||||
|
||||
协议栈工作模式
|
||||
++++++++++++++++++++++++++++++++++
|
||||
|
@ -2392,7 +2424,7 @@ Wi-Fi 使用的堆内存峰值是 Wi-Fi 驱动程序 **理论上消耗的最大
|
|||
参数
|
||||
++++++++++++++
|
||||
|
||||
适当增加上述缓冲区的大小或数量,可以提高 Wi-Fi 性能,但同时,会减少应用程序的可用内存。下面我们将介绍您需要配置的参数:
|
||||
适当增加上述缓冲区的大小或数量,可以提高 Wi-Fi 性能,但同时,会减少应用程序的可用内存。下面我们将介绍你需要配置的参数:
|
||||
|
||||
**接收数据方向:**
|
||||
|
||||
|
@ -2483,7 +2515,7 @@ Wi-Fi 使用的堆内存峰值是 Wi-Fi 驱动程序 **理论上消耗的最大
|
|||
|
||||
{IDF_TARGET_NAME} 的内存由协议栈和应用程序共享。
|
||||
|
||||
在这里,我们给出了几种配置等级。在大多数情况下,您应根据应用程序所占用内存的大小,选择合适的等级进行参数配置。
|
||||
在这里,我们给出了几种配置等级。在大多数情况下,应根据应用程序所占用内存的大小,选择合适的等级进行参数配置。
|
||||
|
||||
下表中未提及的参数应设置为默认值。
|
||||
|
||||
|
@ -3018,7 +3050,7 @@ Wi-Fi 使用的堆内存峰值是 Wi-Fi 驱动程序 **理论上消耗的最大
|
|||
{IDF_TARGET_NAME} 的极端性能等级,用于测试极端性能。
|
||||
|
||||
- **高性能等级**
|
||||
{IDF_TARGET_NAME} 的高性能配置等级,适用于应用程序占用内存较少且有高性能要求的场景。在该等级中,您可以根据使用场景选择使用接收数据优先等级或发送数据优先等级。
|
||||
{IDF_TARGET_NAME} 的高性能配置等级,适用于应用程序占用内存较少且有高性能要求的场景。在该等级中,可以根据使用场景选择使用接收数据优先等级或发送数据优先等级。
|
||||
|
||||
- **默认等级**
|
||||
{IDF_TARGET_NAME} 的默认配置等级、兼顾可用内存和性能。
|
||||
|
@ -3499,7 +3531,7 @@ Wi-Fi Menuconfig
|
|||
Wi-Fi 缓冲区配置
|
||||
+++++++++++++++++++++++
|
||||
|
||||
如果您要修改默认的缓冲区数量或类型,最好也了解缓冲区在数据路径中是如何分配或释放的。下图显示了发送数据方向的这一过程。
|
||||
如果要修改默认的缓冲区数量或类型,最好也了解缓冲区在数据路径中如何分配或释放。下图显示了发送数据方向的过程。
|
||||
|
||||
.. blockdiag::
|
||||
:caption: TX Buffer Allocation
|
||||
|
@ -3645,12 +3677,12 @@ Wi-Fi AMPDU
|
|||
如何使用低功耗模式
|
||||
-----------------------
|
||||
|
||||
对于物联网应用场景,终端的待机性能表现十分重要,本文档旨在介绍{IDF_TARGET_NAME}低功耗的基本原理,同时介绍{IDF_TARGET_NAME}支持的低功耗模式,需注意本文档主要针对 station mode。文档还会具体给出每种模式的配置步骤、推荐配置和功耗表现,以帮助用户根据实际需求快速配置适合的低功耗模式。
|
||||
对于物联网应用场景,终端的待机性能表现十分重要,本文档旨在介绍 {IDF_TARGET_NAME} 低功耗的基本原理,同时介绍 {IDF_TARGET_NAME} 支持的低功耗模式,需注意本文档主要针对 station mode。文档还会具体给出每种模式的配置步骤、推荐配置和功耗表现,以帮助用户根据实际需求快速配置适合的低功耗模式。
|
||||
|
||||
纯系统下低功耗模式介绍
|
||||
++++++++++++++++++++++++++++++++++
|
||||
|
||||
低功耗模式不仅涉及到系统相关问题,还涉及到芯片具体的工作场景,如处在Wi-Fi工作场景就会与处在蓝牙工作场景时产生不同。为此本节将首先介绍纯系统角度,即不涉及具体场景的低功耗模式,主要有 DFS、light sleep、deep sleep。纯系统下的低功耗模式主要思想就是在休眠时关闭或门控一些功能模块来降低功耗。
|
||||
低功耗模式不仅涉及到系统相关问题,还涉及到芯片具体的工作场景,如处在 Wi-Fi 工作场景就会与处在蓝牙工作场景时产生不同。为此本节将首先介绍纯系统角度,即不涉及具体场景的低功耗模式,主要有 DFS、Light-sleep、Deep-sleep。纯系统下的低功耗模式主要思想就是在休眠时关闭或门控一些功能模块来降低功耗。
|
||||
|
||||
DFS
|
||||
++++++++++++++++++++++++++++++++++
|
||||
|
@ -3750,7 +3782,7 @@ DFS 有如下可配置选项:
|
|||
该参数表示最大 CPU 频率 (MHz),即 CPU 最高性能工作时候的频率,一般设置为芯片参数的最大值。
|
||||
|
||||
- min_freq_mhz
|
||||
该参数表示最小 CPU 频率 (MHz),即系统处在空闲状态时CPU的工作频率。该字段可设置为晶振 (XTAL) 频率值,或者 XTAL 频率值除以整数。
|
||||
该参数表示最小 CPU 频率 (MHz),即系统处在空闲状态时 CPU 的工作频率。该字段可设置为晶振 (XTAL) 频率值,或者 XTAL 频率值除以整数。
|
||||
|
||||
- light_sleep_enable
|
||||
使能该选项,系统将在空闲状态下自动进入 Light-sleep 状态,即 Auto Light-sleep 使能,上文已经具体介绍。
|
||||
|
@ -3814,7 +3846,7 @@ Auto Light-sleep 有如下可配置选项:
|
|||
如果使能该选项,一些 RTOS IDLE 功能将被移至 IRAM,减少代码运行时间,降低系统功耗,IRAM 使用量将增加 260B。
|
||||
|
||||
- RTC slow clock source
|
||||
该参数表表示RTC慢速时钟源。系统休眠时计时器模块的时钟被门控,此时使用 RTC Timer 进行计时,唤醒后使用 RTC Timer 的计数值对系统时间进行补偿。
|
||||
该参数表表示 RTC 慢速时钟源。系统休眠时计时器模块的时钟被门控,此时使用 RTC Timer 进行计时,唤醒后使用 RTC Timer 的计数值对系统时间进行补偿。
|
||||
|
||||
.. list-table::
|
||||
:header-rows: 1
|
||||
|
@ -3838,16 +3870,16 @@ Auto Light-sleep 有如下可配置选项:
|
|||
.. only:: esp32c3 or esp32s3
|
||||
|
||||
- Power down MAC and baseband
|
||||
如果使能该选项,系统将在休眠时关闭WiFi和蓝牙的MAC和baseband来降低功耗,休眠电流约降低 100 uA, 但是为保存上下文信息,将额外消耗5.3K DRAM。
|
||||
如果使能该选项,系统将在休眠时关闭 Wi-Fi 和蓝牙的 MAC 和 baseband 来降低功耗,休眠电流约降低 100 uA, 但是为保存上下文信息,将额外消耗 5.3 K DRAM。
|
||||
|
||||
- Power down CPU
|
||||
如果使能该选项,系统将在休眠时将关闭CPU来降低功耗,对于 esp32c3,休眠电流减小 100 uA 左右,对于 esp32s3,休眠电流减小 650 uA 左右。但是为保存上下文信息,对于 esp32c3,将消耗 1.6 KB 的 DRAM 空间,对于 esp32s3,将消耗 8.58 KB 的 DRAM 空间。
|
||||
如果使能该选项,系统将在休眠时将关闭 CPU 来降低功耗,对于 esp32c3,休眠电流减小 100 uA 左右,对于 esp32s3,休眠电流减小 650 uA 左右。但是为保存上下文信息,对于 esp32c3,将消耗 1.6 KB 的 DRAM 空间,对于 esp32s3,将消耗 8.58 KB 的 DRAM 空间。
|
||||
|
||||
- Power down I/D-cache tag memory
|
||||
如果使能该选项,系统将在休眠时关闭 I/D cache tag memory 来降低功耗, 但是为保存 tag memory 信息,将额外消耗最大约 9 KB DRAM,同时因为 tag memory 信息特殊性,如需打开该选项,建议多进行测试。
|
||||
如果使能该选项,系统将在休眠时关闭 I/D cache tag memory 来降低功耗, 但是为保存 tag memory 信息,将额外消耗最大约 9 KB DRAM,同时因为 tag memory 信息特殊性,如需打开该选项,建议多进行测试。
|
||||
|
||||
- Power down flash in light-sleep
|
||||
如果使能该选项,系统将在 light-sleep 休眠时关闭 flash,降低系统功耗,该选项的前提是系统没有使用 PSRAM 。
|
||||
- Power down flash in Light-sleep
|
||||
如果使能该选项,系统将在 Light-sleep 休眠时关闭 flash,降低系统功耗,该选项的前提是系统没有使用 PSRAM。
|
||||
|
||||
唤醒源:
|
||||
|
||||
|
@ -4069,14 +4101,14 @@ Deep-sleep 有如下可配置选项:
|
|||
|
||||
用户可以通过下列配置选项,让一些特定模块在休眠时保持开启状态:
|
||||
|
||||
- Power up External 40MHz XTAL
|
||||
在一些特殊应用中,部分模块对休眠时的时钟精度及稳定度有很高要求(例如 BT)。这种情况下,可以考虑在休眠过程中打开 External 40MHz XTAL。
|
||||
- Power up External 40 MHz XTAL
|
||||
在一些特殊应用中,部分模块对休眠时的时钟精度及稳定度有很高要求(例如 BT)。这种情况下,可以考虑在休眠过程中打开 External 40 MHz XTAL。
|
||||
打开和关闭代码如下::
|
||||
|
||||
ESP_ERROR_CHECK(esp_sleep_pd_config(ESP_PD_DOMAIN_XTAL, ESP_PD_OPTION_ON));
|
||||
ESP_ERROR_CHECK(esp_sleep_pd_config(ESP_PD_DOMAIN_XTAL, ESP_PD_OPTION_OFF));
|
||||
|
||||
- Power up Internal 8MHz OSC
|
||||
- Power up Internal 8 MHz OSC
|
||||
在一些特殊应用中,部分模块(例如 LEDC)将 Internal 8 MHz OSC 作为时钟源,并且希望在 Light-sleep 休眠过程中也可以正常使用。这种情况下,可以考虑在休眠过程中打开 Internal 8 MHz OSC。
|
||||
打开和关闭代码如下::
|
||||
|
||||
|
@ -4087,14 +4119,14 @@ Deep-sleep 有如下可配置选项:
|
|||
Wi-Fi 场景下低功耗模式介绍
|
||||
++++++++++++++++++++++++++++++++++
|
||||
|
||||
上文介绍了纯系统方向下的低功耗模式,但在实际应用中还需结合具体应用场景。本节将结合纯系统下的功耗模式来介绍在WiFi场景下的低功耗模式。因为WiFi场景的复杂性,本节会会首先介绍WiFi省电的基本原理,然后再介绍具体的低功耗模式,同时本节主要针对station模式。
|
||||
上文介绍了纯系统方向下的低功耗模式,但在实际应用中还需结合具体应用场景。本节将结合纯系统下的功耗模式来介绍在 Wi-Fi 场景下的低功耗模式。因为 Wi-Fi 场景的复杂性,本节会会首先介绍 Wi-Fi 省电的基本原理,然后再介绍具体的低功耗模式,同时本节主要针对 station 模式。
|
||||
|
||||
Wi-Fi 省电的基本原理
|
||||
+++++++++++++++++++++
|
||||
|
||||
首先,在 station 的工作过程中,为在接收发送过程中避免冲突,需要长时间监听信道,能耗较大的 RF 模块会一直处于工作中,浪费电量。为此,Wi-Fi 协议引入省电模式。
|
||||
|
||||
省电模式的基本原理是通过减少不必要的监听时间来降低耗能。AP 会缓存进入省电模式的 station 的包,同时周期发送包含 TIM 信息的 Beacon 帧,TIM 会指示 AP 缓存的单播包。TIM 中,DTIM 较为特殊,其会缓存广播包,并以n 个(由 AP 决定)TIM 为周期发送。对 station 来说,TIM 非必听,而 DTIM 为必听。因此,station 可以选择只在每一个 DTIM 帧前醒来打开 Wi-Fi 相关模块(RF 模块),而不必时刻处于监听状态,这样就能有效降低功耗。
|
||||
省电模式的基本原理是通过减少不必要的监听时间来降低耗能。AP 会缓存进入省电模式的 station 的包,同时周期发送包含 TIM 信息的 Beacon 帧,TIM 会指示 AP 缓存的单播包。TIM 中,DTIM 较为特殊,其会缓存广播包,并以 n 个(由 AP 决定)TIM 为周期发送。对 station 来说,TIM 非必听,而 DTIM 为必听。因此,station 可以选择只在每一个 DTIM 帧前醒来打开 Wi-Fi 相关模块(RF 模块),而不必时刻处于监听状态,这样就能有效降低功耗。
|
||||
|
||||
.. figure:: ../../_static/Low-power-DTIM4.png
|
||||
:align: center
|
||||
|
@ -4113,38 +4145,38 @@ Wi-Fi 省电的基本原理
|
|||
|
||||
芯片工作时间组成图
|
||||
|
||||
此外,在 station 没有处于 Wi-Fi 接收或发送状态时,影响功耗的因素变成了芯片的其他模块。不同的功耗模式会配置不同的时钟源,或者动态调整一些模块的工作频率如 CPU ,同时还会关闭不同数量的功能模块,这将有效降低芯片的功耗。其实也就是纯系统相关的模式,用户可根据需求自己选择合适的配置。
|
||||
此外,在 station 没有处于 Wi-Fi 接收或发送状态时,影响功耗的因素变成了芯片的其他模块。不同的功耗模式会配置不同的时钟源,或者动态调整一些模块的工作频率如 CPU,同时还会关闭不同数量的功能模块,这将有效降低芯片的功耗。其实也就是纯系统相关的模式,用户可根据需求自己选择合适的配置。
|
||||
|
||||
如果以时间为横轴,电流大小为纵轴建立坐标轴,那么处在低功耗模式下芯片的理想工作电流图可以简化成下图:
|
||||
|
||||
.. figure:: ../../_static/Low-power-WiFi-base-current.png
|
||||
:align: center
|
||||
|
||||
理想情况下WiFi场景低功耗模式电流图
|
||||
理想情况下 Wi-Fi 场景低功耗模式电流图
|
||||
|
||||
其中 station 要进行 Wi-Fi 通信时,Wi-Fi 相关模块(PHY)开启,电流会显著上升,在工作完成前,电流会一直维持在一个较高的水平。工作完成后,芯片会关闭 Wi-Fi 相关模块,这时电流又会降低到一个较低水平。
|
||||
其中 station 要进行 Wi-Fi 通信时,Wi-Fi 相关模块 (PHY) 开启,电流会显著上升,在工作完成前,电流会一直维持在一个较高的水平。工作完成后,芯片会关闭 Wi-Fi 相关模块,这时电流又会降低到一个较低水平。
|
||||
|
||||
可以看出影响功耗表现的主要有三点:interval、period 和 base current。
|
||||
|
||||
- Interval 是 station Wi-Fi 相关模块工作的间隔,既可以由低功耗模式自定义,也可根据 Wi-Fi 协议省电机制(3.1第一点介绍),由 DTIM 周期决定。可以看出在同等情下,interval 越大,功耗表现会更好,但是响应会更慢,影响通信的及时性。
|
||||
- Interval 是 station Wi-Fi 相关模块工作的间隔,既可以由低功耗模式自定义,也可根据 Wi-Fi 协议省电机制(3.1 第一点介绍),由 DTIM 周期决定。可以看出在同等情下,interval 越大,功耗表现会更好,但是响应会更慢,影响通信的及时性。
|
||||
|
||||
- Period 可以看作每次 station Wi-Fi 工作的时间,这段时间的长度也会影响功耗的表现。period 不是一个固定的时长(3.1第二点介绍),在保证WiFi通信正常的情况下,period 持续时间越短,功耗表现越好。但是减少 period 时间,必然会影响通信的可靠性。
|
||||
- Period 可以看作每次 station Wi-Fi 工作的时间,这段时间的长度也会影响功耗的表现。period 不是一个固定的时长(3.1 第二点介绍),在保证 Wi-Fi 通信正常的情况下,period 持续时间越短,功耗表现越好。但是减少 period 时间,必然会影响通信的可靠性。
|
||||
|
||||
- Base current 是 Wi-Fi相关模块不工作时芯片的电流,影响其大小的因素很多,不同的功耗模式下休眠策略不同。所以,在满足功能的情况下,优化配置降低该电流大小可以提高功耗表现,但同时关闭其余模块会影响相关功能和芯片的唤醒时间。
|
||||
- Base current 是 Wi-Fi 相关模块不工作时芯片的电流,影响其大小的因素很多,不同的功耗模式下休眠策略不同。所以,在满足功能的情况下,优化配置降低该电流大小可以提高功耗表现,但同时关闭其余模块会影响相关功能和芯片的唤醒时间。
|
||||
|
||||
知道了影响功耗的三点因素之后,要想降低功耗应从这三点入手,接下来介绍两种低功耗模式,Modem sleep、Auto Light-sleep 。两种模式主要区别就是对三点因素的优化不同。
|
||||
知道了影响功耗的三点因素之后,要想降低功耗应从这三点入手,接下来介绍两种低功耗模式,Modem sleep、Auto Light-sleep。两种模式主要区别就是对三点因素的优化不同。
|
||||
|
||||
|
||||
Modem sleep
|
||||
Modem-sleep Mode
|
||||
++++++++++++++++++
|
||||
|
||||
Modem sleep 模式主要工作原理基于 DTIM 机制,周期性的醒来处理 Wi-Fi 相关工作,又在周期间隔之间进入休眠,关闭 PHY(RF模块)来降低功耗。同时通过 DTIM 机制,station 可以与 AP 保持 Wi-Fi 连接,数据传输。
|
||||
Modem-sleep 模式主要工作原理基于 DTIM 机制,周期性的醒来处理 Wi-Fi 相关工作,又在周期间隔之间进入休眠,关闭 PHY(RF 模块)来降低功耗。同时通过 DTIM 机制,station 可以与 AP 保持 Wi-Fi 连接,数据传输。
|
||||
|
||||
Modem sleep 模式会在 WiFi task 结束后自动进入休眠无需调用 API,休眠时仅会关闭 Wi-Fi 相关模块(PHY),其余模块均处在正常上电状态。
|
||||
Modem-sleep 模式会在 Wi-Fi task 结束后自动进入休眠无需调用 API,休眠时仅会关闭 Wi-Fi 相关模块 (PHY),其余模块均处在正常上电状态。
|
||||
|
||||
Modem sleep 模式默认会根据 DTIM 周期或 listen interval(下文介绍)醒来,相当于系统自动设置了一个 Wi-Fi 唤醒源,因此用户无需再配置唤醒源,同时系统主动发包时也可以唤醒。
|
||||
Modem-sleep 模式默认会根据 DTIM 周期或 listen interval(下文介绍)醒来,相当于系统自动设置了一个 Wi-Fi 唤醒源,因此用户无需再配置唤醒源,同时系统主动发包时也可以唤醒。
|
||||
|
||||
Modem sleep 是一个开关型的模式,调用 API 开启后一直自动运行,其工作流程十分简单,具体如下图。
|
||||
Modem-sleep 是一个开关型的模式,调用 API 开启后一直自动运行,其工作流程十分简单,具体如下图。
|
||||
|
||||
.. figure:: ../../_static/Low-power-modem-process.png
|
||||
:align: center
|
||||
|
@ -4152,21 +4184,21 @@ Modem sleep 是一个开关型的模式,调用 API 开启后一直自动运行
|
|||
Modem sleep 工作流程图
|
||||
|
||||
|
||||
根据上文的基本电流图,结合 Modem sleep的 工作原理,以 Min Modem(下文介绍)为例可得理想情况下电流变化图。
|
||||
根据上文的基本电流图,结合 Modem-sleep 的 工作原理,以 Min Modem(下文介绍)为例可得理想情况下电流变化图。
|
||||
|
||||
.. figure:: ../../_static/Low-power-modem-current.png
|
||||
:align: center
|
||||
|
||||
Min Modem sleep理想电流图
|
||||
Min Modem-sleep 理想电流图
|
||||
|
||||
Modem-sleep 一般用于 CPU 持续处于工作状态并需要保持 Wi-Fi 连接的应用场景,例如,使用 {IDF_TARGET_NAME} 本地语音唤醒功能,CPU 需要持续采集和处理音频数据。
|
||||
|
||||
DFS+Modem sleep
|
||||
++++++++++++++++++
|
||||
|
||||
Modem sleep 模式休眠状态中CPU仍处在工作状态,而DFS机制主要作用于 CPU 和 APB 工作频率来降低功耗,因此 DFS+Modem sleep 可以进一步优化功耗表现,又因为 Wi-Fi task 会申请 ESP_PM_CPU_FREQ_MAX 电源锁来保证 Wi-Fi 任务快速运行,所以 DFS+Modem sleep 产生调频只会发生在 base current 阶段,即 Wi-Fi task 结束后。
|
||||
Modem sleep 模式休眠状态中 CPU 仍处在工作状态,而 DFS 机制主要作用于 CPU 和 APB 工作频率来降低功耗,因此 DFS + Modem sleep 可以进一步优化功耗表现,又因为 Wi-Fi task 会申请 ESP_PM_CPU_FREQ_MAX 电源锁来保证 Wi-Fi 任务快速运行,所以 DFS + Modem sleep 产生调频只会发生在 base current 阶段,即 Wi-Fi task 结束后。
|
||||
|
||||
在 Wi-Fi 场景下,为了介绍的简化,让用户抓住主要的变化,DFS可以进行一定的状态简化。具体来说,虽然 DFS 主要根据 CPU 和 APB 两把锁的最高需求来调频,但是 Wi-Fi 场景都需要 CPU 的频率最大化来工作,同时 Wi-Fi task 结束后,也可以理想化的认为,没有其余的工作要完成,这样就可以简单认为经过一段时间会释放两把锁进入空闲状态(IDLE状态),也同时忽略这段时间锁的变化导致的电流变化,简化状态。
|
||||
在 Wi-Fi 场景下,为了介绍的简化,让用户抓住主要的变化,DFS 可以进行一定的状态简化。具体来说,虽然 DFS 主要根据 CPU 和 APB 两把锁的最高需求来调频,但是 Wi-Fi 场景都需要 CPU 的频率最大化来工作,同时 Wi-Fi task 结束后,也可以理想化的认为,没有其余的工作要完成,这样就可以简单认为经过一段时间会释放两把锁进入空闲状态(IDLE 状态),也同时忽略这段时间锁的变化导致的电流变化,简化状态。
|
||||
|
||||
在 Wi-Fi 场景下,DFS 最终简化为如下流程:
|
||||
|
||||
|
@ -4190,7 +4222,7 @@ Auto Light-sleep+Wi-Fi 场景
|
|||
|
||||
Auto Light-sleep 模式在 Wi-Fi 场景下是 ESP-IDF 电源管理机制、DTIM 机制和 light-sleep 的结合。开启电源管理是其前置条件,auto 体现在系统进入 IDLE 状态超过设定值后自动进入 light-sleep。同时 auto light sleep 模式同样遵循 DTIM 机制,会自动苏醒,可以与 AP 保持 Wi-Fi 连接。
|
||||
|
||||
Auto Light-sleep 模式在 Wi-Fi 场景下休眠机制与纯系统下一样,仍然依赖于电源管理机制,进入休眠的条件为系统处于IDLE状态的时间超过设定时间,并且系统会提前判断空闲时间是否满足条件,若满足直接休眠。该过程为自动进行。休眠时会自动关闭 RF、 8 MHz 振荡器、40 MHz 高速晶振、PLL ,门控数字内核时钟,暂停 CPU 工作。
|
||||
Auto Light-sleep 模式在 Wi-Fi 场景下休眠机制与纯系统下一样,仍然依赖于电源管理机制,进入休眠的条件为系统处于 IDLE 状态的时间超过设定时间,并且系统会提前判断空闲时间是否满足条件,若满足直接休眠。该过程为自动进行。休眠时会自动关闭 RF、8 MHz 振荡器、40 MHz 高速晶振、PLL,门控数字内核时钟,暂停 CPU 工作。
|
||||
|
||||
Auto Light-sleep 模式在 Wi-Fi 场景下遵循 DTIM 机制,自动在 DTIM 帧到来前苏醒,相当于系统自动设置了一个 Wi-Fi 唤醒源,因此用户无需再配置唤醒源。同时系统主动发包时也可以唤醒。
|
||||
|
||||
|
@ -4208,28 +4240,28 @@ Auto Light-sleep 模式在 Wi-Fi 场景下经常与 modem sleep 同时开启,
|
|||
|
||||
modem+auto light-sleep 模式理想电流图
|
||||
|
||||
Auto Light-sleep 模式在 Wi-Fi 场景下可用于需要保持WiFi连接,可以实时响应 AP 发来数据的场景。并且在未接收到命令时,CPU 可以处于空闲状态。比如 Wi-Fi 开关的应用,大部分时间 CPU 都是空闲的,直到收到控制命令,CPU 才需要进行 GPIO 的操作。
|
||||
Auto Light-sleep 模式在 Wi-Fi 场景下可用于需要保持 Wi-Fi 连接,可以实时响应 AP 发来数据的场景。并且在未接收到命令时,CPU 可以处于空闲状态。比如 Wi-Fi 开关的应用,大部分时间 CPU 都是空闲的,直到收到控制命令,CPU 才需要进行 GPIO 的操作。
|
||||
|
||||
|
||||
Deep-sleep+Wi-Fi 场景
|
||||
+++++++++++++++++++++++++++++++++
|
||||
|
||||
Deep-sleep 模式在 Wi-Fi 场景下与纯系统下基本相同,详情可以参考(`Deep-sleep`_)这里不再介绍。
|
||||
Deep-sleep 模式在 Wi-Fi 场景下与纯系统下基本相同,详情可以参考 `Deep-sleep`_ 这里不再介绍。
|
||||
|
||||
|
||||
如何配置 Wi-Fi 场景下低功耗模式
|
||||
+++++++++++++++++++++++++++++++++++++
|
||||
|
||||
介绍完WiFi场景下低功耗模式后,本节将介绍公共配置选项、每种模式独有的配置选项,以及相应低功耗模式API的使用说明,同时给出相应模式推荐的配置(包含纯系统下的低功耗推荐配置)以及该配置的具体表现。
|
||||
介绍完 Wi-Fi 场景下低功耗模式后,本节将介绍公共配置选项、每种模式独有的配置选项,以及相应低功耗模式 API 的使用说明,同时给出相应模式推荐的配置(包含纯系统下的低功耗推荐配置)以及该配置的具体表现。
|
||||
|
||||
公共配置选项:
|
||||
|
||||
- 功耗类:
|
||||
|
||||
- Max Wi-Fi TX power (dBm)
|
||||
该参数表示最大 TX 功率,降低该参数会减小发包功耗,但会影响WiFi性能,默认设置最大20。
|
||||
该参数表示最大 TX 功率,降低该参数会减小发包功耗,但会影响 Wi-Fi 性能,默认设置最大 20。
|
||||
|
||||
- IRAM类:
|
||||
- IRAM 类:
|
||||
|
||||
- Wi-Fi IRAM speed optimization
|
||||
如果使能该选项,一些 Wi-Fi 功能将被移至 IRAM,减少代码运行时间,降低系统功耗,IRAM 使用量将增加,默认开启。
|
||||
|
@ -4243,16 +4275,16 @@ Deep-sleep 模式在 Wi-Fi 场景下与纯系统下基本相同,详情可以
|
|||
- Wi-Fi 协议类:
|
||||
|
||||
- Minimum active time
|
||||
该参数表示 Station 接收完一次数据后需要等待时间。当终端与 AP 进行通信时,AP 发送到终端的数据经常是突发形式的,为确保后续的突发数据能够正常接收到,需要等待一段时间。默认50。
|
||||
该参数表示 Station 接收完一次数据后需要等待时间。当终端与 AP 进行通信时,AP 发送到终端的数据经常是突发形式的,为确保后续的突发数据能够正常接收到,需要等待一段时间。默认 50。
|
||||
|
||||
- Maximum keep alive time
|
||||
该参数表示周期性的发送 sleep null data 来通告 AP 维持连接的时间。在 DTIM 机制下,若 AP长 时间没有某个 station 的包,可能会断开连接,因此需要 station 需要周期发送 sleep null data 维持连接。默认10。
|
||||
该参数表示周期性的发送 sleep null data 来通告 AP 维持连接的时间。在 DTIM 机制下,若 AP 长时间没有某个 station 的包,可能会断开连接,因此需要 station 需要周期发送 sleep null data 维持连接。默认 10。
|
||||
|
||||
- Send gratuitous ARP periodically
|
||||
如果使能该选项,Station 将周期性的发送 gratuitous ARP 请求更新 AP ARP 缓存表。如无该需求,可以关闭。
|
||||
|
||||
- Wi-Fi sleep optimize when beacon lost
|
||||
如果使能该选项, Station 在检测到已经错过或者丢失 beacon 时, 会立即关闭 RF 进入低功耗状态。
|
||||
如果使能该选项,Station 在检测到已经错过或者丢失 beacon 时,会立即关闭 RF 进入低功耗状态。
|
||||
|
||||
Modem sleep 配置方法如下:
|
||||
|
||||
|
@ -4262,7 +4294,7 @@ Modem sleep 配置方法如下:
|
|||
该参数表示 station 按照 DTIM 周期工作,在每个 DTIM 前醒来接收 Beacon,这样不会漏掉广播信息,但是 DTIM 周期由 AP 决定,如果 DTIM 周期较短,省电效果会降低。
|
||||
|
||||
- Max Modem
|
||||
该参数表示 station 会自定义一个 listen interval,并以 listen interval 为周期醒来接受 Beacon。这样在 listen interval 较大时会省电,但是容易漏听 DTIM ,错过广播数据。
|
||||
该参数表示 station 会自定义一个 listen interval,并以 listen interval 为周期醒来接受 Beacon。这样在 listen interval 较大时会省电,但是容易漏听 DTIM,错过广播数据。
|
||||
|
||||
|
||||
- 配置方法:
|
||||
|
@ -4292,7 +4324,7 @@ Modem sleep 配置方法如下:
|
|||
|
||||
配置推荐:
|
||||
|
||||
这里给出的配置推荐是 Min Modem sleep+DFS 开启的配置
|
||||
这里给出的配置推荐是 Min Modem sleep + DFS 开启的配置
|
||||
|
||||
.. list-table::
|
||||
:header-rows: 1
|
||||
|
@ -4323,43 +4355,43 @@ Modem sleep 配置方法如下:
|
|||
|
||||
.. include:: sleep-current/{IDF_TARGET_PATH_NAME}_modem_sleep.inc
|
||||
|
||||
Auto Light-sleep+Wi-Fi 场景配置:
|
||||
Auto Light-sleep + Wi-Fi 场景配置:
|
||||
|
||||
Auto Light-sleep 在 Wi-Fi 场景下的配置比纯系统下少了唤醒源的配置要求,其余几乎与纯系统下配置一致,因此可配置选项、配置步骤、推荐配置的详细介绍可以参考上文( `Light-sleep`_ )。同时Wi-Fi相关配置保持默认。
|
||||
Auto Light-sleep 在 Wi-Fi 场景下的配置比纯系统下少了唤醒源的配置要求,其余几乎与纯系统下配置一致,因此可配置选项、配置步骤、推荐配置的详细介绍可以参考上文 `Light-sleep`_。同时 Wi-Fi 相关配置保持默认。
|
||||
|
||||
配置表现:
|
||||
|
||||
该配置表现为 Auto Light-sleep 纯系统推荐配置+默认的 Wi-Fi 相关配置在 Wi-Fi 场景的表现。
|
||||
该配置表现为 Auto Light-sleep 纯系统推荐配置 + 默认的 Wi-Fi 相关配置在 Wi-Fi 场景的表现。
|
||||
|
||||
.. include:: sleep-current/{IDF_TARGET_PATH_NAME}_light_sleep.inc
|
||||
|
||||
Deep-sleep+Wi-Fi 场景配置:
|
||||
Deep-sleep + Wi-Fi 场景配置:
|
||||
|
||||
Deep-sleep 模式在 Wi-Fi 场景下的配置与纯系统下配置基本一致,因此可配置选项、配置步骤、推荐配置的详细介绍可以参考上文( `Deep-sleep`_ )。同时 Wi-Fi 相关配置保持默认。
|
||||
Deep-sleep 模式在 Wi-Fi 场景下的配置与纯系统下配置基本一致,因此可配置选项、配置步骤、推荐配置的详细介绍可以参考上文 `Deep-sleep`_。同时 Wi-Fi 相关配置保持默认。
|
||||
|
||||
配置表现:
|
||||
|
||||
该配置表现为 Deep-sleep 纯系统推荐配置+默认的 Wi-Fi 相关配置在 Wi-Fi 场景的表现。
|
||||
该配置表现为 Deep-sleep 纯系统推荐配置 + 默认的 Wi-Fi 相关配置在 Wi-Fi 场景的表现。
|
||||
|
||||
.. only:: esp32
|
||||
|
||||
平均电流约5.0 μA
|
||||
平均电流约 5.0 μA
|
||||
|
||||
.. only:: esp32s2
|
||||
|
||||
平均电流约5.0 μA
|
||||
平均电流约 5.0 μA
|
||||
|
||||
.. only:: esp32s3
|
||||
|
||||
平均电流约6.9 μA
|
||||
平均电流约 6.9 μA
|
||||
|
||||
.. only:: esp32c3
|
||||
|
||||
平均电流约4.8 μA
|
||||
平均电流约 4.8 μA
|
||||
|
||||
.. only:: esp32c2
|
||||
|
||||
平均电流约4.9 μA
|
||||
平均电流约 4.9 μA
|
||||
|
||||
|
||||
Wi-Fi 场景如何选择低功耗模式
|
||||
|
@ -4370,6 +4402,7 @@ Wi-Fi 场景如何选择低功耗模式
|
|||
.. include:: sleep-current/{IDF_TARGET_PATH_NAME}_summary.inc
|
||||
|
||||
.. note::
|
||||
|
||||
上表中所有电流均为平均电流
|
||||
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
****************************
|
||||
乐鑫 Wireshark 使用指南
|
||||
****************************
|
||||
|
||||
:link_to_translation:`en:[English]`
|
||||
|
||||
===========
|
||||
|
@ -82,11 +83,11 @@ Wireshark 是目前全世界最广泛的网络封包分析软件之一。
|
|||
|
||||
* **Wireshark 不是入侵检测系统**
|
||||
|
||||
如果您的网络中存在任何可疑活动,Wireshark 并不会主动发出警告。不过,当您希望对这些可疑活动一探究竟时,Wireshark 可以发挥作用。
|
||||
如果你的网络中存在任何可疑活动,Wireshark 并不会主动发出警告。不过,当你希望对这些可疑活动一探究竟时,Wireshark 可以发挥作用。
|
||||
|
||||
* **Wireshark 不会处理网络事务,它仅仅是“测量”(监视)网络**
|
||||
|
||||
Wireshark 不会发送网络包或做其它交互性的事情(名称解析除外,但您也可以禁止解析)。
|
||||
Wireshark 不会发送网络包或做其它交互性的事情(名称解析除外,但你也可以禁止解析)。
|
||||
|
||||
|
||||
========================
|
||||
|
@ -95,7 +96,7 @@ Wireshark 是目前全世界最广泛的网络封包分析软件之一。
|
|||
|
||||
官网链接:https://www.wireshark.org/download.html
|
||||
|
||||
Wireshark 支持多种操作系统,请在下载安装文件时,注意选择与您所用操作系统匹配的安装文件。
|
||||
Wireshark 支持多种操作系统,请在下载安装文件时,注意选择与你所用操作系统匹配的安装文件。
|
||||
|
||||
|
||||
==============
|
||||
|
@ -181,7 +182,7 @@ Linux 下,可编写一个 Shell 脚本,运行该文件即可启动 Wireshark
|
|||
|
||||
过滤条件工具栏
|
||||
|
||||
点击在此区域输入或修改显示的过滤字符,在输入过程中会进行语法检查。如果您输入的格式不正确,或者未输入完成,则背景显示为红色。直到您输入合法的表达式,背景会变为绿色。你可以点击下拉列表选择您先前键入的过滤字符。列表会一直保留,即使您重新启动程序。
|
||||
点击在此区域输入或修改显示的过滤字符,在输入过程中会进行语法检查。如果输入的格式不正确,或者未输入完成,则背景显示为红色。直到输入合法的表达式,背景会变为绿色。你可以点击下拉列表选择先前键入的过滤字符。列表会一直保留,即使重新启动程序。
|
||||
|
||||
例如:下图所示,直接输入 2 个 MAC 作为过滤条件,点击 *Apply* (即图中的蓝色箭头),则表示只抓取 2 个此 MAC 地址之间的交互的包。
|
||||
|
||||
|
@ -242,5 +243,5 @@ Linux 下,可以通过依次点击 "File" -> "Export Packet Dissections" -> "A
|
|||
|
||||
上图中,需要注意的是,选择 *All packets*、*Displayed* 以及 *All expanded* 三项。
|
||||
|
||||
Wireshark 捕捉的包可以保存为其原生格式文件(libpcap),也可以保存为其他格式(如.txt 文件)供其他工具进行读取分析。
|
||||
Wireshark 捕捉的包可以保存为其原生格式文件 (libpcap),也可以保存为其他格式(如.txt 文件)供其他工具进行读取分析。
|
||||
|
||||
|
|
Ładowanie…
Reference in New Issue