uCos移植中进入HardFault_Handler问题
【摘要】
项目场景:
最近使用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)