论坛» 综合技术» 基础知识

COS,II,OSTimeDly μCOS-II下OSTimeDly()实现任务切换的疑问?

院士
2006-12-22 22:43 1楼
COS,II,OSTimeDly μCOS-II下OSTimeDly()实现任务切换的疑问?
院士
2006-12-22 22:43 2楼
问 1.在μ COS- II中调用延时函数是导致任务切换的一种方式?我的理解是,只要在一个任务中第一次出现了 OSTimeDly()调用,此任务处于等待状态,系统中除它以外的,优先级最高且处于就绪态的任务就立即运行。但如果按照这个理解,以下这个用于控制蜂鸣的任务:
void Task2(void *pdata)
{
pdata = pdata; /* 避免编译警告 */
BeeMoo(); /* 使蜂鸣器鸣叫 */
OSTimeDly(OS_TICKS_PER_SEC / 8); /* 延时 */
BeeNoMoo(); /* 使蜂鸣器停止鸣叫 */
OSTimeDly(OS_TICKS_PER_SEC / 4); /* 延时 */
BeeMoo(); /* 使蜂鸣器鸣叫 */
OSTimeDly(OS_TICKS_PER_SEC / 8); /* 延时 */
BeeNoMoo(); /* 使蜂鸣器停止鸣叫 */
OSTaskDel(OS_PRIO_SELF); /* 删除自己 */
}
在程序中无限循环中的第一个 OSTimeDly(OS_TICKS_PER_SEC / 8);就会造成任务切换,下面的任务还如何运行?那么蜂鸣器还如何实现蜂鸣?

2.为什么这个任务没写成无限循环的?

3.在基于μ COS- II的程序中是不是所有要用延时的地方就调用μ COS- II自带的延时函数,用不到自己编写的延时子程序?
1: 我的理解 本例中task2这个任务只执行一次,执行完后调用
OSTaskDel(OS_PRIO_SELF);
将自己删除了

蜂鸣器响几下后,停止

除非程序在其它地方重新激活该任务

呵呵,没用过μ COS- II,瞎猜的 2: 自毁的任务不需循环OS的定时都是靠节拍的,一般取10mS.
所谓任务切换,就是当前任务可能要延时或自己的级别太高不好意思长期占用而将任务控制权暂交OS管理.
OS可能又转交控制权给另外一个需要执行的任务(也可能是个低级任务).
每个任务必须用死循环套住,否则不知道该到那里运行.
while(1)的目的就是要在必要是进行任务切换.
这就象前后台子程序的互相调用一样.
自毁的任务一般做为一个单独的初始化任务,它在完成各个任务的建立后就没必要再活着了---活着也白活,难道还要它再建立一个已存在并运行的任务???

这样肯定发晕~~~

在小于1个节拍的延时,肯定要用户自己在编写延时函数了,如10uS的延时.

而且OS的延时及利用OS的节拍肯定是不准确的,除非这个任务的级别最高.

在级别高也没用,因为在低级别任务运行期间,而且在节拍中断未到来前,天王老子也管不了低级别任务在干什么!!! 3: 感谢hotpower多次给我解答:1.上面的蜂鸣的任务和下面这个按键扫描的任务配合使用:
void Task1(void *pdata)
{
pdata = pdata; /* 避免编译警告 */
for (;;) //(1)
{
OSTimeDly(OS_TICKS_PER_SEC / 50); /* 延时20毫秒 */ //(2)
if (GetKey() != KEY1) /* GetKey用于获取键盘当前状态 */
{
continue; /* 不是KEY1不理会 */
}
OSTimeDly(OS_TICKS_PER_SEC / 50); /* 延时20毫秒,用于去抖 */ //(3)
if (GetKey() != KEY1) /* 还是KEY1才正确 */
{
continue;
}
OSTaskCreate(Task2, (void *)0, &TaskStk[TASK_STK_SIZE - 1], 10); //(4)
while (GetKey() != 0) /* 等待松开按键 */
{
OSTimeDly(OS_TICKS_PER_SEC / 50); /* 延时20毫秒 */ //(5)
}
}
}

那么,在蜂鸣任务运行过程中,没遇到一次 OSTimeDly();就会切换到这个键盘扫描任务(因为键盘扫描任务的优先级比它高),如果恰巧这时又有按键按下,于是就又重新建了个新的蜂鸣任务并立即运行,这样,蜂鸣不就乱套了吗?

2、按此说来,把蜂鸣任务改为:
void Task2(void *pdata)
{
pdata = pdata; /* 避免编译警告 */
BeeMoo(); /* 使蜂鸣器鸣叫 */
自己的延时子函数; /* 延时 */
BeeNoMoo(); /* 使蜂鸣器停止鸣叫 */
自己的延时子函数; /* 延时 */
BeeMoo(); /* 使蜂鸣器鸣叫 */
自己的延时子函数; /* 延时 */
BeeNoMoo(); /* 使蜂鸣器停止鸣叫 */
OSTaskDel(OS_PRIO_SELF); /* 删除自己 */
}
岂不是更合理?

3、推广到μ COS- II下的一切的任务中,有以下原则:
所有希望发生任务切换的地方都调用μ COS- II自带的延时函数,在不希望发生任务切换,但还需要延时的地方就用自己的延时子程序,这样可以提高系统的运行效率。
我这个理解对吗?

4: 长延时不必自己编写,这样将违反OS的原则2、按此说来,把蜂鸣任务改为:
void Task2(void *pdata)
{
pdata = pdata; /* 避免编译警告 */
BeeMoo(); /* 使蜂鸣器鸣叫 */
自己的延时子函数; /* 延时 */
BeeNoMoo(); /* 使蜂鸣器停止鸣叫 */
自己的延时子函数; /* 延时 */
BeeMoo(); /* 使蜂鸣器鸣叫 */
自己的延时子函数; /* 延时 */
BeeNoMoo(); /* 使蜂鸣器停止鸣叫 */
OSTaskDel(OS_PRIO_SELF); /* 删除自己 */
}
岂不是更合理?

非也!!!
因为蜂鸣器一般需要100mS切换才好听,这样肯定要大于节拍中断所需要的定时时间.
它和OS的延时程序不同,它将占用CPU的实际时间,而OS的延时程序是假延时(可以说没延时).
它不过是每次节拍中断的计数值.若某任务调用OS的延时程序后,CPU的控制权将暂时由OS接管.
任务不知也无权过问OS想干什么.
OS可以将控制再转交其他任务,哪怕是最低的任务(一般为空闲任务,用于掉电进入低功耗).

这个和自己编写的延时程序是有本质的不同.

由于自己编写的延时程序,低级别的任务会赖着不交出控制权来,这样只能等待
节拍中断由OS法庭来抢夺控制权了.

由于(因为键盘扫描任务的优先级比它高),故键盘扫描任务可被执行.
如果任务低的话,则键盘扫描任务在Task2中遇到OSTaskDel(OS_PRIO_SELF); /* 删除自己 */
前是不会交权的...

在你改写后,空闲任务不会得到执行,其他低级任务也无法运行.

实际上我只看过μ COS- II,实话说不太喜欢,我只是以自己的观点来分析此主题的... 5: 再次请教hotpower:“由于键盘扫描任务的优先级比蜂鸣任务的高,故键盘扫描任务可被执行.”那么对与上面那个由键盘扫描任务和蜂鸣任务组成的系统,在切换到蜂鸣任务并运行完第一个 BeeMoo(); /* 使蜂鸣器鸣叫 */函数后,我设想内核的调度如下:
内核得知运行到了蜂鸣任务中的第一个 OSTimeDly(OS_TICKS_PER_SEC / 8);根据优先级高低,立即将控制权切换给键盘扫描任务,恰巧此时键盘按下,在键盘扫描任务中的OSTaskCreate(Task2, (void *)0, &TaskStk[TASK_STK_SIZE - 1], 10);语句前共有2个 OSTimeDly(OS_TICKS_PER_SEC / 50);延时,2个1/50秒的延时肯定小于BeeMoo();和BeeNoMoo();间的那个1/8秒延时。那么键盘扫描任务继续执行OSTaskCreate(Task2……),又重新建立了蜂鸣任务,并转到蜂鸣任务运行,蜂鸣任务又从头开始执行,运行到第一个延时处又发生切换,这样的结果,岂不是蜂鸣器一直响着?我这样的推理错在哪里?
6: 哈哈,我记得任务是不能覆盖建立的即便是可以再次创建一个正在运行的任务,也不会发生长鸣之事.

因为在BeeNoMoo()后运行 OSTimeDly(OS_TICKS_PER_SEC / 8),很可能切换到键盘扫描任务继续执行并且到OSTaskCreate(Task2……),这里假定可以再次创建(实际是不可能的,如果可以就晕到了).
接着会执行
while (GetKey() != 0) /* 等待松开按键 */
{
OSTimeDly(OS_TICKS_PER_SEC / 50); /* 延时20毫秒 */ //(5)
}
由于 OSTimeDly()将会将控制权交给Task2,这种交替任务的切换肯定能到关闭BEEP的时候,不过它可能实行很长的时间(肯定小于1S),所以是不会受影响的...
7: 总结一下:归根到底一句话:
在μ COS- II下的所有延时,只要不是短于一个时钟节拍,那么都要调用μ COS- II自带的延时函数。
这种说法严密吗?
8: 1个半节拍不玩了---别的定时器在吃闲饭???在比较精准的长定时中(相对),可以采用硬件定时中断.
当然也可以建立一个处理任务,如果不想在中断中干活的话.
这个处理任务由于只接收这个定时服务的处理,所以它可以安排的级别较高.
这样退出硬件定时中断后,由于"龟壳"的作用,中断退出后会立即在这个任务中处理的.
就象在中断里处理一样,只不过有些延迟,只要你能容许即可. 9: 那我修改一下:除去需要用硬件定时器延时和节拍数不为整数的延时外,都要调用μ COS- II自带的延时函数。那种通过累加或累减来实现软件延时的子程序是不必要的。
对吗?
共2条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册]