OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 9010|回复: 17

使用 FreeRTOS 任务执行一次就挂了 ,请教各位帮忙分析

[复制链接]

7

主题

60

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
299
金钱
299
注册时间
2015-10-21
在线时间
52 小时
发表于 2017-8-25 18:25:21 | 显示全部楼层 |阅读模式
本帖最后由 打洞者 于 2017-8-25 18:34 编辑

[mw_shl_code=c,true]

#include "includes.h"

/*
**********************************************************************************************************
                                                                                        函数声明
**********************************************************************************************************
*/
static void vTaskTaskUserIF(void *pvParameters);
static void vTaskLED(void *pvParameters);
static void AppTaskCreate (void);

/*
**********************************************************************************************************
                                                                                        变量声明
**********************************************************************************************************
*/
static TaskHandle_t xHandleTaskUserIF = NULL;
static TaskHandle_t xHandleTaskLED = NULL;

/*
*********************************************************************************************************
*        函 数 名: main
*        功能说明: 标准c程序入口。
*        形    参:无
*        返 回 值: 无
*********************************************************************************************************
*/

u8 *str = (u8*)"我就是esp8266!\n";

int main(void)
{
        
        /* 硬件初始化 */
        bsp_Init();

        /* 关闭全局中断 */
        __set_PRIMASK(1);
  
       /* 创建任务 */
        AppTaskCreate();
        
       /* 启动调度,开始执行任务 */
       vTaskStartScheduler();


        while(1)
        {


        };
}

/*
*********************************************************************************************************
*        函 数 名: vTaskTaskUserIF
*        功能说明: 接口消息处理,这里用作LED闪烁        
*        形    参: pvParameters 是在创建该任务时传递的形参
*        返 回 值: 无
*********************************************************************************************************
*/
static void vTaskTaskUserIF(void *pvParameters)
{
    while(1)
    {
                bsp_LedToggle(1);
                        
                esp8266_apsta_test(str);  //esp8266发送数据
               
                vTaskDelay(500);
        }
}

/*
*********************************************************************************************************
*        函 数 名: vTaskLED
*        功能说明: LED闪烁        
*        形    参: pvParameters 是在创建该任务时传递的形参
*        返 回 值: 无
*   优 先 级: 2  
*********************************************************************************************************
*/
static void vTaskLED(void *pvParameters)
{
    while(1)
    {
                bsp_LedToggle(2);
                vTaskDelay(200);
    }
}

/*
*********************************************************************************************************
*        函 数 名: AppTaskCreate
*        功能说明: 创建应用任务
*        形    参:无
*        返 回 值: 无
*********************************************************************************************************
*/
static void AppTaskCreate (void)
{
    xTaskCreate( vTaskTaskUserIF,           /* 任务函数  */
                 "vTaskUserIF",             /* 任务名    */
                 512,                       /* 任务栈大小,单位word,也就是4字节 */
                 NULL,                      /* 任务参数  */
                 4,                         /* 任务优先级*/
                 &xHandleTaskUserIF );  /* 任务句柄  */
        
        
        xTaskCreate( vTaskLED,                    /* 任务函数  */
                 "vTaskLED",                  /* 任务名    */
                 512,                         /* 任务栈大小,单位word,也就是4字节 */
                 NULL,                        /* 任务参数  */
                 2,                           /* 任务优先级*/
                 &xHandleTaskLED ); /* 任务句柄  */

        __set_PRIMASK(0);   //开启全局中断
}


[/mw_shl_code]
[mw_shl_code=c,true]void esp8266_apsta_test(u8 *p)
{
        while(esp8266_send_cmd("AT+CIPSEND=15",">",20));//send a fixed-length data
        esp8266_send_data(p,"SEND OK",200);
}[/mw_shl_code]


【问题描述】

问题出在第 68 行代码  esp8266_apsta_test(str);
工程中未加入 该函数,即未加入函数 esp8266_apsta_test(str) 到 vTaskTaskUserIF() 或 vTaskLED() 任务中

                1)整个工程运行正常, LED 闪烁。


      2.将函数 esp8266_apsta_test(str) 放入 vTaskTaskUserIF() 或 vTaskLED() 任务中

                1)把任务延时函数 vTaskDelay(n) 注释掉,则该函数所在任务运行正常,其他任务不执行。不论 vTaskTaskUserIF() 或 vTaskLED()
                     哪个优先级高哪个低,但调试结果是高优先级任务并未打断低优先级任务而执行。

                2)不注释任务延时函数 vTaskDelayt(n),从调试结果看所有的任务包括空闲任务依次执行一遍,然后系统就挂了。

【分析】

由未加入函数 esp8266_apsta_test(str) 前调试结果,LED 闪烁工作正常,说明操作系统任务切换无问题
由加入函数 esp8266_apsta_test(str) 后调试结果,推出函数 esp8266_apsta_test(str) 所在任务空间足够或系统栈空间不够



【已采取的解决办法】

改变栈空间大小,系统栈和任务栈改变均无作用,结果依旧



正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

120

主题

7877

帖子

13

精华

资深版主

Rank: 8Rank: 8

积分
12010
金钱
12010
注册时间
2013-9-10
在线时间
427 小时
发表于 2017-8-26 19:52:30 | 显示全部楼层
打洞者 发表于 2017-8-26 16:42
esp8266_apsta_test(str)函数内没有关闭全局中断的语句,单步调试该函数是执行完毕后,执行下一句延时函 ...

esp8266_apsta_test这个函数代码发看下
现在,程序把烂铜烂铁变得智能化了,人呢,一旦离开了这烂铜烂铁就不知道干啥了
回复 支持 0 反对 1

使用道具 举报

120

主题

7877

帖子

13

精华

资深版主

Rank: 8Rank: 8

积分
12010
金钱
12010
注册时间
2013-9-10
在线时间
427 小时
发表于 2017-8-26 12:11:03 | 显示全部楼层
1、打开INCLUDE_uxTaskGetStackHighWaterMark宏定义(FreeRTOS.h文件中),看下highwater值是多少,堆栈空间要够
2、esp8266_apsta_test(str)函数中是否有关闭全局中断的语句?或者占用CPU时间过长的操作
现在,程序把烂铜烂铁变得智能化了,人呢,一旦离开了这烂铜烂铁就不知道干啥了
回复 支持 反对

使用道具 举报

8

主题

28

帖子

0

精华

初级会员

Rank: 2

积分
134
金钱
134
注册时间
2013-9-25
在线时间
21 小时
发表于 2017-8-26 16:26:06 | 显示全部楼层
跟踪一下函数esp8266_apsta_test(str);  //esp8266发送数据,看看是否被阻塞住,不能向下执行
回复 支持 反对

使用道具 举报

7

主题

60

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
299
金钱
299
注册时间
2015-10-21
在线时间
52 小时
 楼主| 发表于 2017-8-26 16:40:39 | 显示全部楼层
似水流年 发表于 2017-8-26 16:26
跟踪一下函数esp8266_apsta_test(str);  //esp8266发送数据,看看是否被阻塞住,不能向下执行

没有阻塞语句,该函数执行完毕,执行到下一句延时函数内就挂了
回复 支持 反对

使用道具 举报

7

主题

60

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
299
金钱
299
注册时间
2015-10-21
在线时间
52 小时
 楼主| 发表于 2017-8-26 16:42:26 | 显示全部楼层
八度空间 发表于 2017-8-26 12:11
1、打开INCLUDE_uxTaskGetStackHighWaterMark宏定义(FreeRTOS.h文件中),看下highwater值是多少,堆栈空 ...

esp8266_apsta_test(str)函数内没有关闭全局中断的语句,单步调试该函数是执行完毕后,执行下一句延时函数后挂了
回复 支持 反对

使用道具 举报

7

主题

60

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
299
金钱
299
注册时间
2015-10-21
在线时间
52 小时
 楼主| 发表于 2017-8-28 09:45:48 | 显示全部楼层
本帖最后由 打洞者 于 2017-8-28 09:52 编辑
八度空间 发表于 2017-8-26 19:52
esp8266_apsta_test这个函数代码发看下

[mw_shl_code=c,true]/**
*        @brief : esp8266 APSTA-mode test
*        @param : to send data
*        @retval: none
**/
void esp8266_apsta_test(u8 *p)
{
        while(esp8266_send_cmd("AT+CIPSEND=15",">",200));//send a fixed-length data
        esp8266_send_data(p,"SEND OK",200);
}

/**
*        @brief : to esp8266 send command
*        @param : cmd        : to send cmd
*                       ack         :expected ack
*                       waitime   :wait time (unit:10ms)
*        @retval: 0:success        (get expected ack)
*                     1:failure        (overtime return)
**/
u8 esp8266_send_cmd(u8 *cmd,u8 *ack,u16 waitime)
{
        u8 res=0;
        USART1_RX_STA=0;
        u1_printf("%s\r\n",cmd);
        if(ack&&waitime)
        {
                while(--waitime)
                {
                        delay_ms(10);
                        if(USART1_RX_STA&0x8000)        //receive a time data
                        {
                                if(esp8266_check_cmd(ack))break;        //get expected ack
                                USART1_RX_STA=0;
                        }
                }
                if(waitime==0)res=1;
        }
        return res;
}

/**
*        @brief : check received ack after send cmd
*        @param : none
*        @retval: 0:success
*                     1:failure
**/
u8* esp8266_check_cmd(u8 *str)
{
        char *strx = 0;
        if(USART1_RX_STA&0x8000)                //receive a time data
        {
                USART1_RX_BUF[USART1_RX_STA&0x7FFF]=0;//add end char
                strx=strstr((const char*)USART1_RX_BUF,(const char*)str);
        }
        return (u8*)strx;
}

/**
*        @brief : to esp8266 send data
*        @param : cmd        :to send data
*                       ack         :expected ack
*                       waitime   :wait time (unit:10ms)
*        @retval: 0:success        (get expected ack)
*                     1:failure        (overtime return)
**/
u8 esp8266_send_data(u8 *data,u8 *ack,u16 waitime)
{
        u8 res=0;
        USART1_RX_STA=0;
        u1_printf("%s",data);
        if(ack&&waitime)
        {
                while(--waitime)
                {
                        delay_ms(10);
                        if(USART1_RX_STA&0x8000)        //receive a time data
                        {
                                if(esp8266_check_cmd(ack))break;        //get expected ack
                                USART1_RX_STA=0;
                        }
                }
                if(waitime==0)res=1;
        }
        return res;
}
[/mw_shl_code]
回复 支持 反对

使用道具 举报

120

主题

7877

帖子

13

精华

资深版主

Rank: 8Rank: 8

积分
12010
金钱
12010
注册时间
2013-9-10
在线时间
427 小时
发表于 2017-8-28 12:42:36 | 显示全部楼层
打洞者 发表于 2017-8-28 09:45
[mw_shl_code=c,true]/**
*        @brief : esp8266 APSTA-mode test
*        @param : to send da ...

while()这样的死等,建议弄个超时进去,不然出不来就完蛋了
现在,程序把烂铜烂铁变得智能化了,人呢,一旦离开了这烂铜烂铁就不知道干啥了
回复 支持 反对

使用道具 举报

7

主题

60

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
299
金钱
299
注册时间
2015-10-21
在线时间
52 小时
 楼主| 发表于 2017-8-28 16:41:09 | 显示全部楼层
八度空间 发表于 2017-8-28 12:42
while()这样的死等,建议弄个超时进去,不然出不来就完蛋了

一般是不能死等,但我的目的就是要将数据发送出去,如果未收到正确的响应,执行到下一句没有任何意义,所以此处必须要死等。
回复 支持 反对

使用道具 举报

7

主题

60

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
299
金钱
299
注册时间
2015-10-21
在线时间
52 小时
 楼主| 发表于 2017-8-28 17:06:03 | 显示全部楼层
八度空间 发表于 2017-8-28 12:42
while()这样的死等,建议弄个超时进去,不然出不来就完蛋了

刚刚调试发现,在空闲任务中加入了打印函数,显示用户任务执行完一遍后,系统就一直待在了空闲任务,不停的打印提示信息

我将任务中的函数 esp8266_apsta_test(str) 放入临界段中,结果系统卡死在 while(esp8266_send_cmd("AT+CIPSEND=15",">",200)),同样的工程我移植 RTXOS 结果与 FreeRTOS 版本的一致,但在 RTXOS 版本中加入临界段任务锁,问题解决,经连续测试 1小时工作正常。
[mw_shl_code=c,true]static void vTaskTaskUserIF(void *pvParameters)
{
       
    while(1)
    {
                bsp_LedToggle(1);
               
                taskENTER_CRITICAL();

                esp8266_apsta_test(str);

                taskEXIT_CRITICAL();
               
                vTaskDelay(500);
        }
}[/mw_shl_code]
回复 支持 反对

使用道具 举报

120

主题

7877

帖子

13

精华

资深版主

Rank: 8Rank: 8

积分
12010
金钱
12010
注册时间
2013-9-10
在线时间
427 小时
发表于 2017-8-28 17:32:48 | 显示全部楼层
打洞者 发表于 2017-8-28 16:41
一般是不能死等,但我的目的就是要将数据发送出去,如果未收到正确的响应,执行到下一句没有任何意义,所 ...

你不能做重发啊,超过一定次数就认为失败,不然死等,在多任务中绝对死翘翘
现在,程序把烂铜烂铁变得智能化了,人呢,一旦离开了这烂铜烂铁就不知道干啥了
回复 支持 反对

使用道具 举报

120

主题

7877

帖子

13

精华

资深版主

Rank: 8Rank: 8

积分
12010
金钱
12010
注册时间
2013-9-10
在线时间
427 小时
发表于 2017-8-28 17:33:40 | 显示全部楼层
打洞者 发表于 2017-8-28 17:06
刚刚调试发现,在空闲任务中加入了打印函数,显示用户任务执行完一遍后,系统就一直待在了空闲任务,不停 ...

我目前在跑FreeRTOS
现在,程序把烂铜烂铁变得智能化了,人呢,一旦离开了这烂铜烂铁就不知道干啥了
回复 支持 反对

使用道具 举报

7

主题

60

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
299
金钱
299
注册时间
2015-10-21
在线时间
52 小时
 楼主| 发表于 2017-8-28 17:36:35 | 显示全部楼层
本帖最后由 打洞者 于 2017-8-28 17:38 编辑
八度空间 发表于 2017-8-26 19:52
esp8266_apsta_test这个函数代码发看下

将 main() 函数中有关任务的代码都注释掉,单独测试工程下的 esp8266_apsta_test(str) 函数,运行正常
[mw_shl_code=c,true]int main(void)
{         
        /* 硬件初始化 */
        bsp_Init();
        
        /* 打开全局中断 */
        __set_PRIMASK(0);  
        
//        AppTaskCreate();
        

//      vTaskStartScheduler();

        
        while(1)
        {

                bsp_LedToggle(1);               
                        
                esp8266_apsta_test(str);                 
               
                delay_ms(500);

        }[/mw_shl_code]
QQ拼音截图未命名00.png


回复 支持 反对

使用道具 举报

7

主题

60

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
299
金钱
299
注册时间
2015-10-21
在线时间
52 小时
 楼主| 发表于 2017-8-28 17:45:04 | 显示全部楼层
八度空间 发表于 2017-8-28 17:32
你不能做重发啊,超过一定次数就认为失败,不然死等,在多任务中绝对死翘翘

发送命令函数 u8 esp8266_send_cmd(u8 *cmd,u8 *ack,u16 waitime)  最后一个参数就防止死等而设置最大等待时长,我工程中写的是 200 也就是 2s,意思就是超过 2s后,本次放弃等下次继续请求。
回复 支持 反对

使用道具 举报

120

主题

7877

帖子

13

精华

资深版主

Rank: 8Rank: 8

积分
12010
金钱
12010
注册时间
2013-9-10
在线时间
427 小时
发表于 2017-8-28 17:48:28 | 显示全部楼层
打洞者 发表于 2017-8-28 17:36
将 main() 函数中有关任务的代码都注释掉,单独测试工程下的 esp8266_apsta_test(str) 函数,运行正常
[ ...

硬件接口初始化完成后,用事件标志组做等待,全部任务的接口都初始化完成,才进入whlie循环去下图是我的做法
QQ截图20170828173929.png
每一个任务在进入while之前都有这个,保证所有的硬件接口都初始化完成后才真正的跑任务的内容,这样可以避免一些由于其他硬件没准备好的情况而出现错误或者死机的现象
现在,程序把烂铜烂铁变得智能化了,人呢,一旦离开了这烂铜烂铁就不知道干啥了
回复 支持 反对

使用道具 举报

7

主题

60

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
299
金钱
299
注册时间
2015-10-21
在线时间
52 小时
 楼主| 发表于 2017-8-28 17:53:31 | 显示全部楼层
八度空间 发表于 2017-8-28 17:48
硬件接口初始化完成后,用事件标志组做等待,全部任务的接口都初始化完成,才进入whlie循环去下图是我的 ...

这是肯定的,硬件初始化完毕后,方可开始操作系统创建任务、开始任务调度。。。
回复 支持 反对

使用道具 举报

120

主题

7877

帖子

13

精华

资深版主

Rank: 8Rank: 8

积分
12010
金钱
12010
注册时间
2013-9-10
在线时间
427 小时
发表于 2017-8-28 17:58:38 | 显示全部楼层
打洞者 发表于 2017-8-28 17:53
这是肯定的,硬件初始化完毕后,方可开始操作系统创建任务、开始任务调度。。。

现在,程序把烂铜烂铁变得智能化了,人呢,一旦离开了这烂铜烂铁就不知道干啥了
回复 支持 反对

使用道具 举报

7

主题

60

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
299
金钱
299
注册时间
2015-10-21
在线时间
52 小时
 楼主| 发表于 2017-8-30 17:03:10 | 显示全部楼层

问题已解决,延时部分对 systick 做了修改
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2024-11-22 23:19

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表