Add xPortInIsrContext function + unit test. This function returns true when the current CPU runs in an interrupt handler context.

This commit is contained in:
Jeroen Domburg 2017-02-27 16:34:19 +08:00
parent 290c40a4ab
commit 6739d5b99f
5 changed files with 77 additions and 14 deletions

View 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).
*/

View 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.

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_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());
}
/*

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/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 */
}