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

相关推荐
珠***格15 分钟前
通信链路全打通:西格电力四可装置的 4G/5G + 加密认证技术详解
大数据·数据库·分布式·5g·架构·能源
盗理者15 分钟前
AI Agent 技能分享|从零实现 MCP Server,让 Agent 安全读取数据库
数据库·oracle
xqqxqxxq1 小时前
Redis 五大常用数据类型 + 通用命令笔记
数据库·redis·笔记
l1t1 小时前
DeepSeek总结的在 pg_stat_statements 中诊断高基数工作负载
数据库·缓存·postgresql
国科安芯1 小时前
详解ADC 规则组外部触发:CH2、CH3 与 TRGO2
运维·网络·单片机·嵌入式硬件·mcu·系统架构
神奇霸王龙2 小时前
Agentic RAG 双硬门屠夫:5 旗舰实测
数据库·人工智能·ai·agent·ai编程·ai写作·rag
ACP广源盛139246256732 小时前
WAIC2026 国产算力浪潮@ACP#YLB3118 在算力矩阵中的存储定位与落地场景
大数据·人工智能·分布式·单片机·嵌入式硬件
ACP广源盛139246256732 小时前
WAIC2026 国产算力浪潮下@ACP#IX8024 在算力矩阵中的定位与落地场景
大数据·数据库·人工智能·嵌入式硬件·线性代数·矩阵
snow@li2 小时前
MySQL:库表设计完整规范与实战方案
数据库·mysql
ClouGence2 小时前
数据库管理工具 CloudDM 4.1.0 发布,支持达梦、Cloudberry
数据库·开源