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:
commit
432b25f755
5 changed files with 77 additions and 14 deletions
|
@ -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).
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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());
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
51
components/freertos/test/test_freertos_isinisrcontext.c
Normal file
51
components/freertos/test/test_freertos_isinisrcontext.c
Normal 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);
|
||||||
|
}
|
||||||
|
|
|
@ -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 */
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue