diff --git a/components/newlib/test/test_shared_stack_printf.c b/components/newlib/test/test_shared_stack_printf.c index e7e6d1f9d3..98928871db 100644 --- a/components/newlib/test/test_shared_stack_printf.c +++ b/components/newlib/test/test_shared_stack_printf.c @@ -21,9 +21,8 @@ void external_stack_function(void) void another_external_stack_function(void) { //We can even use Freertos resources inside of this context. - printf("We can even use FreeRTOS resources delaying..., sp=%p\n", get_sp()); - vTaskDelay(100); - printf("Done!, sp=%p\n", get_sp()); + printf("We can even use FreeRTOS resources... yielding, sp=%p\n", get_sp()); + taskYIELD(); shared_stack_sp = (StackType_t *)get_sp(); } @@ -31,19 +30,21 @@ TEST_CASE("test printf using shared buffer stack", "[newlib]") { portSTACK_TYPE *shared_stack = malloc(SHARED_STACK_SIZE); - TEST_ASSERT(shared_stack != NULL); + TEST_ASSERT_NOT_NULL(shared_stack); SemaphoreHandle_t printf_lock = xSemaphoreCreateMutex(); TEST_ASSERT_NOT_NULL(printf_lock); - printf("SP: %p\n", get_sp()); + printf("current task sp: %p\n", get_sp()); printf("shared_stack: %p\n", (void *)shared_stack); + printf("shared_stack expected top: %p\n", (void *)(shared_stack + SHARED_STACK_SIZE)); + esp_execute_shared_stack_function(printf_lock, shared_stack, SHARED_STACK_SIZE, external_stack_function); - TEST_ASSERT(((shared_stack_sp >= shared_stack_sp) && + TEST_ASSERT(((shared_stack_sp >= shared_stack) && (shared_stack_sp < (shared_stack + SHARED_STACK_SIZE)))); esp_execute_shared_stack_function(printf_lock, @@ -51,7 +52,7 @@ TEST_CASE("test printf using shared buffer stack", "[newlib]") SHARED_STACK_SIZE, another_external_stack_function); - TEST_ASSERT(((shared_stack_sp >= shared_stack_sp) && + TEST_ASSERT(((shared_stack_sp >= shared_stack) && (shared_stack_sp < (shared_stack + SHARED_STACK_SIZE)))); vSemaphoreDelete(printf_lock); diff --git a/components/xtensa/expression_with_stack_xtensa.c b/components/xtensa/expression_with_stack_xtensa.c index bc8283560b..3ba962e316 100644 --- a/components/xtensa/expression_with_stack_xtensa.c +++ b/components/xtensa/expression_with_stack_xtensa.c @@ -16,12 +16,14 @@ #include #include #include +#include -StackType_t *shared_stack; -shared_stack_function shared_stack_callback; -jmp_buf shared_stack_env; -bool shared_stack_function_done = false; -portMUX_TYPE shared_stack_spinlock = portMUX_INITIALIZER_UNLOCKED; +StackType_t *xtensa_shared_stack; +shared_stack_function xtensa_shared_stack_callback; +jmp_buf xtensa_shared_stack_env; +bool xtensa_shared_stack_function_done = false; +static portMUX_TYPE xtensa_shared_stack_spinlock = portMUX_INITIALIZER_UNLOCKED; +static void *current_task_stack = NULL; extern void esp_shared_stack_invoke_function(void); @@ -31,6 +33,15 @@ static void esp_switch_stack_setup(StackType_t *stack, size_t stack_size) esp_clear_watchpoint(1); uint32_t watchpoint_place = ((uint32_t)stack + 32) & ~0x1f ; #endif + //We need also to tweak current task stackpointer to avoid erroneous + //stack overflow indication, so fills the stack with freertos known pattern: + memset(stack, 0xa5U, stack_size * sizeof(StackType_t)); + + StaticTask_t *current = (StaticTask_t *)xTaskGetCurrentTaskHandle(); + //Then put the fake stack inside of TCB: + current_task_stack = current->pxDummy6; + current->pxDummy6 = (void *)stack; + StackType_t *top_of_stack = stack + stack_size; //Align stack to a 16byte boundary, as required by CPU specific: @@ -40,7 +51,7 @@ static void esp_switch_stack_setup(StackType_t *stack, size_t stack_size) esp_set_watchpoint(1, (uint8_t *)watchpoint_place, 32, ESP_WATCHPOINT_STORE); #endif - shared_stack = top_of_stack; + xtensa_shared_stack = top_of_stack; } @@ -52,21 +63,24 @@ void esp_execute_shared_stack_function(SemaphoreHandle_t lock, void *stack, size assert(function); xSemaphoreTake(lock, portMAX_DELAY); - portENTER_CRITICAL(&shared_stack_spinlock); - shared_stack_function_done = false; + portENTER_CRITICAL(&xtensa_shared_stack_spinlock); + xtensa_shared_stack_function_done = false; esp_switch_stack_setup(stack, stack_size); - shared_stack_callback = function; - portEXIT_CRITICAL(&shared_stack_spinlock); + xtensa_shared_stack_callback = function; + portEXIT_CRITICAL(&xtensa_shared_stack_spinlock); - setjmp(shared_stack_env); - if(!shared_stack_function_done) { + setjmp(xtensa_shared_stack_env); + if(!xtensa_shared_stack_function_done) { esp_shared_stack_invoke_function(); } - portENTER_CRITICAL(&shared_stack_spinlock); + portENTER_CRITICAL(&xtensa_shared_stack_spinlock); StaticTask_t *current = (StaticTask_t *)xTaskGetCurrentTaskHandle(); + + //Restore current task stack: + current->pxDummy6 = (StackType_t *)current_task_stack; vPortSetStackWatchpoint(current->pxDummy6); - portEXIT_CRITICAL(&shared_stack_spinlock); + portEXIT_CRITICAL(&xtensa_shared_stack_spinlock); xSemaphoreGive(lock); } \ No newline at end of file diff --git a/components/xtensa/expression_with_stack_xtensa_asm.S b/components/xtensa/expression_with_stack_xtensa_asm.S index deac4f7e02..67f1fea976 100644 --- a/components/xtensa/expression_with_stack_xtensa_asm.S +++ b/components/xtensa/expression_with_stack_xtensa_asm.S @@ -14,9 +14,10 @@ #include - .extern shared_stack - .extern shared_stack_callback - .extern shared_stack_function_done + .extern xtensa_shared_stack + .extern xtensa_shared_stack_callback + .extern xtensa_shared_stack_function_done + .extern xtensa_shared_stack_env .extern longjmp .text @@ -29,16 +30,18 @@ esp_shared_stack_invoke_function: #ifndef __XTENSA_CALL0_ABI__ - movi a0, 0 /* no need to rotate window, it will be destroyed anyway */ - movi a6, shared_stack + movi a0, 0 /* must not rotate the window here, */ + /* the state of execution for shared stack */ + /* functions will be completely destroyed at end */ + movi a6, xtensa_shared_stack l32i sp, a6, 0 /* load shared stack pointer */ - movi a12, shared_stack_callback + movi a12, xtensa_shared_stack_callback l32i a12, a12, 0 callx4 a12 /* call user function */ - movi a6, shared_stack_function_done + movi a6, xtensa_shared_stack_function_done movi a7, 1 s32i a7, a6, 0 /* hint the function was finished */ - movi a6, shared_stack_env + movi a6, xtensa_shared_stack_env movi a7, 0 movi a12, longjmp callx4 a12 /* jump to last clean state previously saved */