mirror of
https://github.com/espressif/esp-idf.git
synced 2025-08-02 04:04:31 +02:00
doc: add generation of tags from sdkconfig and x_caps.h headers
Also updates the way we handle exclude_patterns to use the new tags Closes IDF-1484
This commit is contained in:
@@ -67,6 +67,8 @@ extensions = ['breathe',
|
|||||||
'idf_extensions.gen_idf_tools_links',
|
'idf_extensions.gen_idf_tools_links',
|
||||||
'idf_extensions.format_idf_target',
|
'idf_extensions.format_idf_target',
|
||||||
'idf_extensions.latex_builder',
|
'idf_extensions.latex_builder',
|
||||||
|
'idf_extensions.gen_defines',
|
||||||
|
'idf_extensions.exclude_docs',
|
||||||
|
|
||||||
# from https://github.com/pfalcon/sphinx_selective_exclude
|
# from https://github.com/pfalcon/sphinx_selective_exclude
|
||||||
'sphinx_selective_exclude.eager_only',
|
'sphinx_selective_exclude.eager_only',
|
||||||
@@ -124,47 +126,49 @@ print('Version: {0} Release: {1}'.format(version, release))
|
|||||||
exclude_patterns = ['**/inc/**', '_static', '**/_build']
|
exclude_patterns = ['**/inc/**', '_static', '**/_build']
|
||||||
|
|
||||||
|
|
||||||
# Add target-specific excludes based on tags (for the IDF_TARGET). Haven't found any better way to do this yet
|
BT_DOCS = ['api-guides/blufi.rst',
|
||||||
def update_exclude_patterns(tags):
|
'api-guides/esp-ble-mesh/**',
|
||||||
if "esp32" not in tags:
|
'api-reference/bluetooth/**']
|
||||||
# Exclude ESP32-only document pages so they aren't found in the initial search for .rst files
|
|
||||||
# note: in toctrees, these also need to be marked with a :esp32: filter
|
|
||||||
for e in ['api-guides/blufi.rst',
|
|
||||||
'api-guides/build-system-legacy.rst',
|
|
||||||
'api-guides/esp-ble-mesh/**',
|
|
||||||
'api-guides/RF_calibration.rst', # temporary until support re-added in esp_wifi
|
|
||||||
'api-guides/ulp-legacy.rst',
|
|
||||||
'api-guides/unit-tests-legacy.rst',
|
|
||||||
'api-guides/ulp_instruction_set.rst',
|
|
||||||
'api-guides/jtag-debugging/configure-wrover.rst',
|
|
||||||
'api-reference/system/himem.rst',
|
|
||||||
'api-reference/bluetooth/**',
|
|
||||||
'api-reference/peripherals/sdio_slave.rst',
|
|
||||||
'api-reference/peripherals/esp_slave_protocol.rst',
|
|
||||||
'api-reference/peripherals/mcpwm.rst',
|
|
||||||
'api-reference/peripherals/sd_pullup_requirements.rst',
|
|
||||||
'api-reference/peripherals/sdmmc_host.rst',
|
|
||||||
'api-reference/protocols/esp_serial_slave_link.rst',
|
|
||||||
'api-reference/system/ipc.rst',
|
|
||||||
'get-started-legacy/**',
|
|
||||||
'security/secure-boot-v1.rst',
|
|
||||||
'security/secure-boot-v2.rst',
|
|
||||||
'gnu-make-legacy.rst',
|
|
||||||
'hw-reference/esp32/**',
|
|
||||||
]:
|
|
||||||
exclude_patterns.append(e)
|
|
||||||
|
|
||||||
if "esp32s2" not in tags:
|
SDMMC_DOCS = ['api-reference/peripherals/sdmmc_host.rst',
|
||||||
# Exclude ESP32-S2-only document pages so they aren't found in the initial search for .rst files
|
'api-reference/peripherals/sd_pullup_requirements.rst']
|
||||||
# note: in toctrees, these also need to be marked with a :esp32: filter
|
|
||||||
for e in ['esp32s2.rst',
|
|
||||||
'hw-reference/esp32s2/**',
|
|
||||||
'api-guides/dfu.rst',
|
|
||||||
'api-guides/ulps2_instruction_set.rst',
|
|
||||||
'api-reference/peripherals/hmac.rst',
|
|
||||||
'api-reference/peripherals/temp_sensor.rst']:
|
|
||||||
exclude_patterns.append(e)
|
|
||||||
|
|
||||||
|
SDIO_SLAVE_DOCS = ['api-reference/peripherals/sdio_slave.rst',
|
||||||
|
'api-reference/peripherals/esp_slave_protocol.rst',
|
||||||
|
'api-reference/protocols/esp_serial_slave_link.rst']
|
||||||
|
|
||||||
|
MCPWM_DOCS = ['api-reference/peripherals/mcpwm.rst']
|
||||||
|
|
||||||
|
LEGACY_DOCS = ['api-guides/build-system-legacy.rst',
|
||||||
|
'gnu-make-legacy.rst',
|
||||||
|
'api-guides/ulp-legacy.rst',
|
||||||
|
'api-guides/unit-tests-legacy.rst',
|
||||||
|
'get-started-legacy/**']
|
||||||
|
|
||||||
|
ESP32_DOCS = ['api-guides/ulp_instruction_set.rst',
|
||||||
|
'api-guides/jtag-debugging/configure-wrover.rst',
|
||||||
|
'api-reference/system/himem.rst',
|
||||||
|
'api-guides/RF_calibration.rst',
|
||||||
|
'api-reference/system/ipc.rst',
|
||||||
|
'security/secure-boot-v1.rst',
|
||||||
|
'security/secure-boot-v2.rst',
|
||||||
|
'hw-reference/esp32/**'] + LEGACY_DOCS
|
||||||
|
|
||||||
|
ESP32S2_DOCS = ['esp32s2.rst',
|
||||||
|
'hw-reference/esp32s2/**',
|
||||||
|
'api-guides/ulps2_instruction_set.rst',
|
||||||
|
'api-guides/dfu.rst',
|
||||||
|
'api-reference/peripherals/hmac.rst',
|
||||||
|
'api-reference/peripherals/temp_sensor.rst'
|
||||||
|
'']
|
||||||
|
|
||||||
|
# format: {tag needed to include: documents to included}, tags are parsed from sdkconfig and peripheral_caps.h headers
|
||||||
|
conditional_include_dict = {'SOC_BT_SUPPORTED':BT_DOCS,
|
||||||
|
'SOC_SDMMC_HOST_SUPPORTED':SDMMC_DOCS,
|
||||||
|
'SOC_SDIO_SLAVE_SUPPORTED':SDIO_SLAVE_DOCS,
|
||||||
|
'SOC_MCPWM_SUPPORTED':MCPWM_DOCS,
|
||||||
|
'esp32':ESP32_DOCS,
|
||||||
|
'esp32s2':ESP32S2_DOCS}
|
||||||
|
|
||||||
# The reST default role (used for this markup: `text`) to use for all
|
# The reST default role (used for this markup: `text`) to use for all
|
||||||
# documents.
|
# documents.
|
||||||
@@ -378,6 +382,8 @@ def setup(app):
|
|||||||
app.add_config_value('idf_target', None, 'env')
|
app.add_config_value('idf_target', None, 'env')
|
||||||
app.add_config_value('idf_targets', None, 'env')
|
app.add_config_value('idf_targets', None, 'env')
|
||||||
|
|
||||||
|
app.add_config_value('conditional_include_dict', None, 'env')
|
||||||
|
|
||||||
# Breathe extension variables (depend on build_dir)
|
# Breathe extension variables (depend on build_dir)
|
||||||
# note: we generate into xml_in and then copy_if_modified to xml dir
|
# note: we generate into xml_in and then copy_if_modified to xml dir
|
||||||
app.config.breathe_projects = {"esp32-idf": os.path.join(app.config.build_dir, "xml_in/")}
|
app.config.breathe_projects = {"esp32-idf": os.path.join(app.config.build_dir, "xml_in/")}
|
||||||
|
@@ -4,7 +4,7 @@ ESP-IDF FreeRTOS SMP Changes
|
|||||||
Overview
|
Overview
|
||||||
--------
|
--------
|
||||||
|
|
||||||
.. only:: esp32
|
.. only:: not CONFIG_FREERTOS_UNICORE
|
||||||
|
|
||||||
The vanilla FreeRTOS is designed to run on a single core. However the ESP32 is
|
The vanilla FreeRTOS is designed to run on a single core. However the ESP32 is
|
||||||
dual core containing a Protocol CPU (known as **CPU 0** or **PRO_CPU**) and an
|
dual core containing a Protocol CPU (known as **CPU 0** or **PRO_CPU**) and an
|
||||||
@@ -25,7 +25,7 @@ see :doc:`ESP-IDF FreeRTOS Additions<../api-reference/system/freertos_additions>
|
|||||||
port of FreeRTOS v8.2.0, a number of FreeRTOS v9.0.0 features have been backported
|
port of FreeRTOS v8.2.0, a number of FreeRTOS v9.0.0 features have been backported
|
||||||
to ESP-IDF.
|
to ESP-IDF.
|
||||||
|
|
||||||
.. only:: esp32
|
.. only:: not CONFIG_FREERTOS_UNICORE
|
||||||
|
|
||||||
:ref:`tasks-and-task-creation`: Use :cpp:func:`xTaskCreatePinnedToCore` or
|
:ref:`tasks-and-task-creation`: Use :cpp:func:`xTaskCreatePinnedToCore` or
|
||||||
:cpp:func:`xTaskCreateStaticPinnedToCore` to create tasks in ESP-IDF FreeRTOS. The
|
:cpp:func:`xTaskCreateStaticPinnedToCore` to create tasks in ESP-IDF FreeRTOS. The
|
||||||
@@ -155,133 +155,133 @@ ESP-IDF FreeRTOS (see :ref:`backported-features`).
|
|||||||
|
|
||||||
For more details see :component_file:`freertos/tasks.c`
|
For more details see :component_file:`freertos/tasks.c`
|
||||||
|
|
||||||
The ESP-IDF FreeRTOS task creation functions are nearly identical to their
|
The ESP-IDF FreeRTOS task creation functions are nearly identical to their
|
||||||
vanilla counterparts with the exception of the extra parameter known as
|
vanilla counterparts with the exception of the extra parameter known as
|
||||||
``xCoreID``. This parameter specifies the core on which the task should run on
|
``xCoreID``. This parameter specifies the core on which the task should run on
|
||||||
and can be one of the following values.
|
and can be one of the following values.
|
||||||
|
|
||||||
- ``0`` pins the task to **PRO_CPU**
|
- ``0`` pins the task to **PRO_CPU**
|
||||||
- ``1`` pins the task to **APP_CPU**
|
- ``1`` pins the task to **APP_CPU**
|
||||||
- ``tskNO_AFFINITY`` allows the task to be run on both CPUs
|
- ``tskNO_AFFINITY`` allows the task to be run on both CPUs
|
||||||
|
|
||||||
For example ``xTaskCreatePinnedToCore(tsk_callback, “APP_CPU Task”, 1000, NULL, 10, NULL, 1)``
|
For example ``xTaskCreatePinnedToCore(tsk_callback, “APP_CPU Task”, 1000, NULL, 10, NULL, 1)``
|
||||||
creates a task of priority 10 that is pinned to **APP_CPU** with a stack size
|
creates a task of priority 10 that is pinned to **APP_CPU** with a stack size
|
||||||
of 1000 bytes. It should be noted that the ``uxStackDepth`` parameter in
|
of 1000 bytes. It should be noted that the ``uxStackDepth`` parameter in
|
||||||
vanilla FreeRTOS specifies a task’s stack depth in terms of the number of
|
vanilla FreeRTOS specifies a task’s stack depth in terms of the number of
|
||||||
words, whereas ESP-IDF FreeRTOS specifies the stack depth in terms of bytes.
|
words, whereas ESP-IDF FreeRTOS specifies the stack depth in terms of bytes.
|
||||||
|
|
||||||
Note that the vanilla FreeRTOS functions :cpp:func:`xTaskCreate` and
|
Note that the vanilla FreeRTOS functions :cpp:func:`xTaskCreate` and
|
||||||
:cpp:func:`xTaskCreateStatic` have been defined in ESP-IDF FreeRTOS as inline functions which call
|
:cpp:func:`xTaskCreateStatic` have been defined in ESP-IDF FreeRTOS as inline functions which call
|
||||||
:cpp:func:`xTaskCreatePinnedToCore` and :cpp:func:`xTaskCreateStaticPinnedToCore`
|
:cpp:func:`xTaskCreatePinnedToCore` and :cpp:func:`xTaskCreateStaticPinnedToCore`
|
||||||
respectively with ``tskNO_AFFINITY`` as the ``xCoreID`` value.
|
respectively with ``tskNO_AFFINITY`` as the ``xCoreID`` value.
|
||||||
|
|
||||||
Each Task Control Block (TCB) in ESP-IDF stores the ``xCoreID`` as a member.
|
Each Task Control Block (TCB) in ESP-IDF stores the ``xCoreID`` as a member.
|
||||||
Hence when each core calls the scheduler to select a task to run, the
|
Hence when each core calls the scheduler to select a task to run, the
|
||||||
``xCoreID`` member will allow the scheduler to determine if a given task is
|
``xCoreID`` member will allow the scheduler to determine if a given task is
|
||||||
permitted to run on the core that called it.
|
permitted to run on the core that called it.
|
||||||
|
|
||||||
Scheduling
|
Scheduling
|
||||||
----------
|
----------
|
||||||
|
|
||||||
The vanilla FreeRTOS implements scheduling in the ``vTaskSwitchContext()``
|
The vanilla FreeRTOS implements scheduling in the ``vTaskSwitchContext()``
|
||||||
function. This function is responsible for selecting the highest priority task
|
function. This function is responsible for selecting the highest priority task
|
||||||
to run from a list of tasks in the Ready state known as the Ready Tasks List
|
to run from a list of tasks in the Ready state known as the Ready Tasks List
|
||||||
(described in the next section). In ESP-IDF FreeRTOS, each core will call
|
(described in the next section). In ESP-IDF FreeRTOS, each core will call
|
||||||
``vTaskSwitchContext()`` independently to select a task to run from the
|
``vTaskSwitchContext()`` independently to select a task to run from the
|
||||||
Ready Tasks List which is shared between both cores. There are several
|
Ready Tasks List which is shared between both cores. There are several
|
||||||
differences in scheduling behavior between vanilla and ESP-IDF FreeRTOS such as
|
differences in scheduling behavior between vanilla and ESP-IDF FreeRTOS such as
|
||||||
differences in Round Robin scheduling, scheduler suspension, and tick interrupt
|
differences in Round Robin scheduling, scheduler suspension, and tick interrupt
|
||||||
synchronicity.
|
synchronicity.
|
||||||
|
|
||||||
.. _round-robin-scheduling:
|
.. _round-robin-scheduling:
|
||||||
|
|
||||||
Round Robin Scheduling
|
Round Robin Scheduling
|
||||||
^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
Given multiple tasks in the Ready state and of the same priority, vanilla
|
Given multiple tasks in the Ready state and of the same priority, vanilla
|
||||||
FreeRTOS implements Round Robin scheduling between each task. This will result
|
FreeRTOS implements Round Robin scheduling between each task. This will result
|
||||||
in running those tasks in turn each time the scheduler is called
|
in running those tasks in turn each time the scheduler is called
|
||||||
(e.g. every tick interrupt). On the other hand, the ESP-IDF FreeRTOS scheduler
|
(e.g. every tick interrupt). On the other hand, the ESP-IDF FreeRTOS scheduler
|
||||||
may skip tasks when Round Robin scheduling multiple Ready state tasks of the
|
may skip tasks when Round Robin scheduling multiple Ready state tasks of the
|
||||||
same priority.
|
same priority.
|
||||||
|
|
||||||
The issue of skipping tasks during Round Robin scheduling arises from the way
|
The issue of skipping tasks during Round Robin scheduling arises from the way
|
||||||
the Ready Tasks List is implemented in FreeRTOS. In vanilla FreeRTOS,
|
the Ready Tasks List is implemented in FreeRTOS. In vanilla FreeRTOS,
|
||||||
``pxReadyTasksList`` is used to store a list of tasks that are in the Ready
|
``pxReadyTasksList`` is used to store a list of tasks that are in the Ready
|
||||||
state. The list is implemented as an array of length ``configMAX_PRIORITIES``
|
state. The list is implemented as an array of length ``configMAX_PRIORITIES``
|
||||||
where each element of the array is a linked list. Each linked list is of type
|
where each element of the array is a linked list. Each linked list is of type
|
||||||
``List_t`` and contains TCBs of tasks of the same priority that are in the
|
``List_t`` and contains TCBs of tasks of the same priority that are in the
|
||||||
Ready state. The following diagram illustrates the ``pxReadyTasksList``
|
Ready state. The following diagram illustrates the ``pxReadyTasksList``
|
||||||
structure.
|
structure.
|
||||||
|
|
||||||
.. figure:: ../../_static/freertos-ready-task-list.png
|
.. figure:: ../../_static/freertos-ready-task-list.png
|
||||||
:align: center
|
:align: center
|
||||||
:alt: Vanilla FreeRTOS Ready Task List Structure
|
:alt: Vanilla FreeRTOS Ready Task List Structure
|
||||||
|
|
||||||
Illustration of FreeRTOS Ready Task List Data Structure
|
Illustration of FreeRTOS Ready Task List Data Structure
|
||||||
|
|
||||||
|
|
||||||
Each linked list also contains a ``pxIndex`` which points to the last TCB
|
Each linked list also contains a ``pxIndex`` which points to the last TCB
|
||||||
returned when the list was queried. This index allows the ``vTaskSwitchContext()``
|
returned when the list was queried. This index allows the ``vTaskSwitchContext()``
|
||||||
to start traversing the list at the TCB immediately after ``pxIndex`` hence
|
to start traversing the list at the TCB immediately after ``pxIndex`` hence
|
||||||
implementing Round Robin Scheduling between tasks of the same priority.
|
implementing Round Robin Scheduling between tasks of the same priority.
|
||||||
|
|
||||||
In ESP-IDF FreeRTOS, the Ready Tasks List is shared between cores hence
|
In ESP-IDF FreeRTOS, the Ready Tasks List is shared between cores hence
|
||||||
``pxReadyTasksList`` will contain tasks pinned to different cores. When a core
|
``pxReadyTasksList`` will contain tasks pinned to different cores. When a core
|
||||||
calls the scheduler, it is able to look at the ``xCoreID`` member of each TCB
|
calls the scheduler, it is able to look at the ``xCoreID`` member of each TCB
|
||||||
in the list to determine if a task is allowed to run on calling the core. The
|
in the list to determine if a task is allowed to run on calling the core. The
|
||||||
ESP-IDF FreeRTOS ``pxReadyTasksList`` is illustrated below.
|
ESP-IDF FreeRTOS ``pxReadyTasksList`` is illustrated below.
|
||||||
|
|
||||||
.. figure:: ../../_static/freertos-ready-task-list-smp.png
|
.. figure:: ../../_static/freertos-ready-task-list-smp.png
|
||||||
:align: center
|
:align: center
|
||||||
:alt: ESP-IDF FreeRTOS Ready Task List Structure
|
:alt: ESP-IDF FreeRTOS Ready Task List Structure
|
||||||
|
|
||||||
Illustration of FreeRTOS Ready Task List Data Structure in ESP-IDF
|
Illustration of FreeRTOS Ready Task List Data Structure in ESP-IDF
|
||||||
|
|
||||||
Therefore when **PRO_CPU** calls the scheduler, it will only consider the tasks
|
Therefore when **PRO_CPU** calls the scheduler, it will only consider the tasks
|
||||||
in blue or purple. Whereas when **APP_CPU** calls the scheduler, it will only
|
in blue or purple. Whereas when **APP_CPU** calls the scheduler, it will only
|
||||||
consider the tasks in orange or purple.
|
consider the tasks in orange or purple.
|
||||||
|
|
||||||
Although each TCB has an ``xCoreID`` in ESP-IDF FreeRTOS, the linked list of
|
Although each TCB has an ``xCoreID`` in ESP-IDF FreeRTOS, the linked list of
|
||||||
each priority only has a single ``pxIndex``. Therefore when the scheduler is
|
each priority only has a single ``pxIndex``. Therefore when the scheduler is
|
||||||
called from a particular core and traverses the linked list, it will skip all
|
called from a particular core and traverses the linked list, it will skip all
|
||||||
TCBs pinned to the other core and point the pxIndex at the selected task. If
|
TCBs pinned to the other core and point the pxIndex at the selected task. If
|
||||||
the other core then calls the scheduler, it will traverse the linked list
|
the other core then calls the scheduler, it will traverse the linked list
|
||||||
starting at the TCB immediately after ``pxIndex``. Therefore, TCBs skipped on
|
starting at the TCB immediately after ``pxIndex``. Therefore, TCBs skipped on
|
||||||
the previous scheduler call from the other core would not be considered on the
|
the previous scheduler call from the other core would not be considered on the
|
||||||
current scheduler call. This issue is demonstrated in the following
|
current scheduler call. This issue is demonstrated in the following
|
||||||
illustration.
|
illustration.
|
||||||
|
|
||||||
.. figure:: ../../_static/freertos-ready-task-list-smp-pxIndex.png
|
.. figure:: ../../_static/freertos-ready-task-list-smp-pxIndex.png
|
||||||
:align: center
|
:align: center
|
||||||
:alt: ESP-IDF pxIndex Behavior
|
:alt: ESP-IDF pxIndex Behavior
|
||||||
|
|
||||||
Illustration of pxIndex behavior in ESP-IDF FreeRTOS
|
Illustration of pxIndex behavior in ESP-IDF FreeRTOS
|
||||||
|
|
||||||
Referring to the illustration above, assume that priority 9 is the highest
|
Referring to the illustration above, assume that priority 9 is the highest
|
||||||
priority, and none of the tasks in priority 9 will block hence will always be
|
priority, and none of the tasks in priority 9 will block hence will always be
|
||||||
either in the running or Ready state.
|
either in the running or Ready state.
|
||||||
|
|
||||||
1) **PRO_CPU** calls the scheduler and selects Task A to run, hence moves
|
1) **PRO_CPU** calls the scheduler and selects Task A to run, hence moves
|
||||||
``pxIndex`` to point to Task A
|
``pxIndex`` to point to Task A
|
||||||
|
|
||||||
2) **APP_CPU** calls the scheduler and starts traversing from the task after
|
2) **APP_CPU** calls the scheduler and starts traversing from the task after
|
||||||
``pxIndex`` which is Task B. However Task B is not selected to run as it is not
|
``pxIndex`` which is Task B. However Task B is not selected to run as it is not
|
||||||
pinned to **APP_CPU** hence it is skipped and Task C is selected instead.
|
pinned to **APP_CPU** hence it is skipped and Task C is selected instead.
|
||||||
``pxIndex`` now points to Task C
|
``pxIndex`` now points to Task C
|
||||||
|
|
||||||
3) **PRO_CPU** calls the scheduler and starts traversing from Task D. It skips
|
3) **PRO_CPU** calls the scheduler and starts traversing from Task D. It skips
|
||||||
Task D and selects Task E to run and points ``pxIndex`` to Task E. Notice that
|
Task D and selects Task E to run and points ``pxIndex`` to Task E. Notice that
|
||||||
Task B isn’t traversed because it was skipped the last time **APP_CPU** called
|
Task B isn’t traversed because it was skipped the last time **APP_CPU** called
|
||||||
the scheduler to traverse the list.
|
the scheduler to traverse the list.
|
||||||
|
|
||||||
4) The same situation with Task D will occur if **APP_CPU** calls the
|
4) The same situation with Task D will occur if **APP_CPU** calls the
|
||||||
scheduler again as ``pxIndex`` now points to Task E
|
scheduler again as ``pxIndex`` now points to Task E
|
||||||
|
|
||||||
One solution to the issue of task skipping is to ensure that every task will
|
One solution to the issue of task skipping is to ensure that every task will
|
||||||
enter a blocked state so that they are removed from the Ready Task List.
|
enter a blocked state so that they are removed from the Ready Task List.
|
||||||
Another solution is to distribute tasks across multiple priorities such that
|
Another solution is to distribute tasks across multiple priorities such that
|
||||||
a given priority will not be assigned multiple tasks that are pinned to
|
a given priority will not be assigned multiple tasks that are pinned to
|
||||||
different cores.
|
different cores.
|
||||||
|
|
||||||
.. _scheduler-suspension:
|
.. _scheduler-suspension:
|
||||||
@@ -289,22 +289,22 @@ different cores.
|
|||||||
Scheduler Suspension
|
Scheduler Suspension
|
||||||
^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
In vanilla FreeRTOS, suspending the scheduler via :cpp:func:`vTaskSuspendAll` will
|
In vanilla FreeRTOS, suspending the scheduler via :cpp:func:`vTaskSuspendAll` will
|
||||||
prevent calls of ``vTaskSwitchContext`` from context switching until the
|
prevent calls of ``vTaskSwitchContext`` from context switching until the
|
||||||
scheduler has been resumed with :cpp:func:`xTaskResumeAll`. However servicing ISRs
|
scheduler has been resumed with :cpp:func:`xTaskResumeAll`. However servicing ISRs
|
||||||
are still permitted. Therefore any changes in task states as a result from the
|
are still permitted. Therefore any changes in task states as a result from the
|
||||||
current running task or ISRSs will not be executed until the scheduler is
|
current running task or ISRSs will not be executed until the scheduler is
|
||||||
resumed. Scheduler suspension in vanilla FreeRTOS is a common protection method
|
resumed. Scheduler suspension in vanilla FreeRTOS is a common protection method
|
||||||
against simultaneous access of data shared between tasks, whilst still allowing
|
against simultaneous access of data shared between tasks, whilst still allowing
|
||||||
ISRs to be serviced.
|
ISRs to be serviced.
|
||||||
|
|
||||||
In ESP-IDF FreeRTOS, :cpp:func:`xTaskSuspendAll` will only prevent calls of
|
In ESP-IDF FreeRTOS, :cpp:func:`xTaskSuspendAll` will only prevent calls of
|
||||||
``vTaskSwitchContext()`` from switching contexts on the core that called for the
|
``vTaskSwitchContext()`` from switching contexts on the core that called for the
|
||||||
suspension. Hence if **PRO_CPU** calls :cpp:func:`vTaskSuspendAll`, **APP_CPU** will
|
suspension. Hence if **PRO_CPU** calls :cpp:func:`vTaskSuspendAll`, **APP_CPU** will
|
||||||
still be able to switch contexts. If data is shared between tasks that are
|
still be able to switch contexts. If data is shared between tasks that are
|
||||||
pinned to different cores, scheduler suspension is **NOT** a valid method of
|
pinned to different cores, scheduler suspension is **NOT** a valid method of
|
||||||
protection against simultaneous access. Consider using critical sections
|
protection against simultaneous access. Consider using critical sections
|
||||||
(disables interrupts) or semaphores (does not disable interrupts) instead when
|
(disables interrupts) or semaphores (does not disable interrupts) instead when
|
||||||
protecting shared resources in ESP-IDF FreeRTOS.
|
protecting shared resources in ESP-IDF FreeRTOS.
|
||||||
|
|
||||||
In general, it's better to use other RTOS primitives like mutex semaphores to protect
|
In general, it's better to use other RTOS primitives like mutex semaphores to protect
|
||||||
@@ -313,34 +313,34 @@ against data shared between tasks, rather than :cpp:func:`vTaskSuspendAll`.
|
|||||||
|
|
||||||
.. _tick-interrupt-synchronicity:
|
.. _tick-interrupt-synchronicity:
|
||||||
|
|
||||||
Tick Interrupt Synchronicity
|
Tick Interrupt Synchronicity
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
In ESP-IDF FreeRTOS, tasks on different cores that unblock on the same tick
|
In ESP-IDF FreeRTOS, tasks on different cores that unblock on the same tick
|
||||||
count might not run at exactly the same time due to the scheduler calls from
|
count might not run at exactly the same time due to the scheduler calls from
|
||||||
each core being independent, and the tick interrupts to each core being
|
each core being independent, and the tick interrupts to each core being
|
||||||
unsynchronized.
|
unsynchronized.
|
||||||
|
|
||||||
In vanilla FreeRTOS the tick interrupt triggers a call to
|
In vanilla FreeRTOS the tick interrupt triggers a call to
|
||||||
:cpp:func:`xTaskIncrementTick` which is responsible for incrementing the tick
|
:cpp:func:`xTaskIncrementTick` which is responsible for incrementing the tick
|
||||||
counter, checking if tasks which have called :cpp:func:`vTaskDelay` have fulfilled
|
counter, checking if tasks which have called :cpp:func:`vTaskDelay` have fulfilled
|
||||||
their delay period, and moving those tasks from the Delayed Task List to the
|
their delay period, and moving those tasks from the Delayed Task List to the
|
||||||
Ready Task List. The tick interrupt will then call the scheduler if a context
|
Ready Task List. The tick interrupt will then call the scheduler if a context
|
||||||
switch is necessary.
|
switch is necessary.
|
||||||
|
|
||||||
In ESP-IDF FreeRTOS, delayed tasks are unblocked with reference to the tick
|
In ESP-IDF FreeRTOS, delayed tasks are unblocked with reference to the tick
|
||||||
interrupt on PRO_CPU as PRO_CPU is responsible for incrementing the shared tick
|
interrupt on PRO_CPU as PRO_CPU is responsible for incrementing the shared tick
|
||||||
count. However tick interrupts to each core might not be synchronized (same
|
count. However tick interrupts to each core might not be synchronized (same
|
||||||
frequency but out of phase) hence when PRO_CPU receives a tick interrupt,
|
frequency but out of phase) hence when PRO_CPU receives a tick interrupt,
|
||||||
APP_CPU might not have received it yet. Therefore if multiple tasks of the same
|
APP_CPU might not have received it yet. Therefore if multiple tasks of the same
|
||||||
priority are unblocked on the same tick count, the task pinned to PRO_CPU will
|
priority are unblocked on the same tick count, the task pinned to PRO_CPU will
|
||||||
run immediately whereas the task pinned to APP_CPU must wait until APP_CPU
|
run immediately whereas the task pinned to APP_CPU must wait until APP_CPU
|
||||||
receives its out of sync tick interrupt. Upon receiving the tick interrupt,
|
receives its out of sync tick interrupt. Upon receiving the tick interrupt,
|
||||||
APP_CPU will then call for a context switch and finally switches contexts to
|
APP_CPU will then call for a context switch and finally switches contexts to
|
||||||
the newly unblocked task.
|
the newly unblocked task.
|
||||||
|
|
||||||
Therefore, task delays should **NOT** be used as a method of synchronization
|
Therefore, task delays should **NOT** be used as a method of synchronization
|
||||||
between tasks in ESP-IDF FreeRTOS. Instead, consider using a counting semaphore
|
between tasks in ESP-IDF FreeRTOS. Instead, consider using a counting semaphore
|
||||||
to unblock multiple tasks at the same time.
|
to unblock multiple tasks at the same time.
|
||||||
|
|
||||||
|
|
||||||
@@ -349,47 +349,47 @@ to unblock multiple tasks at the same time.
|
|||||||
Critical Sections & Disabling Interrupts
|
Critical Sections & Disabling Interrupts
|
||||||
----------------------------------------
|
----------------------------------------
|
||||||
|
|
||||||
Vanilla FreeRTOS implements critical sections in ``vTaskEnterCritical`` which
|
Vanilla FreeRTOS implements critical sections in ``vTaskEnterCritical`` which
|
||||||
disables the scheduler and calls ``portDISABLE_INTERRUPTS``. This prevents
|
disables the scheduler and calls ``portDISABLE_INTERRUPTS``. This prevents
|
||||||
context switches and servicing of ISRs during a critical section. Therefore,
|
context switches and servicing of ISRs during a critical section. Therefore,
|
||||||
critical sections are used as a valid protection method against simultaneous
|
critical sections are used as a valid protection method against simultaneous
|
||||||
access in vanilla FreeRTOS.
|
access in vanilla FreeRTOS.
|
||||||
|
|
||||||
.. only:: esp32
|
.. only:: not CONFIG_FREERTOS_UNICORE
|
||||||
|
|
||||||
On the other hand, the ESP32 has no hardware method for cores to disable each
|
On the other hand, the ESP32 has no hardware method for cores to disable each
|
||||||
other’s interrupts. Calling ``portDISABLE_INTERRUPTS()`` will have no effect on
|
other’s interrupts. Calling ``portDISABLE_INTERRUPTS()`` will have no effect on
|
||||||
the interrupts of the other core. Therefore, disabling interrupts is **NOT**
|
the interrupts of the other core. Therefore, disabling interrupts is **NOT**
|
||||||
a valid protection method against simultaneous access to shared data as it
|
a valid protection method against simultaneous access to shared data as it
|
||||||
leaves the other core free to access the data even if the current core has
|
leaves the other core free to access the data even if the current core has
|
||||||
disabled its own interrupts.
|
disabled its own interrupts.
|
||||||
|
|
||||||
.. only:: esp32s2
|
.. only:: CONFIG_FREERTOS_UNICORE
|
||||||
|
|
||||||
ESP-IDF contains some modifications to work with dual core concurrency,
|
ESP-IDF contains some modifications to work with dual core concurrency,
|
||||||
and the dual core API is used even on a single core only chip.
|
and the dual core API is used even on a single core only chip.
|
||||||
|
|
||||||
For this reason, ESP-IDF FreeRTOS implements critical sections using special mutexes,
|
For this reason, ESP-IDF FreeRTOS implements critical sections using special mutexes,
|
||||||
referred by portMUX_Type objects on top of specific spinlock component
|
referred by portMUX_Type objects on top of specific spinlock component
|
||||||
and calls to enter or exit a critical must provide a spinlock object that
|
and calls to enter or exit a critical must provide a spinlock object that
|
||||||
is associated with a shared resource requiring access protection.
|
is associated with a shared resource requiring access protection.
|
||||||
When entering a critical section in ESP-IDF FreeRTOS, the calling core will disable
|
When entering a critical section in ESP-IDF FreeRTOS, the calling core will disable
|
||||||
its scheduler and interrupts similar to the vanilla FreeRTOS implementation. However,
|
its scheduler and interrupts similar to the vanilla FreeRTOS implementation. However,
|
||||||
the calling core will also take the locks whilst the other core is left unaffected during
|
the calling core will also take the locks whilst the other core is left unaffected during
|
||||||
the critical section. If the other core attempts to take the spinlock, it
|
the critical section. If the other core attempts to take the spinlock, it
|
||||||
will spin until the lock is released. Therefore, the ESP-IDF FreeRTOS
|
will spin until the lock is released. Therefore, the ESP-IDF FreeRTOS
|
||||||
implementation of critical sections allows a core to have protected access to a
|
implementation of critical sections allows a core to have protected access to a
|
||||||
shared resource without disabling the other core. The other core will only be
|
shared resource without disabling the other core. The other core will only be
|
||||||
affected if it tries to concurrently access the same resource.
|
affected if it tries to concurrently access the same resource.
|
||||||
|
|
||||||
The ESP-IDF FreeRTOS critical section functions have been modified as follows…
|
The ESP-IDF FreeRTOS critical section functions have been modified as follows…
|
||||||
|
|
||||||
- ``taskENTER_CRITICAL(mux)``, ``taskENTER_CRITICAL_ISR(mux)``,
|
- ``taskENTER_CRITICAL(mux)``, ``taskENTER_CRITICAL_ISR(mux)``,
|
||||||
``portENTER_CRITICAL(mux)``, ``portENTER_CRITICAL_ISR(mux)`` are all macro
|
``portENTER_CRITICAL(mux)``, ``portENTER_CRITICAL_ISR(mux)`` are all macro
|
||||||
defined to call :cpp:func:`vTaskEnterCritical`
|
defined to call :cpp:func:`vTaskEnterCritical`
|
||||||
|
|
||||||
- ``taskEXIT_CRITICAL(mux)``, ``taskEXIT_CRITICAL_ISR(mux)``,
|
- ``taskEXIT_CRITICAL(mux)``, ``taskEXIT_CRITICAL_ISR(mux)``,
|
||||||
``portEXIT_CRITICAL(mux)``, ``portEXIT_CRITICAL_ISR(mux)`` are all macro
|
``portEXIT_CRITICAL(mux)``, ``portEXIT_CRITICAL_ISR(mux)`` are all macro
|
||||||
defined to call :cpp:func:`vTaskExitCritical`
|
defined to call :cpp:func:`vTaskExitCritical`
|
||||||
|
|
||||||
- ``portENTER_CRITICAL_SAFE(mux)``, ``portEXIT_CRITICAL_SAFE(mux)`` macro identifies
|
- ``portENTER_CRITICAL_SAFE(mux)``, ``portEXIT_CRITICAL_SAFE(mux)`` macro identifies
|
||||||
@@ -400,14 +400,14 @@ The ESP-IDF FreeRTOS critical section functions have been modified as follows…
|
|||||||
For more details see :component_file:`soc/include/soc/spinlock.h`
|
For more details see :component_file:`soc/include/soc/spinlock.h`
|
||||||
and :component_file:`freertos/tasks.c`
|
and :component_file:`freertos/tasks.c`
|
||||||
|
|
||||||
It should be noted that when modifying vanilla FreeRTOS code to be ESP-IDF
|
It should be noted that when modifying vanilla FreeRTOS code to be ESP-IDF
|
||||||
FreeRTOS compatible, it is trivial to modify the type of critical section
|
FreeRTOS compatible, it is trivial to modify the type of critical section
|
||||||
called as they are all defined to call the same function. As long as the same
|
called as they are all defined to call the same function. As long as the same
|
||||||
spinlock is provided upon entering and exiting, the type of call should not
|
spinlock is provided upon entering and exiting, the type of call should not
|
||||||
matter.
|
matter.
|
||||||
|
|
||||||
|
|
||||||
.. only:: esp32
|
.. only:: not CONFIG_FREERTOS_UNICORE
|
||||||
|
|
||||||
.. _floating-points:
|
.. _floating-points:
|
||||||
|
|
||||||
@@ -415,16 +415,16 @@ matter.
|
|||||||
-------------------------
|
-------------------------
|
||||||
|
|
||||||
ESP-IDF FreeRTOS implements Lazy Context Switching for FPUs. In other words,
|
ESP-IDF FreeRTOS implements Lazy Context Switching for FPUs. In other words,
|
||||||
the state of a core's FPU registers are not immediately saved when a context
|
the state of a core's FPU registers are not immediately saved when a context
|
||||||
switch occurs. Therefore, tasks that utilize ``float`` must be pinned to a
|
switch occurs. Therefore, tasks that utilize ``float`` must be pinned to a
|
||||||
particular core upon creation. If not, ESP-IDF FreeRTOS will automatically pin
|
particular core upon creation. If not, ESP-IDF FreeRTOS will automatically pin
|
||||||
the task in question to whichever core the task was running on upon the task's
|
the task in question to whichever core the task was running on upon the task's
|
||||||
first use of ``float``. Likewise due to Lazy Context Switching, only interrupt
|
first use of ``float``. Likewise due to Lazy Context Switching, only interrupt
|
||||||
service routines of lowest priority (that is it the Level 1) can use ``float``,
|
service routines of lowest priority (that is it the Level 1) can use ``float``,
|
||||||
higher priority interrupts do not support FPU usage.
|
higher priority interrupts do not support FPU usage.
|
||||||
|
|
||||||
ESP32 does not support hardware acceleration for double precision floating point
|
ESP32 does not support hardware acceleration for double precision floating point
|
||||||
arithmetic (``double``). Instead ``double`` is implemented via software hence the
|
arithmetic (``double``). Instead ``double`` is implemented via software hence the
|
||||||
behavioral restrictions with regards to ``float`` do not apply to ``double``. Note
|
behavioral restrictions with regards to ``float`` do not apply to ``double``. Note
|
||||||
that due to the lack of hardware acceleration, ``double`` operations may consume
|
that due to the lack of hardware acceleration, ``double`` operations may consume
|
||||||
significantly larger amount of CPU time in comparison to ``float``.
|
significantly larger amount of CPU time in comparison to ``float``.
|
||||||
@@ -495,7 +495,7 @@ The ESP-IDF FreeRTOS can be configured in the project configuration menu
|
|||||||
highlights some of the ESP-IDF FreeRTOS configuration options. For a full list of
|
highlights some of the ESP-IDF FreeRTOS configuration options. For a full list of
|
||||||
ESP-IDF FreeRTOS configurations, see :doc:`FreeRTOS <../api-reference/kconfig>`
|
ESP-IDF FreeRTOS configurations, see :doc:`FreeRTOS <../api-reference/kconfig>`
|
||||||
|
|
||||||
.. only:: esp32
|
.. only:: not CONFIG_FREERTOS_UNICORE
|
||||||
|
|
||||||
:ref:`CONFIG_FREERTOS_UNICORE` will run ESP-IDF FreeRTOS only
|
:ref:`CONFIG_FREERTOS_UNICORE` will run ESP-IDF FreeRTOS only
|
||||||
on **PRO_CPU**. Note that this is **not equivalent to running vanilla
|
on **PRO_CPU**. Note that this is **not equivalent to running vanilla
|
||||||
@@ -504,9 +504,9 @@ ESP-IDF FreeRTOS configurations, see :doc:`FreeRTOS <../api-reference/kconfig>`
|
|||||||
effects of running ESP-IDF FreeRTOS on a single core, search for
|
effects of running ESP-IDF FreeRTOS on a single core, search for
|
||||||
occurences of ``CONFIG_FREERTOS_UNICORE`` in the ESP-IDF components.
|
occurences of ``CONFIG_FREERTOS_UNICORE`` in the ESP-IDF components.
|
||||||
|
|
||||||
.. only:: esp32s2
|
.. only:: CONFIG_FREERTOS_UNICORE
|
||||||
|
|
||||||
As ESP32-S2 is a single core SoC, the config item :ref:`CONFIG_FREERTOS_UNICORE` is
|
As {IDF_TARGET_NAME} is a single core SoC, the config item :ref:`CONFIG_FREERTOS_UNICORE` is
|
||||||
always set. This means ESP-IDF only runs on the single CPU. Note that this is **not
|
always set. This means ESP-IDF only runs on the single CPU. Note that this is **not
|
||||||
equivalent to running vanilla FreeRTOS**. Behaviors of multiple components in ESP-IDF
|
equivalent to running vanilla FreeRTOS**. Behaviors of multiple components in ESP-IDF
|
||||||
will be modified. For more details regarding the effects of running ESP-IDF FreeRTOS
|
will be modified. For more details regarding the effects of running ESP-IDF FreeRTOS
|
||||||
|
@@ -6,14 +6,14 @@ API Guides
|
|||||||
:maxdepth: 1
|
:maxdepth: 1
|
||||||
|
|
||||||
Application Level Tracing <app_trace>
|
Application Level Tracing <app_trace>
|
||||||
:esp32: BluFi <blufi>
|
:SOC_BT_SUPPORTED: BluFi <blufi>
|
||||||
Bootloader <bootloader>
|
Bootloader <bootloader>
|
||||||
Build System <build-system>
|
Build System <build-system>
|
||||||
:esp32: Build System (Legacy GNU Make) <build-system-legacy>
|
:esp32: Build System (Legacy GNU Make) <build-system-legacy>
|
||||||
Deep Sleep Wake Stubs <deep-sleep-stub>
|
Deep Sleep Wake Stubs <deep-sleep-stub>
|
||||||
:esp32s2: Device Firmware Upgrade through USB <dfu>
|
:esp32s2: Device Firmware Upgrade through USB <dfu>
|
||||||
Error Handling <error-handling>
|
Error Handling <error-handling>
|
||||||
:esp32: ESP-BLE-MESH <esp-ble-mesh/ble-mesh-index>
|
:SOC_BT_SUPPORTED: ESP-BLE-MESH <esp-ble-mesh/ble-mesh-index>
|
||||||
ESP-MESH (Wi-Fi) <mesh>
|
ESP-MESH (Wi-Fi) <mesh>
|
||||||
Core Dump <core_dump>
|
Core Dump <core_dump>
|
||||||
Event Handling <event-handling>
|
Event Handling <event-handling>
|
||||||
|
@@ -6,7 +6,7 @@ API Reference
|
|||||||
.. toctree::
|
.. toctree::
|
||||||
:maxdepth: 2
|
:maxdepth: 2
|
||||||
|
|
||||||
:esp32: Bluetooth <bluetooth/index>
|
:SOC_BT_SUPPORTED: Bluetooth <bluetooth/index>
|
||||||
Networking <network/index>
|
Networking <network/index>
|
||||||
Peripherals <peripherals/index>
|
Peripherals <peripherals/index>
|
||||||
Protocols <protocols/index>
|
Protocols <protocols/index>
|
||||||
|
@@ -15,13 +15,13 @@ Peripherals API
|
|||||||
I2C <i2c>
|
I2C <i2c>
|
||||||
I2S <i2s>
|
I2S <i2s>
|
||||||
LED Control <ledc>
|
LED Control <ledc>
|
||||||
:esp32: MCPWM <mcpwm>
|
:SOC_MCPWM_SUPPORTED: MCPWM <mcpwm>
|
||||||
Pulse Counter <pcnt>
|
Pulse Counter <pcnt>
|
||||||
Remote Control <rmt>
|
Remote Control <rmt>
|
||||||
:esp32: SD Pull-up Requirements <sd_pullup_requirements>
|
:esp32: SD Pull-up Requirements <sd_pullup_requirements>
|
||||||
:esp32: SDMMC Host <sdmmc_host>
|
:SOC_SDMMC_HOST_SUPPORTED: SDMMC Host <sdmmc_host>
|
||||||
SD SPI Host <sdspi_host>
|
SD SPI Host <sdspi_host>
|
||||||
:esp32: SDIO Slave <sdio_slave>
|
:SOC_SDIO_SLAVE_SUPPORTED: SDIO Slave <sdio_slave>
|
||||||
Sigma-delta Modulation <sigmadelta>
|
Sigma-delta Modulation <sigmadelta>
|
||||||
SPI Master <spi_master>
|
SPI Master <spi_master>
|
||||||
SPI Slave <spi_slave>
|
SPI Slave <spi_slave>
|
||||||
|
@@ -18,5 +18,3 @@ copyright = u'2016 - 2020, Espressif Systems (Shanghai) CO., LTD'
|
|||||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||||
# for a list of supported languages.
|
# for a list of supported languages.
|
||||||
language = 'en'
|
language = 'en'
|
||||||
|
|
||||||
update_exclude_patterns(tags) # noqa: F405, need to import * from conf_common
|
|
||||||
|
@@ -128,15 +128,6 @@ Other Extensions
|
|||||||
:idf_file:`docs/idf_extensions/link_roles.py`
|
:idf_file:`docs/idf_extensions/link_roles.py`
|
||||||
This is an implementation of a custom `Sphinx Roles <https://www.sphinx-doc.org/en/master/usage/restructuredtext/roles.html>`_ to help linking from documentation to specific files and folders in `ESP-IDF`_. For description of implemented roles please see :ref:`link-custom-roles` and :ref:`link-language-versions`.
|
This is an implementation of a custom `Sphinx Roles <https://www.sphinx-doc.org/en/master/usage/restructuredtext/roles.html>`_ to help linking from documentation to specific files and folders in `ESP-IDF`_. For description of implemented roles please see :ref:`link-custom-roles` and :ref:`link-language-versions`.
|
||||||
|
|
||||||
:idf_file:`docs/idf_extensions/run_doxygen.py`
|
|
||||||
Subscribes to ``idf-info`` event and runs Doxygen (:idf_file:`docs/Doxyfile`) to generate XML files describing key headers, and then runs Breathe to convert these to ``.inc`` files which can be included directly into API reference pages.
|
|
||||||
|
|
||||||
Pushes a number of target-specific custom environment variables into Doxygen, including all macros defined in the project's default ``sdkconfig.h`` file and all macros defined in all ``soc`` component ``xxx_caps.h`` headers. This means that public API headers can depend on target-specific configuration options or ``soc`` capabilities headers options as ``#ifdef`` & ``#if`` preprocessor selections in the header.
|
|
||||||
|
|
||||||
This means we can generate different Doxygen files, depending on the target we are building docs for.
|
|
||||||
|
|
||||||
Please refer to :doc:`documenting-code` and :doc:`../api-reference/template`, section **API Reference** for additional details on this process.
|
|
||||||
|
|
||||||
:idf_file:`docs/idf_extensions/esp_err_definitions.py`
|
:idf_file:`docs/idf_extensions/esp_err_definitions.py`
|
||||||
Small wrapper extension that calls ``gen_esp_err_to_name.py`` and updates the included .rst file if it has changed.
|
Small wrapper extension that calls ``gen_esp_err_to_name.py`` and updates the included .rst file if it has changed.
|
||||||
|
|
||||||
@@ -166,6 +157,27 @@ Other Extensions
|
|||||||
|
|
||||||
Creates and adds the espidf.sty latex package to the output directory, which contains some macros for run-time variables such as IDF-Target.
|
Creates and adds the espidf.sty latex package to the output directory, which contains some macros for run-time variables such as IDF-Target.
|
||||||
|
|
||||||
|
:idf_file:`docs/idf_extensions/gen_defines.py`
|
||||||
|
Sphinx extension to integrate defines from IDF into the Sphinx build, runs after the IDF dummy project has been built.
|
||||||
|
|
||||||
|
Parses defines and adds them as sphinx tags.
|
||||||
|
|
||||||
|
Emits the new 'idf-defines-generated' event which has a dictionary of raw text define values that other extensions can use to generate relevant data.
|
||||||
|
|
||||||
|
:idf_file:`docs/idf_extensions/exclude_docs.py`
|
||||||
|
Sphinx extension that updates the excluded documents according to the conditional_include_dict {tag:documents}. If the tag is set, then the list of documents will be included.
|
||||||
|
|
||||||
|
Subscribes to ``idf-defines-generated`` as it relies on the sphinx tags to determine which documents to exclude
|
||||||
|
|
||||||
|
:idf_file:`docs/idf_extensions/run_doxygen.py`
|
||||||
|
Subscribes to ``idf-defines-generated`` event and runs Doxygen (:idf_file:`docs/Doxyfile`) to generate XML files describing key headers, and then runs Breathe to convert these to ``.inc`` files which can be included directly into API reference pages.
|
||||||
|
|
||||||
|
Pushes a number of target-specific custom environment variables into Doxygen, including all macros defined in the project's default ``sdkconfig.h`` file and all macros defined in all ``soc`` component ``xxx_caps.h`` headers. This means that public API headers can depend on target-specific configuration options or ``soc`` capabilities headers options as ``#ifdef`` & ``#if`` preprocessor selections in the header.
|
||||||
|
|
||||||
|
This means we can generate different Doxygen files, depending on the target we are building docs for.
|
||||||
|
|
||||||
|
Please refer to :doc:`documenting-code` and :doc:`../api-reference/template`, section **API Reference** for additional details on this process.
|
||||||
|
|
||||||
Related Documents
|
Related Documents
|
||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
|
@@ -252,11 +252,22 @@ The documentation for all of Espressif's chips is built from the same files. To
|
|||||||
|
|
||||||
Exclusion of content based on chip-target
|
Exclusion of content based on chip-target
|
||||||
"""""""""""""""""""""""""""""""""""""""""
|
"""""""""""""""""""""""""""""""""""""""""
|
||||||
Occasionally there will be content that is only relevant for one of targets. When this is the case, you can exclude that content by using the ''.. only:: TARGET'' directive, where you replace 'TARGET' with one of the chip names. As of now the following targets are available:
|
Occasionally there will be content that is only relevant for one of targets. When this is the case, you can exclude that content by using the ''.. only:: TAG'' directive, where you replace 'TAG' with one of the following names:
|
||||||
|
|
||||||
|
Chip name:
|
||||||
|
|
||||||
* esp32
|
* esp32
|
||||||
* esp32s2
|
* esp32s2
|
||||||
|
|
||||||
|
Define identifiers from 'sdkconfig.h', generated by the default menuconfig settings for the target, e.g:
|
||||||
|
|
||||||
|
* CONFIG_FREERTOS_UNICORE
|
||||||
|
|
||||||
|
Define identifiers from the soc '*_caps' headers, e.g:
|
||||||
|
|
||||||
|
* SOC_BT_SUPPORTED
|
||||||
|
* SOC_CAN_SUPPORTED
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
.. code-block:: none
|
.. code-block:: none
|
||||||
@@ -265,6 +276,14 @@ Example:
|
|||||||
|
|
||||||
ESP32 specific content.
|
ESP32 specific content.
|
||||||
|
|
||||||
|
This directive also supports the boolean operators 'and', 'or' and 'not'. Example:
|
||||||
|
|
||||||
|
.. code-block:: none
|
||||||
|
|
||||||
|
.. only:: SOC_BT_SUPPORTED and CONFIG_FREERTOS_UNICORE
|
||||||
|
|
||||||
|
BT specific content only relevant for single-core targets.
|
||||||
|
|
||||||
This functionality is provided by the `Sphinx selective exclude <https://github.com/pfalcon/sphinx_selective_exclude>`_ extension.
|
This functionality is provided by the `Sphinx selective exclude <https://github.com/pfalcon/sphinx_selective_exclude>`_ extension.
|
||||||
|
|
||||||
A weakness in this extension is that it does not correctly handle the case were you exclude a section, and that is directly followed by a labeled new section. In these cases everything will render correctly, but the label will not correctly link to the section that follows. A temporary work-around for the cases were this can't be avoided is the following:
|
A weakness in this extension is that it does not correctly handle the case were you exclude a section, and that is directly followed by a labeled new section. In these cases everything will render correctly, but the label will not correctly link to the section that follows. A temporary work-around for the cases were this can't be avoided is the following:
|
||||||
@@ -290,7 +309,7 @@ A weakness in this extension is that it does not correctly handle the case were
|
|||||||
^^^^^^^^^
|
^^^^^^^^^
|
||||||
Section 2 content
|
Section 2 content
|
||||||
|
|
||||||
The :TARGET: role is used for excluding content from a table of content tree. For example:
|
The :TAG: role is used for excluding content from a table of content tree. For example:
|
||||||
|
|
||||||
.. code-block:: none
|
.. code-block:: none
|
||||||
|
|
||||||
@@ -302,16 +321,20 @@ The :TARGET: role is used for excluding content from a table of content tree. Fo
|
|||||||
|
|
||||||
When building the documents, Sphinx will use the above mentioned directive and role to include or exclude content based on the target tag it was called with.
|
When building the documents, Sphinx will use the above mentioned directive and role to include or exclude content based on the target tag it was called with.
|
||||||
|
|
||||||
.. note:: If excluding an entire document from the toctree based on targets, it's necessary to also update the ``exclude_patterns`` list in :idf_file:`docs/conf_common.py` to exclude the file for other targets, or a Sphinx warning "WARNING: document isn't included in any toctree" will be generated..
|
.. note::
|
||||||
|
|
||||||
If you need to exclude content inside a list or bullet points then this should be done by using the '':TARGET:'' role inside the ''.. list:: '' directive.
|
If excluding an entire document from the toctree based on targets, it's necessary to also update the ``exclude_patterns`` list in :idf_file:`docs/conf_common.py` to exclude the file for other targets, or a Sphinx warning "WARNING: document isn't included in any toctree" will be generated..
|
||||||
|
|
||||||
|
The recommended way of doing it is adding the document to one of the list that gets included in ``conditional_include_dict`` in :idf_file:`docs/conf_common.py`, e.g. a document which should only be shown for BT capable targets should be added to ``BT_DOCS``. :idf_file:`docs/idf_extensions/exclude_docs.py` will then take care of adding it to ``exclude_patterns`` if the corresponding tag is not set.
|
||||||
|
|
||||||
|
If you need to exclude content inside a list or bullet points then this should be done by using the '':TAG:'' role inside the ''.. list:: '' directive.
|
||||||
|
|
||||||
.. code-block:: none
|
.. code-block:: none
|
||||||
|
|
||||||
.. list::
|
.. list::
|
||||||
|
|
||||||
:esp32: - ESP32 specific content
|
:esp32: - ESP32 specific content
|
||||||
:esp32s2: - ESP32 S2 specific content
|
:SOC_BT_SUPPORTED: - BT specific content
|
||||||
- Common bullet point
|
- Common bullet point
|
||||||
- Also common bullet point
|
- Also common bullet point
|
||||||
|
|
||||||
|
@@ -20,8 +20,8 @@ Introduction
|
|||||||
.. list::
|
.. list::
|
||||||
|
|
||||||
* Wi-Fi (2.4 GHz band)
|
* Wi-Fi (2.4 GHz band)
|
||||||
:esp32: * Bluetooth
|
:SOC_BT_SUPPORTED: * Bluetooth
|
||||||
:esp32: * Dual high performance cores
|
:CONFIG_FREERTOS_UNICORE: * Dual high performance cores
|
||||||
* Ultra Low Power co-processor
|
* Ultra Low Power co-processor
|
||||||
* Multiple peripherals
|
* Multiple peripherals
|
||||||
:esp32s2: * Built-in security hardware
|
:esp32s2: * Built-in security hardware
|
||||||
@@ -322,7 +322,7 @@ Linux and macOS
|
|||||||
.. code-block:: bash
|
.. code-block:: bash
|
||||||
|
|
||||||
cd ~/esp/hello_world
|
cd ~/esp/hello_world
|
||||||
idf.py set-target {IDF_TARGET_CL}
|
idf.py set-target {IDF_TARGET_CL}
|
||||||
idf.py menuconfig
|
idf.py menuconfig
|
||||||
|
|
||||||
Windows
|
Windows
|
||||||
@@ -590,7 +590,7 @@ See also:
|
|||||||
|
|
||||||
Now you are ready to try some other :idf:`examples`, or go straight to developing your own applications.
|
Now you are ready to try some other :idf:`examples`, or go straight to developing your own applications.
|
||||||
|
|
||||||
.. important::
|
.. important::
|
||||||
|
|
||||||
Some of examples do not support {IDF_TARGET_NAME} because required hardware is not included in {IDF_TARGET_NAME} so it cannot be supported.
|
Some of examples do not support {IDF_TARGET_NAME} because required hardware is not included in {IDF_TARGET_NAME} so it cannot be supported.
|
||||||
|
|
||||||
|
12
docs/idf_extensions/exclude_docs.py
Normal file
12
docs/idf_extensions/exclude_docs.py
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
# Updates the excluded documents according to the conditional_include_dict {tag:documents}
|
||||||
|
def update_exclude_patterns(app, config):
|
||||||
|
for tag, docs in config.conditional_include_dict.items():
|
||||||
|
if not app.tags.has(tag):
|
||||||
|
app.config.exclude_patterns.extend(docs)
|
||||||
|
|
||||||
|
|
||||||
|
def setup(app):
|
||||||
|
# Tags are generated together with defines
|
||||||
|
app.connect('config-inited', update_exclude_patterns)
|
||||||
|
|
||||||
|
return {'parallel_read_safe': True, 'parallel_write_safe': True, 'version': '0.1'}
|
72
docs/idf_extensions/gen_defines.py
Normal file
72
docs/idf_extensions/gen_defines.py
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
# Sphinx extension to integrate defines into the Sphinx Build
|
||||||
|
#
|
||||||
|
# Runs after the IDF dummy project has been built
|
||||||
|
#
|
||||||
|
# Then emits the new 'idf-defines-generated' event which has a dictionary of raw text define values
|
||||||
|
# that other extensions can use to generate relevant data.
|
||||||
|
|
||||||
|
import glob
|
||||||
|
import os
|
||||||
|
import subprocess
|
||||||
|
import re
|
||||||
|
|
||||||
|
|
||||||
|
def generate_defines(app, project_description):
|
||||||
|
sdk_config_path = os.path.join(project_description["build_dir"], "config")
|
||||||
|
|
||||||
|
# Parse kconfig macros to pass into doxygen
|
||||||
|
#
|
||||||
|
# TODO: this should use the set of "config which can't be changed" eventually,
|
||||||
|
# not the header
|
||||||
|
defines = get_defines(os.path.join(project_description["build_dir"],
|
||||||
|
"config", "sdkconfig.h"), sdk_config_path)
|
||||||
|
|
||||||
|
# Add all SOC _caps.h headers and kconfig macros to the defines
|
||||||
|
#
|
||||||
|
# kind of a hack, be nicer to add a component info dict in project_description.json
|
||||||
|
soc_path = [p for p in project_description["build_component_paths"] if p.endswith("/soc")][0]
|
||||||
|
soc_headers = glob.glob(os.path.join(soc_path, "soc", project_description["target"],
|
||||||
|
"include", "soc", "*_caps.h"))
|
||||||
|
assert len(soc_headers) > 0
|
||||||
|
|
||||||
|
for soc_header in soc_headers:
|
||||||
|
defines.update(get_defines(soc_header, sdk_config_path))
|
||||||
|
|
||||||
|
add_tags(app, defines)
|
||||||
|
|
||||||
|
app.emit('idf-defines-generated', defines)
|
||||||
|
|
||||||
|
|
||||||
|
def get_defines(header_path, sdk_config_path):
|
||||||
|
defines = {}
|
||||||
|
# Note: we run C preprocessor here without any -I arguments (except "sdkconfig.h"), so assumption is
|
||||||
|
# that these headers are all self-contained and don't include any other headers
|
||||||
|
# not in the same directory
|
||||||
|
print("Reading macros from %s..." % (header_path))
|
||||||
|
processed_output = subprocess.check_output(["xtensa-esp32-elf-gcc", "-I", sdk_config_path,
|
||||||
|
"-dM", "-E", header_path]).decode()
|
||||||
|
for line in processed_output.split("\n"):
|
||||||
|
line = line.strip()
|
||||||
|
m = re.search("#define ([^ ]+) ?(.*)", line)
|
||||||
|
if m and not m.group(1).startswith("_"):
|
||||||
|
defines[m.group(1)] = m.group(2)
|
||||||
|
|
||||||
|
return defines
|
||||||
|
|
||||||
|
|
||||||
|
def add_tags(app, defines):
|
||||||
|
# try to parse define values as ints and add to tags
|
||||||
|
for name, value in defines.items():
|
||||||
|
try:
|
||||||
|
define_value = int(value.strip("()"))
|
||||||
|
if define_value > 0:
|
||||||
|
app.tags.add(name)
|
||||||
|
except ValueError:
|
||||||
|
continue
|
||||||
|
|
||||||
|
|
||||||
|
def setup(app):
|
||||||
|
app.connect('idf-info', generate_defines)
|
||||||
|
app.add_event('idf-defines-generated')
|
||||||
|
|
||||||
|
return {'parallel_read_safe': True, 'parallel_write_safe': True, 'version': '0.1'}
|
@@ -2,7 +2,6 @@
|
|||||||
from __future__ import print_function
|
from __future__ import print_function
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
from io import open
|
from io import open
|
||||||
import glob
|
|
||||||
import os
|
import os
|
||||||
import os.path
|
import os.path
|
||||||
import re
|
import re
|
||||||
@@ -45,28 +44,9 @@ def _parse_defines(header_path, sdk_config_path):
|
|||||||
return defines
|
return defines
|
||||||
|
|
||||||
|
|
||||||
def generate_doxygen(app, project_description):
|
def generate_doxygen(app, defines):
|
||||||
build_dir = os.path.dirname(app.doctreedir.rstrip(os.sep))
|
build_dir = os.path.dirname(app.doctreedir.rstrip(os.sep))
|
||||||
|
|
||||||
sdk_config_path = os.path.join(project_description["build_dir"], "config")
|
|
||||||
|
|
||||||
# Parse kconfig macros to pass into doxygen
|
|
||||||
#
|
|
||||||
# TODO: this should use the set of "config which can't be changed" eventually,
|
|
||||||
# not the header
|
|
||||||
defines = _parse_defines(os.path.join(project_description["build_dir"],
|
|
||||||
"config", "sdkconfig.h"), sdk_config_path)
|
|
||||||
|
|
||||||
# Add all SOC _caps.h headers to the defines
|
|
||||||
#
|
|
||||||
# kind of a hack, be nicer to add a component info dict in project_description.json
|
|
||||||
soc_path = [p for p in project_description["build_component_paths"] if p.endswith("/soc")][0]
|
|
||||||
soc_headers = glob.glob(os.path.join(soc_path, "soc", project_description["target"],
|
|
||||||
"include", "soc", "*_caps.h"))
|
|
||||||
assert len(soc_headers) > 0
|
|
||||||
for soc_header in soc_headers:
|
|
||||||
defines.update(_parse_defines(soc_header, sdk_config_path))
|
|
||||||
|
|
||||||
# Call Doxygen to get XML files from the header files
|
# Call Doxygen to get XML files from the header files
|
||||||
print("Calling Doxygen to generate latest XML files")
|
print("Calling Doxygen to generate latest XML files")
|
||||||
doxy_env = os.environ
|
doxy_env = os.environ
|
||||||
|
@@ -31,9 +31,9 @@ API 指南
|
|||||||
ROM debug console <romconsole>
|
ROM debug console <romconsole>
|
||||||
:esp32: RF Calibration <RF_calibration>
|
:esp32: RF Calibration <RF_calibration>
|
||||||
WiFi Driver <wifi>
|
WiFi Driver <wifi>
|
||||||
:esp32: ESP-BLE-MESH <esp-ble-mesh/ble-mesh-index>
|
:SOC_BT_SUPPORTED: ESP-BLE-MESH <esp-ble-mesh/ble-mesh-index>
|
||||||
ESP-MESH (Wi-Fi) <mesh>
|
ESP-MESH (Wi-Fi) <mesh>
|
||||||
:esp32: BluFi <blufi>
|
:SOC_BT_SUPPORTED: BluFi <blufi>
|
||||||
External SPI-connected RAM <external-ram>
|
External SPI-connected RAM <external-ram>
|
||||||
链接脚本生成机制 <linker-script-generation>
|
链接脚本生成机制 <linker-script-generation>
|
||||||
LwIP <lwip>
|
LwIP <lwip>
|
||||||
|
@@ -14,12 +14,12 @@
|
|||||||
I2C <i2c>
|
I2C <i2c>
|
||||||
I2S <i2s>
|
I2S <i2s>
|
||||||
LED Control <ledc>
|
LED Control <ledc>
|
||||||
:esp32: MCPWM <mcpwm>
|
:SOC_MCPWM_SUPPORTED: MCPWM <mcpwm>
|
||||||
Pulse Counter <pcnt>
|
Pulse Counter <pcnt>
|
||||||
Remote Control <rmt>
|
Remote Control <rmt>
|
||||||
:esp32: SDMMC Host <sdmmc_host>
|
:SOC_SDMMC_HOST_SUPPORTED: SDMMC Host <sdmmc_host>
|
||||||
SD SPI Host <sdspi_host>
|
SD SPI Host <sdspi_host>
|
||||||
:esp32: SDIO Slave <sdio_slave>
|
:SOC_SDIO_SLAVE_SUPPORTED: SDIO Slave <sdio_slave>
|
||||||
Sigma-delta Modulation <sigmadelta>
|
Sigma-delta Modulation <sigmadelta>
|
||||||
SPI Master <spi_master>
|
SPI Master <spi_master>
|
||||||
SPI Slave <spi_slave>
|
SPI Slave <spi_slave>
|
||||||
@@ -28,5 +28,5 @@
|
|||||||
Touch Sensor <touch_pad>
|
Touch Sensor <touch_pad>
|
||||||
UART <uart>
|
UART <uart>
|
||||||
|
|
||||||
本部分的 API 示例代码存放在 ESP-IDF 示例项目的 :example:`peripherals` 目录下。
|
本部分的 API 示例代码存放在 ESP-IDF 示例项目的 :example:`peripherals` 目录下。
|
||||||
|
|
||||||
|
@@ -18,5 +18,3 @@ copyright = u'2016 - 2020 乐鑫信息科技(上海)股份有限公司'
|
|||||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||||
# for a list of supported languages.
|
# for a list of supported languages.
|
||||||
language = 'zh_CN'
|
language = 'zh_CN'
|
||||||
|
|
||||||
update_exclude_patterns(tags) # noqa: F405, need to import * from conf_common
|
|
||||||
|
Reference in New Issue
Block a user