0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

MCUXpresso IDE的栈分析功能

恩智浦MCU加油站 来源:恩智浦MCU加油站 2023-05-26 09:35 次阅读

嵌入式系统中,RAM 的大小是非常有限的。尤其是做器件选型时,更小 RAM 的芯片意味着更低的采购价格,产品才会更具竞争力,有更高的毛利。

在这样极致的压榨下,留给堆栈的空间更加少了。开发者不得不面对爆栈的巨大风险。每个软件工程师都想有一个工具能够帮助他们检验栈的使用情况,从而很好的评估风险。

人们寻常采用的方法是把栈里都先写满一个特定的值,比如 0xAA。随后在程序运行一段时间之后看看还剩多少 0xAA 没有被改掉。这种方法确实有一定的效果,但是显然还不够直观,又比较麻烦。尤其是当工程有不止一个栈的时候。

为此,新版本的 gcc 编译器提供了一个有用的编译选项-fstack-usage。使用这个选项后,编译器会额外产生有关栈使用情况的信息,而 MCUXpresso 可以整理这些信息,并将它们非常清晰地显示出来。

fstack-usage与Call Graph

先让我们看看 GNU 关于-fstack-usage 的说明:(https://gcc.gnu.org/onlinedocs/gcc/Developer-Options.html)

7d02d5e8-fafa-11ed-90ce-dac502259ad0.png

它以每个函数为基础,使编译器生成程序的堆栈使用信息。信息存放在后缀名为.su 的文件中。

下图是编译文件夹的内容,可以看到有一个同名的 su 文件。

7d0b6e9c-fafa-11ed-90ce-dac502259ad0.png

这个文件的内容也很简单,它列 出 了 文 件名(system_MIMXRT1052.c), 函数的 行号和列号, 函数的名称, 如 SystemInit,堆栈的使用情况(8),以及如何分配(static)。

7d14b60a-fafa-11ed-90ce-dac502259ad0.png

但是这样单个显示是没有什么参考价值的,我们需要的是整个工程的全景,要把所有的 su 文件整理出来。 MCUXpresso IDE v11 版本提供了这一功能。在 Image Info 窗口中有一个 Call Graph 标签。单击右上角的导入按钮就可以导入当前整个工程的 stack 使用情况。

7d1f7afe-fafa-11ed-90ce-dac502259ad0.png

前面带“>”的函数名称显示“根”函数:它们不能被从其他任何地方调用的。其中ResetISR就是 reset 入 口 函 数 , 而 exception handlers 里 面 都 是 中 断 服 务 程 序 。
HAL_UartReceiveBlocking()函数因为没有其它函数显式的调用它,所以也被认为是根函数。
这里我们可以看到这种分析的一个弱点,如果函数是通过函数指针的方式来调用那么该功能就无能为例了。但是使用者可以自己分析程序给续上。

如果函数是递归的,则用一个特殊的双箭头标记。成本估算将针对单级递归。

Full Cost 表示累积堆栈使用量(此函数加上所有被调用的)。

Local Cost 表示本层的堆栈使用量。

Depth 表示由该函数引起的调用级别数。

请注意Exception Handlers 这里,它集中了所有的中断服务程序。由于没有显式的调用,它们都是根函数,并且这里只统计非中断嵌套情况下的最大用量。所以如果允许中断嵌套, 那么对于栈的分配应该更加保守。

此外,如果函数是用汇编语言写的,那么工具是无法统计它们的栈使用情况, 一律会统计成‘4’。但如果调用到了其它函数,深度和 Full cost 还是会被统计的。

需要注意这个堆栈使用报告仅涵盖每个函数或调用树的堆栈使用情况。它们不包括异常处理程序所需的额外堆栈空间。所以最后的堆栈计算是 ResetISR 栈+中断栈,如果允许中断嵌套,那么整个中断嵌套最长的情况必须要被考虑。 该工具在基于 RTOS(例如 FreeRTOS)的系统中同样运行良好且开箱即用。因此,使用该工具,我们可以很好地估计每个任务堆栈的使用情况。栈计算可以使用下图,它来自 Joseph Yiu,一位来自 ARM 的大牛。

7d2b3740-fafa-11ed-90ce-dac502259ad0.png

其它同栈保护有关的编译选项

GCC 除了提供 stack-usage 这个编译选项外,还有其它一些相关的选项可供选择。

- Wstack-usage

这是一个有用处的编译选项:-Wstack-usage。它能够在堆栈使用超过限制时产生 warning

信息。用法是:

-Wstack-usage=256

它表示如果栈使用量超过 256 时产生警告。这样就能更快速地知道哪个函数超了。只说它有些用处而不是非常有用是因为,只针对单个函数的堆栈用量, 不会按调用树累计被调用函数的堆栈总数。

- fstack-protector 这个选项的解释是: 产生额外的代码来检查缓冲区溢出,例如堆栈粉碎攻击。这是通过向具有易受攻击对象的函数添加保护变量来实现的。这包括调用 alloca 的函数,以及缓冲区大于 8 字节的函数。在输入函数时初始化保护,然后在函数退出时检查保护。如果保护检查失败,将打印错误消息,程序退出。

- fstack-protector-all

同-fstack-protector 基本相同, 区别是它为所有的函数都提供保护。

-fstack-protector和-fstack-protector-all在ebp和ip等信息的地址下面放一个保护数, 如果栈溢出 ,那么这个 32 位数会被修改,就会导致函数进入栈溢出错误处理函数。一旦检测到溢出就会调用__stack_chk_fail()函数。这个函数需要用户自己来写,比如可以打印一个报错信息,或者执行其它一些保护措施。 下图是在编译选项里加入-fstack-protector-all 后一个普通C函数的汇编内容。

7d3318f2-fafa-11ed-90ce-dac502259ad0.png

当然,可以想见,如果每个函数都加这么一段,编译出来的二进制文件会大上许多,执行速度也会变慢一些。而如果仅仅使用-fstack-protector,则很少有函数会被保护。因为 alloca() 是在栈(stack)里面分配空间,而我们一般都是用 malloc()在堆(heap)里面分配。

小结

栈空间防溢出是软件设计中非常关键的问题。MCUXpresso IDE 的 Call Graph 窗口为开发者提供了很好的可视化统计表格, 非常便于对堆栈使用情况的评估。论程序有没有操作系统,它都非常有效。 而GCC编译器提供的其它一些选项,虽然也有用处,但是在嵌入式软件设计中还是用在 debug 阶段会更好一些。开发者还是应该尽量使用 call Graph 功能做到事先防范。

审核编辑:汤梓红

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • mcu
    mcu
    +关注

    关注

    146

    文章

    16984

    浏览量

    350251
  • 恩智浦
    +关注

    关注

    14

    文章

    5825

    浏览量

    106632
  • IDE
    IDE
    +关注

    关注

    0

    文章

    334

    浏览量

    46668
  • 编译器
    +关注

    关注

    1

    文章

    1618

    浏览量

    49045
  • mcuxpresso
    +关注

    关注

    1

    文章

    38

    浏览量

    4153

原文标题:MCUXpresso IDE 的栈分析功能

文章出处:【微信号:NXP_SMART_HARDWARE,微信公众号:恩智浦MCU加油站】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    MCUXpresso IDE 11.6.0增加功耗分析功能

    对于IOT 物联网的应用,对于功耗要求越来越高,因此如果有软件工具能集成功耗分析,对于代码优化以及产品性能提升是有极大帮助,在MCUXpresso IDE 11.6.0里面就集成了功耗分析
    发表于 11-17 10:15 530次阅读

    MCUXpresso IDE怎么使用?

    为什么NXP的跨界 RT单片机没有什么人用?教程也非常少。在外面其实很多人用的。 使用MCUXpresso IDE就更少。我不是开发技术。我是做产品设计的。先了解一下怎么回事。希望大家指教。1
    发表于 01-12 06:14

    MCUXpresso IDE在启动调试会话时崩溃怎么修复?

    MCUXpresso IDE v10.2.1 [Build 795] [2018-07-25] MCUXpresso IDE在启动调试会话时崩溃。错误对话框指出发生了堆栈错误。有人可以
    发表于 03-15 08:47

    MCUXpresso IDE中是否有延迟功能

    我只是想知道 MCUXpresso IDE 中是否有延迟功能。例如,我想在我的程序中创建一个 1 秒的延迟,我想知道是否有一个很好的函数可以用来代替创建嵌套的 for 循环。 例如,在 Arduino 代码中,我只使用函数:延迟
    发表于 03-16 07:58

    如何将示例项目导入MCUXpresso IDE

    你好我是 MCUXpresso IDE 的新手。我已经安装了最新版本。当我为演示板 RT1020 选择示例时,没有电机控制示例 (mc_pmsm)。我在 MCUXpresso 中尝试
    发表于 03-16 08:15

    如何在MCUxpresso IDE的外设中配置USB?

    我必须在 MCUxpresso IDE 中使用 LPC54113 实现 USB 协议代码。请提供以下详细信息,1. 如何在 MCUxpresso IDE 的外设中配置 USB。2.US
    发表于 04-04 06:22

    如何为pn7362使用MCUXpresso IDE

    我想使用 PN7362 芯片实现 NFC 功能。但是,如果安装MCUXpresso IDE 搜索SDK,则没有PN7362 的SDK。 我不知道如何在 MCUXpresso
    发表于 04-23 06:56

    MCUXpresso工具套件启动和运行

    RT开发硬件,与会者将直观地了解如何构建自定义的SDK、配置引脚和时钟设置、生成项目、导入和调试应用,并了解MCUXpresso IDE的高级调试功能,包括追踪、分析、覆盖、观察点等
    的头像 发表于 01-16 07:00 4976次阅读
    <b class='flag-5'>MCUXpresso</b>工具套件启动和运行

    MCUXpresso IDE在Flash调试的注意事项

    大家好,我是痞子衡,是正经搞技术的痞子。今天痞子衡给大家介绍的是 MCUXpresso IDE 下使用 J-Link 下载算法在 Flash 调试注意事项。 介绍一下如何使用新生成的 flash
    的头像 发表于 12-23 13:53 991次阅读

    痞子衡嵌入式:MCUXpresso IDE下在线调试时使用不同复位策略的现象总结

      大家好,我是痞子衡,是正经搞技术的痞子。今天痞子衡给大家分享的是MCUXpresso IDE下在线调试时使用不同复位策略的现象总结。  本篇实际上是《IAR在线调试时设不同复位类型可能会导致
    发表于 11-30 18:06 14次下载
    痞子衡嵌入式:<b class='flag-5'>MCUXpresso</b> <b class='flag-5'>IDE</b>下在线调试时使用不同复位策略的现象总结

    使用Eclipse和MCUXpresso IDE调试RV32M1-VEGA RISC-V开发板

    使用Eclipse和MCUXpresso IDE调试RV32M1-VEGA RISC-V开发板
    发表于 12-06 20:06 7次下载
    使用Eclipse和<b class='flag-5'>MCUXpresso</b> <b class='flag-5'>IDE</b>调试RV32M1-VEGA RISC-V开发板

    MCUXpresso IDE下工程链接文件配置管理与自动生成机制介绍

    我们知道不同 IDE 下链接文件语法是不一样的,而恩智浦 MCUXpresso IDE 底层编译器是 Arm GCC,因此其链接文件就是标准 GCC 下 .ld 文件。
    的头像 发表于 11-17 10:41 3087次阅读
    <b class='flag-5'>MCUXpresso</b> <b class='flag-5'>IDE</b>下工程链接文件配置管理与自动生成机制介绍

    MCUXpresso IDE下生成镜像文件的方法及其与IAR,MDK差异

    MCUXpresso IDE下生成镜像文件的方法及其与IAR,MDK差异
    的头像 发表于 09-28 17:05 811次阅读
    <b class='flag-5'>MCUXpresso</b> <b class='flag-5'>IDE</b>下生成镜像文件的方法及其与IAR,MDK差异

    MCUXpresso IDE下将源码制作成Lib库方法及其与IAR,MDK差异

    MCUXpresso IDE下将源码制作成Lib库方法及其与IAR,MDK差异
    的头像 发表于 11-07 17:13 1162次阅读
    <b class='flag-5'>MCUXpresso</b> <b class='flag-5'>IDE</b>下将源码制作成Lib库方法及其与IAR,MDK差异

    如何在MCUXpresso IDE中测量能耗?

    如何在MCUXpresso IDE中测量能耗?
    的头像 发表于 09-19 16:40 549次阅读
    如何在<b class='flag-5'>MCUXpresso</b> <b class='flag-5'>IDE</b>中测量能耗?