]> granicus.if.org Git - esp-idf/commitdiff
Add xPortInIsrContext function + unit test. This function returns true when the curre...
authorJeroen Domburg <jeroen@espressif.com>
Mon, 27 Feb 2017 08:34:19 +0000 (16:34 +0800)
committerJeroen Domburg <jeroen@espressif.com>
Thu, 2 Mar 2017 09:00:32 +0000 (17:00 +0800)
components/esp32/include/soc/cpu.h
components/freertos/include/freertos/portable.h
components/freertos/port.c
components/freertos/test/test_freertos_isinisrcontext.c [new file with mode: 0644]
components/newlib/locks.c

index 2e0ac7de8029e01031e546bef998755f9f6c76b1..7e1301345b30fcf8f493f1b51f802732262f0cd7 100644 (file)
@@ -36,16 +36,6 @@ static inline void *get_sp()
     return sp;
 }
 
-/* Return true if the CPU is in an interrupt context
-   (PS.UM == 0)
-*/
-static inline bool cpu_in_interrupt_context(void)
-{
-    uint32_t ps;
-    RSR(PS, ps);
-    return (ps & PS_UM) == 0;
-}
-
 /* Functions to set page attributes for Region Protection option in the CPU.
  * See Xtensa ISA Reference manual for explanation of arguments (section 4.6.3.2).
  */
index 0c10ac36eb3116406bb710285aa598d1c2cc7f12..e46ec17fb6141d61f6c85c77074b077ea6d42240 100644 (file)
@@ -194,6 +194,12 @@ void vPortYieldOtherCore( BaseType_t coreid) PRIVILEGED_FUNCTION;
  */
 void vPortSetStackWatchpoint( void* pxStackStart );
 
+/*
+ * Returns true if the current core is in ISR context; low prio ISR, med prio ISR or timer tick ISR. High prio ISRs
+ * aren't detected here, but they normally cannot call C code, so that should not be an issue anyway.
+ */
+BaseType_t xPortInIsrContext();
+
 /*
  * The structures and methods of manipulating the MPU are contained within the
  * port layer.
index 3c26edfabfcacf573c6baeaca7ebf23d15a0b085..756e14295d70ebe4a2e6c0bddf35b1ce678a01a6 100644 (file)
@@ -115,7 +115,7 @@ extern void _xt_coproc_init(void);
 /*-----------------------------------------------------------*/
 
 unsigned port_xSchedulerRunning[portNUM_PROCESSORS] = {0}; // Duplicate of inaccessible xSchedulerRunning; needed at startup to avoid counting nesting
-unsigned port_interruptNesting[portNUM_PROCESSORS] = {0};  // Interrupt nesting level
+unsigned port_interruptNesting[portNUM_PROCESSORS] = {0};  // Interrupt nesting level. Increased/decreased in portasm.c, _frxt_int_enter/_frxt_int_exit
 
 /*-----------------------------------------------------------*/
 
@@ -256,9 +256,24 @@ void vPortStoreTaskMPUSettings( xMPU_SETTINGS *xMPUSettings, const struct xMEMOR
 #endif
 
 
+/*
+ * Returns true if the current core is in ISR context; low prio ISR, med prio ISR or timer tick ISR. High prio ISRs
+ * aren't detected here, but they normally cannot call C code, so that should not be an issue anyway.
+ */
+BaseType_t xPortInIsrContext()
+{
+       unsigned int irqStatus;
+       BaseType_t ret;
+       irqStatus=portENTER_CRITICAL_NESTED();
+       ret=(port_interruptNesting[xPortGetCoreID()] != 0);
+       portEXIT_CRITICAL_NESTED(irqStatus);
+       return ret;
+}
+
+
 void vPortAssertIfInISR()
 {
-       configASSERT(port_interruptNesting[xPortGetCoreID()]==0)
+       configASSERT(xPortInIsrContext());
 }
 
 /*
diff --git a/components/freertos/test/test_freertos_isinisrcontext.c b/components/freertos/test/test_freertos_isinisrcontext.c
new file mode 100644 (file)
index 0000000..9c7d31c
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ See if xPortInIsrContext works
+*/
+
+#include <esp_types.h>
+#include <stdio.h>
+#include "rom/ets_sys.h"
+
+#include "freertos/FreeRTOS.h"
+#include "freertos/task.h"
+#include "freertos/semphr.h"
+#include "freertos/queue.h"
+#include "freertos/xtensa_api.h"
+#include "unity.h"
+#include "esp_intr_alloc.h"
+#include "xtensa/hal.h"
+
+static volatile int in_int_context, int_handled;
+
+
+static void testint(void *arg) {
+    xthal_set_ccompare(1, xthal_get_ccount()+8000000000);
+    ets_printf("INT!\n");
+    if (xPortInIsrContext()) in_int_context++;
+    int_handled++;
+}
+
+
+static void testthread(void *arg) {
+    intr_handle_t handle;
+    in_int_context=0;
+    int_handled=0;
+    TEST_ASSERT(!xPortInIsrContext());
+    xthal_set_ccompare(2, xthal_get_ccount()+8000000);
+    esp_intr_alloc(ETS_INTERNAL_TIMER1_INTR_SOURCE, 0, &testint, NULL, &handle);
+    vTaskDelay(100 / portTICK_PERIOD_MS);
+    TEST_ASSERT(int_handled);
+    TEST_ASSERT(in_int_context);
+    esp_intr_free(handle);
+    vTaskDelete(NULL);
+}
+
+
+TEST_CASE("xPortInIsrContext test", "[freertos]")
+{
+    xTaskCreatePinnedToCore(testthread, "tst" , 4096, NULL, 3, NULL, 0);
+    vTaskDelay(150 / portTICK_PERIOD_MS);
+    xTaskCreatePinnedToCore(testthread, "tst" , 4096, NULL, 3, NULL, 1);
+    vTaskDelay(150 / portTICK_PERIOD_MS);
+}
+
index 21b974a1f197b4a950111f28a54e3314dd6fbe07..c143e3a3dd9603fab0d430e81e16e2fc71966c3c 100644 (file)
@@ -21,6 +21,7 @@
 #include "freertos/semphr.h"
 #include "freertos/portmacro.h"
 #include "freertos/task.h"
+#include "freertos/portable.h"
 
 /* Notes on our newlib lock implementation:
  *
@@ -126,7 +127,7 @@ static int IRAM_ATTR lock_acquire_generic(_lock_t *lock, uint32_t delay, uint8_t
     }
 
     BaseType_t success;
-    if (cpu_in_interrupt_context()) {
+    if (xPortInIsrContext()) {
         /* In ISR Context */
         if (mutex_type == queueQUEUE_TYPE_RECURSIVE_MUTEX) {
             abort(); /* recursive mutexes make no sense in ISR context */
@@ -180,7 +181,7 @@ static void IRAM_ATTR lock_release_generic(_lock_t *lock, uint8_t mutex_type) {
         return;
     }
 
-    if (cpu_in_interrupt_context()) {
+    if (xPortInIsrContext()) {
         if (mutex_type == queueQUEUE_TYPE_RECURSIVE_MUTEX) {
             abort(); /* indicates logic bug, it shouldn't be possible to lock recursively in ISR */
         }