打印
[uCOS/RTOS]

关于RTEMS的时间片轮询的一点疑惑

[复制链接]
2793|3
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
youfimiya|  楼主 | 2014-7-16 11:27 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
RTEMS, ic, TI, ck, ni
    我在RTEMS中首先定义了一个用户初始化任务Init,然后在用户初始化任务Init中定义了4个相同优先级的用户任务usr_tsk1,usr_tsk2,usr_tsk3,usr_tsk4,并在定义任务时使能timeslice(时间片)功能。然后,规定了一个时间片包含50个滴答(tick),一个滴答0.001s。
    每个任务当中都只有一个循环——在每次循环里,读取系统自启动开始总共发生的滴答数并输出到屏幕上,用串口调试助手查看。
    然后,疑问出现了——只有在最开始执行的任务,如usr_tsk1,中循环执行了50个ticks即一个时间片的时间,而紧接着从usr_tsk2开始,usr_tsk2只执行了一次读取滴答数并输出的操作,然后就跳转到usr_tsk3开始执行,而usr_tsk3同样只执行了一次读取滴答数并输出的操作,接下来usr_tsk4和usr_tsk1也执行同样的操作,然后一直循环下去——每次读取滴答数并输出,然后跳转到下一个任务开始执行的过程,平均耗时10个滴答。
    而在下预想的结果应该是每个任务依次执行50个滴答后,再开始新一轮的循环。为什么会出现上面这种情况,求各位大大解惑。
    在下不胜感激!

相关帖子

沙发
arm2009wzm| | 2014-7-16 15:07 | 只看该作者
在前一个任务执行退出前,有没有进行初始化:
1. 有没有清除时钟节拍 (TICK,就是你说的滴答) 中断标志。
2. 如果用信号量等来管理任务,有没有删除信号量等状态。

使用特权

评论回复
板凳
youfimiya|  楼主 | 2014-7-16 15:53 | 只看该作者
#include <rtems.h>

#include <stdlib.h>
#include <time.h>
#include <stdio.h>

#define UART0_DATA         *(volatile unsigned int *)(0x80000070)
#define UART0_STATUS      *(volatile unsigned int *)(0x80000074)
#define UART0_CONTRAL     *(volatile unsigned int *)(0x80000078)
#define UART0_SCALER      *(volatile unsigned int *)(0x8000007c)
#define INT1_MSK            *(volatile unsigned int *)(0x80000090)
#define INT1_CLR            *(volatile unsigned int *)(0x8000009c)

#define SYSTEM_CLK 9600000
#define BAUDERATE  19200

/*定义共同体变量的原因是,读取系统滴答数指令返回值的类型是rtems_interval,是一个非负整数;
*而printf输出的变量类型是unsigned int,若直接输出rtems_interval类型的数据编译时会提示错误;
*注意到两种类型的变量在内存中都占4个字节,使用共同体变量,使用不同类型的变量表示同一段内存里的值,
*可以解决上述问题*/
union time
{
    rtems_interval tick;
    unsigned int count;
}ticks1,ticks2,ticks3,ticks4;

rtems_task Init(rtems_task_argument ignored)
{
UART0_SCALER = ((SYSTEM_CLK * 10)/(BAUDERATE * 8) - 5)/10;
    UART0_CONTRAL = 0x07;

        rtems_status_code status;
       
        /*下面创建了4个同优先级的任务,并依次置于就绪状态*/

        rtems_id tid_2;
rtems_name name_2;       
name_2 = rtems_build_name('A','P','P','2');       
status = rtems_task_create(name_2,2,RTEMS_MINIMUM_STACK_SIZE,
RTEMS_TIMESLICE,RTEMS_NO_FLOATING_POINT,&tid_2);            //创建任务,使能时间片模式,下同       
rtems_task usr_task_2(rtems_task_argument ignored);     //任务的入口地址,下同       
status = rtems_task_start(tid_2,usr_task_2,0);     //任务处于就绪状态,下同
     
rtems_id tid_1;
rtems_name name_1;
name_1 = rtems_build_name('A','P','P','1');       
status = rtems_task_create(name_1,2,RTEMS_MINIMUM_STACK_SIZE,
RTEMS_TIMESLICE,RTEMS_NO_FLOATING_POINT,&tid_1);       
rtems_task usr_task_1(rtems_task_argument ignored);
status = rtems_task_start(tid_1,usr_task_1,1);


rtems_id tid_3;
rtems_name name_3;       
name_3 = rtems_build_name('A','P','P','3');       
status = rtems_task_create(name_3,2,RTEMS_MINIMUM_STACK_SIZE,
RTEMS_TIMESLICE,RTEMS_NO_FLOATING_POINT,&tid_3);       
rtems_task usr_task_3(rtems_task_argument ignored);       
status = rtems_task_start(tid_3,usr_task_3,3);

rtems_id tid_4;
rtems_name name_4;       
name_4 = rtems_build_name('A','P','P','4');       
status = rtems_task_create(name_4,2,RTEMS_MINIMUM_STACK_SIZE,
RTEMS_TIMESLICE,RTEMS_NO_FLOATING_POINT,&tid_4);       
rtems_task usr_task_4(rtems_task_argument ignored);       
status = rtems_task_start(tid_4,usr_task_4,4);

status = rtems_task_delete(RTEMS_SELF);

//exit(1);
}

/*任务1~任务4均为死循环,每次循环中读取系统自启动后经历的滴答数,
*然后输出到屏幕上,由串口调试助手查看*/

//任务1
rtems_task usr_task_1(rtems_task_argument ignored)
{       
while(1)
{   
               ticks1.tick=rtems_clock_get_ticks_since_boot();
    printf("test1 ticks %d \n",ticks1.count);   
}       
}

//任务2
rtems_task usr_task_2(rtems_task_argument ignored)
{   
while(1)
{
         ticks2.tick=rtems_clock_get_ticks_since_boot();
     printf("test2 ticks %d \n",ticks2.count);
}
}

//任务3
rtems_task usr_task_3(rtems_task_argument ignored)
{   
while(1)
{
        ticks3.tick=rtems_clock_get_ticks_since_boot();
    printf("test3 ticks %d \n",ticks3.count);
}
}

//任务4
rtems_task usr_task_4(rtems_task_argument ignored)
{   
while(1)
{
        ticks4.tick=rtems_clock_get_ticks_since_boot();
    printf("test4 ticks %d \n",ticks4.count);       
}
}

/* configuration information */

/* NOTICE: the clock driver is explicitly disabled */
#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER

#define CONFIGURE_MICROSECONDS_PER_TICK 1000     //1 tick = 1000微妙=0.001s
#define CONFIGURE_TICKS_PER_TIMESLICE 50     // 一个时间片有50个滴答

#define CONFIGURE_RTEMS_INIT_TASKS_TABLE
#define CONFIGURE_MAXIMUM_TASKS 5
#define CONFIGURE_MAXIMUM_MESSAGE_QUEUES 1

#define CONFIGURE_INIT

#include <rtems/confdefs.h>

/* end of file */


按照上述代码的流程,由于先启动的任务2,在整个程序的执行过程中,只有任务2在第一次运行时,循环执行了50个滴答,结果是是5次循环读取滴答数,并将结果输出到屏幕上。
而从后面开始执行任务1,任务3,任务4,再返回执行任务2,每个任务都只读取了一次滴答数并输出——这个过程大约耗时10个滴答,并不是按照预想的,每个任务循环执行50个滴答,再执行任务就绪队列中的下一个任务。


这是我当初想当然的看法了,觉得既然每个任务已经使能了时间片功能,然后又在预编译部分定义了时间片相关的参数,然后每个任务就可以依次执行一个时间片然后这样轮着来了。

现在看来不是这样,不还意思,请问前辈——如何清除时钟节拍中断标志?
拜谢不已!

使用特权

评论回复
地板
bh_binghu| | 2016-11-16 11:40 | 只看该作者
每个任务都没有留给其他任务的时间。也就是说每个任务都是想占有所有CPU的时候,
任务切换只是在printf内部,所以导致除第一个任务外,其它都是只能运行一个tick

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

3

主题

5

帖子

0

粉丝