zoukankan      html  css  js  c++  java
  • RTX51 Tiny中容易混淆的问题

    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),那么它的延时时间是多少呢?
    很多人都会认为是一个时间片,其实这不完全对。正确的理解是,延时时间与正在运行的任务相关。因为RTX51 Tiny是一个非占先或多优先级的实时操作系统,是一个平级的时间片轮询实时操作系统,所有的任务平等运行。K_TMO是等待产生超时信号,当信号产生后,只是将相应的任务置上就绪标志位,任务并不是立即就能够运行。任务需要等到其它任务轮流执行,到自己的时间片后才会执行。

      这就是说,最后的效果是延时时间加上正在运行的任务执行时间,而这个时间是与任务数和任务运行情况相关的。如果其它任务执行的时间短,那么延时可能只是一个时间片;如果其它任务执行的时间长,那么就需要多个时间片了。用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
      仿真CPU:AT89C52 12MHz
      RTX51 Tiny:使用Keil自带的RTX51 Tiny操作系统,v2.02。
      RTX51 Tiny的参数:INT_CLOCK=10000,TIMESHARING=5

      其它参数使用默认设置。(需要自己建立一个工程文件,再将下面的文件添加到工程文件中。)
    #include <rtx51tny.h>
    unsigned long int x1,x2,x3;
    void job0(void) _task_ 0{
      x1=x2=x3=0;
      os_create_task(1);
      os_create_task(2);
      os_create_task(3);
      os_create_task(4);
      while(1) {
        os_wait(K_TMO,1,0);
        x1++;
      }
    }
    void job1(void) _task_ 1{
      while(1) {
        os_wait(K_IVL,1,0);
        x2++;
      }
    }
    void job2(void) _task_ 2{
      while(1) {
        os_wait(K_IVL,1,0);
        x3++;
      }
    }
    void job3(void) _task_ 3{
      while(1) {
        os_wait(K_TMO,1,0);
      }
    }
    void job4(void) _task_ 4{
      while(1) {
        //注释下面一句使系统的负担变得很重,不能及时响应job0和job1的延时信号
        //取消注释后,系统负担变轻,可以及时响应
        //os_wait(K_TMO,1,0);
      }
    }

      当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



  • 相关阅读:
    css盒子模型、垂直外边距合并
    mov指令和 add以及sub 指令的区别
    第一章 基础知识
    字符串文档的去重
    python 之 字符串的常用方法
    python格式化输出之format用法
    python 格式化输出之%号
    c++11可变参数模板的使用1
    深入浅出 c++11 std::async
    std::thread 概述
  • 原文地址:https://www.cnblogs.com/techstone/p/2661243.html
Copyright © 2011-2022 走看看