⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 os_cpu_c.c

📁 网络上唯一的ucos 2.52 visual 2008 编译版
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
*********************************************************************************************************
*                                                uC/OS-II
*                                The Real-Time Kernel (by Jean J. Labrosse)
*
*                                             WIN32 PORT
*
*                          (c) Copyright 2004-... Werner.Zimmermann@hs-esslingen.de
*                                           All Rights Reserved
*
* File : OS_CPU_C.C
* By   : Werner Zimmermann
*
* Changes:  1.40 Fixed a bug in OS_log(), thanks to Hu JW. 13 Jul 2004
*	    1.50 Substituted DWORD by INT32U, BOOL by BOOLEAN
*	    1.60 Changes in the PC_Elapsed... functions in the Cygwin and Linux port. Use direct reads
*		 for the Pentium time stamp counter. No change in the Visual C++ port.
*           1.70 Changes to OSScheduleThread for detecting tasks deleted by OSTaskDel in the WIN32 port.
*                Suggested by Hu JW.
*	    2.00 Modifications in the Linux port, no changes in the WIN32 ports, 18 Mar 2005
*	    2.10 Include paths modified to work with uCOS-II 2.70
*           3.00 Modifications to work with uCOS-II 2.80, 30 May 2006, OSTimeTickCallback removed,
*		 made OSTaskIdleHook() and OSTaskCreateHook() instead of OSTCBInitHook() user callable.
*           3.10 Modification in os_cfg.h to ensure compatibility wiht uCOS-II 2.84, 06 April 2007
*		 Major changes in OSScheduleThread() and OSTcbInitHook() to make the code compatible
*		 with Validated Software's verification suite for uCOS-II (www.validatedsoftware.com
*	    3.20 Updated mail address and copyright messages, 03 March 2008
*           3.30 Modified OSTaskDelHook() to avoid memory leakage when deleting tasks. 26 March 2008
	    3.40 Make sources compatible with Visual Studio .NET 2003 and 2005
*
*********************************************************************************************************
*/
#define OS_PORT_VERSION 340					//Version number of the uCOS-II WIN32 port

/*
*********************************************************************************************************
   Includes
*********************************************************************************************************
*/
#define _CRT_SECURE_NO_WARNINGS

#define _WIN32_WINNT  0x0400
#include    <windows.h>
#include    <winbase.h>
#include    <mmsystem.h>

#include    <stdio.h>
#include    <stdlib.h>
#include    <assert.h>

#if (OS_VERSION <= 270)
#include    "os_cpu.h"
#include    "os_cfg.h"
#include    "ucos_ii.h"
#else
#include    "ucos_ii.h"
#endif
/*
*********************************************************************************************************
   Global variables
*********************************************************************************************************
*/
HANDLE  hScheduleEvent, hScheduleThread;			//Scheduler thread variables
volatile HANDLE  hTaskThread[OS_LOWEST_PRIO + 2];		//Map uCOS tasks to WIN32 threads
volatile INT8S   taskSuspended[OS_LOWEST_PRIO + 2];		//Suspend status of mapped tasks/threads
volatile OS_TCB  *pTaskTcb[OS_LOWEST_PRIO + 2];			//Pointer to task TCBs

#define NINTERRUPTS 8						//Number of interrupt events (DO NOT CHANGE)
HANDLE  hInterruptEvent[NINTERRUPTS], hInterruptThread;		//Interrupt handling thread variables
void (*interruptTable[NINTERRUPTS])();
BOOLEAN virtualInterruptFlag=TRUE;
INT32U   interruptThreadId = 0;

CRITICAL_SECTION criticalSection;				//Used to protect critical sections

BOOLEAN idleTrigger = TRUE;					//Trigger a message, when the idle task is
								//invoked (used for debugging purposes)

#define NLOG	16						//Log last scheduled tasks (used for
INT16U taskLog[NLOG];						//... debugging purposes)

int GetThreadIndexForTask(OS_TCB *pTcb);			//Get index of thread in hTaskThread
void ExecuteDeleteTask(int i);

/*
*********************************************************************************************************
   Port-specific functions
*********************************************************************************************************
*/

// DBGPRINT ******************************************************************
// Debug output
void DBGPRINT(INT32U debugLevel, const char *fmt,...)
{   va_list argptr;
    FILE *fd;

    if ((debugLevel & DEBUGLEVEL) == 0)				//Debug output selection
        return;
    if (DEBUGLEVEL < 0x10000000UL)                              //Screen output (does influence real-time performance!)
    {   va_start(argptr, fmt);
        vprintf(fmt, argptr);
        va_end(argptr);
    } else                                                      //File output (does influence real-time performance!)
    {   va_start(argptr, fmt);
        if ((fd = fopen("ucos.log","a+"))!=NULL)
        {   vfprintf(fd, fmt, argptr);
            fclose(fd);
        }
        va_end(argptr);
    }
}

// DumpTaskList ****************************************************************
// Dump a list of all OS tasks by parsing the TCB list
void DumpTaskList(void)
{   int i;
    OS_TCB *pTcb = OSTCBList;

    if (OSTCBCur)
	printf("Cur  pTcb=%X  Prio=%d  Stat=%d\n", OSTCBCur, OSTCBCur->OSTCBPrio, OSTCBCur->OSTCBStat);

    while (pTcb)
    {	printf("Task pTcb=%X  Prio=%d  Stat=%d ", pTcb, pTcb->OSTCBPrio, pTcb->OSTCBStat);
	for (i=0; i <= OS_LOWEST_PRIO; i++) 			//Search for task in thread array
	{   if (pTcb == pTaskTcb[i])
	    {   break;
	    }
	}
	if (i > OS_LOWEST_PRIO)
	{   printf("Thread: not found\n");
	    Beep(400, 500);
	} else
	{   printf("Thread Index: %d  Suspend: %d\n", i, taskSuspended[i]);
	}
    	pTcb = pTcb->OSTCBNext;
    }
}

// OSLog *********************************************************************
// Log the last NLOG scheduled tasks in taskLog (with taskLog[0] = last task)
void OSLog(INT16U prio)
{   int i;

    for (i=NLOG-1; i > 0; i--)					//Shift the previous logged values by one
        taskLog[i]=taskLog[i-1];
    taskLog[0]=prio;						//Log the last one into taskLog[0]
}

// OSPortVersion *************************************************************
// Return the version number of the uCOS-II WIN32 port
INT16U OSPortVersion(void)
{    return OS_PORT_VERSION;
}

// Handle Control - Break and Control - C
BOOLEAN CtrlBreakHandler(INT32U ctrl)
{   if (ctrl==CTRL_C_EVENT)					//Handler if CTRL-C is pressed
    {	printf("---Exiting OSPrioCur=%u-------------\n", OSPrioCur);	//---Display current task priority
    } else if (ctrl==CTRL_BREAK_EVENT)				//Handler if CTRL-BREAK is pressed
    {	printf("---Exiting OSPrioCur=%u-------------\n", OSPrioCur);	//---Display current task priority and exit
 	exit(0);
    }
    return TRUE;
}

// OSEnableInterruptFlag ****************************************************
// Enable the interrupt flag
#if OS_CRITICAL_METHOD == 3
    void OSEnableInterruptFlag(OS_CPU_SR* pCpu_Sr)
#else
    void OSEnableInterruptFlag(void)
#endif
{
    if (virtualInterruptFlag==FALSE)				//If the timer interrupt previously was disabled,
    {
#if OS_CRITICAL_METHOD == 3
	virtualInterruptFlag=*pCpu_Sr;
#else
    	virtualInterruptFlag=TRUE;
#endif
        if ((virtualInterruptFlag==TRUE) && (GetCurrentThreadId()!=interruptThreadId))
            ResumeThread(hInterruptThread);			//... resume the interrupt thread
    }
    DBGPRINT(0x00000080, ">>> ODEnableInterruptFlag %2d\n", virtualInterruptFlag);
}

// OSDisableInterruptFlag ****************************************************
// Disable the Interrupt Flag
#if OS_CRITICAL_METHOD == 3
     void OSDisableInterruptFlag(OS_CPU_SR* pCpu_Sr)
#else
     void OSDisableInterruptFlag(void)
#endif
{
    if (virtualInterruptFlag==TRUE)				//If the timer interrupt previously was enabled,
    {   if (GetCurrentThreadId()!=interruptThreadId)		//... suspend the interrupt thread ...
            SuspendThread(hInterruptThread);
#if OS_CRITICAL_METHOD == 3
        *pCpu_Sr = (OS_CPU_SR) virtualInterruptFlag;
        virtualInterruptFlag=FALSE;
#else
	virtualInterruptFlag=FALSE;
#endif
    }
    DBGPRINT(0x00000080, ">>> OSDisableInterrupts   %2d\n", virtualInterruptFlag);
}

// OSDummyISR *****************************************************************
// Dummy interrupt service routine, if an interrupt is called for which an ISR has
// has not been installed
void OSDummyISR(void)
{   MessageBox(NULL, "Got unsupported interrupt", "uCOS-II WIN32", MB_OK | MB_SETFOREGROUND | MB_ICONERROR);
}

// GetThreadIndexForTask ******************************************************
// Search, if the specified Tcb is already known. If yes, return thread index,
// otherwise return -1
int GetThreadIndexForTask(OS_TCB *pTcb)
{   int i, j;
    for (i=0; i <= OS_LOWEST_PRIO+2; i++) 			//Search thread array for known priority
    {   if (pTcb == pTaskTcb[i])				//If found in thread array, ...
	{   for (j=0; j <= OS_LOWEST_PRIO+2; j++)		//... search in task array
	    {	if (pTcb == OSTCBPrioTbl[j])			//If found in task array, ...
		{   if (i==j)					//... check, if priorities are the same
			return j;
		    else
		    {	if (hTaskThread[j]!=NULL)
			{   printf("ERROR: Thread j=%d already exists\n", j);
			    exit(-1);
			}
			//printf("INFO: Changed task priority from %d to %d\n", i, j);
			//DumpTaskList();
			hTaskThread[j]	=hTaskThread[i];
			taskSuspended[j]=taskSuspended[i];
			pTaskTcb[j]	=pTaskTcb[i];
			hTaskThread[i]	=NULL;
			taskSuspended[i]=0;
			pTaskTcb[i]	=NULL;
			//DumpTaskList();
			return j;
		    }
		}
	    }
	}
    }
    return -1;
}

// OSScheduleThread ***********************************************************
// Start tasks, triggered by hScheduleEvent
void OSScheduleThread(INT32U param)
{   char temp[256];
    INT16S oldIndex, nextIndex;
#if OS_CRITICAL_METHOD == 3
    OS_CPU_SR cpu_sr = TRUE;
#endif
    DBGPRINT(0x00000001, "*** OSScheduleThread First Call\n");

    while (1)
    {   if (WaitForSingleObject(hScheduleEvent, OS_SCHEDULER_TIMEOUT) == WAIT_TIMEOUT)	//Wait for a scheduler event (with timeout)
        {   sprintf(temp, "ERROR: Scheduler timed out in OSScheduleThread  %u --> %u   IF=%u  <-%u<%u<%u<%u<%u<%u<%u<%u<-\n",
                                                OSPrioCur, OSPrioHighRdy, virtualInterruptFlag,
                                                taskLog[0], taskLog[1], taskLog[2], taskLog[3],
                                                taskLog[4], taskLog[5], taskLog[6], taskLog[7]
                                                );
            DBGPRINT(0x00000040, temp);
            MessageBox(NULL, temp, "UCOS-II WIN32", MB_OK | MB_SETFOREGROUND | MB_ICONERROR);	//In case of timeout, display an error message ...
            OSRunning=0;

            SetConsoleCtrlHandler((PHANDLER_ROUTINE) CtrlBreakHandler, FALSE);
            return;										//... and exit (will return to OSStartHighRdy())
        }
        OSTaskSwHook();									//Call the task switch hook function
        EnterCriticalSection(&criticalSection);

	if (taskSuspended[OSPrioCur]==-1)
	{   DBGPRINT(0x00000001, "Old Task %d marked for deletion - %X - %X\n", OSPrioCur, hTaskThread[OSPrioCur], OSTCBCur);
	    SuspendThread(hTaskThread[OSPrioCur]);
	    ExecuteDeleteTask(OSPrioCur);
	    oldIndex = OSPrioCur;
        } else
        {   oldIndex = GetThreadIndexForTask(OSTCBCur);
        }
	nextIndex= GetThreadIndexForTask(OSTCBHighRdy);
	if (oldIndex==-1 || nextIndex==-1)
	{   printf("ERROR: Internal scheduling error: oldIndex=%d - %d   nextIndex=%d - %d\n",oldIndex, OSTCBCur->OSTCBPrio, nextIndex, OSTCBHighRdy->OSTCBPrio);
	    exit(-1);
	}

	OSTCBCur  = OSTCBHighRdy;							//Now logically switch to the new task
        OSPrioCur = (INT8U) nextIndex;

        idleTrigger = TRUE;
        DBGPRINT(0x00000001, "*** OSScheduleThread from %2u to %2u\n", oldIndex, nextIndex);

        if (OSTCBPrioTbl[oldIndex] == NULL)						//If a task has been deleted
        {   if (hTaskThread[oldIndex])							//... remove it, normally this should never happen
            {   if (TerminateThread(hTaskThread[oldIndex], 0)==FALSE)
            	{   printf("ERROR: Terminate thread for task %d (in OSScheduleThread) WIN32 error code: %Xh\n", oldIndex, GetLastError());
        	}
		CloseHandle(hTaskThread[oldIndex]);
            }
            hTaskThread[oldIndex] = NULL;
            taskSuspended[oldIndex]=0;
	} else
	if (oldIndex != nextIndex && taskSuspended[oldIndex]==0)			//If switching context to a new task ...
        {   if (SuspendThread(hTaskThread[oldIndex])!=0)				//... suspend the thread associated with the current task
                printf("ERROR: SuspendThread() (in OSSCheduleThread) failed with error %Xh - task %d - %d\n", GetLastError(), oldIndex, taskSuspended[oldIndex]);
            taskSuspended[oldIndex]++;							//(update suspend counter to avoid multiple suspends of the same task)
        }

        if (taskSuspended[nextIndex]>0)
        {   taskSuspended[nextIndex]--;							//(updates suspend counter to avoid multiple resumes of the same task)
            if (taskSuspended[nextIndex] < 0)
                taskSuspended[nextIndex]=0;
            if (virtualInterruptFlag==FALSE)
#if OS_CRITICAL_METHOD == 3
                OSEnableInterruptFlag(&cpu_sr);
#else
                OSEnableInterruptFlag();
#endif
            OSLog(nextIndex);
            if (ResumeThread(hTaskThread[nextIndex])!=1)					//... and resume the thread associated with the new task
                printf("ERROR: ResumeThread() (in OSSCheduleThread) failed with error %Xh\n", GetLastError());
        } else
        {   if (virtualInterruptFlag==FALSE)
#if OS_CRITICAL_METHOD == 3
                OSEnableInterruptFlag(&cpu_sr);
#else
                OSEnableInterruptFlag();
#endif
        }
        LeaveCriticalSection(&criticalSection);
    }
}

// OSInterruptThread **********************************************************
// Time tick interrupt processing
void OSInterruptThread(INT32U param)
{   char temp[256];
    INT32U eventType;

    DBGPRINT(0x00000001, "*** OSInterruptThread First Call\n");

    while (1)
    {   //if (WaitForSingleObject(hInterruptEvent, OS_INTERRUPT_TIMEOUT) == WAIT_TIMEOUT)	//Wait for a timer interrupt event
    	eventType=WaitForMultipleObjects(NINTERRUPTS, hInterruptEvent, FALSE, OS_INTERRUPT_TIMEOUT);
    	if (eventType == WAIT_TIMEOUT)	//Wait for a timer interrupt event
        {   sprintf(temp, "ERROR: Interrupt timed out in OSInterruptThread   IF=%u\n", virtualInterruptFlag);
            DBGPRINT(0x00000040, temp);
            MessageBox(NULL, temp, "UCOS-II WIN32", MB_OK | MB_SETFOREGROUND | MB_ICONERROR);		//In case of timeout, display an error message ...
            OSRunning=0;
            SetConsoleCtrlHandler((PHANDLER_ROUTINE) CtrlBreakHandler, FALSE);
            exit(-1);									//... and exit
        }
        EnterCriticalSection(&criticalSection);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -