📄 os_cpu_c.c
字号:
/*
*********************************************************************************************************
* 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"
#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_CRITICAL\n");
#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: SetThreadAffinityMask\n");
#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.
;*********************************************************************************************************
*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -