1 /*
2  Test for FreeRTOS vTaskDelayUntil() function by comparing the delay period of
3  the function to comparing it to ref clock.
4 */
5 
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include "freertos/FreeRTOS.h"
9 #include "freertos/task.h"
10 #include "freertos/semphr.h"
11 #include "unity.h"
12 #include "test_utils.h"
13 
14 #define TSK_PRIORITY    (UNITY_FREERTOS_PRIORITY + 1)
15 
16 #define NO_OF_CYCLES    5
17 #define NO_OF_TASKS_PER_CORE 2
18 #define TICKS_TO_DELAY 10
19 #define TICK_RATE   configTICK_RATE_HZ
20 #define TICK_PERIOD_US (1000000/TICK_RATE)
21 #define IDEAL_DELAY_PERIOD_MS  ((1000*TICKS_TO_DELAY)/TICK_RATE)
22 #define IDEAL_DELAY_PERIOD_US   (IDEAL_DELAY_PERIOD_MS*1000)
23 
24 #define TICKS_TO_MS(x)  (((x)*1000)/TICK_RATE)
25 #define REF_TO_ROUND_MS(x)    (((x)+500)/1000)
26 
27 static SemaphoreHandle_t task_delete_semphr;
28 
delaying_task(void * arg)29 static void delaying_task(void* arg)
30 {
31     uint64_t ref_prev, ref_current;
32     TickType_t last_wake_time;
33     TickType_t ticks_before_delay;
34 
35     vTaskDelay(1);  //Delay until next tick to synchronize operations to tick boundaries
36 
37     last_wake_time = xTaskGetTickCount();
38     ticks_before_delay = last_wake_time;
39     ref_prev = ref_clock_get();
40 
41     for(int i = 0; i < NO_OF_CYCLES; i++){
42         //Delay of TICKS_TO_DELAY
43         vTaskDelayUntil(&last_wake_time, TICKS_TO_DELAY);
44         //Get current ref clock
45         TEST_ASSERT_EQUAL(IDEAL_DELAY_PERIOD_MS, TICKS_TO_MS(xTaskGetTickCount() - ticks_before_delay));
46         ref_current = ref_clock_get();
47         TEST_ASSERT_UINT32_WITHIN(TICK_PERIOD_US, IDEAL_DELAY_PERIOD_US, (uint32_t)(ref_current - ref_prev));
48         ref_prev = ref_current;
49         ticks_before_delay = last_wake_time;
50     }
51 
52     //Delete Task after prescribed number of cycles
53     xSemaphoreGive(task_delete_semphr);
54     vTaskDelete(NULL);
55 }
56 
57 TEST_CASE("Test vTaskDelayUntil", "[freertos]")
58 {
59     task_delete_semphr = xQueueCreateCountingSemaphore(NO_OF_TASKS_PER_CORE*portNUM_PROCESSORS, 0);
60     ref_clock_init();
61 
62     for(int i = 0; i < portNUM_PROCESSORS; i++){
63         xTaskCreatePinnedToCore(delaying_task, "delay_pinned", 1024, NULL, TSK_PRIORITY, NULL, i);
64         xTaskCreatePinnedToCore(delaying_task, "delay_no_aff", 1024, NULL, TSK_PRIORITY, NULL, tskNO_AFFINITY);
65     }
66 
67     for(int i = 0; i < NO_OF_TASKS_PER_CORE*portNUM_PROCESSORS; i++){
68         xSemaphoreTake(task_delete_semphr, portMAX_DELAY);
69     }
70     //Cleanup
71     vSemaphoreDelete(task_delete_semphr);
72     ref_clock_deinit();
73 }
74