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

📄 os_cpu_c.c

📁 windows vc ucos
💻 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
*********************************************************************************************************
*/
#define OS_PORT_VERSION 130					//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    "os_cpu.h"
#include    "os_cfg.h"
#include    "ucos_ii.h"

/*
*********************************************************************************************************
   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;
DWORD   interruptThreadId = 0;

CRITICAL_SECTION criticalSection;

BOOLEAN idleTrigger = FALSE;					//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-2; 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;
}

BOOL CtrlBreakHandler(DWORD 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);
}

// OSTickTickCallback ********************************************************
// Callback function for time tick 'interrupt', acts as a relay to OSTickISR
void CALLBACK OSTimeTickCallback(DWORD hTimer, DWORD message, DWORD dwUser, DWORD lparam2, DWORD lparam3)
{   DBGPRINT(0x00000008, "*** OSTimeTickCallback\n");
    SetEvent(hInterruptEvent[0]);				//Trigger the interrupt thread
}

// OSScheduleThread ***********************************************************
// Start tasks, triggered by hScheduleEvent
void OSScheduleThread(DWORD 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);
            exit(-1);									//... and exit
        }
        EnterCriticalSection(&criticalSection);
        oldPrio =OSPrioCur;
        nextPrio=OSPrioHighRdy;
        OSTCBCur  = OSTCBHighRdy;
        OSPrioCur = OSPrioHighRdy;

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

        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]++;
        }

        if (taskSuspended[nextPrio])
        {   taskSuspended[nextPrio]--;
            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(DWORD param)
{   char temp[256];
    DWORD 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();

        DBGPRINT(0x00000001, "--- OSTimeTick\n");

        if (eventType==WAIT_OBJECT_0)							//Call uCOS' interrupt processing
        {   ResetEvent(hInterruptEvent[0]);
            interruptTable[0]();							//IRQ0 reserved vor time tick: OSTimeTick();
        } else if (eventType==WAIT_OBJECT_0+1)
        {   ResetEvent(hInterruptEvent[1]);
            interruptTable[1]();
        } else if (eventType==WAIT_OBJECT_0+2)
        {   ResetEvent(hInterruptEvent[2]);
            interruptTable[2]();
        } else if (eventType==WAIT_OBJECT_0+3)
        {   ResetEvent(hInterruptEvent[3]);
            interruptTable[3]();
        } else if (eventType==WAIT_OBJECT_0+4)
        {   ResetEvent(hInterruptEvent[4]);

⌨️ 快捷键说明

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