intr_alloc.rst 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. Interrupt allocation
  2. ====================
  3. Overview
  4. --------
  5. The ESP32 has two cores, with 32 interrupts each. Each interrupt has a certain priority level, most (but not all) interrupts are connected
  6. to the interrupt mux. Because there are more interrupt sources than interrupts, sometimes it makes sense to share an interrupt in
  7. multiple drivers. The esp_intr_alloc abstraction exists to hide all these implementation details.
  8. A driver can allocate an interrupt for a certain peripheral by calling esp_intr_alloc (or esp_intr_alloc_sintrstatus). It can use
  9. the flags passed to this function to set the type of interrupt allocated, specifying a specific level or trigger method. The
  10. interrupt allocation code will then find an applicable interrupt, use the interrupt mux to hook it up to the peripheral, and
  11. install the given interrupt handler and ISR to it.
  12. This code has two different types of interrupts it handles differently: Shared interrupts and non-shared interrupts. The simplest
  13. of the two are non-shared interrupts: a separate interrupt is allocated per esp_intr_alloc call and this interrupt is solely used for
  14. the peripheral attached to it, with only one ISR that will get called. Non-shared interrupts can have multiple peripherals triggering
  15. it, with multiple ISRs being called when one of the peripherals attached signals an interrupt. Thus, ISRs that are intended for shared
  16. interrupts should check the interrupt status of the peripheral they service in order to see if any action is required.
  17. Non-shared interrupts can be either level- or edge-triggered. Shared interrupts can
  18. only be level interrupts (because of the chance of missed interrupts when edge interrupts are
  19. used.)
  20. (The logic behind this: DevA and DevB share an int. DevB signals an int. Int line goes high. ISR handler
  21. calls code for DevA -> does nothing. ISR handler calls code for DevB, but while doing that,
  22. DevA signals an int. ISR DevB is done, clears int for DevB, exits interrupt code. Now an
  23. interrupt for DevA is still pending, but because the int line never went low (DevA kept it high
  24. even when the int for DevB was cleared) the interrupt is never serviced.)
  25. Multicore issues
  26. ----------------
  27. Peripherals that can generate interrupts can be divided in two types: external peripherals, outside the Xtensa
  28. cores in the ESP32, and internal peripherals, inside the ESP32. Interrupt handling differs slightly between
  29. these two types of peripherals.
  30. Each Xtensa core has its own set of internal peripherals: three timer comparators, a performance monitor and two
  31. software interrupts. These peripherals can only be configured from the core they are associated with. When
  32. generating an interrupt, the interrupt they generate is hard-wired to their associated core; it's not possible
  33. to have e.g. an internal timer comparator of one core generate an interrupt on another core. That is why these
  34. sources can only be managed using a task running on that specific core. Internal interrupt sources are still
  35. allocatable using esp_intr_alloc as normal, but they cannot be shared and will always have a fixed interrupt
  36. level (namely, the one associated in hardware with the peripheral). Internal interrupt sources are defined
  37. in esp_intr_alloc.h as ETS_INTERNAL_*_INTR_SOURCE.
  38. The remaining interrupt slots in both cores are wired to an interrupt multiplexer, which can be used to
  39. route any external interrupt source to any of these interrupt slots. Allocating an external interrupt will always
  40. allocate it on the core that does the allocation, and freeing the interrupt should always happen on the same
  41. core. Disabling and enabling the interrupt from another core is allowed, however. External interrupts can
  42. share an interrupt slot bu passing ESP_INTR_FLAG_SHARED as a flag to esp_intr_alloc. External interrupt sources
  43. are defined in soc/soc.h as ETS_*_INTR_SOURCE.
  44. Care should be taken when allocating an interrupt using a task not pinned to a certain core; while running
  45. code not in a critical secion, these tasks can migrate between cores at any moment, possibly making an
  46. interrupt operation fail because of the reasons mentioned above. It is advised to always use
  47. xTaskCreatePinnedToCore with a specific CoreID argument to create tasks that will handle interrupts.
  48. Application Example
  49. -------------------
  50. API Reference
  51. -------------
  52. Header Files
  53. ^^^^^^^^^^^^
  54. * `esp_intr_alloc.h <https://github.com/espressif/esp-idf/blob/master/components/esp32/include/esp_intr_alloc.h>`_
  55. Macros
  56. ^^^^^^
  57. .. doxygendefine:: ESP_INTR_FLAG_LEVEL1
  58. .. doxygendefine:: ESP_INTR_FLAG_LEVEL2
  59. .. doxygendefine:: ESP_INTR_FLAG_LEVEL3
  60. .. doxygendefine:: ESP_INTR_FLAG_LEVEL4
  61. .. doxygendefine:: ESP_INTR_FLAG_LEVEL5
  62. .. doxygendefine:: ESP_INTR_FLAG_LEVEL6
  63. .. doxygendefine:: ESP_INTR_FLAG_NMI
  64. .. doxygendefine:: ESP_INTR_FLAG_LOWMED
  65. .. doxygendefine:: ESP_INTR_FLAG_HIGH
  66. .. doxygendefine:: ESP_INTR_FLAG_SHARED
  67. .. doxygendefine:: ESP_INTR_FLAG_EDGE
  68. .. doxygendefine:: ESP_INTR_FLAG_IRAM
  69. .. doxygendefine:: ESP_INTR_FLAG_INTRDISABLED
  70. Type Definitions
  71. ^^^^^^^^^^^^^^^^
  72. Enumerations
  73. ^^^^^^^^^^^^
  74. Structures
  75. ^^^^^^^^^^
  76. Functions
  77. ^^^^^^^^^
  78. .. doxygenfunction:: esp_intr_mark_shared
  79. .. doxygenfunction:: esp_intr_reserve
  80. .. doxygenfunction:: esp_intr_alloc
  81. .. doxygenfunction:: esp_intr_alloc_intrstatus
  82. .. doxygenfunction:: esp_intr_free
  83. .. doxygenfunction:: esp_intr_get_cpu
  84. .. doxygenfunction:: esp_intr_get_intno
  85. .. doxygenfunction:: esp_intr_disable
  86. .. doxygenfunction:: esp_intr_enable
  87. .. doxygenfunction:: esp_intr_noniram_disable
  88. .. doxygenfunction:: esp_intr_noniram_enable