RTEMS 应用程序的初始化过程分析

来源:互联网 发布:java qq登录 编辑:程序博客网 时间:2024/05/02 01:18

注意:本笔记仅代表目前阶段的了解
版本 RTEMS 4.10.2

 
看了RTEMS的hello world例子,代码很简单,只有简单的几行。

rtems_task Init(
  rtems_task_argument ignored
)
{
  printf( "\n\n*** HELLO WORLD TEST ***\n" );
  printf( "Hello World\n" );
  printf( "*** END OF HELLO WORLD TEST ***\n" );
  exit( 0 );
}

再查看其他例子,发现应用程序一般都需要一个初始化函数
rtems_task Init( rtems_task_argument ignored )

从名字也能看出。问题来了,RTEMS怎么知道它就是初始化函数呢?看了好多天代码,
突然发现了点事情。记录如下。

hello 应用中定义了

#define CONFIGURE_INIT
#include <rtems/confdefs.h>

这个文件对应源代码的:
/cpukit/sapi/include/Confdefs.h

#ifdef CONFIGURE_INIT
  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
    }
  };
#endif

可以看出,如果定义了初始化,则使用了一个初始化结构体

#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

可见,这个ENTRY POINT 被定义为 Init 函数。这就联系起来了。接着就是分析 Initialization_tasks 怎么
被调用的。

#define CONFIGURE_INIT_TASK_TABLE Initialization_tasks

rtems_api_configuration_table Configuration_RTEMS_API = {
    CONFIGURE_MAXIMUM_TASKS,
    CONFIGURE_NOTEPADS_ENABLED,
    CONFIGURE_MAXIMUM_TIMERS + CONFIGURE_TIMER_FOR_SHARED_MEMORY_DRIVER,
    CONFIGURE_SEMAPHORES,
    CONFIGURE_MAXIMUM_MESSAGE_QUEUES,
    CONFIGURE_MAXIMUM_PARTITIONS,
    CONFIGURE_MAXIMUM_REGIONS,
    CONFIGURE_MAXIMUM_PORTS,
    CONFIGURE_MAXIMUM_PERIODS,
    CONFIGURE_MAXIMUM_BARRIERS,
    CONFIGURE_INIT_TASK_TABLE_SIZE,
    CONFIGURE_INIT_TASK_TABLE
  };

可以看到,这个config table被注册进去了RTEMS API 的配置列表。

然后发现 Configuration_RTEMS_API 在 /cpukit/rtems/src/Taskinitusers.c 中被使用了。

void _RTEMS_tasks_Initialize_user_tasks_body( void )
  user_tasks = Configuration_RTEMS_API.User_initialization_tasks_table;
  maximum    = Configuration_RTEMS_API.number_of_initialization_tasks;

继续看这个函数,发现了 rtems_task_create 原来RTEMS是根据传入的初始化任务列表,创建1到多个
任务来运行 Init 任务的。

然后跟踪一下这个函数是怎么被调用的

void rtems_initialize_data_structures(void)

_RTEMS_API_Initialize();

void _RTEMS_tasks_Manager_initialization(void)

_API_extensions_Add( &_RTEMS_tasks_API_extensions );

API_extensions_Control _RTEMS_tasks_API_extensions = {
  { NULL, NULL },
  #if defined(FUNCTIONALITY_NOT_CURRENTLY_USED_BY_ANY_API)
    NULL,                                   /* predriver */
  #endif
  _RTEMS_tasks_Initialize_user_tasks,       /* postdriver */
  _RTEMS_tasks_Post_switch_extension        /* post switch */
};

void _RTEMS_tasks_Initialize_user_tasks( void )
{
  if ( _RTEMS_tasks_Initialize_user_tasks_p )
    (*_RTEMS_tasks_Initialize_user_tasks_p)();
}

#ifdef CONFIGURE_INIT
  #if defined(CONFIGURE_RTEMS_INIT_TASKS_TABLE) || \
      defined(CONFIGURE_HAS_OWN_INIT_TASK_TABLE)
    void (_RTEMS_tasks_Initialize_user_tasks_body)(void);
    void (*_RTEMS_tasks_Initialize_user_tasks_p)(void) =
              _RTEMS_tasks_Initialize_user_tasks_body;
  #else
    void (*_RTEMS_tasks_Initialize_user_tasks_p)(void) = NULL;
  #endif
#endif

这里可以看到怎么从 bootcard.c 中从 rtems_initialize_data_structures 开始一步一步的调用初始化
函数。

Etual
2012-12-11

原创粉丝点击