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

项目场景:

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

问题描述:

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

1
2
3
4
5
6
7
8
9
10
11
12
13
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
/*-------------------------------------------------*/
/*函数名:定时器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,定时器中断里面处理数据或者较大的任务,使用软件定时器来处理,软件定时器处理任务分配了固定的堆栈,调用时创建局部变量不会被改变,或者直接放在一个普通任务立面,阻塞延时对应的事件就行。比如下面改过的代码:

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
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) 就行:

1
__align(8) static  CPU_STK  Task8_Stk[TASK8_STK_SIZE];

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