From 486316f222c97381ed3019603a5cf93d2f538f38 Mon Sep 17 00:00:00 2001 From: Marius Vikhammer Date: Wed, 8 Jun 2022 14:18:03 +0800 Subject: [PATCH] spinlock: fixed spinlocks not working on S3 if placed in PSRAM The compare and set instruction (S32C1I) cannot be used when lock is not in internal memory. Closes https://github.com/espressif/esp-idf/issues/9120 --- components/esp_hw_support/include/spinlock.h | 6 ++-- .../freertos/test/port/test_spinlocks.c | 28 +++++++++++++++---- 2 files changed, 25 insertions(+), 9 deletions(-) diff --git a/components/esp_hw_support/include/spinlock.h b/components/esp_hw_support/include/spinlock.h index 50ac792cb1..6dd92d1b82 100644 --- a/components/esp_hw_support/include/spinlock.h +++ b/components/esp_hw_support/include/spinlock.h @@ -37,7 +37,7 @@ typedef struct { NEED_VOLATILE_MUX uint32_t count; }spinlock_t; -#if (CONFIG_SPIRAM && CONFIG_IDF_TARGET_ESP32) +#if (CONFIG_SPIRAM) /** * @brief Check if the pointer is on external ram * @param p pointer @@ -108,13 +108,13 @@ static inline bool __attribute__((always_inline)) spinlock_acquire(spinlock_t *l */ result = core_id; -#if (CONFIG_SPIRAM && CONFIG_IDF_TARGET_ESP32) +#if (CONFIG_SPIRAM) if (spinlock_ptr_external_ram(lock)) { compare_and_set_extram(&lock->owner, SPINLOCK_FREE, &result); } else { #endif compare_and_set_native(&lock->owner, SPINLOCK_FREE, &result); -#if (CONFIG_SPIRAM && CONFIG_IDF_TARGET_ESP32) +#if (CONFIG_SPIRAM) } #endif if(result != other_core_id) { diff --git a/components/freertos/test/port/test_spinlocks.c b/components/freertos/test/port/test_spinlocks.c index 40cee0c7fb..f27f6c8d14 100644 --- a/components/freertos/test/port/test_spinlocks.c +++ b/components/freertos/test/port/test_spinlocks.c @@ -78,15 +78,15 @@ TEST_CASE("portMUX recursive locks (no contention)", "[freertos]") #if portNUM_PROCESSORS == 2 static volatile int shared_value; -static portMUX_TYPE shared_mux; +static portMUX_TYPE *shared_mux; static SemaphoreHandle_t done_sem; static void task_shared_value_increment(void *ignore) { for (int i = 0; i < REPEAT_OPS; i++) { - portENTER_CRITICAL(&shared_mux); + portENTER_CRITICAL(shared_mux); shared_value++; - portEXIT_CRITICAL(&shared_mux); + portEXIT_CRITICAL(shared_mux); } xSemaphoreGive(done_sem); vTaskDelete(NULL); @@ -94,8 +94,9 @@ static void task_shared_value_increment(void *ignore) TEST_CASE("portMUX cross-core locking", "[freertos]") { + shared_mux = heap_caps_malloc(sizeof(portMUX_TYPE), MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL); done_sem = xSemaphoreCreateCounting(2, 0); - portMUX_INITIALIZE(&shared_mux); + portMUX_INITIALIZE(shared_mux); shared_value = 0; BENCHMARK_START(); @@ -111,15 +112,17 @@ TEST_CASE("portMUX cross-core locking", "[freertos]") BENCHMARK_END("cross-core incrementing"); vSemaphoreDelete(done_sem); + free(shared_mux); TEST_ASSERT_EQUAL_INT(REPEAT_OPS * 2, shared_value); } -TEST_CASE("portMUX high contention", "[freertos]") +void portmux_high_contention_test(uint32_t lock_malloc_caps) { const int TOTAL_TASKS = 8; /* half on each core */ + shared_mux = heap_caps_malloc(sizeof(portMUX_TYPE), lock_malloc_caps); done_sem = xSemaphoreCreateCounting(TOTAL_TASKS, 0); - portMUX_INITIALIZE(&shared_mux); + portMUX_INITIALIZE(shared_mux); shared_value = 0; BENCHMARK_START(); @@ -141,8 +144,21 @@ TEST_CASE("portMUX high contention", "[freertos]") BENCHMARK_END("cross-core high contention"); vSemaphoreDelete(done_sem); + free(shared_mux); TEST_ASSERT_EQUAL_INT(REPEAT_OPS * TOTAL_TASKS, shared_value); } +TEST_CASE("portMUX high contention", "[freertos]") +{ + portmux_high_contention_test(MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL); +} + +#if CONFIG_SPIRAM_USE_MALLOC || CONFIG_SPIRAM_USE_CAPS_ALLOC +TEST_CASE("portMUX high contention, PSRAM", "[freertos]") +{ + portmux_high_contention_test(MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM); +} +#endif// CONFIG_SPIRAM_USE_MALLOC || CONFIG_SPIRAM_USE_CAPS_ALLOC + #endif // portNUM_PROCESSORS == 2