diff --git a/components/esp32/include/soc/cpu.h b/components/esp32/include/soc/cpu.h index 2e0ac7de80..7e1301345b 100644 --- a/components/esp32/include/soc/cpu.h +++ b/components/esp32/include/soc/cpu.h @@ -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). */ diff --git a/components/freertos/include/freertos/portable.h b/components/freertos/include/freertos/portable.h index 0c10ac36eb..e46ec17fb6 100644 --- a/components/freertos/include/freertos/portable.h +++ b/components/freertos/include/freertos/portable.h @@ -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. diff --git a/components/freertos/port.c b/components/freertos/port.c index 3c26edfabf..756e14295d 100644 --- a/components/freertos/port.c +++ b/components/freertos/port.c @@ -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 index 0000000000..9c7d31c270 --- /dev/null +++ b/components/freertos/test/test_freertos_isinisrcontext.c @@ -0,0 +1,51 @@ +/* + See if xPortInIsrContext works +*/ + +#include +#include +#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); +} + diff --git a/components/newlib/locks.c b/components/newlib/locks.c index 21b974a1f1..c143e3a3dd 100644 --- a/components/newlib/locks.c +++ b/components/newlib/locks.c @@ -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 */ }