[MCU] ARM MCU检测堆栈用量的方法

[复制链接]
 楼主| aple0807 发表于 2021-11-3 13:49 | 显示全部楼层 |阅读模式
分享一个测试工程项目堆栈使用量的方法。
通常由于担心堆栈溢出,我们会给系统配置一个很大的堆栈空间,这样往往会挤占APP部分RAM用量,造成资源浪费,这种情况在小容量MCU中特别明显。如果堆栈实际用量已知,我们可以留一定裕量即可,也无需再担心分配的堆栈是否足够。

下面介绍具体的方法
==================================================================================================================================
首先定义中断向量表位置和堆栈大小。
向量表位置一般是ROM区首地址,实际项目有变动应保持一直。堆栈大小和启动文件中的stack_size值应相同。
  1. /*******************************************************************************
  2. * stack infomation
  3. *******************************************************************************/
  4. #define VECT_ADDR                                0x8000000
  5. #define STACK_SIZE                                0x400


初始化:必须在main()函数内的首行调用。用于给堆栈内存添加水印。
  1. /*******************************************************************************
  2. * mem_clr define
  3. * \param[in] none
  4. * \retval: none
  5. *******************************************************************************/
  6. #define mem_clr(base, size, val)    \
  7.     pdata = (uint32_t*)(base);      \
  8.     Len = (size)/4;                 \
  9.     while(Len--)                    \
  10.     {                               \
  11.         *pdata++ = val;             \
  12.     }                               \

  13. #define inpw(port)                (*((volatile unsigned long *)(port)))

  14. /*******************************************************************************
  15. * stack init, keil 进入mian时,SP=Vect[0]
  16. * \param[in] none
  17. * \retval: none
  18. *******************************************************************************/
  19. void stack_init(void)
  20. {
  21.          volatile  uint32_t * pdata;
  22.         register uint32_t Len;
  23.         register uint32_t addr;
  24.         
  25.         // stack
  26.         addr = inpw(VECT_ADDR) - STACK_SIZE;
  27.         mem_clr(addr, STACK_SIZE - 0x20, 0xEFEFEFEF);
  28. }



检测已用STACK。原理是检测堆栈初始化时的水印是否被破坏,以此来判定STACK最大使用量。
返回一个千分数。
可以在任意位置调用查看。
  1. /*******************************************************************************
  2. * stack_used
  3. * \param[in] none
  4. * \retval:  千分数
  5. *******************************************************************************/
  6. uint16_t stack_used(void)
  7. {
  8.         uint32_t unused = 0;
  9.         uint32_t * pdata;
  10.         register uint32_t ofsset;
  11.         register uint32_t addr;
  12.         
  13.         addr = inpw(VECT_ADDR) - STACK_SIZE;
  14.         pdata = (uint32_t *)addr;
  15.                
  16.         for(ofsset =0; ofsset < STACK_SIZE; ofsset+=4)
  17.         {
  18.                 if(0xEFEFEFEF == *pdata++)
  19.                 {
  20.                         unused += 4;
  21.                 }
  22.                 else
  23.                 {
  24.                         break;
  25.                 }
  26.         }
  27.         
  28.         return         (1000 - unused * 1000 / STACK_SIZE);
  29. }





  
您需要登录后才可以回帖 登录 | 注册

本版积分规则

77

主题

326

帖子

2

粉丝
快速回复 在线客服 返回列表 返回顶部