📄 kernellib.c
字号:
* | |* | ROOT STACK |* | |* ------------------------ <--- pRootStackBase;* | |* | WIND_TCB |* | |* ------------------------* | | We have to leave room for these block headers* | 1 FREE_BLOCK | so we can add the root task memory to the pool.* | 1 BLOCK_HDR |* | |* ------------------------ <--- pRootMemStart;* ------------------------* | |* ~ FREE MEMORY POOL ~ pool initialized in kernelRoot()* | |* ------------------------ <--- pMemPoolStart + intStackSize; vxIntStackEnd* | |* | INTERRUPT STACK |* | |* ------------------------ <--- pMemPoolStart; vxIntStackBase* - LOW MEMORY -* .CE** RETURNS: N/A** SEE ALSO: intLockLevelSet()*/void kernelInit ( FUNCPTR rootRtn, /* user start-up routine */ unsigned rootMemSize, /* memory for TCB and root stack */ char * pMemPoolStart, /* beginning of memory pool */ char * pMemPoolEnd, /* end of memory pool */ unsigned intStackSize, /* interrupt stack size */ int lockOutLevel /* interrupt lock-out level (1-7) */ ) { union { double align8; /* 8-byte alignment dummy */ WIND_TCB initTcb; /* context from which to activate root */ } tcbAligned; WIND_TCB * pTcb; /* pTcb for root task */ unsigned rootStackSize; /* actual stacksize of root task */ unsigned memPoolSize; /* initial size of mem pool */ char * pRootStackBase; /* base of root task's stack */ /* align input size and address parameters */ rootMemNBytes = STACK_ROUND_UP(rootMemSize); pMemPoolStart = (char *) STACK_ROUND_UP(pMemPoolStart); pMemPoolEnd = (char *) STACK_ROUND_DOWN(pMemPoolEnd); intStackSize = STACK_ROUND_UP(intStackSize); /* initialize VxWorks interrupt lock-out level */ intLockLevelSet (lockOutLevel); /* round-robin mode is disabled by default */ roundRobinOn = FALSE; /* initialize the time to zero */ vxTicks = 0; /* good morning */ /* If the architecture supports a separate interrupt stack, * carve the interrupt stack from the beginning of the memory pool * and fill it with 0xee for checkStack (). The MC680[016]0, I960, and * I80X86 not do support a separate interrupt stack. I80X86, however, * allocate the stack for checkStack () which is not used. */#if (_STACK_DIR == _STACK_GROWS_DOWN)#if (CPU != MC68000 && CPU != MC68010 && CPU != MC68060) vxIntStackBase = pMemPoolStart + intStackSize; vxIntStackEnd = pMemPoolStart; bfill (vxIntStackEnd, (int) intStackSize, 0xee); windIntStackSet (vxIntStackBase); pMemPoolStart = vxIntStackBase;#if (CPU_FAMILY == AM29XXX) /* * The Am29K family uses 3 interrupt stacks, one for the local registers * stack, one for the memory stack and another for the saved registers * set (ESF). The average register stack and memory stack usage for * C program gives a ratio of 1/3 between the register stack and the * memory stack (dixit AMD). But because routines used at interrupt * level are mostly simple routines with not a lot of local variables * we change the ratio between the two stacks to 1. * The dedicated memory pool is shared as follow: * * ------------------ vxIntStackBase * 1/3| Kernel | * |Interrupt Stack | * | | * | | * ------------------ vxRegIntStackBase * 1/3| Register | * |Interrupt Stack | * | | * | | * ------------------ vxMemIntStackBase * | | * | Memory | * 1/3|Interrupt Stack | * | | * | | * ------------------ */ { int am29kStacksSize; am29kStacksSize = MEM_ROUND_UP (intStackSize / 3); /* * The interrupt register stack must be aligned of 128 * 4 boundary * because of the stack cut-across mecanism (see intALib.s). */ vxRegIntStackBase = (char *) ROUND_DOWN ((int) vxIntStackBase - am29kStacksSize, 512); vxMemIntStackBase = vxRegIntStackBase - am29kStacksSize; }#endif /* (CPU_FAMILY == AM29XXX)*/#if (CPU_FAMILY == ARM) /* * The ARM family uses 3 interrupt stacks. The ratio of the sizes of * these stacks is dependent on the interrupt structure of the board * and so is handled in the BSP code. Note that FIQ is now external to * VxWorks. */ if (_func_armIntStackSplit != NULL) (_func_armIntStackSplit)(vxIntStackBase, intStackSize);#endif /* (CPU_FAMILY == ARM) */#endif /* (CPU != MC68000 && CPU != MC68010 && CPU != MC68060) */#else /* _STACK_DIR == _STACK_GROWS_UP */#if CPU_FAMILY != I960 vxIntStackBase = pMemPoolStart; vxIntStackEnd = pMemPoolStart + intStackSize; bfill (vxIntStackBase, intStackSize, 0xee); windIntStackSet (vxIntStackBase); pMemPoolStart = vxIntStackEnd;#endif /* CPU_FAMILY != I960 */#endif /* (_STACK_DIR == _STACK_GROWS_UP) */ /* Carve the root stack and tcb from the end of the memory pool. We have * to leave room at the very top and bottom of the root task memory for * the memory block headers that are put at the end and beginning of a * free memory block by memLib's memAddToPool() routine. The root stack * is added to the memory pool with memAddToPool as the root task's * dieing breath. */ rootStackSize = rootMemNBytes - WIND_TCB_SIZE - MEM_TOT_BLOCK_SIZE; pRootMemStart = pMemPoolEnd - rootMemNBytes;#if (_STACK_DIR == _STACK_GROWS_DOWN) pRootStackBase = pRootMemStart + rootStackSize + MEM_BASE_BLOCK_SIZE; pTcb = (WIND_TCB *) pRootStackBase;#else /* _STACK_GROWS_UP */ pTcb = (WIND_TCB *) (pRootMemStart + MEM_BASE_BLOCK_SIZE); pRootStackBase = pRootMemStart + WIND_TCB_SIZE + MEM_BASE_BLOCK_SIZE;#endif /* _STACK_GROWS_UP */ /* We initialize the root task with taskIdCurrent == 0. This only works * because when taskInit calls windExit (), the ready queue will be * empty and thus the comparison of taskIdCurrent to the head of the * ready queue will result in equivalence. In this case windExit () * just returns to the caller, without changing anybody's context. */ taskIdCurrent = (WIND_TCB *) NULL; /* initialize taskIdCurrent */ bfill ((char *) &tcbAligned.initTcb, sizeof (WIND_TCB), 0); memPoolSize = (unsigned) ((int) pRootMemStart - (int) pMemPoolStart); taskInit (pTcb, "tRootTask", 0, VX_UNBREAKABLE | VX_DEALLOC_STACK, pRootStackBase, (int) rootStackSize, (FUNCPTR) rootRtn, (int) pMemPoolStart, (int)memPoolSize, 0, 0, 0, 0, 0, 0, 0, 0); rootTaskId = (int) pTcb; /* fill in the root task ID */ /* Now taskIdCurrent needs to point at a context so when we switch into * the root task, we have some place for windExit () to store the old * context. We just use a local stack variable to save memory. */ taskIdCurrent = &tcbAligned.initTcb; /* update taskIdCurrent */ taskActivate ((int) pTcb); /* activate root task */ }/********************************************************************************* kernelVersion - return the kernel revision string** This routine returns a string which contains the current revision of the* kernel. The string is of the form "WIND version x.y", where "x"* corresponds to the kernel major revision, and "y" corresponds to the* kernel minor revision.** RETURNS: A pointer to a string of format "WIND version x.y".*/char *kernelVersion (void) { return ("WIND version 2.5"); }/********************************************************************************* kernelTimeSlice - enable round-robin selection** This routine enables round-robin selection among tasks of same priority* and sets the system time-slice to <ticks>. Round-robin scheduling is* disabled by default. A time-slice of zero ticks disables round-robin* scheduling.** For more information about round-robin scheduling, see the manual entry* for kernelLib.** RETURNS: OK, always.*/STATUS kernelTimeSlice ( int ticks /* time-slice in ticks or 0 to disable round-robin */ ) { if (ticks == 0) /* 0 means turn off round-robin mode */ roundRobinOn = FALSE; else { roundRobinSlice = ticks; /* set new time-slice */ roundRobinOn = TRUE; /* enable round-robin scheduling mode */ } return (OK); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -