1
9
10
18
19
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
67
68
69
73
74
75
76
77
78
79
83
84
85
89
90
91
92
96
97
98
99
117
118
119
124
129
130
131
132
133
134
135
136
137
148
149
150
151
152
153
154
157
158
159
168
169
170
171
172
173
174
175
176
177
178
179
180
184
185
186
187
188
/* ... */
#include "sdkconfig.h"
#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"
#include "esp_err.h"8 includes
#define NUM_OF_SPIN_TASKS 6
#define SPIN_ITER 500000
#define SPIN_TASK_PRIO 2
#define STATS_TASK_PRIO 3
#define STATS_TICKS pdMS_TO_TICKS(1000)
#define ARRAY_SIZE_OFFSET 5 6 defines
static char task_names[NUM_OF_SPIN_TASKS][configMAX_TASK_NAME_LEN];
static SemaphoreHandle_t sync_spin_task;
static SemaphoreHandle_t sync_stats_task;
/* ... */
static esp_err_t print_real_time_stats(TickType_t xTicksToWait)
{
TaskStatus_t *start_array = NULL, *end_array = NULL;
UBaseType_t start_array_size, end_array_size;
configRUN_TIME_COUNTER_TYPE start_run_time, end_run_time;
esp_err_t ret;
start_array_size = uxTaskGetNumberOfTasks() + ARRAY_SIZE_OFFSET;
start_array = malloc(sizeof(TaskStatus_t) * start_array_size);
if (start_array == NULL) {
ret = ESP_ERR_NO_MEM;
goto exit;
}{...}
start_array_size = uxTaskGetSystemState(start_array, start_array_size, &start_run_time);
if (start_array_size == 0) {
ret = ESP_ERR_INVALID_SIZE;
goto exit;
}{...}
vTaskDelay(xTicksToWait);
end_array_size = uxTaskGetNumberOfTasks() + ARRAY_SIZE_OFFSET;
end_array = malloc(sizeof(TaskStatus_t) * end_array_size);
if (end_array == NULL) {
ret = ESP_ERR_NO_MEM;
goto exit;
}{...}
end_array_size = uxTaskGetSystemState(end_array, end_array_size, &end_run_time);
if (end_array_size == 0) {
ret = ESP_ERR_INVALID_SIZE;
goto exit;
}{...}
uint32_t total_elapsed_time = (end_run_time - start_run_time);
if (total_elapsed_time == 0) {
ret = ESP_ERR_INVALID_STATE;
goto exit;
}{...}
printf("| Task | Run Time | Percentage\n");
for (int i = 0; i < start_array_size; i++) {
int k = -1;
for (int j = 0; j < end_array_size; j++) {
if (start_array[i].xHandle == end_array[j].xHandle) {
k = j;
start_array[i].xHandle = NULL;
end_array[j].xHandle = NULL;
break;
}{...}
}{...}
if (k >= 0) {
uint32_t task_elapsed_time = end_array[k].ulRunTimeCounter - start_array[i].ulRunTimeCounter;
uint32_t percentage_time = (task_elapsed_time * 100UL) / (total_elapsed_time * CONFIG_FREERTOS_NUMBER_OF_CORES);
printf("| %s | %"PRIu32" | %"PRIu32"%%\n", start_array[i].pcTaskName, task_elapsed_time, percentage_time);
}{...}
}{...}
for (int i = 0; i < start_array_size; i++) {
if (start_array[i].xHandle != NULL) {
printf("| %s | Deleted\n", start_array[i].pcTaskName);
}{...}
}{...}
for (int i = 0; i < end_array_size; i++) {
if (end_array[i].xHandle != NULL) {
printf("| %s | Created\n", end_array[i].pcTaskName);
}{...}
}{...}
ret = ESP_OK;
exit:
free(start_array);
free(end_array);
return ret;
}{ ... }
static void spin_task(void *arg)
{
xSemaphoreTake(sync_spin_task, portMAX_DELAY);
while (1) {
for (int i = 0; i < SPIN_ITER; i++) {
__asm__ __volatile__("NOP");
}{...}
vTaskDelay(pdMS_TO_TICKS(100));
}{...}
}{ ... }
static void stats_task(void *arg)
{
xSemaphoreTake(sync_stats_task, portMAX_DELAY);
for (int i = 0; i < NUM_OF_SPIN_TASKS; i++) {
xSemaphoreGive(sync_spin_task);
}{...}
while (1) {
printf("\n\nGetting real time stats over %"PRIu32" ticks\n", STATS_TICKS);
if (print_real_time_stats(STATS_TICKS) == ESP_OK) {
printf("Real time stats obtained\n");
}{...} else {
printf("Error getting real time stats\n");
}{...}
vTaskDelay(pdMS_TO_TICKS(1000));
}{...}
}{ ... }
void app_main(void)
{
vTaskDelay(pdMS_TO_TICKS(100));
sync_spin_task = xSemaphoreCreateCounting(NUM_OF_SPIN_TASKS, 0);
sync_stats_task = xSemaphoreCreateBinary();
for (int i = 0; i < NUM_OF_SPIN_TASKS; i++) {
snprintf(task_names[i], configMAX_TASK_NAME_LEN, "spin%d", i);
xTaskCreatePinnedToCore(spin_task, task_names[i], 1024, NULL, SPIN_TASK_PRIO, NULL, tskNO_AFFINITY);
}{...}
xTaskCreatePinnedToCore(stats_task, "stats", 4096, NULL, STATS_TASK_PRIO, NULL, tskNO_AFFINITY);
xSemaphoreGive(sync_stats_task);
}{ ... }