IAR for ARM 运行 Micrium OS-III - 了解内存使用情况
IAR for ARM running Micrium OS-III - Understanding memory usage
- 如何通过生成的 MAP 文件确定任务正在使用的堆栈大小?
- 如何确定ARM内存中栈和堆的大小
- 如何确定是否需要为任务分配更多堆栈大小?
如果您运行正在使用最新版本的 IAR EWARM,那么有一个内置工具可以帮助您解决这些问题。
- 如何通过生成的 MAP 文件确定任务正在使用的堆栈大小?
对于第一个问题,您需要在映射文件中搜索每个任务堆栈的名称。在这种情况下,地图文件没有多大帮助,因为您最好在项目中搜索 CPU_STK
类型,因为这将为您提供包含所有正确定义的堆栈的结果。如果您查看地图文件,您可能会看到这样一行:
MainStack 0x20000000 0x1000 Data Lc main.o [1]
这意味着 MainStack
(大概是 MainTask
的堆栈)大小为 0x1000 或 4096 字节。第一列是符号名称,第二列是地址中的位置space,第三列是大小,第四列是类型(数据,代码),第五列是范围(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 字节。这需要在地图文件中搜索特定堆栈名称才能获得结果,所以我觉得这更容易。
- 如何确定ARM的RAM中栈和堆的大小?
对于这个,您需要深入研究链接器配置文件或选项中的链接器部分。更简单的方法是通过选项。转到您的项目选项,然后是左侧的链接器项。在配置选项卡下,select 编辑...,然后转到 Stack/Heap 选项卡。这将使您可以轻松访问 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
的大小由文件中前面定义的符号定义。您可以按照这些定义来获取大小。不过,您的链接器文件可能与此有很大不同,所以正如我所说,真的很难给出一个通用的答案。
- 如何确定是否需要为任务分配更多堆栈大小?
较新版本的 IAR 有一个很棒的实用程序,可以确定任何函数所需的堆栈深度。在项目选项中,在 Advanced 选项卡的 Linker 下,您可以检查 "Enable stack usage analysis"。当您启用它时,您的映射文件将包含根函数及其最大调用链。例如,我的 MainTask
看起来像这样:
Uncalled function
"MainTask" in main.o [1]: 0x0000ac41
Maximum call chain *?* 396 bytes
所以,这告诉我 MainTask 是一个未调用的函数(它不是直接调用的,而是通过函数指针调用的,IAR 无法自动解析),它需要 396 字节的堆栈。在它下面,它会向你展示总计 396 字节的调用链。
使用此工具需要注意的是,如果您使用函数指针和间接调用,IAR 无法自动找出这些指向的位置。有一组 pragma
指令可用于告诉它在间接调用点调用哪些可能的函数,您需要将它们放入以获得 100% 准确的堆栈深度。
另一种方法是 运行 硬件上的程序,但让 OS 监视堆栈溢出。 Micrium 有一个关于检测堆栈溢出的页面:Detecting Task Stack Overflows. Additionally, here is the documentation on a function to get information about a task's stack usage: OSTaskStkChk()
- 如何通过生成的 MAP 文件确定任务正在使用的堆栈大小?
- 如何确定ARM内存中栈和堆的大小
- 如何确定是否需要为任务分配更多堆栈大小?
如果您运行正在使用最新版本的 IAR EWARM,那么有一个内置工具可以帮助您解决这些问题。
- 如何通过生成的 MAP 文件确定任务正在使用的堆栈大小?
对于第一个问题,您需要在映射文件中搜索每个任务堆栈的名称。在这种情况下,地图文件没有多大帮助,因为您最好在项目中搜索 CPU_STK
类型,因为这将为您提供包含所有正确定义的堆栈的结果。如果您查看地图文件,您可能会看到这样一行:
MainStack 0x20000000 0x1000 Data Lc main.o [1]
这意味着 MainStack
(大概是 MainTask
的堆栈)大小为 0x1000 或 4096 字节。第一列是符号名称,第二列是地址中的位置space,第三列是大小,第四列是类型(数据,代码),第五列是范围(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 字节。这需要在地图文件中搜索特定堆栈名称才能获得结果,所以我觉得这更容易。
- 如何确定ARM的RAM中栈和堆的大小?
对于这个,您需要深入研究链接器配置文件或选项中的链接器部分。更简单的方法是通过选项。转到您的项目选项,然后是左侧的链接器项。在配置选项卡下,select 编辑...,然后转到 Stack/Heap 选项卡。这将使您可以轻松访问 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
的大小由文件中前面定义的符号定义。您可以按照这些定义来获取大小。不过,您的链接器文件可能与此有很大不同,所以正如我所说,真的很难给出一个通用的答案。
- 如何确定是否需要为任务分配更多堆栈大小?
较新版本的 IAR 有一个很棒的实用程序,可以确定任何函数所需的堆栈深度。在项目选项中,在 Advanced 选项卡的 Linker 下,您可以检查 "Enable stack usage analysis"。当您启用它时,您的映射文件将包含根函数及其最大调用链。例如,我的 MainTask
看起来像这样:
Uncalled function
"MainTask" in main.o [1]: 0x0000ac41
Maximum call chain *?* 396 bytes
所以,这告诉我 MainTask 是一个未调用的函数(它不是直接调用的,而是通过函数指针调用的,IAR 无法自动解析),它需要 396 字节的堆栈。在它下面,它会向你展示总计 396 字节的调用链。
使用此工具需要注意的是,如果您使用函数指针和间接调用,IAR 无法自动找出这些指向的位置。有一组 pragma
指令可用于告诉它在间接调用点调用哪些可能的函数,您需要将它们放入以获得 100% 准确的堆栈深度。
另一种方法是 运行 硬件上的程序,但让 OS 监视堆栈溢出。 Micrium 有一个关于检测堆栈溢出的页面:Detecting Task Stack Overflows. Additionally, here is the documentation on a function to get information about a task's stack usage: OSTaskStkChk()