1 /*
2 * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <esp_expression_with_stack.h>
8 #include <riscv/rvruntime-frames.h>
9 #include <string.h>
10 #include "freertos/FreeRTOS.h"
11 #include "freertos/portmacro.h"
12
13 static portMUX_TYPE shared_stack_spinlock = portMUX_INITIALIZER_UNLOCKED;
14 static void *current_task_stack = NULL;
15
16 extern void esp_shared_stack_invoke_function(shared_stack_function function, void *stack);
17
esp_switch_stack_setup(StackType_t * stack,size_t stack_size)18 static StackType_t *esp_switch_stack_setup(StackType_t *stack, size_t stack_size)
19 {
20 //We need also to tweak current task stackpointer to avoid erroneous
21 //stack overflow indication, so fills the stack with freertos known pattern:
22 memset(stack, 0xa5U, stack_size * sizeof(StackType_t));
23
24 StaticTask_t *current = (StaticTask_t *)xTaskGetCurrentTaskHandle();
25 //Then put the fake stack inside of TCB:
26 current_task_stack = current->pxDummy6;
27 current->pxDummy6 = (void *)stack;
28
29 StackType_t *top_of_stack = stack + stack_size;
30
31 //Align stack to a 16byte boundary, as required by CPU specific:
32 top_of_stack = (StackType_t *)(((UBaseType_t)(top_of_stack - 16) & ~0xf));
33 StackType_t *adjusted_top_of_stack = top_of_stack - RV_STK_FRMSZ;
34
35 #if CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK
36 vPortSetStackWatchpoint(stack);
37 #endif
38 return ((StackType_t *)adjusted_top_of_stack);
39 }
40
41
esp_execute_shared_stack_function(SemaphoreHandle_t lock,void * stack,size_t stack_size,shared_stack_function function)42 void esp_execute_shared_stack_function(SemaphoreHandle_t lock, void *stack, size_t stack_size, shared_stack_function function)
43 {
44 assert(lock);
45 assert(stack);
46 assert(stack_size > 0 && stack_size >= CONFIG_ESP_MINIMAL_SHARED_STACK_SIZE);
47 assert(function);
48
49 xSemaphoreTake(lock, portMAX_DELAY);
50 portENTER_CRITICAL(&shared_stack_spinlock);
51 stack = esp_switch_stack_setup(stack, stack_size);
52 portEXIT_CRITICAL(&shared_stack_spinlock);
53
54 esp_shared_stack_invoke_function(function, stack);
55
56 portENTER_CRITICAL(&shared_stack_spinlock);
57 StaticTask_t *current = (StaticTask_t *)xTaskGetCurrentTaskHandle();
58
59 //Restore current task stack:
60 current->pxDummy6 = (StackType_t *)current_task_stack;
61 #if CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK
62 vPortSetStackWatchpoint(current->pxDummy6);
63 #endif
64 portEXIT_CRITICAL(&shared_stack_spinlock);
65
66 xSemaphoreGive(lock);
67 }
68