搜索
bottom↓
回复: 13

ucosII的任务切换问题,程序如下,出现的问题在后面,求...

[复制链接]

出0入0汤圆

发表于 2016-8-4 14:40:50 | 显示全部楼层 |阅读模式
#include "includes.h"

#define START_TASK_PRIO 10
#define START_STK_SIZE  128
OS_STK START_TAST_STK[START_STK_SIZE];
void start_task(void *pdata);

#define LED0_TASK_PRIO 7
#define LED0_STK_SIZE  64
OS_STK LED0_TASK_STK[LED0_STK_SIZE];
void led0_task(void *pdata);

#define LED1_TASK_PRIO 6
#define LED1_STK_SIZE  128
OS_STK LED1_TASK_STK[LED1_STK_SIZE];
void led1_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);

int main(void)
{
        OS_CPU_SysTickInit();
        NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
        
        uart_init(115200);
        LED_Init();
        TIM3_Int_Init();
        
        OSInit();
        OSTaskCreate(start_task,(void *)0,(OS_STK *)
                                &START_TAST_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(led0_task,(void *)0,(OS_STK *)
                  &LED0_TASK_STK[LED0_STK_SIZE-1],LED0_TASK_PRIO);
        OSTaskCreate(led1_task,(void *)0,(OS_STK *)
                  &LED1_TASK_STK[LED1_STK_SIZE-1],LED1_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();
}

void led0_task(void *pdata)
{
        while(1)
        {
                OS_CPU_SR cpu_sr=0;
                OS_ENTER_CRITICAL();
                LED0=0;
                delay_ms(50);//TIM3做的延时
                LED0=1;
                delay_ms(50);
                OS_EXIT_CRITICAL();
                OSTimeDly(10);
               
        }
}

void led1_task(void *pdata)
{
        while(1)
        {
                OS_CPU_SR cpu_sr=0;
                OS_ENTER_CRITICAL();
                LED1=0;
                delay_ms(1000);
                LED1=1;
                delay_ms(1000);
                OS_EXIT_CRITICAL();
                OSTimeDly(10);
               
        }
}

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("êä3öfloat_num:%.4f\r\n",float_num);
               
                delay_ms(500);
                OS_EXIT_CRITICAL();
                OSTimeDly(30);
        }
}
LED1灯闪烁正常,LED0亮的时间正常,但灭的时间过长,一直要等到LED1亮时才亮,串口打印也不是500ms,感觉是5s

出0入0汤圆

发表于 2016-8-4 14:56:34 | 显示全部楼层
delay_ms?有OS还用这个没有释放CPU吧

出0入46汤圆

发表于 2016-8-4 14:59:23 | 显示全部楼层
OS_ENTER_CRITICAL();   OS_EXIT_CRITICAL();这个之间的代码 delay肯定互相影响了

出0入46汤圆

发表于 2016-8-4 15:00:19 | 显示全部楼层
非关键代码,应该不能随便OS_ENTER_CRITICAL();   OS_EXIT_CRITICAL();
往往OS_ENTER_CRITICAL();   OS_EXIT_CRITICAL();之间的代码应该是非常快就结束的

出0入0汤圆

 楼主| 发表于 2016-8-5 07:55:39 | 显示全部楼层
jasonzhu8888 发表于 2016-8-4 14:59
OS_ENTER_CRITICAL();   OS_EXIT_CRITICAL();这个之间的代码 delay肯定互相影响了

要是用delay_ms();该怎么用怎么改?大神
void TIM3_Int_Init(void)
{
        RCC->APB1ENR|=1<<1;        //TIM6ʱÖÓʹÄÜ                     
}
//0<ms<=65535/2
void delay_ms(int ms)
{

        TIM3->PSC=36000-1;
        TIM3->CNT=0x00;
        TIM3->ARR=ms*2;          //É趨¼ÆÊýÆ÷×Ô¶¯ÖØ×°Öµ
//        TIM6->EGR = 0x0001;  //UG=1 Á¢¿Ì¸üÐÂÔ¤·ÖƵÆ÷£¬Á¢¿ÌÇå¿Õ¼ÆÊýÆ÷£¬µ«»á²úÉú¸üÐÂÖжϣ¬Ê¹UIFÖÃ1
//        TIM6->CR1|=(1<<3);
        TIM6->SR&=0x00;
//        TIM3->DIER=0x01;
        TIM3->CR1|=0x05;    //ARPE:ÎÞ»º³å£¬UDIS£ºÉÏÒç²úÉú¸üÐÂʼþ£¬USR£º¸üÐÂÔ´Ö»ÓÐÉÏÏÂÒç
        while((TIM3->SR&0x01)==0);        //µÈ´ýʱ¼äµ½´ï  ¸üÐÂÖжϱê־루¸üÐÂʼþ£ºÒ²ÊǶÔARRºÍPSC¸üУ©  
        TIM3->SR=0x00;
        TIM3->CR1&=~(1<<0);

}

出0入8汤圆

发表于 2016-8-5 08:21:25 | 显示全部楼层
建议 LZ 先去看看 操作系统原理以及应用相关知识,
再来实战,
没有理论的支撑,就实战,会很痛苦。

出0入0汤圆

发表于 2016-8-5 08:38:29 来自手机 | 显示全部楼层
时钟节拍的问题,

出0入0汤圆

发表于 2016-8-5 08:42:07 | 显示全部楼层
void start_task(void *pdata)
{
        pdata=pdata;
        OSStatInit();
        OSTaskCreate(led0_task,(void *)0,(OS_STK *)
                  &LED0_TASK_STK[LED0_STK_SIZE-1],LED0_TASK_PRIO);
        OSTaskCreate(led1_task,(void *)0,(OS_STK *)
                  &LED1_TASK_STK[LED1_STK_SIZE-1],LED1_TASK_PRIO);
        OSTaskCreate(float_task,(void *)0,(OS_STK *)
                  &FLOAT_TASK_STK[FLOAT_STK_SIZE-1],FLOAT_TASK_PRIO);
        OSTaskSuspend(START_TASK_PRIO);

}

void led0_task(void *pdata)
{
        while(1)
        {
                LED0=0;
                OSTimeDly(OS_TICKS_PER_SEC/20);//延迟0.05s(=50ms)
                LED0=1;
                OSTimeDly(OS_TICKS_PER_SEC/20);//延迟0.05s(=50ms)               
        }
}

void led1_task(void *pdata)
{
        while(1)
        {
                LED1=0;
                OSTimeDly(OS_TICKS_PER_SEC);// 延迟1s(=1000ms)
                LED1=1;
                OSTimeDly(OS_TICKS_PER_SEC);// 延迟1s(=1000ms)
        }
}

void float_task(void *pdata)
{

        static float float_num=0.01;
        while(1)
        {
                float_num+=0.01f;

                printf("float_num:%.4f\r\n",float_num);
                OSTimeDly(OS_TICKS_PER_SEC/2);// 延迟0.5s(=500ms)

        }
}

出0入0汤圆

 楼主| 发表于 2016-8-5 09:30:44 | 显示全部楼层
Eric_Xue 发表于 2016-8-5 08:42
void start_task(void *pdata)
{
        pdata=pdata;

谢谢,这个我试过了,可行,要是非要用TIM3来做延时,是不是做不了?与SysTick会有冲突?

出0入8汤圆

发表于 2016-8-5 09:40:51 | 显示全部楼层
ccfuser 发表于 2016-8-5 09:30
谢谢,这个我试过了,可行,要是非要用TIM3来做延时,是不是做不了?与SysTick会有冲突? ...


先不说你进入中断临界区的事情,
你采用硬延时的话(没有调用操作系统的 task_delay),高优先级的任务,就会一直占着 CPU,低优先级的任务就没法执行。
这些多任务的知识,我建议,你还是去啃啃书,踩的坑会少一点(当然直接去踩坑,然后再去啃书也可以)

出0入0汤圆

发表于 2016-8-5 09:48:58 来自手机 | 显示全部楼层
操作系统都用了,还delay_ms

出0入0汤圆

 楼主| 发表于 2016-8-5 10:41:20 | 显示全部楼层
security 发表于 2016-8-5 09:40
先不说你进入中断临界区的事情,
你采用硬延时的话(没有调用操作系统的 task_delay),高优先级的任务, ...

我看了些基本知识,对下面代码分析如下,你看看是不是正解
void led0_task(void *pdata)    //priority 7
{
        while(1)
        {
                LED0=0;    //假设执行这句需1ms,灯亮
                delay_ms(500);
                LED0=1; //假设执行这句需1ms
                delay_ms(500);
                OSTimeDly(10);  //
               
        }
}

void led1_task(void *pdata)     //priority 6
{
        while(1)
        {
                LED1=0; //假设执行这句需1ms
                delay_ms(1000);
                LED1=1; //假设执行这句需1ms
                delay_ms(1000);
                OSTimeDly(10);   //a步
               
        }
}

这样是不是led1_task执行到a步后,led0_task只能执行10个时钟节拍(8ms中断一次),也就是led0亮80ms后又开始运行led1了,led1运行2002ms后,
又接着执行delay_ms(500);但只运行80ms,所以led0亮的时间比500ms多。以此类推,是不是???????

出0入8汤圆

发表于 2016-8-5 10:46:47 | 显示全部楼层
ccfuser 发表于 2016-8-5 10:41
我看了些基本知识,对下面代码分析如下,你看看是不是正解
void led0_task(void *pdata)    //priority 7 ...

是这样的,
所以你要参考 楼上坛友 的例子,不要用软件死等延时,要多用操作系统的接口,这样才能多任务并发。

出0入0汤圆

发表于 2016-8-5 18:42:01 | 显示全部楼层
ccfuser 发表于 2016-8-5 10:41
我看了些基本知识,对下面代码分析如下,你看看是不是正解
void led0_task(void *pdata)    //priority 7 ...

不清楚LZ为何非要执着用自己 delay_ms(),而不是OSTimeDly()?
采用LZ自己delay_ms()的缺点是:

(1)如果你的delay_ms()在critical area内,则执行到delay_ms()时,不响应中断,也不进行任何任务切换,程序相当于在死等。如果你要延迟500mS,那么这500ms时间内,程序一直死在此处。
       不过这确实能达到你要求的500ms,而且非常精确(其他事都不干了,就在等定时时间到,能不精确么)
void led0_task(void *pdata)
{
        while(1)
        {
                OS_CPU_SR cpu_sr=0;
                OS_ENTER_CRITICAL();
                 ……
                delay_ms(50);//TIM3做的延时
                ……
                OS_EXIT_CRITICAL();

               
        }
}

(2)如果你的delay_ms()不在critical area内,则执行到delay_ms()时,任务级的切换被关闭,但是由于中断开着,所以可以进行中断级的任务切换。也就是说在delay_ms()期间,只有该任务以及比该任务优先级更高的任务才能执行。
       这个可能定时的精度就没有那么高了。因为定时时间到了,而其他高优先级的任务可能占据CPU,等到高任务级的任务释放CPU,执行delay_ms()的任务要求定时时间已经过了。


LZ需要明白的是:各个任务的延迟的定时时间是否需要那么精确?大部分情况下,定时时间并不需要那么精确。比如要求每隔500ms闪烁一次灯。实际是闪烁在490ms~510ms之间可以,人眼分辨不出来。

      执行OSTimeDly()的误差约为 1/OS_TICKS_PER_SEC。假如OS_TICKS_PER_SEC=1000,也就是每秒1000个中断,则执行OSTimeDly(500ms)的误差为1ms。
       如果LZ可以忍受这个误差,完全可以采用OSTimeDly()。如果LZ要求的定时时间的误差小,可以采用定时器方式。这个看需求。


回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-4-20 22:46

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

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