Merge branch 'feature/tasks_can_return' into 'master'
freertos: enclose task functions in wrapper function See merge request idf/esp-idf!2935
This commit is contained in:
commit
822fdd6e53
|
@ -419,4 +419,15 @@ endif #FREERTOS_UNICORE
|
||||||
|
|
||||||
endif # FREERTOS_DEBUG_INTERNALS
|
endif # FREERTOS_DEBUG_INTERNALS
|
||||||
|
|
||||||
|
config FREERTOS_TASK_FUNCTION_WRAPPER
|
||||||
|
bool "Enclose all task functions in a wrapper function"
|
||||||
|
depends on OPTIMIZATION_LEVEL_DEBUG
|
||||||
|
default y
|
||||||
|
help
|
||||||
|
If enabled, all FreeRTOS task functions will be enclosed in a wrapper function.
|
||||||
|
If a task function mistakenly returns (i.e. does not delete), the call flow will
|
||||||
|
return to the wrapper function. The wrapper function will then log an error and
|
||||||
|
abort the application. This option is also required for GDB backtraces and C++
|
||||||
|
exceptions to work correctly inside top-level task functions.
|
||||||
|
|
||||||
endmenu
|
endmenu
|
||||||
|
|
|
@ -108,6 +108,7 @@
|
||||||
#include "esp_crosscore_int.h"
|
#include "esp_crosscore_int.h"
|
||||||
|
|
||||||
#include "esp_intr_alloc.h"
|
#include "esp_intr_alloc.h"
|
||||||
|
#include "esp_log.h"
|
||||||
|
|
||||||
/* Defined in portasm.h */
|
/* Defined in portasm.h */
|
||||||
extern void _frxt_tick_timer_init(void);
|
extern void _frxt_tick_timer_init(void);
|
||||||
|
@ -133,6 +134,18 @@ unsigned port_interruptNesting[portNUM_PROCESSORS] = {0}; // Interrupt nesting
|
||||||
// User exception dispatcher when exiting
|
// User exception dispatcher when exiting
|
||||||
void _xt_user_exit(void);
|
void _xt_user_exit(void);
|
||||||
|
|
||||||
|
#if CONFIG_FREERTOS_TASK_FUNCTION_WRAPPER
|
||||||
|
// Wrapper to allow task functions to return (increases stack overhead by 16 bytes)
|
||||||
|
static void vPortTaskWrapper(TaskFunction_t pxCode, void *pvParameters)
|
||||||
|
{
|
||||||
|
pxCode(pvParameters);
|
||||||
|
//FreeRTOS tasks should not return. Log the task name and abort.
|
||||||
|
char * pcTaskName = pcTaskGetTaskName(NULL);
|
||||||
|
ESP_LOGE("FreeRTOS", "FreeRTOS Task \"%s\" should not return, Aborting now!", pcTaskName);
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Stack initialization
|
* Stack initialization
|
||||||
*/
|
*/
|
||||||
|
@ -173,19 +186,33 @@ StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t px
|
||||||
frame = (XtExcFrame *) sp;
|
frame = (XtExcFrame *) sp;
|
||||||
|
|
||||||
/* Explicitly initialize certain saved registers */
|
/* Explicitly initialize certain saved registers */
|
||||||
frame->pc = (UBaseType_t) pxCode; /* task entrypoint */
|
#if CONFIG_FREERTOS_TASK_FUNCTION_WRAPPER
|
||||||
frame->a0 = 0; /* to terminate GDB backtrace */
|
frame->pc = (UBaseType_t) vPortTaskWrapper; /* task wrapper */
|
||||||
frame->a1 = (UBaseType_t) sp + XT_STK_FRMSZ; /* physical top of stack frame */
|
#else
|
||||||
frame->exit = (UBaseType_t) _xt_user_exit; /* user exception exit dispatcher */
|
frame->pc = (UBaseType_t) pxCode; /* task entrypoint */
|
||||||
|
#endif
|
||||||
|
frame->a0 = 0; /* to terminate GDB backtrace */
|
||||||
|
frame->a1 = (UBaseType_t) sp + XT_STK_FRMSZ; /* physical top of stack frame */
|
||||||
|
frame->exit = (UBaseType_t) _xt_user_exit; /* user exception exit dispatcher */
|
||||||
|
|
||||||
/* Set initial PS to int level 0, EXCM disabled ('rfe' will enable), user mode. */
|
/* Set initial PS to int level 0, EXCM disabled ('rfe' will enable), user mode. */
|
||||||
/* Also set entry point argument parameter. */
|
/* Also set entry point argument parameter. */
|
||||||
#ifdef __XTENSA_CALL0_ABI__
|
#ifdef __XTENSA_CALL0_ABI__
|
||||||
frame->a2 = (UBaseType_t) pvParameters;
|
#if CONFIG_FREERTOS_TASK_FUNCTION_WRAPPER
|
||||||
|
frame->a2 = (UBaseType_t) pxCode;
|
||||||
|
frame->a3 = (UBaseType_t) pvParameters;
|
||||||
|
#else
|
||||||
|
frame->a2 = (UBaseType_t) pvParameters;
|
||||||
|
#endif
|
||||||
frame->ps = PS_UM | PS_EXCM;
|
frame->ps = PS_UM | PS_EXCM;
|
||||||
#else
|
#else
|
||||||
/* + for windowed ABI also set WOE and CALLINC (pretend task was 'call4'd). */
|
/* + for windowed ABI also set WOE and CALLINC (pretend task was 'call4'd). */
|
||||||
frame->a6 = (UBaseType_t) pvParameters;
|
#if CONFIG_FREERTOS_TASK_FUNCTION_WRAPPER
|
||||||
|
frame->a6 = (UBaseType_t) pxCode;
|
||||||
|
frame->a7 = (UBaseType_t) pvParameters;
|
||||||
|
#else
|
||||||
|
frame->a6 = (UBaseType_t) pvParameters;
|
||||||
|
#endif
|
||||||
frame->ps = PS_UM | PS_EXCM | PS_WOE | PS_CALLINC(1);
|
frame->ps = PS_UM | PS_EXCM | PS_WOE | PS_CALLINC(1);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -496,3 +496,11 @@ functionality of :cpp:func:`xTaskCreateStaticPinnedToCore` in ESP-IDF FreeRTOS
|
||||||
particular functions in ESP-IDF FreeRTOS which have not been fully tested
|
particular functions in ESP-IDF FreeRTOS which have not been fully tested
|
||||||
in an SMP context.
|
in an SMP context.
|
||||||
|
|
||||||
|
:envvar:`CONFIG_FREERTOS_TASK_FUNCTION_WRAPPER` will enclose all task functions
|
||||||
|
within a wrapper function. In the case that a task function mistakenly returns
|
||||||
|
(i.e. does not call :cpp:func:`vTaskDelete`), the call flow will return to the
|
||||||
|
wrapper function. The wrapper function will then log an error and abort the
|
||||||
|
application, as illustrated below::
|
||||||
|
|
||||||
|
E (25) FreeRTOS: FreeRTOS task should not return. Aborting now!
|
||||||
|
abort() was called at PC 0x40085c53 on core 0
|
||||||
|
|
Loading…
Reference in a new issue