堆&栈

堆就是一段能动态分配的内存。用malloc()分配。

栈就是一种“后进先出”的数据结构。

栈顶:允许插入和删除元素的一端,最后放入的元素在栈顶。
栈底:栈的另一端,最早放入的元素在栈底,不能直接操作。
栈深度:栈能容纳的最大元素数量。
压栈:把新元素放到栈顶。
弹栈:把栈顶元素取出并删除。
先进后出:先压入栈的元素会被后压入的元素压在下面,只能等上面的元素都弹出后才能出来,所以“先进后出”。

调用栈

“调用栈”就是由系统自动维护的栈,作用是在函数调用发生时保存上下文。
函数调用之前需要保存上下文,包括:参数、局部变量和返回地址。

//main方法
int main
{
int ret;
ret = f(3);
return ret;
}
//f() = 10x +3 + g(y)
int f(int x)
{
int a1,a2,a3,ret;
a1 = 10 * x;
a2 = 3;
a3 = g(x);
ret = a1 + a2 + a3;
return ret;
}
//g() = y^2 +5y
int g(int y)
{
int b1,b2,ret;
b1 = square(y);
b2 = 5 * y;
ret = b1 + b2;
return ret;
}
//计算平方
int square(int z)
{
return z*z;
}
main()方法的上下文
参数:无
局部变量:ret
返回地址:main()+3
f()方法的上下文
参数:x
局部变量:a1,a2,a3,ret
返回地址:f()+5
g()方法的上下文
参数:y
局部变量:b1.b2,ret
返回地址:g()+3

在FreeRTOS中,为每个任务分配一个调用栈,通过heap_x动态分配。

示例:估算一下任务的栈深度。

1234567891011121314151617181920212223
static void f(void){	float b[64];//局部变量,浮点型数组,长度64	......} void vTask1(void *pvParameters){	int a[64];//局部变量,整形数组,长度64	f();	......} int main(void){	......	xTaskCreate(vTask1, "task1", 栈深度, NULL, 1, NULL);	vTaskStartScheduler();	while(1)	{	......	}}
vTask1()f()
参数void *pvParameters(4个字节)
局部变量int a[64](256个字节)float b[64](256个字节)
返回地址4个字节

栈深度,单位是 字(word)。在常见的 32 位单片机(如 STM32、ESP32)上,StackType_t 通常是 uint32_t,即 4 字节,所以分配的字节数应该大于:520字节/4 = 130字

因此栈深度要写一个大于130的数字,比如设置成256。

🔍 ×