mirror of
https://github.com/espressif/ESP8266_RTOS_SDK.git
synced 2025-08-06 15:15:15 +08:00
feat(freertos): add feature to modify task stack deepth dynamically
This commit is contained in:
@ -5221,4 +5221,114 @@ when performing module tests). */
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if( configENABLE_TASK_MODIFY_STACK_DEPTH == 1 )
|
||||||
|
|
||||||
|
#if( INCLUDE_xTimerPendFunctionCall != 1 || configUSE_TIMERS != 1)
|
||||||
|
#error "INCLUDE_xTimerPendFunctionCall and configUSE_TIMERS should be enable"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "semphr.h"
|
||||||
|
|
||||||
|
struct prvTaskModifyParam {
|
||||||
|
TCB_t *pxTCB;
|
||||||
|
uint32_t newStackDepth;
|
||||||
|
SemaphoreHandle_t sem;
|
||||||
|
BaseType_t uxResult;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void prvTaskModifyStackDepth(void *param, uint32_t null_val)
|
||||||
|
{
|
||||||
|
struct prvTaskModifyParam *pTaskModifyParam = (struct prvTaskModifyParam *)param;
|
||||||
|
StackType_t *pxStack;
|
||||||
|
UBaseType_t oldStackBytes;
|
||||||
|
TCB_t *pxTCB = (TCB_t *)pTaskModifyParam->pxTCB;
|
||||||
|
UBaseType_t newStackBytes = (size_t)pTaskModifyParam->newStackDepth * sizeof(StackType_t);
|
||||||
|
const UBaseType_t unitSize = sizeof(void *);
|
||||||
|
|
||||||
|
oldStackBytes = (size_t)pxTCB->pxEndOfStack - (size_t)pxTCB->pxTopOfStack + unitSize;
|
||||||
|
if (oldStackBytes >= newStackBytes) {
|
||||||
|
pTaskModifyParam->uxResult = pdFAIL;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
pxStack = pvPortMalloc(newStackBytes);
|
||||||
|
if (!pxStack) {
|
||||||
|
pTaskModifyParam->uxResult = pdFAIL;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
memset(pxStack, tskSTACK_FILL_BYTE, newStackBytes - oldStackBytes);
|
||||||
|
vPortInitContextFromOldStack(&pxStack[newStackBytes - oldStackBytes], (StackType_t *)pxTCB->pxTopOfStack, oldStackBytes);
|
||||||
|
|
||||||
|
vPortFree(pxTCB->pxStack);
|
||||||
|
|
||||||
|
pxTCB->pxStack = pxStack;
|
||||||
|
pxTCB->pxTopOfStack = &pxStack[newStackBytes - oldStackBytes];
|
||||||
|
pxTCB->pxEndOfStack = (StackType_t *)((size_t)pxStack + (size_t)pTaskModifyParam->newStackDepth - unitSize);
|
||||||
|
|
||||||
|
pTaskModifyParam->uxResult = pdPASS;
|
||||||
|
|
||||||
|
exit:
|
||||||
|
if (pTaskModifyParam->sem)
|
||||||
|
xSemaphoreGive(pTaskModifyParam->sem);
|
||||||
|
}
|
||||||
|
|
||||||
|
BaseType_t vTaskModifyStackDepth(TaskHandle_t xTask, const configSTACK_DEPTH_TYPE newStackDepth)
|
||||||
|
{
|
||||||
|
BaseType_t xReturn;
|
||||||
|
|
||||||
|
if (newStackDepth & 0x3) {
|
||||||
|
return pdFAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prvGetTCBFromHandle(xTask) != pxCurrentTCB) {
|
||||||
|
struct prvTaskModifyParam taskModifyParam;
|
||||||
|
|
||||||
|
taskModifyParam.pxTCB = prvGetTCBFromHandle(xTask);
|
||||||
|
taskModifyParam.newStackDepth = newStackDepth;
|
||||||
|
taskModifyParam.sem = NULL;
|
||||||
|
|
||||||
|
vTaskSuspend(xTask);
|
||||||
|
prvTaskModifyStackDepth(&taskModifyParam, 0);
|
||||||
|
xReturn = taskModifyParam.uxResult;
|
||||||
|
vTaskResume(xTask);
|
||||||
|
} else {
|
||||||
|
SemaphoreHandle_t sem;
|
||||||
|
struct prvTaskModifyParam *taskModifyParam;
|
||||||
|
|
||||||
|
if (xTimerGetTimerDaemonTaskHandle() == xTask) {
|
||||||
|
return pdFAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (xTaskGetSchedulerState() != taskSCHEDULER_RUNNING) {
|
||||||
|
return pdFAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
sem = xSemaphoreCreateBinary();
|
||||||
|
if (!sem) {
|
||||||
|
return pdFAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
taskModifyParam = pvPortMalloc(sizeof(struct prvTaskModifyParam));
|
||||||
|
if (!taskModifyParam) {
|
||||||
|
vSemaphoreDelete(sem);
|
||||||
|
return pdFAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
taskModifyParam->pxTCB = prvGetTCBFromHandle(xTask);
|
||||||
|
taskModifyParam->newStackDepth = newStackDepth;
|
||||||
|
taskModifyParam->sem = sem;
|
||||||
|
|
||||||
|
xReturn = xTimerPendFunctionCall(prvTaskModifyStackDepth, taskModifyParam, 0, portMAX_DELAY);
|
||||||
|
if (xReturn == pdPASS) {
|
||||||
|
xSemaphoreTake(sem, portMAX_DELAY);
|
||||||
|
xReturn = taskModifyParam->uxResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
vSemaphoreDelete(sem);
|
||||||
|
vPortFree(taskModifyParam);
|
||||||
|
}
|
||||||
|
|
||||||
|
return xReturn;
|
||||||
|
}
|
||||||
|
#endif /* configENABLE_TASK_MODIFY_STACK_DEPTH == 1 */
|
||||||
|
|
||||||
|
@ -146,6 +146,16 @@ void vPortEndScheduler( void ) PRIVILEGED_FUNCTION;
|
|||||||
*/
|
*/
|
||||||
int xPortInIsrContext(void);
|
int xPortInIsrContext(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Copy thread context from old thread stack to new thread stack and
|
||||||
|
* then reset the SP.
|
||||||
|
*
|
||||||
|
* @param newStackTop new thread stack pointer
|
||||||
|
* @param oldStackTop old thread stack pointer
|
||||||
|
* @param stackSize stack size
|
||||||
|
*/
|
||||||
|
void vPortInitContextFromOldStack(StackType_t *newStackTop, StackType_t *oldStackTop, UBaseType_t stackSize);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -2383,6 +2383,16 @@ typedef struct xTASK_SNAPSHOT
|
|||||||
*/
|
*/
|
||||||
UBaseType_t uxTaskGetSnapshotAll( TaskSnapshot_t * const pxTaskSnapshotArray, const UBaseType_t uxArraySize, UBaseType_t * const pxTcbSz );
|
UBaseType_t uxTaskGetSnapshotAll( TaskSnapshot_t * const pxTaskSnapshotArray, const UBaseType_t uxArraySize, UBaseType_t * const pxTcbSz );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Modify task stack size dynamically.
|
||||||
|
*
|
||||||
|
* @param xTask task handle which created by xTaskCreate.
|
||||||
|
* @param newStackDepth task' new stack size.
|
||||||
|
*
|
||||||
|
* @return pdPASS if success or others if failed
|
||||||
|
*/
|
||||||
|
BaseType_t vTaskModifyStackDepth(TaskHandle_t xTask, const configSTACK_DEPTH_TYPE newStackDepth);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -194,5 +194,9 @@ uint32_t esp_get_time(void);
|
|||||||
#define configENABLE_TASK_SNAPSHOT 1
|
#define configENABLE_TASK_SNAPSHOT 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef configENABLE_TASK_MODIFY_STACK_DEPTH
|
||||||
|
#define configENABLE_TASK_MODIFY_STACK_DEPTH 1
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif /* FREERTOS_CONFIG_H */
|
#endif /* FREERTOS_CONFIG_H */
|
||||||
|
|
||||||
|
@ -29,6 +29,7 @@
|
|||||||
/* Scheduler includes. */
|
/* Scheduler includes. */
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#include <xtensa/config/core.h>
|
#include <xtensa/config/core.h>
|
||||||
#include <xtensa/tie/xt_interrupt.h>
|
#include <xtensa/tie/xt_interrupt.h>
|
||||||
@ -218,6 +219,15 @@ portBASE_TYPE xPortStartScheduler(void)
|
|||||||
return pdTRUE;
|
return pdTRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void vPortInitContextFromOldStack(StackType_t *newStackTop, StackType_t *oldStackTop, UBaseType_t stackSize)
|
||||||
|
{
|
||||||
|
uintptr_t *sp;
|
||||||
|
|
||||||
|
memcpy(newStackTop, oldStackTop, stackSize);
|
||||||
|
sp = (uintptr_t *)newStackTop;
|
||||||
|
sp[XT_STK_A1 / sizeof(uintptr_t)] = (uintptr_t)sp + XT_STK_FRMSZ;
|
||||||
|
}
|
||||||
|
|
||||||
void vPortEndScheduler(void)
|
void vPortEndScheduler(void)
|
||||||
{
|
{
|
||||||
/* It is unlikely that the CM3 port will require this function as there
|
/* It is unlikely that the CM3 port will require this function as there
|
||||||
|
113
components/freertos/test/test_freertos_task_modify_stack_depth.c
Normal file
113
components/freertos/test/test_freertos_task_modify_stack_depth.c
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
/* FreeRTOS timer tests
|
||||||
|
*/
|
||||||
|
//#define LOG_LOCAL_LEVEL 5
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "unity.h"
|
||||||
|
#include "esp_system.h"
|
||||||
|
#include "esp_log.h"
|
||||||
|
#include "freertos/FreeRTOS.h"
|
||||||
|
#include "freertos/task.h"
|
||||||
|
#include "freertos/semphr.h"
|
||||||
|
|
||||||
|
#define TASK_DEPTH_SIZE 8192
|
||||||
|
#define TAG "test_modify_stack_depth"
|
||||||
|
|
||||||
|
static SemaphoreHandle_t s_main_sem, s_sync_sem[3];
|
||||||
|
static TaskHandle_t s_task_handle[3];
|
||||||
|
|
||||||
|
static void test_thread_1(void *p)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < 16; i++) {
|
||||||
|
ESP_LOGD(TAG, "Modify tasks' stack depth to be %u", TASK_DEPTH_SIZE - i * 128);
|
||||||
|
|
||||||
|
vTaskModifyStackDepth(NULL, TASK_DEPTH_SIZE - i * 128);
|
||||||
|
}
|
||||||
|
|
||||||
|
xSemaphoreGive(s_main_sem);
|
||||||
|
|
||||||
|
vTaskDelete(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_thread_2(void *p)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < 10; i++) {
|
||||||
|
vTaskPrioritySet(NULL, 5);
|
||||||
|
|
||||||
|
ESP_LOGD(TAG, "Modify tasks' stack depth to be %u", TASK_DEPTH_SIZE - i * 128);
|
||||||
|
|
||||||
|
for (int j = 0; j < 3; j++) {
|
||||||
|
vTaskModifyStackDepth(s_task_handle[j], TASK_DEPTH_SIZE - i * 128);
|
||||||
|
xSemaphoreGive(s_sync_sem[j]);
|
||||||
|
}
|
||||||
|
|
||||||
|
ESP_LOGD(TAG, "Modify successfully");
|
||||||
|
|
||||||
|
vTaskPrioritySet(NULL, 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
xSemaphoreGive(s_main_sem);
|
||||||
|
|
||||||
|
vTaskDelete(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_thread_3(void *p)
|
||||||
|
{
|
||||||
|
int count = 10;
|
||||||
|
int num = (int)p;
|
||||||
|
|
||||||
|
while (count--) {
|
||||||
|
TEST_ASSERT(xSemaphoreTake(s_sync_sem[num], portMAX_DELAY) == pdTRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
vTaskDelete(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Test task modifies itself's stack depth", "[freertos]")
|
||||||
|
{
|
||||||
|
TEST_ASSERT(s_main_sem = xSemaphoreCreateBinary());
|
||||||
|
|
||||||
|
TEST_ASSERT(xTaskCreatePinnedToCore(test_thread_1, "thread_1", TASK_DEPTH_SIZE, NULL, 5, NULL, 0) == pdTRUE);
|
||||||
|
|
||||||
|
TEST_ASSERT(xSemaphoreTake(s_main_sem, portMAX_DELAY) == pdTRUE);
|
||||||
|
|
||||||
|
vQueueDelete(s_main_sem);
|
||||||
|
s_main_sem = NULL;
|
||||||
|
|
||||||
|
vTaskDelay(5);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Test task modifies other tasks' stack depth", "[freertos]")
|
||||||
|
{
|
||||||
|
ESP_LOGD(TAG, "before heap is %u", esp_get_free_heap_size());
|
||||||
|
|
||||||
|
TEST_ASSERT(s_main_sem = xSemaphoreCreateBinary());
|
||||||
|
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
TEST_ASSERT(s_sync_sem[i] = xSemaphoreCreateBinary());
|
||||||
|
}
|
||||||
|
|
||||||
|
vTaskSuspendAll();
|
||||||
|
|
||||||
|
TEST_ASSERT(xTaskCreatePinnedToCore(test_thread_2, "thread_2", TASK_DEPTH_SIZE, NULL, 5, NULL, 0) == pdTRUE);
|
||||||
|
|
||||||
|
TEST_ASSERT(xTaskCreatePinnedToCore(test_thread_3, "thread_4", TASK_DEPTH_SIZE, (void *)0, 4, &s_task_handle[0], 0) == pdTRUE);
|
||||||
|
TEST_ASSERT(xTaskCreatePinnedToCore(test_thread_3, "thread_5", TASK_DEPTH_SIZE, (void *)1, 5, &s_task_handle[1], 0) == pdTRUE);
|
||||||
|
TEST_ASSERT(xTaskCreatePinnedToCore(test_thread_3, "thread_6", TASK_DEPTH_SIZE, (void *)2, 6, &s_task_handle[2], 0) == pdTRUE);
|
||||||
|
|
||||||
|
xTaskResumeAll();
|
||||||
|
|
||||||
|
TEST_ASSERT(xSemaphoreTake(s_main_sem, portMAX_DELAY) == pdTRUE);
|
||||||
|
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
vQueueDelete(s_sync_sem[i]);
|
||||||
|
s_sync_sem[i] = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
vQueueDelete(s_main_sem);
|
||||||
|
s_main_sem = NULL;
|
||||||
|
|
||||||
|
vTaskDelay(5);
|
||||||
|
|
||||||
|
ESP_LOGD(TAG, "after heap is %u", esp_get_free_heap_size());
|
||||||
|
}
|
@ -139,6 +139,12 @@ static void openssl_task(void *p)
|
|||||||
|
|
||||||
ESP_LOGI(TAG, "OK");
|
ESP_LOGI(TAG, "OK");
|
||||||
|
|
||||||
|
#if configENABLE_TASK_MODIFY_STACK_DEPTH == 1
|
||||||
|
ESP_LOGI(TAG, "Before modification stack depth of this thread, free heap size is %u", esp_get_free_heap_size());
|
||||||
|
vTaskModifyStackDepth(NULL, 2048);
|
||||||
|
ESP_LOGI(TAG, "After modification stack depth of this thread, free heap size is %u", esp_get_free_heap_size());
|
||||||
|
#endif
|
||||||
|
|
||||||
ESP_LOGI(TAG, "send request to %s port %d ......", OPENSSL_DEMO_TARGET_NAME, OPENSSL_DEMO_TARGET_TCP_PORT);
|
ESP_LOGI(TAG, "send request to %s port %d ......", OPENSSL_DEMO_TARGET_NAME, OPENSSL_DEMO_TARGET_TCP_PORT);
|
||||||
ret = SSL_write(ssl, send_data, send_bytes);
|
ret = SSL_write(ssl, send_data, send_bytes);
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user