一、背景
一般来说堆栈的使用率概念是针对于操作系统,且操作系统一般都会有响应的接口直接调用查看。如果针对裸机程序的话,堆 Heap 的概念不存在了,只有栈 Stack 在使用,所以在此是针对栈的使用率测试。
二、背景知识
栈的生长方向是从上至下的,如下图所示:
栈顶地址,可以通过生成的 map 文件
在此以 IAR 生成的 map 为例,生成方法
再 选择 rebuild all ,即可在对应的文件夹找到 map 文件 ,打开找到
可得到 Stack Top : 0x2000'2c10 ,大小为 0x1000
三、测试方法
测试逻辑:MCU 在上电初始内存中的值是随机的,从 main 函数开始执行,在进入 main 的时候 Stack 的使用率是小的,那么就可以在 这个阶段将 一部分的 Stack 空间值初始化为固定的值(0x00 或者 0xFF 等等),此时并不熟影响程序的正常运行。
所以,首先指定一个 偏移地址 ,从偏移地址到 栈底之间的全部初始化为一个固定的值,如果后续程序执行,将会主动修改这些固定的值,这样只需要找到某个地址,该地址前一个地址为非0xFF, 本地址为 0xFF, 如下所示:ADDR2 即为所求。(当然也会存在可能 程序运行时,被修改为 0xFF, 这种特殊情况暂不考虑,本质上也就相差 几个字节,对总体结果影响不大 )
void StackUsageRateTestFillInit(void)
{
while (1)
{
if ( stackCheckAddr >= (stackTopAddr-stackOffsetAddr))
{
break;
}
else
{
*(UINT8*)stackCheckAddr = 0xFF;
stackCheckAddr++;
}
}
stackCheckAddr = 0x20000000;
}
上述代码是将 图 - 4 灰色部分初始化
main 函数中调用
void StackUsageRateTest(void)
{
if ( *(UINT8*)stackCheckAddr == 0xFF )
{
stackCheckAddr++;
DEBUG(" stack addr + [ 0x%X ]", stackCheckAddr);
}
else
{
stackCheckAddr--;
DEBUG(" stack addr - [ 0x%X ]", stackCheckAddr);
}
}
int main(void)
{
// 芯片初始化
Init();
StackUsageRateTestFillInit();
while
{
StackUsageRateTest();
// other task
}
}
随着程序的运行,出现如下打印信息
那么最终可以确定,Stack Max Use 地址为 0x2000293F ,
栈深为 0x20002C10( Stack Top ) - 0x2000293F
栈的使用率为 StackMaxUse / StackTotal x 100%