Freertos学习06-任务堆栈

发布时间 2023-06-27 12:01:47作者: seekwhale13

一、前言

  在FreeRTOS中,每个任务都有自己的堆栈,用于存储任务执行期间使用的局部变量和函数调用。堆栈的大小在任务创建时指定,如果任务使用的堆栈空间超过了指定的大小,就会发生堆栈溢出错误。

二、介绍

1.堆栈分配

image
xTaskCreate()为任务分配堆栈大小,但是需要注意的是,usStackDepth并不是以字为单位,而是以堆栈宽度为单位,例如在该系统中堆栈宽度为4 byte,我们为任务分配100堆栈空间,那么最后的堆栈大小为400byte(4*100)。如果我们分配的内存过少,可能会导致堆栈溢出,单片机会出现无限重启的情况。
具体介绍如下:
image

2.函数介绍

uxTaskGetStackHighWaterMark()是FreeRTOS中的一个函数,用于获取任务堆栈的高水位标记。即任务堆栈中未使用的空间大小。通过调用该函数,可以确定任务堆栈使用的最大空间,以便在创建任务时指定正确的堆栈大小,从而避免堆栈溢出错误。
image

三、代码测试

#include <stdio.h>
#include "sdkconfig.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_system.h"
#include "driver/gpio.h"

#define LED1_IO 12
#define LED1_IO_PIN (1ULL << 12)

void blinke_slow(void *pvparam)
{
	while (1)
	{
		gpio_set_level(LED1_IO, 1); // 高低电平
		printf("靓仔\n");
		vTaskDelay(1000 / portTICK_PERIOD_MS); // 延时
		gpio_set_level(LED1_IO, 0);			   // 高低电平
		vTaskDelay(1000 / portTICK_PERIOD_MS); // 延时
	}
}

void app_main(void)
{
	gpio_config_t LED_cof;
	// 设置配置IO为12
	LED_cof.pin_bit_mask = LED1_IO_PIN;
	// 设置为输出模式
	LED_cof.mode = GPIO_MODE_OUTPUT;
	// 禁止上拉
	LED_cof.pull_up_en = 0;
	// 禁止下拉
	LED_cof.pull_down_en = 0;
	// 禁用中断
	LED_cof.intr_type = 0;
	// 将配置写入
	gpio_config(&LED_cof);

	TaskHandle_t xHandle = NULL;
	xTaskCreate(blinke_slow, "mytask1", 1024, NULL, 1, &xHandle);

	UBaseType_t iStack;
	while (1)
	{
		iStack = uxTaskGetStackHighWaterMark(xHandle);
		printf("task1 istack = %d\n", iStack);

		vTaskDelay(3000 / portTICK_PERIOD_MS); // 延时
	}
}

测试结果:可见剩余堆栈从848减少至524.
image

THE END!