做完项目报告,可以休息几天了,所以接着看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)进程调度
本文详细介绍了VxWorks内核初始化过程中的关键步骤,特别是usrRoot函数的作用及其内部如何进行系统初始化,包括内存池初始化、I/O系统初始化、驱动安装、网络初始化等。同时,阐述了时钟中断处理程序的注册和启用,通过sysClkConnect函数连接系统时钟中断,进而调用sysClkInt函数处理时钟中断,最后通过usrClock函数实现系统计时功能。
578

被折叠的 条评论
为什么被折叠?



