//vs2008_ucos\uCOSII_port\os_cpu_c.c[part3] 移植ucosii在VS2008--part4
/***************************************************************************************************
* INTERRUPT LEVEL CONTEXT SWITCH
*
* Description: This function is called by OSIntExit() to perform a context switch from an ISR.
* Arguments : none
* Note(s) : 1) OSIntCtxSw() MUST:
* a) Call OSTaskSwHook() then,
* b) Set OSTCBCur = OSTCBHighRdy,
* c) Set OSPrioCur = OSPrioHighRdy,
* d) Switch to the highest priority task.
***************************************************************************************************/
void OSIntCtxSw (void)
{
OS_TCB *ptcb;
OS_TASK_STK *pstack;
OS_TASK_STK *pstack_new;
INT8U state_err;
OSTaskSwHook();
ptcb = OSTCBCur;
pstack = (OS_TASK_STK *)ptcb->OSTCBStkPtr;
switch (pstack->TaskState) {
case STATE_RUNNING:
SuspendThread(pstack->ThreadHandle);
SwitchToThread();
pstack->TaskState = STATE_INTERRUPTED;
state_err = 0;
break;
#if (OS_MSG_TRACE > 0)
case STATE_NONE:
OSPrintf("[OSIntCtxSw] Error: Invalid state STATE_NONE\nCur Task[%3.1d] '%s' Thread ID %5.0d\n",
(CPU_INT16S)ptcb->OSTCBId,
ptcb->OSTCBTaskName,
pstack->ThreadID);
state_err = 1;
break;
case STATE_CREATED:
OSPrintf("[OSIntCtxSw] Error: Invalid state STATE_CREATED\nCur Task[%3.1d] '%s' Thread ID %5.0d\n",
(CPU_INT16S)ptcb->OSTCBId,
ptcb->OSTCBTaskName,
pstack->ThreadID);
state_err = 1;
break;
case STATE_INTERRUPTED:
OSPrintf("[OSIntCtxSw] Error: Invalid state STATE_INTERRUPTED\nCur Task[%3.1d] '%s' Thread ID %5.0d\n",
(CPU_INT16S)ptcb->OSTCBId,
ptcb->OSTCBTaskName,
pstack->ThreadID);
state_err = 1;
break;
case STATE_SUSPENDED:
OSPrintf("[OSIntCtxSw] Error: Invalid state STATE_SUSPENDED\nCur Task[%3.1d] '%s' Thread ID %5.0d\n",
(CPU_INT16S)ptcb->OSTCBId,
ptcb->OSTCBTaskName,
pstack->ThreadID);
state_err = 1;
break;
case STATE_TERMINATING:
OSPrintf("[OSIntCtxSw] Error: Invalid state STATE_TERMINATING\nCur Task[%3.1d] '%s' Thread ID %5.0d\n",
(CPU_INT16S)ptcb->OSTCBId,
ptcb->OSTCBTaskName,
pstack->ThreadID);
state_err = 1;
break;
case STATE_TERMINATED:
OSPrintf("[OSIntCtxSw] Error: Invalid state STATE_TERMINATED\nCur Task[%3.1d] '%s' Thread ID %5.0d\n",
(CPU_INT16S)ptcb->OSTCBId,
ptcb->OSTCBTaskName,
pstack->ThreadID);
state_err = 1;
break;
#endif
default:
state_err = 1;
break;
}
if (state_err == 0) {
OSTCBCur = OSTCBHighRdy;
OSPrioCur = OSPrioHighRdy;
ptcb = OSTCBHighRdy;
pstack_new = (OS_TASK_STK *)ptcb->OSTCBStkPtr;
switch (pstack_new->TaskState) {
case STATE_CREATED:
ResumeThread(pstack_new->ThreadHandle);
while (pstack_new->TaskState == STATE_CREATED) { /* Wait until new task is ready to run. */
SwitchToThread();
}
SetEvent(pstack_new->SignalPtr);
break;
case STATE_INTERRUPTED:
pstack_new->TaskState = STATE_RUNNING;
ResumeThread(pstack_new->ThreadHandle);
break;
case STATE_SUSPENDED:
pstack_new->TaskState = STATE_RUNNING;
SetEvent(pstack_new->SignalPtr);
break;
#if (OS_MSG_TRACE > 0)
case STATE_NONE:
OSPrintf("[OSIntCtxSw] Error: Invalid state STATE_NONE\nNew Task[%3.1d] '%s' Thread ID %5.0d\n",
(CPU_INT16S)ptcb->OSTCBId,
ptcb->OSTCBTaskName,
pstack_new->ThreadID);
break;
case STATE_RUNNING:
OSPrintf("[OSIntCtxSw] Error: Invalid state STATE_RUNNING\nNew Task[%3.1d] '%s' Thread ID %5.0d\n",
(CPU_INT16S)ptcb->OSTCBId,
ptcb->OSTCBTaskName,
pstack_new->ThreadID);
break;
case STATE_TERMINATING:
OSPrintf("[OSIntCtxSw] Error: Invalid state STATE_TERMINATING\nNew Task[%3.1d] '%s' Thread ID %5.0d\n",
(CPU_INT16S)ptcb->OSTCBId,
ptcb->OSTCBTaskName,
pstack_new->ThreadID);
break;
case STATE_TERMINATED:
OSPrintf("[OSIntCtxSw] Error: Invalid state STATE_TERMINATED\nNew Task[%3.1d] '%s' Thread ID %5.0d\n",
(CPU_INT16S)ptcb->OSTCBId,
ptcb->OSTCBTaskName,
pstack_new->ThreadID);
break;
#endif
default:
break;
}
} else {
OSDebuggerBreak();
}
}
/***************************************************************************************************
* WIN32 TASK - OSTickW32()
* Description: This functions is the Win32 task that generates the tick interrupts for uC/OS-II.
* Arguments : lpParameter is a pointer to parameters of the task.
* Note(s) : 1) Priorities of these tasks are very important.
***************************************************************************************************/
static DWORD WINAPI OSTickW32 (LPVOID lpParameter)
{
BOOLEAN terminate;
#if (TIMER_METHOD == WIN32_MM_TMR)
HANDLE wait_signal[2];
wait_signal[0] = OSTerminate_SignalPtr;
wait_signal[1] = OSTick_SignalPtr;
#endif
(void)lpParameter;
terminate = 0;
while (!terminate) {
#if (TIMER_METHOD == WIN32_MM_TMR)
switch (WaitForMultipleObjects(2, wait_signal, FALSE, INFINITE)) {
case WAIT_OBJECT_0 + 1:
ResetEvent(OSTick_SignalPtr);
#elif (TIMER_METHOD == WIN32_SLEEP)
switch (WaitForSingleObject(OSTerminate_SignalPtr, 1000 / OS_TICKS_PER_SEC)) {
case WAIT_TIMEOUT:
#endif
OSCriticalEnter();
OSIntEnter();
OSTimeTick();
OSIntExit();
OSCriticalExit();
break;
case WAIT_OBJECT_0 + 0:
terminate = 1;
break;
default:
#if (OS_MSG_TRACE > 0)
OSPrintf("[OSTickW32] Error: Invalid signal.\n");
#endif
terminate = 1;
break;
}
}
#if (OS_MSG_TRACE > 0)
OSPrintf("[OSTickW32] Terminated.\n");
#endif
return (0);
}
/***************************************************************************************************
* WIN32 TASK - OSTaskW32()
* Description: This function is a generic Win32 task wrapper for uC/OS-II tasks.
* Arguments : lpParameter is a pointer to special paraleter of the task.
* Note(s) : 1) Priorities of these tasks are very important.
***************************************************************************************************/
static DWORD WINAPI OSTaskW32 (LPVOID lpParameter)
{
OS_TASK_STK *pstack;
OS_TCB *ptcb;
ptcb = (OS_TCB *)lpParameter;
pstack = (OS_TASK_STK *)ptcb->OSTCBStkPtr;
pstack->TaskState = STATE_SUSPENDED;
WaitForSingleObject(pstack->SignalPtr, INFINITE);
OSSetThreadName(pstack->ThreadID, ptcb->OSTCBTaskName);
pstack->TaskState = STATE_RUNNING;
#if (OS_MSG_TRACE > 0)
OSPrintf("Task[%3.1d] '%s' Running\n", (CPU_INT16S)ptcb->OSTCBId, ptcb->OSTCBTaskName);
#endif
pstack->Task(pstack->TaskArgPtr);
pstack->TaskState = STATE_TERMINATING;
OSTaskDel(ptcb->OSTCBPrio);
return (0);
}
/*****************************************************************************************************
* OSCtrlBreakHandler()
* Description: This function handles control signals sent to the console window.
* Arguments : ctrl is the control signal type.
***************************************************************************************************/
static BOOLEAN OSCtrlBreakHandler (INT32U ctrl)
{
BOOL ret;
ret = FALSE;
switch (ctrl) {
case CTRL_C_EVENT: /* CTRL-C pressed. */
case CTRL_BREAK_EVENT: /* CTRL-BREAK pressed. */
case CTRL_CLOSE_EVENT: /* Console window is closing. */
case CTRL_LOGOFF_EVENT: /* Logoff has started. */
case CTRL_SHUTDOWN_EVENT: /* System shutdown in process. */
#if (OS_MSG_TRACE > 0)
OSPrintf("\nTerminating Scheduler...\n");
#endif
SetEvent(OSTerminate_SignalPtr);
if (ctrl == CTRL_CLOSE_EVENT) {
Sleep(500); /* Give a chance to OSTickW32 to terminate. */
} else {
ret = TRUE;
}
break;
default:
break;
}
return (ret);
}
/*****************************************************************************************************
* OSPrintf()
* Description: This function is analog of printf.
* Arguments : str is a pointer to format string output.
***************************************************************************************************/
#if (OS_MSG_TRACE > 0)
static int OSPrintf (char *str, ...)
{
va_list param;
int ret;
va_start(param, str);
ret = vprintf_s(str, param);
va_end(param);
return (ret);
}
#endif
/*****************************************************************************************************
* OSDebuggerBreak()
* Description: This function throws a breakpoint exception when a debugger is present.
* Arguments : none
***************************************************************************************************/
static void OSDebuggerBreak (void)
{
__try {
DebugBreak();
}
__except(GetExceptionCode() == EXCEPTION_BREAKPOINT ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
return;
}
}
/*****************************************************************************************************
* OSSetThreadName()
* Description: This function sets thread names.
* Arguments : dwThreadID Thread ID.
* strThreadName is a pointer to name of the thread string.
***************************************************************************************************/
static void OSSetThreadName (DWORD dwThreadID, INT8U *strThreadName)
{
THREADNAME_INFO info;
info.dwType = (DWORD )0x1000;
info.szName = (LPCSTR)strThreadName;
info.dwThreadID = (DWORD )dwThreadID;
info.dwFlags = (DWORD )0;
__try {
RaiseException(MS_VC_EXCEPTION, 0, sizeof(info)/sizeof(ULONG_PTR), (ULONG_PTR*)&info);
}
__except(EXCEPTION_EXECUTE_HANDLER) {
}
}