ucos ii堆栈大小检测

在使用ucos ii时经常会有疑问,这个堆栈该给多大,虽然ucos ii 自带了任务堆栈检测,但是我觉得太麻烦了,而且还会占用资源,我投机取巧的使用内存是否为0来判断堆栈是否使用过,进而检测出堆栈的最大使用量,我的这个方法能快速的检测出历史堆栈的最大使用量,你的实际堆栈大小必须大于历史最大使用量。

原理就是将任务堆栈使用static标记,这样任务堆栈数组都会被清零,使用过程中随着数据入栈(变为非0了,全部入栈都是0的可能性微乎其微),然后数据虽然出栈了,但是并没有清零(也没必要),通过从栈底找到第一个非0的地方(就是被使用过),这样就类似水库中的水在墙壁上留下的印记,就知道历史最高水位一样,通过这个方法可以获取ucos ii的最大堆栈消耗甚至可以知道系统的最大堆栈消耗,通过长期的运行,获取到系统的最大堆栈占用量,能够合理的给每个任务分配堆栈大小。

/*************************************************************************************************************
 * 文件名:			TaskStackMonitor.c
 * 功能:			UCOS II 任务堆栈监视
 * 作者:			[email protected]
 * 创建时间:		2019-01-25
 * 最后修改时间:	2019-01-25
 * 详细:			在最低优先级任务中进行调用,会监控所有任务的堆栈使用量,并记录最大值,最小值,同时记录CPU的最大与最小使用量
					通过监测足够长的时间,可以保证任务堆栈的合理性
					2019-01-28:增加CPU监控显示,增加socket状态显示
*************************************************************************************************************/
#include "system.h"
#include "usart.h"
#include "main.h"
#include "string.h"
#include "board.h"
#include "rtc.h"
#include "wdg.h"
#include "board.h"
#include "w5500_socket.h"

//从堆栈底部往上找到第一个非0位置,返回偏移:字
u32 FindFirstNonzeroPosition(u32 *pStackBottom, u32 StackSize);


//线程状态监控
void TaskStackMonitor(void)
{
	u32 i;
	u32 StackBottomAddr;	//栈底地址
	u32 StackResidual;		//堆栈剩余
	
	uart_printf("\r\n----------------任务状态----------------\r\n");
	for(i = 0;i < sizeof(cg_TaskBuff)/sizeof(TASK_STACK_INFO);i ++)
	{
		StackBottomAddr = cg_TaskBuff[i].StackTopAddr+4;// - (cg_TaskBuff[i].StackSize*4) + 4;					//计算栈底地址
		StackResidual = FindFirstNonzeroPosition((u32 *)StackBottomAddr, cg_TaskBuff[i].StackSize);			//计算使用量
		uart_printf("任务%d,堆栈剩余:%d,使用量:%%%d\r\n", cg_TaskBuff[i].Proi, StackResidual, (cg_TaskBuff[i].StackSize-StackResidual)*100/cg_TaskBuff[i].StackSize);
	}
	uart_printf("CPU占用率:%%%d\r\n", OSCPUUsage);
	//PrintfSocketsStatus();			//调试打印socket状态
}


//从堆栈底部往上找到第一个非0位置,返回偏移:字
u32 FindFirstNonzeroPosition(u32 *pStackBottom, u32 StackSize)
{
	u32 i = 0;
	
	for(i = 0;i < StackSize;i ++)
	{
		if(pStackBottom[i] != 0) break;		
	}
	
	return i;
}

/*************************************************************************************************************
 * 文件名:			TaskStackMonitor.h
 * 功能:			UCOS II 任务堆栈监视
 * 作者:			[email protected]
 * 创建时间:		2019-01-25
 * 最后修改时间:	2019-01-25
 * 详细:			在最低优先级任务中进行调用,会监控所有任务的堆栈使用量,并记录最大值,最小值,同时记录CPU的最大与最小使用量
					通过监测足够长的时间,可以保证任务堆栈的合理性
*************************************************************************************************************/
#ifndef __TASK_STACK_MONITOR_H__
#define __TASK_STACK_MONITOR_H__

#include "system.h"
#include "ucos_ii.h"
#include "rtc.h"
#include "board.h"
#include "RTU.h"


//任务堆栈信息
typedef struct
{
	u32  StackTopAddr;		//任务栈顶地址(注意:堆栈为向下生长)
	u32	 StackSize;			//任务堆栈大小(单位:CPU字长,STM32为4字节,32bit)
	u8	 Proi;				//任务的优先级
}TASK_STACK_INFO;


void TaskStackMonitor(void);//任务堆栈监视

#endif	//__TASK_STACK_MONITOR_H__

//任务堆栈指针相关的数组,放进去就可以了

//任务堆栈声明
static OS_STK	TASK_MODBUS1_STK[MODBUS1_STK_SIZE];				//MODBUS 通信线程1
static OS_STK	TASK_MODBUS2_STK[MODBUS2_STK_SIZE];				//MODBUS 通信线程2
static OS_STK	TASK_MODBUS3_STK[MODBUS3_STK_SIZE];				//MODBUS 通信线程3 -扩展的TTL串口
static __align(8) OS_STK	TASK_SYSTEM_STK[SYSTEM_STK_SIZE];	//系统主进程
static OS_STK	TASK_GPRS_STK[GPRS_STK_SIZE];					//GPRS进程
static OS_STK	TASK_BACK_STK[BACK_STK_SIZE];					//BACK进程
static OS_STK	TASK_ASSIST_STK[ASSIST_STK_SIZE];				//ASSIST进程
static OS_STK	TASK_COLL_STK[COLL_STK_SIZE];					//数据采集时间查询进程
static OS_STK	TASK_KEY_STK[KEY_STK_SIZE];						//按钮查询进程
static OS_STK	TASK_DEBUG_STK[DEBUG_STK_SIZE];					//DEBUG进程
static OS_STK	TASK_W5500_STK[W5500_STK_SIZE];					//W5500进程
static OS_STK	TASK_OVERLAY_STK[OVERLAY_STK_SIZE];				//视频叠加进程
static OS_STK	TASK_SERVER_STK[SERVER_STK_SIZE];				//UDP Server服务器


//任务记录
const TASK_STACK_INFO cg_TaskBuff[13] = 
{
	{(u32)TASK_MODBUS1_STK, MODBUS1_STK_SIZE, MODBUS1_TASK_Prio},	
	{(u32)TASK_MODBUS2_STK, MODBUS2_STK_SIZE, MODBUS2_TASK_Prio},	
	{(u32)TASK_MODBUS3_STK, MODBUS3_STK_SIZE, MODBUS3_TASK_Prio},	
	{(u32)TASK_SYSTEM_STK, SYSTEM_STK_SIZE, SYSTEM_TASK_Prio},	
	{(u32)TASK_GPRS_STK, GPRS_STK_SIZE, GPRS_TASK_Prio},	
	{(u32)TASK_BACK_STK, BACK_STK_SIZE, BACK_TASK_Prio},	
	{(u32)TASK_COLL_STK, ASSIST_STK_SIZE, ASSIST_TASK_Prio},
	{(u32)TASK_COLL_STK, COLL_STK_SIZE, COLL_TASK_Prio},	
	{(u32)TASK_KEY_STK, KEY_STK_SIZE, KEY_TASK_Prio},	
	{(u32)TASK_DEBUG_STK, DEBUG_STK_SIZE, DEBUG_TASK_Prio},	
	{(u32)TASK_W5500_STK, W5500_STK_SIZE, W5500_TASK_Prio},
	{(u32)TASK_OVERLAY_STK, OVERLAY_STK_SIZE, OVERLAY_TASK_Prio},
	{(u32)TASK_SERVER_STK, SERVER_STK_SIZE, SERVER_TASK_Prio},
};

//使用

TaskStackMonitor();	//任务堆栈监视

运行时间越久,这个越准,因为堆栈的占用是动态的,随着你的代码逻辑会变化。

//最终结果

发布了143 篇原创文章 · 获赞 370 · 访问量 81万+

猜你喜欢

转载自blog.csdn.net/cp1300/article/details/86680895
今日推荐