uCos移植中进入HardFault_Handler问题

举报
JeckXu666 发表于 2022/01/15 22:49:00 2022/01/15
【摘要】 项目场景: 最近使用ucos做一个比赛,移植esp8266到ucos上,裸机测试代码一切正常,但移植后就出现了问题 问题描述: ucos调用esp8266发送时代码总是进入hard fault死...

项目场景:

最近使用ucos做一个比赛,移植esp8266到ucos上,裸机测试代码一切正常,但移植后就出现了问题


问题描述:

ucos调用esp8266发送时代码总是进入hard fault死循环之中,仿真发现每次报错,同时调用了该函数printf函数内部分数据,发现数据与预想的不同,程序如下

void TempHumi_State(void)
{
	u8 tempdata,humidata;	
	char temp[256];  
	
	DHT11_Read_Data(&tempdata,&humidata);	//读取温湿度值	
	//	AHT10_Data(&tempdata,&humidata);
	u1_printf("温度:%d  湿度:%d\r\n",tempdata,humidata);

	sprintf(temp,"{\"method\":\"thing.event.property.post\",\"id\":\"203302322\",\"params\":		    {\"CuTemperature\":%2d,\"CurrentHumidity\":%2d},\"version\":\"1.0.0\"}",tempdata,humidata);  //构建回复湿度温度数据
	
	MQTT_PublishQs0(P_TOPIC_NAME,temp,strlen(temp));   //添加数据,发布给服务器
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

程序调用位置:在定时器二中断中调用:

/*-------------------------------------------------*/
/*函数名:定时器2中断服务函数                      */
/*参  数:无                                       */
/*返回值:无                                       */
/*-------------------------------------------------*/
void TIM2_IRQHandler(void)
{	
	if(TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET){  //如果TIM_IT_Update置位,表示TIM2溢出中断,进入if	
		TempHumi_State();
		TIM_ClearITPendingBit(TIM2, TIM_IT_Update);     //清除TIM2溢出中断标志 	
	}
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

原因分析:

此处是有两个bug,sprintf这个问题挺容易解决的,只要定位到错误的位置,百度一下,分分钟就能解决了,但第二个数据与预想的值不一样我花了较长时间解决,问题分析如下。

首先我找问题是在仿真中设置断点,用二分法逐渐确定hardware错误地址,这一步有更简单的方式,通过地址查询报错地址,我还没详细了解过
下面是第一个bug

  • 程序每次在到sprintf之后函数就跑飞了,这里的原因是因为sprintf处理数据是需要8字节对齐的,而ucos里面任务堆栈分配如果在初始化中没有声明的时候,默认是不对齐的,运行到这就会报错,同时要注意sprintf需要的内存很大,使用时一定要预留足够大的空间

第二个bug:

  • 我在移植程序的时候,对应的程序是在定时器中断里面执行操作的,1s处理一次,当时因为偷懒,直接将中断移植到UCOS里面,简单的加上一个现场保护就直接使用了,这就导致了问题的出现,中断中调用了一个子程序,子程序创建了一个较大的内存空间,但在程序执行中程序有进入新的中断,新中断也有局部变量的创建,两者之间内存重叠,导致问题的出现,变量的值被改变,得到的结果和期望值不同,发送错误。

解决方案:

先解决第二个bug,定时器中断里面处理数据或者较大的任务,使用软件定时器来处理,软件定时器处理任务分配了固定的堆栈,调用时创建局部变量不会被改变,或者直接放在一个普通任务立面,阻塞延时对应的事件就行。比如下面改过的代码:

static  void  Task8 (void *p_arg)
{
	
  (void)p_arg; 
	while(1)
	{
		OS_ERR err;
		OS_MSG_SIZE msg_size2;
		u8 *TEXT_Buffer2;
		char *dat; 
		u16 data_pack[5];
		
		dat=	mymalloc(SRAMIN,2*1024);

		TEXT_Buffer2 = OSQPend ((OS_Q         *)&messg2,               
									(OS_TICK       )0,                   
									(OS_OPT        )OS_OPT_PEND_BLOCKING,  //如果没有获取到信号量就等待
									(OS_MSG_SIZE  *)&msg_size2,          
									(CPU_TS       *)0,                     
									(OS_ERR       *)&err); 
		
		data_pack[0]=(TEXT_Buffer2[0]+((TEXT_Buffer2[1])<<8));
		data_pack[1]=(TEXT_Buffer2[2]+((TEXT_Buffer2[3])<<8));
		data_pack[2]=(TEXT_Buffer2[4]+((TEXT_Buffer2[5])<<8));
		sprintf(dat,"{\"method\":\"thing.event.property.post\",\"id\":\"203302322\",\"params\":{\"state\":%d,\"youwei\":%.2f,\"carInsideTemp\":%.1f,\"speed\":%.2f,\"interiorLightOnOff\":%d,\"nightLight\":%d},\"version\":\"1.0.0\"}",(u16)run_sta,((float)data_pack[0]/100.0),(float)data_pack[2]/10,((float)data_pack[1]/100.0),TEXT_Buffer2[6],TEXT_Buffer2[7]);
		MQTT_PublishQs0(P_TOPIC_NAME,dat,strlen(dat));   //添加数据,发布给服务器	
		
		myfree(SRAMIN,dat);

		delay_ms(2000);
	}
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32

第一个bug是在把数据发送放在任务中出现的,这时只要给对应的任务堆栈前面加上强行8位对齐语句 __align(8) 就行:

__align(8) static  CPU_STK  Task8_Stk[TASK8_STK_SIZE];

  
 
  • 1

我的任务是TASK8 所以给8的堆栈强行对齐,之后所有bug就解决了!

文章来源: blog.csdn.net,作者:JeckXu666,版权归原作者所有,如需转载,请联系作者。

原文链接:blog.csdn.net/qq_45396672/article/details/111414074

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。