mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
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
@ -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).
|
||||
*/
|
||||
|
@ -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.
|
||||
|
@ -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());
|
||||
}
|
||||
|
||||
/*
|
||||
|
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/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 */
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user