注意:本笔记仅代表目前阶段的了解
版本 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