📄 os_cpu_c.c
字号:
/*
*********************************************************************************************************
* 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 + -