os_cpu_c.c
上传用户:tkwrx3909
上传日期:2015-10-06
资源大小:3310k
文件大小:28k
- /*
- *********************************************************************************************************
- * uC/OS-II
- * The Real-Time Kernel
- *
- * Win32 Specific code
- *
- * This is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- *
- * File : OS_CPU_C.C
- * By : Vladimir Antonenko
- *********************************************************************************************************
- */
- #define OS_CPU_GLOBALS
- #include "includes.h"
- #include "os_trace.h"
- #include <windows.h>
- #include <mmsystem.h>
- #if 0
- #define USE_CRITICAL_SECTION /* use Win32 critical sections */
- #endif
- #define ALLOW_CS_RECURSION /* allow recursion of critical sections */
- #define SET_AFFINITY_MASK /* must be used for miltiprocessor systems */
- #define OS_CPU_TRACE /* allow print trace messages */
- #define WIN_MM_TICK /* Enabling WIN_MM_TICK will cause the uC/OS-II port to use the high resolution Multimedia */
- /* timer instead of Sleep. The higher resolution timer has a resolution of 1 ms, which */
- /* results in a much more "real-time" feel - jdf */
- #define WIN_MM_MIN_RES (1) /* Minimum timer resolution */
- /*
- *********************************************************************************************************
- * Prototypes
- *********************************************************************************************************
- */
- DWORD WINAPI OSCtxSwW32( LPVOID lpParameter );
- DWORD WINAPI OSTickW32 ( LPVOID lpParameter );
- DWORD WINAPI OSTaskW32 ( LPVOID lpParameter );
- /*
- *********************************************************************************************************
- * Globals
- *********************************************************************************************************
- */
- INT32U OSTerminateTickW32 = 0;
- INT32U OSTerminateCtxSwW32 = 0;
- INT32U OSTerminateTickCtrlW32 = 0;
- HANDLE OSTick32Handle;
- HANDLE OSCtxSwW32Event;
- HANDLE OSCtxSwW32Handle;
- #ifdef WIN_MM_TICK
- HANDLE OSTickEventHandle;
- DWORD OSTickTimer;
- TIMECAPS OSTimeCap;
- #endif
- CRITICAL_SECTION OSCriticalSection;
- HANDLE OSSemaphore;
- OS_EMU_STK *SS_SP;
- #ifdef ALLOW_CS_RECURSION
- DWORD ThreadID = 0;
- int Recursion = 0;
- #endif
- /*
- *********************************************************************************************************
- * OS INITIALIZATION HOOK
- * (BEGINNING)
- *
- * Description: This function is called by OSInit() at the beginning of OSInit().
- *
- * Arguments : none
- *
- * Note(s) : 1) Interrupts should be disabled during this call.
- *********************************************************************************************************
- */
- void OSInitHookBegin(void)
- {
- #ifdef USE_CRITICAL_SECTION
- InitializeCriticalSection(&OSCriticalSection);
- #else
- OSSemaphore = CreateSemaphore( NULL, 1, 1, NULL );
- #endif
- }
- /*
- *********************************************************************************************************
- * OS INITIALIZATION HOOK
- * (END)
- *
- * Description: This function is called by OSInit() at the end of OSInit().
- *
- * Arguments : none
- *
- * Note(s) : 1) Interrupts should be disabled during this call.
- *********************************************************************************************************
- */
- void OSInitHookEnd(void) {}
- /*
- *********************************************************************************************************
- * OS_INIT_CRITICAL()
- * Initialize code necessary for WIN32 implementation
- * of ENTER and EXIT CRITICAL routines.
- *********************************************************************************************************
- */
- void OS_INIT_CRITICAL()
- {
- #ifdef USE_CRITICAL_SECTION
- InitializeCriticalSection(&OSCriticalSection);
- #endif
- }
- /*
- *********************************************************************************************************
- * OS_ENTER_CRITICAL()
- * Defines the beginning of a critical section of code.
- *********************************************************************************************************
- */
- void OS_ENTER_CRITICAL()
- {
- #ifdef USE_CRITICAL_SECTION
- EnterCriticalSection(&OSCriticalSection);
- #else
- #ifdef ALLOW_CS_RECURSION
- if( WaitForSingleObject( OSSemaphore, 0 ) == WAIT_TIMEOUT )
- {
- if( GetCurrentThreadId() != ThreadID )
- WaitForSingleObject( OSSemaphore, INFINITE );
- }
- ThreadID = GetCurrentThreadId();
- ++Recursion;
- #else
- WaitForSingleObject( OSSemaphore, INFINITE );
- #endif
- #endif
- }
- /*
- *********************************************************************************************************
- * OS_EXIT_CRITICAL()
- * Defines the end of a critical section of code.
- *********************************************************************************************************
- */
- void OS_EXIT_CRITICAL()
- {
- #ifdef USE_CRITICAL_SECTION
- LeaveCriticalSection(&OSCriticalSection);
- #else
- #ifdef ALLOW_CS_RECURSION
- if( Recursion > 0 ) {
- if(--Recursion == 0 ) {
- ThreadID = 0;
- ReleaseSemaphore( OSSemaphore, 1, NULL );
- }
- }
- else {
- #ifdef OS_CPU_TRACE
- OS_Printf("Error: OS_EXIT_CRITICALn");
- #endif
- }
- #else
- ReleaseSemaphore( OSSemaphore, 1, NULL );
- #endif
- #endif
- }
- /*
- *********************************************************************************************************
- * INITIALIZE A TASK'S STACK
- *
- * Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the
- * stack frame of the task being created. This function is highly processor specific.
- *
- * Arguments : task is a pointer to the task code
- *
- * pdata is a pointer to a user supplied data area that will be passed to the task
- * when the task first executes.
- *
- * ptos is a pointer to the top of stack. It is assumed that 'ptos' points to
- * a 'free' entry on the task stack. If OS_STK_GROWTH is set to 1 then
- * 'ptos' will contain the HIGHEST valid address of the stack. Similarly, if
- * OS_STK_GROWTH is set to 0, the 'ptos' will contains the LOWEST valid address
- * of the stack.
- *
- * opt specifies options that can be used to alter the behavior of OSTaskStkInit().
- * (see uCOS_II.H for OS_TASK_OPT_???).
- *
- * Returns : Always returns the location of the new top-of-stack' once the processor registers have
- * been placed on the stack in the proper order.
- *
- * Note(s) : Interrupts are enabled when your task starts executing. You can change this by setting the
- * PSW to 0x0002 instead. In this case, interrupts would be disabled upon task startup. The
- * application code would be responsible for enabling interrupts at the beginning of the task
- * code. You will need to modify OSTaskIdle() and OSTaskStat() so that they enable
- * interrupts. Failure to do this will make your system crash!
- *********************************************************************************************************
- */
- OS_STK *OSTaskStkInit (void (*task)(void *pd), void *pdata, OS_STK *ptos, INT16U opt)
- {
- OS_EMU_STK *stk;
- stk = (OS_EMU_STK *)((char*)ptos-sizeof(OS_EMU_STK)); /* Load stack pointer */
- stk->pData = pdata;
- stk->Opt = opt;
- stk->Task = task;
- stk->Handle = NULL;
- stk->Id = 0;
- stk->Exit = 0;
- return ((void *)stk);
- }
- /*$PAGE*/
- #if OS_CPU_HOOKS_EN
- /*
- *********************************************************************************************************
- * TASK CREATION HOOK
- *
- * Description: This function is called when a task is created.
- *
- * Arguments : ptcb is a pointer to the task control block of the task being created.
- *
- * Note(s) : 1) Interrupts are disabled during this call.
- *********************************************************************************************************
- */
- void OSTCBInitHook(OS_TCB *ptcb)
- {
- OS_EMU_STK *stack;
-
- stack = (OS_EMU_STK*) ptcb->OSTCBStkPtr;
- stack->Handle = CreateThread( NULL, 0, OSTaskW32, ptcb, CREATE_SUSPENDED, &stack->Id );
-
- #ifdef SET_AFFINITY_MASK
- if( SetThreadAffinityMask( stack->Handle, 1 ) == 0 )
- {
- #ifdef OS_CPU_TRACE
- OS_Printf("Error: SetThreadAffinityMaskn");
- #endif
- }
- #endif
- }
- void OSTaskCreateHook (OS_TCB *ptcb)
- {
- }
- /*
- *********************************************************************************************************
- * TASK DELETION HOOK
- *
- * Description: This function is called when a task is deleted.
- *
- * Arguments : ptcb is a pointer to the task control block of the task being deleted.
- *
- * Note(s) : 1) Interrupts are disabled during this call.
- *********************************************************************************************************
- */
- void OSTaskDelHook (OS_TCB *ptcb)
- {
- OS_EMU_STK *stack;
-
- stack = (OS_EMU_STK*) ptcb->OSTCBStkPtr;
- if(!(stack->Exit))
- {
- SuspendThread(stack->Handle);
- CloseHandle(stack->Handle);
- }
- }
- /*
- *********************************************************************************************************
- * TASK SWITCH HOOK
- *
- * Description: This function is called when a task switch is performed. This allows you to perform other
- * operations during a context switch.
- *
- * Arguments : none
- *
- * Note(s) : 1) Interrupts are disabled during this call.
- * 2) It is assumed that the global pointer 'OSTCBHighRdy' points to the TCB of the task that
- * will be 'switched in' (i.e. the highest priority task) and, 'OSTCBCur' points to the
- * task being switched out (i.e. the preempted task).
- *********************************************************************************************************
- */
- void OSTaskSwHook (void)
- {
- }
- /*
- *********************************************************************************************************
- * STATISTIC TASK HOOK
- *
- * Description: This function is called every second by uC/OS-II's statistics task. This allows your
- * application to add functionality to the statistics task.
- *
- * Arguments : none
- *********************************************************************************************************
- */
- void OSTaskStatHook (void)
- {
- }
- /*
- *********************************************************************************************************
- * TICK HOOK
- *
- * Description: This function is called every tick.
- *
- * Arguments : none
- *
- * Note(s) : 1) Interrupts may or may not be ENABLED during this call.
- *********************************************************************************************************
- */
- void OSTimeTickHook (void)
- {
- }
- /*
- *********************************************************************************************************
- * TASK IDLE HOOK
- *
- * Description: This function is called by the idle task.
- *
- * Arguments : none
- *
- * Note(s) : 1) Interrupts may or may not be ENABLED during this call.
- *********************************************************************************************************
- */
- void OSTaskIdleHook (void)
- {
- }
- #endif
- /*
- ;*********************************************************************************************************
- ; START MULTITASKING
- ; void OSStartHighRdy(void)
- ;
- ; The stack frame is assumed to look as follows:
- ;
- ; OSTCBHighRdy->OSTCBStkPtr --> DS (Low memory)
- ; ES
- ; DI
- ; SI
- ; BP
- ; SP
- ; BX
- ; DX
- ; CX
- ; AX
- ; OFFSET of task code address
- ; SEGMENT of task code address
- ; Flags to load in PSW
- ; OFFSET of task code address
- ; SEGMENT of task code address
- ; OFFSET of 'pdata'
- ; SEGMENT of 'pdata' (High memory)
- ;
- ; Note : OSStartHighRdy() MUST:
- ; a) Call OSTaskSwHook() then,
- ; b) Set OSRunning to TRUE,
- ; c) Switch to the highest priority task.
- ;*********************************************************************************************************
- */
- void OSStartHighRdy()
- {
- DWORD dwID;
- OSInitTrace(100000);
- OS_ENTER_CRITICAL();
- OSTaskSwHook();
- ++OSRunning;
- OSCtxSwW32Event = CreateEvent(NULL,FALSE,FALSE,NULL);
- OSCtxSwW32Handle = CreateThread( NULL, 0, OSCtxSwW32, 0, 0, &dwID );
- SetPriorityClass(OSCtxSwW32Handle,THREAD_PRIORITY_HIGHEST);
- #ifdef SET_AFFINITY_MASK
- if( SetThreadAffinityMask( OSCtxSwW32Handle, 1 ) == 0 ) {
- #ifdef OS_CPU_TRACE
- OS_Printf("Error: SetThreadAffinityMaskn");
- #endif
- }
- #endif
-
- SetThreadPriority(OSCtxSwW32Handle,THREAD_PRIORITY_TIME_CRITICAL);
- OSTick32Handle = CreateThread( NULL, 0, OSTickW32, 0, 0, &dwID );
- SetPriorityClass(OSTick32Handle,THREAD_PRIORITY_HIGHEST);
- #ifdef SET_AFFINITY_MASK
- if( SetThreadAffinityMask( OSTick32Handle, 1 ) == 0 )
- {
- #ifdef OS_CPU_TRACE
- OS_Printf("Error: SetThreadAffinityMaskn");
- #endif
- }
- #endif
- SetThreadPriority(OSTick32Handle,THREAD_PRIORITY_HIGHEST);
- #ifdef WIN_MM_TICK
- timeGetDevCaps(&OSTimeCap, sizeof(OSTimeCap));
- if( OSTimeCap.wPeriodMin < WIN_MM_MIN_RES )
- OSTimeCap.wPeriodMin = WIN_MM_MIN_RES;
- timeBeginPeriod(OSTimeCap.wPeriodMin);
- OSTickEventHandle = CreateEvent(NULL, FALSE, FALSE, NULL);
- OSTickTimer = timeSetEvent((1000/OS_TICKS_PER_SEC),OSTimeCap.wPeriodMin,(LPTIMECALLBACK)OSTickEventHandle, dwID,TIME_PERIODIC|TIME_CALLBACK_EVENT_SET);
- #endif
-
-
- SS_SP = (OS_EMU_STK*) OSTCBHighRdy->OSTCBStkPtr; /* OSTCBCur = OSTCBHighRdy; */
- /* OSPrioCur = OSPrioHighRdy; */
- ResumeThread(SS_SP->Handle);
- OS_EXIT_CRITICAL();
-
- WaitForSingleObject(OSCtxSwW32Handle,INFINITE);
- #ifdef WIN_MM_TICK
- timeKillEvent(OSTickTimer);
- timeEndPeriod(OSTimeCap.wPeriodMin);
- CloseHandle(OSTickEventHandle);
- #endif
- CloseHandle(OSTick32Handle);
- CloseHandle(OSCtxSwW32Event);
- }
- /*
- ;*********************************************************************************************************
- ; PERFORM A CONTEXT SWITCH (From task level)
- ; void OSCtxSw(void)
- ;
- ; Note(s): 1) Upon entry,
- ; OSTCBCur points to the OS_TCB of the task to suspend
- ; OSTCBHighRdy points to the OS_TCB of the task to resume
- ;
- ; 2) The stack frame of the task to suspend looks as follows:
- ;
- ; SP -> OFFSET of task to suspend (Low memory)
- ; SEGMENT of task to suspend
- ; PSW of task to suspend (High memory)
- ;
- ; 3) The stack frame of the task to resume looks as follows:
- ;
- ; OSTCBHighRdy->OSTCBStkPtr --> DS (Low memory)
- ; ES
- ; DI
- ; SI
- ; BP
- ; SP
- ; BX
- ; DX
- ; CX
- ; AX
- ; OFFSET of task code address
- ; SEGMENT of task code address
- ; Flags to load in PSW (High memory)
- ;*********************************************************************************************************
- */
- void OSCtxSw()
- {
- DWORD n = 0;
- if(!(SS_SP->Exit)) {
- n = SuspendThread(SS_SP->Handle);
- }
- OSTaskSwHook();
- OSTrace( OBJ_SW, PT_SW_CTX, OSTCBHighRdy, 0, OSPrioCur, OSPrioHighRdy,0 );
- OSTCBCur = OSTCBHighRdy;
- OSPrioCur = OSPrioHighRdy;
- SS_SP = (OS_EMU_STK*) OSTCBHighRdy->OSTCBStkPtr;
- ResumeThread(SS_SP->Handle);
- }
- /*
- ;*********************************************************************************************************
- ; PERFORM A CONTEXT SWITCH (From an ISR)
- ; void OSIntCtxSw(void)
- ;
- ; Note(s): 1) Upon entry,
- ; OSTCBCur points to the OS_TCB of the task to suspend
- ; OSTCBHighRdy points to the OS_TCB of the task to resume
- ;
- ; 2) The stack frame of the task to suspend looks as follows:
- ;
- ; SP+0 --> OFFSET of return address of OSIntCtxSw() (Low memory)
- ; +2 SEGMENT of return address of OSIntCtxSw()
- ; +4 PSW saved by OS_ENTER_CRITICAL() in OSIntExit()
- ; +6 OFFSET of return address of OSIntExit()
- ; +8 SEGMENT of return address of OSIntExit()
- ; +10 DS
- ; ES
- ; DI
- ; SI
- ; BP
- ; SP
- ; BX
- ; DX
- ; CX
- ; AX
- ; OFFSET of task code address
- ; SEGMENT of task code address
- ; Flags to load in PSW (High memory)
- ;
- ; 3) The stack frame of the task to resume looks as follows:
- ;
- ; OSTCBHighRdy->OSTCBStkPtr --> DS (Low memory)
- ; ES
- ; DI
- ; SI
- ; BP
- ; SP
- ; BX
- ; DX
- ; CX
- ; AX
- ; OFFSET of task code address
- ; SEGMENT of task code address
- ; Flags to load in PSW (High memory)
- ;*********************************************************************************************************
- */
- void OSIntCtxSw()
- {
- DWORD n = 0;
- if(!(SS_SP->Exit)) {
- n = SuspendThread(SS_SP->Handle);
- }
- OSTaskSwHook();
- OSTrace( OBJ_SW, PT_SW_INT, OSTCBHighRdy, 0, OSPrioCur,OSPrioHighRdy,0 );
- OSTCBCur = OSTCBHighRdy;
- OSPrioCur = OSPrioHighRdy;
- SS_SP = (OS_EMU_STK*) OSTCBHighRdy->OSTCBStkPtr;
- ResumeThread(SS_SP->Handle);
- }
- /*
- ;*********************************************************************************************************
- ; HANDLE TICK ISR
- ;
- ; Description: This function is called 199.99 times per second or, 11 times faster than the normal DOS
- ; tick rate of 18.20648 Hz. Thus every 11th time, the normal DOS tick handler is called.
- ; This is called chaining. 10 times out of 11, however, the interrupt controller on the PC
- ; must be cleared to allow for the next interrupt.
- ;
- ; Arguments : none
- ;
- ; Returns : none
- ;
- ; Note(s) : The following C-like pseudo-code describe the operation being performed in the code below.
- ;
- ; Save all registers on the current task's stack;
- ; OSIntNesting++;
- ; OSTickDOSCtr--;
- ; if (OSTickDOSCtr == 0) {
- ; INT 81H; Chain into DOS every 54.925 mS
- ; (Interrupt will be cleared by DOS)
- ; } else {
- ; Send EOI to PIC; Clear tick interrupt by sending an End-Of-Interrupt to the 8259
- ; PIC (Priority Interrupt Controller)
- ; }
- ; OSTimeTick(); Notify uC/OS-II that a tick has occured
- ; OSIntExit(); Notify uC/OS-II about end of ISR
- ; Restore all registers that were save on the current task's stack;
- ; Return from Interrupt;
- ;*********************************************************************************************************
- */
- void OSTickISR()
- {
- OSIntEnter();
- OSTimeTick();
- OSIntExit();
- }
- /*
- *********************************************************************************************************
- * WIN32 TASK - OSCtxSwW32()
- *
- * Description: These functions are body of OS multitasking in WIN32.
- *
- * Arguments : lpParameter is a pointer to special paraleter of the task.
- *
- * Note(s) : 1) Priorities of these tasks are very important.
- *********************************************************************************************************
- */
- DWORD WINAPI OSCtxSwW32( LPVOID lpParameter )
- {
- OS_INIT_CRITICAL();
- while(!OSTerminateCtxSwW32)
- {
- if( WAIT_OBJECT_0 == WaitForSingleObject(OSCtxSwW32Event,INFINITE) )
- {
- OS_ENTER_CRITICAL();
- OSCtxSw();
- OS_EXIT_CRITICAL();
- }
- }
- return 0;
- }
- /*
- *********************************************************************************************************
- * WIN32 TASK - OSTickW32()
- *
- * Description: These functions are body of OS multitasking in WIN32.
- *
- * Arguments : lpParameter is a pointer to special paraleter of the task.
- *
- * Note(s) : 1) Priorities of these tasks are very important.
- *********************************************************************************************************
- */
- DWORD WINAPI OSTickW32( LPVOID lpParameter )
- {
- OS_INIT_CRITICAL();
- while(!OSTerminateTickW32)
- {
- OSTickISR();
- #ifdef WIN_MM_TICK
- if( WaitForSingleObject(OSTickEventHandle, 5000) == WAIT_TIMEOUT)
- {
- #ifdef OS_CPU_TRACE
- OS_Printf("Error: MM OSTick Timeout!n");
- #endif
- }
- ResetEvent(OSTickEventHandle);
- #else
- Sleep(1000/OS_TICKS_PER_SEC);
- #endif
- }
- return 0;
- }
- /*
- *********************************************************************************************************
- * WIN32 TASK - OSTaskW32()
- *
- * Description: These functions are body of OS multitasking in WIN32.
- *
- * Arguments : lpParameter is a pointer to special paraleter of the task.
- *
- * Note(s) : 1) Priorities of these tasks are very important.
- *********************************************************************************************************
- */
- DWORD WINAPI OSTaskW32( LPVOID lpParameter )
- {
- OS_TCB *ptcb;
- OS_EMU_STK *stack;
- ptcb = (OS_TCB*) lpParameter;
- stack = (OS_EMU_STK*) ptcb->OSTCBStkPtr;
-
- #ifdef DISABLE_PRIORITY_BOOST
- if( SetThreadPriorityBoost( stack->Handle, TRUE ) == 0 ) {
- #ifdef OS_CPU_TRACE
- OS_Printf("Error: SetThreadPriorityBoostn");
- #endif
- }
- #endif
- OS_INIT_CRITICAL();
- stack->Task(stack->pData);
- stack->Exit = 1;
- OSTaskDel(ptcb->OSTCBPrio);
- return 0;
- }
- /*
- *********************************************************************************************************
- * WIN32 TASK - OS_SLEEP()
- *
- * Description: These functions are body of OS multitasking in WIN32.
- *
- * Arguments : lpParameter is a pointer to special paraleter of the task.
- *
- * Note(s) : 1) Priorities of these tasks are very important.
- *********************************************************************************************************
- */
- void OS_SLEEP()
- {
- Sleep(1);
- }
- /*
- *********************************************************************************************************
- * WIN32 TASK - OS_STOP()
- *
- * Description: These functions are body of OS multitasking in WIN32.
- *
- * Arguments : lpParameter is a pointer to special paraleter of the task.
- *
- * Note(s) : 1) Priorities of these tasks are very important.
- *********************************************************************************************************
- */
- void OS_STOP()
- {
- OS_ENTER_CRITICAL();
- ++OSTerminateTickW32;
- ++OSTerminateCtxSwW32;
- OS_TASK_SW();
- OS_EXIT_CRITICAL();
- Sleep(1000/OS_TICKS_PER_SEC);
- }
- /*
- *********************************************************************************************************
- * OS_Printf()
- *
- * Description: These functions help make application more reliable.
- *
- * OS_Printf - analog of printf, but use critical sections
- *********************************************************************************************************
- */
- int OS_Printf(char *str, ...)
- {
- int ret;
- va_list marker;
- va_start( marker, str );
- OS_ENTER_CRITICAL();
- ret = vprintf( str, marker );
- OS_EXIT_CRITICAL();
- va_end( marker );
- return ret;
- }