]> granicus.if.org Git - esp-idf/commitdiff
esp32: sanity check ISR handler address passed into esp_intr_alloc
authorIvan Grokhotkov <igrokhotkov@gmail.com>
Tue, 10 Jan 2017 17:14:18 +0000 (01:14 +0800)
committerIvan Grokhotkov <igrokhotkov@gmail.com>
Wed, 11 Jan 2017 03:38:17 +0000 (11:38 +0800)
Return ESP_ERR_INVALID_ARG if the handler is not in IRAM (or RTC fast memory)

components/esp32/crosscore_int.c
components/esp32/include/esp_intr_alloc.h
components/esp32/intr_alloc.c
components/esp32/test/test_intr_alloc.c

index b58d3d62c5cda8f2d764dbb86a9a67d6f78b1749..1e131eeef714d8d657f6015ff6bba5b440165e10 100644 (file)
@@ -73,11 +73,13 @@ void esp_crosscore_int_init() {
     portENTER_CRITICAL(&reasonSpinlock);
     reason[xPortGetCoreID()]=0;
     portEXIT_CRITICAL(&reasonSpinlock);
+    esp_err_t err;
     if (xPortGetCoreID()==0) {
-        esp_intr_alloc(ETS_FROM_CPU_INTR0_SOURCE, ESP_INTR_FLAG_IRAM, esp_crosscore_isr, (void*)&reason[xPortGetCoreID()], NULL);
+        err = esp_intr_alloc(ETS_FROM_CPU_INTR0_SOURCE, ESP_INTR_FLAG_IRAM, esp_crosscore_isr, (void*)&reason[xPortGetCoreID()], NULL);
     } else {
-        esp_intr_alloc(ETS_FROM_CPU_INTR1_SOURCE, ESP_INTR_FLAG_IRAM, esp_crosscore_isr, (void*)&reason[xPortGetCoreID()], NULL);
+        err = esp_intr_alloc(ETS_FROM_CPU_INTR1_SOURCE, ESP_INTR_FLAG_IRAM, esp_crosscore_isr, (void*)&reason[xPortGetCoreID()], NULL);
     }
+    assert(err == ESP_OK);
 }
 
 void esp_crosscore_int_send_yield(int coreId) {
index c1f91dd2e36fa7b2f6d79616bd74b3d00ef7576d..7195d07d87072efe4e7ad8e89eb77b4303163c3c 100644 (file)
@@ -124,6 +124,9 @@ esp_err_t esp_intr_reserve(int intno, int cpu);
  *
  * The interrupt will always be allocated on the core that runs this function.
  *
+ * If ESP_INTR_FLAG_IRAM flag is used, and handler address is not in IRAM or
+ * RTC_FAST_MEM, then ESP_ERR_INVALID_ARG is returned.
+ *
  * @param source The interrupt source. One of the ETS_*_INTR_SOURCE interrupt mux
  *               sources, as defined in soc/soc.h, or one of the internal
  *               ETS_INTERNAL_*_INTR_SOURCE sources as defined in this header.
@@ -264,4 +267,4 @@ void esp_intr_noniram_enable();
 }
 #endif
 
-#endif
\ No newline at end of file
+#endif
index 4fdda2f396f0f34c2bdb11aa13f53edc6a4c0dc8..1cb2fba5d9de3e153958bba65892f8342b530fc7 100644 (file)
@@ -446,6 +446,12 @@ esp_err_t esp_intr_alloc_intrstatus(int source, int flags, uint32_t intrstatusre
     if ((flags&ESP_INTR_FLAG_SHARED) && (!handler || source<0)) return ESP_ERR_INVALID_ARG;
     //Statusreg should have a mask
     if (intrstatusreg && !intrstatusmask) return ESP_ERR_INVALID_ARG;
+    //If the ISR is marked to be IRAM-resident, the handler must not be in the cached region
+    if ((flags&ESP_INTR_FLAG_IRAM) &&
+            (ptrdiff_t) handler >= 0x400C0000 &&
+            (ptrdiff_t) handler < 0x50000000 ) {
+        return ESP_ERR_INVALID_ARG;
+    }
 
     //Default to prio 1 for shared interrupts. Default to prio 1, 2 or 3 for non-shared interrupts.
     if ((flags&ESP_INTR_FLAG_LEVELMASK)==0) {
index 329fc9a9e4d24ad7d4d371fc912ab791102a0c5f..a5e6f0683487f8ffcd310d0f8b5ac53f50d22b3b 100644 (file)
@@ -201,3 +201,30 @@ TEST_CASE("Intr_alloc test, shared ints", "[esp32]")
 {
     timer_test(ESP_INTR_FLAG_SHARED);
 }
+
+TEST_CASE("Can allocate IRAM int only with an IRAM handler", "[esp32]")
+{
+    void dummy(void* arg)
+    {
+    }
+    IRAM_ATTR void dummy_iram(void* arg)
+    {
+    }
+    RTC_IRAM_ATTR void dummy_rtc(void* arg)
+    {
+    }
+    intr_handle_t ih;
+    esp_err_t err = esp_intr_alloc(ETS_INTERNAL_PROFILING_INTR_SOURCE,
+            ESP_INTR_FLAG_IRAM, &dummy, NULL, &ih);
+    TEST_ASSERT_EQUAL_INT(ESP_ERR_INVALID_ARG, err);
+    err = esp_intr_alloc(ETS_INTERNAL_PROFILING_INTR_SOURCE,
+            ESP_INTR_FLAG_IRAM, &dummy_iram, NULL, &ih);
+    TEST_ESP_OK(err);
+    err = esp_intr_free(ih);
+    TEST_ESP_OK(err);
+    err = esp_intr_alloc(ETS_INTERNAL_PROFILING_INTR_SOURCE,
+            ESP_INTR_FLAG_IRAM, &dummy_rtc, NULL, &ih);
+    TEST_ESP_OK(err);
+    err = esp_intr_free(ih);
+    TEST_ESP_OK(err);
+}