参考《FreeRTOS入门与工程实践(基于DshanMCU-103).pdf》
目录
- 估算栈的大小
- 回顾
- 简介
- 计算说明
- 估计函数用到的栈有多大
- 合计
估算栈的大小
回顾
上一篇文章链接:http://t.csdnimg.cn/Cc8b4
传送门: 上一篇文章
上一篇文章创建的三个任务
/* 创建任务:声 */
// 先创建一个动态分配内存的任务
ret = xTaskCreate( //加返回值是 判断任务有没有创建成功
PlayMusic, //孤勇者的函数
"SoundTask", //声音任务
128, //栈大小
NULL, //无传入的参数
osPriorityNormal, //优先级默认
& xSoundTaskHandle //任务句柄
);
/* 创建任务:光 */
// 创建一个静态分配内存的任务
xLightTaskHandle = xTaskCreateStatic(
Led_Test, //LED测试函数,PC13以500ms间隔亮灭一次
"LightTask", //光任务
128, //栈大小,这里提供了栈的大小(长度)
NULL, //无传入的参数
osPriorityNormal, //优先级默认
g_pucStackOfLightTask, // 静态分配的栈,一个buffer,这里只提供了首地址,长度就是栈的大小,最开始栈的类型不对,栈的类型uint32_t
&g_TCBofLightTask // 取址TCB
);
/* 创建任务:色 */
xColorTaskHandle = xTaskCreateStatic(
ColorLED_Test, //LED测试函数,PC13以500ms间隔亮灭一次
"ColorTask", //光任务
128, //栈大小,这里提供了栈的大小(长度)
NULL, //无传入的参数
osPriorityNormal, //优先级默认
g_pucStackOfColorTask, // 静态分配的栈,一个buffer,这里只提供了首地址,长度就是栈的大小
&g_TCBofColorTask // 取址TCB
);
简介
上一篇文章的任务,要么是动态分配,分配指定大小的栈,要么提供一个数组,得告诉函数这个数组有多大
那么 — 栈的大小如何选取
栈里会保存什么
- 返回地址,其他寄存器Reg — 取决于函数调用深度(函数调用关系)
- 局部变量 — 取决char buf[x] ,数组的大小x
- 现场 - 16个寄存器,16*4=64byte
选取最复杂的调用关系
举个例子
函数A调用函数B,函数B调用函数C,函数C调用函数D,函数D调用函数E
- 调用关系 A > B > C > D > E
每一级调用里,需要保存哪些寄存器?
去反汇编看一看
这里保存了4个寄存器
- R2 R3 R4 LR
这里保存了4个寄存器
- R4 R5 R6 LR
这里保存了5个寄存器
- R4 R5 R6 R7 LR
理论上保存几个寄存器?最多能保存几个寄存器
理论上需要保存 R4~R11、LR这些寄存器,一共需要保存9个寄存器,称为被调用者寄存器
计算说明
-
每一级函数都需要9*4=36字节来保存寄存器
-
5级调用 * 9个寄存器 * 4字节
-
调用深度越深,用到的栈越大
但是用到栈最大的情况,并不一定在最深的调用关系出现
如下图,A调用F,但是F函数里定义了一个巨大的布局变量
所以得看代码,找到使用局部变量最多的函数
估计函数用到的栈有多大
以音乐播放的任务为例子
调用关系
-
局部变量 两个2字节的变量 = 4byte
-
4层调用
这个函数里定义了一个结构体
TIM_OC_InitTypeDef sConfig = { 0 };
调到结构体里,看看这个结构体有多大 7*4 = 28 byte
/**
* @brief TIM Output Compare Configuration Structure definition
*/
typedef struct
{
uint32_t OCMode; /*!< Specifies the TIM mode.
This parameter can be a value of @ref TIM_Output_Compare_and_PWM_modes */
uint32_t Pulse; /*!< Specifies the pulse value to be loaded into the Capture Compare Register.
This parameter can be a number between Min_Data = 0x0000 and Max_Data = 0xFFFF */
uint32_t OCPolarity; /*!< Specifies the output polarity.
This parameter can be a value of @ref TIM_Output_Compare_Polarity */
uint32_t OCNPolarity; /*!< Specifies the complementary output polarity.
This parameter can be a value of @ref TIM_Output_Compare_N_Polarity
@note This parameter is valid only for timer instances supporting break feature. */
uint32_t OCFastMode; /*!< Specifies the Fast mode state.
This parameter can be a value of @ref TIM_Output_Fast_State
@note This parameter is valid only in PWM1 and PWM2 mode. */
uint32_t OCIdleState; /*!< Specifies the TIM Output Compare pin state during Idle state.
This parameter can be a value of @ref TIM_Output_Compare_Idle_State
@note This parameter is valid only for timer instances supporting break feature. */
uint32_t OCNIdleState; /*!< Specifies the TIM Output Compare pin state during Idle state.
This parameter can be a value of @ref TIM_Output_Compare_N_Idle_State
@note This parameter is valid only for timer instances supporting break feature. */
} TIM_OC_InitTypeDef;
任务要是切换出去的话要用到64字节
合计
估算栈大小 = 4层调用 + 局部变量 + 现场
= 4层调用 + 4 + 28 + 现场
= 4*36 + 32 +64
= 144+32+64
= 240 Byte
我们提供的栈是128个字,128*4 = 512 Byte
512大于240,这么估算栈的大小是够用的!
现在只是粗略的计算,后面会学习精确计算栈的大小的方法~
这节视频的链接:【FreeRTOS入门与工程实践 --由浅入深带你学习FreeRTOS(FreeRTOS教程 基于STM32,以实际项目为导向)】 【精准空降到 00:39】 https://www.bilibili.com/video/BV1Jw411i7Fz/?p=17&share_source=copy_web&vd_source=8af85e60c2df9af1f0fd23935753a933&t=39
参考文章:http://t.csdnimg.cn/MAJe7
参考文章:http://t.csdnimg.cn/YEwmm