📄 os_cpu_c.c
字号:
/*********************************************************************************************************** uC/OS-II* The Real-Time Kernel (by Jean J. Labrosse)** LINUX PORT** (c) Copyright 2004, Werner.Zimmermann@fht-esslingen.de* All Rights Reserved** File : OS_CPU_C.C* By : Werner Zimmermann** Changes: 1.50 First Release of LINUX Port - same version number as WIN32 port* 1.60 Increased resolution of PC_Elapsed... time measurement. Now uses the Pentium* time stamp counter.***********************************************************************************************************/#define OS_PORT_VERSION 160 //Version number of the uCOS-II LINUX port/********************************************************************************************************** Includes**********************************************************************************************************/#include <stdio.h>#include <stdlib.h>#include <stdarg.h>#include <sys/time.h>#include <sys/resource.h>#include <sys/sem.h>#include <signal.h>#include <sched.h>#include <assert.h>#include "os_cpu.h"#include "os_cfg.h"#include "uCOS_II.h"typedef struct itimerval ITIMERVAL;typedef int (*LPTHREAD_START_ROUTINE)(void*);/********************************************************************************************************** Global variables**********************************************************************************************************/INT32S hMainThread;INT32S hScheduleEvent, hScheduleThread; //Scheduler thread variablesINT32S hTaskThread[OS_LOWEST_PRIO + 2]; //Map uCOS tasks to LINUX threadsINT8S taskSuspended[OS_LOWEST_PRIO + 2]; //Suspend status of mapped tasks/threads#define NINTERRUPTS 8 //Number of interrupt events (DO NOT CHANGE)INT32S hInterruptEvent[NINTERRUPTS], hInterruptThread; //Interrupt handling thread variablesvoid (*interruptTable[NINTERRUPTS])();BOOLEAN virtualInterruptFlag=TRUE;INT32S eventType = 0;sigset_t interruptSignalSet;INT32S criticalSection;BOOLEAN idleTrigger = TRUE; //Trigger a message, when the idle task is //invoked (used for debugging purposes)#define NLOG 16 //Log last scheduled tasks (used forINT16U taskLog[NLOG]; //... debugging purposes)/********************************************************************************************************** Port-specific functions**********************************************************************************************************/void InitializeCriticalSection(INT32S *sema){ *sema = semget(1, 1, IPC_CREAT | 0666); semctl(*sema, 0, SETVAL, 1);}void EnterCriticalSection(INT32S *sema){ struct sembuf op; op.sem_num=0; op.sem_flg=0; op.sem_op=-1; }void LeaveCriticalSection(INT32S *sema){ struct sembuf op; op.sem_num=0; op.sem_flg=0; op.sem_op=+1; }// DBGPRINT ******************************************************************// Debug outputvoid 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 LINUX portINT16U OSPortVersion(void){ return OS_PORT_VERSION;}void CtrlBreakHandler(int ctrl){ if (ctrl==SIGTSTP) //Handler if CTRL-D is pressed { printf("---Exiting OSPrioCur=%u-------------\n", OSPrioCur); //---Display current task priority } else if (ctrl==SIGINT) //Handler if CTRL-C is pressed { printf("---Exiting OSPrioCur=%u-------------\n", OSPrioCur); //---Display current task priority and exit exit(0); }}// OSEnableInterruptFlag ****************************************************// Enable the interrupt flagvoid OSEnableInterruptFlag(void){ if (virtualInterruptFlag==FALSE) //If the timer interrupt previously was disabled, { virtualInterruptFlag=TRUE; if (getpid()!=hInterruptThread) sigprocmask(SIG_UNBLOCK, &interruptSignalSet, NULL);//... resume the interrupt thread } DBGPRINT(0x00000080, ">>> ODEnableInterruptFlag %2d\n", virtualInterruptFlag);}// OSDisableInterruptFlag ****************************************************// Disable the Interrupt Flagvoid OSDisableInterruptFlag(void){ if (virtualInterruptFlag==TRUE) //If the timer interrupt previously was enabled, { if (getpid()!=hInterruptThread) //... suspend the interrupt thread ... sigprocmask(SIG_BLOCK, &interruptSignalSet, NULL); virtualInterruptFlag=FALSE; } DBGPRINT(0x00000080, ">>> OSDisableInterrupts %2d\n", virtualInterruptFlag);}void OSDummyISR(void){ perror("Got unsupported interrupt");}// OSTickTickCallback ********************************************************// Callback function for time tick 'interrupt', acts as a relay to OSTickISRvoid OSTimeTickCallback(int para){ DBGPRINT(0x00000008, "*** OSTimeTickCallback\n"); kill(hInterruptThread, hInterruptEvent[0]); //Trigger the interrupt thread}// OSScheduleThread ***********************************************************// Start tasks, triggered by hScheduleEventvoid OSScheduleEventHandler(int val){ //dummy handler, necessary for pause() in OSScheduleThread()}void OSScheduleThread(int param){ char temp[256]; INT16U oldPrio, nextPrio; DBGPRINT(0x00000001, "*** OSScheduleThread First Call\n", oldPrio, nextPrio); while (1) { pause(); 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 ... { kill(hTaskThread[oldPrio], SIGSTOP); //... 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); kill(hTaskThread[nextPrio], SIGCONT); //... and resume the thread associated with the new task } else { if (virtualInterruptFlag==FALSE) OSEnableInterruptFlag(); } LeaveCriticalSection(&criticalSection); }}// OSInterruptThread **********************************************************// Time tick interrupt processingvoid OSInterruptEventHandler(int val){ eventType=val; //dummy handler, necessary for pause() in OSInterruptThread()}void OSInterruptThread(int param){ char temp[256]; DBGPRINT(0x00000001, "*** OSInterruptThread First Call\n"); while (1) { pause(); 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==hInterruptEvent[0]) //Call uCOS' interrupt processing { interruptTable[0](); //IRQ0 reserved vor time tick: OSTimeTick(); } else if (eventType==hInterruptEvent[1]) { interruptTable[1](); } else if (eventType==hInterruptEvent[2]) { interruptTable[2](); } else if (eventType==hInterruptEvent[3]) { interruptTable[3](); } else if (eventType==hInterruptEvent[4]) { interruptTable[4](); } else if (eventType==hInterruptEvent[5]) { interruptTable[5](); } else if (eventType==hInterruptEvent[6]) { interruptTable[6](); } else if (eventType==hInterruptEvent[7]) { interruptTable[7]();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -