1 #include <stdlib.h>
2 #include <stdint.h>
3 
4 #include "esp_timer.h"
5 #include "esp_log.h"
6 #include "esp_attr.h"
7 #include "ccomp_timer.h"
8 
9 #include "freertos/FreeRTOS.h"
10 #include "freertos/task.h"
11 #ifndef CONFIG_FREERTOS_UNICORE
12 #include "esp_ipc.h"
13 #endif
14 
15 #include "unity.h"
16 
17 #ifndef CONFIG_FREERTOS_UNICORE
start_timer(void * param)18 static void start_timer(void *param)
19 {
20     esp_err_t *err = (esp_err_t *)param;
21     *err = ccomp_timer_start();
22 }
23 
stop_timer(void * param)24 static void stop_timer(void *param)
25 {
26     int64_t *t = (int64_t *)param;
27     *t = ccomp_timer_stop();
28 }
29 #endif
30 
computation(void * param)31 static void computation(void *param)
32 {
33     int *l = (int *)param;
34     for (volatile int i = 0, a = 0; i < *l; i++)
35     {
36         a += i;
37     }
38 }
39 
40 TEST_CASE("starting and stopping works", "[test_utils][ccomp_timer]")
41 {
42     esp_err_t err;
43     int64_t t;
44 
45     /*
46    * Test on the same task
47    */
48     err = ccomp_timer_start();
49     TEST_ASSERT_EQUAL(ESP_OK, err);
50 
51     // Start an already started timer
52     err = ccomp_timer_start();
53     TEST_ASSERT_EQUAL(ESP_ERR_INVALID_STATE, err);
54 
55     t = ccomp_timer_stop();
56     TEST_ASSERT_GREATER_OR_EQUAL(0, t);
57 
58     // Stopping a non started timer
59     t = ccomp_timer_stop();
60     TEST_ASSERT_EQUAL(-1, t);
61 
62 #ifndef CONFIG_FREERTOS_UNICORE
63     /*
64    * Test on different task on same core
65    */
66     err = ccomp_timer_start();
67     TEST_ASSERT_EQUAL(ESP_OK, err);
68 
69     esp_ipc_call_blocking(xPortGetCoreID(), start_timer, &err);
70     TEST_ASSERT_EQUAL(ESP_ERR_INVALID_STATE, err);
71 
72     t = ccomp_timer_stop();
73     TEST_ASSERT_GREATER_OR_EQUAL(0, t);
74 
75     esp_ipc_call_blocking(xPortGetCoreID(), stop_timer, &t);
76     TEST_ASSERT_EQUAL(-1, t);
77 
78     /*
79    * Timer being stopped from another task on the same core
80    */
81     err = ccomp_timer_start();
82     TEST_ASSERT_EQUAL(ESP_OK, err);
83 
84     esp_ipc_call_blocking(xPortGetCoreID(), stop_timer, &t);
85     TEST_ASSERT_GREATER_OR_EQUAL(0, t);
86 
87     /*
88    * Test on different task on same core
89    */
90     err = ccomp_timer_start();
91     TEST_ASSERT_EQUAL(ESP_OK, err);
92 
93     esp_ipc_call_blocking(xPortGetCoreID() == 0 ? 1 : 0, start_timer, &err);
94     TEST_ASSERT_EQUAL(ESP_OK, err);
95 
96     t = ccomp_timer_stop();
97     TEST_ASSERT_GREATER_OR_EQUAL(0, t);
98 
99     esp_ipc_call_blocking(xPortGetCoreID() == 0 ? 1 : 0, stop_timer, &t);
100     TEST_ASSERT_GREATER_OR_EQUAL(0, t);
101 #endif
102 }
103 
104 TEST_CASE("getting the time works", "[test_utils][ccomp_timer]")
105 {
106     // Get wall time and start ccomp timer
107     int64_t start = esp_timer_get_time();
108     ccomp_timer_start();
109 
110     int64_t t_a = ccomp_timer_get_time();
111 
112     int temp = 10000;
113     computation(&temp);
114 
115     int64_t t_b = ccomp_timer_get_time();
116 
117     // Check that ccomp time after computation is more than
118     // ccomp time before computation.
119     TEST_ASSERT_LESS_THAN(t_b, t_a);
120 
121     // Get time diff between wall time and ccomp time
122     int64_t t_1 = ccomp_timer_stop();
123     int64_t t_2 = esp_timer_get_time() - start;
124 
125     // The times should at least be in the same ballpark (at least within 10%)
126     float diff = (abs(t_1 - t_2)) / ((float)t_2);
127     TEST_ASSERT(diff <= 10.0f);
128 
129     // Since the timer was already stopped, test that ccomp_timer_get_time
130     // returns the same time as ccomp_timer_stop
131     int64_t t_c = ccomp_timer_get_time();
132     TEST_ASSERT_EQUAL(t_1, t_c);
133 }
134 
135 #ifndef CONFIG_FREERTOS_UNICORE
136 TEST_CASE("timers for each core counts independently", "[test_utils][ccomp_timer]")
137 {
138     esp_err_t err;
139 
140     // Start a timer on this core
141     err = ccomp_timer_start();
142     TEST_ASSERT_EQUAL(ESP_OK, err);
143 
144     // Do some work on this core
145     int temp = 10000;
146     computation(&temp);
147 
148     // Start a timer on the other core
149     esp_ipc_call_blocking(xPortGetCoreID() == 0 ? 1 : 0, start_timer, &err);
150     TEST_ASSERT_EQUAL(ESP_OK, err);
151 
152     // Do some work on other core (less work than this core did)
153     temp = 5000;
154     esp_ipc_call_blocking(xPortGetCoreID() == 0 ? 1 : 0, computation, &temp);
155 
156     // Stop timers from both cores
157     int64_t t_1 = ccomp_timer_stop();
158     TEST_ASSERT_GREATER_OR_EQUAL(0, t_1);
159 
160     int64_t t_2;
161     esp_ipc_call_blocking(xPortGetCoreID() == 0 ? 1 : 0, stop_timer, &t_2);
162     TEST_ASSERT_GREATER_OR_EQUAL(0, t_2);
163 
164     // Since this core did more work, it probably has longer measured time
165     TEST_ASSERT_GREATER_THAN(t_2, t_1);
166 }
167 #endif
168