diff --git a/components/esp_common/Kconfig b/components/esp_common/Kconfig index bbed1dca1e..d236d804fa 100644 --- a/components/esp_common/Kconfig +++ b/components/esp_common/Kconfig @@ -77,6 +77,13 @@ menu "Common ESP-related" FreeRTOS timer task size, see "FreeRTOS timer task stack size" option in "FreeRTOS" menu. + config ESP_MINIMAL_SHARED_STACK_SIZE + int "Minimal allowed size for shared stack" + default 2048 + help + Minimal value of size, in bytes, accepted to execute a expression + with shared stack. + choice ESP_CONSOLE_UART prompt "UART for console output" default ESP_CONSOLE_UART_DEFAULT diff --git a/components/esp_common/include/esp_expression_with_stack.h b/components/esp_common/include/esp_expression_with_stack.h index 3aa12a2538..cd1e4765a8 100644 --- a/components/esp_common/include/esp_expression_with_stack.h +++ b/components/esp_common/include/esp_expression_with_stack.h @@ -11,14 +11,16 @@ // 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. - -#ifndef __ESP_EXPRESSION_WITH_STACK_H -#define __ESP_EXPRESSION_WITH_STACK_H +#pragma once #include "freertos/FreeRTOS.h" #include "freertos/semphr.h" #include "esp_debug_helpers.h" +#include "esp_log.h" +#ifdef __cplusplus +extern "C" { +#endif /** * @brief Executes a 1-line expression with a application alocated stack @@ -26,20 +28,21 @@ * @param stack Pointer to user alocated stack * @param stack_size Size of current stack in bytes * @param expression Expression or function to be executed using the stack + * @note if either lock, stack or stack size is invalid, the expression will + * be called using the current stack. */ -#define ESP_EXECUTE_EXPRESSION_WITH_STACK(lock, stack, stack_size, expression) \ -({ \ - if (lock && stack && stack_size) { \ - uint32_t backup; \ - xSemaphoreTake(lock, portMAX_DELAY); \ - StackType_t *top_of_stack = esp_switch_stack_setup(stack, stack_size);\ - esp_switch_stack_enter(top_of_stack, &backup); \ - { \ - expression; \ - } \ - esp_switch_stack_exit(&backup); \ - xSemaphoreGive(lock); \ - } \ +#define ESP_EXECUTE_EXPRESSION_WITH_STACK(lock, stack, stack_size, expression) \ +({ \ + assert(lock && stack && (stack_size >= CONFIG_ESP_MINIMAL_SHARED_STACK_SIZE)); \ + uint32_t backup; \ + xSemaphoreTake(lock, portMAX_DELAY); \ + StackType_t *top_of_stack = esp_switch_stack_setup(stack, stack_size); \ + esp_switch_stack_enter(top_of_stack, &backup); \ + { \ + expression; \ + } \ + esp_switch_stack_exit(&backup); \ + xSemaphoreGive(lock); \ }) /** @@ -66,4 +69,6 @@ extern void esp_switch_stack_enter(StackType_t *stack, uint32_t *backup_stack); */ extern void esp_switch_stack_exit(uint32_t *backup_stack); +#ifdef __cplusplus +} #endif \ No newline at end of file diff --git a/components/newlib/test/test_shared_stack_printf.c b/components/newlib/test/test_shared_stack_printf.c index 9b020f5815..81997a5a9a 100644 --- a/components/newlib/test/test_shared_stack_printf.c +++ b/components/newlib/test/test_shared_stack_printf.c @@ -1,4 +1,5 @@ #include +#include #include "unity.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" @@ -29,3 +30,4 @@ TEST_CASE("test printf using shared buffer stack", "[newlib]") vSemaphoreDelete(printf_lock); free(shared_stack); } + diff --git a/components/xtensa/expression_with_stack_xtensa.c b/components/xtensa/expression_with_stack_xtensa.c index 6f9cf4ca3c..74829d7e8b 100644 --- a/components/xtensa/expression_with_stack_xtensa.c +++ b/components/xtensa/expression_with_stack_xtensa.c @@ -1,10 +1,26 @@ +// 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 StackType_t * esp_switch_stack_setup(StackType_t *stack, size_t stack_size) { +#if CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK int watchpoint_place = (((int)stack + 31) & ~31); +#endif StackType_t *top_of_stack = (StackType_t *)&stack[0] + ((stack_size * sizeof(StackType_t)) / sizeof(StackType_t)); @@ -18,6 +34,9 @@ StackType_t * esp_switch_stack_setup(StackType_t *stack, size_t stack_size) frame->a0 = 0; frame->a1 = (UBaseType_t)top_of_stack; +#if CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK esp_set_watchpoint(2, (char*)watchpoint_place, 32, ESP_WATCHPOINT_STORE); +#endif + return top_of_stack; } \ 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 106eb6f9c4..f868131ba0 100644 --- a/components/xtensa/expression_with_stack_xtensa_asm.S +++ b/components/xtensa/expression_with_stack_xtensa_asm.S @@ -46,9 +46,13 @@ esp_switch_stack_exit: #ifndef __XTENSA_CALL0_ABI__ entry sp, 0x10 + +#if CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK movi a6, 2 movi a4, esp_clear_watchpoint callx4 a4 /* clear the watchpoint before releasing stack */ +#endif + l32i a4, a2, 0 /* recover the original task stack */ mov a1, a4 /* put it on sp register again */ retw