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

📄 os_cpu_c.c

📁 ucos2.85在vs2005上模拟环境
💻 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
*
*********************************************************************************************************
*/
#define OS_PORT_VERSION 330					//Version number of the uCOS-II WIN32 port

/*
*********************************************************************************************************
   Includes
*********************************************************************************************************
*/
//#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

⌨️ 快捷键说明

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