mirror of
https://gitee.com/beecue/fastbee.git
synced 2025-12-19 01:15:54 +08:00
165 lines
5.3 KiB
C
165 lines
5.3 KiB
C
/******************************************************************************
|
||
* 作者:kerwincui
|
||
* 时间:2021-06-08
|
||
* 邮箱:164770707@qq.com
|
||
* 源码地址:https://gitee.com/kerwincui/wumei-smart
|
||
* author: kerwincui
|
||
* create: 2021-06-08
|
||
* email:164770707@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);
|
||
}
|