docs: update api-ref system docs for C2

This commit is contained in:
Marius Vikhammer
2022-07-25 18:40:31 +08:00
parent 0330e952d1
commit 9d599c207f
7 changed files with 31 additions and 127 deletions
@@ -41,7 +41,7 @@ To get the list of your image segments, please run the following command:
Checksum: e8 (valid)Validation Hash: 407089ca0eae2bbf83b4120979d3354b1c938a49cb7a0c997f240474ef2ec76b (valid)
You can also see the information on segments in the ESP-IDF logs while your application is booting:
.. code-block::
I (443) esp_image: segment 0: paddr=0x00020020 vaddr=0x3f400020 size=0x13ce0 ( 81120) map
@@ -62,7 +62,7 @@ You can also see the information on segments in the ESP-IDF logs while your appl
For more details on the type of memory segments and their address ranges, see *{IDF_TARGET_NAME} Technical Reference Manual* > *System and Memory* > *Embedded Memory* [`PDF <{IDF_TARGET_TRM_EN_URL}#sysmem>`__].
.. only:: esp32s2 or esp32s3 or esp32c3
.. only:: not esp32
For more details on the type of memory segments and their address ranges, see *{IDF_TARGET_NAME} Technical Reference Manual* > *System and Memory* > *Internal Memory* [`PDF <{IDF_TARGET_TRM_EN_URL}#sysmem>`__].
@@ -21,10 +21,11 @@ Configure and Install driver
:cpp:func:`esp_async_memcpy_install` is used to install the driver with user's configuration. Please note that async memcpy has to be called with the handle returned from :cpp:func:`esp_async_memcpy_install`.
Driver configuration is described in :cpp:type:`async_memcpy_config_t`:
:cpp:member:`backlog`: This is used to configured the maximum number of DMA operation that can be working at the background at the same time.
:cpp:member:`sram_trans_align`: Declare SRAM alignment for both data address and copy size, set to zero if the data has no restriction in alignment. If set to a quadruple value (i.e. 4X), the driver will enable the burst mode internally, which is helpful for some performance related application.
:cpp:member:`psram_trans_align`: Declare PSRAM alignment for both data address and copy size. User has to give it a valid value (only 16, 32, 64 are supported) if the destination of memcpy is located in PSRAM. The default alignment (i.e. 16) will be applied if it's set to zero. Internally, the driver configures the size of block used by DMA to access PSRAM, according to the alignment.
:cpp:member:`flags`: This is used to enable some special driver features.
* :cpp:member:`backlog`: This is used to configure the maximum number of DMA operations being processed at the same time.
* :cpp:member:`sram_trans_align`: Declare SRAM alignment for both data address and copy size, set to zero if the data has no restriction in alignment. If set to a quadruple value (i.e. 4X), the driver will enable the burst mode internally, which is helpful for some performance related application.
* :cpp:member:`psram_trans_align`: Declare PSRAM alignment for both data address and copy size. User has to give it a valid value (only 16, 32, 64 are supported) if the destination of memcpy is located in PSRAM. The default alignment (i.e. 16) will be applied if it's set to zero. Internally, the driver configures the size of block used by DMA to access PSRAM, according to the alignment.
* :cpp:member:`flags`: This is used to enable some special driver features.
:c:macro:`ASYNC_MEMCPY_DEFAULT_CONFIG` provides a default configuration, which specifies the backlog to 8.
@@ -4,13 +4,7 @@ Call function with external stack
Overview
--------
A given function can be executed with a user allocated stack space
which is independent of current task stack, this mechanism can be
used to save stack space wasted by tasks which call a common function
with intensive stack usage such as `printf`. The given function can
be called inside the shared stack space which is a callback function
deferred by calling :cpp:func:`esp_execute_shared_stack_function`,
passing that function as parameter
A given function can be executed with a user allocated stack space which is independent of current task stack, this mechanism can be used to save stack space wasted by tasks which call a common function with intensive stack usage such as `printf`. The given function can be called inside the shared stack space which is a callback function deferred by calling :cpp:func:`esp_execute_shared_stack_function`, passing that function as parameter.
Usage
-----
@@ -22,9 +16,7 @@ Usage
- the size of stack in bytes
- a pointer to the shared stack function
The user defined function will be deferred as a callback
and can be called using the user allocated space without
taking space from current task stack.
The user defined function will be deferred as a callback and can be called using the user allocated space without taking space from current task stack.
The usage may look like the code below:
@@ -46,15 +38,15 @@ The usage may look like the code below:
//Allocate a mutex to protect its usage:
SemaphoreHandle_t printf_lock = xSemaphoreCreateMutex();
assert(printf_lock != NULL);
//Call the desired function using the macro helper:
esp_execute_shared_stack_function(printf_lock,
esp_execute_shared_stack_function(printf_lock,
shared_stack,
8192,
external_stack_function);
vSemaphoreDelete(printf_lock);
free(shared_stack);
vSemaphoreDelete(printf_lock);
free(shared_stack);
}
.. _esp-call-with-stack-basic_usage:
@@ -4,8 +4,7 @@ ESP HTTPS OTA
Overview
--------
``esp_https_ota`` provides simplified APIs to perform firmware upgrades over HTTPS.
It's an abstraction layer over existing OTA APIs.
``esp_https_ota`` provides simplified APIs to perform firmware upgrades over HTTPS. It's an abstraction layer over existing OTA APIs.
Application Example
-------------------
@@ -43,15 +42,11 @@ Please refer to :ref:`ESP-TLS: TLS Server Verification <esp_tls_server_verificat
Partial Image Download over HTTPS
---------------------------------
To use partial image download feature, enable ``partial_http_download`` configuration in ``esp_https_ota_config_t``.
When this configuration is enabled, firmware image will be downloaded in multiple HTTP requests of specified size.
Maximum content length of each request can be specified by setting ``max_http_request_size`` to required value.
To use partial image download feature, enable ``partial_http_download`` configuration in ``esp_https_ota_config_t``. When this configuration is enabled, firmware image will be downloaded in multiple HTTP requests of specified size. Maximum content length of each request can be specified by setting ``max_http_request_size`` to required value.
This option is useful while fetching image from a service like AWS S3, where mbedTLS Rx buffer size (:ref:`CONFIG_MBEDTLS_SSL_IN_CONTENT_LEN`)
can be set to lower value which is not possible without enabling this configuration.
This option is useful while fetching image from a service like AWS S3, where mbedTLS Rx buffer size (:ref:`CONFIG_MBEDTLS_SSL_IN_CONTENT_LEN`) can be set to lower value which is not possible without enabling this configuration.
Default value of mbedTLS Rx buffer size is set to 16K. By using partial_http_download with max_http_request_size of 4K,
size of mbedTLS Rx buffer can be reduced to 4K. With this configuration, memory saving of around 12K is expected.
Default value of mbedTLS Rx buffer size is set to 16K. By using partial_http_download with max_http_request_size of 4K, size of mbedTLS Rx buffer can be reduced to 4K. With this configuration, memory saving of around 12K is expected.
Signature Verification
----------------------
+10 -34
View File
@@ -16,32 +16,19 @@ Overview
The {IDF_TARGET_NAME} has two cores, with 32 interrupts. Each interrupt has a certain priority level, most (but not all) interrupts are connected to the interrupt mux.
.. only:: esp32c3
.. only:: esp32c3 or esp32c2
The {IDF_TARGET_NAME} has one core, with 31 interrupts. Each interrupt has a programmable priority level.
Because there are more interrupt sources than interrupts, sometimes it makes sense to share an interrupt in multiple drivers. The :cpp:func:`esp_intr_alloc` abstraction exists to hide all these implementation details.
A driver can allocate an interrupt for a certain peripheral by calling :cpp:func:`esp_intr_alloc` (or :cpp:func:`esp_intr_alloc_intrstatus`). It can use
the flags passed to this function to set the type of interrupt allocated, specifying a particular level or trigger method. The
interrupt allocation code will then find an applicable interrupt, use the interrupt mux to hook it up to the peripheral, and
install the given interrupt handler and ISR to it.
A driver can allocate an interrupt for a certain peripheral by calling :cpp:func:`esp_intr_alloc` (or :cpp:func:`esp_intr_alloc_intrstatus`). It can use the flags passed to this function to set the type of interrupt allocated, specifying a particular level or trigger method. The interrupt allocation code will then find an applicable interrupt, use the interrupt mux to hook it up to the peripheral, and install the given interrupt handler and ISR to it.
This code presents two different types of interrupts, handled differently: shared interrupts and non-shared interrupts. The simplest
ones are non-shared interrupts: a separate interrupt is allocated per :cpp:func:`esp_intr_alloc` call and this interrupt is solely used for
the peripheral attached to it, with only one ISR that will get called. On the other hand, shared interrupts can have multiple peripherals triggering
them, with multiple ISRs being called when one of the peripherals attached signals an interrupt. Thus, ISRs that are intended for shared
interrupts should check the interrupt status of the peripheral they service in order to check if any action is required.
This code presents two different types of interrupts, handled differently: shared interrupts and non-shared interrupts. The simplest ones are non-shared interrupts: a separate interrupt is allocated per :cpp:func:`esp_intr_alloc` call and this interrupt is solely used for the peripheral attached to it, with only one ISR that will get called. On the other hand, shared interrupts can have multiple peripherals triggering them, with multiple ISRs being called when one of the peripherals attached signals an interrupt. Thus, ISRs that are intended for shared interrupts should check the interrupt status of the peripheral they service in order to check if any action is required.
Non-shared interrupts can be either level- or edge-triggered. Shared interrupts can
only be level interrupts due to the chance of missed interrupts when edge interrupts are
used.
Non-shared interrupts can be either level- or edge-triggered. Shared interrupts can only be level interrupts due to the chance of missed interrupts when edge interrupts are used.
For example, let's say DevA and DevB share an interrupt. DevB signals an interrupt, so INT line goes high. The ISR handler
calls code for DevA but does nothing. Then, ISR handler calls code for DevB, but while doing that,
DevA signals an interrupt. DevB's ISR is done, it clears interrupt status for DevB and exits interrupt code. Now, an
interrupt for DevA is still pending, but because the INT line never went low, as DevA kept it high
even when the interrupt for DevB was cleared, the interrupt is never serviced.
For example, let's say DevA and DevB share an interrupt. DevB signals an interrupt, so INT line goes high. The ISR handler calls code for DevA but does nothing. Then, ISR handler calls code for DevB, but while doing that, DevA signals an interrupt. DevB's ISR is done, it clears interrupt status for DevB and exits interrupt code. Now, an interrupt for DevA is still pending, but because the INT line never went low, as DevA kept it high even when the interrupt for DevB was cleared, the interrupt is never serviced.
.. only:: esp32 or esp32s3
@@ -67,28 +54,21 @@ even when the interrupt for DevB was cleared, the interrupt is never serviced.
Internal interrupt sources are defined in esp_intr_alloc.h as ``ETS_INTERNAL_*_INTR_SOURCE``.
These peripherals can only be configured from the core they are associated with. When generating an interrupt,
the interrupt they generate is hard-wired to their associated core; it's not possible to have, for example, an internal
timer comparator of one core generate an interrupt on another core. That is why these sources can only be managed
using a task running on that specific core. Internal interrupt sources are still allocatable using :cpp:func:`esp_intr_alloc`
as normal, but they cannot be shared and will always have a fixed interrupt level (namely, the one associated in
hardware with the peripheral).
These peripherals can only be configured from the core they are associated with. When generating an interrupt, the interrupt they generate is hard-wired to their associated core; it's not possible to have, for example, an internal timer comparator of one core generate an interrupt on another core. That is why these sources can only be managed using a task running on that specific core. Internal interrupt sources are still allocatable using :cpp:func:`esp_intr_alloc` as normal, but they cannot be shared and will always have a fixed interrupt level (namely, the one associated in hardware with the peripheral).
External Peripheral Interrupts
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The remaining interrupt sources are from external peripherals. These are defined in soc/soc.h as ``ETS_*_INTR_SOURCE``.
Non-internal interrupt slots in both CPU cores are wired to an interrupt multiplexer, which can be used to
route any external interrupt source to any of these interrupt slots.
Non-internal interrupt slots in both CPU cores are wired to an interrupt multiplexer, which can be used to route any external interrupt source to any of these interrupt slots.
- Allocating an external interrupt will always allocate it on the core that does the allocation.
- Freeing an external interrupt must always happen on the same core it was allocated on.
- Disabling and enabling external interrupts from another core is allowed.
- Multiple external interrupt sources can share an interrupt slot by passing ``ESP_INTR_FLAG_SHARED`` as a flag to :cpp:func:`esp_intr_alloc`.
Care should be taken when calling :cpp:func:`esp_intr_alloc` from a task which is not pinned to a core. During task switching, these tasks can migrate between cores. Therefore it is impossible to tell which CPU the interrupt is allocated on, which makes it difficult to free the interrupt handle and may also
cause debugging difficulties. It is advised to use :cpp:func:`xTaskCreatePinnedToCore` with a specific CoreID argument to create tasks that will allocate interrupts. In the case of internal interrupt sources, this is required.
Care should be taken when calling :cpp:func:`esp_intr_alloc` from a task which is not pinned to a core. During task switching, these tasks can migrate between cores. Therefore it is impossible to tell which CPU the interrupt is allocated on, which makes it difficult to free the interrupt handle and may also cause debugging difficulties. It is advised to use :cpp:func:`xTaskCreatePinnedToCore` with a specific CoreID argument to create tasks that will allocate interrupts. In the case of internal interrupt sources, this is required.
IRAM-Safe Interrupt Handlers
----------------------------
@@ -104,15 +84,11 @@ Refer to the :ref:`SPI flash API documentation <iram-safe-interrupt-handlers>` f
Multiple Handlers Sharing A Source
----------------------------------
Several handlers can be assigned to a same source, given that all handlers are allocated using the ``ESP_INTR_FLAG_SHARED`` flag.
They will all be allocated to the interrupt, which the source is attached to, and called sequentially when the source is active.
The handlers can be disabled and freed individually. The source is attached to the interrupt (enabled), if one or more handlers are enabled, otherwise detached.
A handler will never be called when disabled, while **its source may still be triggered** if any one of its handler enabled.
Several handlers can be assigned to a same source, given that all handlers are allocated using the ``ESP_INTR_FLAG_SHARED`` flag. They will all be allocated to the interrupt, which the source is attached to, and called sequentially when the source is active. The handlers can be disabled and freed individually. The source is attached to the interrupt (enabled), if one or more handlers are enabled, otherwise detached. A handler will never be called when disabled, while **its source may still be triggered** if any one of its handler enabled.
Sources attached to non-shared interrupt do not support this feature.
Though the framework support this feature, you have to use it *very carefully*. There usually exist two ways to stop an interrupt from being triggered: *disable the source* or *mask peripheral interrupt status*.
IDF only handles enabling and disabling of the source itself, leaving status and mask bits to be handled by users.
Though the framework support this feature, you have to use it *very carefully*. There usually exist two ways to stop an interrupt from being triggered: *disable the source* or *mask peripheral interrupt status*. IDF only handles enabling and disabling of the source itself, leaving status and mask bits to be handled by users.
**Status bits shall either be masked before the handler responsible for it is disabled, either be masked and then properly handled in another enabled interrupt**.
Please note that leaving some status bits unhandled without masking them, while disabling the handlers for them, will cause the interrupt(s) to be triggered indefinitely, resulting therefore in a system crash.