mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
freertos: Add task function wrapper
This commit adds an option to enclose all FreeRTOS task functions within a wrapper function. In the case that a task function returns, the wrapper function will log an error and abort the application immediately. Closes #2269 Closes #2300
This commit is contained in:
parent
9844779553
commit
3ba63a520c
@ -419,4 +419,15 @@ endif #FREERTOS_UNICORE
|
||||
|
||||
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
|
||||
|
@ -108,6 +108,7 @@
|
||||
#include "esp_crosscore_int.h"
|
||||
|
||||
#include "esp_intr_alloc.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
/* Defined in portasm.h */
|
||||
extern void _frxt_tick_timer_init(void);
|
||||
@ -133,6 +134,18 @@ unsigned port_interruptNesting[portNUM_PROCESSORS] = {0}; // Interrupt nesting
|
||||
// User exception dispatcher when exiting
|
||||
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
|
||||
*/
|
||||
@ -173,19 +186,33 @@ StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t px
|
||||
frame = (XtExcFrame *) sp;
|
||||
|
||||
/* Explicitly initialize certain saved registers */
|
||||
frame->pc = (UBaseType_t) pxCode; /* task entrypoint */
|
||||
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 */
|
||||
#if CONFIG_FREERTOS_TASK_FUNCTION_WRAPPER
|
||||
frame->pc = (UBaseType_t) vPortTaskWrapper; /* task wrapper */
|
||||
#else
|
||||
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. */
|
||||
/* Also set entry point argument parameter. */
|
||||
#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;
|
||||
#else
|
||||
/* + 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);
|
||||
#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
|
||||
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 New Issue
Block a user