【问题标题】:c/c++: How can I know the size of used flash memory?c/c++:如何知道已用闪存的大小?
【发布时间】:2014-03-01 00:18:37
【问题描述】:

我最近遇到了闪存溢出问题。在对代码进行了一些优化之后,我保存了一些闪存并成功执行了软件。我想通过我的更改节省多少闪存。请让我知道如何检查已用闪存/可用闪存。我还想知道特定功能/文件使用了多少闪存。

以下是关于我的开发环境的一些信息。 - 具有 64 k ram 和 512 K 闪存的 Avr 微控制器。 - 使用 freeRtos。 - 使用 GNU C++ 编译器。 - 使用 AVRATJTAGEICE 进行编程和调试。

请告诉我解决方案。

问候, 贾加迪普。

【问题讨论】:

    标签: c++ c flash memory out-of-memory


    【解决方案1】:

    GCC 的 size 程序正是您所寻找的。​​p>


    size 可以传递完整编译的.elf 文件。默认情况下,它会输出如下内容:

    $ size linked-file.elf
       text    data     bss     dec     hex filename
      11228     112    1488   12828    321c linked-file.elf
    

    这是说:

    此文件的.text“部分”中有11228 字节。这通常用于函数。
    112字节的初始化数据:程序中有初始值的全局变量。
    1488字节的未初始化数据:没有初始值的全局变量。

    dec 只是前 3 个值的总和:11228 + 112 + 1488 = 12828
    hex 只是 dec 值的十六进制表示:0x321c == 12828

    对于嵌入式系统,通常dec 需要小于目标设备的闪存大小(或设备上的可用空间)。

    通常只需观察 GCC 的 size 命令的 dectext 输出,即可随着时间的推移监控已编译代码的大小。大小的大幅跳跃通常表明新功能实现不佳或 constexpr 没有被编译掉。 (别忘了function-sectionsdata-sections)。

    注意:对于 AVR,您需要使用 avr-size 检查 AVR .elf 文件的链接大小。 avr-size 需要一个目标芯片的额外参数,并会自动计算您选择的芯片的已用闪存百分比。


    GCC 的size 也可以直接作用于中间对象文件。

    如果您想检查函数的编译大小,这特别有用。

    你应该会看到类似这样的摘录:

    $ size -A main.cpp.o
    main.cpp.o  :
    section                                                                size   addr
    .group                                                                    8      0
    .group                                                                    8      0
    .text                                                                     0      0
    .data                                                                     0      0
    .bss                                                                      0      0
    .text._Z8sendByteh                                                        8      0
    .text._ZN3XMC5IOpin7setModeENS0_4ModeE                                   64      0
    .text._ZN7NamSpac6OptionIN5Clock4TimeEEmmEi                              76      0
    .text.Default_Handler                                                    24      0
    .text.HardFault_Handler                                                  16      0
    .text.SVC_Handler                                                        16      0
    .text.PendSV_Handler                                                     16      0
    .text.SysTick_Handler                                                    28      0
    .text._Z5errorPKc                                                         8      0
    .text._ZN7NamSpac5Motor2goEi                                            368      0
    .text._ZN7NamSpac5Motor3getEv                                            12      0
    .rodata.cst1                                                              1      0
    .text.startup.main                                                      632      0
    .text._ZN7NamSpac7Program3runEv                                         380      0
    .text._ZN7NamSpac8Position4tickEv                                        24      0
    .text.startup._GLOBAL__sub_I__ZN7NamSpac7displayE                       292      0
    .init_array                                                               4      0
    .bss._ZN5Debug9formatterE                                                 4      0
    .rodata._ZL10dispDigits                                                   8      0
    .bss.position                                                             4      0
    .bss.motorState                                                           4      0
    .bss.count                                                                4      0
    .rodata._ZL9diameters                                                    20      0
    .bss._ZN7NamSpac8diameterE                                               16      0
    .bss._ZN5Debug3pinE                                                      12      0
    .bss._ZN7NamSpac7displayE                                                24      0
    .rodata.str1.4                                                          153      0
    .rodata._ZL12dispSegments                                                32      0
    .bss._ZL16diametersDisplay                                               10      0
    .bss.loadAggregate                                                        4      0
    .bss.startCount                                                           4      0
    .bss._ZL15runtimesDisplay                                                10      0
    .bss._ZN7NamSpac7runtimeE                                                16      0
    .bss.startTime                                                            4      0
    .rodata._ZL8runtimes                                                     20      0
    .comment                                                                111      0
    .ARM.attributes                                                          49      0
    Total                                                                  2494
    

    【讨论】:

      【解决方案2】:

      请告诉我解决方案。

      抱歉,没有解决方案!您必须了解与最终 ELF 相关联的内容,并确定它是有意链接还是不想要的默认链接。

      请告诉我如何检查已用闪存/可用闪存。

      这主要取决于您的实际目标硬件平台,因此您必须设法让您的.text 部分适合那里。

      我还想知道特定功能/文件使用了多少闪存。

      GCC binutils 的nm 工具提供有关在 ELF 文件中找到的任何(全局)符号的详细信息,以及它在相关部分中占用的空间。您只需要grep 特定函数/类/命名空间的结果(最好解构!)来累积部分类型和符号过滤输出以供分析。

      这就是方法,我一直在使用一个名为nmalyzr 的小工具。很抱歉,因为它位于 GIT 存储库中,它并没有真正按预期工作(我有工作版本,没有被推回)。


      一般来说,寻找具有#include <iostream> 语句的代码(无论是否使用std::cout 或类似的,都提供静态实例!)或不需要的newlib/libstdc++ 绑定是一个很好的策略,例如默认异常处理。

      【讨论】:

        【解决方案3】:

        对生成的 elf 文件使用 binutils 中的 size 命令。由于您似乎使用 AVR 芯片,请使用avr-size

        要获取函数的大小,请使用 binutils 中的 nm 命令(AVR 芯片上的 avr-nm)。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2015-01-15
          • 2010-12-31
          • 2010-12-02
          • 2012-03-17
          • 2019-03-08
          • 2018-11-08
          • 1970-01-01
          相关资源
          最近更新 更多