📄 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.* 2.00 Major change of signal generation and handling to adapt the Linux port to* threading changes in Linux kernel 2.6.x. Use gettid() instead getpid() and* tkill() instead of kill() because clone() changed.* 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,* made OSTaskIdleHook() and OSTaskCreateHook() instead of OSTCBInitHook() user callable.***********************************************************************************************************/#define OS_PORT_VERSION 300 //Version number of the uCOS-II LINUX port#define SHOWTID 1/********************************************************************************************************** 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 <linux/unistd.h>#include <asm/unistd.h>#if (OS_VERSION <= 270)#include "os_cpu.h"#include "os_cfg.h"#include "ucos_ii.h"#else#include "ucos_ii.h"#endiftypedef 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, scheduleSignalSet, oldScheduleSignalSet, oldInterruptSignalSet;BOOLEAN interruptSignalFlag=FALSE, scheduleSignalFlag=FALSE;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"); DBGPRINT(0x00000008, "--- Sending signal to PID=%u\n", hInterruptThread); kill(hInterruptThread, hInterruptEvent[0]); //Trigger the interrupt thread}// OSScheduleThread ***********************************************************// Start tasks, triggered by hScheduleEventvoid OSScheduleEventHandler(int val){ //dummy handler, necessary for pause() in OSScheduleThread() DBGPRINT(0x00000001, "--- OSScheduleEventHandler ---\n"); scheduleSignalFlag=TRUE;}void OSScheduleThread(int param){ char temp[256]; INT16U oldPrio, nextPrio; DBGPRINT(0x00000001, "*** OSScheduleThread First Call %u %u PID=%u TID=%u\n", oldPrio, nextPrio, getpid(), gettid()); while (1) { DBGPRINT(0x00000001, "--- OSScheduleThread: Going to pause ---\n");// pause(); sigprocmask(SIG_BLOCK, &scheduleSignalSet, &oldScheduleSignalSet); while(!scheduleSignalFlag) sigsuspend(&oldScheduleSignalSet); sigprocmask(SIG_UNBLOCK, &scheduleSignalSet, NULL); scheduleSignalFlag=FALSE; DBGPRINT(0x00000001, "--- OSScheduleThread: Resume from pause ---\n"); OSTaskSwHook(); //Call the task switch hook function EnterCriticalSection(&criticalSection); oldPrio =OSPrioCur; nextPrio=OSPrioHighRdy; OSTCBCur = OSTCBHighRdy; OSPrioCur = OSPrioHighRdy; idleTrigger = TRUE; DBGPRINT(0x00000001, "*** OSScheduleThread from %2u to %2u PID=%u TID=%u\n", oldPrio, nextPrio, getpid(), gettid()); if (oldPrio != nextPrio && taskSuspended[oldPrio]==0) //If switching context to a new task ... { DBGPRINT(0x00000001, "--- Sending signal SIGSTOP to PID=%u\n", hTaskThread[oldPrio]); 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); DBGPRINT(0x00000001, "--- Sending signal SIGCONT to PID=%u\n", hTaskThread[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() DBGPRINT(0x00000001, "--- OSInterruptEventHandler ---\n"); interruptSignalFlag=TRUE;}void OSInterruptThread(int param){ char temp[256]; DBGPRINT(0x00000001, "*** OSInterruptThread First Call PID=%u TID=%u\n", getpid(), gettid()); while (1) { DBGPRINT(0x00000001, "--- OSInterruptThread: Going to pause ---\n");// pause(); sigprocmask(SIG_BLOCK, &interruptSignalSet, &oldInterruptSignalSet); while(!interruptSignalFlag) sigsuspend(&oldInterruptSignalSet); sigprocmask(SIG_UNBLOCK, &interruptSignalSet, NULL); interruptSignalFlag=FALSE; DBGPRINT(0x00000001, "--- OSInterruptThread: Resume from pause ---\n"); EnterCriticalSection(&criticalSection); DBGPRINT(0x00000001, "*** OSInterruptThread PDI=%x TID=%u\n", getpid(), gettid()); 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();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -