Merge branch 'doc/update_CN_translation_for_API_guides_and_Contribute' into 'master'

update CN translation for api-guides and contribute

See merge request espressif/esp-idf!12662
This commit is contained in:
Krzysztof Budzynski 2021-03-23 08:05:28 +00:00
commit 15c3a42dcf
6 changed files with 389 additions and 203 deletions

View File

@ -40,6 +40,7 @@ Configuration Options and Dependencies
Using of this feature depends on two components:
1. **Host side:** Application tracing is done over JTAG, so it needs OpenOCD to be set up and running on host machine. For instructions on how to set it up, please see :doc:`JTAG Debugging <../api-guides/jtag-debugging/index>` for details.
2. **Target side:** Application tracing functionality can be enabled in menuconfig. *Component config > Application Level Tracing* menu allows selecting destination for the trace data (HW interface for transport). Choosing any of the destinations automatically enables ``CONFIG_APPTRACE_ENABLE`` option.
.. note::
@ -49,6 +50,7 @@ Using of this feature depends on two components:
There are two additional menuconfig options not mentioned above:
1. *Threshold for flushing last trace data to host on panic* (:ref:`CONFIG_APPTRACE_POSTMORTEM_FLUSH_THRESH`). This option is necessary due to the nature of working over JTAG. In that mode trace data are exposed to the host in 16 KB blocks. In post-mortem mode when one block is filled it is exposed to the host and the previous one becomes unavailable. In other words trace data are overwritten in 16 KB granularity. On panic the latest data from the current input block are exposed to host and host can read them for post-analysis. System panic may occur when very small amount of data are not exposed to the host yet. In this case the previous 16 KB of collected data will be lost and host will see the latest, but very small piece of the trace. It can be insufficient to diagnose the problem. This menuconfig option allows avoiding such situations. It controls the threshold for flushing data in case of panic. For example user can decide that it needs not less then 512 bytes of the recent trace data, so if there is less then 512 bytes of pending data at the moment of panic they will not be flushed and will not overwrite previous 16 KB. The option is only meaningful in post-mortem mode and when working over JTAG.
2. *Timeout for flushing last trace data to host on panic* (:ref:`CONFIG_APPTRACE_ONPANIC_HOST_FLUSH_TMO`). The option is only meaningful in streaming mode and controls the maximum time tracing module will wait for the host to read the last data in case of panic.
@ -425,7 +427,7 @@ Good instruction on how to install, configure and visualize data in Impulse from
Configure Impulse for Dual Core Traces
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
After installing Impulse and ensuring that it can successfully load trace files for each core in separate tabs user can add special Multi Adapter port and load both files into one view. To do this user needs to do the following in Eclipse:
After installing Impulse and ensuring that it can successfully load trace files for each core in separate tabs users can add special Multi Adapter port and load both files into one view. To do this, users need to do the following in Eclipse:
1. Open 'Signal Ports' view. Go to Windows->Show View->Other menu. Find 'Signal Ports' view in Impulse folder and double-click on it.
2. In 'Signal Ports' view right-click on 'Ports' and select 'Add ...'->New Multi Adapter Port
@ -455,11 +457,13 @@ Source code coverage is data indicating the count and frequency of every program
Generally, using Gcov to compile and run programs on the Host will undergo these steps:
1. Compile the source code using GCC with the ``--coverage`` option enabled. This will cause the compiler to generate a ``.gcno`` notes files during compilation. The notes files contain information to reconstruct execution path block graphs and map each block to source code line numbers. Each source file compiled with the ``--coverage`` option should have their own ``.gcno`` file of the same name (e.g., a ``main.c`` will generate a ``main.gcno`` when compiled).
2. Execute the program. During execution, the program should generate ``.gcda`` data files. These data files contain the counts of the number of times an execution path was taken. The program will generate a ``.gcda`` file for each source file compiled with the ``--coverage`` option (e.g., ``main.c`` will generate a ``main.gcda``.
3. Gcov or Gcovr can be used 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
"""""""""""""""""""""""""
"""""""""""""""""""""""""""
Using Gcov in ESP-IDF is complicated by the fact that the program is running remotely from the Host (i.e., on the target). The code coverage data (i.e., the ``.gcda`` files) is initially stored on the target itself. OpenOCD is then used to dump the code coverage data from the target to the host via JTAG during runtime. Using Gcov in ESP-IDF can be split into the following steps.
@ -510,7 +514,7 @@ The dumping of code coverage data can be done multiple times throughout an appli
ESP-IDF supports two methods of dumping code coverage data form the target to the host:
* Instant Run-Time Dump
* Instant Run-Time Dumpgit
* Hard-coded Dump
Instant Run-Time Dump

View File

@ -5,8 +5,7 @@ Linker Script Generation
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.
.. only:: SOC_ULP_SUPPORTED
@ -16,9 +15,7 @@ writable data in RAM, etc. However, it is sometimes necessary to change these de
For example, it may be necessary to place critical code in RAM for performance reasons or to place code in RTC memory for use in a wake stub.
With the linker script generation mechanism, it is possible to specify these placements at the component level within ESP-IDF. The component presents
information on how it would like to place its symbols, objects or the entire archive. During build the information presented by the components are collected,
parsed and processed; and the placement rules generated is used to link the app.
With the linker script generation mechanism, it is possible to specify these placements at the component level within ESP-IDF. The component presents information on how it would like to place its symbols, objects or the entire archive. During build, the information presented by the components are collected, parsed and processed; and the placement rules generated is used to link the app.
Quick Start
------------
@ -38,26 +35,20 @@ For this guide, suppose we have the following::
- my_src3.c
- my_linker_fragment_file.lf
- a component named ``my_component`` that is archived as library ``libmy_component.a`` during build
- three source files archived under the library, ``my_src1.c``, ``my_src2.c`` and ``my_src3.c`` which are compiled as ``my_src1.o``, ``my_src2.o`` and ``my_src3.o``, respectively
- under ``my_src1.o``, the function ``my_function1`` is defined; under ``my_src2.o``, the function ``my_function2`` is defined
- there exist bool-type config ``PERFORMANCE_MODE`` (y/n) and int type config ``PERFORMANCE_LEVEL`` (with range 0-3) in ``my_component``'s Kconfig
- there is bool-type config ``PERFORMANCE_MODE`` (y/n) and int type config ``PERFORMANCE_LEVEL`` (with range 0-3) in ``my_component``'s Kconfig
Creating and Specifying a Linker Fragment File
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Before anything else, a linker fragment file needs to be created. A linker fragment file
is simply a text file with a ``.lf`` extension upon which the desired placements will be written.
After creating the file, it is then necessary to present it to the build system. The instructions for the build systems
supported by ESP-IDF are as follows:
Before anything else, a linker fragment file needs to be created. A linker fragment file is simply a text file with a ``.lf`` extension upon which the desired placements will be written. After creating the file, it is then necessary to present it to the build system. The instructions for the build systems supported by ESP-IDF are as follows:
Make
""""
In the component's ``component.mk`` file, set the variable ``COMPONENT_ADD_LDFRAGMENTS`` to the path of the created linker
fragment file. The path can either be an absolute path or a relative path from the component directory.
In the component's ``component.mk`` file, set the variable ``COMPONENT_ADD_LDFRAGMENTS`` to the path of the created linker fragment file. The path can either be an absolute path or a relative path from the component directory.
.. code-block:: make
@ -66,9 +57,7 @@ fragment file. The path can either be an absolute path or a relative path from t
CMake
"""""
In the component's ``CMakeLists.txt`` file, specify argument ``LDFRAGMENTS`` in the ``idf_component_register`` call.
The value of ``LDFRAGMENTS`` can either be an absolute path or a relative path from the component directory to the
created linker fragment file.
In the component's ``CMakeLists.txt`` file, specify argument ``LDFRAGMENTS`` in the ``idf_component_register`` call. The value of ``LDFRAGMENTS`` can either be an absolute path or a relative path from the component directory to the created linker fragment file.
.. code-block:: cmake
@ -93,8 +82,7 @@ It is possible to specify placements at the following levels of granularity:
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.
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.
In the the linker fragment file, we can write:
.. code-block:: none
@ -105,14 +93,12 @@ In the 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
""""""""""""""""
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:
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:
.. code-block:: none
@ -122,15 +108,13 @@ only ``my_function2`` needs to execute after the chip comes out of deep sleep. T
my_src1:my_function1 (noflash)
my_src2:my_function2 (rtc)
The default placements are used for the rest of the functions in ``my_src1.o`` and ``my_src2.o`` and the entire ``object3.o``. Something similar
can be achieved for placing data by writing the variable name instead of the function name, like so::
The default placements are used for the rest of the functions in ``my_src1.o`` and ``my_src2.o`` and the entire ``object3.o``. Something similar can be achieved for placing data by writing the variable name instead of the function name, like so::
my_src1:my_variable (noflash)
.. warning::
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>`.
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
"""""""""""""""""""""""
@ -156,8 +140,7 @@ Similarly, this places the entire component in RTC memory:
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:
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:
.. code-block:: none
@ -169,10 +152,7 @@ This could be written as:
else:
* (default)
For a more complex config-dependent placement, suppose the following requirements: when ``CONFIG_PERFORMANCE_LEVEL == 1``, only ``object1.o`` is put in RAM;
when ``CONFIG_PERFORMANCE_LEVEL == 2``, ``object1.o`` and ``object2.o``; and when ``CONFIG_PERFORMANCE_LEVEL == 3`` all object files under the archive
are to be put into RAM. When these three are false however, put entire library in RTC memory. This scenario is a bit contrived, but,
it can be written as:
For a more complex config-dependent placement, suppose the following requirements: when ``CONFIG_PERFORMANCE_LEVEL == 1``, only ``object1.o`` is put in RAM; when ``CONFIG_PERFORMANCE_LEVEL == 2``, ``object1.o`` and ``object2.o``; and when ``CONFIG_PERFORMANCE_LEVEL == 3`` all object files under the archive are to be put into RAM. When these three are false however, put entire library in RTC memory. This scenario is a bit contrived, but, it can be written as:
.. code-block:: none
@ -211,30 +191,21 @@ Nesting condition-checking is also possible. The following is equivalent to the
.. _ldgen-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.
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.
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.
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::
@ -245,10 +216,7 @@ that the linker script passed to the linker is dynamically generated from: (1) t
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
"""""""
@ -277,14 +245,11 @@ The three fragment types share a common grammar:
The only valid characters for fragment names and keys are alphanumeric characters and underscore.
.. _ldgen-condition-checking :
**Condition Checking**
Condition checking enable the linker script generation to be configuration-aware. Depending on whether expressions involving configuration values
are true or not, a particular set of values for a key can be used. The evaluation uses ``eval_string`` from kconfiglib package
and adheres to its required syntax and limitations. Supported operators are as follows:
Condition checking enable the linker script generation to be configuration-aware. Depending on whether expressions involving configuration values are true or not, a particular set of values for a key can be used. The evaluation uses ``eval_string`` from kconfiglib package and adheres to its required syntax and limitations. Supported operators are as follows:
- comparison
- LessThan ``<``
@ -300,8 +265,7 @@ and adheres to its required syntax and limitations. Supported operators are as f
- grouping
- Parenthesis ``()``
Condition checking behaves as you would expect an ``if...elseif/elif...else`` block in other languages. Condition-checking is possible
for both key values and entire fragments. The two sample fragments below are equivalent:
Condition checking behaves as you would expect an ``if...elseif/elif...else`` block in other languages. Condition-checking is possible for both key values and entire fragments. The two sample fragments below are equivalent:
.. code-block:: none
@ -337,8 +301,7 @@ for both key values and entire fragments. The two sample fragments below are equ
**Comments**
Comment in linker fragment files begin with ``#``. Like in other languages, comment are used to provide helpful descriptions and documentation
and are ignored during processing.
Comment in linker fragment files begin with ``#``. Like in other languages, comment are used to provide helpful descriptions and documentation and are ignored during processing.
Compatibility with ESP-IDF v3.x Linker Script Fragment Files
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
@ -349,10 +312,7 @@ ESP-IDF v4.0 brings some changes to the linker script fragment file grammar:
- move to ``if...elif...else`` structure for conditionals, with the ability to nest checks and place entire fragments themselves inside conditionals
- mapping fragments now requires a name like other fragment types
Linker script generator should be able to parse ESP-IDF v3.x linker fragment files that are indented properly (as demonstrated by
the ESP-IDF v3.x version of this document). Backward compatibility with the previous mapping fragment grammar (optional
name and the old grammar for conditionals) has also been retained but with a deprecation warning. Users should switch to the newer grammar discussed
in this document as support for the old grammar is planned to be removed in the future.
Linker script generator should be able to parse ESP-IDF v3.x linker fragment files that are indented properly (as demonstrated by the ESP-IDF v3.x version of this document). Backward compatibility with the previous mapping fragment grammar (optional name and the old grammar for conditionals) has also been retained but with a deprecation warning. Users should switch to the newer grammar discussed in this document as support for the old grammar is planned to be removed in the future.
Note that linker fragment files using the new ESP-IDF v4.0 grammar is not supported on ESP-IDF v3.x, however.
@ -363,8 +323,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.
@ -421,21 +380,15 @@ Example:
The ``default`` scheme
There exists a special scheme with the name ``default``. This scheme is special because catch-all placement rules are generated from
its entries. This means that, if one of its entries is ``text -> flash_text``, the placement rule
There exists a special scheme with the name ``default``. This scheme is special because catch-all placement rules are generated from its entries. This means that, if one of its entries is ``text -> flash_text``, the placement rule will be generated for the target ``flash_text``.
.. code-block:: none
*(.literal .literal.* .text .text.*)
will be generated for the target ``flash_text``.
These catch-all rules then effectively serve as fallback rules for those whose mappings were not specified.
The ``default scheme`` is defined in :component_file:`{IDF_TARGET_PATH_NAME}/ld/{IDF_TARGET_PATH_NAME}_fragments.lf`. The ``noflash`` and ``rtc`` scheme fragments which are
built-in schemes referenced in the quick start guide are also defined in this file.
The ``default scheme`` is defined in :component_file:`{IDF_TARGET_PATH_NAME}/ld/{IDF_TARGET_PATH_NAME}_fragments.lf`. The ``noflash`` and ``rtc`` scheme fragments which are built-in schemes referenced in the quick start guide are also defined in this file.
.. _ldgen-mapping-fragment :
@ -495,42 +448,33 @@ Example:
entries:
* (noflash)
Aside from the entity and scheme, flags can also be specified in an entry. The following
flags are supported (note: <> = argument name, [] = optional):
Aside from the entity and scheme, flags can also be specified in an entry. The following flags are supported (note: <> = argument name, [] = optional):
1. ALIGN(<alignment>[, pre, post])
Align the placement by the amount specified in ``alignment``. Generates
.. code-block::none
. = ALIGN(<alignment>)
before and/or after (depending whether ``pre``, ``post`` or both are specified)
the input section description generated from the mapping
fragment entry. If neither 'pre' or 'post' is specified, the alignment command is
generated before the input section description. Order sensitive.
before and/or after (depending whether ``pre``, ``post`` or both are specified) the input section description generated from the mapping fragment entry. If neither 'pre' or 'post' is specified, the alignment command is generated before the input section description. Order sensitive.
2. SORT([<sort_by_first>, <sort_by_second>])
Emits ``SORT_BY_NAME``, ``SORT_BY_ALIGNMENT``,
``SORT_BY_INIT_PRIORITY`` or ``SORT`` in the input section description.
Possible values for ``sort_by_first`` and ``sort_by_second`` are:
``name``, ``alignment``, ``init_priority``.
If both ``sort_by_first`` and ``sort_by_second`` are not specified, the input
sections are sorted by name. If both are specified, then the nested
sorting follows the same rules discussed in
https://sourceware.org/binutils/docs/ld/Input-Section-Wildcards.html.
Emits ``SORT_BY_NAME``, ``SORT_BY_ALIGNMENT``, ``SORT_BY_INIT_PRIORITY`` or ``SORT`` in the input section description.
Possible values for ``sort_by_first`` and ``sort_by_second`` are: ``name``, ``alignment``, ``init_priority``.
If both ``sort_by_first`` and ``sort_by_second`` are not specified, the input sections are sorted by name. If both are specified, then the nested sorting follows the same rules discussed in https://sourceware.org/binutils/docs/ld/Input-Section-Wildcards.html.
3. KEEP()
Prevent the linker from discarding the placement by
surrounding the input section description with KEEP command.
See https://sourceware.org/binutils/docs/ld/Input-Section-Keep.html
for more details.
Prevent the linker from discarding the placement by surrounding the input section description with KEEP command. See https://sourceware.org/binutils/docs/ld/Input-Section-Keep.html for more details.
4.SURROUND(<name>)
Generate symbols before and after the placement. The generated symbols
follow the naming ``_<name>_start`` and ``_<name>_end``. For example, if
``name`` == sym1,
Generate symbols before and after the placement. The generated symbols follow the naming ``_<name>_start`` and ``_<name>_end``. For example, if ``name`` == sym1,
.. code-block::none
@ -540,8 +484,7 @@ flags are supported (note: <> = argument name, [] = optional):
These symbols can then be referenced from C/C++ code. Order sensitive.
When adding flags, the specific ``section -> target`` in the scheme needs to be specified.
For multiple ``section -> target``, use a comma as a separator. For example,
When adding flags, the specific ``section -> target`` in the scheme needs to be specified. For multiple ``section -> target``, use a comma as a separator. For example,
.. code-block:: none
@ -572,9 +515,7 @@ generates an output on the linker script:
KEEP(lib1.a:obj1.*( SORT(.rodata) SORT(.rodata.*) ))
__my_sym_end = ABSOLUTE(.)
Note that ALIGN and SURROUND, as mentioned in the flag descriptions, are order sensitive.
Therefore, if for the same mapping fragment these two are switched, the following
is generated instead:
Note that ALIGN and SURROUND, as mentioned in the flag descriptions, are order sensitive. Therefore, if for the same mapping fragment these two are switched, the following is generated instead:
.. code-block:: none
@ -589,12 +530,10 @@ is generated instead:
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.
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.
@ -604,8 +543,7 @@ However, this is not the case for static data declared in function scope, as the
Linker Script Template
^^^^^^^^^^^^^^^^^^^^^^
The linker script template is the skeleton in which the generated placement rules are put into. It is an otherwise ordinary linker script, with a specific marker syntax
that indicates where the generated placement rules are placed.
The linker script template is the skeleton in which the generated placement rules are put into. It is an otherwise ordinary linker script, with a specific marker syntax that indicates where the generated placement rules are placed.
To reference the placement rules collected under a ``target`` token, the following syntax is used:
@ -615,8 +553,7 @@ To reference the placement rules collected under a ``target`` token, the followi
Example:
The example below is an excerpt from a possible linker script template. It defines an output section ``.iram0.text``, and inside is a marker referencing
the target ``iram0_text``.
The example below is an excerpt from a possible linker script template. It defines an output section ``.iram0.text``, and inside is a marker referencing the target ``iram0_text``.
.. code-block:: none
@ -674,15 +611,10 @@ Then the corresponding excerpt from the generated linker script will be as follo
``*libfreertos.a:(.literal .text .literal.* .text.*)``
Rule generated from the entry ``* (noflash)`` of the ``freertos`` mapping fragment. All ``text`` sections of all
object files under the archive ``libfreertos.a`` will be collected under the target ``iram0_text`` (as per the ``noflash`` scheme)
and placed wherever in the template ``iram0_text`` is referenced by a marker.
Rule generated from the entry ``* (noflash)`` of the ``freertos`` mapping fragment. All ``text`` sections of all object files under the archive ``libfreertos.a`` will be collected under the target ``iram0_text`` (as per the ``noflash`` scheme) and placed wherever in the template ``iram0_text`` is referenced by a marker.
``*(.iram1 .iram1.*)``
Rule generated from the default scheme entry ``iram -> iram0_text``. Since the default scheme specifies an ``iram -> iram0_text`` entry,
it too is placed wherever ``iram0_text`` is referenced by a marker. Since it is a rule generated from the default scheme, it comes first
among all other rules collected under the same target name.
Rule generated from the default scheme entry ``iram -> iram0_text``. Since the default scheme specifies an ``iram -> iram0_text`` entry, it too is placed wherever ``iram0_text`` is referenced by a marker. Since it is a rule generated from the default scheme, it comes first among all other rules collected under the same target name.
The linker script template currently used is :component_file:`{IDF_TARGET_PATH_NAME}/ld/{IDF_TARGET_PATH_NAME}.project.ld.in`, specified by the ``{IDF_TARGET_PATH_NAME}`` component; the
generated output script is put under its build directory.
The linker script template currently used is :component_file:`{IDF_TARGET_PATH_NAME}/ld/{IDF_TARGET_PATH_NAME}.project.ld.in`, specified by the ``{IDF_TARGET_PATH_NAME}`` component; the generated output script is put under its build directory.

View File

@ -1,5 +1,6 @@
Documentation Add-ons and Extensions Reference
==============================================
:link_to_translation:`zh_CN:[中文]`
This documentation is created using `Sphinx <http://www.sphinx-doc.org/>`_ application that renders text source files in `reStructuredText <https://en.wikipedia.org/wiki/ReStructuredText>`_ (``.rst``) format located in :idf:`docs` directory. For some more details on that process, please refer to section :doc:`documenting-code`.
@ -12,7 +13,6 @@ On top of that, we have created a couple of custom add-ons and extensions to hel
The purpose of this section is to provide a quick reference to the add-ons and the extensions.
Documentation Folder Structure
------------------------------
@ -143,9 +143,15 @@ Other Extensions
:idf_file:`docs/idf_extensions/format_idf_target.py`
An extension for replacing generic target related names with the idf_target passed to the Sphinx command line.
This is a {\IDF_TARGET_NAME}, with /{\IDF_TARGET_PATH_NAME}/soc.c, compiled with `{\IDF_TARGET_TOOLCHAIN_PREFIX}-gcc` with `CONFIG_{\IDF_TARGET_CFG_PREFIX}_MULTI_DOC` will, if the backspaces are removed, render as This is a {IDF_TARGET_NAME}, with /{IDF_TARGET_PATH_NAME}/soc.c, compiled with `{IDF_TARGET_TOOLCHAIN_PREFIX}-gcc` with `CONFIG_{IDF_TARGET_CFG_PREFIX}_MULTI_DOC`.
Also supports markup for defining local (single .rst-file) substitions with the following syntax: {\IDF_TARGET_TX_PIN:default="IO3",esp32="IO4",esp32s2="IO5"}
This is a {\IDF_TARGET_NAME}, with /{\IDF_TARGET_PATH_NAME}/soc.c, compiled with `{\IDF_TARGET_TOOLCHAIN_PREFIX}-gcc`
with `CONFIG_{\IDF_TARGET_CFG_PREFIX}_MULTI_DOC`
will, if the backspaces are removed, render as
This is a {IDF_TARGET_NAME}, with /{IDF_TARGET_PATH_NAME}/soc.c, compiled with `{IDF_TARGET_TOOLCHAIN_PREFIX}-gcc` with `CONFIG_{IDF_TARGET_CFG_PREFIX}_MULTI_DOC`.
Also supports markup for defining local (single .rst-file) substitions with the following syntax:
{\IDF_TARGET_TX_PIN:default="IO3",esp32="IO4",esp32s2="IO5"}
This will define a replacement of the tag {\IDF_TARGET_TX_PIN} in the current rst-file.
@ -182,7 +188,7 @@ Other Extensions
Please refer to :doc:`documenting-code` and :doc:`../api-reference/template`, section **API Reference** for additional details on this process.
Related Documents
-----------------
-------------------
* :doc:`documenting-code`

View File

@ -10,8 +10,9 @@
开发人员可以使用这个功能库将应用程序的运行状态发送给主机,在运行时接收来自主机的命令或者其他类型的信息。该库的主要使用场景有:
1. 收集应用程序特定的数据,具体请参阅 :ref:`app_trace-application-specific-tracing`
2. 轻量级日志记录,具体请参阅 :ref:`app_trace-logging-to-host`
2. 记录到主机的轻量级日志,具体请参阅 :ref:`app_trace-logging-to-host`
3. 系统行为分析,具体请参阅 :ref:`app_trace-system-behaviour-analysis-with-segger-systemview`
4. 源代码覆盖率,具体请参阅 :ref:`app_trace-gcov-source-code-coverage`
使用 JTAG 接口的跟踪组件工作示意图:
@ -61,7 +62,7 @@
.. _app_trace-application-specific-tracing:
特定应用程序的跟踪
~~~~~~~~~~~~~~~~~~
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
通常,用户需要决定在每个方向上待传输数据的类型以及如何解析(处理)这些数据。要想在目标和主机之间传输数据,用户必须要执行以下几个步骤。
@ -158,9 +159,8 @@
5. 使用特殊的 OpenOCD 命令开始收集待跟踪的命令,此命令将传输跟踪数据并将其重定向到指定的文件或套接字(当前仅支持文件作为跟踪数据目标)。相关命令的说明请参阅 :ref:`jtag-debugging-launching-debugger`
6. 最后一步是处理接收到的数据,由于数据格式由用户定义,因此处理阶段超出了本文档的范围。数据处理的范例可以参考位于 ``$IDF_PATH/tools/esp_app_trace`` 下的 Python 脚本 ``apptrace_proc.py`` (用于功能测试)和 ``logtrace_proc.py`` (请参阅 :ref:`app_trace-logging-to-host` 章节中的详细信息)。
OpenOCD 应用程序跟踪命令
^^^^^^^^^^^^^^^^^^^^^^^^
""""""""""""""""""""""""""""""
*HW UP BUFFER* 在用户数据块之间共享,并且会替 API 的调用者(在任务或者中断上下文中)填充分配到的内存。在多线程环境中,正在填充缓冲区的任务/中断可能会被另一个高优先级的任务/中断抢占有可能发生主机读取还未准备好的用户数据的情况。为了处理这样的情况跟踪模块在所有用户数据块之前添加一个数据头其中包含有分配的用户缓冲区的大小2 字节和实际写入的数据长度2 字节),也就是说数据头总共长 4 字节。负责读取跟踪数据的 OpenOCD 命令在读取到不完整的用户数据块时会报错,但是无论如何它都会将整个用户数据块(包括还未填充的区域)的内容放到输出文件中。
@ -250,6 +250,7 @@ Start 子命令的语法:
.. _app_trace-logging-to-host:
记录日志到主机
^^^^^^^^^^^^^^
@ -354,7 +355,7 @@ OpenOCD SystemView 跟踪命令选项
``esp32 sysview [start <options>] | [stop] | [status]``
命令:
命令:
``start``
开启跟踪(连续流模式)。
@ -406,9 +407,13 @@ Start 子命令语法:
数据可视化
""""""""""
收集到跟踪数据后,用户可以使用特殊的工具来可视化结果并分析程序的行为。遗憾的是SystemView 不支持从多个核心进行跟踪。所以当追踪双核模式下的 ESP32 时会生成两个文件:一个用于 PRO CPU另一个用于 APP CPU。用户可以将每个文件加载到工具中单独分析。
收集到跟踪数据后,用户可以使用特殊的工具来可视化结果并分析程序的行为。
在工具中单独分析每个核的跟踪数据是比较棘手的,幸运的是, Eclipse 中有一款 *Impulse* 的插件可以加载多个跟踪文件,并且可以在同一个视图中检查来自两个内核的事件。此外,与免费版的 SystemView 相比,此插件没有 1,000,000 个事件的限制。
.. only:: not CONFIG_FREERTOS_UNICORE
遗憾的是SystemView 不支持从多个核心进行跟踪。所以当追踪双核模式下的 {IDF_TARGET_NAME} 时会生成两个文件:一个用于 PRO CPU另一个用于 APP CPU。用户可以将每个文件加载到工具中单独分析。
在工具中单独分析每个核的跟踪数据是比较棘手的,但是 Eclipse 提供了一个叫 *Impulse* 的插件可以加载多个跟踪文件,并且可以在同一个视图中检查来自两个内核的事件。此外,与免费版的 SystemView 相比,此插件没有 1,000,000 个事件的限制。
关于如何安装、配置 Impulse 并使用它可视化来自单个核心的跟踪数据,请参阅 `官方教程 <https://mcuoneclipse.com/2016/07/31/impulse-segger-systemview-in-eclipse/>`_
@ -417,22 +422,183 @@ Start 子命令语法:
IDF 使用自己的 SystemView FreeRTOS 事件 ID 映射,因此用户需要将 ``$SYSVIEW_INSTALL_DIR/Description/SYSVIEW_FreeRTOS.txt`` 替换成 ``$IDF_PATH/docs/api-guides/SYSVIEW_FreeRTOS.txt``
在使用上述链接配置 SystemView 序列化程序时,也应该使用该 IDF 特定文件的内容。
.. only:: not CONFIG_FREERTOS_UNICORE
配置 Impulse 实现双核跟踪
~~~~~~~~~~~~~~~~~~~~~~~~~
配置 Impulse 实现双核跟踪
~~~~~~~~~~~~~~~~~~~~~~~~~
在安装好 Impulse 插件后,先确保它能够在单独的选项卡中成功加载每个核心的跟踪文件,然后用户可以添加特殊的 Multi Adapter 端口并将这两个文件加载到一个视图中。为此,用户需要在 Eclipse 中执行以下操作:
在安装好 Impulse 插件并确保 Impulse 能够在单独的选项卡中成功加载每个核心的跟踪文件后,用户可以添加特殊的 Multi Adapter 端口并将这两个文件加载到一个视图中。为此,用户需要在 Eclipse 中执行以下操作:
1. 打开 “Signal Ports” 视图,前往 Windows->Show View->Other 菜单,在 Impulse 文件夹中找到 “Signal Ports” 视图,然后双击它。
2. 在 “Signal Ports” 视图中,右键单击 “Ports” 并选择 “Add ...”,然后选择 New Multi Adapter Port。
3. 在打开的对话框中按下 “Add” 按钮,选择 “New Pipe/File”。
4. 在打开的对话框中选择 “SystemView Serializer” 并设置 PRO CPU 跟踪文件的路径,按下确定保存设置。
5. 对 APP CPU 的跟踪文件重复步骤 3 和 4。
6. 双击创建的端口,会打开此端口的视图。
7. 单击 Start/Stop Streaming 按钮,数据将会被加载。
8. 使用 “Zoom Out”“Zoom In” 和 “Zoom Fit” 按钮来查看数据。
9. 有关设置测量光标和其他的功能,请参阅 `Impulse 官方文档 <http://toem.de/index.php/projects/impulse>`_
.. note::
如果您在可视化方面遇到了问题未显示数据或者缩放操作异常您可以尝试删除当前的信号层次结构再双击必要的文件或端口。Eclipse 会请求您创建新的信号层次结构。
.. _app_trace-gcov-source-code-coverage:
Gcov源代码覆盖
^^^^^^^^^^^^^^^^^^^^^^^^^^^
Gcov 和 Gcovr 简介
""""""""""""""""""""""""
源代码覆盖率显示程序运行时间内执行的每一条程序执行路径的数量和频率。`Gcov <https://en.wikipedia.org/wiki/Gcov>`_ 是一个 GCC 工具,与编译器协同使用时,可生成日志文件,显示源文件每行的执行次数。`Gcovr <https://gcovr.com>`_ 是管理 Gcov 和生成代码覆盖率总结的工具。
一般来说,使用 Gcov 在主机上编译和运行程序会经过以下步骤:
1. 使用 GCC 以及 ``--coverage`` 选项编译源代码。这会让编译器在编译过程中生成一个 ``.gcno`` 注释文件,该文件包含重建执行路径块图以及将每个块映射到源代码行号等信息。每个用 ``--coverage`` 选项编译的源文件都会有自己的同名 ``.gcno`` 文件(如 ``main.c`` 在编译时会生成 ``main.gcno``)。
2. 执行程序。在执行过程中,程序会生成 ``.gcda`` 数据文件。这些数据文件包含了执行路径的次数统计。程序将为每个用 ``--coverage`` 选项编译的源文件生成一个 ``.gcda`` 文件(如 ``main.c`` 将生成 ``main.gcda``)。
3. Gcov 或 Gcovr 可用于生成基于 ``.gcno````.gcda`` 和源文件的代码覆盖。Gcov 将以 ``.gcov`` 文件的形式为每个源文件生成基于文本的覆盖报告,而 Gcovr 将以 HTML 格式生成覆盖报告。
ESP-IDF 中 Gcov 和 Gcovr 应用
"""""""""""""""""""""""""""""""
在 ESP-IDF 中使用 Gcov 比较复杂,因为程序不在主机上运行(即在目标机上运行)。代码覆盖率数据(即 ``.gcda`` 文件)最初存储在目标机上。然后 OpenOCD 在运行时通过 JTAG 将代码覆盖数据从目标机转储到主机上。在 ESP-IDF 中使用 Gcov 可以分为以下几个步骤:
1. :ref:`app_trace-gcov-setup-project`
2. :ref:`app_trace-gcov-dumping-data`
3. :ref:`app_trace-gcov-generate-report`
.. _app_trace-gcov-setup-project:
为 Gcov 设置项目
"""""""""""""""""""""""""""""""
编译器选项
~~~~~~~~~~~~~~~
为了获得项目中的代码覆盖率数据,项目中的一个或多个源文件必须用 ``--coverage`` 选项进行编译。在 ESP-IDF 中,这可以在组件级或单个源文件级实现:
使组件中的所有源文件用 ``--coverage`` 选项进行编译:
- 如果使用 CMake则在组件的 ``CMakeLists.txt`` 文件中添加 ``target_compile_options(${COMPONENT_LIB} PRIVATE --coverage)``
- 如果使用 Make则在组件的 ``component.mk`` 文件中添加 ``CFLAGS += --coverage``
使同一组件中选定的一些源文件(如 ``sourec1.c````source2.c``)通过 ``--coverage`` 选项编译:
- 如果使用 CMake则在组件的 ``CMakeLists.txt`` 文件中添加 ``set_source_files_properties(source1.c source2.c PROPERTIES COMPILE_FLAGS --coverage)``
- 如果使用 Make则在组件的 ``component.mk`` 文件中添加 ``source1.o: CFLAGS += --coverage````source2.o: CFLAGS += --coverage``
当一个源文件用 ``--coverage`` 选项编译时(例如 ``gcov_example.c``),编译器会在项目的构建目录下生成 ``gcov_example.gcno`` 文件。
项目配置
~~~~~~~~~~~~~~~~~
在构建一个有源代码覆盖的项目之前,请通过运行 ``idf.py menuconfig``(如使用传统的 Make 构建系统,则启用 ``make menuconfig``)启用以下项目配置选项。
- 通过 :ref:`CONFIG_APPTRACE_DESTINATION` 选项选择 *Trace Memory* 来启用应用程序跟踪模块。
- 通过 :ref:`CONFIG_APPTRACE_GCOV_ENABLE` 选项启用 Gcov 主机。
.. _app_trace-gcov-dumping-data:
转储代码覆盖数据
""""""""""""""""""""""""""
一旦一个项目使用 ``--coverage`` 选项编译并烧录到目标机上,在应用程序运行时,代码覆盖数据将存储在目标机内部(即在跟踪存储器中)。将代码覆盖率数据从目标机转移到主机上的过程称为转储。
覆盖率数据的转储通过 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`` 中(如果使用传统 Make 构建系统,则是在 ``build/main/gcov_example_main.gcda`` 中)生成一个 ``gcov_example_main.gcda`` 文件。注意,编译过程中产生的 ``.gcno`` 文件也放在同一个目录下。
代码覆盖数据的转储可以在应用程序的整个生命周期内多次进行。每次转储都会用最新的代码覆盖信息更新 ``.gcda`` 文件。代码覆盖数据是累积的,因此最新的数据将包含应用程序整个生命周期中每个代码路径的总执行次数。
ESP-IDF 支持两种将代码覆盖数据从目标机转储到主机的方法:
* 运行中实时转储
* 硬编码转储
运行中实时转储
~~~~~~~~~~~~~~~~~~~~~
通过 telnet 会话调用 OpenOCD 命令 ``{IDF_TARGET_NAME} gcov`` 来触发运行时的实时转储。一旦被调用OpenOCD 将立即抢占 {IDF_TARGET_NAME} 的当前状态,并执行一个内置的 IDF Gcov 调试存根函数。调试存根函数将数据转储到主机。完成后,{IDF_TARGET_NAME} 将恢复当前状态。
硬编码转储
~~~~~~~~~~~~~~~
硬编码转储是由应用程序本身从程序内部调用 :cpp:func:`esp_gcov_dump` 函数触发的。在调用时,应用程序将停止并等待 OpenOCD 连接并检索代码覆盖数据。一旦 :cpp:func:`esp_gcov_dump` 函数被调用,主机将通过 telnet 会话执行 ``esp gcov dump`` OpenOCD 命令。``esp gcov dump`` 命令会让 OpenOCD 连接到 {IDF_TARGET_NAME},检索代码覆盖数据,然后断开与 {IDF_TARGET_NAME} 的连接,从而恢复应用程序。可以在应用程序的生命周期中多次触发硬编码转储。
通过在必要地方放置 :cpp:func:`esp_gcov_dump` (如在应用程序初始化后,在应用程序主循环的每次迭代期间),当应用程序在生命周期的某刻需要代码覆盖率数据时,硬编码转储会非常有用。
GDB 可以用来在 :cpp:func:`esp_gcov_dump` 上设置一个断点,然后通过使用 ``gdbinit`` 脚本自动调用 ``mon esp gcov dump`` (关于 GDB 的使用可参考 :ref:`jtag-debugging-using-debugger-command-line`)。
以下 GDB 脚本将在 :cpp:func:`esp_gcov_dump` 处添加一个断点,然后调用 ``mon esp gcov dump`` OpenOCD 命令。
.. code-block:: none
b esp_gcov_dump
commands
mon esp gcov dump
end
1. 打开 “Signal Ports” 视图,前往 Windows->Show View->Other 菜单,在 Impulse 文件夹中找到 “Signal Ports” 视图,然后双击它。
2. 在 “Signal Ports” 视图中,右键单击 “Ports” 并选择 “Add ...”,然后选择 New Multi Adapter Port。
3. 在打开的对话框中按下 “Add” 按钮,选择 “New Pipe/File”。
4. 在打开的对话框中选择 “SystemView Serializer” 并设置 PRO CPU 跟踪文件的路径,按下确定保存设置。
5. 对 APP CPU 的跟踪文件重复步骤 3 和 4。
6. 双击创建的端口,会打开此端口的视图。
7. 单击 Start/Stop Streaming 按钮,数据将会被加载。
8. 使用 “Zoom Out”“Zoom In” 和 “Zoom Fit” 按钮来查看数据。
9. 有关设置测量光标和其他的功能,请参阅 `Impulse 官方文档 <http://toem.de/index.php/projects/impulse>`_
.. note::
注意所有的 OpenOCD 命令都应该在 GDB 中以 ``mon <oocd_command>`` 方式调用。
如果您在可视化方面遇到了问题未显示数据或者缩放操作很奇怪您可以尝试删除当前的信号层次结构再双击必要的文件或端口。Eclipse 会请求您创建新的信号层次结构。
.. _app_trace-gcov-generate-report:
生成代码覆盖报告
""""""""""""""""""""""""""
一旦代码覆盖数据被转储,``.gcno````.gcda`` 和源文件可以用来生成代码覆盖报告。该报告会显示源文件中每行被执行的次数。
Gcov 和 Gcovr 都可以用来生成代码覆盖报告。安装 Xtensa 工具链时会一起安装 Gcov但 Gcovr 可能需要单独安装。关于如何使用 Gcov 或 Gcovr请参考 `Gcov documentation <https://gcc.gnu.org/onlinedocs/gcc/Gcov.html>`_`Gcovr documentation <http://gcovr.com/>`_
在工程中添加 Gcovr 构建目标
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
用户可以在自己的工程中定义额外的构建目标从而更方便地生成报告。可以通过一个简单的构建命令生成这样的报告。
CMake 构建系统
************************
对于 CMake 构建系统,请在您工程的 ``CMakeLists.txt`` 文件中添加以下内容:
.. code-block:: none
include($ENV{IDF_PATH}/tools/cmake/gcov.cmake)
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``:删除所有代码覆盖数据文件。
Make 构建系统
************************
对于 Make 构建系统,请在您工程的 ``Makefile`` 文件中添加以下内容:
.. code-block:: none
GCOV := $(call dequote,$(CONFIG_SDK_TOOLPREFIX))gcov
REPORT_DIR := $(BUILD_DIR_BASE)/coverage_report
gcovr-report:
echo "Generating coverage report in: $(REPORT_DIR)"
echo "Using gcov: $(GCOV)"
mkdir -p $(REPORT_DIR)/html
cd $(BUILD_DIR_BASE)
gcovr -r $(PROJECT_PATH) --gcov-executable $(GCOV) -s --html-details $(REPORT_DIR)/html/index.html
cov-data-clean:
echo "Remove coverage data files..."
find $(BUILD_DIR_BASE) -name "*.gcda" -exec rm {} +
rm -rf $(REPORT_DIR)
.PHONY: gcovr-report cov-data-clean
可使用以下命令:
* ``make gcovr-report``:在 ``$(BUILD_DIR_BASE)/coverage_report/html`` 目录下生成 HTML 格式代码覆盖报告。
* ``make cov-data-clean``:删除所有代码覆盖数据文件。

View File

@ -1,20 +1,28 @@
链接脚本生成机制
================
链接脚本生成机制
======================
:link_to_translation:`en:[English]`
概述
----
-------
用于存放代码和数据的 :ref:` 内存区域 <memory-layout>`有多个。代码和只读数据默认存放在 flash 中,可写数据存放在 RAM 中。不过有时,我们必须更改默认存放区域,例如为了提高性能,将关键代码存放到 RAM 中,或者将代码存放到 RTC 存储器中以便在 :doc:`唤醒桩 <deep-sleep-stub>` 和 ULP 协处理器中使用
{IDF_TARGET_NAME} 中有多个用于存放代码和数据的 :ref:`内存区域<memory-layout>` 。代码和只读数据默认存放在 flash 中,可写数据存放在 RAM 中。不过有时,用户必须更改默认存放区域
链接脚本生成机制可以让用户指定代码和数据在 ESP-IDF 组件中的存放区域。组件包含如何存放符号、目标或完整库的信息。在构建应用程序时,组件中的这些信息会被收集、解析并处理;生成的存放规则用于链接应用程序。
.. only:: SOC_ULP_SUPPORTED
例如为了提高性能,将关键代码存放到 RAM 中,或者将代码存放到 RTC 存储器中以便在 :doc:`唤醒桩 <deep-sleep-stub>` 和 ULP 协处理器中使用。
.. only:: not SOC_ULP_SUPPORTED
例如为了提高性能,将关键代码存放到 RAM 中,或者将代码存放到 RTC 存储器中以便在 :doc:`唤醒桩 <deep-sleep-stub>` 中使用。
链接器脚本生成机制可以让用户指定代码和数据在 ESP-IDF 组件中的存放区域。组件包含如何存放符号、目标或完整库的信息。在构建应用程序时,组件中的这些信息会被收集、解析并处理;生成的存放规则用于链接应用程序。
快速上手
--------
------------
本段将指导如何使用 ESP-IDF 的即用方案,快速将代码和数据放入 RAM 和 RTC 存储器中。
假设我们有::
假设用户有::
- components/
- my_component/
@ -28,19 +36,19 @@
- my_linker_fragment_file.lf
- 名为 ``my_component`` 的组件,在构建过程中存储为 ``libmy_component.a`` 库文件
- 库文件包含的三个源文件:``my_src1.c````my_src2.c````my_src3.c``,编译后分别为 ``my_src1.o````my_src2.o````my_src3.o``,
- 在 ``my_src1.o`` 定义 ``my_function1`` 功能;在 ``my_src2.o`` 定义 ``my_function2`` 功能
- 存储``my_component`` 下 Kconfig 中布尔类型配置 ``PERFORMANCE_MODE`` (y/n) 和整数类型配置 ``PERFORMANCE_LEVEL`` (范围是 0-3
- 库文件包含的三个源文件:``my_src1.c````my_src2.c````my_src3.c``,编译后分别为 ``my_src1.o````my_src2.o````my_src3.o``
- 在 ``my_src1.o`` 定义 ``my_function1`` 功能;在 ``my_src2.o`` 定义 ``my_function2`` 功能
- 在 ``my_component`` 下 Kconfig 中存在布尔类型配置 ``PERFORMANCE_MODE`` (y/n) 和整数类型配置 ``PERFORMANCE_LEVEL`` (范围是 0-3
创建和指定链接片段文件
^^^^^^^^^^^^^^^^^^^^^^
创建和指定链接片段文件
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
首先,我们需要创建链接片段文件。链接片段文件是一个拓展名为 ``.lf`` 的文本文件,文件内写有想要存放的位置。文件创建成功后需要将其呈现在构建系统中。ESP-IDF 支持的构建系统指南如下:
首先,用户需要创建链接器片段文件。链接器片段文件是一个扩展名为 ``.lf`` 的文本文件,想要存放的位置信息会写入该文件内。文件创建成功后需要将其呈现在构建系统中。ESP-IDF 支持的构建系统指南如下:
Make
""""
在组件目录的 ``component.mk`` 文件中设置 ``COMPONENT_ADD_LDFRAGMENTS`` 变量的值,使其指向已创建的链接片段文件。路径可以为绝对路径,也可以为组件目录的相对路径。
在组件目录的 ``component.mk`` 文件中设置 ``COMPONENT_ADD_LDFRAGMENTS`` 变量的值,使其指向已创建的链接片段文件。路径可以为绝对路径,也可以为组件目录的相对路径。
.. code-block:: make
@ -49,7 +57,7 @@ Make
CMake
"""""
在组件目录的 ``CMakeLists.txt`` 文件中,指定 ``idf_component_register`` 调用引数 ``LDFRAGMENTS`` 的值。``LDFRAGMENTS`` 可以为绝对路径,也可为组件目录的相对路径,指向刚才创建的链接片段文件。
在组件目录的 ``CMakeLists.txt`` 文件中,指定 ``idf_component_register`` 调用引数 ``LDFRAGMENTS`` 的值。``LDFRAGMENTS`` 可以为绝对路径,也可为组件目录的相对路径,指向已创建的链接器片段文件。
.. code-block:: cmake
@ -61,7 +69,7 @@ CMake
指定存放区域
^^^^^^^^^^^^
^^^^^^^^^^^^^^^
可以按照下列粒度指定存放区域:
@ -75,7 +83,7 @@ CMake
""""""""""""
假设整个 ``my_src1.o`` 目标文件对性能至关重要,所以最好把该文件放在 RAM 中。另外,``my_src2.o`` 目标文件包含从深度睡眠唤醒所需的符号,因此需要将其存放到 RTC 存储器中。
在链接片段文件中可以写入以下内容:
在链接片段文件中可以写入以下内容:
.. code-block:: none
@ -87,11 +95,10 @@ CMake
那么 ``my_src3.o`` 放在哪里呢?由于未指定存放区域,``my_src3.o`` 会存放到默认区域。更多关于默认存放区域的信息,请查看 :ref:`这里<ldgen-default-placements>`
存放符号
""""""""
继续上文的例子,假设 ``object1.o`` 目标文件定义的功能中,只有 ``function1`` 影响到性能;``object2.o`` 目标文件中只有 ``function2`` 需要在芯片从深度睡眠中唤醒后运行。可在链接片段文件中写入以下内容实现
继续上文的例子,假设 ``object1.o`` 目标文件定义的功能中,只有 ``my_function1`` 影响到性能;``object2.o`` 目标文件中只有 ``my_function2`` 需要在芯片从深度睡眠中唤醒后运行。要实现该目的,可在链接片段文件中写入以下内容:
.. code-block:: none
@ -101,8 +108,7 @@ CMake
my_src1:my_function1 (noflash)
my_src2:my_function2 (rtc)
``my_src1.o````my_src2.o`` 中的其他函数以及整个 ``object3.o`` 目标文件会存放到默认区域。
要指定数据的存放区域,仅需将上文的函数名替换为变量名即可,如::
``my_src1.o````my_src2.o`` 中的其他函数以及整个 ``object3.o`` 目标文件会存放到默认区域。要指定数据的存放区域,仅需将上文的函数名替换为变量名即可,如::
my_src1:my_variable (noflash)
@ -113,7 +119,7 @@ CMake
存放整个库
""""""""""
在这个例子中,假设整个组件库都需存放到 RAM 中,可以写入以下内容实现
在这个例子中,假设整个组件库都需存放到 RAM 中,可以写入以下内容存放整个库
.. code-block:: none
@ -185,33 +191,32 @@ CMake
.. _ldgen-default-placements:
默认存放区域
^^^^^^^^^^^^
^^^^^^^^^^^^^^^^
到目前为止,“默认存放区域”在未指定 ``rtc````noflash`` 存放规则时才会使用,作为备选方案。需要注意的是,``noflash`` 或者 ``rtc`` 标记不仅仅是关键字,实际上还是被称作片段的实体,确切地说是 :ref:`协议 <ldgen-scheme-fragment>`
到目前为止,“默认存放区域”在未指定 ``rtc````noflash`` 存放规则时才会作为备选方案使用。需要注意的是,``noflash`` 或者 ``rtc`` 标记不仅仅是关键字,实际上还是被称作片段的实体,确切地说是 :ref:`协议 <ldgen-scheme-fragment>`
``rtc````noflash`` 类似,还有一个 ``默认`` 协议,定义了默认存放规则。顾名思义,该协议规定了代码和数据通常存放的区域,即代码和恒量存放在 flash 中,变量存放在 RAM 中。更多关于默认协议的信息,请见 :ref:`这里<ldgen-default-scheme>`
.. note::
使用链接脚本生成机制的 IDF 组件示例,请参阅 :component_file:`freertos/CMakeLists.txt`。为了提高性能,``freertos`` 使用链接脚本生成机制,将其目标文件存放到 RAM 中。
使用链接脚本生成机制的 IDF 组件示例,请参阅 :component_file:`freertos/CMakeLists.txt`。为了提高性能,``freertos`` 使用链接脚本生成机制,将其目标文件存放到 RAM 中。
快速入门指南到此结束,下文将详述这个机制的内核,有助于创建自定义存放区域或修改默认方式。
链接脚本生成机制内核
--------------------
链接脚本生成机制内核
---------------------------
链接是将 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::
执行链接脚本生成机制的工具存放在 :idf:`tools/ldgen` 之下。
执行链接脚本生成机制的工具存放在 :idf:`tools/ldgen` 之下。
.. _ldgen-linker-fragment-files :
链接片段文件
^^^^^^^^^^^^
链接片段文件
^^^^^^^^^^^^^^^^
如快速入门指南所述,片段文件是拓展名为 ``.lf`` 的简单文本文件,内含想要存放区域的信息。不过,这是对片段文件所包含内容的简化版描述。实际上,片段文件内包含的是“片段”。片段是实体,包含多条信息,这些信息放在一起组成了存放规则,说明目标文件各个段在二进制输出文件中的存放位置。片段一共有三种,分别是 :ref:`段<ldgen-sections-fragment>`
:ref:`协议<ldgen-scheme-fragment>`:ref:`映射<ldgen-mapping-fragment>`
如快速入门指南所述,片段文件是拓展名为 ``.lf`` 的简单文本文件,内含想要存放区域的信息。不过,这是对片段文件所包含内容的简化版描述。实际上,片段文件内包含的是“片段”。片段是实体,包含多条信息,这些信息放在一起组成了存放规则,说明目标文件各个段在二进制输出文件中的存放位置。片段一共有三种,分别是 :ref:`段<ldgen-sections-fragment>`:ref:`协议<ldgen-scheme-fragment>`:ref:`映射<ldgen-mapping-fragment>`
语法
""""
@ -244,7 +249,7 @@ CMake
**条件检查**
条件检查使得链接脚本生成机制可以感知配置。含有配置值的表达式是否为真,决定了使用哪些特定键值。检查使用的是 kconfiglib 脚本的 ``eval_string``,遵循该脚本要求的语法和局限性,支持:
条件检查使得链接脚本生成机制可以感知配置。含有配置值的表达式是否为真,决定了使用哪些特定键值。检查使用的是 kconfiglib 脚本的 ``eval_string``,遵循该脚本要求的语法和局限性,支持:
- 比较
- 小于 ``<``
@ -256,7 +261,7 @@ CMake
- 逻辑
- 或 ``||``
- 和 ``&&``
- 否定?取反 ``!``
- 取反 ``!``
- 分组
- 圆括号 ``()``
@ -296,23 +301,23 @@ CMake
**注释**
链接片段文件中的注释以 ``#`` 开头。和在其他语言中一样,注释提供了有用的描述和资料,在处理过程中会被忽略。
链接片段文件中的注释以 ``#`` 开头。和在其他语言中一样,注释提供了有用的描述和资料,在处理过程中会被忽略。
与 ESP-IDF v3.x 链接脚本片段文件兼容
与 ESP-IDF v3.x 链接脚本片段文件兼容
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
ESP-IDF v4.0 变更了链接脚本片段文件使用的一些语法:
ESP-IDF v4.0 变更了链接脚本片段文件使用的一些语法:
- 必须缩进,缩进不当的文件会产生解析异常;旧版本不强制缩进,但之前的文档和示例均遵循了正确的缩进语法
- 条件改用 ``if...elif...else`` 结构,可以嵌套检查,将完整片段置于条件内
- 映射片段和其他片段类型一样,需有名称
链接脚本生成器可解析 ESP-IDF v3.x 版本中缩进正确的链接片段文件(如 ESP-IDF v3.x 版本中的本文件所示),依然可以向后兼容此前的映射片段语法(可选名称和条件的旧语法),但是会有弃用警告。用户应换成本文档介绍的新语法,因为旧语法将在未来停用。
链接脚本生成器可解析 ESP-IDF v3.x 版本中缩进正确的链接片段文件(如 ESP-IDF v3.x 版本中的本文件所示),依然可以向后兼容此前的映射片段语法(可选名称和条件的旧语法),但是会有弃用警告。用户应换成本文档介绍的新语法,因为旧语法将在未来停用。
请注意ESP-IDF v3.x 不支持使用 ESP-IDF v4.0 新语法的链接片段文件。
请注意ESP-IDF v3.x 不支持使用 ESP-IDF v4.0 新语法的链接片段文件。
类型
""""
"""""""
.. _ldgen-sections-fragment :
@ -406,7 +411,7 @@ ESP-IDF v4.0 变更了链接脚本片段文件使用的一些语法:
- 目标:只指定目标文件名称。
- 库:指定 ``*``,即某个库下面所有目标文件的简化表达法。
为了更好地理解条目的含义,我们看一个按目标存放的例子。
为了更好地理解条目的含义,看一个按目标存放的例子。
.. code-block:: none
@ -424,7 +429,6 @@ ESP-IDF v4.0 变更了链接脚本片段文件使用的一些语法:
.. code-block:: none
object (.section,
.section,
... -> target, # 根据目标文件将这里所列出的所有段放在该目标位置
@ -444,26 +448,102 @@ ESP-IDF v4.0 变更了链接脚本片段文件使用的一些语法:
entries:
* (noflash)
除了实体和协议,条目中也支持指定如下标志:(注:<> = 参数名称,[] = 可选参数)
1. ALIGN(<alignment>[, pre, post])
根据 ``alignment`` 中指定的数字对齐存放区域,根据是否指定 ``pre````post``,或两者都指定,在输入段描述(生成于映射条目)的前面和/或后面生成:
.. code-block::none
. = ALIGN(<alignment>)
如果既没有指定 ``pre`` 也没有指定 ``post``,则对齐命令会在输入段描述前生成。对顺序敏感。
2. SORT([<sort_by_first>, <sort_by_second>])
在输入段描述中输出 ``SORT_BY_NAME``, ``SORT_BY_ALIGNMENT``, ``SORT_BY_INIT_PRIORITY````SORT``
``sort_by_first````sort_by_second`` 的值可以是:``name````alignment````init_priority``
如果既没指定 ``sort_by_first`` 也没指定 ``sort_by_second``,则输入段会按照名称排序,如果两者都指定了,那么嵌套排序会遵循 https://sourceware.org/binutils/docs/ld/Input-Section-Wildcards.html 中的规则。
3. KEEP()
用 KEEP 命令包围输入段描述,从而防止链接器丢弃存放区域。更多细节请参考 https://sourceware.org/binutils/docs/ld/Input-Section-Keep.html
4.SURROUND(<name>)
在存放区域的前面和后面生成符号,生成的符号遵循 ``_<name>_start````_<name>_end`` 的命名方式,例如,如果 ``name`` == sym1
.. code-block::none
_sym1_start = ABSOLUTE(.)
...
_sym2_end = ABSOLUTE(.)
可以从 C/C++ 代码中引用这些符号。对顺序敏感。
在添加标志时,协议中需要指定具体的 ``section -> target``。对于多个 ``section -> target``,使用逗号作为分隔符,例如:
.. code-block:: none
# 注意
# A. entity-scheme 后使用分号
# B. section2 -> target2 前使用逗号
# C. 在 scheme1 条目中 定义 section1 -> target1 和 section2 -> target2
entity1 (scheme1);
section1 -> target1 KEEP() ALIGN(4, pre, post),
section2 -> target2 SURROUND(sym) ALIGN(4, post) SORT()
合并后,如下的映射:
.. code-block:: none
[mapping:name]
archive: lib1.a
entries:
obj1 (noflash);
rodata -> dram0_data KEEP() SORT() ALIGN(8) SURROUND(my_sym)
会在链接器脚本上生成如下输出:
.. code-block:: none
. = ALIGN(8)
__my_sym_start = ABSOLUTE(.)
KEEP(lib1.a:obj1.*( SORT(.rodata) SORT(.rodata.*) ))
__my_sym_end = ABSOLUTE(.)
注意,正如在 flag 描述中提到的ALIGN 和 SURROUND 的使用对顺序敏感,因此如果将两者顺序调换后用到相同的映射片段,则会生成:
.. code-block:: none
__my_sym_start = ABSOLUTE(.)
. = ALIGN(8)
KEEP(lib1.a:obj1.*( SORT(.rodata) SORT(.rodata.*) ))
__my_sym_end = ABSOLUTE(.)
.. _ldgen-symbol-granularity-placements :
按符号存放
""""""""""
""""""""""""""
按符号存放可通过编译器标志 ``-ffunction-sections````-ffdata-sections`` 实现。ESP-IDF 默认用这些标志编译。
用户若选择移除标志,便不能按符号存放。另外,即便有标志,也会其他限制,具体取决于编译器输出的段。
比如,使用 ``-ffunction-sections``,针对每个功能会输出单独的段。段的名称可以预测,即 ``.text.{func_name}``
``.literal.{func_name}``。但是功能内的字符串并非如此,因为字符串会进入字符串池,或者使用生成的段名称。
比如,使用 ``-ffunction-sections``,针对每个功能会输出单独的段。段的名称可以预测,即 ``.text.{func_name}````.literal.{func_name}``。但是功能内的字符串并非如此,因为字符串会进入字符串池,或者使用生成的段名称。
使用 ``-fdata-sections``,对全局数据来说编译器可输出 ``.data.{var_name}````.rodata.{var_name}````.bss.{var_name}``;因此 ``类型 I`` 映射词条可以适用。
但是,功能中声明的静态数据并非如此,生成的段名称是将变量名称和其他信息混合。
.. _ldgen-linker-script-template :
链接脚本模板
^^^^^^^^^^^^
链接脚本模板
^^^^^^^^^^^^^^^^^^
链接脚本模板是指定存放规则的存放位置的框架,与其他链接脚本没有本质区别,但带有特定的标记语法,可以指示存放生成的存放规则的位置。
链接脚本模板是指定存放规则的存放位置的框架,与其他链接脚本没有本质区别,但带有特定的标记语法,可以指示存放生成的存放规则的位置。
如需引用一个 ``目标`` 标记下的所有存放规则,请使用以下语法:
@ -473,7 +553,7 @@ ESP-IDF v4.0 变更了链接脚本片段文件使用的一些语法:
示例:
以下示例是某个链接脚本模板的摘录,定义了输出段 ``.iram0.text``,该输出段包含一个引用目标 ``iram0_text`` 的标记。
以下示例是某个链接脚本模板的摘录,定义了输出段 ``.iram0.text``,该输出段包含一个引用目标 ``iram0_text`` 的标记。
.. code-block:: none
@ -488,7 +568,7 @@ ESP-IDF v4.0 变更了链接脚本片段文件使用的一些语法:
_iram_text_end = ABSOLUTE(.);
} > iram0_0_seg
假设链接脚本生成器收集到了以下片段定义:
假设链接脚本生成器收集到了以下片段定义:
.. code-block:: none
@ -513,7 +593,7 @@ ESP-IDF v4.0 变更了链接脚本片段文件使用的一些语法:
entries:
* (noflash)
则该脚本生成器生成的链接脚本文件,其摘录应如下所示
然后生成的链接器脚本的相应摘录如下
.. code-block:: c
@ -537,5 +617,4 @@ ESP-IDF v4.0 变更了链接脚本片段文件使用的一些语法:
这是根据默认协议条目 ``iram -> iram0_text`` 生成的规则。默认协议指定了 ``iram -> iram0_text`` 条目,因此生成的规则同样也放在被 ``iram0_text`` 标记的地方。由于该规则是根据默认协议生成的,因此在同一目标下收集的所有规则下排在第一位。
目前使用的链接脚本模板是 :component_file:`{IDF_TARGET_PATH_NAME}/ld/{IDF_TARGET_PATH_NAME}.project.ld.in`,由 ``{IDF_TARGET_PATH_NAME}`` 组件指定,生成的脚本存放在构建目录下。
目前使用的链接器脚本模板是 :component_file:`{IDF_TARGET_PATH_NAME}/ld/{IDF_TARGET_PATH_NAME}.project.ld.in`,由 ``{IDF_TARGET_PATH_NAME}`` 组件指定,生成的脚本存放在构建目录下。

View File

@ -41,6 +41,7 @@ ESP-IDF 中包含多种芯片的双语文档(英文,简体中文)。如运
^^^^^^^
:idf_file:`docs/build_docs.py`
最高级可执行程序,负责运行 Sphinx 为单个或多个语言/目标生成文档。运行 ``build_docs.py --help`` 可查阅所有命令选项。
当使用 ``build_docs.py`` 运行 Sphinx 时,系统将为 ``idf_target`` 配置变量,并设置一个与该配置变量相同名称的 Sphinx 标签,然后使用一些环境变量将路径发送至 :ref:`IDF-Specific Extensions`
@ -61,9 +62,9 @@ ESP-IDF 中包含多种芯片的双语文档(英文,简体中文)。如运
该脚本将检测整个 `ESP-IDF`_ 库,在源代码头文件中查找是否有错误代码和信息,然后在 :doc:`../api-reference/error-codes` 内生成一个 ``.inc`` 文件记录这些信息。
:idf_file:`tools/kconfig_new/confgen.py`
ESP-IDF :idf:`components` 的配置选项包含在每个件目录下的 ``Kconfig`` 文件中,如 :idf_file:`components/bt/Kconfig`。该脚本将检测所有 ``component`` 目录并记录检测到的配置选项,然后在 :ref:`configuration-options-reference` 内生成一个 ``.inc`` 文件记录这些信息。
ESP-IDF :idf:`components` 的配置选项包含在每个件目录下的 ``Kconfig`` 文件中,如 :idf_file:`components/bt/Kconfig`。该脚本将检测所有 ``component`` 目录并记录检测到的配置选项,然后在 :ref:`configuration-options-reference` 内生成一个 ``.inc`` 文件记录这些信息。
泛型扩展
通用扩展
^^^^^^^^^^^^^^^^^^
以下是专为 IDF 开发的 Sphinx 扩展,这些扩展不依赖于任何特定的 IDF 文档操作或配置:
@ -116,7 +117,6 @@ CMake 项目模型运行完成后,系统将在构建初期发出 ``idf-info``
其它 IDF 专属的扩展功能均订阅该事件,并使用该事件根据系统构建信息来设置一些文档参数。
其它扩展
#############
@ -124,7 +124,7 @@ CMake 项目模型运行完成后,系统将在构建初期发出 ``idf-info``
``include-build-file`` 指令相当于是内置的 ``include-file`` 指令,只是文件路径是相对于 ``build_dir`` 来评估的。
:idf_file:`docs/idf_extensions/kconfig_reference.py`
订阅 ``idf-info`` 事件,并使用 confgen 从默认构建项目所使用的件中生成 ``kconfig.inc`` 文件。之后,这个文件将被存储至 :doc:`/api-reference/kconfig` 中。
订阅 ``idf-info`` 事件,并使用 confgen 从默认构建项目所使用的件中生成 ``kconfig.inc`` 文件。之后,这个文件将被存储至 :doc:`/api-reference/kconfig` 中。
:idf_file:`docs/idf_extensions/link_roles.py`
一个自定义的 `Sphinx 角色 <https://www.sphinx-doc.org/en/master/usage/restructuredtext/roles.html>`_ 的实现功能,帮助从文档链接到 `ESP-IDF`_ 项目中具体的文件和文件夹处。有关具体实现了哪些角色,请参阅 :ref:`link-custom-roles`:ref:`link-language-versions`
@ -195,4 +195,3 @@ CMake 项目模型运行完成后,系统将在构建初期发出 ``idf-info``
.. _ESP-IDF: https://github.com/espressif/esp-idf/
.. _Sphinx selective exclude: https://github.com/pfalcon/sphinx_selective_exclude