OpenEdv-开源电子网

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

ucosIII运行一段时间会卡死,或不能运行

[复制链接]

14

主题

51

帖子

0

精华

初级会员

Rank: 2

积分
168
金钱
168
注册时间
2020-9-2
在线时间
41 小时
发表于 2020-12-23 08:31:23 | 显示全部楼层 |阅读模式
1金钱
我使用正点原子的ucosIII的模板总共创建了4个任务,在stm32f103RBt6上运行的,任务间的切换是通过OSTimeDlyHMSM(0,0,0,110,OS_OPT_TIME_HMSM_STRICT,&err)进行切换的,它正常运行一段时间后就自动停止运行了或是卡死了。请问这问题出在哪里了?是移植的时候出错还是?卡死的原因有哪些?谢谢!

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

使用道具 举报

2

主题

26

帖子

0

精华

初级会员

Rank: 2

积分
86
金钱
86
注册时间
2018-12-26
在线时间
24 小时
发表于 2020-12-23 10:34:22 | 显示全部楼层
琐碎时光,悄悄溜走
回复

使用道具 举报

14

主题

51

帖子

0

精华

初级会员

Rank: 2

积分
168
金钱
168
注册时间
2020-9-2
在线时间
41 小时
 楼主| 发表于 2020-12-23 11:22:02 | 显示全部楼层
本帖最后由 binzhang 于 2020-12-23 11:23 编辑

#define START_TASK_PRIO                3
//任务堆栈大小        
#define START_STK_SIZE                 128
//任务控制块
OS_TCB StartTaskTCB;
//任务堆栈        
CPU_STK START_TASK_STK[START_STK_SIZE];
//任务函数
void start_task(void *p_arg);

//任务优先级
#define REC_TASK_PRIO                4
//任务堆栈大小        
#define REC_STK_SIZE                 128
//任务控制块
OS_TCB REC_TaskTCB;
//任务堆栈        
CPU_STK REC_TASK_STK[REC_STK_SIZE];
void REC_task(void *p_arg);

//任务优先级
#define USART2_SendData_TASK_PRIO                5
//任务堆栈大小        
#define USART2_SendData_STK_SIZE                 128
//任务控制块
OS_TCB USART2_SendData_TaskTCB;
//任务堆栈        
CPU_STK USART2_SendData_TASK_STK[USART2_SendData_STK_SIZE];
//任务函数
void USART2_SendData_task(void *p_arg);

//任务优先级
#define Handle_TASK_PRIO                6
//任务堆栈大小        
#define Handle_STK_SIZE                 128
//任务控制块
OS_TCB Handle_TaskTCB;
//任务堆栈        
CPU_STK Handle_TASK_STK[Handle_STK_SIZE];
//任务函数
void Handle_task(void *p_arg);

//任务优先级
#define length_TASK_PRIO                7
//任务堆栈大小        
#define length_STK_SIZE                 128
//任务控制块
OS_TCB length_TaskTCB;
//任务堆栈        
CPU_STK length_TASK_STK[length_STK_SIZE];
//任务函数
void length_task(void *p_arg);

//主函数
int main(void)
{
        OS_ERR err;
        CPU_SR_ALLOC();

        delay_init();  //时钟初始化
        NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//中断分组配置
        uart_init(115200);   //串口初始化
        LED_Init();         //LED初始化        
        //BEEP_Init();
        USART2_Init(115200);
        KEY_Init();
        OSInit(&err);                    //初始化UCOSIII
        OS_CRITICAL_ENTER();        //进入临界区                        
        //创建开始任务
        OSTaskCreate((OS_TCB         * )&StartTaskTCB,                //任务控制块
                                 (CPU_CHAR        * )"start task",                 //任务名字
                 (OS_TASK_PTR )start_task,                         //任务函数
                 (void                * )0,                                        //传递给任务函数的参数
                 (OS_PRIO          )START_TASK_PRIO,     //任务优先级
                 (CPU_STK   * )&START_TASK_STK[0],        //任务堆栈基地址
                 (CPU_STK_SIZE)START_STK_SIZE/10,        //任务堆栈深度限位
                 (CPU_STK_SIZE)START_STK_SIZE,                //任务堆栈大小
                 (OS_MSG_QTY  )0,                                        //任务内部消息队列能够接收的最大消息数目,为0时禁止接收消息
                 (OS_TICK          )0,                                        //当使能时间片轮转时的时间片长度,为0时为默认长度,
                 (void           * )0,                                        //用户补充的存储区
                 (OS_OPT      )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR, //任务选项
                 (OS_ERR         * )&err);                                //存放该函数错误时的返回值
        OS_CRITICAL_EXIT();        //退出临界区         
        OSStart(&err);      //开启UCOSIII
}

//开始任务任务函数
void start_task(void *p_arg)
{
        OS_ERR err;
        CPU_SR_ALLOC();
        p_arg = p_arg;

        CPU_Init();
#if OS_CFG_STAT_TASK_EN > 0u
   OSStatTaskCPUUsageInit(&err);          //统计任务               
#endif
        
#ifdef CPU_CFG_INT_DIS_MEAS_EN                //如果使能了测量中断关闭时间
    CPU_IntDisMeasMaxCurReset();        
#endif
        
#if        OS_CFG_SCHED_ROUND_ROBIN_EN  //当使用时间片轮转的时候
         //使能时间片轮转调度功能,时间片长度为1个系统时钟节拍,既1*5=5ms
        OSSchedRoundRobinCfg(DEF_ENABLED,1,&err);  
#endif        
        
        OS_CRITICAL_ENTER();        //进入临界区
        //创建TASK1任务
        OSTaskCreate((OS_TCB         * )&REC_TaskTCB,               
                                 (CPU_CHAR        * )"REC task",                 
                 (OS_TASK_PTR )REC_task,                        
                 (void                * )0,                                       
                 (OS_PRIO          )REC_TASK_PRIO,     
                 (CPU_STK   * )&REC_TASK_STK[0],        
                 (CPU_STK_SIZE)REC_STK_SIZE/10,        
                 (CPU_STK_SIZE)REC_STK_SIZE,               
                 (OS_MSG_QTY  )0,                                       
                 (OS_TICK          )0,                                       
                 (void           * )0,                                       
                 (OS_OPT      )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR,
                 (OS_ERR         * )&err);                                
                                 
        //创建TASK2任务
        OSTaskCreate((OS_TCB         * )&USART2_SendData_TaskTCB,               
                                 (CPU_CHAR        * )"USART2_SendData task",                 
                 (OS_TASK_PTR )USART2_SendData_task,                        
                 (void                * )0,                                       
                 (OS_PRIO          )USART2_SendData_TASK_PRIO,            
                 (CPU_STK   * )&USART2_SendData_TASK_STK[0],        
                 (CPU_STK_SIZE)USART2_SendData_STK_SIZE/10,        
                 (CPU_STK_SIZE)USART2_SendData_STK_SIZE,               
                 (OS_MSG_QTY  )0,                                       
                 (OS_TICK          )0,                                       
                 (void           * )0,                                
                 (OS_OPT      )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR,
                 (OS_ERR         * )&err);        
                //创建TASK3任务
        OSTaskCreate((OS_TCB         * )&Handle_TaskTCB,               
                                 (CPU_CHAR        * )"Handle task",                 
                 (OS_TASK_PTR )Handle_task,                        
                 (void                * )0,                                       
                 (OS_PRIO          )Handle_TASK_PRIO,            
                 (CPU_STK   * )&Handle_TASK_STK[0],        
                 (CPU_STK_SIZE)Handle_STK_SIZE/10,        
                 (CPU_STK_SIZE)Handle_STK_SIZE,               
                 (OS_MSG_QTY  )0,                                       
                 (OS_TICK          )0,                                       
                 (void           * )0,                                
                 (OS_OPT      )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR,
                 (OS_ERR         * )&err);
        OSTaskCreate((OS_TCB         * )&length_TaskTCB,               
                                 (CPU_CHAR        * )"length task",                 
                 (OS_TASK_PTR )length_task,                        
                 (void                * )0,                                       
                 (OS_PRIO          )length_TASK_PRIO,            
                 (CPU_STK   * )&length_TASK_STK[0],        
                 (CPU_STK_SIZE)length_STK_SIZE/10,        
                 (CPU_STK_SIZE)length_STK_SIZE,               
                 (OS_MSG_QTY  )0,                                       
                 (OS_TICK          )0,                                       
                 (void           * )0,                                
                 (OS_OPT      )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR,
                 (OS_ERR         * )&err);
        OS_CRITICAL_EXIT();        //退出临界区
        OSTaskDel((OS_TCB*)0,&err);        //删除start_task任务自身
}


//2.4G无线接收数据任务函数
void REC_task(void *p_arg)
{
        u8 i;
        OS_ERR err;
        CPU_SR_ALLOC();
        p_arg = p_arg;
        
        OS_CRITICAL_ENTER();        //进入临界区
        drv_spi_init();
        NRF24L01_Gpio_Init();
        
        NRF24L01_check();
        RF24L01_Init();                    //初始化NRF24L01
        //RF24L01_Set_Mode(MODE_TX);
        RF24L01_Set_Mode( MODE_RX );                //接收模式
        OS_CRITICAL_EXIT();        //退出临界区
        while(1)
        {
               
                i = NRF24L01_RxPacket( Rx_buff );                //接收字节
                //printf("任务1\r\n");
                if( 0 != i )
                {
                                drv_uart_tx_bytes(Rx_buff,i);                                       
                                Rec_flag=1;
                }        
                OSTimeDlyHMSM(0,0,0,110,OS_OPT_TIME_HMSM_STRICT,&err); //延时1s
        }
}

//串口2发送数据任务函数
void USART2_SendData_task(void *p_arg)
{
        u8 i=0;
        OS_ERR err;
        CPU_SR_ALLOC();
        p_arg = p_arg;

        OS_CRITICAL_ENTER();        //进入临界区
        RecToUsart2();
        checkData();
        OS_CRITICAL_EXIT();        //退出临界区
        while(1)
        {
                //printf("任务2\r\n");
                if(USART2Flag==1)
                {
                        for(i=0;i<USART2_LEN;i++)
                        {
                                while( RESET == USART_GetFlagStatus( USART2, USART_FLAG_TXE ));
                                USART_SendData(USART2,USART2_BUFF);                                
                       
}
                }
                else if(USART2Flag==0)
                {
                        clearBuff();
                }
                OSTimeDlyHMSM(0,0,0,100,OS_OPT_TIME_HMSM_STRICT,&err); //延时1s
        }
}
//数据处理任务函数
void Handle_task(void *p_arg)
{

        OS_ERR err;
        CPU_SR_ALLOC();
        p_arg = p_arg;
        
        while(1)
        {
                        //printf("任务3\r\n");
//                        if(USART1_RX_BUF[9]<=2)//如果气压值小于某个值时蜂鸣器发声
//                        {
//                                
//                        }
//                        if(Rx_buff[2]==0x04)//如果遥控器发来的是倒退命令,则启动步进电机的收线功能,根据到退的速度来进行调整步进电机的速度
//                        {
//                                
//                        }
//                        if(0==KEY_Scan(1))//检测按键并手动收线功能
//                        {
//                        
//                        }
                        
                        OSTimeDlyHMSM(0,0,0,80,OS_OPT_TIME_HMSM_STRICT,&err); //延时1s
        }
        
}
//行走距离计算
void length_task(void *p_arg)
{
        OS_ERR err;
        CPU_SR_ALLOC();
        p_arg = p_arg;
        
        while(1)
        {
                //printf("任务4\r\n");
                        //根据编码器来计算机器人行走的距离
                OSTimeDlyHMSM(0,0,0,80,OS_OPT_TIME_HMSM_STRICT,&err); //延时1s
        }
}
void drv_uart_tx_bytes( uint8_t* TxBuffer, uint8_t Length )
{
        while( Length-- )
        {
                while( RESET == USART_GetFlagStatus( USART1, USART_FLAG_TXE ));
                USART_SendData(USART1,*TxBuffer);
                TxBuffer++;
        }
}
void USART1_IRQHandler(void)         //串口1接收数据中断服务函数
{
        unsigned char r;
        OSIntEnter();
        
        if(USART_GetFlagStatus(USART1,USART_IT_RXNE)!=RESET)
        {
                printf("串口1中断接收任务产生\r\n");
                r=USART_ReceiveData(USART1);
                USART1_RX_BUF[USART1_REC_CNT]=r;
                USART1_REC_CNT++;
                if(USART1_REC_LEN==USART1_REC_CNT)
                {
                        USART1RecFlag=1;
                }
        }
        USART_ClearITPendingBit(USART1,USART_FLAG_TC); //清除中断标志        
        analyData();        
        OSIntExit();
}
回复

使用道具 举报

14

主题

51

帖子

0

精华

初级会员

Rank: 2

积分
168
金钱
168
注册时间
2020-9-2
在线时间
41 小时
 楼主| 发表于 2020-12-23 11:24:43 | 显示全部楼层

是因为单片机性能不够?还是我程序块搞的不对?
回复

使用道具 举报

2

主题

26

帖子

0

精华

初级会员

Rank: 2

积分
86
金钱
86
注册时间
2018-12-26
在线时间
24 小时
发表于 2020-12-23 11:38:36 | 显示全部楼层
binzhang 发表于 2020-12-23 11:24
是因为单片机性能不够?还是我程序块搞的不对?

一般不是单片机的事情,ucos需要的RAM很小,一般没事;应该是程序的事情,首先你再串口中断中处理数据就有点不合适,这样会占用CPU的时间过长,建议采用DMA传输,或者是在串口中用信号量或消息做同步进行数据处理。  卡住的问题我再看看啊
琐碎时光,悄悄溜走
回复

使用道具 举报

2

主题

26

帖子

0

精华

初级会员

Rank: 2

积分
86
金钱
86
注册时间
2018-12-26
在线时间
24 小时
发表于 2020-12-23 13:50:22 | 显示全部楼层
看你的程序,任务之间的通信我没看到信号量或事件。中断中analyData();  是处理数据吗?在RTOS中中断里放处理数据函数不太好。
琐碎时光,悄悄溜走
回复

使用道具 举报

2

主题

26

帖子

0

精华

初级会员

Rank: 2

积分
86
金钱
86
注册时间
2018-12-26
在线时间
24 小时
发表于 2020-12-23 13:51:14 | 显示全部楼层
      USART1RecFlag=1;这个标志位通知的是哪段程序?
琐碎时光,悄悄溜走
回复

使用道具 举报

14

主题

51

帖子

0

精华

初级会员

Rank: 2

积分
168
金钱
168
注册时间
2020-9-2
在线时间
41 小时
 楼主| 发表于 2020-12-23 14:21:13 | 显示全部楼层
MH居士 发表于 2020-12-23 13:50
看你的程序,任务之间的通信我没看到信号量或事件。中断中analyData();  是处理数据吗?在RTOS中中断里放处 ...

analyData()只是用来校验接收的数据是否正确
这是余下的程序


void clearBuff()
{
        int i=0;
        for(i=0;i<12;i++)
        {
                USART1_RX_BUF=0;
                USART2_BUFF=0;
        }
        USART1_REC_CNT=0;
}
void RecToUsart2()
{
        if(USART1_flag==1)
        {
                USART2_BUFF[2]=USART1_RX_BUF[2];
                USART2_BUFF[3]=USART1_RX_BUF[3];
                USART2_BUFF[4]=USART1_RX_BUF[4];
                USART2_BUFF[5]=USART1_RX_BUF[5];
                USART2_BUFF[6]=USART1_RX_BUF[6];
                USART2_BUFF[7]=USART1_RX_BUF[7];
                USART2_BUFF[8]=USART1_RX_BUF[8];
                USART2_BUFF[9]=USART1_RX_BUF[9];
                USART2_BUFF[10]=USART1_RX_BUF[10];
                USART2_BUFF[11]=USART1_RX_BUF[11];
                USART2_BUFF[12]=USART1_RX_BUF[12];
                USART2_BUFF[13]=Rx_buff[3];
                USART2_BUFF[14]=Rx_buff[7];
                USART2_BUFF[15]=Rx_buff[8];
                //USART2_BUFF[16]=Rx_buff[3];//计算出电机行走的米数
                //USART2_BUFF[17]=Rx_buff[3];//当气压值小于一定值时发送报警信号
                //USART2_BUFF[9]=Rx_buff[]
        }
        else if(USART1_flag==0)
        {
                clearBuff();
        }
       
}
//串口2发送数据检查
void checkData()
{
        unsigned char check_sum;
                if((USART2_BUFF[0]==0xff)&&(USART2_BUFF[1]==0xff))
                {
                        check_sum=USART2_BUFF[2]+USART2_BUFF[3]+USART2_BUFF[4]+USART2_BUFF[5]+USART2_BUFF[6]+USART2_BUFF[7]+USART2_BUFF[8]+USART2_BUFF[9]+USART2_BUFF[10]+USART2_BUFF[11]+USART2_BUFF[12]+USART2_BUFF[13]+USART2_BUFF[14]+USART2_BUFF[15]+USART2_BUFF[16]+USART2_BUFF[17]+USART2_BUFF[18]+0xff+0xff;
                        check_sum=~check_sum;
                        check_sum=check_sum&0xff;
                        if(check_sum==USART2_BUFF[18])
                        {
                                USART2Flag=1;
                        }
                }
                USART2Flag=0;

}
//串口1接收数据校验
void analyData()
{
        unsigned char check_sum;
        if(USART1RecFlag==1)
        {
                if((USART1_RX_BUF[0]==0xff)&&(USART1_RX_BUF[1]==0xff))
                {
                        check_sum=USART1_RX_BUF[2]+USART1_RX_BUF[3]+USART1_RX_BUF[4]+USART1_RX_BUF[5]+USART1_RX_BUF[6]+USART1_RX_BUF[7]+USART1_RX_BUF[8]+USART1_RX_BUF[9]+USART1_RX_BUF[10]+USART1_RX_BUF[11]+USART1_RX_BUF[12]+0xff+0xff;
                        check_sum=~check_sum;
                        check_sum=check_sum&0xff;
                        if(check_sum==USART1_RX_BUF[13])
                        {
                                USART1_flag=1;
                        }
                        else
                        {
                                USART1_flag=0;
                        }
                }
                else
                {
                        USART1_flag=0;
                        clearBuff();
                }
        }
        else if(USART1RecFlag==0)
        {
                USART1_flag=0;
                clearBuff();
        }
       

}


回复

使用道具 举报

2

主题

26

帖子

0

精华

初级会员

Rank: 2

积分
86
金钱
86
注册时间
2018-12-26
在线时间
24 小时
发表于 2020-12-23 15:05:32 | 显示全部楼层
老大啊,你的程序架构很是让我惊艳啊,,,RecToUsart2();  checkData();属于数据处理的东西,一般放在循环中。   运行时应该都进不去if(USART2Flag==1)这句吧,你可以仿真看一下能不能进去。       REC_task这个任务我看是定时查询来没来数据,可以不用优先级这么高,之前提到的数据处理函数要放在任务最高的函数中(仅做参考)    if(USART2Flag==1)这句中应该把USART2Flag清零,程序中的好多flag要及时清零。     还有就是吧任务堆栈的字节数提高点,256或512(如果可以的话)
琐碎时光,悄悄溜走
回复

使用道具 举报

14

主题

51

帖子

0

精华

初级会员

Rank: 2

积分
168
金钱
168
注册时间
2020-9-2
在线时间
41 小时
 楼主| 发表于 2020-12-23 15:17:48 | 显示全部楼层
MH居士 发表于 2020-12-23 15:05
老大啊,你的程序架构很是让我惊艳啊,,,RecToUsart2();  checkData();属于数据处理的东西,一般放在循环 ...

好的谢谢!我改改试试
回复

使用道具 举报

14

主题

51

帖子

0

精华

初级会员

Rank: 2

积分
168
金钱
168
注册时间
2020-9-2
在线时间
41 小时
 楼主| 发表于 2020-12-23 16:49:15 | 显示全部楼层
MH居士 发表于 2020-12-23 15:05
老大啊,你的程序架构很是让我惊艳啊,,,RecToUsart2();  checkData();属于数据处理的东西,一般放在循环 ...

我这个是中间部分的程序。我们项目是有遥控器+操作柜+机器人的三部分程序。遥控器是一直发送命令的
回复

使用道具 举报

0

主题

1

帖子

0

精华

新手入门

积分
15
金钱
15
注册时间
2020-12-27
在线时间
4 小时
发表于 2020-12-27 20:43:19 来自手机 | 显示全部楼层
中断服务里面简单一点   发个信号   其他任务里面处理
回复

使用道具 举报

14

主题

51

帖子

0

精华

初级会员

Rank: 2

积分
168
金钱
168
注册时间
2020-9-2
在线时间
41 小时
 楼主| 发表于 2021-1-8 16:39:01 | 显示全部楼层
MH居士 发表于 2020-12-23 11:38
一般不是单片机的事情,ucos需要的RAM很小,一般没事;应该是程序的事情,首先你再串口中断中处理数据就 ...

我在串口中断里使用任务信号量,中断会接收第一次数据然后第二次程序就会卡死在串口中断里了!请问这个怎么解决,谢谢!
//任务1的任务函数
void task1_task(void *p_arg)
{
        u8 key;
        u8 num;
        OS_ERR err;
        while(1)
        {

                //OSTaskSemPost(&Task2_TaskTCB,OS_OPT_POST_NONE,&err);        //使用系统内建信号量向任务task2发送信号量
                       
         
                OSTimeDlyHMSM(0,0,0,10,OS_OPT_TIME_PERIODIC,&err);                   //延时10ms
        }
}

//任务2的任务函数
void task2_task(void *p_arg)
{       
        u8 num;
        OS_ERR err;
        while(1)
        {
                OSTaskSemPend(0,OS_OPT_PEND_BLOCKING,0,&err);                //请求任务内建的信号量
                num++;
                printf("任务信号量获取成功!\r\n");
                LED1 = ~LED1;
                OSTimeDlyHMSM(0,0,1,0,OS_OPT_TIME_PERIODIC,&err);   //延时1s
        }
}
void USART1_IRQHandler(void)        
{
        unsigned char r;
        OS_ERR err;
        OSIntEnter();
       
        if(USART_GetFlagStatus(USART1,USART_IT_RXNE)!=RESET)
        {
                r=USART_ReceiveData(USART1);
               
                 
                printf("数据接收完成,释放一个任务信号量到数据分析任务\r\n");

                        OSTaskSemPost((OS_TCB  *)&Task2_TaskTCB,           //目标任务
                                                        (OS_OPT   )OS_OPT_POST_NONE,        //没选项要求
                                                        (OS_ERR  *)&err);
               
        }       
               
        USART_ClearITPendingBit(USART1,USART_IT_RXNE); //清除中断标志
        OSIntExit();
}

回复

使用道具 举报

1

主题

77

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
388
金钱
388
注册时间
2020-11-7
在线时间
44 小时
发表于 2021-1-23 11:52:49 | 显示全部楼层
binzhang 发表于 2021-1-8 16:39
我在串口中断里使用任务信号量,中断会接收第一次数据然后第二次程序就会卡死在串口中断里了!请问这个怎 ...

学习中,不过给你提点建议:1.仿真看看卡在了哪里?2.UCOSiii的任务函数,err会包含错误返回值,打印出来分析分析。
回复

使用道具 举报

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

本版积分规则



关闭

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

正点原子公众号

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

GMT+8, 2024-11-25 11:51

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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