Merge branch 'feature/in_isr_context' into 'master'

Add xPortInIsrContext function + unit test

As title states.

See merge request !533
This commit is contained in:
Jeroen Domburg 2017-03-02 17:17:23 +08:00
commit 432b25f755
5 changed files with 77 additions and 14 deletions

View file

@ -36,16 +36,6 @@ static inline void *get_sp()
return 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. /* 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). * See Xtensa ISA Reference manual for explanation of arguments (section 4.6.3.2).
*/ */

View file

@ -194,6 +194,12 @@ void vPortYieldOtherCore( BaseType_t coreid) PRIVILEGED_FUNCTION;
*/ */
void vPortSetStackWatchpoint( void* pxStackStart ); 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 * The structures and methods of manipulating the MPU are contained within the
* port layer. * port layer.

View 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_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 #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() void vPortAssertIfInISR()
{ {
configASSERT(port_interruptNesting[xPortGetCoreID()]==0) configASSERT(xPortInIsrContext());
} }
/* /*

View file

@ -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);
}

View file

@ -21,6 +21,7 @@
#include "freertos/semphr.h" #include "freertos/semphr.h"
#include "freertos/portmacro.h" #include "freertos/portmacro.h"
#include "freertos/task.h" #include "freertos/task.h"
#include "freertos/portable.h"
/* Notes on our newlib lock implementation: /* 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; BaseType_t success;
if (cpu_in_interrupt_context()) { if (xPortInIsrContext()) {
/* In ISR Context */ /* In ISR Context */
if (mutex_type == queueQUEUE_TYPE_RECURSIVE_MUTEX) { if (mutex_type == queueQUEUE_TYPE_RECURSIVE_MUTEX) {
abort(); /* recursive mutexes make no sense in ISR context */ 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; return;
} }
if (cpu_in_interrupt_context()) { if (xPortInIsrContext()) {
if (mutex_type == queueQUEUE_TYPE_RECURSIVE_MUTEX) { if (mutex_type == queueQUEUE_TYPE_RECURSIVE_MUTEX) {
abort(); /* indicates logic bug, it shouldn't be possible to lock recursively in ISR */ abort(); /* indicates logic bug, it shouldn't be possible to lock recursively in ISR */
} }