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

时间:2021-04-25 19:22:43
各位大大,在下在学习RTEMS时遇到了一点疑问:
 
        我在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个滴答后,再开始新一轮的循环。为什么会出现上面这种情况,求各位大大解惑。
        在下不胜感激!


     

4 个解决方案

#1


每个任务下加while(true)循环了吗?还是系统调度原因,执行完一个任务后,执行就绪的任务???

#2


#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 */

#3


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

求问各位大侠解惑,感激不尽!

#4


急求大神帮助啊!
拜谢各位了!

#1


每个任务下加while(true)循环了吗?还是系统调度原因,执行完一个任务后,执行就绪的任务???

#2


#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 */

#3


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

求问各位大侠解惑,感激不尽!

#4


急求大神帮助啊!
拜谢各位了!