0
  • 如何通过生成的 MAP 文件确定任务使用的堆栈大小?
  • 如何确定ARM的RAM中堆栈和堆的大小
  • 如何确定是否需要为任务分配更多堆栈大小?
4

1 回答 1

3

如果您正在运行最新版本的 IAR EWARM,则有一个内置工具可以帮助您解决这些问题。

  1. 如何通过生成的 MAP 文件确定任务使用的堆栈大小?

对于您的第一个问题,您需要在地图文件中搜索每个任务堆栈的名称。在这种情况下,地图文件没有那么有用,因为您最好在项目中搜索CPU_STK类型,因为这将为您提供所有正确定义的堆栈的结果。如果你查看地图文件,你可能会看到这样的一行:

MainStack               0x20000000  0x1000  Data  Lc  main.o [1]

这意味着MainStack(可能是 a 的堆栈MainTask)的大小为 0x1000 或 4096 字节。第一列是符号名称,第二列是地址空间中的位置,第三列是大小,第四列是类型(Data,Code),第五列是范围(Lc = local,Gb = Global),最后一列是它所在的对象模块。

相反,如果您在项目中搜索您的实例,CPU_STK则会发现以下内容:

static  CPU_STK          MainStack[4096];

这为您提供了与MainStack大小 4096 相同的信息,但通过搜索 CPU_STK,它还会为您提供其他任务的结果,因此您实际上可能会在结果中看到以下内容:

static  CPU_STK          MainStack[4096];
static  CPU_STK          AuxStack[512];

所以,现在你可以看到还有一个AuxStack(大概是一个AuxTask),它是 512 字节。这将需要在映射文件中搜索特定堆栈名称以获得结果,所以我会发现这更容易。

  1. 如何确定ARM的RAM中堆栈和堆的大小?

对于这个,您需要深入研究链接器配置文件或选项中的链接器部分。更简单的方法是通过选项。转到您的项目选项,然后转到左侧的链接器项目。在配置选项卡下,选择编辑...,然后转到堆栈/堆选项卡。这将使您可以轻松访问 IAR 将用于在链接器中分配 HEAP 和 CSTACK 内存区域的大小。

或者,您可以深入研究该.icf文件,您可能会发现一组如下所示的行:

/*-Sizes-*/
define symbol __ICFEDIT_size_cstack__ = 0x400;
define symbol __ICFEDIT_size_heap__   = 0x400;

define block CSTACK    with alignment = 8, size = __ICFEDIT_size_cstack__   { };
define block HEAP      with alignment = 8, size = __ICFEDIT_size_heap__     { };

它也可能看起来完全不同!很难给出一个通用的答案,所以你最好看看选项。但是,在上面的代码中,您可以看到它们的大小CSTACK并由HEAP文件中前面定义的符号定义。您可以按照这些定义来获取大小。不过,您的链接器文件可能与此非常不同,正如我所说,很难给出一个普遍的答案。

  1. 如何确定是否需要为任务分配更多堆栈大小?

较新版本的 IAR 有一个很好的实用程序,可以确定任何函数所需的堆栈深度。在项目选项中,在高级选项卡的链接器下,您可以选中“启用堆栈使用分析”。启用此功能后,您的映射文件将包含根函数及其最大调用链。例如,我的MainTask样子是这样的:

Uncalled function
  "MainTask" in main.o [1]: 0x0000ac41
  Maximum call chain                            *?* 396 bytes

所以,这告诉我 MainTask 是一个未调用的函数(它不是直接调用的,而是通过函数指针调用的,IAR 无法自动解析),它需要 396 字节的堆栈。在它的下方,它将向您显示总计 396 个字节的调用链。

该工具值得注意的是,如果您使用函数指针和间接调用,IAR 无法自动找出这些指向何处。有一组pragma指令可用于告诉它在间接调用点调用了哪些可能的函数,您需要将它们放入以获得 100% 准确的堆栈深度。

另一种方法是在您的硬件上运行程序,但让操作系统监视堆栈溢出。Micrium 在这里有一个关于检测堆栈溢出的页面:检测任务堆栈溢出。此外,这里是获取有关任务堆栈使用信息的函数的文档:OSTaskStkChk()

于 2015-07-10T14:42:30.903 回答