mirror of
https://github.com/espressif/esp-idf.git
synced 2026-04-27 19:13:21 +00:00
test(freertos): harden mutex owner assert reset test
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
* SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
@@ -7,35 +7,73 @@
|
|||||||
#include "freertos/FreeRTOS.h"
|
#include "freertos/FreeRTOS.h"
|
||||||
#include "freertos/task.h"
|
#include "freertos/task.h"
|
||||||
#include "freertos/semphr.h"
|
#include "freertos/semphr.h"
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include "esp_attr.h"
|
||||||
|
#include "soc/soc_caps.h"
|
||||||
|
#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE
|
||||||
|
#include "hal/cache_ll.h"
|
||||||
|
#endif
|
||||||
#include "unity.h"
|
#include "unity.h"
|
||||||
#include "test_utils.h"
|
#include "test_utils.h"
|
||||||
#include "esp_system.h"
|
|
||||||
|
|
||||||
/* If assertions aren't set to fail this code still crashes, but not with an abort... */
|
/* If assertions aren't set to fail this code still crashes, but not with an abort... */
|
||||||
#if CONFIG_FREERTOS_CHECK_MUTEX_GIVEN_BY_OWNER && !CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_DISABLE
|
#if !CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_DISABLE
|
||||||
|
|
||||||
|
/* Persists across reset so stage 2 can confirm stage 1 reached the failure path. */
|
||||||
|
static __NOINIT_ATTR bool s_restart_marker;
|
||||||
|
/* Reinitialized on reboot so stage 2 can distinguish a real restart from normal return. */
|
||||||
|
static bool s_runtime_marker;
|
||||||
|
|
||||||
static void mutex_release_task(void* arg)
|
static void mutex_release_task(void* arg)
|
||||||
{
|
{
|
||||||
SemaphoreHandle_t mutex = (SemaphoreHandle_t) arg;
|
SemaphoreHandle_t mutex = (SemaphoreHandle_t) arg;
|
||||||
xSemaphoreGive(mutex);
|
xSemaphoreGive(mutex);
|
||||||
|
/* The spawned task gives a mutex it does not own. Because the mutex is still held by the
|
||||||
|
main task, the give flows through xSemaphoreGive(), xQueueGenericSend(),
|
||||||
|
prvCopyDataToQueue(), and xTaskPriorityDisinherit(), where configASSERT(pxTCB ==
|
||||||
|
pxCurrentTCB) fires and the panic resets the chip. */
|
||||||
TEST_FAIL_MESSAGE("should not be reached");
|
TEST_FAIL_MESSAGE("should not be reached");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void check_reset_reason_panic(void)
|
static void setup_restart_markers(void)
|
||||||
{
|
{
|
||||||
TEST_ASSERT_EQUAL(ESP_RST_PANIC, esp_reset_reason());
|
s_restart_marker = true;
|
||||||
|
s_runtime_marker = true;
|
||||||
|
|
||||||
|
#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE
|
||||||
|
/* If internal data is behind a cache it might not be written to the physical memory when we crash
|
||||||
|
force a full writeback here to ensure this */
|
||||||
|
cache_ll_writeback_all(CACHE_LL_LEVEL_INT_MEM, CACHE_TYPE_DATA, CACHE_LL_ID_ALL);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static void check_system_restarted(void)
|
||||||
|
{
|
||||||
|
/* s_restart_marker is NOINIT so it still holds the true value set in stage 1 across the
|
||||||
|
* software reset; s_runtime_marker is BSS so it is re-initialized to false on every boot. */
|
||||||
|
TEST_ASSERT_TRUE(s_restart_marker);
|
||||||
|
TEST_ASSERT_FALSE(s_runtime_marker);
|
||||||
|
|
||||||
|
s_restart_marker = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void do_mutex_release_assert(void)
|
static void do_mutex_release_assert(void)
|
||||||
{
|
{
|
||||||
|
setup_restart_markers();
|
||||||
|
|
||||||
SemaphoreHandle_t mutex = xSemaphoreCreateMutex();
|
SemaphoreHandle_t mutex = xSemaphoreCreateMutex();
|
||||||
xSemaphoreTake(mutex, portMAX_DELAY);
|
xSemaphoreTake(mutex, portMAX_DELAY);
|
||||||
xTaskCreate(&mutex_release_task, "mutex_release", 2048, mutex, UNITY_FREERTOS_PRIORITY + 1, NULL);
|
xTaskCreate(&mutex_release_task, "mutex_release", 2048, mutex, UNITY_FREERTOS_PRIORITY + 1, NULL);
|
||||||
vTaskDelay(1);
|
/* Stage 1 must not return to Unity before the releaser trips the panic. */
|
||||||
|
vTaskSuspend(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE_MULTIPLE_STAGES("mutex released not by owner causes an assert", "[freertos][reset=assert,SW_CPU_RESET]",
|
TEST_CASE_MULTIPLE_STAGES("mutex released not by owner causes an assert", "[freertos]",
|
||||||
|
/* On dual-core ESP32 the panic handler can deadlock on S32C1I if the
|
||||||
|
* stalled core was mid-atomic, causing an RTC WDT reset (ESP_RST_WDT)
|
||||||
|
* instead of ESP_RST_PANIC. Stage 2 therefore verifies a real reboot
|
||||||
|
* via NOINIT and BSS state instead of checking the reset reason. */
|
||||||
do_mutex_release_assert,
|
do_mutex_release_assert,
|
||||||
check_reset_reason_panic)
|
check_system_restarted)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user