RTEMS初始化线程(task)运行

RTEMS是如何运行第一个任务的?又是怎么样新建任务并进行切换的?

这要从RTEMS运行到boot_card开始说起,boot_card之前的初始化过程可参考之前的博文:

http://blog.csdn.net/hahachenchen789/article/details/52929513


boot_card函数位于c/src/lib/libbsp/shared/boot_card.c文件中,函数在调用完一些驱动和hooking之后,最后调用rtems_initialize_start_multitasking函数来进入初始化task。

void boot_card(
  const char *cmdline
)
{
.......

  /*
   *  Complete initialization of RTEMS and switch to the first task.
   *  Global C++ constructors will be executed in the context of that task.
   */
  rtems_initialize_start_multitasking();

  /***************************************************************
   ***************************************************************
   *  APPLICATION RUNS NOW!!!  We will not return to here!!!     *
   ***************************************************************
   ***************************************************************/
}

rtems_initialize_start_multitasking函数位于rtems/cpukit/sapi/exinit.c中:

void rtems_initialize_start_multitasking(void)
{
  _System_state_Set( SYSTEM_STATE_UP );

  _SMP_Request_start_multitasking();

  _Thread_Start_multitasking();

  /*******************************************************************
   *******************************************************************
   *******************************************************************
   ******                 APPLICATION RUNS HERE                 ******
   ******              THE FUNCTION NEVER RETURNS               ******
   *******************************************************************
   *******************************************************************
   *******************************************************************/
}

那么通常第一个调用的task就是Init,这也是RTEMS的testsuites中大部分例子的第一个task。也就是用户的初始化任务,那么为了保证在其他应用任务启动前初始化任务能先启动,必须给它分配一个较高的优先级。

比如在rtems/testsuites/samples/base_sp中init.c中的函数init就是典型的例子:

rtems_task Init(
  rtems_task_argument argument
)
{
  rtems_name        task_name;
  rtems_id          tid;
  rtems_status_code status;

  TEST_BEGIN();
  printf( "Creating and starting an application task\n" );

  task_name = rtems_build_name( 'T', 'A', '1', ' ' );

  status = rtems_task_create( task_name, 1, RTEMS_MINIMUM_STACK_SIZE,
             RTEMS_INTERRUPT_LEVEL(0), RTEMS_DEFAULT_ATTRIBUTES, &tid );
  directive_failed( status, "create" ); 

  status = rtems_task_start( tid, Application_task, ARGUMENT );
  directive_failed( status, "start" ); 

  status = rtems_task_delete( RTEMS_SELF );
  directive_failed( status, "delete" ); 
}
首先用户初始化任务会创建并启动一个新的任务,然后把自身删除。然后就是运行这个新任务了。


那么用户的初始化任务,也就是init是如何开始运行的?

在cpukit/rtems/include/rtems/rtems/tasks.h中定义了系统的初始化任务表这样一个数据结构,包含了初始化任务的名字,栈的大小,初始的优先级,属性,入口点等参数。

typedef struct {
  /** This is the Initialization Task's name. */
  rtems_name            name;
  /** This is the Initialization Task's stack size. */
  size_t                stack_size;
  /** This is the Initialization Task's priority. */
  rtems_task_priority   initial_priority;
  /** This is the Initialization Task's attributes. */
  rtems_attribute       attribute_set;
  /** This is the Initialization Task's entry point. */
  rtems_task_entry      entry_point;
  /** This is the Initialization Task's initial mode. */
  rtems_mode            mode_set;
  /** This is the Initialization Task's argument. */
  rtems_task_argument	argument;
} rtems_initialization_tasks_table;

在cpukit/sapi/include/confdefs.h中定义哥系统的初始化任务表,只包含一个初始化任务:

  rtems_initialization_tasks_table Initialization_tasks[] = {
    { CONFIGURE_INIT_TASK_NAME,
      CONFIGURE_INIT_TASK_STACK_SIZE,
      CONFIGURE_INIT_TASK_PRIORITY,
      CONFIGURE_INIT_TASK_ATTRIBUTES,
      CONFIGURE_INIT_TASK_ENTRY_POINT,
      CONFIGURE_INIT_TASK_INITIAL_MODES,
      CONFIGURE_INIT_TASK_ARGUMENTS
    }
  };
其中CONFIGURE_INIT_TASK_ENTRY_POINT的定义如下:
#ifndef CONFIGURE_INIT_TASK_ENTRY_POINT
  #ifdef __cplusplus
  extern "C" {
  #endif
    rtems_task Init (rtems_task_argument );
  #ifdef __cplusplus
  }
  #endif
  #define CONFIGURE_INIT_TASK_ENTRY_POINT   Init
  extern const char* bsp_boot_cmdline;
  #define CONFIGURE_INIT_TASK_ARGUMENTS     ((rtems_task_argument) &bsp_boot_cmdline)
#endif
也就是说如果用户没有定义 CONFIGURE_INIT_TASK_ENTRY_POINT,则系统会将init作为默认的初始化任务的入口点。也就是转到了init函数。而且CONFIGURE_INIT_TASK_PRIORITY的值为1,优先级非常高,仅次于0,因此能够保证其优先执行。

ps:RTEMS共256个优先级(0-255).数字越小,优先级越高,要注意的是RTEMS与POSIX标准正好相反,所以使用RTEMS的标准时,会转化为POSIX的优先级,转化方法是Prtems=255-Pposix。


那么在RTEMS中 新建一个task的函数就是 rtems_task_create

rtems_status_code rtems_task_create(
  rtems_name           name,
  rtems_task_priority  initial_priority,
  size_t               stack_size,
  rtems_mode           initial_modes,
  rtems_attribute      attribute_set,
  rtems_id            *id
);

可以利用该函数实现多线程。

注意:该函数从功能上类似于Unix中的fork和exec,但是不同的在于,Unix具有内存管理功能,fork和exec函数之后的父进程和子进程之间的地址空间是隔离的。但是RTEMS并不具有这种功能,因此更为准确的描述是该函数与POSIX 的thread功能相同。


  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值