Files
fastbee/firmware/esp-idf/wumei-smart-firmware/main/statistic_free_rtos.c
2021-07-13 17:15:20 +08:00

165 lines
5.3 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/******************************************************************************
* 作者kerwincui
* 时间2021-06-08
* 邮箱164770707@qq.com
* 源码地址https://gitee.com/kerwincui/wumei-smart
* author: kerwincui
* create: 2021-06-08
* email164770707@qq.com
* source:https://github.com/kerwincui/wumei-smart
******************************************************************************/
#include "statistic_free_rtos.h"
static char task_names[NUM_OF_SPIN_TASKS][configMAX_TASK_NAME_LEN];
static SemaphoreHandle_t sync_spin_task;
static SemaphoreHandle_t sync_stats_task;
/**
* @brief 函数打印给定时间内任务的CPU使用情况
*
*
* @param xTicksToWait 统计测量周期
*
* @return
* - ESP_OK 成功
* - ESP_ERR_NO_MEM 内存不足,无法分配内部数组
* - ESP_ERR_INVALID_SIZE uxTaskGetSystemState的数组大小不足尝试增加ARRAY_SIZE_OFFSET
* - ESP_ERR_INVALID_STATE 延迟时间太短
*/
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;
uint32_t 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 * portNUM_PROCESSORS);
printf("| %s | %d | %d%%\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) {
//消耗CPU周期
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 %d 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 free_rtos_start(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);
}