博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
rtems网络移植-rtems系统初始化过程分析
阅读量:6855 次
发布时间:2019-06-26

本文共 11621 字,大约阅读时间需要 38 分钟。

rtems的网络驱动移植,首先要知道如何将设备初始化函数放入初始化过程中,如何将这个网卡设备注册到系统中。这涉及到rtems的系统初始化,接下来就具体分析初始化过程:

系统初始化第一阶段:

这部分代码主要是用汇编写的,属于bsp的一部分,然后rtems进入基于c代码的初始化第二阶段,但在进入第二阶段之前,必须要有一个可靠的运行环境,这就是第一阶段的汇编代码的工作,总结如下:

  • 屏蔽中断
  • 初始化cpu工作模式
  • 建立内核堆栈
  • 对bss段清零
  • 建立基本的内存布局

最开始的代码位于/rtems/c/src/lib/libbsp/pc386(这里选择对应的处理器)/start/start.s

函数调用如下图所示:
这里写图片描述

大致的执行流程如下:

  • 屏蔽中断
  • 读取grub传递的multiboot_info,存放到boot_multiboot_info结构中
  • 跳转到_load_segment处,加载与pc硬件相关的全局描述符和中断描述符
  • 跳转到_establish,建立rtems内核栈空间
  • 清除BSS
  • 调用initvideo函数进行显示初始化
  • 调用checkcputypesetcr0查找cpu类型
  • 设定调用参数,调用第一个c函数boot_card

系统初始化第二阶段:

这一阶段主要是初始化内核组件和驱动程序做准备,与bsp联系紧密,主要工作如下:

  • 初始化rtems_cpu_table结构体的cpu_table全局变量
  • 初始化rtems_configuration_table结构体的configuration全局变量
  • 设置rtems workspace区域
  • 初始化中断和异常管理 初始化pci bios interface

执行流程:

这里写图片描述

boot_card函数首先更新cpu配置表和rtems配置表,然后调用bsp_start函数,该函数主要完成以下工作:

  • 计算1ms时间指令的loop值
  • 进一步更新rtems的cpu配置表
  • 制定rtems的workspace的起始地址并分配空间
  • 初始化pci bios interface

执行完bsp_start函数后,进入第三阶段,开始执行rtems_initialize_executive_early函数。

系统初始化第三阶段:

这一阶段的工作量相对于前两个阶段要大很多,其最终目的是完成多任务切换,并切换到用户提供的任务,这部分主要工作是:

  • 初始化rtems核心层和系统服务层的功能组件
  • 初始化驱动程序
  • 进行多任务初始化

初始化管理器组件介绍:

当板级支持包bsp完成硬件级的基本初始化工作后,把控制权交给初始化管理器,初始化管理器的工作主要是负责启动和关闭rtems,启动rtems包括创建并且启动所有的配置好的初始化任务,并且初始化rtems系统使用到的设备驱动程序。

初始化rtems:

初始化管理器的主要操作体现在rtems_initialize_executive函数的实现机制,如果不使用该机制,也可以采用rtems_initialize_executive_early函数和rtems_initialize_executive_late函数的实现机制初始化。在rtems只能使用一种方法初始化系统化,不能重复初始化。

初始化所有的驱动程序:

这分成四个步骤,在具体执行初始化驱动程序之前,需要执行钩子函数(predriver_hook),然后执行IO_initialize_all_drivers()来完成具体的驱动程序初始化过程。
具体代码如下:
bootcard.c

/** * @file * * @ingroup bsp_bootcard * * @brief Standard system startup. * *  This is the C entry point for ALL RTEMS BSPs.  It is invoked *  from the assembly language initialization file usually called *  start.S.  It provides the framework for the BSP initialization *  sequence.  For the basic flow of initialization see RTEMS C User's Guide, *  Initialization Manager. * *  This style of initialization ensures that the C++ global *  constructors are executed after RTEMS is initialized. *  Thanks to Chris Johns 
for the idea * to move C++ global constructors into the first task. *//* * COPYRIGHT (c) 1989-2014. * On-Line Applications Research Corporation (OAR). * * The license and distribution terms for this file may be * found in the file LICENSE in this distribution or at * http://www.rtems.org/license/LICENSE. */#include
#include
#include
/* * At most a single pointer to the cmdline for those target * short on memory and not supporting a command line. */const char *bsp_boot_cmdline;RTEMS_SYSINIT_ITEM( bsp_work_area_initialize, RTEMS_SYSINIT_BSP_WORK_AREAS, RTEMS_SYSINIT_ORDER_MIDDLE);RTEMS_SYSINIT_ITEM( bsp_start, RTEMS_SYSINIT_BSP_START, RTEMS_SYSINIT_ORDER_MIDDLE);RTEMS_SYSINIT_ITEM( bsp_predriver_hook, RTEMS_SYSINIT_BSP_PRE_DRIVERS, RTEMS_SYSINIT_ORDER_MIDDLE);/* * This is the initialization framework routine that weaves together * calls to RTEMS and the BSP in the proper sequence to initialize * the system while maximizing shared code and keeping BSP code in C * as much as possible. */void boot_card( const char *cmdline){ rtems_interrupt_level bsp_isr_level; /* * Make sure interrupts are disabled. */ (void) bsp_isr_level; rtems_interrupt_local_disable( bsp_isr_level ); bsp_boot_cmdline = cmdline; rtems_initialize_executive(); /*************************************************************** *************************************************************** * APPLICATION RUNS NOW!!! We will not return to here!!! * *************************************************************** ***************************************************************/}

其中包含了三个初始化函数的调用:

RTEMS_SYSINIT_ITEM(  bsp_work_area_initialize,  RTEMS_SYSINIT_BSP_WORK_AREAS,  RTEMS_SYSINIT_ORDER_MIDDLE);RTEMS_SYSINIT_ITEM(  bsp_start,  RTEMS_SYSINIT_BSP_START,  RTEMS_SYSINIT_ORDER_MIDDLE);RTEMS_SYSINIT_ITEM(  bsp_predriver_hook,  RTEMS_SYSINIT_BSP_PRE_DRIVERS,  RTEMS_SYSINIT_ORDER_MIDDLE);

boot_card函数中,包含rtems_initialize_executive函数,这是初始化管理函数,位于exinit.c文件中:

exinit.c

/** * @file * * @brief Initialization Manager * * @ingroup ClassicRTEMS *//* *  COPYRIGHT (c) 1989-2014. *  On-Line Applications Research Corporation (OAR). * *  The license and distribution terms for this file may be *  found in the file LICENSE in this distribution or at *  http://www.rtems.org/license/LICENSE. */#if HAVE_CONFIG_H#include "config.h"#endif#include 
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
const char _Copyright_Notice[] ="COPYRIGHT (c) 1989-2008.\n\On-Line Applications Research Corporation (OAR).\n";static Objects_Information *_Internal_Objects[ OBJECTS_INTERNAL_CLASSES_LAST + 1 ];static Objects_Information *_RTEMS_Objects[ OBJECTS_RTEMS_CLASSES_LAST + 1 ];static Objects_Information *_POSIX_Objects[ OBJECTS_POSIX_CLASSES_LAST + 1 ];Objects_Information ** const_Objects_Information_table[ OBJECTS_APIS_LAST + 1 ] = { NULL, &_Internal_Objects[ 0 ], &_RTEMS_Objects[ 0 ], &_POSIX_Objects[ 0 ]};API_Mutex_Control *_RTEMS_Allocator_Mutex;API_Mutex_Control *_Once_Mutex;static void rtems_initialize_data_structures(void){ /* * Dispatching and interrupts are disabled until the end of the * initialization sequence. This prevents an inadvertent context * switch before the executive is initialized. * * WARNING: Interrupts should have been disabled by the BSP and * are disabled by boot_card(). */ /* * Initialize any target architecture specific support as early as possible */ _CPU_Initialize(); _Thread_Dispatch_initialization(); _ISR_Handler_initialization(); _API_Mutex_Initialization( 2 ); _API_Mutex_Allocate( &_RTEMS_Allocator_Mutex ); _API_Mutex_Allocate( &_Once_Mutex ); _Thread_Handler_initialization(); _Scheduler_Handler_initialization(); _SMP_Handler_initialize();}RTEMS_LINKER_ROSET( _Sysinit, rtems_sysinit_item );RTEMS_SYSINIT_ITEM( rtems_initialize_data_structures, RTEMS_SYSINIT_DATA_STRUCTURES, RTEMS_SYSINIT_ORDER_MIDDLE);/* * No threads should be created before this point!!! * _Thread_Executing and _Thread_Heir are not set. * * At this point all API extensions are in place. After the call to * _Thread_Create_idle() _Thread_Executing and _Thread_Heir will be set. * * Scheduling can properly occur afterwards as long as we avoid dispatching. */RTEMS_SYSINIT_ITEM( _Thread_Create_idle, RTEMS_SYSINIT_IDLE_THREADS, RTEMS_SYSINIT_ORDER_MIDDLE);/* Initialize I/O drivers. * * Driver Manager note: * All drivers may not be registered yet. Drivers will dynamically * be initialized when registered in level 2,3 and 4. */RTEMS_SYSINIT_ITEM( _IO_Initialize_all_drivers, RTEMS_SYSINIT_DEVICE_DRIVERS, RTEMS_SYSINIT_ORDER_MIDDLE);void rtems_initialize_executive(void){ const volatile rtems_sysinit_item *cur = RTEMS_LINKER_SET_BEGIN(_Sysinit ); const volatile rtems_sysinit_item *end = RTEMS_LINKER_SET_END( _Sysinit ); /* Invoke the registered system initialization handlers */ while ( cur != end ) { ( *cur->handler )(); ++cur; } _System_state_Set( SYSTEM_STATE_UP ); _SMP_Request_start_multitasking(); _Thread_Start_multitasking(); /******************************************************************* ******************************************************************* ******************************************************************* ****** APPLICATION RUNS HERE ****** ****** THE FUNCTION NEVER RETURNS ****** ******************************************************************* ******************************************************************* *******************************************************************/}

在该文件中,包含了IO_initialize_all_drivers()函数的调用:

RTEMS_SYSINIT_ITEM(  _IO_Initialize_all_drivers,  RTEMS_SYSINIT_DEVICE_DRIVERS,  RTEMS_SYSINIT_ORDER_MIDDLE);

IO_initialize_all_drivers()函数的定义在io.c文件中

#if HAVE_CONFIG_H#include "config.h"#endif#include 
bool _IO_All_drivers_initialized;void _IO_Initialize_all_drivers( void ){ rtems_device_major_number major; _IO_All_drivers_initialized = true; for ( major=0 ; major < _IO_Number_of_drivers ; major ++ ) (void) rtems_io_initialize( major, 0, NULL );}

可以看到,主要是利用for循环rtems_io_initialize函数进行初始化,其中major就是driver的注册的数量,查找rtems_io_initialize函数的实现,在ioInitialize.c文件中:

ioInitialize.c

#if HAVE_CONFIG_H#include "config.h"#endif#include 
rtems_status_code rtems_io_initialize( rtems_device_major_number major, rtems_device_minor_number minor, void *argument){ rtems_device_driver_entry callout; if ( major >= _IO_Number_of_drivers ) return RTEMS_INVALID_NUMBER; callout = _IO_Driver_address_table[major].initialization_entry; return callout ? callout(major, minor, argument) : RTEMS_SUCCESSFUL;}

从该函数的实现可以看出,其实驱动函数的初始化就是调用_IO_Driver_address_table这个表中驱动设备的初始化入口成员函数,也就是initialization_entry,现在就比较明朗了,只要查找_IO_Driver_address_table表,然后向其中添加设备注册即可。该表位于confdefs.h文件中。

rtems_driver_address_table    _IO_Driver_address_table[ CONFIGURE_MAXIMUM_DRIVERS ] = {    #ifdef CONFIGURE_BSP_PREREQUISITE_DRIVERS      CONFIGURE_BSP_PREREQUISITE_DRIVERS,    #endif    #ifdef CONFIGURE_APPLICATION_PREREQUISITE_DRIVERS      CONFIGURE_APPLICATION_PREREQUISITE_DRIVERS,    #endif    #ifdef CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER      CONSOLE_DRIVER_TABLE_ENTRY,    #endif    #ifdef CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER      CLOCK_DRIVER_TABLE_ENTRY,    #endif    #ifdef CONFIGURE_APPLICATION_NEEDS_RTC_DRIVER      RTC_DRIVER_TABLE_ENTRY,    #endif    #ifdef CONFIGURE_APPLICATION_NEEDS_WATCHDOG_DRIVER      WATCHDOG_DRIVER_TABLE_ENTRY,    #endif    #ifdef CONFIGURE_APPLICATION_NEEDS_STUB_DRIVER      DEVNULL_DRIVER_TABLE_ENTRY,    #endif    #ifdef CONFIGURE_APPLICATION_NEEDS_ZERO_DRIVER      DEVZERO_DRIVER_TABLE_ENTRY,    #endif    #ifdef CONFIGURE_APPLICATION_NEEDS_IDE_DRIVER      IDE_CONTROLLER_DRIVER_TABLE_ENTRY,    #endif    #ifdef CONFIGURE_APPLICATION_NEEDS_ATA_DRIVER      ATA_DRIVER_TABLE_ENTRY,    #endif    #ifdef CONFIGURE_APPLICATION_NEEDS_FRAME_BUFFER_DRIVER      FRAME_BUFFER_DRIVER_TABLE_ENTRY,    #endif    #ifdef CONFIGURE_APPLICATION_EXTRA_DRIVERS      CONFIGURE_APPLICATION_EXTRA_DRIVERS,    #endif    #ifdef CONFIGURE_APPLICATION_NEEDS_NULL_DRIVER      NULL_DRIVER_TABLE_ENTRY    #elif !defined(CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER) && \        !defined(CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER) && \        !defined(CONFIGURE_APPLICATION_NEEDS_RTC_DRIVER) && \        !defined(CONFIGURE_APPLICATION_NEEDS_STUB_DRIVER) && \        !defined(CONFIGURE_APPLICATION_NEEDS_ZERO_DRIVER) && \        !defined(CONFIGURE_APPLICATION_NEEDS_IDE_DRIVER) && \        !defined(CONFIGURE_APPLICATION_NEEDS_ATA_DRIVER) && \        !defined(CONFIGURE_APPLICATION_NEEDS_FRAME_BUFFER_DRIVER) && \        !defined(CONFIGURE_APPLICATION_EXTRA_DRIVERS)      NULL_DRIVER_TABLE_ENTRY    #endif  };

可以看到这个table包含了很多外设的宏entry入口,比如console、clock等,接下来以console串口的entry举例,CONSOLE_DRIVER_TABLE_ENTRY,该宏定义位于console.h中:

#define CONSOLE_DRIVER_TABLE_ENTRY \  { console_initialize, console_open, console_close, \    console_read, console_write, console_control }

发现宏中包含了很多console函数的声明:

console_initialize:

rtems_device_driver console_initialize(  rtems_device_major_number  major,  rtems_device_minor_number  minor,  void                      *arg);

参数major:设备驱动的主号码

参数minor:设备驱动的次号码
当返回RTEMS_SUCCESSFUL表示初始化成功

这些函数的实现基本都是在具体的处理器和bsp代码中。所以可移植性很强。只要保证接口函数相同即可。

最后在rtems_initialize_executive函数中,执行_Thread_Start_multitasking();开始多任务模式,rtems的系统初始化工作就结束了。

转载于:https://www.cnblogs.com/sichenzhao/p/9320307.html

你可能感兴趣的文章
如果你没被WannaCry感染就一定要小心Adylkuzz
查看>>
HR:2017/2018年数据中心驱动400Gbps部署
查看>>
单元测试覆盖工具coverlipse
查看>>
Jmeter分布式部署文档
查看>>
微软打算用DNA存储数据 但成本和速度仍是个大问题
查看>>
使用Java向properties存数据
查看>>
产能过剩的光伏电池,是否还是未来的朝阳产业?
查看>>
如何在SaaS企业及服务市场上站稳脚跟
查看>>
移动端App测试实用指南(下)
查看>>
为什么没有一个软件质量保证的RUP工作流程
查看>>
海尔王淼:智能家居互联互通先解决用户需求
查看>>
商务部:中国将采取一切措施维护光伏企业合法权益
查看>>
MySQL数据库开发必备常识
查看>>
晶科能源力促分布式光伏行业标准制定
查看>>
苏征:大贲科技让酒店更智慧
查看>>
Ascent公司在亚特兰大和多伦多收购数据中心资产
查看>>
linux 安装 node
查看>>
“不劳而获”的数字货币真的存在么?
查看>>
k8s拾遗 - Secret
查看>>
Android SparseArray 原理解析
查看>>