【FreeRTOS】估算栈的大小

参考《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
  );


简介

上一篇文章的任务,要么是动态分配,分配指定大小的栈,要么提供一个数组,得告诉函数这个数组有多大

那么 — 栈的大小如何选取

栈里会保存什么

  1. 返回地址,其他寄存器Reg — 取决于函数调用深度(函数调用关系)
  2. 局部变量 — 取决char buf[x] ,数组的大小x
  3. 现场 - 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

  • 27
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
FreeRTOS中的任务是指用于保存任务执行上下文信息的内存区域。任务通常位于芯片的RAM中。在FreeRTOS中,任务大小可以通过配置文件或任务创建函数来确定。任务大小要足够容纳任务执行所需的变量和函数调用的帧信息。 在FreeRTOS中,任务创建函数中的参数值是以字为单位的。而uxTaskGetStackHighWaterMark()函数返回的值也是以字为单位的。因此,需要将这些字节大小的值转换为实际的字节大小任务大小应该根据任务的需求和RAM的可用空间来确定。 需要注意的是,在uC/OS-II中,没有类似FreeRTOS中的configTOTAL_HEAP_SIZE这样的大堆需要配置。在uC/OS-II中,任务是静态分配的,没有动态的内存管理,也没有类似malloc()和free()这样的内存管理函数。因此,在uC/OS-II中不存在由于频繁的内存管理导致的内存碎片问题。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [freertos与STM32分析、堆、全局区、常量区、代码区、RAM、ROM,及如何分配堆栈空间](https://blog.csdn.net/qq6738966/article/details/118441134)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *3* [FreeRTOS任务内存分配](https://blog.csdn.net/weixin_47321452/article/details/121691339)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

北国无红豆

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值