VxWorks5.5之usrRoot函数源码分析

本文详细介绍了VxWorks内核初始化过程中的关键步骤,特别是usrRoot函数的作用及其内部如何进行系统初始化,包括内存池初始化、I/O系统初始化、驱动安装、网络初始化等。同时,阐述了时钟中断处理程序的注册和启用,通过sysClkConnect函数连接系统时钟中断,进而调用sysClkInt函数处理时钟中断,最后通过usrClock函数实现系统计时功能。

做完项目报告,可以休息几天了,所以接着看BSP源码。在经过usrInit函数做一些必要的初始化后,开始调用usrRoot执行第一个内核任务,同样以S3C2410为例,内核以VxWorks_rom为例进行详细的分析。

/*******************************************************************************
*
* usrRoot - the root task
*
* This is the first task to run under the multitasking kernel.  It performs
* all final initialization and then starts other tasks.
*
* It initializes the I/O system, installs drivers, creates devices, and sets
* up the network, etc., as necessary for a particular configuration.  It
* may also create and load the system symbol table, if one is to be included.
* It may then load and spawn additional tasks as needed.  In the default
* configuration, it simply initializes the VxWorks shell.
*
* 初始化I/O系统,安装驱动,创建设备,设置网络等,另外可能创建和加载系统符号表,默认配置下,只是简单初始化VxWorks shell.
* RETURNS: N/A
*/

void usrRoot
    (
    char *	pMemPoolStart,		/* start of system memory partition */
    unsigned	memPoolSize		/* initial size of mem pool */
    )
    {
    char tyName [20];
    int  ix;

    /* Initialize the memory pool before initializing any other package.
     * The memory associated with the root task will be reclaimed at the
     * completion of its activities.
     */

#ifdef INCLUDE_MEM_MGR_FULL//在Makefile中定义
    memInit (pMemPoolStart, memPoolSize);	/* initialize memory pool */
#endif /* INCLUDE_MEM_MGR_FULL */

#ifdef	INCLUDE_SHOW_ROUTINES//在Makefile中定义
    memShowInit ();				/* initialize memShow routine */
#endif	/* INCLUDE_SHOW_ROUTINES */

#if	defined(INCLUDE_MMU_BASIC) || defined(INCLUDE_MMU_FULL) || \
	defined(INCLUDE_MMU_MPU)//在Makefile中定义了INCLUDE_MMU_BASIC
    usrMmuInit ();				/* initialize the mmu */
#endif	/* defined(INCLUDE_MMU_BASIC, INCLUDE_MMU_FULL, INCLUDE_MMU_MPU) */

    /* set up system timer */

    sysClkConnect ((FUNCPTR) usrClock, 0);	/* connect clock ISR 在2410Timer.c中定义*/
    sysClkRateSet (SYS_CLK_RATE);	/* set system clock rate */
    sysClkEnable ();				/* start it */

    /*
     * The select library needs to be initialized before the tyLib module
     * since the _func_selWakeupListInit FUNCPTR is required (SPR #3314).
     * The installation of the select task delete hooks is performed
     * later in usrRoot() after NFS and RPC have been initialized.
     */
    selectInit (NUM_FILES);//默认定义NUM_FILES为50

    /* initialize I/O system */

#ifdef  INCLUDE_IO_SYSTEM
    iosInit (NUM_DRIVERS, NUM_FILES, "/null");

    consoleFd = NONE;                           /* assume no console device */
#ifdef  INCLUDE_TTY_DEV
    if (NUM_TTY > 0)
	{
	ttyDrv();				/* install console driver */

	for (ix = 0; ix < NUM_TTY; ix++)	/* create serial devices */
	    {
#if     (defined( ttyDevCreate ) && (WDB_COMM_TYPE == WDB_COMM_SERIAL))
	    if (ix == WDB_TTY_CHANNEL)		/* don't use WDBs channel */
		continue;
#endif
	    sprintf (tyName, "%s%d", "/tyCo/", ix);
	    (void) ttyDevCreate (tyName, sysSerialChanGet(ix), 512, 512);//read buffer 为512字节,write buffer也为512字节

	    if (ix == CONSOLE_TTY)		/* init the tty console *//*#define CONSOLE_TTY 1*/
		{
		strcpy (consoleName, tyName);
		consoleFd = open (consoleName, O_RDWR, 0);
		(void) ioctl (consoleFd, FIOBAUDRATE, CONSOLE_BAUD_RATE);
		(void) ioctl (consoleFd, FIOSETOPTIONS, OPT_TERMINAL);
		}
	    }
	}
#endif  /* INCLUDE_TTY_DEV */
    ioGlobalStdSet (STD_IN,  consoleFd);//设置标准输入设备
    ioGlobalStdSet (STD_OUT, consoleFd);//设置标准输出设备
    ioGlobalStdSet (STD_ERR, consoleFd);//设置标准错误设备
#endif  /* INCLUDE_IO_SYSTEM */

    /* initialize symbol table facilities */
    hashLibInit ();			/* initialize hash table package */
    symLibInit ();			/* initialize symbol table package */
    symShowInit ();			/* initialize symbol table show */

    /* initialize exception handling */
    excShowInit ();
    excInit ();				/* initialize exception handling */

    lstLibInit ();

    logInit (consoleFd, MAX_LOG_MSGS);	/* initialize logging */

    sigInit ();				/* initialize signals */

    /* initialize debugging */
    dbgInit ();				/* initialize debugging */
    /* initialize pipe driver */
    pipeDrv ();				/* install pipe driver */

    /* initialize standard I/O package */
    stdioInit ();			/* initialize standard I/O library */
    stdioShowInit ();

    cbioLibInit();

    /* initialize filesystems and disk drivers */

#ifdef INCLUDE_DOSFS_MAIN  /* dosFs2 file system initialization */

    hashLibInit ();			/* initialize hash table package */

    /* First initialize the main dosFs module */

    dosFsLibInit( 0 );

    /* Initialize sub-modules */

    /* ensure that at least one directory handler is defined */
    /* init VFAT (MS long file names) module */
    /* Sub-module: VFAT Directory Handler */

    dosVDirLibInit();

    /* init strict 8.3 and vxLongNames handler */
#   ifdef INCLUDE_DOSFS_DIR_FIXED

    /* Sub-module: Vintage 8.3 and VxLong Directory Handler */

    dosDirOldLibInit();

#   endif /* INCLUDE_DOSFS_DIR_FIXED */

    /* Sub-module: FAT12/FAT16/FAT32 FAT Handler */

    dosFsFatInit();

#   ifdef INCLUDE_DOSFS_CHKDSK 

    /* Sub-module: Consistency check handler */

    dosChkLibInit();

#   endif /* INCLUDE_DOSFS_CHKDSK */

#   ifdef INCLUDE_DOSFS_FMT

    /* Sub-module: Formatter */

    dosFsFmtLibInit();           /* init dosFs scalable formatter */

#   endif /* INCLUDE_DOSFS_FMT */

#endif /* INCLUDE_DOSFS_MAIN */

    /* dosFs1 legacy code, dosFsInit(), usrDosFsOld.c */
#ifdef	INCLUDE_DOSFS
    hashLibInit ();			/* initialize hash table package */
    dosFsInit (NUM_DOSFS_FILES); 	/* init dosFs filesystem */
#endif	/* INCLUDE_DOSFS */

#ifdef	INCLUDE_RAMDRV
    ramDrv ();				/* initialize ram disk driver */
#endif	/* INCLUDE_RAMDRV */

    /* initialize USB components */
#ifdef INCLUDE_USB_INIT
    usbInit (); 		/* USB Host Stack Initialization */
#endif

#ifdef	INCLUDE_TFFS
    tffsDrv ();				/* it should be after pcmciaInit() */
#endif	/* INCLUDE_TFFS */

#ifdef  INCLUDE_FORMATTED_IO
    fioLibInit ();			/* initialize formatted I/O */
#endif  /* INCLUDE_FORMATTED_IO */

    /* initialize floating point facilities */

#ifdef	INCLUDE_FLOATING_POINT
    floatInit ();			/* initialize floating point I/O */
#endif	/* INCLUDE_FLOATING_POINT */

    /* install software floating point emulation (if applicable) */

#ifdef	INCLUDE_SW_FP
    mathSoftInit ();		/* use software emulation for fp math */
#endif	/* INCLUDE_SW_FP */


    /* initialize performance monitoring tools */
#ifdef	INCLUDE_TIMEX
    timexInit ();			/* install function timing tool */
#endif	/* INCLUDE_TIMEX */

#ifdef  INCLUDE_ENV_VARS
    envLibInit (ENV_VAR_USE_HOOKS);	/* initialize environment variable */
#endif	/* INCLUDE_ENV_VARS */

    /* initialize object module loader */

#ifdef	INCLUDE_LOADER
    moduleLibInit ();			/* initialize module manager */

#if	defined(INCLUDE_AOUT)
    loadAoutInit ();				/* use a.out format */
#else	/* coff or ecoff */
#if	defined(INCLUDE_COFF)
    loadCoffInit ();				/* use coff format */
#else   /* coff */
#if	defined(INCLUDE_ELF)
    loadElfInit ();				/* use elf format */
#else
#if	defined(INCLUDE_SOM_COFF)
    loadSomCoffInit ();
#else
#if	defined(INCLUDE_PECOFF)
    {
    extern int loadPecoffInit();

    loadPecoffInit ();
    }
#endif
#endif
#endif
#endif
#endif
#endif

#endif	/* INCLUDE_LOADER */
    /* initialize network */
#ifdef  INCLUDE_NET_INIT
    usrBootLineInit (sysStartType);	/* crack the bootline */
    usrNetInit (BOOT_LINE_ADRS);	/* initialize network support */
#endif	/* INCLUDE_NET_INIT */

    /* initialize shared memory objects */

#ifdef INCLUDE_SM_OBJ			/* unbundled shared memory objects */
    usrSmObjInit (BOOT_LINE_ADRS);
#endif /* INCLUDE_SM_OBJ */

    /* write protect text segment & vector table only after bpattach () */
    /* install select hook only after NFS/RPC for proper delete hook order */

#ifdef	INCLUDE_SELECT
    selTaskDeleteHookAdd ();
#endif	/* INCLUDE_SELECT */

    /* create system and status symbol tables */

#ifdef  INCLUDE_STANDALONE_SYM_TBL
    sysSymTbl = symTblCreate (SYM_TBL_HASH_SIZE_LOG2, TRUE, memSysPartId);
    printf ("\nAdding %ld symbols for standalone.\n", standTblSize);
    /* fill in from built in table*/
    for (ix = 0; (ULONG) ix < standTblSize; ix++)
	symTblAdd (sysSymTbl, &(standTbl[ix]));
#endif	/* INCLUDE_STANDALONE_SYM_TBL */

#ifdef  INCLUDE_NET_SYM_TBL
    sysSymTbl = symTblCreate (SYM_TBL_HASH_SIZE_LOG2, TRUE, memSysPartId);

    netLoadSymTbl ();				/* fill in table from host */
#endif	/* INCLUDE_NET_SYM_TBL */

#ifdef  INCLUDE_STAT_SYM_TBL
    statSymTbl = symTblCreate (STAT_TBL_HASH_SIZE_LOG2, FALSE, memSysPartId);

    for (ix = 0; (ULONG)ix < statTblSize; ix ++) /* fill in from builtin table*/
	symTblAdd (statSymTbl, &(statTbl [ix]));
#endif	/* INCLUDE_STAT_SYM_TBL */
#ifdef  INCLUDE_CTORS_DTORS 
  /* 
   * call compiler generated init functions (usually - but not necessarily -
   * C++ related)
   */
   cplusCtorsLink ();
#endif

    /* initialize Wind Web Server */

#ifdef INCLUDE_HTTP
    httpd ();
#endif /* INCLUDE_HTTP */

#ifdef   INCLUDE_RBUFF                  /* install rBuff support */
    rBuffLibInit();
    rBuffShowInit ();                   /* install rBuff show routine */
#endif /* INCLUDE_RBUFF */


    /* initialize the WDB debug agent */

#ifdef  INCLUDE_WDB
    wdbConfig();
#ifdef	INCLUDE_WDB_BANNER

#if (WDB_COMM_TYPE ==  WDB_COMM_END)
#define WDB_COMM_TYPE_STR "WDB_COMM_END"
#endif /* WDB_COMM_TYPE == WDB_COMM_END */

#ifndef INCLUDE_SHELL
    /* WDB banner same as printed by usrWdbBanner */
    printf ("\n\n");
    printf ("%23s\n\n", runtimeName);
    printf ("Copyright 1984-2002  Wind River Systems, Inc.\n\n");
    printf ("            CPU: %s\n", sysModel ());
    printf ("   Runtime Name: %s\n", runtimeName);
    printf ("Runtime Version: %s\n", runtimeVersion);
    printf ("    BSP version: " BSP_VERSION BSP_REV "\n");
    printf ("        Created: %s\n", creationDate);
    printf ("  WDB Comm Type: %s\n", WDB_COMM_TYPE_STR);
    printf ("            WDB: %s.\n\n",
	    ((wdbRunsExternal () || wdbRunsTasking ()) ?
		 "Ready" : "Agent configuration failed") );
#endif /*INCLUDE_SHELL*/

#endif /*INCLUDE_WDB_BANNER*/

#endif  /* INCLUDE_WDB */

    /* initialize interactive shell */

#ifdef  INCLUDE_SHELL
    printLogo ();				/* print out the banner page */

    printf ("                               ");
    printf ("CPU: %s.  Processor #%d.\n", sysModel (), sysProcNumGet ());
    printf ("                              ");
    printf ("Memory Size: 0x%x.", (UINT)(sysMemTop () - (char *)LOCAL_MEM_LOCAL_ADRS));
    printf ("  BSP version " BSP_VERSION BSP_REV ".");
#if defined(INCLUDE_WDB) && defined(INCLUDE_WDB_BANNER)
    printf ("\n                             ");
    printf ("WDB Comm Type: %s", WDB_COMM_TYPE_STR);
    printf ("\n                            ");
    printf ("WDB: %s.",
	    ((wdbRunsExternal () || wdbRunsTasking ()) ?
		 "Ready" : "Agent configuration failed") );
#endif /*INCLUDE_WDB && INCLUDE_WDB_BANNER*/
    printf ("\n\n");
    shellInit (SHELL_STACK_SIZE, TRUE);		/* create the shell */
#endif	/* INCLUDE_SHELL */

#if defined(INCLUDE_JAVA)
    javaConfig ();
#endif	/* INCLUDE_JAVA */

#ifdef INCLUDE_HTML
    usrHtmlInit ();
#endif /* INCLUDE_HTML */

#ifdef INCLUDE_USER_APPL
    /* Startup the user's application */
    USER_APPL_INIT;	/* must be a valid C statement or block */
#endif

    }
其中进行了时钟中断的注册和启用,详细代码如下:

/*******************************************************************************
*
* sysClkConnect - connect a routine to the system clock interrupt
*
* This routine specifies the interrupt service routine to be called at each
* clock interrupt.  Normally, it is called from usrRoot() in usrConfig.c to 
* connect usrClock() to the system clock interrupt.
*
* RETURN: OK, or ERROR if the routine cannot be connected to the interrupt.
*
* SEE ALSO: intConnect(), usrClock(), sysClkEnable()
*/

STATUS sysClkConnect
    (
    FUNCPTR routine,    /* routine to be called at each clock interrupt */
    int arg        /* argument with which to call routine */
    )
    {
	UINT32 oier;    

    if (sysClkConnected == FALSE)
        {
        /* counter is 16bits so must be divide*/
        SNGS3C_REG_READ (rTCFG0, oier);
        oier &=0xffffff00;	/*TIMER0-1 PRESCALER=99 */  
        oier |=0x00000063;
        SNGS3C_REG_WRITE (rTCFG0, oier); 
        
        SNGS3C_REG_READ (rTCFG1,oier);
        oier &=0xfffffff0;	/*div=2*/
        SNGS3C_REG_WRITE (rTCFG1,oier);  /*TIMER0 0.64/2=320kHZ*//*外设总线时钟PCLK=50MHZ?? TIMER0 OUT = 50MHZ/(99+1)/2=250KHZ*/
        
        SNGS3C_REG_READ (rTCON, oier);
        oier = (oier & 0xffffff00) | AUTO_RELOAD_TIMER0; /*设置Timer0的方式为自动重载*/
        SNGS3C_REG_WRITE (rTCON, oier);
        sysHwInit2 ();  /* timer int initial here*/
        sysClkConnected = TRUE;
        }

    sysClkRoutine   = NULL;
    sysClkArg        = arg;

    sysClkRoutine = routine;

    return (OK);
    }
/*******************************************************************************
*
* sysHwInit2 - additional system configuration and initialization
*
* This routine connects system interrupts and does any additional
* configuration necessary.  Note that this is called from
* sysClkConnect() in the timer driver.
*
* RETURNS: N/A
*
*/

void sysHwInit2 (void)
    {
    static BOOL initialised = FALSE;

    if (initialised)
    	return;

    /* initialize the interrupt library and interrupt driver */
    intLibInit (SNGS3C_INTNUMLEVELS, SNGS3C_INTNUMLEVELS, INT_MODE);
    sngs3cIntDevInit();

    /* connect sys clock interrupt and auxiliary clock interrupt */

    (void)intConnect (INUM_TO_IVEC (SYS_TIMER_INT_VEC), sysClkInt, 0);

#ifdef INCLUDE_SERIAL
    /* connect serial interrupt */
    sysSerialHwInit2();
#endif /* INCLUDE_SERIAL */

#if defined (INCLUDE_PCI)
#if defined (INCLUDE_DEC21X40END) || defined (INCLUDE_FEI82557END)

    /* map all appropriate Ethernet PCI device memory and I/O addresses */

    sysLanPciInit ();

#endif  /* INCLUDE_DEC21X40END/FEI82557END */
#if defined (INCLUDE_USB)
    /* Low level init for usb */

    sysUsbPciInit();

#endif
#endif  /* INCLUDE_PCI */

    initialised = TRUE;

    }
/*******************************************************************************
*
* sysClkInt - interrupt level processing for system clock
*
* This routine handles a system clock interrupt.  It acknowledges the
* interrupt and calls the routine installed by sysClkConnect().
*/

void sysClkInt (void)
    {
	UINT32 oier;  
    /* call system clock service routine */

    if (sysClkRoutine != NULL)
        (* sysClkRoutine) (sysClkArg);
        
    SNGS3C_REG_READ  (rINTPND, oier);                
    SNGS3C_REG_WRITE (rSRCPND, oier);
    SNGS3C_REG_WRITE (rINTPND, oier); 
	
	WatchDogReset();
    }
/*******************************************************************************
*
* usrClock - user-defined system clock interrupt routine
*
* This routine is called at interrupt level on each clock interrupt.
* It is installed by usrRoot() with a sysClkConnect() call.
* It calls all the other packages that need to know about clock ticks,
* including the kernel itself.
*
* If the application needs anything to happen at the system clock interrupt
* level, it can be added to this routine.
*
* RETURNS: N/A
*/

void usrClock ()

    {
    tickAnnounce ();	/* announce system tick to kernel */
    }

sysClkConnect函数完成时钟中断处理程序的注册,在sysClkConnect函数中调用sysHwInit2,在该函数中注册sysClkInt作为时钟中断响应函数,然后sysClkConnect将userClock作为二次函数调用注册到VxWorks内核中,sysClk函数进一步调用userClock函数,userClock函数在userConfig.c中定义,它直接调用tickAnnounce作为响应,tickAnnounce函数主要完成以下工作:

(1)对vxTick变量做加1运算

(2)对处于等待状态的任务进行检查,讲超时任务重新设置为ready状态,并转移到调度队列中

(3)遍历内核工作队列,对延迟的内核工作进行执行

(4)进程调度

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值