Ver Fonte

Fix example code, add chapter to docs about interrupts and multicore issues

Jeroen Domburg há 9 anos atrás
pai
commit
baa6a477c5

+ 2 - 3
components/driver/include/driver/rmt.h

@@ -568,15 +568,14 @@ esp_err_t rmt_config(rmt_config_t* rmt_param);
  * @brief   register RMT interrupt handler, the handler is an ISR.
  *
  *          The handler will be attached to the same CPU core that this function is running on.
- *          @note
- *          If you already called rmt_driver_install to use system RMT driver,
+ * @note If you already called rmt_driver_install to use system RMT driver,
  *          please do not register ISR handler again.
  *
  * @param fn Interrupt handler function.
  * @param arg Parameter for handler function
  * @param  intr_alloc_flags Flags used to allocate the interrupt. One or multiple (ORred)
  *            ESP_INTR_FLAG_* values. See esp_intr_alloc.h for more info.
- * @param  If non-zero, a handle to later clean up the ISR gets stored here.
+ * @param  handle If non-zero, a handle to later clean up the ISR gets stored here.
  *
  * @return
  *     - ESP_OK Success

+ 2 - 1
components/driver/include/driver/uart.h

@@ -381,7 +381,8 @@ esp_err_t uart_isr_register(uart_port_t uart_num, void (*fn)(void*), void * arg,
 
 
 /**
- * @brief Free UART interrupt handler registered by uart_isr_register.
+ * @brief Free UART interrupt handler registered by uart_isr_register. Must be called on the same core as
+ * uart_isr_register was called.
  *
  * @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2
  *

+ 28 - 1
docs/api/intr_alloc.rst

@@ -29,7 +29,33 @@ interrupt for DevA is still pending, but because the int line never went low (De
 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, outside the Xtensa
+cores in the ESP32, and internal peripherals, inside the ESP32. Interrupt handling differs slightly between
+these two types of peripherals.
+
+Each Xtensa core has its own set of internal peripherals: three timer comparators, a performance monitor and two
+software interrupts. 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). Internal interrupt sources are defined
+in esp_intr_alloc.h as ETS_INTERNAL_*_INTR_SOURCE.
+
+The remaining interrupt slots in both 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, and freeing the interrupt should always happen on the same
+core. Disabling and enabling the interrupt from another core is allowed, however. External interrupts can
+share an interrupt slot bu passing ESP_INTR_FLAG_SHARED as a flag to esp_intr_alloc. External interrupt sources 
+are defined in soc/soc.h as ETS_*_INTR_SOURCE.
+
+Care should be taken when allocating an interrupt using a task not pinned to a certain core; while running
+code not in a critical secion, these tasks can migrate between cores at any moment, possibly making an
+interrupt operation fail because of the reasons mentioned above. It is advised to always use 
+xTaskCreatePinnedToCore with a specific CoreID argument to create tasks that will handle interrupts.
 
 Application Example
 -------------------
@@ -58,6 +84,7 @@ Macros
 .. doxygendefine:: ESP_INTR_FLAG_SHARED
 .. doxygendefine:: ESP_INTR_FLAG_EDGE
 .. doxygendefine:: ESP_INTR_FLAG_IRAM
+.. doxygendefine:: ESP_INTR_FLAG_INTRDISABLED
 
 Type Definitions
 ^^^^^^^^^^^^^^^^

+ 2 - 2
examples/13_timer_group/main/timer_group.c

@@ -157,7 +157,7 @@ void tg0_timer0_init()
     /*Enable timer interrupt*/
     timer_enable_intr(timer_group, timer_idx);
     /*Set ISR handler*/
-    timer_isr_register(timer_group, timer_idx, timer_group0_isr, (void*) timer_idx, ESP_INTR_FLAG_IRAM);
+    timer_isr_register(timer_group, timer_idx, timer_group0_isr, (void*) timer_idx, ESP_INTR_FLAG_IRAM, NULL);
     /*Start timer counter*/
     timer_start(timer_group, timer_idx);
 }
@@ -187,7 +187,7 @@ void tg0_timer1_init()
     /*Enable timer interrupt*/
     timer_enable_intr(timer_group, timer_idx);
     /*Set ISR handler*/
-    timer_isr_register(timer_group, timer_idx, timer_group0_isr, (void*) timer_idx, ESP_INTR_FLAG_IRAM);
+    timer_isr_register(timer_group, timer_idx, timer_group0_isr, (void*) timer_idx, ESP_INTR_FLAG_IRAM, NULL);
     /*Start timer counter*/
     timer_start(timer_group, timer_idx);
 }

+ 1 - 1
examples/16_pcnt/main/pcnt_test.c

@@ -176,7 +176,7 @@ static void pcnt_init(void)
     /*Reset counter value*/
     pcnt_counter_clear(PCNT_TEST_UNIT);
     /*Register ISR handler*/
-    pcnt_isr_register(pcnt_intr_handler, NULL, 0);
+    pcnt_isr_register(pcnt_intr_handler, NULL, 0, NULL);
     /*Enable interrupt for PCNT unit*/
     pcnt_intr_enable(PCNT_TEST_UNIT);
     /*Resume counting*/