From a004a21b13c3567fe98b812c47cbc0e749c74bdf Mon Sep 17 00:00:00 2001 From: Rahul Kar <118818625+kar-rahul-aws@users.noreply.github.com> Date: Wed, 14 Aug 2024 11:56:38 +0530 Subject: [PATCH 1/5] Remove ipLOCAL_MAC_ADDRESS from demo files (#1244) * Remove ipLOCAL_MAC_ADDRESS from demo files * Add return variable for IP_Init fucntions --- .../Demo/FreeRTOS_Plus_TCP_Echo_Posix/main_networking.c | 9 +++++---- .../FreeRTOS_Plus_TCP_Echo_Qemu_mps2/main_networking.c | 6 ++++-- .../IPv6_Multi_WinSim_demo/main.c | 5 ++++- .../main.c | 9 ++++++--- .../FreeRTOS+TCP/plus_tcp_hooks_winsim.c | 2 +- 5 files changed, 20 insertions(+), 11 deletions(-) diff --git a/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Echo_Posix/main_networking.c b/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Echo_Posix/main_networking.c index 8fde5343f51..42563624dd4 100644 --- a/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Echo_Posix/main_networking.c +++ b/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Echo_Posix/main_networking.c @@ -135,6 +135,7 @@ static UBaseType_t ulNextRand; void main_tcp_echo_client_tasks( void ) { + BaseType_t xResult; const uint32_t ulLongTime_ms = pdMS_TO_TICKS( 1000UL ); /* @@ -157,8 +158,6 @@ void main_tcp_echo_client_tasks( void ) /* Initialise the network interface.*/ FreeRTOS_debug_printf( ( "FreeRTOS_IPInit\r\n" ) ); - memcpy( ipLOCAL_MAC_ADDRESS, ucMACAddress, sizeof( ucMACAddress ) ); - #if defined( ipconfigIPv4_BACKWARD_COMPATIBLE ) && ( ipconfigIPv4_BACKWARD_COMPATIBLE == 0 ) extern NetworkInterface_t * pxLibslirp_FillInterfaceDescriptor( BaseType_t xEMACIndex, NetworkInterface_t * pxInterface ); @@ -173,12 +172,14 @@ void main_tcp_echo_client_tasks( void ) } #endif /* ( ipconfigUSE_DHCP != 0 ) */ - FreeRTOS_IPInit_Multi(); + xResult = FreeRTOS_IPInit_Multi(); #else /* if defined( ipconfigIPv4_BACKWARD_COMPATIBLE ) && ( ipconfigIPv4_BACKWARD_COMPATIBLE == 0 ) */ /* Using the old /single /IPv4 library, or using backward compatible mode of the new /multi library. */ - FreeRTOS_IPInit( ucIPAddress, ucNetMask, ucGatewayAddress, ucDNSServerAddress, ucMACAddress ); + xResult = FreeRTOS_IPInit( ucIPAddress, ucNetMask, ucGatewayAddress, ucDNSServerAddress, ucMACAddress ); #endif /* if defined( ipconfigIPv4_BACKWARD_COMPATIBLE ) && ( ipconfigIPv4_BACKWARD_COMPATIBLE == 0 ) */ + configASSERT( xResult == pdTRUE ); + /* Start the RTOS scheduler. */ FreeRTOS_debug_printf( ( "vTaskStartScheduler\n" ) ); vTaskStartScheduler(); diff --git a/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Echo_Qemu_mps2/main_networking.c b/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Echo_Qemu_mps2/main_networking.c index 60e5ca36402..dd964506011 100644 --- a/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Echo_Qemu_mps2/main_networking.c +++ b/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Echo_Qemu_mps2/main_networking.c @@ -140,6 +140,7 @@ static UBaseType_t ulNextRand; void main_tcp_echo_client_tasks( void ) { + BaseType_t xReturn; const uint32_t ulLongTime_ms = pdMS_TO_TICKS( 1000UL ); /* @@ -180,12 +181,13 @@ void main_tcp_echo_client_tasks( void ) } #endif /* ( ipconfigUSE_DHCP != 0 ) */ - FreeRTOS_IPInit_Multi(); + xReturn = FreeRTOS_IPInit_Multi(); #else /* if defined( ipconfigIPv4_BACKWARD_COMPATIBLE ) && ( ipconfigIPv4_BACKWARD_COMPATIBLE == 0 ) */ /* Using the old /single /IPv4 library, or using backward compatible mode of the new /multi library. */ - FreeRTOS_IPInit( ucIPAddress, ucNetMask, ucGatewayAddress, ucDNSServerAddress, ucMACAddress ); + xReturn = FreeRTOS_IPInit( ucIPAddress, ucNetMask, ucGatewayAddress, ucDNSServerAddress, ucMACAddress ); #endif /* defined( ipconfigIPv4_BACKWARD_COMPATIBLE ) && ( ipconfigIPv4_BACKWARD_COMPATIBLE == 0 ) */ + configASSERT( xReturn == pdTRUE ); /* Start the RTOS scheduler. */ FreeRTOS_debug_printf( ( "vTaskStartScheduler\n" ) ); diff --git a/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_IPv6_Demo/IPv6_Multi_WinSim_demo/main.c b/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_IPv6_Demo/IPv6_Multi_WinSim_demo/main.c index eeeb0a88e6b..62ba4277f51 100644 --- a/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_IPv6_Demo/IPv6_Multi_WinSim_demo/main.c +++ b/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_IPv6_Demo/IPv6_Multi_WinSim_demo/main.c @@ -189,6 +189,7 @@ NetworkInterface_t * pxWinPcap_FillInterfaceDescriptor( BaseType_t xEMACIndex, int main( void ) { + BaseType_t xReturn; const uint32_t ulLongTime_ms = pdMS_TO_TICKS( 1000UL ); /* @@ -314,7 +315,9 @@ int main( void ) } #endif /* ( mainNETWORK_UP_COUNT >= 3U ) */ - FreeRTOS_IPInit_Multi(); + xReturn = FreeRTOS_IPInit_Multi(); + + configASSERT( xReturn == pdTRUE ); /* Start the RTOS scheduler. */ FreeRTOS_debug_printf( ( "vTaskStartScheduler\r\n" ) ); diff --git a/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_UDP_Mode_CLI_Windows_Simulator/main.c b/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_UDP_Mode_CLI_Windows_Simulator/main.c index 1f7ff80b924..1626361c4a4 100644 --- a/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_UDP_Mode_CLI_Windows_Simulator/main.c +++ b/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_UDP_Mode_CLI_Windows_Simulator/main.c @@ -130,6 +130,7 @@ static UBaseType_t ulNextRand; int main( void ) { + BaseType_t xResult; const uint32_t ulLongTime_ms = 250UL; /* Create a mutex that is used to guard against the console being accessed @@ -157,13 +158,15 @@ int main( void ) xEndPoints[ 0 ].bits.bWantDHCP = pdTRUE; } #endif /* ( ipconfigUSE_DHCP != 0 ) */ - memcpy( ipLOCAL_MAC_ADDRESS, ucMACAddress, sizeof( ucMACAddress ) ); - FreeRTOS_IPInit_Multi(); + + xResult = FreeRTOS_IPInit_Multi(); #else /* if defined( ipconfigIPv4_BACKWARD_COMPATIBLE ) && ( ipconfigIPv4_BACKWARD_COMPATIBLE == 0 ) */ /* Using the old /single /IPv4 library, or using backward compatible mode of the new /multi library. */ - FreeRTOS_IPInit( ucIPAddress, ucNetMask, ucGatewayAddress, ucDNSServerAddress, ucMACAddress ); + xResult = FreeRTOS_IPInit( ucIPAddress, ucNetMask, ucGatewayAddress, ucDNSServerAddress, ucMACAddress ); #endif /* defined( ipconfigIPv4_BACKWARD_COMPATIBLE ) && ( ipconfigIPv4_BACKWARD_COMPATIBLE == 0 ) */ + configASSERT( xResult == pdTRUE ); + /* Initialise the logging. */ uint32_t ulLoggingIPAddress; diff --git a/FreeRTOS-Plus/VisualStudio_StaticProjects/FreeRTOS+TCP/plus_tcp_hooks_winsim.c b/FreeRTOS-Plus/VisualStudio_StaticProjects/FreeRTOS+TCP/plus_tcp_hooks_winsim.c index 2529592cac9..92d08fc5d7f 100644 --- a/FreeRTOS-Plus/VisualStudio_StaticProjects/FreeRTOS+TCP/plus_tcp_hooks_winsim.c +++ b/FreeRTOS-Plus/VisualStudio_StaticProjects/FreeRTOS+TCP/plus_tcp_hooks_winsim.c @@ -228,7 +228,7 @@ void vPlatformInitIpStack( void ) xEndPoints[ 0 ].bits.bWantDHCP = pdTRUE; } #endif /* ( ipconfigUSE_DHCP != 0 ) */ - memcpy( ipLOCAL_MAC_ADDRESS, ucMACAddress, sizeof( ucMACAddress ) ); + xResult = FreeRTOS_IPInit_Multi(); #else /* if defined( ipconfigIPv4_BACKWARD_COMPATIBLE ) && ( ipconfigIPv4_BACKWARD_COMPATIBLE == 0 ) */ /* Using the old /single /IPv4 library, or using backward compatible mode of the new /multi library. */ From 98c2b04bbc0eebcd9af22f991fa9f8b64de4b7e6 Mon Sep 17 00:00:00 2001 From: chinglee-iot <61685396+chinglee-iot@users.noreply.github.com> Date: Fri, 16 Aug 2024 16:36:05 +0800 Subject: [PATCH 2/5] Add SMP interrupt wait critical secton on target test (#1181) Add SMP interrupt wait critical secton on target test --- .../interrupt_wait_critical/CMakeLists.txt | 29 ++ .../interrupt_wait_critical_test_runner.c | 75 ++++ .../interrupt_wait_critical.c | 341 ++++++++++++++++++ .../smp/interrupt_wait_critical/test_config.h | 58 +++ 4 files changed, 503 insertions(+) create mode 100644 FreeRTOS/Test/Target/boards/pico/tests/smp/interrupt_wait_critical/CMakeLists.txt create mode 100644 FreeRTOS/Test/Target/boards/pico/tests/smp/interrupt_wait_critical/interrupt_wait_critical_test_runner.c create mode 100644 FreeRTOS/Test/Target/tests/smp/interrupt_wait_critical/interrupt_wait_critical.c create mode 100644 FreeRTOS/Test/Target/tests/smp/interrupt_wait_critical/test_config.h diff --git a/FreeRTOS/Test/Target/boards/pico/tests/smp/interrupt_wait_critical/CMakeLists.txt b/FreeRTOS/Test/Target/boards/pico/tests/smp/interrupt_wait_critical/CMakeLists.txt new file mode 100644 index 00000000000..8a889c53188 --- /dev/null +++ b/FreeRTOS/Test/Target/boards/pico/tests/smp/interrupt_wait_critical/CMakeLists.txt @@ -0,0 +1,29 @@ +cmake_minimum_required(VERSION 3.13) + +set(TEST_INCLUDE_PATHS ${CMAKE_CURRENT_LIST_DIR}/../../../../../tests/smp/interrupt_wait_critical) +set(TEST_SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR}/../../../../../tests/smp/interrupt_wait_critical) + +add_library(interrupt_wait_critical INTERFACE) +target_sources(interrupt_wait_critical INTERFACE + ${BOARD_LIBRARY_DIR}/main.c + ${CMAKE_CURRENT_LIST_DIR}/interrupt_wait_critical_test_runner.c + ${TEST_SOURCE_DIR}/interrupt_wait_critical.c) + +target_include_directories(interrupt_wait_critical INTERFACE + ${CMAKE_CURRENT_LIST_DIR}/../../.. + ${TEST_INCLUDE_PATHS} + ) + +target_link_libraries(interrupt_wait_critical INTERFACE + FreeRTOS-Kernel + FreeRTOS-Kernel-Heap4 + ${BOARD_LINK_LIBRARIES}) + +add_executable(test_interrupt_wait_critical) +enable_board_functions(test_interrupt_wait_critical) +target_link_libraries(test_interrupt_wait_critical interrupt_wait_critical) +target_include_directories(test_interrupt_wait_critical PUBLIC + ${BOARD_INCLUDE_PATHS}) +target_compile_definitions(test_interrupt_wait_critical PRIVATE + ${BOARD_DEFINES} +) diff --git a/FreeRTOS/Test/Target/boards/pico/tests/smp/interrupt_wait_critical/interrupt_wait_critical_test_runner.c b/FreeRTOS/Test/Target/boards/pico/tests/smp/interrupt_wait_critical/interrupt_wait_critical_test_runner.c new file mode 100644 index 00000000000..00dbcbda161 --- /dev/null +++ b/FreeRTOS/Test/Target/boards/pico/tests/smp/interrupt_wait_critical/interrupt_wait_critical_test_runner.c @@ -0,0 +1,75 @@ +/* + * FreeRTOS V202212.00 + * Copyright (C) 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * https://www.FreeRTOS.org + * https://github.com/FreeRTOS + * + */ + +/** + * @file only_one_task_enter_critical_test_runner.c + * @brief The implementation of main function to start test runner task. + * + * Procedure: + * - Initialize environment. + * - Run the test case. + */ + +/* Kernel includes. */ +#include "FreeRTOS.h" +#include "task.h" + +/* Unit testing support functions. */ +#include "unity.h" + +/* Pico includes. */ +#include "pico/multicore.h" +#include "pico/stdlib.h" + +/*-----------------------------------------------------------*/ + +static void prvTestRunnerTask( void * pvParameters ); + +extern void vRunInterruptWaitCriticalTest( void ); + +/*-----------------------------------------------------------*/ + +static void prvTestRunnerTask( void * pvParameters ) +{ + ( void ) pvParameters; + + /* Run test case. */ + vRunInterruptWaitCriticalTest(); + + vTaskDelete( NULL ); +} +/*-----------------------------------------------------------*/ + +void vRunTest( void ) +{ + xTaskCreate( prvTestRunnerTask, + "testRunner", + configMINIMAL_STACK_SIZE, + NULL, + configMAX_PRIORITIES - 1, + NULL ); +} +/*-----------------------------------------------------------*/ diff --git a/FreeRTOS/Test/Target/tests/smp/interrupt_wait_critical/interrupt_wait_critical.c b/FreeRTOS/Test/Target/tests/smp/interrupt_wait_critical/interrupt_wait_critical.c new file mode 100644 index 00000000000..fd0485c57b2 --- /dev/null +++ b/FreeRTOS/Test/Target/tests/smp/interrupt_wait_critical/interrupt_wait_critical.c @@ -0,0 +1,341 @@ +/* + * FreeRTOS V202212.00 + * Copyright (C) 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * https://www.FreeRTOS.org + * https://github.com/FreeRTOS + * + */ + +/** + * @file interrupt_wait_critical.c + * @brief If a task is interrupted while it is waiting to enter a critical + * section, it shall relinquish the core instead of continuing to wait to + * enter the critical section. + * + * Procedure: + * - Create 1 low priority task, T0. + * - Create n - 1 high priority tasks, T1~Tn-1. + * - Create 1 high priority task, Tn. + * - Tasks T1~Tn-1 suspends themselves. + * - Tn enters critical section. + * - T0 attempts to enter critical section and busy waits to enter + * critical section. + * - Tn resumes tasks T1-Tn-1. + * - At this point, tasks T1-Tn are ready and must be running. As a result, T0 + * - must have been interrupted while busy waiting to enter critical section. + * - Tn leaves critical section. + * Expected: + * - T0 must not enter the critical section as it was interrupted while busy + * waiting to enter critical section. + */ + +/* Standard includes. */ +#include + +/* Kernel includes. */ +#include "FreeRTOS.h" +#include "task.h" + +/* Unit testing support functions. */ +#include "unity.h" +/*-----------------------------------------------------------*/ + +/** + * @brief Busy looping count to wait for other cores. + */ +#define TEST_BUSY_LOOPING_COUNT ( 10000U ) + +/** + * @brief Nop operation for busy looping. + */ +#ifdef portNOP + #define TEST_NOP portNOP +#else + #define TEST_NOP() __asm volatile ( "nop" ) +#endif + +/** + * @brief Timeout value to stop test. + */ +#define TEST_TIMEOUT_MS ( 1000 ) +/*-----------------------------------------------------------*/ + +#if ( configNUMBER_OF_CORES < 2 ) + #error This test is for FreeRTOS SMP and therefore, requires at least 2 cores. +#endif /* if ( configNUMBER_OF_CORES < 2 ) */ + +#if ( configRUN_MULTIPLE_PRIORITIES != 1 ) + #error configRUN_MULTIPLE_PRIORITIES must be enabled by including test_config.h in FreeRTOSConfig.h. +#endif /* if ( configRUN_MULTIPLE_PRIORITIES != 1 ) */ + +#if ( configMAX_PRIORITIES <= 3 ) + #error configMAX_PRIORITIES must be larger than 3 to avoid scheduling idle tasks unexpectedly. +#endif /* if ( configMAX_PRIORITIES <= 3 ) */ +/*-----------------------------------------------------------*/ + +/** + * @brief Low priority task function that tries to enter critical section. + */ +static void prvLowPriorityEnterCriticalTask( void * pvParameters ); + +/** + * @brief High priority task function that tries to enter critical section. + */ +static void prvHighPriorityEnterCriticalTask( void * pvParameters ); + +/** + * @brief Function that implements a never blocking FreeRTOS task. + */ +static void prvEverRunningTask( void * pvParameters ); + +/** + * @brief Test case "Interrupt Wait Critical". + */ +void Test_InterruptWaitCritical( void ); +/*-----------------------------------------------------------*/ + +/** + * @brief Handles of the tasks created in this test. + */ +static TaskHandle_t xTaskHandles[ configNUMBER_OF_CORES + 1 ]; + +/** + * @brief A flag to trace if high priority task entered critical section. + */ +static volatile BaseType_t xHighPriorityTaskEnterCriticalSection = pdFALSE; + +/** + * @brief A flag to trace if low priority task entered critical section. + */ +static volatile BaseType_t xLowPriorityTaskEnterCriticalSection = pdFALSE; +/*-----------------------------------------------------------*/ + +static void prvEverRunningTask( void * pvParameters ) +{ + /* Silence warnings about unused parameters. */ + ( void ) pvParameters; + + vTaskSuspend( NULL ); + + for( ; ; ) + { + TEST_NOP(); + } +} +/*-----------------------------------------------------------*/ + +static void prvLowPriorityEnterCriticalTask( void * pvParameters ) +{ + /* Silence warnings about unused parameters. */ + ( void ) pvParameters; + + /* Wait for the high priority task Tn to enter the critical section first. */ + while( xHighPriorityTaskEnterCriticalSection == pdFALSE ) + { + } + + /* The high priority task Tn is inside the critical section. So this low + * priority task must busy wait here to enter critical section. Tn resumes + * tasks T1~Tn-1 from within the critical section. As a result, n tasks + * T1~Tn are ready to run when this task is busy waiting here to enter + * critical section. Since n higher priority tasks are ready, this low + * priority task must be interrupted and relinquish the core. */ + taskENTER_CRITICAL(); + { + /* As this task must relinquish this core instead of entering the + * critical section, this line must not be run. */ + xLowPriorityTaskEnterCriticalSection = pdTRUE; + } + taskEXIT_CRITICAL(); + + for( ; ; ) + { + TEST_NOP(); + } +} +/*-----------------------------------------------------------*/ + +static void prvHighPriorityEnterCriticalTask( void * pvParameters ) +{ + uint32_t i; + eTaskState taskState; + BaseType_t xAllTasksInExpectedState = pdFALSE; + + /* Silence warnings about unused parameters. */ + ( void ) pvParameters; + + /* Check that low priority task T0 is running and high priority tasks + * T1~Tn-1 are suspended. */ + while( xAllTasksInExpectedState == pdFALSE ) + { + /* Check the state of low priority task T0. */ + taskState = eTaskGetState( xTaskHandles[ 0 ] ); + + if( taskState == eRunning ) + { + /* Check the state of high priority tasks T1~Tn-1. */ + for( i = 1; i < configNUMBER_OF_CORES; i++ ) + { + taskState = eTaskGetState( xTaskHandles[ i ] ); + + if( taskState != eSuspended ) + { + break; + } + } + + if( i == configNUMBER_OF_CORES ) + { + xAllTasksInExpectedState = pdTRUE; + } + } + } + + taskENTER_CRITICAL(); + { + xHighPriorityTaskEnterCriticalSection = pdTRUE; + + /* Busy looping here to wait for low priority task. */ + for( i = 0; i < TEST_BUSY_LOOPING_COUNT; i++ ) + { + TEST_NOP(); + } + + /* Resume tasks T1~Tn-1. All the n cores must be occupied by tasks T1~Tn + * as these are higher priority tasks. The low priority task T0 which is + * busy waiting to enter critical section, must be interrupted. */ + for( i = 1; i < configNUMBER_OF_CORES; i++ ) + { + vTaskResume( xTaskHandles[ i ] ); + } + } + taskEXIT_CRITICAL(); + + for( ; ; ) + { + /* Always running, put asm here to avoid optimization by compiler. */ + TEST_NOP(); + } +} +/*-----------------------------------------------------------*/ + +void Test_InterruptWaitCritical( void ) +{ + uint32_t i; + BaseType_t xTaskCreationResult; + + /* Create one task T0 with low priority. */ + xTaskCreationResult = xTaskCreate( prvLowPriorityEnterCriticalTask, + "EnterCSLow", + configMINIMAL_STACK_SIZE, + NULL, + configMAX_PRIORITIES - 3, + &( xTaskHandles[ 0 ] ) ); + + TEST_ASSERT_EQUAL_MESSAGE( pdPASS, xTaskCreationResult, "Task creation failed." ); + + /* Create ( configNUMBER_OF_CORES - 1 ) tasks T1-Tn-1 with high priority. */ + for( i = 1; i < configNUMBER_OF_CORES; i++ ) + { + xTaskCreationResult = xTaskCreate( prvEverRunningTask, + "EverRunning", + configMINIMAL_STACK_SIZE, + NULL, + configMAX_PRIORITIES - 2, + &( xTaskHandles[ i ] ) ); + + TEST_ASSERT_EQUAL_MESSAGE( pdPASS, xTaskCreationResult, "Task creation failed." ); + } + + /* Create one task Tn with high priority. */ + xTaskCreationResult = xTaskCreate( prvHighPriorityEnterCriticalTask, + "EnterCSHigh", + configMINIMAL_STACK_SIZE, + NULL, + configMAX_PRIORITIES - 2, + &( xTaskHandles[ configNUMBER_OF_CORES ] ) ); + + TEST_ASSERT_EQUAL_MESSAGE( pdPASS, xTaskCreationResult, "Task creation failed." ); + + vTaskDelay( pdMS_TO_TICKS( TEST_TIMEOUT_MS ) ); + + /* Verify the high priority task entered the critical section. */ + TEST_ASSERT_EQUAL_MESSAGE( pdTRUE, xHighPriorityTaskEnterCriticalSection, "High priority task not enter the critical section." ); + + /* Verify the low priority task relinquishes the core when it is interrupted + * while waiting to enter a critical section. */ + TEST_ASSERT_EQUAL_MESSAGE( pdFALSE, xLowPriorityTaskEnterCriticalSection, "Low priority task should relinquish the core." ); + + /* Suspend the high priority task Tn and block the test runner. The low + * priority task should be able to enter the critical section now due to a + * core being available. */ + vTaskSuspend( xTaskHandles[ configNUMBER_OF_CORES ] ); + vTaskDelay( pdMS_TO_TICKS( TEST_TIMEOUT_MS ) ); + + /* Verify the low priority task was able to enter the critical section. */ + TEST_ASSERT_EQUAL_MESSAGE( pdTRUE, xLowPriorityTaskEnterCriticalSection, "Low priority task should enter the critical section." ); +} +/*-----------------------------------------------------------*/ + +/* Runs before every test, put init calls here. */ +void setUp( void ) +{ + uint32_t i; + + for( i = 0U; i < ( configNUMBER_OF_CORES + 1 ); i++ ) + { + xTaskHandles[ i ] = NULL; + } + + xHighPriorityTaskEnterCriticalSection = pdFALSE; + xLowPriorityTaskEnterCriticalSection = pdFALSE; +} +/*-----------------------------------------------------------*/ + +/* Runs after every test, put clean-up calls here. */ +void tearDown( void ) +{ + uint32_t i; + + /* Delete all the tasks. */ + for( i = 0; i < ( configNUMBER_OF_CORES + 1 ); i++ ) + { + if( xTaskHandles[ i ] != NULL ) + { + vTaskDelete( xTaskHandles[ i ] ); + xTaskHandles[ i ] = NULL; + } + } +} +/*-----------------------------------------------------------*/ + +/** + * @brief Entry point for test runner to run interrupt task wait critical section test. + */ +void vRunInterruptWaitCriticalTest( void ) +{ + UNITY_BEGIN(); + + RUN_TEST( Test_InterruptWaitCritical ); + + UNITY_END(); +} +/*-----------------------------------------------------------*/ diff --git a/FreeRTOS/Test/Target/tests/smp/interrupt_wait_critical/test_config.h b/FreeRTOS/Test/Target/tests/smp/interrupt_wait_critical/test_config.h new file mode 100644 index 00000000000..150d0f0ba80 --- /dev/null +++ b/FreeRTOS/Test/Target/tests/smp/interrupt_wait_critical/test_config.h @@ -0,0 +1,58 @@ +/* + * FreeRTOS V202212.00 + * Copyright (C) 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * https://www.FreeRTOS.org + * https://github.com/FreeRTOS + * + */ + +#ifndef TEST_CONFIG_H +#define TEST_CONFIG_H + +/* This file must be included at the end of the FreeRTOSConfig.h. It contains + * any FreeRTOS specific configurations that the test requires. */ + +#ifdef configRUN_MULTIPLE_PRIORITIES + #undef configRUN_MULTIPLE_PRIORITIES +#endif /* ifdef configRUN_MULTIPLE_PRIORITIES */ + +#ifdef configUSE_TIME_SLICING + #undef configUSE_TIME_SLICING +#endif /* ifdef configUSE_TIME_SLICING */ + +#ifdef configUSE_PREEMPTION + #undef configUSE_PREEMPTION +#endif /* ifdef configUSE_PREEMPTION */ + +#define configRUN_MULTIPLE_PRIORITIES 1 +#define configUSE_TIME_SLICING 1 +#define configUSE_PREEMPTION 1 + +/*-----------------------------------------------------------*/ + +/** + * @brief Entry point for test runner to run interrupt task wait critical section test. + */ +void vRunInterruptWaitCriticalTest( void ); + +/*-----------------------------------------------------------*/ + +#endif /* ifndef TEST_CONFIG_H */ From 6ed67f54bb085e45427e15925281f4074d2d384f Mon Sep 17 00:00:00 2001 From: chinglee-iot <61685396+chinglee-iot@users.noreply.github.com> Date: Fri, 16 Aug 2024 16:53:22 +0800 Subject: [PATCH 3/5] Add SMP one task enter critical on target test (#1180) Add SMP one task enter critical on target test --- .../CMakeLists.txt | 33 +++ ...only_one_task_enter_critical_test_runner.c | 73 ++++++ .../only_one_task_enter_critical.c | 244 ++++++++++++++++++ .../test_config.h | 58 +++++ 4 files changed, 408 insertions(+) create mode 100644 FreeRTOS/Test/Target/boards/pico/tests/smp/only_one_task_enter_critical/CMakeLists.txt create mode 100644 FreeRTOS/Test/Target/boards/pico/tests/smp/only_one_task_enter_critical/only_one_task_enter_critical_test_runner.c create mode 100644 FreeRTOS/Test/Target/tests/smp/only_one_task_enter_critical/only_one_task_enter_critical.c create mode 100644 FreeRTOS/Test/Target/tests/smp/only_one_task_enter_critical/test_config.h diff --git a/FreeRTOS/Test/Target/boards/pico/tests/smp/only_one_task_enter_critical/CMakeLists.txt b/FreeRTOS/Test/Target/boards/pico/tests/smp/only_one_task_enter_critical/CMakeLists.txt new file mode 100644 index 00000000000..e55e3f262a2 --- /dev/null +++ b/FreeRTOS/Test/Target/boards/pico/tests/smp/only_one_task_enter_critical/CMakeLists.txt @@ -0,0 +1,33 @@ +cmake_minimum_required(VERSION 3.13) + +project(example C CXX ASM) +set(CMAKE_C_STANDARD 11) +set(CMAKE_CXX_STANDARD 17) + +set(TEST_INCLUDE_PATHS ${CMAKE_CURRENT_LIST_DIR}/../../../../../tests/smp/only_one_task_enter_critical) +set(TEST_SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR}/../../../../../tests/smp/only_one_task_enter_critical) + +add_library(only_one_task_enter_critical INTERFACE) +target_sources(only_one_task_enter_critical INTERFACE + ${BOARD_LIBRARY_DIR}/main.c + ${CMAKE_CURRENT_LIST_DIR}/only_one_task_enter_critical_test_runner.c + ${TEST_SOURCE_DIR}/only_one_task_enter_critical.c) + +target_include_directories(only_one_task_enter_critical INTERFACE + ${CMAKE_CURRENT_LIST_DIR}/../../.. + ${TEST_INCLUDE_PATHS} + ) + +target_link_libraries(only_one_task_enter_critical INTERFACE + FreeRTOS-Kernel + FreeRTOS-Kernel-Heap4 + ${BOARD_LINK_LIBRARIES}) + +add_executable(test_only_one_task_enter_critical) +enable_board_functions(test_only_one_task_enter_critical) +target_link_libraries(test_only_one_task_enter_critical only_one_task_enter_critical) +target_include_directories(test_only_one_task_enter_critical PUBLIC + ${BOARD_INCLUDE_PATHS}) +target_compile_definitions(test_only_one_task_enter_critical PRIVATE + ${BOARD_DEFINES} +) diff --git a/FreeRTOS/Test/Target/boards/pico/tests/smp/only_one_task_enter_critical/only_one_task_enter_critical_test_runner.c b/FreeRTOS/Test/Target/boards/pico/tests/smp/only_one_task_enter_critical/only_one_task_enter_critical_test_runner.c new file mode 100644 index 00000000000..32ba8498095 --- /dev/null +++ b/FreeRTOS/Test/Target/boards/pico/tests/smp/only_one_task_enter_critical/only_one_task_enter_critical_test_runner.c @@ -0,0 +1,73 @@ +/* + * FreeRTOS V202212.00 + * Copyright (C) 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * https://www.FreeRTOS.org + * https://github.com/FreeRTOS + * + */ + +/** + * @file only_one_task_enter_critical_test_runner.c + * @brief The implementation of main function to start test runner task. + * + * Procedure: + * - Initialize environment. + * - Run the test case. + */ + +/* Kernel includes. */ +#include "FreeRTOS.h" +#include "task.h" + +/* Unit testing support functions. */ +#include "unity.h" + +/* Pico includes. */ +#include "pico/multicore.h" +#include "pico/stdlib.h" + +/*-----------------------------------------------------------*/ + +static void prvTestRunnerTask( void * pvParameters ); + +/*-----------------------------------------------------------*/ + +static void prvTestRunnerTask( void * pvParameters ) +{ + ( void ) pvParameters; + + /* Run test case. */ + vRunOnlyOneTaskEnterCriticalTest(); + + vTaskDelete( NULL ); +} +/*-----------------------------------------------------------*/ + +void vRunTest( void ) +{ + xTaskCreate( prvTestRunnerTask, + "testRunner", + configMINIMAL_STACK_SIZE, + NULL, + configMAX_PRIORITIES - 1, + NULL ); +} +/*-----------------------------------------------------------*/ diff --git a/FreeRTOS/Test/Target/tests/smp/only_one_task_enter_critical/only_one_task_enter_critical.c b/FreeRTOS/Test/Target/tests/smp/only_one_task_enter_critical/only_one_task_enter_critical.c new file mode 100644 index 00000000000..f789312aefd --- /dev/null +++ b/FreeRTOS/Test/Target/tests/smp/only_one_task_enter_critical/only_one_task_enter_critical.c @@ -0,0 +1,244 @@ +/* + * FreeRTOS V202212.00 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * https://www.FreeRTOS.org + * https://github.com/FreeRTOS + * + */ + +/** + * @file only_one_task_enter_critical.c + * @brief Only one task/ISR shall be able to enter critical section at a time. + * + * Procedure: + * - Create ( num of cores ) tasks. + * - All tasks increase the counter for TASK_INCREASE_COUNTER_TIMES times in + * critical section. + * Expected: + * - All tasks have correct value of counter after increasing. + */ + +/* Standard includes. */ +#include + +/* Kernel includes. */ +#include "FreeRTOS.h" +#include "task.h" + +/* Unit testing support functions. */ +#include "unity.h" +/*-----------------------------------------------------------*/ + +/** + * @brief As time of loop for task to increase counter. + */ +#define TASK_INCREASE_COUNTER_TIMES ( 1000000 ) + +/** + * @brief Timeout value to stop test. + */ +#define TEST_TIMEOUT_MS ( 1000 ) +/*-----------------------------------------------------------*/ + +/** + * @brief Test case "Only One Task Enter Critical". + */ +void Test_OnlyOneTaskEnterCritical( void ); + +/** + * @brief Task function to increase counter then keep delaying. + */ +static void prvTaskIncCounter( void * pvParameters ); +/*-----------------------------------------------------------*/ + +#if ( configNUMBER_OF_CORES < 2 ) + #error This test is for FreeRTOS SMP and therefore, requires at least 2 cores. +#endif /* if ( configNUMBER_OF_CORES < 2 ) */ + +#if ( configMAX_PRIORITIES <= 2 ) + #error configMAX_PRIORITIES must be larger than 2 to avoid scheduling idle tasks unexpectedly. +#endif /* if ( configMAX_PRIORITIES <= 2 ) */ +/*-----------------------------------------------------------*/ + +/** + * @brief Handles of the tasks created in this test. + */ +static TaskHandle_t xTaskHandles[ configNUMBER_OF_CORES ]; + +/** + * @brief Indexes of the tasks created in this test. + */ +static uint32_t xTaskIndexes[ configNUMBER_OF_CORES ]; + +/** + * @brief Flags to indicate if task T0 ~ T(n - 1) finish or not. + */ +static BaseType_t xTaskTestResults[ configNUMBER_OF_CORES ]; + +/** + * @brief Variables to indicate task is ready for testing. + */ +static volatile BaseType_t xTaskReady[ configNUMBER_OF_CORES ]; + +/** + * @brief Counter for all tasks to increase. + */ +static volatile uint32_t xTaskCounter; +/*-----------------------------------------------------------*/ + +static void prvTaskIncCounter( void * pvParameters ) +{ + uint32_t currentTaskIdx = *( ( uint32_t * ) pvParameters ); + BaseType_t xAllTaskReady = pdFALSE; + BaseType_t xTestResult = pdPASS; + uint32_t xTempTaskCounter = 0; + uint32_t i; + + /* Ensure all test tasks are running in the task function. */ + xTaskReady[ currentTaskIdx ] = pdTRUE; + + while( xAllTaskReady == pdFALSE ) + { + xAllTaskReady = pdTRUE; + + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + if( xTaskReady[ i ] != pdTRUE ) + { + xAllTaskReady = pdFALSE; + break; + } + } + } + + /* Increase the test counter in the loop. The test expects only one task + * can increase the shared variable xTaskCounter protected by the critical + * section at the same time. */ + taskENTER_CRITICAL(); + { + xTempTaskCounter = xTaskCounter; + + for( i = 0; i < TASK_INCREASE_COUNTER_TIMES; i++ ) + { + /* Increase the local variable xTempTaskCounter and shared variable + * xTaskCounter. They must have the same value in the critical + * section. */ + xTaskCounter++; + xTempTaskCounter++; + + /* If multiple tasks enter the critical section, the shared variable + * xTaskCounter will be increased by multiple tasks.As a result, the + * local variable xTempTaskCounter won't be equal to the shared + * variable xTaskCounter. */ + if( xTaskCounter != xTempTaskCounter ) + { + xTestResult = pdFAIL; + break; + } + } + } + taskEXIT_CRITICAL(); + + xTaskTestResults[ currentTaskIdx ] = xTestResult; + + /* Blocking the test task. */ + vTaskDelay( portMAX_DELAY ); +} +/*-----------------------------------------------------------*/ + +void Test_OnlyOneTaskEnterCritical( void ) +{ + uint32_t i; + BaseType_t xTaskCreationResult; + + /* Create configNUMBER_OF_CORES low priority tasks. */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + xTaskCreationResult = xTaskCreate( prvTaskIncCounter, + "IncCounter", + configMINIMAL_STACK_SIZE, + &( xTaskIndexes[ i ] ), + configMAX_PRIORITIES - 2, + &( xTaskHandles[ i ] ) ); + + TEST_ASSERT_EQUAL_MESSAGE( pdPASS, xTaskCreationResult, "Task creation failed." ); + } + + /* Delay for other cores to run tasks. */ + vTaskDelay( pdMS_TO_TICKS( TEST_TIMEOUT_MS ) ); + + /* Verify each test task result. */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + TEST_ASSERT_EQUAL_MESSAGE( pdPASS, xTaskTestResults[ i ], "Critical section test task failed." ); + } + + /* Verify the shared variable counter value. */ + TEST_ASSERT_EQUAL_UINT32( configNUMBER_OF_CORES * TASK_INCREASE_COUNTER_TIMES, xTaskCounter ); +} +/*-----------------------------------------------------------*/ + +/* Runs before every test, put init calls here. */ +void setUp( void ) +{ + uint32_t i; + + xTaskCounter = 0; + + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + xTaskIndexes[ i ] = i; + xTaskHandles[ i ] = NULL; + xTaskTestResults[ i ] = pdFALSE; + xTaskReady[ i ] = pdFALSE; + } +} +/*-----------------------------------------------------------*/ + +/* Runs after every test, put clean-up calls here. */ +void tearDown( void ) +{ + uint32_t i; + + /* Delete all the tasks. */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + if( xTaskHandles[ i ] != NULL ) + { + vTaskDelete( xTaskHandles[ i ] ); + xTaskHandles[ i ] = NULL; + } + } +} +/*-----------------------------------------------------------*/ + +/** + * @brief Entry point for test runner to run critical section test. + */ +void vRunOnlyOneTaskEnterCriticalTest( void ) +{ + UNITY_BEGIN(); + + RUN_TEST( Test_OnlyOneTaskEnterCritical ); + + UNITY_END(); +} +/*-----------------------------------------------------------*/ diff --git a/FreeRTOS/Test/Target/tests/smp/only_one_task_enter_critical/test_config.h b/FreeRTOS/Test/Target/tests/smp/only_one_task_enter_critical/test_config.h new file mode 100644 index 00000000000..c35b26e5181 --- /dev/null +++ b/FreeRTOS/Test/Target/tests/smp/only_one_task_enter_critical/test_config.h @@ -0,0 +1,58 @@ +/* + * FreeRTOS V202212.00 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * https://www.FreeRTOS.org + * https://github.com/FreeRTOS + * + */ + +#ifndef TEST_CONFIG_H +#define TEST_CONFIG_H + +/* This file must be included at the end of the FreeRTOSConfig.h. It contains + * any FreeRTOS specific configurations that the test requires. */ + +#ifdef configRUN_MULTIPLE_PRIORITIES + #undef configRUN_MULTIPLE_PRIORITIES +#endif /* ifdef configRUN_MULTIPLE_PRIORITIES */ + +#ifdef configUSE_TIME_SLICING + #undef configUSE_TIME_SLICING +#endif /* ifdef configUSE_TIME_SLICING */ + +#ifdef configUSE_PREEMPTION + #undef configUSE_PREEMPTION +#endif /* ifdef configUSE_PREEMPTION */ + +#define configRUN_MULTIPLE_PRIORITIES 1 +#define configUSE_TIME_SLICING 1 +#define configUSE_PREEMPTION 1 + +/*-----------------------------------------------------------*/ + +/** + * @brief Entry point for test runner to run critical section test. + */ +void vRunOnlyOneTaskEnterCriticalTest( void ); + +/*-----------------------------------------------------------*/ + +#endif /* ifndef TEST_CONFIG_H */ From 520fc225eb2dd5e21c951ca325e1c51eed3a5c13 Mon Sep 17 00:00:00 2001 From: chinglee-iot <61685396+chinglee-iot@users.noreply.github.com> Date: Fri, 16 Aug 2024 17:08:01 +0800 Subject: [PATCH 4/5] Add SMP task delete on target test (#1176) Add SMP task delete on target test --- .../pico/tests/smp/task_delete/CMakeLists.txt | 33 +++ .../smp/task_delete/task_delete_test_runner.c | 73 +++++ .../tests/smp/task_delete/task_delete.c | 260 ++++++++++++++++++ .../tests/smp/task_delete/test_config.h | 58 ++++ 4 files changed, 424 insertions(+) create mode 100644 FreeRTOS/Test/Target/boards/pico/tests/smp/task_delete/CMakeLists.txt create mode 100644 FreeRTOS/Test/Target/boards/pico/tests/smp/task_delete/task_delete_test_runner.c create mode 100644 FreeRTOS/Test/Target/tests/smp/task_delete/task_delete.c create mode 100644 FreeRTOS/Test/Target/tests/smp/task_delete/test_config.h diff --git a/FreeRTOS/Test/Target/boards/pico/tests/smp/task_delete/CMakeLists.txt b/FreeRTOS/Test/Target/boards/pico/tests/smp/task_delete/CMakeLists.txt new file mode 100644 index 00000000000..1f1daadadb8 --- /dev/null +++ b/FreeRTOS/Test/Target/boards/pico/tests/smp/task_delete/CMakeLists.txt @@ -0,0 +1,33 @@ +cmake_minimum_required(VERSION 3.13) + +project(example C CXX ASM) +set(CMAKE_C_STANDARD 11) +set(CMAKE_CXX_STANDARD 17) + +set(TEST_INCLUDE_PATHS ${CMAKE_CURRENT_LIST_DIR}/../../../../../tests/smp/task_delete) +set(TEST_SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR}/../../../../../tests/smp/task_delete) + +add_library(task_delete INTERFACE) +target_sources(task_delete INTERFACE + ${BOARD_LIBRARY_DIR}/main.c + ${CMAKE_CURRENT_LIST_DIR}/task_delete_test_runner.c + ${TEST_SOURCE_DIR}/task_delete.c) + +target_include_directories(task_delete INTERFACE + ${CMAKE_CURRENT_LIST_DIR}/../../.. + ${TEST_INCLUDE_PATHS} + ) + +target_link_libraries(task_delete INTERFACE + FreeRTOS-Kernel + FreeRTOS-Kernel-Heap4 + ${BOARD_LINK_LIBRARIES}) + +add_executable(test_task_delete) +enable_board_functions(test_task_delete) +target_link_libraries(test_task_delete task_delete) +target_include_directories(test_task_delete PUBLIC + ${BOARD_INCLUDE_PATHS}) +target_compile_definitions(test_task_delete PRIVATE + ${BOARD_DEFINES} +) diff --git a/FreeRTOS/Test/Target/boards/pico/tests/smp/task_delete/task_delete_test_runner.c b/FreeRTOS/Test/Target/boards/pico/tests/smp/task_delete/task_delete_test_runner.c new file mode 100644 index 00000000000..047260822d4 --- /dev/null +++ b/FreeRTOS/Test/Target/boards/pico/tests/smp/task_delete/task_delete_test_runner.c @@ -0,0 +1,73 @@ +/* + * FreeRTOS V202212.00 + * Copyright (C) 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * https://www.FreeRTOS.org + * https://github.com/FreeRTOS + * + */ + +/** + * @file task_delete_test_runner.c + * @brief The implementation of main function to start test runner task. + * + * Procedure: + * - Initialize environment. + * - Run the test case. + */ + +/* Kernel includes. */ +#include "FreeRTOS.h" +#include "task.h" + +/* Unit testing support functions. */ +#include "unity.h" + +/* Pico includes. */ +#include "pico/multicore.h" +#include "pico/stdlib.h" + +/*-----------------------------------------------------------*/ + +static void prvTestRunnerTask( void * pvParameters ); + +/*-----------------------------------------------------------*/ + +static void prvTestRunnerTask( void * pvParameters ) +{ + ( void ) pvParameters; + + /* Run test case. */ + vRunTaskDeleteTest(); + + vTaskDelete( NULL ); +} +/*-----------------------------------------------------------*/ + +void vRunTest( void ) +{ + xTaskCreate( prvTestRunnerTask, + "testRunner", + configMINIMAL_STACK_SIZE, + NULL, + configMAX_PRIORITIES - 1, + NULL ); +} +/*-----------------------------------------------------------*/ diff --git a/FreeRTOS/Test/Target/tests/smp/task_delete/task_delete.c b/FreeRTOS/Test/Target/tests/smp/task_delete/task_delete.c new file mode 100644 index 00000000000..a7cf587d58e --- /dev/null +++ b/FreeRTOS/Test/Target/tests/smp/task_delete/task_delete.c @@ -0,0 +1,260 @@ +/* + * FreeRTOS V202212.00 + * Copyright (C) 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * https://www.FreeRTOS.org + * https://github.com/FreeRTOS + * + */ + +/** + * @file tasks_delete.c + * @brief When a n RTOS object is deleted, the associated resources shall be freed. + * + * Procedure: + * - TestRunner records original memory size. + * - Create ( num of cores ) tasks T0 ~ T(n - 1). + * - Tasks T0 ~ T(n - 1) delete themselves. + * - TestRunner checks if memory is freed. + * - Create ( num of cores ) tasks T0 ~ T(n - 1). + * - Task T0 ~ T(n - 1) delay in loop. + * - TestRunner deletes T0 ~ T(n - 1). + * - TestRunner checks if memory freed. + * Expected: + * - Have same remaining memory before creating task and after deleting task. + */ + +/* Standard includes. */ +#include + +/* Kernel includes. */ +#include "FreeRTOS.h" +#include "task.h" + +/* Unit testing support functions. */ +#include "unity.h" + +/*-----------------------------------------------------------*/ + +/** + * @brief Timeout value to stop test. + */ +#define TEST_TIMEOUT_MS ( 1000 ) + +/*-----------------------------------------------------------*/ + +#if ( configNUMBER_OF_CORES < 2 ) + #error This test is for FreeRTOS SMP and therefore, requires at least 2 cores. +#endif /* if ( configNUMBER_OF_CORES < 2 ) */ + +#if ( configMAX_PRIORITIES <= 2 ) + #error configMAX_PRIORITIES must be larger than 2 to avoid scheduling idle tasks unexpectedly. +#endif /* if ( configMAX_PRIORITIES <= 2 ) */ + +/*-----------------------------------------------------------*/ + +/** + * @brief Test case "Task Delete". + */ +void Test_TaskDelete( void ); + +/** + * @brief Partial test case in "Task Delete" for "Self deletion". + */ +static void prvTestTaskSelfDelete( void ); + +/** + * @brief Partial test case in "Task Delete" for "Remote deletion". + */ +static void prvTestTaskRemoteDelete( void ); + +/** + * @brief Task entry to delete itself. + */ +static void prvSelfDeleteTask( void * pvParameters ); + +/** + * @brief Task entry to loop in delay. + */ +static void prvDelayTask( void * pvParameters ); +/*-----------------------------------------------------------*/ + +/** + * @brief Handles of the tasks created in this test. + */ +static TaskHandle_t xTaskHandles[ configNUMBER_OF_CORES ]; + +/** + * @brief Flag to indicate task run status. + */ +static BaseType_t xTaskRunStatus[ configNUMBER_OF_CORES ]; + +/** + * @brief The heap size before creating tasks T0 ~ T(n - 1). + */ +static uint32_t ulOriginalFreeHeapSize; +/*-----------------------------------------------------------*/ + +static void prvSelfDeleteTask( void * pvParameters ) +{ + BaseType_t * pxTaskRunStatus = ( BaseType_t * ) pvParameters; + + /* Set the flag to indicate the task has run. */ + *pxTaskRunStatus = pdTRUE; + + vTaskDelete( NULL ); + + /* The task delete itself. This line should not be run. */ + *pxTaskRunStatus = pdFALSE; +} +/*-----------------------------------------------------------*/ + +static void prvDelayTask( void * pvParameters ) +{ + BaseType_t * pxTaskRunStatus = ( BaseType_t * ) pvParameters; + + /* Set the flag to indicate the task has run. */ + *pxTaskRunStatus = pdTRUE; + + /* Block this task forever. */ + vTaskDelay( portMAX_DELAY ); +} +/*-----------------------------------------------------------*/ + +static void prvTestTaskSelfDelete( void ) +{ + uint32_t i; + BaseType_t xTaskCreationResult; + uint32_t ulFreeHeapSize; + + /* Create configNUMBER_OF_CORES low priority tasks. */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + xTaskRunStatus[ i ] = pdFALSE; + xTaskCreationResult = xTaskCreate( prvSelfDeleteTask, + "SelfDel", + configMINIMAL_STACK_SIZE, + ( void * ) ( &( xTaskRunStatus[ i ] ) ), + configMAX_PRIORITIES - 2, + &( xTaskHandles[ i ] ) ); + + TEST_ASSERT_EQUAL_MESSAGE( pdPASS, xTaskCreationResult, "Task creation failed." ); + } + + /* Wait task to delete itself. */ + vTaskDelay( pdMS_TO_TICKS( TEST_TIMEOUT_MS ) ); + + /* Verify the task run status. */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + TEST_ASSERT_EQUAL_MESSAGE( pdTRUE, xTaskRunStatus[ i ], "Task hasn't been run." ); + xTaskHandles[ i ] = NULL; + } + + /* Verify the memory used for task TCB and stack is freed. */ + ulFreeHeapSize = xPortGetFreeHeapSize(); + TEST_ASSERT_EQUAL_INT_MESSAGE( ulOriginalFreeHeapSize, ulFreeHeapSize, "Self deleted task test failed." ); +} +/*-----------------------------------------------------------*/ + +static void prvTestTaskRemoteDelete( void ) +{ + uint32_t i; + BaseType_t xTaskCreationResult; + uint32_t ulFreeHeapSize; + + /* Create configNUMBER_OF_CORES low priority tasks. */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + xTaskRunStatus[ i ] = pdFALSE; + xTaskCreationResult = xTaskCreate( prvDelayTask, + "KeepDelay", + configMINIMAL_STACK_SIZE, + ( void * ) ( &( xTaskRunStatus[ i ] ) ), + configMAX_PRIORITIES - 2, + &( xTaskHandles[ i ] ) ); + + TEST_ASSERT_EQUAL_MESSAGE( pdPASS, xTaskCreationResult, "Task creation failed." ); + } + + /* Delay a while for tasks just created to run. */ + vTaskDelay( pdMS_TO_TICKS( TEST_TIMEOUT_MS ) ); + + /* Verify the task run status. */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + TEST_ASSERT_EQUAL_MESSAGE( pdTRUE, xTaskRunStatus[ i ], "Task hasn't been run." ); + } + + /* Delete tasks remotely. */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + vTaskDelete( xTaskHandles[ i ] ); + xTaskHandles[ i ] = NULL; + } + + ulFreeHeapSize = xPortGetFreeHeapSize(); + TEST_ASSERT_EQUAL_INT_MESSAGE( ulOriginalFreeHeapSize, ulFreeHeapSize, "Remote deleted task test failed." ); +} +/*-----------------------------------------------------------*/ + +void Test_TaskDelete( void ) +{ + prvTestTaskSelfDelete(); + prvTestTaskRemoteDelete(); +} +/*-----------------------------------------------------------*/ + +/* Runs before every test, put init calls here. */ +void setUp( void ) +{ + /* Get the heap size before creating tasks. */ + ulOriginalFreeHeapSize = xPortGetFreeHeapSize(); +} +/*-----------------------------------------------------------*/ + +/* Runs after every test, put clean-up calls here. */ +void tearDown( void ) +{ + uint32_t i; + + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + if( xTaskHandles[ i ] != NULL ) + { + vTaskDelete( xTaskHandles[ i ] ); + xTaskHandles[ i ] = NULL; + } + } +} +/*-----------------------------------------------------------*/ + +/** + * @brief Entry point for test runner to task delete test. + */ +void vRunTaskDeleteTest( void ) +{ + UNITY_BEGIN(); + + RUN_TEST( Test_TaskDelete ); + + UNITY_END(); +} +/*-----------------------------------------------------------*/ diff --git a/FreeRTOS/Test/Target/tests/smp/task_delete/test_config.h b/FreeRTOS/Test/Target/tests/smp/task_delete/test_config.h new file mode 100644 index 00000000000..dba5cfa453b --- /dev/null +++ b/FreeRTOS/Test/Target/tests/smp/task_delete/test_config.h @@ -0,0 +1,58 @@ +/* + * FreeRTOS V202212.00 + * Copyright (C) 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * https://www.FreeRTOS.org + * https://github.com/FreeRTOS + * + */ + +#ifndef TEST_CONFIG_H +#define TEST_CONFIG_H + +/* This file must be included at the end of the FreeRTOSConfig.h. It contains + * any FreeRTOS specific configurations that the test requires. */ + +#ifdef configRUN_MULTIPLE_PRIORITIES + #undef configRUN_MULTIPLE_PRIORITIES +#endif /* ifdef configRUN_MULTIPLE_PRIORITIES */ + +#ifdef configUSE_TIME_SLICING + #undef configUSE_TIME_SLICING +#endif /* ifdef configUSE_TIME_SLICING */ + +#ifdef configUSE_PREEMPTION + #undef configUSE_PREEMPTION +#endif /* ifdef configUSE_PREEMPTION */ + +#define configRUN_MULTIPLE_PRIORITIES 1 +#define configUSE_TIME_SLICING 1 +#define configUSE_PREEMPTION 1 + +/*-----------------------------------------------------------*/ + +/** + * @brief A start entry for test runner to task delete test. + */ +void vRunTaskDeleteTest( void ); + +/*-----------------------------------------------------------*/ + +#endif /* ifndef TEST_CONFIG_H */ From 4b039b82e9bb5ba34304f5345f3d7ba25be882ba Mon Sep 17 00:00:00 2001 From: chinglee-iot <61685396+chinglee-iot@users.noreply.github.com> Date: Tue, 20 Aug 2024 12:23:21 +0800 Subject: [PATCH 5/5] Remove no new core added coverage test for coreAffinitySet (#1248) * Remove this unit test due to implementation change --- ...g_multiple_priorities_no_timeslice_utest.c | 56 ------------------- 1 file changed, 56 deletions(-) diff --git a/FreeRTOS/Test/CMock/smp/multiple_priorities_no_timeslice/covg_multiple_priorities_no_timeslice_utest.c b/FreeRTOS/Test/CMock/smp/multiple_priorities_no_timeslice/covg_multiple_priorities_no_timeslice_utest.c index 0d96dba8d0e..f7858c0ac14 100644 --- a/FreeRTOS/Test/CMock/smp/multiple_priorities_no_timeslice/covg_multiple_priorities_no_timeslice_utest.c +++ b/FreeRTOS/Test/CMock/smp/multiple_priorities_no_timeslice/covg_multiple_priorities_no_timeslice_utest.c @@ -1337,62 +1337,6 @@ void test_coverage_vTaskCoreAffinitySet_null_task_handle( void ) TEST_ASSERT_EQUAL( pdTRUE, xYieldPendings[ 0 ] ); } -/** - * @brief vTaskCoreAffinitySet - no new core for task which is not running. - * - * Set core mask for a not running task. The new core mask doesn't enable the task - * to run on any new core. Verify the core mask set is correct. - * - * Coverage - * @code{c} - * if( taskTASK_IS_RUNNING( pxTCB ) == pdTRUE ) - * { - * ... - * } - * else - * { - * if( ( uxPrevNotAllowedCores & uxCoreAffinityMask ) != 0U ) - * { - * prvYieldForTask( pxTCB ); - * } - * } - * @endcode - * ( taskTASK_IS_RUNNING( pxTCB ) == pdTRUE ) is false. - * ( ( uxPrevNotAllowedCores & uxCoreAffinityMask ) != 0U ) is false. - */ -void test_coverage_vTaskCoreAffinitySet_task_not_running_no_new_core( void ) -{ - TCB_t xTaskTCB = { NULL }; - UBaseType_t uxCoreAffinityMask; - UBaseType_t uxNewCoreAffinityMask; - - /* Setup the variables and structure. */ - /* This task is allowed to run on core 0 and core 1 only. */ - uxCoreAffinityMask = ( 1U << 0 ) | ( 1U << 1 ); - vCreateStaticTestTaskAffinity( &xTaskTCB, - uxCoreAffinityMask, - tskIDLE_PRIORITY, - configNUMBER_OF_CORES, - pdFALSE ); - xSchedulerRunning = pdTRUE; - - /* Expectations. */ - vFakePortEnterCriticalSection_StubWithCallback( NULL ); - vFakePortExitCriticalSection_StubWithCallback( NULL ); - vFakePortCheckIfInISR_StopIgnore(); - - vFakePortEnterCriticalSection_Expect(); - vFakePortExitCriticalSection_Expect(); - - /* API call. */ - /* No new core is enabled for this task. */ - uxNewCoreAffinityMask = ( 1U << 0 ); - vTaskCoreAffinitySet( &xTaskTCB, uxNewCoreAffinityMask ); - - /* Validations. */ - TEST_ASSERT_EQUAL( uxNewCoreAffinityMask, xTaskTCB.uxCoreAffinityMask ); -} - /** * @brief prvYieldForTask - running task with xTaskRunState equals to configNUMBER_OF_CORES. *