uCos移植中进入HardFault_Handler问题

项目场景:

最近使用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));   //添加数据,发布给服务器
}

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

/*-------------------------------------------------*/
/*函数名:定时器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溢出中断标志 	
	}
}

原因分析:

此处是有两个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);
	}
}

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

__align(8) static  CPU_STK  Task8_Stk[TASK8_STK_SIZE];

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

posted @ 2020-12-20 12:27  JeckXu666  阅读(172)  评论(0编辑  收藏  举报