i2s: deprecate confusing names
This commit is contained in:
@@ -80,8 +80,8 @@ Configuration example:
|
||||
.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT,
|
||||
.communication_format = I2S_COMM_FORMAT_STAND_I2S
|
||||
.tx_desc_auto_clear = false,
|
||||
.dma_buf_count = 8,
|
||||
.dma_buf_len = 64,
|
||||
.dma_desc_num = 8,
|
||||
.dma_frame_num = 64,
|
||||
.use_apll = false,
|
||||
.intr_alloc_flags = ESP_INTR_FLAG_LEVEL1 // Interrupt level 1, default 0
|
||||
};
|
||||
@@ -101,8 +101,8 @@ Configuration example:
|
||||
.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT,
|
||||
.communication_format = I2S_COMM_FORMAT_STAND_I2S,
|
||||
.tx_desc_auto_clear = false,
|
||||
.dma_buf_count = 8,
|
||||
.dma_buf_len = 64,
|
||||
.dma_desc_num = 8,
|
||||
.dma_frame_num = 64,
|
||||
.bits_per_chan = I2S_BITS_PER_SAMPLE_16BIT
|
||||
};
|
||||
|
||||
@@ -194,8 +194,8 @@ Example for general usage.
|
||||
.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT,
|
||||
.communication_format = I2S_COMM_FORMAT_STAND_I2S
|
||||
.tx_desc_auto_clear = false,
|
||||
.dma_buf_count = 8,
|
||||
.dma_buf_len = 64,
|
||||
.dma_desc_num = 8,
|
||||
.dma_frame_num = 64,
|
||||
.use_apll = false,
|
||||
.intr_alloc_flags = ESP_INTR_FLAG_LEVEL1 // Interrupt level 1, default 0
|
||||
};
|
||||
@@ -238,8 +238,8 @@ Example for general usage.
|
||||
.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT,
|
||||
.communication_format = I2S_COMM_FORMAT_STAND_I2S
|
||||
.tx_desc_auto_clear = false,
|
||||
.dma_buf_count = 8,
|
||||
.dma_buf_len = 64
|
||||
.dma_desc_num = 8,
|
||||
.dma_frame_num = 64
|
||||
};
|
||||
|
||||
static const i2s_pin_config_t pin_config = {
|
||||
@@ -282,8 +282,8 @@ Example for general usage.
|
||||
.channel_format = I2S_CHANNEL_FMT_MULTIPLE,
|
||||
.communication_format = I2S_COMM_FORMAT_STAND_I2S
|
||||
.tx_desc_auto_clear = false,
|
||||
.dma_buf_count = 8,
|
||||
.dma_buf_len = 64,
|
||||
.dma_desc_num = 8,
|
||||
.dma_frame_num = 64,
|
||||
.chan_mask = I2S_TDM_ACTIVE_CH0 | I2S_TDM_ACTIVE_CH2
|
||||
};
|
||||
|
||||
@@ -328,8 +328,8 @@ Example for general usage.
|
||||
.bits_per_sample = 16, /* the DAC module will only take the 8bits from MSB */
|
||||
.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT,
|
||||
.intr_alloc_flags = 0, // default interrupt priority
|
||||
.dma_buf_count = 8,
|
||||
.dma_buf_len = 64,
|
||||
.dma_desc_num = 8,
|
||||
.dma_frame_num = 64,
|
||||
.use_apll = false
|
||||
};
|
||||
|
||||
|
||||
@@ -62,12 +62,12 @@ You can also see the information on segments in the IDF logs while your applicat
|
||||
|
||||
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 esp32c3
|
||||
.. only:: esp32s2 or esp32s3 or esp32c3
|
||||
|
||||
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>`__].
|
||||
|
||||
3. The image has a single checksum byte after the last segment. This byte is written on a sixteen byte padded boundary, so the application image might need padding.
|
||||
4. If the ``hash_appended`` field from :cpp:type:`esp_image_header_t` is set then a SHA256 checksum will be appended. The value of SHA256 is calculated on the range from first byte and up to this field. The length of this field is 32 bytes.
|
||||
4. If the ``hash_appended`` field from :cpp:type:`esp_image_header_t` is set then a SHA256 checksum will be appended. The value of SHA256 is calculated on the range from the first byte and up to this field. The length of this field is 32 bytes.
|
||||
5. If the options :ref:`CONFIG_SECURE_SIGNED_APPS_SCHEME` is set to ECDSA then the application image will have additional 68 bytes for an ECDSA signature, which includes:
|
||||
|
||||
* version word (4 bytes),
|
||||
@@ -78,6 +78,7 @@ Application Description
|
||||
|
||||
The ``DROM`` segment starts with the :cpp:type:`esp_app_desc_t` structure which carries specific fields describing the application:
|
||||
|
||||
* ``magic_word`` - the magic word for the esp_app_desc structure.
|
||||
* ``secure_version`` - see :doc:`Anti-rollback</api-reference/system/ota>`.
|
||||
* ``version`` - see :doc:`App version</api-reference/system/system>`. ``*``
|
||||
* ``project_name`` is filled from ``PROJECT_NAME``. ``*``
|
||||
@@ -92,7 +93,7 @@ This structure is useful for identification of images uploaded OTA because it ha
|
||||
Adding a Custom Structure to an Application
|
||||
-------------------------------------------
|
||||
|
||||
Customer also has the opportunity to have similar structure with a fixed offset relative to the beginning of the image.
|
||||
Users also have the opportunity to have similar structure with a fixed offset relative to the beginning of the image.
|
||||
The following pattern can be used to add a custom structure to your image:
|
||||
|
||||
::
|
||||
|
||||
@@ -4,7 +4,7 @@ Application Level Tracing
|
||||
Overview
|
||||
--------
|
||||
|
||||
IDF provides useful feature for program behaviour analysis: application level tracing. It is implemented in the corresponding library and can be enabled via menuconfig. This feature allows to transfer arbitrary data between host and {IDF_TARGET_NAME} via JTAG interface with small overhead on program execution.
|
||||
IDF provides a useful feature for program behavior analysis called **Application Level Tracing**. The feature can be enabled in menuconfig and allows transfer of arbitrary data between the host and {IDF_TARGET_NAME} via JTAG interface with minimal overhead on program execution.
|
||||
Developers can use this library to send application specific state of execution to the host and receive commands or other type of info in the opposite direction at runtime. The main use cases of this library are:
|
||||
|
||||
1. Collecting application specific data, see :ref:`app_trace-application-specific-tracing`
|
||||
|
||||
@@ -7,7 +7,7 @@ Overview
|
||||
The event loop library allows components to declare events to which other components can register handlers -- code which will
|
||||
execute when those events occur. This allows loosely coupled components to attach desired behavior to changes in state of other components
|
||||
without application involvement. For instance, a high level connection handling library may subscribe to events produced
|
||||
by the wifi subsystem directly and act on those events. This also simplifies event processing by serializing and deferring
|
||||
by the Wi-Fi subsystem directly and act on those events. This also simplifies event processing by serializing and deferring
|
||||
code execution to another context.
|
||||
|
||||
Using ``esp_event`` APIs
|
||||
@@ -15,7 +15,7 @@ Using ``esp_event`` APIs
|
||||
|
||||
There are two objects of concern for users of this library: events and event loops.
|
||||
|
||||
Events are occurrences of note. For example, for WiFi, a successful connection to the access point may be an event.
|
||||
Events are occurrences of note. For example, for Wi-Fi, a successful connection to the access point may be an event.
|
||||
Events are referenced using a two part identifier which are discussed more :ref:`here <esp-event-declaring-defining-events>`.
|
||||
Event loops are the vehicle by which events get posted by event sources and handled by event handler functions.
|
||||
These two appear prominently in the event loop library APIs.
|
||||
@@ -84,7 +84,7 @@ In code, the flow above may look like as follows:
|
||||
Declaring and defining events
|
||||
-----------------------------
|
||||
|
||||
As mentioned previously, events consists of two-part identifers: the event base and the event ID. The event base identifies an independent group
|
||||
As mentioned previously, events consists of two-part identifiers: the event base and the event ID. The event base identifies an independent group
|
||||
of events; the event ID identifies the event within that group. Think of the event base and event ID as a
|
||||
person's last name and first name, respectively. A last name identifies a family, and the first name identifies a person within that family.
|
||||
|
||||
@@ -104,7 +104,7 @@ Event base definition:
|
||||
|
||||
.. note::
|
||||
|
||||
In IDF, the base identifiers for system events are uppercase and are postfixed with ``_EVENT``. For example, the base for wifi events is declared and defined
|
||||
In IDF, the base identifiers for system events are uppercase and are postfixed with ``_EVENT``. For example, the base for Wi-Fi events is declared and defined
|
||||
as ``WIFI_EVENT``, the ethernet event base ``ETHERNET_EVENT``, and so on. The purpose is to have event bases look like constants (although
|
||||
they are global variables considering the defintions of macros ``ESP_EVENT_DECLARE_BASE`` and ``ESP_EVENT_DEFINE_BASE``).
|
||||
|
||||
@@ -126,7 +126,7 @@ Event ID:
|
||||
Default Event Loop
|
||||
------------------
|
||||
|
||||
The default event loop is a special type of loop used for system events (WiFi events, for example). The handle for this
|
||||
The default event loop is a special type of loop used for system events (Wi-Fi events, for example). The handle for this
|
||||
loop is hidden from the user. The creation, deletion, handler registration/unregistration and posting of events is done
|
||||
through a variant of the APIs for user event loops. The table below enumerates those variants, and the user event
|
||||
loops equivalent.
|
||||
|
||||
@@ -15,16 +15,18 @@ passing that function as parameter
|
||||
Usage
|
||||
-----
|
||||
|
||||
:cpp:func:`esp_execute_shared_stack_function` takes four arguments,
|
||||
a mutex object allocated by the caller, which is used to protect if
|
||||
the same function shares its allocated stack, a pointer to the top
|
||||
of stack used to that fuction, the size in bytes of stack and, a pointer
|
||||
to a user function where the shared stack space will reside, after calling
|
||||
the function, the user defined function will be deferred as a callback
|
||||
where functions can be called using the user allocated space without
|
||||
taking space from current task stack.
|
||||
:cpp:func:`esp_execute_shared_stack_function` takes four arguments:
|
||||
|
||||
The usage may looks like the code below:
|
||||
- a mutex object allocated by the caller, which is used to protect if the same function shares its allocated stack
|
||||
- a pointer to the top of stack used for that fuction
|
||||
- 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 usage may look like the code below:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
@@ -33,8 +35,8 @@ The usage may looks like the code below:
|
||||
printf("Executing this printf from external stack! \n");
|
||||
}
|
||||
|
||||
//Let's suppose we wanting to call printf using a separated stack space
|
||||
//allowing app to reduce its stack size.
|
||||
//Let's suppose we want to call printf using a separated stack space
|
||||
//allowing the app to reduce its stack size.
|
||||
void app_main()
|
||||
{
|
||||
//Allocate a stack buffer, from heap or as a static form:
|
||||
|
||||
@@ -40,7 +40,7 @@ This option is useful while fetching image from a service like AWS S3, where mbe
|
||||
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 confiuration, memory saving of around 12K is expected.
|
||||
size of mbedTLS Rx buffer can be reduced to 4K. With this configuration, memory saving of around 12K is expected.
|
||||
|
||||
Signature Verification
|
||||
----------------------
|
||||
|
||||
@@ -15,7 +15,7 @@ An interrupt level of the handler depends on the :ref:`CONFIG_ESP_TIMER_INTERRUP
|
||||
|
||||
``esp_timer`` set of APIs provides one-shot and periodic timers, microsecond time resolution, and 64-bit range.
|
||||
|
||||
Internally, ``esp_timer`` uses a 64-bit hardware timer, where the implemention depends on :ref:`CONFIG_ESP_TIMER_IMPL`. Available options are:
|
||||
Internally, ``esp_timer`` uses a 64-bit hardware timer, where the implementation depends on :ref:`CONFIG_ESP_TIMER_IMPL`. Available options are:
|
||||
|
||||
.. list::
|
||||
|
||||
@@ -27,18 +27,18 @@ Internally, ``esp_timer`` uses a 64-bit hardware timer, where the implemention d
|
||||
|
||||
.. note:: The FRC2 is a legacy option for ESP32 until v4.2, a 32-bit hardware timer was used. Starting at v4.2, use the new LAC timer option instead, it has a simpler implementation, and has smaller run time overhead because software handling of timer overflow is not needed.
|
||||
|
||||
Timer callbacks can dispatched by two methods:
|
||||
Timer callbacks can be dispatched by two methods:
|
||||
|
||||
- ``ESP_TIMER_TASK``
|
||||
- ``ESP_TIMER_ISR``. Available only if :ref:`CONFIG_ESP_TIMER_SUPPORTS_ISR_DISPATCH_METHOD` is enabled (by default disabled).
|
||||
|
||||
``ESP_TIMER_TASK``. Timer callbacks are dispatched from a high-priority ``esp_timer`` task. Because all the callbacks are dispatched from the same task, it is recommended to only do the minimal possible amount of work from the callback itself, posting an event to a lower priority task using a queue instead.
|
||||
|
||||
If other tasks with priority higher than ``esp_timer`` are running, callback dispatching will be delayed until ``esp_timer`` task has a chance to run. For example, this will happen if a SPI Flash operation is in progress.
|
||||
If other tasks with priority higher than ``esp_timer`` are running, callback dispatching will be delayed until ``esp_timer`` task has a chance to run. For example, this will happen if an SPI Flash operation is in progress.
|
||||
|
||||
``ESP_TIMER_ISR``. Timer callbacks are dispatched directly from the timer interrupt handler. This method is useful for some simple callbacks which aim for lower latency.
|
||||
|
||||
Creating and starting a timer, and dispatching the callback takes some time. Therefore there is a lower limit to the timeout value of one-shot ``esp_timer``. If :cpp:func:`esp_timer_start_once` is called with a timeout value less than 20us, the callback will be dispatched only after approximately 20us.
|
||||
Creating and starting a timer, and dispatching the callback takes some time. Therefore, there is a lower limit to the timeout value of one-shot ``esp_timer``. If :cpp:func:`esp_timer_start_once` is called with a timeout value less than 20us, the callback will be dispatched only after approximately 20us.
|
||||
|
||||
Periodic ``esp_timer`` also imposes a 50us restriction on the minimal timer period. Periodic software timers with period of less than 50us are not practical since they would consume most of the CPU time. Consider using dedicated hardware peripherals or DMA features if you find that a timer with small period is required.
|
||||
|
||||
@@ -61,7 +61,7 @@ Note that the timer must not be running when :cpp:func:`esp_timer_start_once` or
|
||||
Callback functions
|
||||
------------------
|
||||
|
||||
.. note: Keep the callback functions as short as possible otherwise it will affect all timers.
|
||||
.. note:: Keep the callback functions as short as possible otherwise it will affect all timers.
|
||||
|
||||
Timer callbacks which are processed by ``ESP_TIMER_ISR`` method should not call the context switch call - ``portYIELD_FROM_ISR()``, instead of this you should use the :cpp:func:`esp_timer_isr_dispatch_need_yield` function.
|
||||
The context switch will be done after all ISR dispatch timers have been processed, if required by the system.
|
||||
|
||||
@@ -7,7 +7,7 @@ Overview
|
||||
This section contains documentation of FreeRTOS types, functions, and macros. It is automatically generated from FreeRTOS header files.
|
||||
|
||||
.. note::
|
||||
ESP-IDF FreeRTOS is based on the Xtensa port of FreeRTOS v10.2.0,
|
||||
ESP-IDF FreeRTOS is based on the Xtensa port of FreeRTOS v10.4.3
|
||||
|
||||
For more information about FreeRTOS features specific to ESP-IDF, see :doc:`ESP-IDF FreeRTOS SMP Changes<../../api-guides/freertos-smp>`
|
||||
and :doc:`ESP-IDF FreeRTOS Additions<freertos_additions>`.
|
||||
|
||||
@@ -4,9 +4,9 @@ FreeRTOS Additions
|
||||
Overview
|
||||
--------
|
||||
|
||||
ESP-IDF FreeRTOS is based on the Xtensa port of FreeRTOS v10.2.0 with significant modifications
|
||||
ESP-IDF FreeRTOS is based on the Xtensa port of FreeRTOS v10.4.3 with significant modifications
|
||||
for SMP compatibility (see :doc:`ESP-IDF FreeRTOS SMP Changes<../../api-guides/freertos-smp>`).
|
||||
However various features specific to ESP-IDF FreeRTOS have been added. The features are as follows:
|
||||
However, various features specific to ESP-IDF FreeRTOS have been added. The features are as follows:
|
||||
|
||||
:ref:`ring-buffers`: Ring buffers were added to provide a form of buffer that could accept
|
||||
entries of arbitrary lengths.
|
||||
@@ -32,35 +32,35 @@ For efficiency reasons,
|
||||
items *must also be returned* to the ring buffer by using :cpp:func:`vRingbufferReturnItem` or :cpp:func:`vRingbufferReturnItemFromISR`, in order for them to be removed from the ring buffer completely.
|
||||
The ring buffers are split into the three following types:
|
||||
|
||||
**No-Split** buffers will guarantee that an item is stored in contiguous memory and will not
|
||||
attempt to split an item under any circumstances. Use no-split buffers when items must occupy
|
||||
contiguous memory. *Only this buffer type allows you getting the data item address and writting
|
||||
to the item by yourself.*
|
||||
**No-Split buffers** will guarantee that an item is stored in contiguous memory and will not
|
||||
attempt to split an item under any circumstances. Use No-Split buffers when items must occupy
|
||||
contiguous memory. *Only this buffer type allows you to get the data item address and write
|
||||
to the item by yourself.* Refer the documentation of the functions :cpp:func:`xRingbufferSendAcquire` and :cpp:func:`xRingbufferSendComplete` for more details.
|
||||
|
||||
**Allow-Split** buffers will allow an item to be split when wrapping around if doing so will allow
|
||||
the item to be stored. Allow-split buffers are more memory efficient than no-split buffers but
|
||||
can return an item in two parts when retrieving.
|
||||
**Allow-Split buffers** will allow an item to be split in two parts when wrapping around the end of the buffer if there
|
||||
is enough space at the tail and the head of the buffer combined to store the item. Allow-Split buffers are more memory
|
||||
efficient than No-Split buffers but can return an item in two parts when retrieving.
|
||||
|
||||
**Byte buffers** do not store data as separate items. All data is stored as a sequence of bytes,
|
||||
and any number of bytes and be sent or retrieved each time. Use byte buffers when separate items
|
||||
and any number of bytes can be sent or retrieved each time. Use byte buffers when separate items
|
||||
do not need to be maintained (e.g. a byte stream).
|
||||
|
||||
.. note::
|
||||
No-split/allow-split buffers will always store items at 32-bit aligned addresses. Therefore when
|
||||
No-Split buffers and Allow-Split buffers will always store items at 32-bit aligned addresses. Therefore, when
|
||||
retrieving an item, the item pointer is guaranteed to be 32-bit aligned. This is useful
|
||||
especially when you need to send some data to the DMA.
|
||||
|
||||
.. note::
|
||||
Each item stored in no-split/allow-split buffers will **require an additional 8 bytes for a header**.
|
||||
Each item stored in No-Split or Allow-Split buffers will **require an additional 8 bytes for a header**.
|
||||
Item sizes will also be rounded up to a 32-bit aligned size (multiple of 4 bytes), however the true
|
||||
item size is recorded within the header. The sizes of no-split/allow-split buffers will also
|
||||
item size is recorded within the header. The sizes of No-Split and Allow-Split buffers will also
|
||||
be rounded up when created.
|
||||
|
||||
Usage
|
||||
^^^^^
|
||||
|
||||
The following example demonstrates the usage of :cpp:func:`xRingbufferCreate`
|
||||
and :cpp:func:`xRingbufferSend` to create a ring buffer then send an item to it.
|
||||
and :cpp:func:`xRingbufferSend` to create a ring buffer and then send an item to it.
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
@@ -83,8 +83,8 @@ and :cpp:func:`xRingbufferSend` to create a ring buffer then send an item to it.
|
||||
}
|
||||
|
||||
The following example demonstrates the usage of :cpp:func:`xRingbufferSendAcquire` and
|
||||
:cpp:func:`xRingbufferSendComplete` instead of :cpp:func:`xRingbufferSend` to apply for the
|
||||
memory on the ring buffer (of type `RINGBUF_TYPE_NOSPLIT`) and then send an item to it. This way
|
||||
:cpp:func:`xRingbufferSendComplete` instead of :cpp:func:`xRingbufferSend` to acquire
|
||||
memory on the ring buffer (of type `RINGBUF_TYPE_NOSPLIT`) and then send an item to it. This
|
||||
adds one more step, but allows getting the address of the memory to write to, and writing to the
|
||||
memory yourself.
|
||||
|
||||
@@ -103,7 +103,7 @@ memory yourself.
|
||||
...
|
||||
|
||||
//Retrieve space for DMA descriptor and corresponding data buffer
|
||||
//This has to be done with SendAcquire, or the address may be different when copy
|
||||
//This has to be done with SendAcquire, or the address may be different when we copy
|
||||
dma_item_t item;
|
||||
UBaseType_t res = xRingbufferSendAcquire(buf_handle,
|
||||
&item, DMA_ITEM_SIZE(buffer_size), pdMS_TO_TICKS(1000));
|
||||
@@ -123,7 +123,7 @@ memory yourself.
|
||||
printf("Failed to send item\n");
|
||||
}
|
||||
|
||||
The following example demonstrates retrieving and returning an item from a **no-split ring buffer**
|
||||
The following example demonstrates retrieving and returning an item from a **No-Split ring buffer**
|
||||
using :cpp:func:`xRingbufferReceive` and :cpp:func:`vRingbufferReturnItem`
|
||||
|
||||
.. code-block:: c
|
||||
@@ -149,7 +149,7 @@ using :cpp:func:`xRingbufferReceive` and :cpp:func:`vRingbufferReturnItem`
|
||||
}
|
||||
|
||||
|
||||
The following example demonstrates retrieving and returning an item from an **allow-split ring buffer**
|
||||
The following example demonstrates retrieving and returning an item from an **Allow-Split ring buffer**
|
||||
using :cpp:func:`xRingbufferReceiveSplit` and :cpp:func:`vRingbufferReturnItem`
|
||||
|
||||
.. code-block:: c
|
||||
@@ -217,17 +217,17 @@ For ISR safe versions of the functions used above, call :cpp:func:`xRingbufferSe
|
||||
Sending to Ring Buffer
|
||||
^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
The following diagrams illustrate the differences between no-split/allow-split buffers
|
||||
and byte buffers with regards to sending items/data. The diagrams assume that three
|
||||
The following diagrams illustrate the differences between No-Split and Allow-Split buffers as compared to
|
||||
byte buffers with regard to sending items/data. The diagrams assume that three
|
||||
items of sizes **18, 3, and 27 bytes** are sent respectively to a **buffer of 128 bytes**.
|
||||
|
||||
.. packetdiag:: ../../../_static/diagrams/ring-buffer/ring_buffer_send_non_byte_buf.diag
|
||||
:caption: Sending items to no-split/allow-split ring buffers
|
||||
:caption: Sending items to No-Split or Allow-Split ring buffers
|
||||
:align: center
|
||||
|
||||
For no-split/allow-split buffers, a header of 8 bytes precedes every data item. Furthermore, the space
|
||||
For No-Split and Allow-Split buffers, a header of 8 bytes precedes every data item. Furthermore, the space
|
||||
occupied by each item is **rounded up to the nearest 32-bit aligned size** in order to maintain overall
|
||||
32-bit alignment. However the true size of the item is recorded inside the header which will be
|
||||
32-bit alignment. However, the true size of the item is recorded inside the header which will be
|
||||
returned when the item is retrieved.
|
||||
|
||||
Referring to the diagram above, the 18, 3, and 27 byte items are **rounded up to 20, 4, and 28 bytes**
|
||||
@@ -246,67 +246,67 @@ byte buffer and **merged into a single item of 48 bytes**.
|
||||
Using SendAcquire and SendComplete
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Items in no-split buffers are acquired (by SendAcquire) in strict FIFO order and must be sent to
|
||||
the buffer by SendComplete for the data to be accessible by the consumer. Multiple items can be
|
||||
sent or acquired without calling SendComplete, and the items do not necessarily need to be
|
||||
completed in the order they were acquired. However the receiving of data items must occur in FIFO
|
||||
order, therefore not calling SendComplete the earliest acquired item will prevent the subsequent
|
||||
Items in No-Split buffers are acquired (by ``SendAcquire``) in strict FIFO order and must be sent to
|
||||
the buffer by ``SendComplete`` for the data to be accessible by the consumer. Multiple items can be
|
||||
sent or acquired without calling ``SendComplete``, and the items do not necessarily need to be
|
||||
completed in the order they were acquired. However, the receiving of data items must occur in FIFO
|
||||
order, therefore not calling ``SendComplete`` for the earliest acquired item will prevent the subsequent
|
||||
items from being received.
|
||||
|
||||
The following diagrams illustrate what will happen when SendAcquire/SendComplete don't happen in
|
||||
the same order. At the beginning, there is already an data item of 16 bytes sent to the ring
|
||||
buffer. Then SendAcquire is called to acquire space of 20, 8, 24 bytes on the ring buffer.
|
||||
The following diagrams illustrate what will happen when ``SendAcquire`` and ``SendComplete`` don't happen in
|
||||
the same order. At the beginning, there is already a data item of 16 bytes sent to the ring
|
||||
buffer. Then ``SendAcquire`` is called to acquire space of 20, 8, 24 bytes on the ring buffer.
|
||||
|
||||
.. packetdiag:: ../../../_static/diagrams/ring-buffer/ring_buffer_send_acquire_complete.diag
|
||||
:caption: SendAcquire/SendComplete items in no-split ring buffers
|
||||
:caption: SendAcquire/SendComplete items in No-Split ring buffers
|
||||
:align: center
|
||||
|
||||
After that, we fill (use) the buffers, and send them to the ring buffer by SendComplete in the
|
||||
After that, we fill (use) the buffers, and send them to the ring buffer by ``SendComplete`` in the
|
||||
order of 8, 24, 20. When 8 bytes and 24 bytes data are sent, the consumer still can only get the
|
||||
16 bytes data item. Due to the usage if 20 bytes item is not complete, it's not available, nor
|
||||
the following data items.
|
||||
16 bytes data item. Hence, if ``SendComplete`` is not called for the 20 bytes, it will not be available, nor will
|
||||
the data items following the 20 bytes item.
|
||||
|
||||
When the 20 bytes item is finally completed, all the 3 data items can be received now, in the
|
||||
order of 20, 8, 24 bytes, right after the 16 bytes item existing in the buffer at the beginning.
|
||||
|
||||
Allow-split/byte buffers do not allow using SendAcquire/SendComplete since acquired buffers are
|
||||
Allow-Split buffers and byte buffers do not allow using ``SendAcquire`` or ``SendComplete`` since acquired buffers are
|
||||
required to be complete (not wrapped).
|
||||
|
||||
|
||||
Wrap around
|
||||
^^^^^^^^^^^
|
||||
|
||||
The following diagrams illustrate the differences between no-split, allow-split, and byte
|
||||
buffers when a sent item requires a wrap around. The diagrams assumes a buffer of **128 bytes**
|
||||
The following diagrams illustrate the differences between No-Split, Allow-Split, and byte
|
||||
buffers when a sent item requires a wrap around. The diagrams assume a buffer of **128 bytes**
|
||||
with **56 bytes of free space that wraps around** and a sent item of **28 bytes**.
|
||||
|
||||
.. packetdiag:: ../../../_static/diagrams/ring-buffer/ring_buffer_wrap_no_split.diag
|
||||
:caption: Wrap around in no-split buffers
|
||||
:caption: Wrap around in No-Split buffers
|
||||
:align: center
|
||||
|
||||
No-split buffers will **only store an item in continuous free space and will not split
|
||||
No-Split buffers will **only store an item in continuous free space and will not split
|
||||
an item under any circumstances**. When the free space at the tail of the buffer is insufficient
|
||||
to completely store the item and its header, the free space at the tail will be **marked as dummy data**.
|
||||
The buffer will then wrap around and store the item in the free space at the head of the buffer.
|
||||
|
||||
Referring to the diagram above, the 16 bytes of free space at the tail of the buffer is
|
||||
insufficient to store the 28 byte item. Therefore the 16 bytes is marked as dummy data and
|
||||
insufficient to store the 28 byte item. Therefore, the 16 bytes is marked as dummy data and
|
||||
the item is written to the free space at the head of the buffer instead.
|
||||
|
||||
.. packetdiag:: ../../../_static/diagrams/ring-buffer/ring_buffer_wrap_allow_split.diag
|
||||
:caption: Wrap around in allow-split buffers
|
||||
:caption: Wrap around in Allow-Split buffers
|
||||
:align: center
|
||||
|
||||
Allow-split buffers will attempt to **split the item into two parts** when the free space at the tail
|
||||
Allow-Split buffers will attempt to **split the item into two parts** when the free space at the tail
|
||||
of the buffer is insufficient to store the item data and its header. Both parts of the
|
||||
split item will have their own headers (therefore incurring an extra 8 bytes of overhead).
|
||||
|
||||
Referring to the diagram above, the 16 bytes of free space at the tail of the buffer is insufficient
|
||||
to store the 28 byte item. Therefore the item is split into two parts (8 and 20 bytes) and written
|
||||
to store the 28 byte item. Therefore, the item is split into two parts (8 and 20 bytes) and written
|
||||
as two parts to the buffer.
|
||||
|
||||
.. note::
|
||||
Allow-split buffers treats the both parts of the split item as two separate items, therefore call
|
||||
Allow-Split buffers treat both parts of the split item as two separate items, therefore call
|
||||
:cpp:func:`xRingbufferReceiveSplit` instead of :cpp:func:`xRingbufferReceive` to receive both
|
||||
parts of a split item in a thread safe manner.
|
||||
|
||||
@@ -319,30 +319,30 @@ data will then be stored in the free space at the head of the buffer. No overhea
|
||||
around in byte buffers.
|
||||
|
||||
Referring to the diagram above, the 16 bytes of free space at the tail of the buffer is insufficient to
|
||||
completely store the 28 bytes of data. Therefore the 16 bytes of free space is filled with data, and the
|
||||
completely store the 28 bytes of data. Therefore, the 16 bytes of free space is filled with data, and the
|
||||
remaining 12 bytes are written to the free space at the head of the buffer. The buffer now contains
|
||||
data in two separate continuous parts, and each part continuous will be treated as a separate item by the
|
||||
data in two separate continuous parts, and each continuous part will be treated as a separate item by the
|
||||
byte buffer.
|
||||
|
||||
Retrieving/Returning
|
||||
^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
The following diagrams illustrates the differences between no-split/allow-split and
|
||||
The following diagrams illustrate the differences between No-Split and Allow-Split buffers as compared to
|
||||
byte buffers in retrieving and returning data.
|
||||
|
||||
.. packetdiag:: ../../../_static/diagrams/ring-buffer/ring_buffer_read_ret_non_byte_buf.diag
|
||||
:caption: Retrieving/Returning items in no-split/allow-split ring buffers
|
||||
:caption: Retrieving/Returning items in No-Split and Allow-Split ring buffers
|
||||
:align: center
|
||||
|
||||
Items in no-split/allow-split buffers are **retrieved in strict FIFO order** and **must be returned**
|
||||
Items in No-Split buffers and Allow-Split buffers are **retrieved in strict FIFO order** and **must be returned**
|
||||
for the occupied space to be freed. Multiple items can be retrieved before returning, and the items
|
||||
do not necessarily need to be returned in the order they were retrieved. However the freeing of space
|
||||
do not necessarily need to be returned in the order they were retrieved. However, the freeing of space
|
||||
must occur in FIFO order, therefore not returning the earliest retrieved item will prevent the space
|
||||
of subsequent items from being freed.
|
||||
|
||||
Referring to the diagram above, the **16, 20, and 8 byte items are retrieved in FIFO order**. However the items
|
||||
are not returned in they were retrieved (20, 8, 16). As such, the space is not freed until the first item
|
||||
(16 byte) is returned.
|
||||
Referring to the diagram above, the **16, 20, and 8 byte items are retrieved in FIFO order**. However, the items
|
||||
are not returned in the order they were retrieved. First, the 20 byte item is returned followed by the 8 byte and the 16
|
||||
byte items. The space is not freed until the first item, i.e., the 16 byte item is returned.
|
||||
|
||||
.. packetdiag:: ../../../_static/diagrams/ring-buffer/ring_buffer_read_ret_byte_buf.diag
|
||||
:caption: Retrieving/Returning data in byte buffers
|
||||
@@ -408,7 +408,7 @@ Ring Buffers with Static Allocation
|
||||
The :cpp:func:`xRingbufferCreateStatic` can be used to create ring buffers with specific memory requirements (such as a ring buffer being allocated in external RAM). All blocks of memory used by a ring buffer must be manually allocated beforehand then passed to the :cpp:func:`xRingbufferCreateStatic` to be initialized as a ring buffer. These blocks include the following:
|
||||
|
||||
- The ring buffer's data structure of type :cpp:type:`StaticRingbuffer_t`
|
||||
- The ring buffer's storage area of size ``xBufferSize``. Note that ``xBufferSize`` must be 32-bit aligned for no-split/allow-split buffers.
|
||||
- The ring buffer's storage area of size ``xBufferSize``. Note that ``xBufferSize`` must be 32-bit aligned for No-Split and Allow-Split buffers.
|
||||
|
||||
The manner in which these blocks are allocated will depend on the users requirements (e.g. all blocks being statically declared, or dynamically allocated with specific capabilities such as external RAM).
|
||||
|
||||
@@ -460,11 +460,11 @@ Ring Buffer API Reference
|
||||
this should prevent any lower priority tasks from being serviced as the semaphore should
|
||||
always be given to the highest priority task.
|
||||
|
||||
However in between iterations of acquiring the semaphore, there is a **gap in the critical
|
||||
However, in between iterations of acquiring the semaphore, there is a **gap in the critical
|
||||
section** which may permit another task (on the other core or with an even higher priority) to
|
||||
free some space on the ring buffer and as a result give the semaphore. Therefore the semaphore
|
||||
free some space on the ring buffer and as a result give the semaphore. Therefore, the semaphore
|
||||
will be given before the highest priority task can re-acquire the semaphore. This will result
|
||||
in the **semaphore being acquired by the second highest priority task** waiting to send, hence
|
||||
in the **semaphore being acquired by the second-highest priority task** waiting to send, hence
|
||||
causing priority inversion.
|
||||
|
||||
This side effect will not affect ring buffer performance drastically given if the number
|
||||
@@ -482,7 +482,7 @@ Hooks
|
||||
FreeRTOS consists of Idle Hooks and Tick Hooks which allow for application
|
||||
specific functionality to be added to the Idle Task and Tick Interrupt.
|
||||
ESP-IDF provides its own Idle and Tick Hook API in addition to the hooks
|
||||
provided by Vanilla FreeRTOS. ESP-IDF hooks have the added benefit of
|
||||
provided by vanilla FreeRTOS. ESP-IDF hooks have the added benefit of
|
||||
being run time configurable and asymmetrical.
|
||||
|
||||
Vanilla FreeRTOS Hooks
|
||||
@@ -501,7 +501,7 @@ in :doc:`project configuration menu </api-reference/kconfig>`.
|
||||
.. only:: not CONFIG_FREERTOS_UNICORE
|
||||
|
||||
Due to vanilla FreeRTOS being designed for single core, ``vApplicationIdleHook()``
|
||||
and ``vApplicationTickHook()`` can only be defined once. However, the {IDF_TARGET_NAME} is dual core
|
||||
and ``vApplicationTickHook()`` can only be defined once. However, the {IDF_TARGET_NAME} is dual-core
|
||||
in nature, therefore same Idle Hook and Tick Hook are used for both cores (in other words,
|
||||
the hooks are symmetrical for both cores).
|
||||
|
||||
@@ -513,15 +513,15 @@ that are configurable at run time.
|
||||
|
||||
.. only:: not CONFIG_FREERTOS_UNICORE
|
||||
|
||||
Furthermore, due to the the dual core nature of the {IDF_TARGET_NAME}, it may be necessary for some
|
||||
Furthermore, due to the dual-core nature of the {IDF_TARGET_NAME}, it may be necessary for some
|
||||
applications to have separate hooks for each core.
|
||||
|
||||
Therefore the ESP-IDF provides it's own hooks API in addition to the legacy hooks provided
|
||||
by Vanilla FreeRTOS.
|
||||
Therefore, ESP-IDF provides its own hooks API in addition to the legacy hooks provided
|
||||
by vanilla FreeRTOS.
|
||||
|
||||
The ESP-IDF tick/idle hooks are registered at run time, and each tick/idle hook
|
||||
must be registered to a specific CPU. When the idle task runs/tick Interrupt
|
||||
occurs on a particular CPU, the CPU will run each of its registered idle/tick hooks
|
||||
The ESP-IDF tick and idle hooks are registered at run time. Each tick hook and idle hook
|
||||
must be registered to a specific CPU. When the idle task runs or a tick interrupt
|
||||
occurs on a particular CPU, the CPU will run each of its registered idle hook and tick hook
|
||||
in turn.
|
||||
|
||||
.. note:: Tick interrupt stays active whilst cache is disabled and hence ``vApplicationTickHook()`` (legacy case) or ESP-IDF tick hooks must be placed in internal RAM. Please refer to the :ref:`SPI flash API documentation <iram-safe-interrupt-handlers>` for more details.
|
||||
@@ -538,6 +538,6 @@ Hooks API Reference
|
||||
Component Specific Properties
|
||||
-----------------------------
|
||||
|
||||
Besides standard component variables that could be gotten with basic cmake build properties FreeRTOS component also provides an arguments (only one so far) for simpler integration with other modules:
|
||||
Besides standard component variables that are available with basic cmake build properties, FreeRTOS component also provides arguments (only one so far) for simpler integration with other modules:
|
||||
|
||||
- `ORIG_INCLUDE_PATH` - contains an absolute path to freertos root include folder. Thus instead of `#include "freertos/FreeRTOS.h"` you can refer to headers directly: `#include "FreeRTOS.h"`.
|
||||
|
||||
@@ -18,7 +18,7 @@ To obtain information about the state of the heap:
|
||||
- :cpp:func:`xPortGetFreeHeapSize` is a FreeRTOS function which returns the number of free bytes in the (data memory) heap. This is equivalent to calling ``heap_caps_get_free_size(MALLOC_CAP_8BIT)``.
|
||||
- :cpp:func:`heap_caps_get_free_size` can also be used to return the current free memory for different memory capabilities.
|
||||
- :cpp:func:`heap_caps_get_largest_free_block` can be used to return the largest free block in the heap. This is the largest single allocation which is currently possible. Tracking this value and comparing to total free heap allows you to detect heap fragmentation.
|
||||
- :cpp:func:`xPortGetMinimumEverFreeHeapSize` and the related :cpp:func:`heap_caps_get_minimum_free_size` can be used to track the heap "low water mark" since boot.
|
||||
- :cpp:func:`xPortGetMinimumEverFreeHeapSize` and the related :cpp:func:`heap_caps_get_minimum_free_size` can be used to track the heap "low watermark" since boot.
|
||||
- :cpp:func:`heap_caps_get_info` returns a :cpp:class:`multi_heap_info_t` structure which contains the information from the above functions, plus some additional heap-specific data (number of allocations, etc.).
|
||||
- :cpp:func:`heap_caps_print_heap_info` prints a summary to stdout of the information returned by :cpp:func:`heap_caps_get_info`.
|
||||
- :cpp:func:`heap_caps_dump` and :cpp:func:`heap_caps_dump_all` will output detailed information about the structure of each block in the heap. Note that this can be large amount of output.
|
||||
@@ -47,13 +47,13 @@ It's also possible to manually check heap integrity by calling :cpp:func:`heap_c
|
||||
Memory Allocation Failed Hook
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Users can use :cpp:func:`heap_caps_register_failed_alloc_callback` to register a callback that will be invoked every time a allocation
|
||||
Users can use :cpp:func:`heap_caps_register_failed_alloc_callback` to register a callback that will be invoked every time an allocation
|
||||
operation fails.
|
||||
|
||||
Additionaly user can enable a generation of a system abort if allocation operation fails by following the steps below:
|
||||
Additionally, users can enable the generation of a system abort if an allocation operation fails by following the steps below:
|
||||
- In the project configuration menu, navigate to ``Component config`` -> ``Heap Memory Debugging`` and select ``Abort if memory allocation fails`` option (see :ref:`CONFIG_HEAP_ABORT_WHEN_ALLOCATION_FAILS`).
|
||||
|
||||
The example below show how to register a allocation failure callback::
|
||||
The example below shows how to register an allocation failure callback::
|
||||
|
||||
#include "esp_heap_caps.h"
|
||||
|
||||
@@ -80,7 +80,7 @@ Memory corruption can be one of the hardest classes of bugs to find and fix, as
|
||||
- Increasing the Heap memory debugging `Configuration`_ level to "Light impact" or "Comprehensive" can give you a more accurate message with the first corrupt memory address.
|
||||
- Adding regular calls to :cpp:func:`heap_caps_check_integrity_all` or :cpp:func:`heap_caps_check_integrity_addr` in your code will help you pin down the exact time that the corruption happened. You can move these checks around to "close in on" the section of code that corrupted the heap.
|
||||
- Based on the memory address which is being corrupted, you can use :ref:`JTAG debugging <jtag-debugging-introduction>` to set a watchpoint on this address and have the CPU halt when it is written to.
|
||||
- If you don't have JTAG, but you do know roughly when the corruption happens, then you can set a watchpoint in software just beforehand via :cpp:func:`esp_cpu_set_watchpoint`. A fatal exception will occur when the watchpoint triggers. For example ``esp_cpu_set_watchpoint(0, (void *)addr, 4, ESP_WATCHPOINT_STORE``. Note that watchpoints are per-CPU and are set on the current running CPU only, so if you don't know which CPU is corrupting memory then you will need to call this function on both CPUs.
|
||||
- If you don't have JTAG, but you do know roughly when the corruption happens, then you can set a watchpoint in software just beforehand via :cpp:func:`esp_cpu_set_watchpoint`. A fatal exception will occur when the watchpoint triggers. The following is an example of how to use the function - ``esp_cpu_set_watchpoint(0, (void *)addr, 4, ESP_WATCHPOINT_STORE)``. Note that watchpoints are per-CPU and are set on the current running CPU only, so if you don't know which CPU is corrupting memory then you will need to call this function on both CPUs.
|
||||
- For buffer overflows, `heap tracing`_ in ``HEAP_TRACE_ALL`` mode lets you see which callers are allocating which addresses from the heap. See `Heap Tracing To Find Heap Corruption`_ for more details. If you can find the function which allocates memory with an address immediately before the address which is corrupted, this will probably be the function which overflows the buffer.
|
||||
- Calling :cpp:func:`heap_caps_dump` or :cpp:func:`heap_caps_dump_all` can give an indication of what heap blocks are surrounding the corrupted region and may have overflowed/underflowed/etc.
|
||||
|
||||
@@ -125,7 +125,7 @@ Comprehensive
|
||||
|
||||
This level incorporates the "light impact" detection features plus additional checks for uninitialised-access and use-after-free bugs. In this mode, all freshly allocated memory is filled with the pattern 0xCE, and all freed memory is filled with the pattern 0xFE.
|
||||
|
||||
Enabling "Comprehensive" detection has a substantial runtime performance impact (as all memory needs to be set to the allocation patterns each time a malloc/free completes, and the memory also needs to be checked each time.) However it allows easier detection of memory corruption bugs which are much more subtle to find otherwise. It is recommended to only enable this mode when debugging, not in production.
|
||||
Enabling "Comprehensive" detection has a substantial runtime performance impact (as all memory needs to be set to the allocation patterns each time a malloc/free completes, and the memory also needs to be checked each time.) However, it allows easier detection of memory corruption bugs which are much more subtle to find otherwise. It is recommended to only enable this mode when debugging, not in production.
|
||||
|
||||
Crashes in Comprehensive Mode
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
@@ -251,7 +251,7 @@ In ``HEAP_TRACE_LEAKS`` mode, for each traced memory allocation which has not al
|
||||
|
||||
.. list::
|
||||
|
||||
- ``XX bytes`` is number of bytes allocated
|
||||
- ``XX bytes`` is the number of bytes allocated
|
||||
- ``@ 0x...`` is the heap address returned from malloc/calloc.
|
||||
- ``CPU x`` is the CPU (0 or 1) running when the allocation was made.
|
||||
- ``ccount 0x...`` is the CCOUNT (CPU cycle count) register value when the allocation was mode. Is different for CPU 0 vs CPU 1.
|
||||
@@ -276,7 +276,7 @@ Once you've identified the code which you think is leaking:
|
||||
- In the project configuration menu, navigate to ``Component settings`` -> ``Application Level Tracing`` -> ``FreeRTOS SystemView Tracing`` and enable :ref:`CONFIG_APPTRACE_SV_ENABLE`.
|
||||
- Call the function :cpp:func:`heap_trace_init_tohost` early in the program, to initialize JTAG heap tracing module.
|
||||
- Call the function :cpp:func:`heap_trace_start` to begin recording all mallocs/frees in the system. Call this immediately before the piece of code which you suspect is leaking memory.
|
||||
In host-based mode argument to this function is ignored and heap tracing module behaves like ``HEAP_TRACE_ALL`` was passed: all allocations and deallocations are sent to the host.
|
||||
In host-based mode, the argument to this function is ignored, and the heap tracing module behaves like ``HEAP_TRACE_ALL`` was passed: all allocations and deallocations are sent to the host.
|
||||
- Call the function :cpp:func:`heap_trace_stop` to stop the trace once the suspect piece of code has finished executing.
|
||||
|
||||
An example::
|
||||
@@ -428,7 +428,7 @@ Heap Tracing To Find Heap Corruption
|
||||
|
||||
Heap tracing can also be used to help track down heap corruption. When a region in heap is corrupted, it may be from some other part of the program which allocated memory at a nearby address.
|
||||
|
||||
If you have some idea at what time the corruption occurred, enabling heap tracing in ``HEAP_TRACE_ALL`` mode allows you to record all of the functions which allocated memory, and the addresses of the allocations.
|
||||
If you have some idea at what time the corruption occurred, enabling heap tracing in ``HEAP_TRACE_ALL`` mode allows you to record all the functions which allocated memory, and the addresses of the allocations.
|
||||
|
||||
Using heap tracing in this way is very similar to memory leak detection as described above. For memory which is allocated and not freed, the output is the same. However, records will also be shown for memory which has been freed.
|
||||
|
||||
@@ -448,7 +448,7 @@ Not everything printed by :cpp:func:`heap_trace_dump` is necessarily a memory le
|
||||
- Allocations may be made by other tasks in the system. Depending on the timing of these tasks, it's quite possible this memory is freed after :cpp:func:`heap_trace_stop` is called.
|
||||
- The first time a task uses stdio - for example, when it calls ``printf()`` - a lock (RTOS mutex semaphore) is allocated by the libc. This allocation lasts until the task is deleted.
|
||||
- Certain uses of ``printf()``, such as printing floating point numbers, will allocate some memory from the heap on demand. These allocations last until the task is deleted.
|
||||
- The Bluetooth, WiFi, and TCP/IP libraries will allocate heap memory buffers to handle incoming or outgoing data. These memory buffers are usually short lived, but some may be shown in the heap leak trace if the data was received/transmitted by the lower levels of the network while the leak trace was running.
|
||||
- The Bluetooth, Wi-Fi, and TCP/IP libraries will allocate heap memory buffers to handle incoming or outgoing data. These memory buffers are usually short-lived, but some may be shown in the heap leak trace if the data was received/transmitted by the lower levels of the network while the leak trace was running.
|
||||
- TCP connections will continue to use some memory after they are closed, because of the ``TIME_WAIT`` state. After the ``TIME_WAIT`` period has completed, this memory will be freed.
|
||||
|
||||
One way to differentiate between "real" and "false positive" memory leaks is to call the suspect code multiple times while tracing is running, and look for patterns (multiple matching allocations) in the heap trace output.
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
Application Example
|
||||
-------------------
|
||||
|
||||
The logging library is commonly used by most esp-idf components and examples. For demonstration of log functionality, check ESP-IDF's :idf:`examples` directory. The most revelant examples that deal with logging are the following:
|
||||
The logging library is commonly used by most esp-idf components and examples. For demonstration of log functionality, check ESP-IDF's :idf:`examples` directory. The most relevant examples that deal with logging are the following:
|
||||
|
||||
* :example:`system/ota`
|
||||
* :example:`storage/sd_card`
|
||||
|
||||
@@ -18,7 +18,7 @@ OTA Data Partition
|
||||
|
||||
An OTA data partition (type ``data``, subtype ``ota``) must be included in the :doc:`Partition Table <../../api-guides/partition-tables>` of any project which uses the OTA functions.
|
||||
|
||||
For factory boot settings, the OTA data partition should contain no data (all bytes erased to 0xFF). In this case the esp-idf software bootloader will boot the factory app if it is present in the the partition table. If no factory app is included in the partition table, the first available OTA slot (usually ``ota_0``) is booted.
|
||||
For factory boot settings, the OTA data partition should contain no data (all bytes erased to 0xFF). In this case the esp-idf software bootloader will boot the factory app if it is present in the partition table. If no factory app is included in the partition table, the first available OTA slot (usually ``ota_0``) is booted.
|
||||
|
||||
After the first OTA update, the OTA data partition is updated to specify which OTA app slot partition should be booted next.
|
||||
|
||||
@@ -35,7 +35,7 @@ The main purpose of the application rollback is to keep the device working after
|
||||
* The application has critical errors and further work is not possible, a rollback to the previous application is required, :cpp:func:`esp_ota_mark_app_invalid_rollback_and_reboot` marks the running application with the state ``ESP_OTA_IMG_INVALID`` and reset. This application will not be selected by the bootloader for boot and will boot the previously working application.
|
||||
* If the :ref:`CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE` option is set, and a reset occurs without calling either function then the application is rolled back.
|
||||
|
||||
Note: The state is not written to the binary image of the application it is written to the ``otadata`` partition. The partition contains a ``ota_seq`` counter which is a pointer to the slot (ota_0, ota_1, ...) from which the application will be selected for boot.
|
||||
.. note:: The state is not written to the binary image of the application but rather to the ``otadata`` partition. The partition contains a ``ota_seq`` counter which is a pointer to the slot (ota_0, ota_1, ...) from which the application will be selected for boot.
|
||||
|
||||
App OTA State
|
||||
^^^^^^^^^^^^^
|
||||
@@ -53,7 +53,7 @@ States control the process of selecting a boot app:
|
||||
be selected only once. In bootloader the state immediately changes to
|
||||
``ESP_OTA_IMG_PENDING_VERIFY``.
|
||||
ESP_OTA_IMG_PENDING_VERIFY If :ref:`CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE` option is set it will
|
||||
not be selected and the state will change to ``ESP_OTA_IMG_ABORTED``.
|
||||
not be selected, and the state will change to ``ESP_OTA_IMG_ABORTED``.
|
||||
============================= ======================================================================
|
||||
|
||||
If :ref:`CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE` option is not enabled (by default), then the use of the following functions :cpp:func:`esp_ota_mark_app_valid_cancel_rollback` and :cpp:func:`esp_ota_mark_app_invalid_rollback_and_reboot` are optional, and ``ESP_OTA_IMG_NEW`` and ``ESP_OTA_IMG_PENDING_VERIFY`` states are not used.
|
||||
@@ -65,11 +65,11 @@ Rollback Process
|
||||
|
||||
The description of the rollback process when :ref:`CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE` option is enabled:
|
||||
|
||||
* The new application successfully downloaded and :cpp:func:`esp_ota_set_boot_partition` function makes this partition bootable and sets the state ``ESP_OTA_IMG_NEW``. This state means that the application is new and should be monitored for its first boot.
|
||||
* The new application is successfully downloaded and :cpp:func:`esp_ota_set_boot_partition` function makes this partition bootable and sets the state ``ESP_OTA_IMG_NEW``. This state means that the application is new and should be monitored for its first boot.
|
||||
* Reboot :cpp:func:`esp_restart`.
|
||||
* The bootloader checks for the ``ESP_OTA_IMG_PENDING_VERIFY`` state if it is set, then it will be written to ``ESP_OTA_IMG_ABORTED``.
|
||||
* The bootloader selects a new application to boot so that the state is not set as ``ESP_OTA_IMG_INVALID`` or ``ESP_OTA_IMG_ABORTED``.
|
||||
* The bootloader checks the selected application for ``ESP_OTA_IMG_NEW`` state if it is set, then it will be written to ``ESP_OTA_IMG_PENDING_VERIFY``. This state means that the application requires confirmation of its operability, if this does not happen and a reboot occurs, this state will be overwritten to ``ESP_OTA_IMG_ABORTED`` (see above) and this application will no longer be able to start, i.e. there will be a rollback to the previous work application.
|
||||
* The bootloader checks the selected application for ``ESP_OTA_IMG_NEW`` state if it is set, then it will be written to ``ESP_OTA_IMG_PENDING_VERIFY``. This state means that the application requires confirmation of its operability, if this does not happen and a reboot occurs, this state will be overwritten to ``ESP_OTA_IMG_ABORTED`` (see above) and this application will no longer be able to start, i.e. there will be a rollback to the previous working application.
|
||||
* A new application has started and should make a self-test.
|
||||
* If the self-test has completed successfully, then you must call the function :cpp:func:`esp_ota_mark_app_valid_cancel_rollback` because the application is awaiting confirmation of operability (``ESP_OTA_IMG_PENDING_VERIFY`` state).
|
||||
* If the self-test fails then call :cpp:func:`esp_ota_mark_app_invalid_rollback_and_reboot` function to roll back to the previous working application, while the invalid application is set ``ESP_OTA_IMG_INVALID`` state.
|
||||
@@ -128,12 +128,12 @@ A typical anti-rollback scheme is
|
||||
- To make it bootable, run the function :cpp:func:`esp_ota_set_boot_partition`. If the security version of the new application is smaller than the version in the chip, the new application will be erased. Update to new firmware is not possible.
|
||||
- Reboot.
|
||||
- In the bootloader, an application with a security version greater than or equal to the version in the chip will be selected. If otadata is in the initial state, and one firmware was loaded via a serial channel, whose secure version is higher than the chip, then the secure version of efuse will be immediately updated in the bootloader.
|
||||
- New application booted. Then the application should perform diagnostics of the operation and if it is completed successfully, you should call :cpp:func:`esp_ota_mark_app_valid_cancel_rollback` function to mark the running application with the ``ESP_OTA_IMG_VALID`` state and update the secure version on chip. Note that if was called :cpp:func:`esp_ota_mark_app_invalid_rollback_and_reboot` function a rollback may not happend due to the device may not have any bootable apps then it will return ``ESP_ERR_OTA_ROLLBACK_FAILED`` error and stay in the ``ESP_OTA_IMG_PENDING_VERIFY`` state.
|
||||
- New application booted. Then the application should perform diagnostics of the operation and if it is completed successfully, you should call :cpp:func:`esp_ota_mark_app_valid_cancel_rollback` function to mark the running application with the ``ESP_OTA_IMG_VALID`` state and update the secure version on chip. Note that if was called :cpp:func:`esp_ota_mark_app_invalid_rollback_and_reboot` function a rollback may not happen as the device may not have any bootable apps. It will then return ``ESP_ERR_OTA_ROLLBACK_FAILED`` error and stay in the ``ESP_OTA_IMG_PENDING_VERIFY`` state.
|
||||
- The next update of app is possible if a running app is in the ``ESP_OTA_IMG_VALID`` state.
|
||||
|
||||
Recommendation:
|
||||
|
||||
If you want to avoid the download/erase overhead in case of the app from the server has security version lower then running app, you have to get ``new_app_info.secure_version`` from the first package of an image and compare it with the secure version of efuse. Use ``esp_efuse_check_secure_version(new_app_info.secure_version)`` function if it is true then continue downloading otherwise abort.
|
||||
If you want to avoid the download/erase overhead in case of the app from the server has security version lower than the running app, you have to get ``new_app_info.secure_version`` from the first package of an image and compare it with the secure version of efuse. Use ``esp_efuse_check_secure_version(new_app_info.secure_version)`` function if it is true then continue downloading otherwise abort.
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ Unlike many operating systems using POSIX Threads, ESP-IDF is a real-time operat
|
||||
|
||||
If calling a standard libc or C++ sleep function, such as ``usleep`` defined in ``unistd.h``, then the task will only block and yield the CPU if the sleep time is longer than :ref:`one FreeRTOS tick period <CONFIG_FREERTOS_HZ>`. If the time is shorter, the thread will busy-wait instead of yielding to another RTOS task.
|
||||
|
||||
By default all POSIX Threads have the same RTOS priority, but it is possible to change this by calling a :ref:`custom API <esp-pthread>`.
|
||||
By default, all POSIX Threads have the same RTOS priority, but it is possible to change this by calling a :ref:`custom API <esp-pthread>`.
|
||||
|
||||
Standard features
|
||||
-----------------
|
||||
@@ -98,6 +98,20 @@ Static initializer constant ``PTHREAD_COND_INITIALIZER`` is supported.
|
||||
|
||||
.. note:: These functions can be called from tasks created using either pthread or FreeRTOS APIs
|
||||
|
||||
Read/Write Locks
|
||||
^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
* ``pthread_rwlock_init()``
|
||||
- The ``attr`` argument is not implemented and is ignored.
|
||||
* ``pthread_rwlock_destroy()``
|
||||
* ``pthread_rwlock_rdlock()``
|
||||
* ``pthread_rwlock_wrlock()``
|
||||
* ``pthread_rwlock_unlock()``
|
||||
|
||||
Static initializer constant ``PTHREAD_RWLOCK_INITIALIZER`` is supported.
|
||||
|
||||
.. note:: These functions can be called from tasks created using either pthread or FreeRTOS APIs
|
||||
|
||||
Thread-Specific Data
|
||||
^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
@@ -125,7 +139,7 @@ Other POSIX Threads functions (not listed here) are not implemented and will pro
|
||||
ESP-IDF Extensions
|
||||
------------------
|
||||
|
||||
The API :cpp:func:`esp_pthread_set_cfg` defined in the ``esp_pthreads.h`` header offers custom extensions to control how subsequent calls to ``pthread_create()`` will behave. Currently the following configuration can be set:
|
||||
The API :cpp:func:`esp_pthread_set_cfg` defined in the ``esp_pthreads.h`` header offers custom extensions to control how subsequent calls to ``pthread_create()`` will behave. Currently, the following configuration can be set:
|
||||
|
||||
.. list::
|
||||
- Default stack size of new threads, if not specified when calling ``pthread_create()`` (overrides :ref:`CONFIG_PTHREAD_TASK_STACK_SIZE_DEFAULT`).
|
||||
|
||||
@@ -89,7 +89,7 @@ In ESP-IDF these addresses are calculated from a single *Base MAC address*. By d
|
||||
|
||||
.. only:: not SOC_EMAC_SUPPORTED
|
||||
|
||||
.. note:: {IDF_TARGET_NAME} has no integrated Ethernet MAC, but it's still possible to calculate an Ethernet MAC address. This MAC address can only be used with an external interface such as a SPI-Ethernet device, see :doc:`/api-reference/network/esp_eth`.
|
||||
.. note:: {IDF_TARGET_NAME} has no integrated Ethernet MAC, but it's still possible to calculate an Ethernet MAC address. This MAC address can only be used with an external interface such as an SPI-Ethernet device, see :doc:`/api-reference/network/esp_eth`.
|
||||
|
||||
Custom Base MAC
|
||||
^^^^^^^^^^^^^^^
|
||||
@@ -147,7 +147,7 @@ Once MAC address has been obtained using :cpp:func:`esp_efuse_mac_get_custom`, c
|
||||
Local vs Universal MAC addresses
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
{IDF_TARGET_NAME} comes pre-programmed with enough valid Espressif universally administered MAC addresses for all internal interfaces. The specific calculations to derive an interface's MAC address from the base MAC address is shown in the table above..
|
||||
{IDF_TARGET_NAME} comes pre-programmed with enough valid Espressif universally administered MAC addresses for all internal interfaces. The specific calculations to derive an interface's MAC address from the base MAC address is shown in the table above.
|
||||
|
||||
When using a custom MAC address scheme, it's possible that not all interfaces can be assigned a universally administered MAC address. In these cases, a locally administered MAC address is assigned. Note that these addresses are intended for use on a single local network, only.
|
||||
|
||||
@@ -196,7 +196,7 @@ To set version in your project manually you need to set ``PROJECT_VER`` variable
|
||||
|
||||
* In application CMakeLists.txt put ``set(PROJECT_VER "0.1.0.1")`` before including ``project.cmake``.
|
||||
|
||||
If :ref:`CONFIG_APP_PROJECT_VER_FROM_CONFIG` option is set, the value of :ref:`CONFIG_APP_PROJECT_VER` will be used. Otherwise if ``PROJECT_VER`` variable is not set in the project then it will be retrieved from either ``$(PROJECT_PATH)/version.txt`` file (if present) else using git command ``git describe``. If neither is available then ``PROJECT_VER`` will be set to "1". Application can make use of this by calling :cpp:func:`esp_ota_get_app_description` or :cpp:func:`esp_ota_get_partition_description` functions.
|
||||
If :ref:`CONFIG_APP_PROJECT_VER_FROM_CONFIG` option is set, the value of :ref:`CONFIG_APP_PROJECT_VER` will be used. Otherwise, if ``PROJECT_VER`` variable is not set in the project then it will be retrieved from either ``$(PROJECT_PATH)/version.txt`` file (if present) else using git command ``git describe``. If neither is available then ``PROJECT_VER`` will be set to "1". Application can make use of this by calling :cpp:func:`esp_ota_get_app_description` or :cpp:func:`esp_ota_get_partition_description` functions.
|
||||
|
||||
API Reference
|
||||
-------------
|
||||
|
||||
@@ -2,7 +2,7 @@ System Time
|
||||
===========
|
||||
|
||||
{IDF_TARGET_RTC_CLK_FRE:default="150kHz", esp32s2="90kHz"}
|
||||
{IDF_TARGET_HARDWARE_DESIGN_URL:default="`ESP32 Hardware Design Guidelines <https://www.espressif.com/sites/default/files/documentation/esp32_hardware_design_guidelines_en.pdf#page=10>`_", esp32="`ESP32 Hardware Design Guidelines <https://www.espressif.com/sites/default/files/documentation/esp32_hardware_design_guidelines_en.pdf#page=10>`_", esp32s2="`ESP32-S2 Hardware Design Guidelines <https://www.espressif.com/sites/default/files/documentation/esp32-s2_hardware_design_guidelines_en.pdf#page=10>`_"}
|
||||
{IDF_TARGET_HARDWARE_DESIGN_URL:default="`ESP32 Hardware Design Guidelines <https://www.espressif.com/sites/default/files/documentation/esp32_hardware_design_guidelines_en.pdf#page=10>`_", esp32="`ESP32 Hardware Design Guidelines <https://www.espressif.com/sites/default/files/documentation/esp32_hardware_design_guidelines_en.pdf#page=10>`_", esp32s2="`ESP32-S2 Hardware Design Guidelines <https://www.espressif.com/sites/default/files/documentation/esp32-s2_hardware_design_guidelines_en.pdf#page=10>`_", esp32s3="`ESP32-S3 Hardware Design Guidelines <https://www.espressif.com/sites/default/files/documentation/esp32-s3_hardware_design_guidelines_en.pdf#page=11>`"}
|
||||
|
||||
Overview
|
||||
--------
|
||||
@@ -30,7 +30,7 @@ RTC Clock Source
|
||||
|
||||
The RTC timer has the following clock sources:
|
||||
|
||||
- ``Internal {IDF_TARGET_RTC_CLK_FRE} RC oscillator`` (default): Features lowest deep sleep current consumption and no dependence on any external components. However, as frequency stability is affected by temperature fluctuations, time may drift in both Deep and Light sleep modes.
|
||||
- ``Internal {IDF_TARGET_RTC_CLK_FRE} RC oscillator`` (default): Features the lowest deep sleep current consumption and no dependence on any external components. However, as frequency stability is affected by temperature fluctuations, time may drift in both Deep and Light sleep modes.
|
||||
|
||||
- ``External 32kHz crystal``: Requires a 32kHz crystal to be connected to the 32K_XP and 32K_XN pins. Provides better frequency stability at the expense of slightly higher (by 1 uA) Deep sleep current consumption.
|
||||
|
||||
@@ -99,7 +99,7 @@ To set the current time, you can use the POSIX functions ``settimeofday()`` and
|
||||
A function to use inside the lwIP SNTP library depends on a sync mode for system time. Use the function :cpp:func:`sntp_set_sync_mode` to set one of the following sync modes:
|
||||
|
||||
- ``SNTP_SYNC_MODE_IMMED`` (default) updates system time immediately upon receiving a response from the SNTP server after using ``settimeofday()``.
|
||||
- ``SNTP_SYNC_MODE_SMOOTH`` updates time smoothly by gradually reducing time error using the funcion ``adjtime()``. If the difference between the SNTP response time and system time is more than 35 minutes, update system time immediately by using ``settimeofday()``.
|
||||
- ``SNTP_SYNC_MODE_SMOOTH`` updates time smoothly by gradually reducing time error using the function ``adjtime()``. If the difference between the SNTP response time and system time is more than 35 minutes, update system time immediately by using ``settimeofday()``.
|
||||
|
||||
The lwIP SNTP library has API functions for setting a callback function for a certain event. You might need the following functions:
|
||||
|
||||
|
||||
Reference in New Issue
Block a user