OpenEdv-开源电子网

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

uCOSII中任务顺序执行一遍之后进入空闲任务不出来了

[复制链接]

1

主题

7

帖子

0

精华

新手入门

积分
17
金钱
17
注册时间
2016-11-13
在线时间
5 小时
发表于 2016-11-13 15:50:27 | 显示全部楼层 |阅读模式
6金钱
程序如下,浮点测试任务优先级为5,LED闪烁任务优先级为6,DMA发送任务优先级为7,下载程序到板子上后,顺序执行了上面三个任务之后,没有回到LED闪烁任务(优先级为6),而是直接进入了空闲任务不出来了。这是什么原因啊?查看了论坛里所有关于uCOS的帖子也没找到解决办法···求高手帮忙


#define START_TASK_PRIO                        10  
#define START_STK_SIZE                        64
OS_TCB start_task_TCB;
OS_STK START_TASK_STK[START_STK_SIZE];
void start_task(void *pdata);

#define DMA_Send_TASK_PRIO                        7
#define DMA_Send_STK_SIZE                        128
OS_STK DMA_Send_TASK_STK[DMA_Send_STK_SIZE];
void DMA_Send_task(void *pdata);


#define led_trade_TASK_PRIO                        6
#define led_trade_STK_SIZE                128
OS_STK led_trade_TASK_STK[led_trade_STK_SIZE];
void led_trade_task(void *pdata);

#define FLOAT_TASK_PRIO                        5
#define FLOAT_STK_SIZE                        128
__align(8) OS_STK FLOAT_TASK_STK[FLOAT_STK_SIZE];
void float_task(void *pdata);

u8 SendBuff[SEND_BUF_SIZE];
const u8 TEXT_TO_SEND[]={"iCore3 STM32F4 "};
extern u8 RECEIVEBuff[RECEIVE_BUF_SIZE];       
int main(void)
{
        u16 i;
        u8 t=0;
        u8 j,mask=0;
        NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
        delay_init(168);  
        uart_init(115200);       
        led.initialize();
        key.initialize();
        //DMA配置
        MYDMA_Config((u32)&USART4->DR,(u32)SendBuff,SEND_BUF_SIZE,(u32)&USART4->DR,(u32)RECEIVEBuff,RECEIVE_BUF_SIZE);
        j=sizeof(TEXT_TO_SEND);          
        for(i=0;i<SEND_BUF_SIZE;i++)
    {
                if(t>=j)
                        {
                        if(mask)
                                {
                                SendBuff=0x0a;
                                t=0;
                                }else
                                {
                                SendBuff=0x0d;
                                mask++;
                                }       
                        }else
                                {
                        mask=0;
                        SendBuff=TEXT_TO_SEND[t];
                        t++;
                                }             
    }                 
        i=0;
        OSInit();
        OSTaskCreate(start_task,(void*)0,(OS_STK*)&START_TASK_STK[START_STK_SIZE-1],START_TASK_PRIO);
        OSStart();  
}

//开始任务
void start_task(void *pdata)
{
        OS_CPU_SR cpu_sr=0;
        pdata=pdata;
        OSStatInit();  
        OS_ENTER_CRITICAL();
        OSTaskCreate(DMA_Send_task,(void*)0,(OS_STK*)&DMA_Send_TASK_STK[DMA_Send_STK_SIZE-1],DMA_Send_TASK_PRIO);
        OSTaskCreate(led_trade_task,(void*)0,(OS_STK*)&led_trade_TASK_STK[led_trade_STK_SIZE-1],led_trade_TASK_PRIO);
        OSTaskCreate(float_task,(void*)0,(OS_STK*)&FLOAT_TASK_STK[FLOAT_STK_SIZE-1],FLOAT_TASK_PRIO);
        OSTaskSuspend(START_TASK_PRIO);//挂起开始任务
        OS_EXIT_CRITICAL();  
}

//DMA发送数据
void DMA_Send_task(void *pdata)
{
        while(1)
        {
                if(KEY_INPUT)
                {
                        MYDMA_Enable(DMA1_Stream4,SEND_BUF_SIZE);
                }
                OSTaskSuspend(DMA_Send_TASK_PRIO);//1ò&#198;eè&#206;&#206;&#241;
        }
}

//LED闪烁提示系统正在运行
void led_trade_task(void *pdata)
{

        while(1)
        {
                LED_GREEN_ON;
                delay_us(50000);
                LED_BLUE_OFF;
                delay_us(50000);
                LED_GREEN_OFF;
                delay_us(50000);
                LED_BLUE_ON;
                delay_us(50000);
                OSTimeDlyHMSM(0,0,0,100);
        }
}

//浮点测试任务
void float_task(void *pdata)
{
        OS_CPU_SR cpu_sr=0;
        static float float_num=0.01;
        while(1)
        {
                float_num+=0.01f;
                OS_ENTER_CRITICAL();
                printf("float_numμ&#196;&#214;μ&#206;a: %f\r\n",float_num);
                if(float_num>=1)
                        {
                                OSTaskSuspend(FLOAT_TASK_PRIO);
                        }
                OS_EXIT_CRITICAL();
        }
}


1.png
2.png
3.png
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165225
金钱
165225
注册时间
2010-12-1
在线时间
2107 小时
发表于 2016-11-13 18:48:30 | 显示全部楼层
你这个临界区设置有问题吧?在临界区里面挂起任务,不知道可不可行哦,别这么干试试。
回复

使用道具 举报

1

主题

7

帖子

0

精华

新手入门

积分
17
金钱
17
注册时间
2016-11-13
在线时间
5 小时
 楼主| 发表于 2016-11-13 19:25:38 | 显示全部楼层
正点原子 发表于 2016-11-13 18:48
你这个临界区设置有问题吧?在临界区里面挂起任务,不知道可不可行哦,别这么干试试。

恩恩,我试试看先
回复

使用道具 举报

1

主题

7

帖子

0

精华

新手入门

积分
17
金钱
17
注册时间
2016-11-13
在线时间
5 小时
 楼主| 发表于 2016-11-13 19:52:18 | 显示全部楼层
正点原子 发表于 2016-11-13 18:48
你这个临界区设置有问题吧?在临界区里面挂起任务,不知道可不可行哦,别这么干试试。

已经尝试着在临界区外面把任务挂起了,但还是不行,好心塞,修改后的程序代码如下
//开始任务
void start_task(void *pdata)
{
        OS_CPU_SR cpu_sr=0;
        pdata=pdata;
        OSStatInit();  
        OS_ENTER_CRITICAL(); 、
        OSTaskCreate(DMA_Send_task,(void*)0,(OS_STK*)&DMA_Send_TASK_STK[DMA_Send_STK_SIZE-1],DMA_Send_TASK_PRIO);
        OSTaskCreate(led_trade_task,(void*)0,(OS_STK*)&led_trade_TASK_STK[led_trade_STK_SIZE-1],led_trade_TASK_PRIO);
        OSTaskCreate(float_task,(void*)0,(OS_STK*)&FLOAT_TASK_STK[FLOAT_STK_SIZE-1],FLOAT_TASK_PRIO);
        OS_EXIT_CRITICAL();  
        OSTaskSuspend(START_TASK_PRIO);
}

//浮点测试任务
void float_task(void *pdata)
{
        OS_CPU_SR cpu_sr=0;
        static float float_num=0.01;
        while(1)
        {
                float_num+=0.01f;
                OS_ENTER_CRITICAL();
                printf("float_numμ&#196;&#214;μ&#206;a: %f\r\n",float_num);
                OS_EXIT_CRITICAL();
                if(float_num>=1)
                        {
                                OSTaskSuspend(FLOAT_TASK_PRIO);//1ò&#198;eè&#206;&#206;&#241;
                        }
        }
回复

使用道具 举报

1

主题

7

帖子

0

精华

新手入门

积分
17
金钱
17
注册时间
2016-11-13
在线时间
5 小时
 楼主| 发表于 2016-11-13 23:11:44 | 显示全部楼层
正点原子 发表于 2016-11-13 18:48
你这个临界区设置有问题吧?在临界区里面挂起任务,不知道可不可行哦,别这么干试试。

原子哥,知道问题大概出现的地方了,应该是我用DMA串口发送数据的过程中做了什么导致了UCOSII进入了空闲任务出不来。在这个过程中,我采用的是中断的方式,是不是我的中断服务程序中做了什么不该做的事情啊?DMA中断服务程序以及串口中断服务程序如下

//DMA发送中断处理函数
void DMA1_Stream4_IRQHandler(void)
{
#if SYSTEM_SUPPORT_OS        
OSIntEnter();
#endif
        if(DMA_GetITStatus(DMA1_Stream4,DMA_IT_TCIF4)!=RESET)
        {
                //清除标志位
                DMA_ClearFlag(DMA1_Stream4,DMA_FLAG_TCIF4);
                //关闭DMA
                DMA_Cmd(DMA1_Stream4,DISABLE);
                //打开发送完成中断
                USART_ITConfig(USART4,USART_IT_TC,ENABLE);
        }
#if SYSTEM_SUPPORT_OS        
        OSIntExit();                                                                                  
#endif        
}

//串口中断服务函数
void UART4_IRQHandler(void)
{
        u16 LEN;
#if SYSTEM_SUPPORT_OS
        OSIntEnter();
#endif
        //发送完成中断处理,只是简单地清除标志位,并未做其他事情
        if(USART_GetITStatus(USART4, USART_IT_TC) != RESET)
        {
                USART_ClearFlag(USART4,USART_FLAG_TC);//清零TC标志位
        }
        //接收完成中断处理
        if(USART_GetITStatus(USART4, USART_IT_IDLE) != RESET)  
        {
                //清标志
                USART4->SR;
                USART4->DR;
                //关闭DMA
                DMA_Cmd(DMA1_Stream2,DISABLE);
                //清除标志位
                DMA_ClearFlag(DMA1_Stream2,DMA_FLAG_TCIF2);
                //获取接收帧帧长
                LEN=RECEIVE_BUF_SIZE-DMA_GetCurrDataCounter(DMA1_Stream2);
                //重新设置DMA传输数据长度                                             
                DMA_SetCurrDataCounter(DMA1_Stream2,RECEIVE_BUF_SIZE);
                //打开DMA
                DMA_Cmd(DMA1_Stream2,ENABLE);       
#if SYSTEM_SUPPORT_OS
        OSIntExit();                                                                          
#endif
        }
}
回复

使用道具 举报

1

主题

561

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1183
金钱
1183
注册时间
2015-5-28
在线时间
149 小时
发表于 2016-11-14 11:18:25 | 显示全部楼层
如果没有业务,只是几个task之间的延时切换有问题吗?
回复

使用道具 举报

1

主题

7

帖子

0

精华

新手入门

积分
17
金钱
17
注册时间
2016-11-13
在线时间
5 小时
 楼主| 发表于 2016-11-14 11:33:56 | 显示全部楼层
小陀螺爱炒蛋 发表于 2016-11-14 11:18
如果没有业务,只是几个task之间的延时切换有问题吗?

恩,可以的。昨天晚上通过注释掉具体任务内容,只留下简单的三个任务直接的切换,是可以完成调度切换的,加入简单的LED闪烁提示也是可以实现调度切换,不会导致进入空闲任务出不了。唯一的问题就出在我在任务中启动DMA串口发送,就会进入空闲任务死循环里边,所以基本可以确定问题就出在这一块了。不知道我分析的方向是不是对的,但是从昨晚一直做的几个实验(包括重新移植UCOSII以及使用探索者开发板的UCOSII例程进行修改,两种方式)来看,现象是这样子的
回复

使用道具 举报

1

主题

561

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1183
金钱
1183
注册时间
2015-5-28
在线时间
149 小时
发表于 2016-11-14 13:04:40 | 显示全部楼层
oobuding 发表于 2016-11-14 11:33
恩,可以的。昨天晚上通过注释掉具体任务内容,只留下简单的三个任务直接的切换,是可以完成调度切换的, ...

原理上,DMA不会对操作系统有影响,你可以尝试看下systick的配置是不是被改变了~ucos的核心调度都是基于systick的时钟
回复

使用道具 举报

1

主题

7

帖子

0

精华

新手入门

积分
17
金钱
17
注册时间
2016-11-13
在线时间
5 小时
 楼主| 发表于 2016-11-14 16:28:23 | 显示全部楼层
小陀螺爱炒蛋 发表于 2016-11-14 13:04
原理上,DMA不会对操作系统有影响,你可以尝试看下systick的配置是不是被改变了~ucos的核心调度都是基于s ...

对不起,可以提示一下是systick的哪方面的配置被改变了吗?因为用的是探索者开发板的例程修改来的,只修改了外部晶振频率,由原来探索者开发板的8MHz改成了24MHz的外部晶振。修改的地方如下:
(1)、system_stm32f4xx.c文件中#define PLL_M  8修改为#define PLL_M      24
(2)、stm32f4xx.h文件中的#define HSE_VALUE ((uint32_t)8000000)修改为#define HSE_V   ALUE    ((uint32_t)24000000)
其他地方均没有动,包括        主函数中的时钟初始化delay_init(168);没有修改
回复

使用道具 举报

1

主题

561

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1183
金钱
1183
注册时间
2015-5-28
在线时间
149 小时
发表于 2016-11-14 16:40:46 | 显示全部楼层
oobuding 发表于 2016-11-14 16:28
对不起,可以提示一下是systick的哪方面的配置被改变了吗?因为用的是探索者开发板的例程修改来的,只修 ...

看下systick的寄存器,也就是说在你使能了DMA后,有没有导致systick的寄存器配置变了,导致操作系统不会切换任务了
回复

使用道具 举报

1

主题

7

帖子

0

精华

新手入门

积分
17
金钱
17
注册时间
2016-11-13
在线时间
5 小时
 楼主| 发表于 2016-11-14 17:19:59 | 显示全部楼层
小陀螺爱炒蛋 发表于 2016-11-14 16:40
看下systick的寄存器,也就是说在你使能了DMA后,有没有导致systick的寄存器配置变了,导致操作系统不会 ...

恩恩,那我先看看~
回复

使用道具 举报

5

主题

121

帖子

0

精华

高级会员

Rank: 4

积分
615
金钱
615
注册时间
2016-1-26
在线时间
149 小时
发表于 2016-11-14 17:40:57 | 显示全部楼层
给个tips,任务切换的原理是高优先级的任务抢断低优先级的处理器,当高优先级占用处理器的时候因为死循环或者什么原因导致处于一个等待状态,从而没有释放处理器,这就会导致低优先级的任务无法运行
回复

使用道具 举报

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

本版积分规则



关闭

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

正点原子公众号

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

GMT+8, 2024-11-1 10:25

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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