From ec5acf91ee88db44ce04f38d9c6ef4537015e872 Mon Sep 17 00:00:00 2001 From: Felipe Neves Date: Tue, 17 Nov 2020 16:37:28 -0300 Subject: [PATCH] esp_shared_stack: enable shared stack function for riscv and reenable the unit test --- .../port/riscv/include/freertos/xtensa_api.h | 2 + components/riscv/CMakeLists.txt | 2 + .../riscv/expression_with_stack_riscv.c | 79 +++++++++++++++++++ .../riscv/expression_with_stack_riscv_asm.S | 43 ++++++++++ 4 files changed, 126 insertions(+) create mode 100644 components/freertos/port/riscv/include/freertos/xtensa_api.h create mode 100644 components/riscv/expression_with_stack_riscv.c create mode 100644 components/riscv/expression_with_stack_riscv_asm.S diff --git a/components/freertos/port/riscv/include/freertos/xtensa_api.h b/components/freertos/port/riscv/include/freertos/xtensa_api.h new file mode 100644 index 0000000000..245b6246c0 --- /dev/null +++ b/components/freertos/port/riscv/include/freertos/xtensa_api.h @@ -0,0 +1,2 @@ +/* Just a placeholder since this file is exposed in some top-level apps */ +#pragma once diff --git a/components/riscv/CMakeLists.txt b/components/riscv/CMakeLists.txt index 6d3744d6a7..c42b51db9d 100644 --- a/components/riscv/CMakeLists.txt +++ b/components/riscv/CMakeLists.txt @@ -9,6 +9,8 @@ else() set(srcs "interrupt.c" "stdatomic.c" + "expression_with_stack_riscv.c" + "expression_with_stack_riscv_asm.S" "vectors.S") endif() diff --git a/components/riscv/expression_with_stack_riscv.c b/components/riscv/expression_with_stack_riscv.c new file mode 100644 index 0000000000..28e492ce00 --- /dev/null +++ b/components/riscv/expression_with_stack_riscv.c @@ -0,0 +1,79 @@ +// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include +#include + +static portMUX_TYPE shared_stack_spinlock = portMUX_INITIALIZER_UNLOCKED; +static void *current_task_stack = NULL; + +extern void esp_shared_stack_invoke_function(shared_stack_function function, void *stack); + +static StackType_t *esp_switch_stack_setup(StackType_t *stack, size_t stack_size) +{ +#if CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK + // TODO ESP32-C3 IDF-2207 + // 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: + top_of_stack = (StackType_t *)(((UBaseType_t)(top_of_stack - 16) & ~0xf)); + RvExcFrame *adjusted_top_of_stack = (RvExcFrame *) top_of_stack; + adjusted_top_of_stack--; + +#if CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK + // TODO ESP32-C3 IDF-2207 + //esp_set_watchpoint(1, (uint8_t *)watchpoint_place, 32, ESP_WATCHPOINT_STORE); +#endif + + return ((StackType_t *)adjusted_top_of_stack); +} + + +void esp_execute_shared_stack_function(SemaphoreHandle_t lock, void *stack, size_t stack_size, shared_stack_function function) +{ + assert(lock); + assert(stack); + assert(stack_size > 0 && stack_size >= CONFIG_ESP_MINIMAL_SHARED_STACK_SIZE); + assert(function); + + xSemaphoreTake(lock, portMAX_DELAY); + portENTER_CRITICAL(&shared_stack_spinlock); + stack = esp_switch_stack_setup(stack, stack_size); + portEXIT_CRITICAL(&shared_stack_spinlock); + + esp_shared_stack_invoke_function(function, stack); + + portENTER_CRITICAL(&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); + + xSemaphoreGive(lock); +} diff --git a/components/riscv/expression_with_stack_riscv_asm.S b/components/riscv/expression_with_stack_riscv_asm.S new file mode 100644 index 0000000000..99b0ec5840 --- /dev/null +++ b/components/riscv/expression_with_stack_riscv_asm.S @@ -0,0 +1,43 @@ +// Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + + .section .text + + .global esp_shared_stack_invoke_function + .type esp_shared_stack_invoke_function, @function +esp_shared_stack_invoke_function: + /* save current stack and return address */ + mv t0, sp + mv t1, ra + + /* Set shared stack as new stack pointer */ + mv sp, a1 + + /* store the ra and previous stack pointer in a safe place */ + addi sp,sp,-4 + sw t0, 0(sp) + sw t1, 4(sp) + + /* call the subroutine */ + jalr a0, 0 + + /* gets the ra and stack pointer saved previously */ + lw t0, 0(sp) + lw t1, 4(sp) + addi sp, sp, 4 + + /* restore both ra and real stack pointer of current task */ + mv ra, t1 + mv sp, t0 + ret