RTX51 Tiny中容易混淆的问题
RTX51 Tiny是 Keil uVision中自带的一个小型嵌入式RTOS,具有小巧、速度快、系统开销小、使用方便等优点。使用RTX51 Tiny能够提高系统的稳定性,优化程序的性能;而且它是为51单片机专门定制的,所以在51单片机上的运行效率比其它一些通用的RTOS性能也要好一些。
但是,由于RTX51 Tiny的相关资料和书籍比较少,大部分只是对程序自带帮助文件的简单翻译,很少进行深入探讨。下面就RTX51 Tiny使用中经常遇到的一些问题进行探讨。 1 关于时间片的问题 RTX51 Tiny使用的是无优先级时间片轮询法,每个任务使用相同大小的时间片,但是时间片是怎样确定的呢? RTX51 Tiny的配置参数(Conf_tny.a51文件中)中有INT_CLOCK和TIMESHARING两个参数。这两个参数决定了每个任务使用时间片的大小:INT_CLOCK是时钟中断使用的周期数,也就是基本时间片;TIMESHARING是每个任务一次使用的时间片数目。两者决定了一个任务一次使用的最大时间片。如假设一个系统中INT_CLOCK设置为10000,即10ms,那么TIMESHARING=1时,一个任务使用的最大时间片是10ms;TIMESHARING=2时,任务使用最大的时间片是20ms;TIMESHARING=5时,任务使用最大的时间片是50ms;当TIMESHARING设置为0时,系统就不会进行自动任务切换了,这时需要用os_switch_task函数进行任务切换。这部分功能是RTX51 Tiny 2.0中新增加的。 2 关于os_wait延时的问题 os_wait 是RTX51 Tiny中的基本函数之一。它的功能是将当前任务挂起来,等待一个启动信号(K_SIG)或超时信号(K_TMO)或周期信号(K_IVL)或者是它们之间的组合。虽然os_wait很简单,但是因为涉及到多任务的操作方式,很容易产生误解。 2.1 关于K_TMO的延时时间 在RTX51 Tiny中,如果一个任务中使用了os_wait(K_TMO,1,0),那么它的延时时间是多少呢? 这就是说,最后的效果是延时时间加上正在运行的任务执行时间,而这个时间是与任务数和任务运行情况相关的。如果其它任务执行的时间短,那么延时可能只是一个时间片;如果其它任务执行的时间长,那么就需要多个时间片了。用os_wait做时钟是不准确的。 关于延时时间还有一个很容易理解错的地方,那就是os_wait中无论使用K_TMO还是K_IVL参数,延时的时间都只与INT_CLOCK有关,而与TIMESHARING无关。或者说,os_wait函数一次只使用一个基本时间片,而不是任务的时间片。 2.2 关于K_TMO和K_IVL参数的区别 在os_wait中有三个参数:K_TMO、K_IVL和K_SIG。其中,K_TMO与K_IVL是最容易让人混淆的,特别是搞不清楚K_IVL到底是什么含义,好像使用起来与K_TMO效果差不多。一般的书上和Keil自带的RTX51 Tiny的帮助中,也没有清楚解释K_IVL的含义。 K_IVL与K_TMO有很大区别,但是在一定环境下最终产生的效果却差不多。 K_TMO是指等待一个超时信号,只有时间到了,才会产生一个信号。它产生的信号是不会累计的。产生信号后,任务进入就绪状态。K_IVL是指周期信号,每隔一个指定的周期,就会产生一次信号,产生的信号是可以累计的。这里累计的意思是,如果在指定的时间内没有对信号进行响应,信号的次数会迭加,以后进行信号处理时就不会漏掉信号。比如说,在系统中有几个任务,其中一个任务使用K_TMO方式延时,另外一个任务使用K_IVL延时,延时的时间相同。如果系统的任务很轻,两个任务都可以及时响应,那么这两种延时的效果是一样的。如果系统的负担比较重,任务响应比较慢,不能及时响应所有的信号,那么使用K_TMO方式的任务就有可能丢失一部分没有及时响应的信号,而使用K_IVL方式的任务就不会丢失信号。只是信号的响应方式会变成这样:在一段时间内不响应信号,然后一次把所有累计的信号都处理完。 下面的一个例子可以将上面两个关于os_wait的问题解释清楚。 在x1++和x2++这两个地方加上断点,进行仿真,观察执行到断点的时间。然后,去掉任务job4中的语句“//os_wait(K_TMO,1,0);”这一行前面的注释符号,再次仿真。比较一下运行的结果,就可以清楚地知道它们的细微差别了。 软件环境:Keil uVision 7.08 其它参数使用默认设置。(需要自己建立一个工程文件,再将下面的文件添加到工程文件中。) 当job4中os_wait(K_TMO,1,0)的注释不取消时,job0每执行一次,job1就连续执行5次,x2是x1的5倍。因为job1中的os_wait(K_IVL,1,0)产生了5次信号,并累计下来;而job0中的os_wait(K_TMO,1,0)虽然也产生了5次信号,但是没有累计,只有最后一次是真正有效的。 当job4中os_wait(K_TMO,1,0)的注释取消时,job0和job1的执行次数是一样的,x1=x2。 |
本文引用通告地址:http://tvb2058.spaces.eepw.com.cn/articles/trackback/item/15060
P.S. 关于 K_TMO 和 K_IVT 官方说明如下文:
http://www.keil.com/support/docs/451.htm
RTX51: DIFFERENCES BETWEEN K_IVL AND K_TMO
QUESTION
What's the difference between the K_IVL and K_TMO events in the os_wait function call? The documentation is not clear about these two events.
ANSWER
The K_TMO event lets you specify a number of OS ticks to delay a task. The K_IVL event lets you specify an interval to perform a task.
Here are examples to illustrate the differences between these two. Let's assume that the RTX51 tick is set for a period of 1 msec.
The K_TMO event delays for at least the number of OS ticks you specify. For example, if you have a task that loops through code that takes 5 msec to execute, calls os_wait(K_TMO...) with a tick count of 10, and repeats; the whole loop executes in 15 msec (5 msec for the code and 10 msec for the K_TMO).
The K_IVL event delays for a period of time that is at least the time that you specify minus the number of ticks that have elapsed since the last K_IVL event. For example, if you have a task that loops through code that takes 6 msec to execute, calls os_wait(K_IVL...) with a tick count of 10, and repeats; the whole loop executes in 10 msec (6 msec for the code and 4 msec for the K_IVL).
Use the K_TMO event when you need/want to delay a task for a few milliseconds. Use the K_IVL event when you need a task to execute on a specific periodic basis.
Remember that the number of ticks passed to the os_wait function MUST be an unsigned character and, therefore, must have a value of 255 or less.
Last Reviewed: Monday, June 07, 2004