| 
									
										
										
										
											2017-11-23 22:35:54 +08:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * Test backported deletion behavior by creating tasks of various affinities and | 
					
						
							|  |  |  |  * check if the task memory is freed immediately under the correct conditions. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * The behavior of vTaskDelete() has been backported form FreeRTOS v9.0.0. This | 
					
						
							|  |  |  |  * results in the immediate freeing of task memory and the immediate execution | 
					
						
							|  |  |  |  * of deletion callbacks under the following conditions... | 
					
						
							|  |  |  |  * - When deleting a task that is not currently running on either core | 
					
						
							|  |  |  |  * - When deleting a task that is pinned to the same core (with respect to | 
					
						
							|  |  |  |  *   the core that calls vTaskDelete() | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * If the two conditions are not met, freeing of task memory and execution of | 
					
						
							|  |  |  |  * deletion callbacks will still be carried out by the Idle Task. | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2016-11-17 16:36:10 +08:00
										 |  |  | #include <stdio.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "freertos/FreeRTOS.h"
 | 
					
						
							|  |  |  | #include "freertos/task.h"
 | 
					
						
							| 
									
										
										
										
											2017-11-23 22:35:54 +08:00
										 |  |  | #include "esp_heap_caps.h"
 | 
					
						
							| 
									
										
										
										
											2019-03-14 17:29:32 +08:00
										 |  |  | #include "esp32/rom/ets_sys.h"
 | 
					
						
							| 
									
										
										
										
											2017-11-23 22:35:54 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-11-17 16:36:10 +08:00
										 |  |  | #include "unity.h"
 | 
					
						
							| 
									
										
										
										
											2018-10-25 12:52:32 +08:00
										 |  |  | #include "test_utils.h"
 | 
					
						
							| 
									
										
										
										
											2016-11-17 16:36:10 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-23 22:35:54 +08:00
										 |  |  | #define NO_OF_TSKS  3
 | 
					
						
							|  |  |  | #define DELAY_TICKS 2
 | 
					
						
							| 
									
										
										
										
											2018-08-20 16:11:35 +10:00
										 |  |  | /* Caps of all memory which is allocated from when a task is created */ | 
					
						
							|  |  |  | #define HEAP_CAPS   (portTcbMemoryCaps | portStackMemoryCaps)
 | 
					
						
							| 
									
										
										
										
											2017-11-23 22:35:54 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-18 21:58:15 +08:00
										 |  |  | #define DELAY_US_ITERATIONS	1000
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-23 22:35:54 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | static void tsk_self_del(void *param) | 
					
						
							| 
									
										
										
										
											2016-11-17 16:36:10 +08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2017-11-23 22:35:54 +08:00
										 |  |  |     vTaskDelete(NULL);  //Deleting self means deleting currently running task
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void tsk_extern_del(void *param) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     vTaskDelay(portMAX_DELAY);  //Await external deletion
 | 
					
						
							| 
									
										
										
										
											2016-11-17 16:36:10 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-18 21:58:15 +08:00
										 |  |  | static void tsk_self_del_us_delay(void *param) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     uint32_t delay = (uint32_t)param; | 
					
						
							|  |  |  |     ets_delay_us(delay); | 
					
						
							|  |  |  |     vTaskDelete(NULL); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-28 15:31:40 +11:00
										 |  |  | TEST_CASE("FreeRTOS Delete Tasks", "[freertos]") | 
					
						
							| 
									
										
										
										
											2016-11-17 16:36:10 +08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2017-11-23 22:35:54 +08:00
										 |  |  | /* -------------- Test vTaskDelete() on currently running tasks ----------------*/ | 
					
						
							| 
									
										
										
										
											2017-02-28 15:31:40 +11:00
										 |  |  |     uint32_t before_count = uxTaskGetNumberOfTasks(); | 
					
						
							| 
									
										
										
										
											2017-11-23 22:35:54 +08:00
										 |  |  |     uint32_t before_heap = heap_caps_get_free_size(HEAP_CAPS); | 
					
						
							|  |  |  |     for(int i = 0; i < portNUM_PROCESSORS; i++){ | 
					
						
							|  |  |  |         for(int j = 0; j < NO_OF_TSKS; j++){ | 
					
						
							|  |  |  |             TEST_ASSERT_EQUAL(pdTRUE, xTaskCreatePinnedToCore(tsk_self_del, "tsk_self", 1024, NULL, configMAX_PRIORITIES - 1, NULL, i)); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     vTaskDelay(DELAY_TICKS);    //Minimal delay to see if Idle task cleans up all tasks awaiting deletion in a single tick
 | 
					
						
							| 
									
										
										
										
											2017-02-28 15:31:40 +11:00
										 |  |  |     TEST_ASSERT_EQUAL(before_count, uxTaskGetNumberOfTasks()); | 
					
						
							| 
									
										
										
										
											2017-11-23 22:35:54 +08:00
										 |  |  |     TEST_ASSERT_EQUAL(before_heap, heap_caps_get_free_size(HEAP_CAPS)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* ------------- Test vTaskDelete() on not currently running tasks ------------ */ | 
					
						
							|  |  |  |     TaskHandle_t handles[NO_OF_TSKS]; | 
					
						
							|  |  |  |     before_heap = heap_caps_get_free_size(HEAP_CAPS); | 
					
						
							|  |  |  |     //Create task pinned to the same core that will not run during task deletion
 | 
					
						
							|  |  |  |     for(int j = 0 ; j < NO_OF_TSKS; j++){ | 
					
						
							|  |  |  |         TEST_ASSERT_EQUAL(pdTRUE, xTaskCreatePinnedToCore(tsk_extern_del, "tsk_extern", 4096, NULL, configMAX_PRIORITIES - 1, &handles[j], xPortGetCoreID())); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     TEST_ASSERT_NOT_EQUAL(before_heap, heap_caps_get_free_size(HEAP_CAPS));    //Check tasks have been created
 | 
					
						
							|  |  |  |     //Delete the tasks, memory should be freed immediately
 | 
					
						
							|  |  |  |     for(int j = 0; j < NO_OF_TSKS; j++){ | 
					
						
							|  |  |  |         vTaskDelete(handles[j]); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     TEST_ASSERT_EQUAL(before_heap, heap_caps_get_free_size(HEAP_CAPS)); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-18 21:58:15 +08:00
										 |  |  | /* Test self deleting no affinity task is not removed by idle task of other core before context switch */ | 
					
						
							|  |  |  |     for(int i = 0; i < DELAY_US_ITERATIONS; i+= 10){ | 
					
						
							|  |  |  |         vTaskDelay(1);                          //Sync to next tick interrupt
 | 
					
						
							|  |  |  |         xTaskCreatePinnedToCore(tsk_self_del_us_delay, "delay", 1024, (void *)i, UNITY_FREERTOS_PRIORITY - 1, NULL, tskNO_AFFINITY); | 
					
						
							|  |  |  |         ets_delay_us(10);                       //Busy wait to ensure no affinity task runs on opposite core
 | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-11-17 16:36:10 +08:00
										 |  |  | } |