主要参考资料:
CSDN文章《ESP32 IDF开发调试奇技淫巧》: https://blog.csdn.net/qq_43332314/article/details/131859971
查询系统内存剩余堆/最小堆大小
查询系统剩余堆、最小堆大小的 API 位于 esp_system 组件(实际上时调用了heap组件)中。剩余堆大小过小,会导致 malloc 申请内存失败,当剩余堆不够时,很多网络操作均会失败,这是由于网路操作内部涉及很多 malloc 操作。
(1)查询系统剩余堆大小,返回值为 Byte
uint32_t esp_get_free_heap_size( void );
(2)查询系统最小堆大小,返回值为 Byte
uint32_t esp_get_minimun_free_heap_size(void);
示例:
while (1) {
remain_heap = esp_get_free_heap_size() / 1024;
ESP_LOGW(TAG, "Remaining heap tight:%lu k", remain_heap);
vTaskDelay(300);
}
查询线程剩余栈大小
方法一
由于ESP32 IDF采用FreeRTOS,因此查询线程所使用的栈大小空间,可通过FreeRTOS API实现,函数原型如下:
UBaseType_t uxTaskGetStackHighWaterMark( TaskHandle_t xTask );
返回值为线程栈使用的高水位线,所谓高水位线也即自任务开始运行以来,任务所使用的栈最大时所剩余的栈大小。因此此值越大,代表线程峰值栈剩余量越大。
示例:
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
void task_function(void *pvParameter) {
int stack_left = 0;
stack_left = uxTaskGetStackHighWaterMark(NULL);
printf("Stack left: %d bytes\n", stack_left);
while (1) {
char c[1000] = {0};
stack_left = uxTaskGetStackHighWaterMark(NULL);
printf("Stack left: %d bytes\n", stack_left);
vTaskDelay(100);
}
// 线程结束
vTaskDelete(NULL);
}
int app_main(void)
{
xTaskCreate(task_function, "task", 4096, NULL, 1, NULL);
vTaskDelete(NULL);
}
方法二
使用 vTaskList() 查看,函数原型
void vTaskList( char * pcWriteBuffer );
使用此函数需先配置 menuconfig 打开部分功能:
idf menuconfig → Component config → FreeRTOS → kernel→Enable FreeRTOS trace facility
idf menuconfig → Component config → FreeRTOS → kernel→Enable FreeRTOS trace facility → Enable FreeRTOS stats formatting functions
idf menuconfig → Component config → FreeRTOS → kernel→Enable FreeRTOS trace facility → Enable display of xCoreID in vTaskList
示例:
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include <string.h>
void task_function(void *pvParameter) {
uint8_t CPU_RunInfo[400];
while (1) {
memset(CPU_RunInfo, 0, 400);
vTaskList((char *)&CPU_RunInfo);
printf("----------------------------------------------------\r\n");
printf("task_name status priority stack num core\r\n");
printf("%s", CPU_RunInfo);
printf("----------------------------------------------------\r\n");
vTaskDelay(500 / portTICK_PERIOD_MS);
}
}
int app_main(void)
{
xTaskCreate(task_function, "task", 4096, NULL, 1, NULL);
vTaskDelete(NULL);
}
第一列,任务名称
第二列,任务状态
X: running
B: blocked
R: ready
D: deleted
S: suspended
第三列,任务优先级
数值越大,优先级越高
第四列,任务栈
数值越大,代表剩余的任务栈空间越大,单位Byte
注意此值为当前剩余栈大小,而不是峰值剩余栈大小
第五列,任务号
代表任务创建顺序
第六列,任务内核
查询各任务分配时间
esp32 idf 查询任务占用率,依旧可以通过FreeRTOS的任务统计功能来实现,函数原型如下:
void vTaskGetRunTimeStats( char * pcWriteBuffer );
配置menuconfig 打开:
idf.py menuconfig → Component config → FreeRTOS → Kernel → configGENERATE_RUN_TIME_STATS
示例:
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include <string.h>
void task_function(void *pvParameter) {
uint8_t CPU_RunInfo[400];
while (1) {
memset(CPU_RunInfo, 0, 400);
vTaskGetRunTimeStats((char *)&CPU_RunInfo);
printf("task_name run_cnt usage_rate \r\n");
printf("%s", CPU_RunInfo);
printf("----------------------------------------------------\r\n");
vTaskDelay(500 / portTICK_PERIOD_MS);
}
}
int app_main(void)
{
xTaskCreate(task_function, "task", 4096, NULL, 1, NULL);
vTaskDelete(NULL);
}