From 66726ec166f017224f94eb5ec2d43661b149d5e1 Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Wed, 26 Apr 2017 12:45:24 +1000 Subject: [PATCH] freertos: Enable vTaskSuspend()/vTaskResume() API Adds relevant unit tests. TW11878 --- components/freertos/tasks.c | 11 +- .../freertos/test/test_suspend_resume.c | 173 ++++++++++++++++++ tools/unit-test-app/sdkconfig | 54 +++++- 3 files changed, 223 insertions(+), 15 deletions(-) create mode 100644 components/freertos/test/test_suspend_resume.c diff --git a/components/freertos/tasks.c b/components/freertos/tasks.c index ff407d9ba..a324c2a21 100644 --- a/components/freertos/tasks.c +++ b/components/freertos/tasks.c @@ -488,6 +488,8 @@ extern void esp_vApplicationTickHook( void ); * Utility task that simply returns pdTRUE if the task referenced by xTask is * currently in the Suspended state, or pdFALSE if the task referenced by xTask * is in any other state. + * + * Caller must hold xTaskQueueMutex before calling this function. */ #if ( INCLUDE_vTaskSuspend == 1 ) static BaseType_t prvTaskIsTaskSuspended( const TaskHandle_t xTask ) PRIVILEGED_FUNCTION; @@ -1716,13 +1718,11 @@ static void prvAddNewTaskToReadyList( TCB_t *pxNewTCB, TaskFunction_t pxTaskCode /*-----------------------------------------------------------*/ #if ( INCLUDE_vTaskSuspend == 1 ) -/* ToDo: Make this multicore-compatible. */ void vTaskSuspend( TaskHandle_t xTaskToSuspend ) { TCB_t *pxTCB; TCB_t *curTCB; - UNTESTED_FUNCTION(); taskENTER_CRITICAL(&xTaskQueueMutex); { /* If null is passed in here then it is the running task that is @@ -1810,15 +1810,13 @@ static void prvAddNewTaskToReadyList( TCB_t *pxNewTCB, TaskFunction_t pxTaskCode /*-----------------------------------------------------------*/ #if ( INCLUDE_vTaskSuspend == 1 ) - static BaseType_t prvTaskIsTaskSuspended( const TaskHandle_t xTask ) { BaseType_t xReturn = pdFALSE; const TCB_t * const pxTCB = ( TCB_t * ) xTask; /* Accesses xPendingReadyList so must be called from a critical - section. */ - taskENTER_CRITICAL(&xTaskQueueMutex); + section (caller is required to hold xTaskQueueMutex). */ /* It does not make sense to check if the calling task is suspended. */ configASSERT( xTask ); @@ -1849,7 +1847,6 @@ static void prvAddNewTaskToReadyList( TCB_t *pxNewTCB, TaskFunction_t pxTaskCode { mtCOVERAGE_TEST_MARKER(); } - taskEXIT_CRITICAL(&xTaskQueueMutex); return xReturn; } /*lint !e818 xTask cannot be a pointer to const because it is a typedef. */ @@ -1859,12 +1856,10 @@ static void prvAddNewTaskToReadyList( TCB_t *pxNewTCB, TaskFunction_t pxTaskCode #if ( INCLUDE_vTaskSuspend == 1 ) -/* ToDo: Make this multicore-compatible. */ void vTaskResume( TaskHandle_t xTaskToResume ) { TCB_t * const pxTCB = ( TCB_t * ) xTaskToResume; - UNTESTED_FUNCTION(); /* It does not make sense to resume the calling task. */ configASSERT( xTaskToResume ); diff --git a/components/freertos/test/test_suspend_resume.c b/components/freertos/test/test_suspend_resume.c new file mode 100644 index 000000000..5908d2135 --- /dev/null +++ b/components/freertos/test/test_suspend_resume.c @@ -0,0 +1,173 @@ +/* Tests for FreeRTOS task suspend & resume */ +#include + +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/semphr.h" +#include "freertos/queue.h" +#include "freertos/xtensa_api.h" +#include "unity.h" +#include "soc/cpu.h" + +#include "driver/timer.h" + +/* Counter task counts a target variable forever */ +static void task_count(void *vp_counter) +{ + volatile unsigned *counter = (volatile unsigned *)vp_counter; + *counter = 0; + + while (1) { + (*counter)++; + vTaskDelay(1); + } +} + +static void test_suspend_resume(int target_core) +{ + volatile unsigned counter = 0; + TaskHandle_t counter_task; + + xTaskCreatePinnedToCore(task_count, "Count", 2048, + (void *)&counter, UNITY_FREERTOS_PRIORITY + 1, + &counter_task, target_core); + + vTaskDelay(10); + /* check some counting has happened */ + TEST_ASSERT_NOT_EQUAL(0, counter); + + // Do the next part a few times, just to be sure multiple suspends & resumes + // work as expected... + const int TEST_ITERATIONS = 5; + for (int i = 0; i < TEST_ITERATIONS; i++) { + vTaskSuspend(counter_task); + unsigned suspend_count = counter; + printf("Suspending @ %d\n", suspend_count); + + vTaskDelay(2); + + printf("Still suspended @ %d\n", counter); + + /* check the counter hasn't gone up while the task is suspended */ + TEST_ASSERT_EQUAL(suspend_count, counter); + vTaskResume(counter_task); + vTaskDelay(2); + + printf("Resumed @ %d\n", counter); + /* check the counter is going up again now the task is resumed */ + TEST_ASSERT_NOT_EQUAL(suspend_count, counter); + } + + vTaskDelete(counter_task); +} + + +TEST_CASE("Suspend/resume task on same core", "[freertos]") +{ + test_suspend_resume(UNITY_FREERTOS_CPU); +} + +#ifndef CONFIG_FREERTOS_UNICORE +TEST_CASE("Suspend/resume task on other core", "[freertos]") +{ + test_suspend_resume(!UNITY_FREERTOS_CPU); +} +#endif + +/* Task suspends itself, then sets a flag and deletes itself */ +static void task_suspend_self(void *vp_resumed) +{ + volatile bool *resumed = (volatile bool *)vp_resumed; + *resumed = false; + vTaskSuspend(NULL); + *resumed = true; + vTaskDelete(NULL); +} + +TEST_CASE("Suspend the current running task", "[freertos]") +{ + volatile bool resumed = false; + TaskHandle_t suspend_task; + + xTaskCreatePinnedToCore(task_suspend_self, "suspend_self", 2048, + (void *)&resumed, UNITY_FREERTOS_PRIORITY + 1, + &suspend_task, UNITY_FREERTOS_CPU); + + vTaskDelay(1); + TEST_ASSERT_FALSE(resumed); + + vTaskResume(suspend_task); + // Shouldn't need any delay here, as task should resume on this CPU immediately + TEST_ASSERT_TRUE(resumed); +} + + +volatile bool timer_isr_fired; + +/* Timer ISR clears interrupt, sets flag, then resumes the task supplied in the + * callback argument. + */ +void IRAM_ATTR timer_group0_isr(void *vp_arg) +{ + // Clear interrupt + TIMERG0.int_clr_timers.val = TIMERG0.int_st_timers.val; + + timer_isr_fired = true; + TaskHandle_t handle = vp_arg; + BaseType_t higherPriorityTaskWoken = pdFALSE; + higherPriorityTaskWoken = xTaskResumeFromISR(handle); + if (higherPriorityTaskWoken == pdTRUE) { + portYIELD_FROM_ISR(); + } +} + +/* Create a task which suspends itself, then resume it from a timer + * interrupt. */ +static void test_resume_task_from_isr(int target_core) +{ + volatile bool resumed = false; + TaskHandle_t suspend_task; + + xTaskCreatePinnedToCore(task_suspend_self, "suspend_self", 2048, + (void *)&resumed, UNITY_FREERTOS_PRIORITY + 1, + &suspend_task, target_core); + + vTaskDelay(1); + TEST_ASSERT_FALSE(resumed); + + /* Configure timer ISR */ + const timer_config_t config = { + .alarm_en = 1, + .auto_reload = 0, + .counter_dir = TIMER_COUNT_UP, + .divider = 1, + .intr_type = TIMER_INTR_LEVEL, + .counter_en = TIMER_PAUSE, + }; + /*Configure timer*/ + timer_init(TIMER_GROUP_0, TIMER_0, &config); + timer_pause(TIMER_GROUP_0, TIMER_0); + timer_set_counter_value(TIMER_GROUP_0, TIMER_0, 0); + timer_set_alarm_value(TIMER_GROUP_0, TIMER_0, 1000); + timer_enable_intr(TIMER_GROUP_0, TIMER_0); + timer_isr_register(TIMER_GROUP_0, TIMER_0, timer_group0_isr, (void*)suspend_task, ESP_INTR_FLAG_IRAM, NULL); + timer_isr_fired = false; + timer_start(TIMER_GROUP_0, TIMER_0); + + vTaskDelay(1); + + TEST_ASSERT_TRUE(timer_isr_fired); + TEST_ASSERT_TRUE(resumed); +} + +TEST_CASE("Resume task from ISR (same core)", "[freertos]") +{ + test_resume_task_from_isr(UNITY_FREERTOS_CPU); +} + +#ifndef CONFIG_FREERTOS_UNICORE +TEST_CASE("Resume task from ISR (other core)", "[freertos]") +{ + test_resume_task_from_isr(!UNITY_FREERTOS_CPU); +} +#endif diff --git a/tools/unit-test-app/sdkconfig b/tools/unit-test-app/sdkconfig index 44b599b4a..467da45da 100644 --- a/tools/unit-test-app/sdkconfig +++ b/tools/unit-test-app/sdkconfig @@ -81,19 +81,13 @@ CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partition_table_unit_test_app.csv" CONFIG_PARTITION_TABLE_CUSTOM_APP_BIN_OFFSET=0x10000 CONFIG_PARTITION_TABLE_FILENAME="partition_table_unit_test_app.csv" CONFIG_APP_OFFSET=0x10000 -CONFIG_PHY_DATA_OFFSET= CONFIG_OPTIMIZATION_LEVEL_DEBUG=y # CONFIG_OPTIMIZATION_LEVEL_RELEASE is not set # # Component config # - -# -# Amazon Web Service IoT Config -# -CONFIG_AWS_IOT_MQTT_HOST="" -CONFIG_AWS_IOT_MQTT_PORT=8883 +# CONFIG_AWS_IOT_SDK is not set # CONFIG_BT_ENABLED is not set CONFIG_BT_RESERVE_DRAM=0 @@ -117,6 +111,9 @@ CONFIG_ESP32_ENABLE_COREDUMP_TO_NONE=y # CONFIG_ESP32_APPTRACE_DEST_UART is not set CONFIG_ESP32_APPTRACE_DEST_NONE=y # CONFIG_ESP32_APPTRACE_ENABLE is not set +CONFIG_BASE_MAC_STORED_DEFAULT_EFUSE=y +# CONFIG_BASE_MAC_STORED_CUSTOMER_DEFINED_EFUSE is not set +# CONFIG_BASE_MAC_STORED_OTHER_CUSTOMER_DEFINED_PLACE is not set # CONFIG_TWO_MAC_ADDRESS_FROM_EFUSE is not set CONFIG_FOUR_MAC_ADDRESS_FROM_EFUSE=y CONFIG_NUMBER_OF_MAC_ADDRESS_GENERATED_FROM_EFUSE=4 @@ -146,10 +143,18 @@ CONFIG_ESP32_TIME_SYSCALL_USE_RTC_FRC1=y # CONFIG_ESP32_TIME_SYSCALL_USE_FRC1 is not set # CONFIG_ESP32_TIME_SYSCALL_USE_NONE is not set CONFIG_ESP32_RTC_CLOCK_SOURCE_INTERNAL_RC=y +# CONFIG_ESP32_RTC_CLOCK_SOURCE_EXTERNAL_CRYSTAL is not set CONFIG_ESP32_DEEP_SLEEP_WAKEUP_DELAY=0 +# CONFIG_ESP32_XTAL_FREQ_40 is not set +# CONFIG_ESP32_XTAL_FREQ_26 is not set +CONFIG_ESP32_XTAL_FREQ_AUTO=y +CONFIG_ESP32_XTAL_FREQ=0 CONFIG_WIFI_ENABLED=y CONFIG_ESP32_WIFI_STATIC_RX_BUFFER_NUM=10 CONFIG_ESP32_WIFI_DYNAMIC_RX_BUFFER_NUM=0 +# CONFIG_ESP32_WIFI_STATIC_TX_BUFFER is not set +CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER=y +CONFIG_ESP32_WIFI_TX_BUFFER_TYPE=1 CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER_NUM=32 CONFIG_ESP32_WIFI_AMPDU_ENABLED=y CONFIG_ESP32_WIFI_NVS_ENABLED=y @@ -164,6 +169,34 @@ CONFIG_ESP32_PHY_MAX_WIFI_TX_POWER=20 CONFIG_ESP32_PHY_MAX_TX_POWER=20 # CONFIG_ETHERNET is not set +# +# FAT Filesystem support +# +CONFIG_FATFS_CODEPAGE_ASCII=y +# CONFIG_FATFS_CODEPAGE_437 is not set +# CONFIG_FATFS_CODEPAGE_720 is not set +# CONFIG_FATFS_CODEPAGE_737 is not set +# CONFIG_FATFS_CODEPAGE_771 is not set +# CONFIG_FATFS_CODEPAGE_775 is not set +# CONFIG_FATFS_CODEPAGE_850 is not set +# CONFIG_FATFS_CODEPAGE_852 is not set +# CONFIG_FATFS_CODEPAGE_855 is not set +# CONFIG_FATFS_CODEPAGE_857 is not set +# CONFIG_FATFS_CODEPAGE_860 is not set +# CONFIG_FATFS_CODEPAGE_861 is not set +# CONFIG_FATFS_CODEPAGE_862 is not set +# CONFIG_FATFS_CODEPAGE_863 is not set +# CONFIG_FATFS_CODEPAGE_864 is not set +# CONFIG_FATFS_CODEPAGE_865 is not set +# CONFIG_FATFS_CODEPAGE_866 is not set +# CONFIG_FATFS_CODEPAGE_869 is not set +# CONFIG_FATFS_CODEPAGE_932 is not set +# CONFIG_FATFS_CODEPAGE_936 is not set +# CONFIG_FATFS_CODEPAGE_949 is not set +# CONFIG_FATFS_CODEPAGE_950 is not set +CONFIG_FATFS_CODEPAGE=1 +CONFIG_FATFS_MAX_LFN=255 + # # FreeRTOS # @@ -185,6 +218,10 @@ CONFIG_FREERTOS_BREAK_ON_SCHEDULER_START_JTAG=y CONFIG_FREERTOS_ISR_STACKSIZE=1536 # CONFIG_FREERTOS_LEGACY_HOOKS is not set CONFIG_FREERTOS_MAX_TASK_NAME_LEN=16 +# CONFIG_SUPPORT_STATIC_ALLOCATION is not set +CONFIG_TIMER_TASK_PRIORITY=1 +CONFIG_TIMER_TASK_STACK_DEPTH=2048 +CONFIG_TIMER_QUEUE_LENGTH=10 # CONFIG_FREERTOS_DEBUG_INTERNALS is not set # @@ -213,6 +250,8 @@ CONFIG_LWIP_DHCP_MAX_NTP_SERVERS=1 CONFIG_TCP_MAXRTX=12 CONFIG_TCP_SYNMAXRTX=6 # CONFIG_LWIP_DHCP_DOES_ARP_CHECK is not set +CONFIG_TCPIP_TASK_STACK_SIZE=2048 +# CONFIG_PPP_SUPPORT is not set # # mbedTLS @@ -237,3 +276,4 @@ CONFIG_OPENSSL_ASSERT_DO_NOTHING=y # SPI Flash driver # # CONFIG_SPI_FLASH_ENABLE_COUNTERS is not set +CONFIG_SPI_FLASH_ROM_DRIVER_PATCH=y