Getting started guides
This commit is contained in:
@@ -0,0 +1,123 @@
|
||||
Deep Sleep
|
||||
==========
|
||||
|
||||
Overview
|
||||
--------
|
||||
|
||||
ESP32 is capable of deep sleep power saving mode. In this mode CPUs, most of the RAM, and all the digital peripherals which are clocked from APB_CLK are powered off. The only parts of the chip which can still be powered on are: RTC controller, RTC peripherals (including ULP coprocessor), and RTC memories (slow and fast).
|
||||
|
||||
Wakeup from deep sleep mode can be done using several sources. These sources can be combined, in this case the chip will wake up when any one of the sources is triggered. Wakeup sources can be enabled using ``esp_deep_sleep_enable_X_wakeup`` APIs. Next section describes these APIs in detail. Wakeup sources can be configured at any moment before entering deep sleep mode.
|
||||
|
||||
Additionally, the application can force specific powerdown modes for the RTC peripherals and RTC memories using ``esp_deep_sleep_pd_config`` API.
|
||||
|
||||
Once wakeup sources are configured, application can start deep sleep using ``esp_deep_sleep_start`` API. At this point the hardware will be configured according to the requested wakeup sources, and RTC controller will power down the CPUs and digital peripherals.
|
||||
|
||||
Wakeup sources
|
||||
--------------
|
||||
|
||||
Timer
|
||||
^^^^^
|
||||
|
||||
RTC controller has a built in timer which can be used to wake up the chip after a predefined amount of time. Time is specified at microsecond precision, but the actual resolution depends on the clock source selected for RTC SLOW_CLK. See chapter "Reset and Clock" of the ESP32 Technical Reference Manual for details about RTC clock options.
|
||||
|
||||
This wakeup mode doesn't require RTC peripherals or RTC memories to be powered on during deep sleep.
|
||||
|
||||
The following function can be used to enable deep sleep wakeup using a timer.
|
||||
|
||||
.. doxygenfunction:: esp_deep_sleep_enable_timer_wakeup
|
||||
|
||||
Touch pad
|
||||
^^^^^^^^^
|
||||
|
||||
RTC IO module contains logic to trigger wakeup when a touch sensor interrupt occurs. You need to configure the touch pad interrupt before the chip starts deep sleep.
|
||||
|
||||
Revisions 0 and 1 of the ESP32 only support this wakeup mode when RTC peripherals are not forced to be powered on (i.e. ESP_PD_DOMAIN_RTC_PERIPH should be set to ESP_PD_OPTION_AUTO).
|
||||
|
||||
.. doxygenfunction:: esp_deep_sleep_enable_touchpad_wakeup
|
||||
|
||||
|
||||
External wakeup (ext0)
|
||||
^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
RTC IO module contains logic to trigger wakeup when one of RTC GPIOs is set to a predefined logic level. RTC IO is part of RTC peripherals power domain, so RTC peripherals will be kept powered on during deep sleep if this wakeup source is requested.
|
||||
|
||||
Because RTC IO module is enabled in this mode, internal pullup or pulldown resistors can also be used. They need to be configured by the application using ``rtc_gpio_pullup_en`` and ``rtc_gpio_pulldown_en`` functions, before calling ``esp_deep_sleep_start``.
|
||||
|
||||
In revisions 0 and 1 of the ESP32, this wakeup source is incompatible with ULP and touch wakeup sources.
|
||||
|
||||
.. warning:: After wake up from deep sleep, IO pad used for wakeup will be configured as RTC IO. Before using this pad as digital GPIO, reconfigure it using ``rtc_gpio_deinit(gpio_num)`` function.
|
||||
|
||||
.. doxygenfunction:: esp_deep_sleep_enable_ext0_wakeup
|
||||
|
||||
External wakeup (ext1)
|
||||
^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
RTC controller contains logic to trigger wakeup using multiple RTC GPIOs. One of the two logic functions can be used to trigger wakeup:
|
||||
|
||||
- wake up if any of the selected pins is high (``ESP_EXT1_WAKEUP_ANY_HIGH``)
|
||||
- wake up if all the selected pins are low (``ESP_EXT1_WAKEUP_ALL_LOW``)
|
||||
|
||||
This wakeup source is implemented by the RTC controller. As such, RTC peripherals and RTC memories can be powered off in this mode. However, if RTC peripherals are powered down, internal pullup and pulldown resistors will be disabled. To use internal pullup or pulldown resistors, request RTC peripherals power domain to be kept on during deep sleep, and configure pullup/pulldown resistors using ``rtc_gpio_`` functions, before entering deep sleep::
|
||||
|
||||
esp_deep_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON);
|
||||
gpio_pullup_dis(gpio_num);
|
||||
gpio_pulldown_en(gpio_num);
|
||||
|
||||
.. warning:: After wake up from deep sleep, IO pad(s) used for wakeup will be configured as RTC IO. Before using these pads as digital GPIOs, reconfigure them using ``rtc_gpio_deinit(gpio_num)`` function.
|
||||
|
||||
The following function can be used to enable this wakeup mode:
|
||||
|
||||
.. doxygenfunction:: esp_deep_sleep_enable_ext1_wakeup
|
||||
|
||||
.. doxygenenum:: esp_ext1_wakeup_mode_t
|
||||
|
||||
|
||||
ULP coprocessor wakeup
|
||||
^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
ULP coprocessor can run while the chip is in deep sleep, and may be used to poll sensors, monitor ADC or touch sensor values, and wake up the chip when a specific event is detected. ULP coprocessor is part of RTC peripherals power domain, and it runs the program stored in RTC slow memeory. RTC slow memory will be powered on during deep sleep if this wakeup mode is requested. RTC peripherals will be automatically powered on before ULP coprocessor starts running the program; once the program stops running, RTC peripherals are automatically powered down again.
|
||||
|
||||
Revisions 0 and 1 of the ESP32 only support this wakeup mode when RTC peripherals are not forced to be powered on (i.e. ESP_PD_DOMAIN_RTC_PERIPH should be set to ESP_PD_OPTION_AUTO).
|
||||
|
||||
The following function can be used to enable this wakeup mode:
|
||||
|
||||
.. doxygenfunction:: esp_deep_sleep_enable_ulp_wakeup
|
||||
|
||||
Power-down of RTC peripherals and memories
|
||||
------------------------------------------
|
||||
|
||||
By default, ``esp_deep_sleep_start`` function will power down all RTC power domains which are not needed by the enabled wakeup sources. To override this behaviour, the following function is provided:
|
||||
|
||||
Note: in revision 0 of the ESP32, RTC fast memory will always be kept enabled in deep sleep, so that the deep sleep stub can run after reset. This can be overriden, if the application doesn't need clean reset behaviour after deep sleep.
|
||||
|
||||
If some variables in the program are placed into RTC slow memory (for example, using ``RTC_DATA_ATTR`` attribute), RTC slow memory will be kept powered on by default. This can be overriden using ``esp_deep_sleep_pd_config`` function, if desired.
|
||||
|
||||
.. doxygenfunction:: esp_deep_sleep_pd_config
|
||||
.. doxygenenum:: esp_deep_sleep_pd_domain_t
|
||||
.. doxygenenum:: esp_deep_sleep_pd_option_t
|
||||
|
||||
|
||||
Entering deep sleep
|
||||
-------------------
|
||||
|
||||
The following function can be used to enter deep sleep once wakeup sources are configured. It is also possible to go into deep sleep with no wakeup sources configured, in this case the chip will be in deep sleep mode indefinetly, until external reset is applied.
|
||||
|
||||
.. doxygenfunction:: esp_deep_sleep_start
|
||||
|
||||
Checking deep sleep wakeup cause
|
||||
--------------------------------
|
||||
|
||||
The following function can be used to check which wakeup source has triggered wakeup from deep sleep mode. For touch pad and ext1 wakeup sources, it is possible to identify pin or touch pad which has caused wakeup.
|
||||
|
||||
.. doxygenfunction:: esp_deep_sleep_get_wakeup_cause
|
||||
.. doxygenenum:: esp_deep_sleep_wakeup_cause_t
|
||||
.. doxygenfunction:: esp_deep_sleep_get_touchpad_wakeup_status
|
||||
.. doxygenfunction:: esp_deep_sleep_get_ext1_wakeup_status
|
||||
|
||||
|
||||
Application Example
|
||||
-------------------
|
||||
|
||||
Implementation of basic functionality of deep sleep is shown in :example:`protocols/sntp` example, where ESP module is periodically waken up to retrive time from NTP server.
|
||||
|
||||
More extensive example in :example:`system/deep_sleep` illustrates usage of various deep sleep wakeup triggers and ULP coprocessor programming.
|
||||
@@ -0,0 +1,15 @@
|
||||
System API
|
||||
**********
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
Memory Allocation <mem_alloc>
|
||||
Interrupt Allocation <intr_alloc>
|
||||
Watchdogs <wdts>
|
||||
Over The Air Updates (OTA) <ota>
|
||||
Deep Sleep <deep_sleep>
|
||||
Logging <log>
|
||||
|
||||
|
||||
Example code for this API section is provided in :example:`system` directory of ESP-IDF examples.
|
||||
@@ -0,0 +1,128 @@
|
||||
Interrupt allocation
|
||||
====================
|
||||
|
||||
Overview
|
||||
--------
|
||||
|
||||
The ESP32 has two cores, with 32 interrupts each. Each interrupt has a certain priority level, most (but not all) interrupts are connected
|
||||
to the interrupt mux. Because there are more interrupt sources than interrupts, sometimes it makes sense to share an interrupt in
|
||||
multiple drivers. The esp_intr_alloc abstraction exists to hide all these implementation details.
|
||||
|
||||
A driver can allocate an interrupt for a certain peripheral by calling esp_intr_alloc (or esp_intr_alloc_sintrstatus). It can use
|
||||
the flags passed to this function to set the type of interrupt allocated, specifying a specific 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 has two different types of interrupts it handles differently: Shared interrupts and non-shared interrupts. The simplest
|
||||
of the two are non-shared interrupts: a separate interrupt is allocated per esp_intr_alloc call and this interrupt is solely used for
|
||||
the peripheral attached to it, with only one ISR that will get called. Non-shared interrupts can have multiple peripherals triggering
|
||||
it, 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 see if any action is required.
|
||||
|
||||
Non-shared interrupts can be either level- or edge-triggered. Shared interrupts can
|
||||
only be level interrupts (because of the chance of missed interrupts when edge interrupts are
|
||||
used.)
|
||||
(The logic behind this: DevA and DevB share an int. DevB signals an int. Int line goes high. ISR handler
|
||||
calls code for DevA -> does nothing. ISR handler calls code for DevB, but while doing that,
|
||||
DevA signals an int. ISR DevB is done, clears int for DevB, exits interrupt code. Now an
|
||||
interrupt for DevA is still pending, but because the int line never went low (DevA kept it high
|
||||
even when the int for DevB was cleared) the interrupt is never serviced.)
|
||||
|
||||
|
||||
Multicore issues
|
||||
----------------
|
||||
|
||||
Peripherals that can generate interrupts can be divided in two types:
|
||||
|
||||
- External peripherals, within the ESP32 but outside the Xtensa cores themselves. Most ESP32 peripherals are of this type.
|
||||
- Internal peripherals, part of the Xtensa CPU cores themselves.
|
||||
|
||||
Interrupt handling differs slightly between these two types of peripherals.
|
||||
|
||||
Internal peripheral interrupts
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Each Xtensa CPU core has its own set of six internal peripherals:
|
||||
|
||||
- Three timer comparators
|
||||
- A performance monitor
|
||||
- Two software interrupts.
|
||||
|
||||
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 e.g. 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 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.
|
||||
|
||||
- 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 esp_intr_alloc().
|
||||
|
||||
Care should be taken when calling 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 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
|
||||
----------------------------
|
||||
|
||||
The ``ESP_INTR_FLAG_IRAM`` flag registers an interrupt handler that always runs from IRAM (and reads all its data from DRAM), and therefore does not need to be disabled during flash erase and write operations.
|
||||
|
||||
This is useful for interrupts which need a guaranteed minimum execution latency, as flash write and erase operations can be slow (erases can take tens or hundreds of milliseconds to complete).
|
||||
|
||||
It can also be useful to keep an interrupt handler in IRAM if it is called very frequently, to avoid flash cache misses.
|
||||
|
||||
Refer to the :ref:`SPI flash API documentation <iram-safe-interrupt-handlers>` for more details.
|
||||
|
||||
Application Example
|
||||
-------------------
|
||||
|
||||
API Reference
|
||||
-------------
|
||||
|
||||
Header Files
|
||||
^^^^^^^^^^^^
|
||||
|
||||
* :component_file:`esp32/include/esp_intr_alloc.h`
|
||||
|
||||
|
||||
Macros
|
||||
^^^^^^
|
||||
|
||||
.. doxygendefine:: ESP_INTR_FLAG_LEVEL1
|
||||
.. doxygendefine:: ESP_INTR_FLAG_LEVEL2
|
||||
.. doxygendefine:: ESP_INTR_FLAG_LEVEL3
|
||||
.. doxygendefine:: ESP_INTR_FLAG_LEVEL4
|
||||
.. doxygendefine:: ESP_INTR_FLAG_LEVEL5
|
||||
.. doxygendefine:: ESP_INTR_FLAG_LEVEL6
|
||||
.. doxygendefine:: ESP_INTR_FLAG_NMI
|
||||
.. doxygendefine:: ESP_INTR_FLAG_LOWMED
|
||||
.. doxygendefine:: ESP_INTR_FLAG_HIGH
|
||||
.. doxygendefine:: ESP_INTR_FLAG_SHARED
|
||||
.. doxygendefine:: ESP_INTR_FLAG_EDGE
|
||||
.. doxygendefine:: ESP_INTR_FLAG_IRAM
|
||||
.. doxygendefine:: ESP_INTR_FLAG_INTRDISABLED
|
||||
|
||||
Functions
|
||||
^^^^^^^^^
|
||||
|
||||
.. doxygenfunction:: esp_intr_mark_shared
|
||||
.. doxygenfunction:: esp_intr_reserve
|
||||
.. doxygenfunction:: esp_intr_alloc
|
||||
.. doxygenfunction:: esp_intr_alloc_intrstatus
|
||||
.. doxygenfunction:: esp_intr_free
|
||||
.. doxygenfunction:: esp_intr_get_cpu
|
||||
.. doxygenfunction:: esp_intr_get_intno
|
||||
.. doxygenfunction:: esp_intr_disable
|
||||
.. doxygenfunction:: esp_intr_enable
|
||||
.. doxygenfunction:: esp_intr_noniram_disable
|
||||
.. doxygenfunction:: esp_intr_noniram_enable
|
||||
@@ -0,0 +1,68 @@
|
||||
.. include:: ../../../components/log/README.rst
|
||||
|
||||
Application Example
|
||||
-------------------
|
||||
|
||||
Log library is commonly used by most of esp-idf components and examples. For demonstration of log functionality check :idf:`examples` folder of `espressif/esp-idf <https://github.com/espressif/esp-idf>`_ repository, that among others, contains the following examples:
|
||||
|
||||
* :example:`system/ota`
|
||||
* :example:`storage/sd_card`
|
||||
* :example:`protocols/https_request`
|
||||
|
||||
API Reference
|
||||
-------------
|
||||
|
||||
Header Files
|
||||
^^^^^^^^^^^^
|
||||
|
||||
* :component_file:`log/include/esp_log.h`
|
||||
|
||||
Macros
|
||||
^^^^^^
|
||||
|
||||
.. doxygendefine:: LOG_COLOR_E
|
||||
.. doxygendefine:: LOG_COLOR_W
|
||||
.. doxygendefine:: LOG_COLOR_I
|
||||
.. doxygendefine:: LOG_COLOR_D
|
||||
.. doxygendefine:: LOG_COLOR_V
|
||||
.. doxygendefine:: LOG_RESET_COLOR
|
||||
.. doxygendefine:: LOG_FORMAT
|
||||
.. doxygendefine:: LOG_LOCAL_LEVEL
|
||||
.. doxygendefine:: ESP_EARLY_LOGE
|
||||
.. doxygendefine:: ESP_EARLY_LOGW
|
||||
.. doxygendefine:: ESP_EARLY_LOGI
|
||||
.. doxygendefine:: ESP_EARLY_LOGD
|
||||
.. doxygendefine:: ESP_EARLY_LOGV
|
||||
.. doxygendefine:: ESP_LOGE
|
||||
.. doxygendefine:: ESP_LOGW
|
||||
.. doxygendefine:: ESP_LOGI
|
||||
.. doxygendefine:: ESP_LOGD
|
||||
.. doxygendefine:: ESP_LOGV
|
||||
|
||||
Type Definitions
|
||||
^^^^^^^^^^^^^^^^
|
||||
|
||||
.. doxygentypedef:: vprintf_like_t
|
||||
|
||||
Enumerations
|
||||
^^^^^^^^^^^^
|
||||
|
||||
.. doxygenenum:: esp_log_level_t
|
||||
|
||||
Functions
|
||||
^^^^^^^^^
|
||||
|
||||
.. doxygenfunction:: esp_log_level_set
|
||||
.. doxygenfunction:: esp_log_set_vprintf
|
||||
.. doxygenfunction:: esp_log_timestamp
|
||||
.. doxygenfunction:: esp_log_write
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
Memory allocation
|
||||
====================
|
||||
|
||||
Overview
|
||||
--------
|
||||
|
||||
The ESP32 has multiple types of RAM. Internally, there's IRAM, DRAM as well as RAM that can be used as both. It's also
|
||||
possible to connect external SPI flash to the ESP32; it's memory can be integrated into the ESP32s memory map using
|
||||
the flash cache.
|
||||
|
||||
In order to make use of all this memory, esp-idf has a capabilities-based memory allocator. Basically, if you want to have
|
||||
memory with certain properties (for example, DMA-capable, accessible by a certain PID, or capable of executing code), you
|
||||
can create an OR-mask of the required capabilities and pass that to pvPortMallocCaps. For instance, the normal malloc
|
||||
code internally allocates memory with ```pvPortMallocCaps(size, MALLOC_CAP_8BIT)``` in order to get data memory that is
|
||||
byte-addressable.
|
||||
|
||||
Because malloc uses this allocation system as well, memory allocated using pvPortMallocCaps can be freed by calling
|
||||
the standard ```free()``` function.
|
||||
|
||||
Internally, this allocator is split in two pieces. The allocator in the FreeRTOS directory can allocate memory from
|
||||
tagged regions: a tag is an integer value and every region of free memory has one of these tags. The esp32-specific
|
||||
code initializes these regions with specific tags, and contains the logic to select applicable tags from the
|
||||
capabilities given by the user. While shown in the public API, tags are used in the communication between the two parts
|
||||
and should not be used directly.
|
||||
|
||||
Special Uses
|
||||
------------
|
||||
|
||||
If a certain memory structure is only addressed in 32-bit units, for example an array of ints or pointers, it can be
|
||||
useful to allocate it with the MALLOC_CAP_32BIT flag. This also allows the allocator to give out IRAM memory; something
|
||||
which it can't do for a normal malloc() call. This can help to use all the available memory in the ESP32.
|
||||
|
||||
|
||||
API Reference
|
||||
-------------
|
||||
|
||||
Header Files
|
||||
^^^^^^^^^^^^
|
||||
|
||||
* :component_file:`esp32/include/esp_heap_alloc_caps.h`
|
||||
* :component_file:`freertos/include/freertos/heap_regions.h`
|
||||
|
||||
|
||||
Macros
|
||||
^^^^^^
|
||||
|
||||
.. doxygendefine:: MALLOC_CAP_EXEC
|
||||
.. doxygendefine:: MALLOC_CAP_32BIT
|
||||
.. doxygendefine:: MALLOC_CAP_8BIT
|
||||
.. doxygendefine:: MALLOC_CAP_DMA
|
||||
.. doxygendefine:: MALLOC_CAP_PID2
|
||||
.. doxygendefine:: MALLOC_CAP_PID3
|
||||
.. doxygendefine:: MALLOC_CAP_PID4
|
||||
.. doxygendefine:: MALLOC_CAP_PID5
|
||||
.. doxygendefine:: MALLOC_CAP_PID6
|
||||
.. doxygendefine:: MALLOC_CAP_PID7
|
||||
.. doxygendefine:: MALLOC_CAP_SPISRAM
|
||||
.. doxygendefine:: MALLOC_CAP_INVALID
|
||||
|
||||
Type Definitions
|
||||
^^^^^^^^^^^^^^^^
|
||||
|
||||
.. doxygentypedef:: HeapRegionTagged_t
|
||||
|
||||
|
||||
Functions
|
||||
^^^^^^^^^
|
||||
|
||||
.. doxygenfunction:: heap_alloc_caps_init
|
||||
.. doxygenfunction:: pvPortMallocCaps
|
||||
.. doxygenfunction:: xPortGetFreeHeapSizeCaps
|
||||
.. doxygenfunction:: xPortGetMinimumEverFreeHeapSizeCaps
|
||||
.. doxygenfunction:: vPortDefineHeapRegionsTagged
|
||||
.. doxygenfunction:: pvPortMallocTagged
|
||||
.. doxygenfunction:: vPortFreeTagged
|
||||
.. doxygenfunction:: xPortGetMinimumEverFreeHeapSizeTagged
|
||||
.. doxygenfunction:: xPortGetFreeHeapSizeTagged
|
||||
@@ -0,0 +1,77 @@
|
||||
Over The Air Updates (OTA)
|
||||
==========================
|
||||
|
||||
OTA Process Overview
|
||||
^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
The OTA update mechanism allows a device to update itself based on data received while the normal firmware is running
|
||||
(for example, over WiFi or Bluetooth.)
|
||||
|
||||
OTA requires configuring the :doc:`Partition Table <../../api-guides/partition-tables>` of the device with at least two "OTA app slot"
|
||||
partitions (ie `ota_0` and `ota_1`) and an "OTA Data Partition".
|
||||
|
||||
The OTA operation functions write a new app firmware image to whichever OTA app slot is not currently being used for
|
||||
booting. Once the image is verified, the OTA Data partition is updated to specify that this image should be used for the
|
||||
next boot.
|
||||
|
||||
.. _ota_data_partition:
|
||||
|
||||
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.
|
||||
|
||||
After the first OTA update, the OTA data partition is updated to specify which OTA app slot partition should be booted next.
|
||||
|
||||
The OTA data partition is two flash sectors (0x2000 bytes) in size, to prevent problems if there is a power failure
|
||||
while it is being written. Sectors are independently erased and written with matching data, and if they disagree a
|
||||
counter field is used to determine which sector was written more recently.
|
||||
|
||||
See also
|
||||
--------
|
||||
|
||||
* :doc:`Partition Table documentation <../../api-guides/partition-tables>`
|
||||
* :doc:`Lower-Level SPI Flash/Partition API <../storage/spi_flash>`
|
||||
|
||||
Application Example
|
||||
-------------------
|
||||
|
||||
End-to-end example of OTA firmware update workflow: :example:`system/ota`.
|
||||
|
||||
API Reference
|
||||
-------------
|
||||
|
||||
Header Files
|
||||
^^^^^^^^^^^^
|
||||
|
||||
* :component_file:`app_update/include/esp_ota_ops.h`
|
||||
|
||||
Macros
|
||||
^^^^^^
|
||||
|
||||
.. doxygendefine:: ESP_ERR_OTA_BASE
|
||||
.. doxygendefine:: ESP_ERR_OTA_PARTITION_CONFLICT
|
||||
.. doxygendefine:: ESP_ERR_OTA_SELECT_INFO_INVALID
|
||||
.. doxygendefine:: ESP_ERR_OTA_VALIDATE_FAILED
|
||||
.. doxygendefine:: OTA_SIZE_UNKNOWN
|
||||
|
||||
Type Definitions
|
||||
^^^^^^^^^^^^^^^^
|
||||
|
||||
.. doxygentypedef:: esp_ota_handle_t
|
||||
|
||||
Functions
|
||||
^^^^^^^^^
|
||||
|
||||
.. doxygenfunction:: esp_ota_begin
|
||||
.. doxygenfunction:: esp_ota_write
|
||||
.. doxygenfunction:: esp_ota_end
|
||||
.. doxygenfunction:: esp_ota_get_running_partition
|
||||
.. doxygenfunction:: esp_ota_set_boot_partition
|
||||
.. doxygenfunction:: esp_ota_get_boot_partition
|
||||
.. doxygenfunction:: esp_ota_get_next_update_partition
|
||||
@@ -0,0 +1,72 @@
|
||||
Watchdogs
|
||||
=========
|
||||
|
||||
Overview
|
||||
--------
|
||||
|
||||
Esp-idf has support for two types of watchdogs: a task watchdog as well as an interrupt watchdog. Both can be
|
||||
enabled using ``make menuconfig`` and selecting the appropriate options.
|
||||
|
||||
Interrupt watchdog
|
||||
^^^^^^^^^^^^^^^^^^
|
||||
|
||||
The interrupt watchdog makes sure the FreeRTOS task switching interrupt isn't blocked for a long time. This
|
||||
is bad because no other tasks, including potentially important ones like the WiFi task and the idle task,
|
||||
can't get any CPU runtime. A blocked task switching interrupt can happen because a program runs into an
|
||||
infinite loop with interrupts disabled or hangs in an interrupt.
|
||||
|
||||
The default action of the interrupt watchdog is to invoke the panic handler. causing a register dump and an opportunity
|
||||
for the programmer to find out, using either OpenOCD or gdbstub, what bit of code is stuck with interrupts
|
||||
disabled. Depending on the configuration of the panic handler, it can also blindly reset the CPU, which may be
|
||||
preferred in a production environment.
|
||||
|
||||
The interrupt watchdog is built around the hardware watchdog in timer group 1. If this watchdog for some reason
|
||||
cannot execute the NMI handler that invokes the panic handler (e.g. because IRAM is overwritten by garbage),
|
||||
it will hard-reset the SOC.
|
||||
|
||||
Task watchdog
|
||||
^^^^^^^^^^^^^
|
||||
|
||||
Any tasks can elect to be watched by the task watchdog. If such a task does not feed the watchdog within the time
|
||||
specified by the task watchdog timeout (which is configurable using ``make menuconfig``), the watchdog will
|
||||
print out a warning with information about which processes are running on the ESP32 CPUs and which processes
|
||||
failed to feed the watchdog.
|
||||
|
||||
By default, the task watchdog watches the idle tasks. The usual cause of idle tasks not feeding the watchdog
|
||||
is a higher-priority process looping without yielding to the lower-priority processes, and can be an indicator
|
||||
of badly-written code that spinloops on a peripheral or a task that is stuck in an infinite loop.
|
||||
|
||||
Other task can elect to be watched by the task watchdog by calling ``esp_task_wdt_feed()``. Calling this routine
|
||||
for the first time will register the task to the task watchdog; calling it subsequent times will feed
|
||||
the watchdog. If a task does not want to be watched anymore (e.g. because it is finished and will call
|
||||
``vTaskDelete()`` on itself), it needs to call ``esp_task_wdt_delete()``.
|
||||
|
||||
The task watchdog is built around the hardware watchdog in timer group 0. If this watchdog for some reason
|
||||
cannot execute the interrupt handler that prints the task data (e.g. because IRAM is overwritten by garbage
|
||||
or interrupts are disabled entirely) it will hard-reset the SOC.
|
||||
|
||||
JTAG and watchdogs
|
||||
^^^^^^^^^^^^^^^^^^
|
||||
|
||||
While debugging using OpenOCD, if the CPUs are halted the watchdogs will keep running, eventually resetting the
|
||||
CPU. This makes it very hard to debug code; that is why the OpenOCD config will disable both watchdogs on startup.
|
||||
This does mean that you will not get any warnings or panics from either the task or interrupt watchdog when the ESP32
|
||||
is connected to OpenOCD via JTAG.
|
||||
|
||||
API Reference
|
||||
-------------
|
||||
|
||||
Header Files
|
||||
^^^^^^^^^^^^
|
||||
|
||||
* :component_file:`esp32/include/esp_int_wdt.h`
|
||||
* :component_file:`esp32/include/esp_task_wdt.h`
|
||||
|
||||
|
||||
Functions
|
||||
---------
|
||||
|
||||
.. doxygenfunction:: esp_int_wdt_init
|
||||
.. doxygenfunction:: esp_task_wdt_init
|
||||
.. doxygenfunction:: esp_task_wdt_feed
|
||||
.. doxygenfunction:: esp_task_wdt_delete
|
||||
Reference in New Issue
Block a user