ucosII的任务切换问题,程序如下,出现的问题在后面,求...
#include "includes.h"#define START_TASK_PRIO 10
#define START_STK_SIZE128
OS_STK START_TAST_STK;
void start_task(void *pdata);
#define LED0_TASK_PRIO 7
#define LED0_STK_SIZE64
OS_STK LED0_TASK_STK;
void led0_task(void *pdata);
#define LED1_TASK_PRIO 6
#define LED1_STK_SIZE128
OS_STK LED1_TASK_STK;
void led1_task(void *pdata);
#define FLOAT_TASK_PRIO 5
#define FLOAT_STK_SIZE 128
__align(8) OS_STK FLOAT_TASK_STK;
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_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_TASK_PRIO);
OSTaskCreate(led1_task,(void *)0,(OS_STK *)
&LED1_TASK_STK,LED1_TASK_PRIO);
OSTaskCreate(float_task,(void *)0,(OS_STK *)
&FLOAT_TASK_STK,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 delay_ms?有OS还用这个没有释放CPU吧 OS_ENTER_CRITICAL(); OS_EXIT_CRITICAL();这个之间的代码 delay肯定互相影响了 非关键代码,应该不能随便OS_ENTER_CRITICAL(); OS_EXIT_CRITICAL();
往往OS_ENTER_CRITICAL(); OS_EXIT_CRITICAL();之间的代码应该是非常快就结束的 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);
} 建议 LZ 先去看看 操作系统原理以及应用相关知识,
再来实战,
没有理论的支撑,就实战,会很痛苦。 时钟节拍的问题, void start_task(void *pdata)
{
pdata=pdata;
OSStatInit();
OSTaskCreate(led0_task,(void *)0,(OS_STK *)
&LED0_TASK_STK,LED0_TASK_PRIO);
OSTaskCreate(led1_task,(void *)0,(OS_STK *)
&LED1_TASK_STK,LED1_TASK_PRIO);
OSTaskCreate(float_task,(void *)0,(OS_STK *)
&FLOAT_TASK_STK,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)
}
} Eric_Xue 发表于 2016-8-5 08:42
void start_task(void *pdata)
{
pdata=pdata;
谢谢,这个我试过了,可行,要是非要用TIM3来做延时,是不是做不了?与SysTick会有冲突? ccfuser 发表于 2016-8-5 09:30
谢谢,这个我试过了,可行,要是非要用TIM3来做延时,是不是做不了?与SysTick会有冲突? ...
先不说你进入中断临界区的事情,
你采用硬延时的话(没有调用操作系统的 task_delay),高优先级的任务,就会一直占着 CPU,低优先级的任务就没法执行。
这些多任务的知识,我建议,你还是去啃啃书,踩的坑会少一点(当然直接去踩坑,然后再去啃书也可以) 操作系统都用了,还delay_ms 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多。以此类推,是不是??????? ccfuser 发表于 2016-8-5 10:41
我看了些基本知识,对下面代码分析如下,你看看是不是正解
void led0_task(void *pdata) //priority 7 ...
是这样的,
所以你要参考 楼上坛友 的例子,不要用软件死等延时,要多用操作系统的接口,这样才能多任务并发。 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要求的定时时间的误差小,可以采用定时器方式。这个看需求。
页:
[1]