📄 os_core.c
字号:
/*********************************************************************************************************** uC/OS-II* The Real-Time Kernel* CORE FUNCTIONS** (c) Copyright 1992-2001, Jean J. Labrosse, Weston, FL* All Rights Reserved** File : OS_CORE.C* By : Jean J. Labrosse**********************************************************************************************************/#ifndef OS_MASTER_FILE#define OS_GLOBALS#include "includes.h"#endif/*********************************************************************************************************** MAPPING TABLE TO MAP BIT POSITION TO BIT MASK** Note: Index into table is desired bit position, 0..7* Indexed value corresponds to bit mask**********************************************************************************************************/INT8U const OSMapTbl[] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80};/*********************************************************************************************************** PRIORITY RESOLUTION TABLE** Note: Index into table is bit pattern to resolve highest priority* Indexed value corresponds to highest priority bit position (i.e. 0..7)**********************************************************************************************************/INT8U const OSUnMapTbl[] = { 0, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0};/*$PAGE*//*********************************************************************************************************** INITIALIZATION** Description: This function is used to initialize the internals of uC/OS-II and MUST be called prior to* creating any uC/OS-II object and, prior to calling OSStart().** Arguments : none** Returns : none**********************************************************************************************************/void OSInit (void){ INT16U i; INT8U *prdytbl; OS_TCB *ptcb1; OS_TCB *ptcb2;#if (OS_EVENT_EN > 0) && (OS_MAX_EVENTS > 1) OS_EVENT *pevent1; OS_EVENT *pevent2;#endif#if OS_VERSION >= 204 OSInitHookBegin(); /* Call port specific initialization code */#endif#if OS_TIME_GET_SET_EN > 0 OSTime = 0L; /* Clear the 32-bit system clock */#endif OSIntNesting = 0; /* Clear the interrupt nesting counter */ OSLockNesting = 0; /* Clear the scheduling lock counter */ OSTaskCtr = 0; /* Clear the number of tasks */ OSRunning = FALSE; /* Indicate that multitasking not started */ OSIdleCtr = 0L; /* Clear the 32-bit idle counter */#if (OS_TASK_STAT_EN > 0) && (OS_TASK_CREATE_EXT_EN > 0) OSIdleCtrRun = 0L; OSIdleCtrMax = 0L; OSStatRdy = FALSE; /* Statistic task is not ready */#endif OSCtxSwCtr = 0; /* Clear the context switch counter */ OSRdyGrp = 0x00; /* Clear the ready list */ prdytbl = &OSRdyTbl[0]; for (i = 0; i < OS_RDY_TBL_SIZE; i++) { *prdytbl++ = 0x00; } OSPrioCur = 0; OSPrioHighRdy = 0; OSTCBHighRdy = (OS_TCB *)0; /* TCB Initialization */ OSTCBCur = (OS_TCB *)0; OSTCBList = (OS_TCB *)0; for (i = 0; i < (OS_LOWEST_PRIO + 1); i++) { /* Clear the priority table */ OSTCBPrioTbl[i] = (OS_TCB *)0; } ptcb1 = &OSTCBTbl[0]; ptcb2 = &OSTCBTbl[1]; for (i = 0; i < (OS_MAX_TASKS + OS_N_SYS_TASKS - 1); i++) { /* Init. list of free TCBs */ ptcb1->OSTCBNext = ptcb2; ptcb1++; ptcb2++; } ptcb1->OSTCBNext = (OS_TCB *)0; /* Last OS_TCB */ OSTCBFreeList = &OSTCBTbl[0];#if (OS_EVENT_EN > 0) && (OS_MAX_EVENTS > 0) #if OS_MAX_EVENTS == 1 OSEventFreeList = &OSEventTbl[0]; /* Only have ONE event control block */ OSEventFreeList->OSEventType = OS_EVENT_TYPE_UNUSED; OSEventFreeList->OSEventPtr = (OS_EVENT *)0; #else pevent1 = &OSEventTbl[0]; pevent2 = &OSEventTbl[1]; for (i = 0; i < (OS_MAX_EVENTS - 1); i++) { /* Init. list of free EVENT control blocks */ pevent1->OSEventType = OS_EVENT_TYPE_UNUSED; pevent1->OSEventPtr = pevent2; pevent1++; pevent2++; } pevent1->OSEventType = OS_EVENT_TYPE_UNUSED; pevent1->OSEventPtr = (OS_EVENT *)0; OSEventFreeList = &OSEventTbl[0]; #endif#endif#if (OS_VERSION >= 251) && (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) OS_FlagInit(); /* Initialize the event flag structures */#endif#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) OS_QInit(); /* Initialize the message queue structures */#endif#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) OS_MemInit(); /* Initialize the memory manager */#endif /* ------------------------------------- CREATION OF 'IDLE' TASK --------------------------------------- */#if OS_TASK_CREATE_EXT_EN > 0 #if OS_STK_GROWTH == 1 (void)OSTaskCreateExt(OS_TaskIdle, (void *)0, /* No arguments passed to OS_TaskIdle() */ &OSTaskIdleStk[OS_TASK_IDLE_STK_SIZE - 1], /* Set Top-Of-Stack */ OS_IDLE_PRIO, /* Lowest priority level */ OS_TASK_IDLE_ID, &OSTaskIdleStk[0], /* Set Bottom-Of-Stack */ OS_TASK_IDLE_STK_SIZE, (void *)0, /* No TCB extension */ OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR);/* Enable stack checking + clear stack */ #else (void)OSTaskCreateExt(OS_TaskIdle, (void *)0, /* No arguments passed to OS_TaskIdle() */ &OSTaskIdleStk[0], /* Set Top-Of-Stack */ OS_IDLE_PRIO, /* Lowest priority level */ OS_TASK_IDLE_ID, &OSTaskIdleStk[OS_TASK_IDLE_STK_SIZE - 1], /* Set Bottom-Of-Stack */ OS_TASK_IDLE_STK_SIZE, (void *)0, /* No TCB extension */ OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR);/* Enable stack checking + clear stack */ #endif#else #if OS_STK_GROWTH == 1 (void)OSTaskCreate(OS_TaskIdle, (void *)0, &OSTaskIdleStk[OS_TASK_IDLE_STK_SIZE - 1], OS_IDLE_PRIO); #else (void)OSTaskCreate(OS_TaskIdle, (void *)0, &OSTaskIdleStk[0], OS_IDLE_PRIO); #endif#endif /* ------------------------------- CREATION OF 'STATISTIC' TASK ---------------------------------- */#if OS_TASK_STAT_EN > 0 #if OS_TASK_CREATE_EXT_EN > 0 #if OS_STK_GROWTH == 1 (void)OSTaskCreateExt(OS_TaskStat, (void *)0, /* No args passed to OS_TaskStat()*/ &OSTaskStatStk[OS_TASK_STAT_STK_SIZE - 1], /* Set Top-Of-Stack */ OS_STAT_PRIO, /* One higher than the idle task */ OS_TASK_STAT_ID, &OSTaskStatStk[0], /* Set Bottom-Of-Stack */ OS_TASK_STAT_STK_SIZE, (void *)0, /* No TCB extension */ OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR); /* Enable stack checking + clear */ #else (void)OSTaskCreateExt(OS_TaskStat, (void *)0, /* No args passed to OS_TaskStat()*/ &OSTaskStatStk[0], /* Set Top-Of-Stack */ OS_STAT_PRIO, /* One higher than the idle task */ OS_TASK_STAT_ID, &OSTaskStatStk[OS_TASK_STAT_STK_SIZE - 1], /* Set Bottom-Of-Stack */ OS_TASK_STAT_STK_SIZE, (void *)0, /* No TCB extension */ OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR); /* Enable stack checking + clear */ #endif #else #if OS_STK_GROWTH == 1 (void)OSTaskCreate(OS_TaskStat, (void *)0, /* No args passed to OS_TaskStat()*/ &OSTaskStatStk[OS_TASK_STAT_STK_SIZE - 1], /* Set Top-Of-Stack */ OS_STAT_PRIO); /* One higher than the idle task */ #else (void)OSTaskCreate(OS_TaskStat, (void *)0, /* No args passed to OS_TaskStat()*/ &OSTaskStatStk[0], /* Set Top-Of-Stack */ OS_STAT_PRIO); /* One higher than the idle task */ #endif #endif#endif#if OS_VERSION >= 204 OSInitHookEnd(); /* Call port specific init. code */#endif}/*$PAGE*//*********************************************************************************************************** ENTER ISR** Description: This function is used to notify uC/OS-II that you are about to service an interrupt* service routine (ISR). This allows uC/OS-II to keep track of interrupt nesting and thus* only perform rescheduling at the last nested ISR.** Arguments : none** Returns : none** Notes : 1) Your ISR can directly increment OSIntNesting without calling this function because* OSIntNesting has been declared 'global'. You MUST, however, be sure that the increment* is performed 'indivisibly' by your processor to ensure proper access to this critical* resource.* 2) You MUST still call OSIntExit() even though you increment OSIntNesting directly.* 3) You MUST invoke OSIntEnter() and OSIntExit() in pair. In other words, for every call* to OSIntEnter() at the beginning of the ISR you MUST have a call to OSIntExit() at the* end of the ISR.**********************************************************************************************************/void OSIntEnter (void){#if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */ OS_CPU_SR cpu_sr;#endif OS_ENTER_CRITICAL(); if (OSIntNesting < 255) { OSIntNesting++; /* Increment ISR nesting level */ } OS_EXIT_CRITICAL();}/*$PAGE*//*********************************************************************************************************** EXIT ISR** Description: This function is used to notify uC/OS-II that you have completed serviving an ISR. When* the last nested ISR has completed, uC/OS-II will call the scheduler to determine whether* a new, high-priority task, is ready to run.** Arguments : none** Returns : none** Notes : 1) You MUST invoke OSIntEnter() and OSIntExit() in pair. In other words, for every call* to OSIntEnter() at the beginning of the ISR you MUST have a call to OSIntExit() at the* end of the ISR.* 2) Rescheduling is prevented when the scheduler is locked (see OSSchedLock())**********************************************************************************************************/void OSIntExit (void){#if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */ OS_CPU_SR cpu_sr;#endif OS_ENTER_CRITICAL(); if (OSIntNesting > 0) { /* Prevent OSIntNesting from wrapping */ OSIntNesting--; } if ((OSIntNesting == 0) && (OSLockNesting == 0)) { /* Reschedule only if all ISRs complete ... */ OSIntExitY = OSUnMapTbl[OSRdyGrp]; /* ... and not locked. */ OSPrioHighRdy = (INT8U)((OSIntExitY << 3) + OSUnMapTbl[OSRdyTbl[OSIntExitY]]); if (OSPrioHighRdy != OSPrioCur) { /* No Ctx Sw if current task is highest rdy */ OSTCBHighRdy = OSTCBPrioTbl[OSPrioHighRdy]; OSCtxSwCtr++; /* Keep track of the number of context switches */ OSIntCtxSw(); /* Perform interrupt level context switch */ } } OS_EXIT_CRITICAL();}/*$PAGE*//*********************************************************************************************************** PREVENT SCHEDULING** Description: This function is used to prevent rescheduling to take place. This allows your application* to prevent context switches until you are ready to permit context switching.** Arguments : none
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -