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

📄 os_cpu_c.c

📁 此源码为UCOS在WIN32环境下的移植版本
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
*********************************************************************************************************
*                                                uC/OS-II
*                                The Real-Time Kernel (by Jean J. Labrosse)
*
*                                             WIN32 PORT
*
*                          (c) Copyright 2004-... Werner.Zimmermann@fht-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.
*
*********************************************************************************************************
*/
#define OS_PORT_VERSION 300					//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>

#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
HANDLE  hTaskThread[OS_LOWEST_PRIO + 2];			//Map uCOS tasks to WIN32 threads
INT8S   taskSuspended[OS_LOWEST_PRIO + 2];			//Suspend status of mapped tasks/threads

#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)

/*
*********************************************************************************************************
   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);
    }
}


// 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;
}

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
void OSEnableInterruptFlag(void)
{
    if (virtualInterruptFlag==FALSE)				//If the timer interrupt previously was disabled,
    {   virtualInterruptFlag=TRUE;
        if (GetCurrentThreadId()!=interruptThreadId)
            ResumeThread(hInterruptThread);			//... resume the interrupt thread
    }
    DBGPRINT(0x00000080, ">>> ODEnableInterruptFlag %2d\n", virtualInterruptFlag);
}

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

void OSDummyISR(void)
{   MessageBox(NULL, "Got unsupported interrupt", "uCOS-II WIN32", MB_OK | MB_SETFOREGROUND | MB_ICONERROR);
}

// OSScheduleThread ***********************************************************
// Start tasks, triggered by hScheduleEvent
void OSScheduleThread(INT32U param)
{   char temp[256];
    INT16U oldPrio, nextPrio;

    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);
        oldPrio   = OSPrioCur;
        nextPrio  = OSPrioHighRdy;
        OSTCBCur  = OSTCBHighRdy;							//Now logically switch to the new task
        OSPrioCur = OSPrioHighRdy;

        idleTrigger = TRUE;
        DBGPRINT(0x00000001, "*** OSScheduleThread from %2u to %2u\n", oldPrio, nextPrio);
        
        if (OSTCBPrioTbl[oldPrio] == NULL)						//If a task has been deleted
        {   if (hTaskThread[oldPrio])							//... remove it
            {   TerminateThread(hTaskThread[oldPrio], 0);
            	CloseHandle(hTaskThread[oldPrio]);
            }
            hTaskThread[oldPrio] = NULL;
            taskSuspended[oldPrio]=0;
        } else if (oldPrio != nextPrio && taskSuspended[oldPrio]==0)			//If switching context to a new task ...
        {   SuspendThread(hTaskThread[oldPrio]);					//... suspend the thread associated with the current task
            taskSuspended[oldPrio]++;							//(update suspend counter to avoid multiple suspends of the same task)
        }

        if (taskSuspended[nextPrio])
        {   taskSuspended[nextPrio]--;							//(updates suspend counter to avoid multiple resumes of the same task)
            if (taskSuspended[nextPrio] < 0)
                taskSuspended[nextPrio]=0;
            if (virtualInterruptFlag==FALSE)
                OSEnableInterruptFlag();
            OSLog(nextPrio);
            ResumeThread(hTaskThread[nextPrio]);					//... and resume the thread associated with the new task
        } else
        {   if (virtualInterruptFlag==FALSE)
                OSEnableInterruptFlag();
        }
        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);
        DBGPRINT(0x00000001, "*** OSInterruptThread\n");
        if (virtualInterruptFlag==FALSE)
            DBGPRINT(0x00000001, "*** virtualInteruptFlag disabled when calling OSInterruptThread XXX %d\n", virtualInterruptFlag);
        DBGPRINT(0x00000001, "--- OSIntEnter\n");
        OSIntEnter();

⌨️ 快捷键说明

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