Browse Source

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

Jeroen Domburg 9 years ago
parent
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.
  * @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.
  *          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.
  *          please do not register ISR handler again.
  *
  *
  * @param fn Interrupt handler function.
  * @param fn Interrupt handler function.
  * @param arg Parameter for handler function
  * @param arg Parameter for handler function
  * @param  intr_alloc_flags Flags used to allocate the interrupt. One or multiple (ORred)
  * @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.
  *            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
  * @return
  *     - ESP_OK Success
  *     - 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
  * @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.)
 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
 Application Example
 -------------------
 -------------------
@@ -58,6 +84,7 @@ Macros
 .. doxygendefine:: ESP_INTR_FLAG_SHARED
 .. doxygendefine:: ESP_INTR_FLAG_SHARED
 .. doxygendefine:: ESP_INTR_FLAG_EDGE
 .. doxygendefine:: ESP_INTR_FLAG_EDGE
 .. doxygendefine:: ESP_INTR_FLAG_IRAM
 .. doxygendefine:: ESP_INTR_FLAG_IRAM
+.. doxygendefine:: ESP_INTR_FLAG_INTRDISABLED
 
 
 Type Definitions
 Type Definitions
 ^^^^^^^^^^^^^^^^
 ^^^^^^^^^^^^^^^^

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

@@ -157,7 +157,7 @@ void tg0_timer0_init()
     /*Enable timer interrupt*/
     /*Enable timer interrupt*/
     timer_enable_intr(timer_group, timer_idx);
     timer_enable_intr(timer_group, timer_idx);
     /*Set ISR handler*/
     /*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*/
     /*Start timer counter*/
     timer_start(timer_group, timer_idx);
     timer_start(timer_group, timer_idx);
 }
 }
@@ -187,7 +187,7 @@ void tg0_timer1_init()
     /*Enable timer interrupt*/
     /*Enable timer interrupt*/
     timer_enable_intr(timer_group, timer_idx);
     timer_enable_intr(timer_group, timer_idx);
     /*Set ISR handler*/
     /*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*/
     /*Start timer counter*/
     timer_start(timer_group, timer_idx);
     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*/
     /*Reset counter value*/
     pcnt_counter_clear(PCNT_TEST_UNIT);
     pcnt_counter_clear(PCNT_TEST_UNIT);
     /*Register ISR handler*/
     /*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*/
     /*Enable interrupt for PCNT unit*/
     pcnt_intr_enable(PCNT_TEST_UNIT);
     pcnt_intr_enable(PCNT_TEST_UNIT);
     /*Resume counting*/
     /*Resume counting*/