liteos定时器回调时间过长造成死机问题解决思路

项目需求

原代码是稳定的,现我实现EMQ平台断开连接的时候,把HSL的模拟点位数据采集到网关,然后存入Flash,当EMQ平台连接的时候,把Flash里面的点位数据放在消息队列里面,不影响实时采集。

核心1:EMQ平台断开,保持存储稳定

核心2:不影响实时采集的前提下去把flash的数据读出来在空闲的时候发出去

核心3:进入断点续传的条件是连续5次发布失败进入断点续传

问题描述

核心1遇到了问题,就是EMQ断开20分钟左右会死机,没日志输出。

最后的日志,然后就一直在进行度队列操作,队列ID是垃圾值

初步分析

1.队列可能在使用的时候没有创建

2.队列的id存的地方被覆盖了

c 复制代码
[2024-07-24 17:20:49.179]# RECV ASCII>
[INFO][556][Plc_s7_Task:1404] RDataCnt:30,RWarnCnt:0 CDataCnt:30,CWarnCnt:0 Tol:30,elaps: 251ms
[INFO][556][getNetSignalValue:1037] EC20 Get Net Signle: "25"
[INFO][556][print_memory_usage:594] m_aucSysMem0      2000d4f8 Memory Used:5992, Free:135072, Tol:141064, MallocCnt: 21082, FreeCnt: 20964, Malloc-Free: 118
[WARN]osSwTmrTask:111 timer_handler(080540fd) cost too many ms(5995)


代码

c 复制代码
void point_timer_Callback(UINT32 arg)
{
	UINT32 uwReportRet = LOS_OK;
	UINT32 uwCollectRet = LOS_OK;
	uint16_t ep_resources[] = {RESOURCES_STATUS};
	char buff[64] = {0};
	char *buf[1] = {buff};

	LOS_SwtmrStop(point_pusSwTmrID);

    // 反写任务正在执行,跳过本次检查
    if (g_reverse_write_processing == true) {
//		 if (g_reverse_write_processing == true) {	
        //重新开启定时器,准备下一次检查
	    LOS_SwtmrStart(point_pusSwTmrID);
        return;
    }

	if (!Get_Point_Status())
	{
		LOS_SwtmrStart(point_pusSwTmrID);	
		return;
	}

	//启动上报任务
	uwReportRet = start_report_task();
	if(LOS_OK != uwReportRet)
	{	
		ATINY_LOG(LOG_ERR, "start_report_task Error!");
		stop_report_task();
	}

	//启动采集任务
	uwCollectRet = start_collect_task();
	if (LOS_OK != uwCollectRet)
	{
		ATINY_LOG(LOG_ERR, "start_collect_task Error!");
		stop_collect_task();
	}

	if (LOS_OK != uwCollectRet || LOS_OK != uwReportRet)
	{
		//检查是否绑定
		if(0 == read_resoures(LWM2M_EP_OBJECT_ID, 0, ep_resources, buf, 1, RESOURCES_POINT_SAVE_STRING_MAX))
		{
			if(0 == atoi(buf[0]))
			{
				ATINY_LOG(LOG_INFO, "Wait Bing!");
			}
			else
			{
				ATINY_LOG(LOG_INFO, "Restart Report || Collect!");
			}
		}
		else
		{
			ATINY_LOG(LOG_ERR, "File System Error, Need Clean Config & Restart!");
		}
	}

	//检查系统异常
	//TODO:是否应该独立为一个检测线程,但上报通道依赖mqtt,mqtt又和数据点采集耦合在一起。应先解耦mqtt和数据采集
	if(LOS_OK == check_report_task())
	{
		check_sys_warning();
	}

    south_report_gateway();

	print_memory_usage();

	//重新开启定时器,准备下一次检查
	LOS_SwtmrStart(point_pusSwTmrID);	
}

解决方法

080540fd 地址定位到回调函数是void point_timer_Callback(UINT32 arg)

根据日志知道是这个回调时间有点长。

那为啥不是立即死而是过了几十分钟死呢?

代码优化等级从2调为0,进一步调试

c 复制代码
LOS_SwtmrStop(point_pusSwTmrID);

他知道他自己耗时还在函数这里把定时器关了,怒。那为啥会调试的时候死在读队列(队列操作)里面呢?因为定时器的回调函数其实都是存在定时器回调队列里面的,如果一个回调过长,因为定时器的回调优先级0,其他高优先级任务都执行不下去。在实时性操作系统里会紊乱系统,加上屎山代码,就会死机。所以在liteos这种系统里面,多加日志输出,不可完全信调试。调试只是一瞬间的观察,调试可以判断这一段时间进而想一下自己的改动点和日志做分析得出怀疑点。

上面判断条件

c 复制代码
if (g_reverse_write_processing == true )

改为

c 复制代码
if (g_reverse_write_processing == true || BreakPoint_State == BreakPointSaveOnline)

OK,不要动不动在回调函数写耗时操作,一两次可能没问题,但是一直进行回调的话,会造成奇怪的紊乱。

相关推荐
NineData1 小时前
数据库迁移总踩坑?用 NineData 迁移评估,提前识别所有兼容性风险
数据库·程序员·云计算
赵渝强老师3 小时前
【赵渝强老师】PostgreSQL中表的碎片
数据库·postgresql
全栈老石7 小时前
拆解低代码引擎核心:元数据驱动的"万能表"架构
数据库·低代码
倔强的石头_1 天前
kingbase备份与恢复实战(二)—— sys_dump库级逻辑备份与恢复(Windows详细步骤)
数据库
jiayou642 天前
KingbaseES 实战:深度解析数据库对象访问权限管理
数据库
李广坤3 天前
MySQL 大表字段变更实践(改名 + 改类型 + 改长度)
数据库
爱可生开源社区4 天前
2026 年,优秀的 DBA 需要具备哪些素质?
数据库·人工智能·dba
随逸1774 天前
《从零搭建NestJS项目》
数据库·typescript
加号35 天前
windows系统下mysql多源数据库同步部署
数据库·windows·mysql
シ風箏5 天前
MySQL【部署 04】Docker部署 MySQL8.0.32 版本(网盘镜像及启动命令分享)
数据库·mysql·docker