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

📄 ucos.c

📁 各种硬件平台上的us OS移植实例(arm6)
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * u C / O S . c * * Modified * by	Geary Chopoff * for	VLSI * * Version October 18, 1994 *	Added IRQMboxPost() to post a message from an IRQ * * Version July 27, 1994 *  Changed CreateTask so that pdata is passed in a1 (as ARM intended) * * Version July 18, 1994 *	Changed ENTER_CRITICAL to OS_ENTER_CRITICAL *	Changed EXIT_CRITICAL to OS_EXIT_CRITICAL * * Version July 15, 1994 *	Changing OSInit(), removed OSEnter *	Added call to InitTask in OSTaskCreate * * Version July 14, 1994 *	need to fix IRQ vector (look for ***) * * Version July 13, 1994 *	Placed prototypes here * * Version July 12, 1994 *	Continuing with effort to bring uC/OS code inline with manual *	Removed PIDLED code from OSTimeTick(). * * Version July 11, 1994 *	Noted changes between current code and one from manual. *	OSIntExit() may have a major flaw as implemented, remember to investigate. * * Version May 9, 1994 *	Bringing code closer to manual... *	Added comments. *	Verified code * * File: os.c * * uC/OS Real-time multitasking kernel for the ARM processor. * * Copyright (C) 1992 Jean J. Labrosse. All rights reserved. * Copyright (C) 1993 VLSI Technology Inc. All rights reserved. * * VLSI Technology Inc. does not assume any liability arising out of * this program or use thereof. * */#define		uC_OS#include	"ucos.h"    /* uC/OS interface */#include	"osdefs.h"	/* VLSI "OS_STAT_*" values are in here *//* VLSI let's stay on the safe side */#pragma         no_check_stack#pragma         no_optimise_crossjump#pragma         no_optimise_multiple_loads#pragma         no_optimise_cse/* * E x t e r n a l   F u n c t i o n s */extern void		OSStartHighRdy(void);							/* kern600 */extern void		OSCtxSw(void);									/* kern600 */extern void    *InitTask(void *pstk, void *pdata, PTV task);	/* kern600 *//* * P r o t o t y p e s */void		OSInit(void);							/* initialize uC/OS */void		OSTaskIdle(void *data);					/* idle task */void		OSStart(void);							/* start multitasking */void		OSSched(void);							/* scheduler */void		OSSchedLock(void);						/* prevent rescheduling */void		OSSchedUnlock(void);					/* allow rescheduling */int			OSTCBInit(uint	prio, void *pstk);		/* initialize Task Control Block */void		OSIntEnter(void);						/* interrupt entered */int			OSIntExit(void);						/* interrupt exited */int			OSTaskChangePrio(uint oldp, uint newp);	/* change priority of task */int			OSTaskDel(uint p);						/* delete a task */void		OSTimeDly(uint ticks);					/* delay a task */void		OSTimeTick(void);						/* process a system tick */void		OSTimeSet(uint ticks);					/* set system time */uint		OSTimeGet(void);						/* get system time */OS_EVENT   *OSSemCreate(int cnt);					/* create a semaphore */void		OSSemPend(OS_EVENT *pevent, uint timeout, uint *err);	/* wait semaphore */uint		OSSemPost(OS_EVENT *pevent);			/* signal semaphore */OS_EVENT   *OSMboxCreate(void *msg);				/* create mailbox */void	   *OSMboxPend(OS_EVENT *pevent, uint timeout, uint *err);	/* pend for message */uint		OSMboxPost(OS_EVENT *pevent, void *msg);	/* post message */OS_EVENT   *OSQCreate(void **start, uint size);	/* create a queue */void	   *OSQPend(OS_EVENT *pevent, uint timeout, uint *err);	/* pend for message */uint		OSQPost(OS_EVENT *pevent, void *msg);		/* post a message */void		OSEventTaskResume(OS_EVENT *pevent);int			OSTaskCreate(PTV task, void *pdata, void *ptsk, uint prio);uint		IRQMboxPost(OS_EVENT *pevent, void *msg);	/* post message *//* mapping table to map bit position to bit mask */uint const OSMapTbl[] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 };/* priority resolution table */uint const OSUnMapTbl[] = {	0, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,	4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,	5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,	4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,	6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,	4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,	5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,	4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,	7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,	4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,	5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,	4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,	6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,	4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,	5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,	4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,};/* * G L O B A L   V a r i a b l e s */uint    OSCtxSwCtr;			/* context switches counter */uint    OSIdleCtr;			/* Counter used in OSTaskIdle() (idle counter) */uint    OSRunning = FALSE;	/* kernel running flag */uint	OSIntNesting;		/* VLSI interrupt nesting level */OS_TCB  *OSTCBCur;			/* current running TCB pointer */OS_TCB  *OSTCBHighRdy;		/* highest priority TCB ready to run */OS_TCB  *OSTCBPrioTbl[OS_LO_PRIO + 1];	/* GIC 94Jul11 (chg'ed 64 to OS_LO_PRIO+1) table of pointers to created TCBs *//* local variables */static	OS_TCB	*OSTCBList;					/* TCBs are doubled linked list */static	uint	OSRdyGrp;					/* ready list group */static	uint	OSRdyTbl[MAXbits];			/* GIC 94Jul11 (chg'ed 8 to MAXbits) table of ready to run tasks */static	uint	OSLockNesting;				/* multitasking lock nesting level *//* static UBYTE OSIntNesting *** missing GIC 94Jul11  Interrupt nesting level */static	OS_TCB	 *OSTCBFreeList;			/* free TCBs list */static	OS_EVENT *OSEventFreeList;			/* free EVENT CB list */static	OS_Q	 *OSQFreeList;				/* free QUEUE CB list */static	uint	  OSTime;					/* system time in ticks *//* static UBYTE OSIntExitY *** missing GIC 94Jul11 Variable used by 'OSIntExit' to prevent using locals */static	uint	OSIdleStk[OS_IDLE_STK_SIZE]; /* idle task stack */static	OS_TCB	OSTCBTbl[OS_MAX_TASKS + 1];	/* TCBs table */static	OS_EVENT OSEventTbl[OS_MAX_EVENTS];	/* EVENT CBs table */static	OS_Q	OSQTbl[OS_MAX_QS];			/* QUEUE CBs table */IRQHandlerFn IRQvectors[NUMIRQS];   /* VLSI: IRQ source bit handlers */FIQHandlerFn FIQvectors[NUMFIQS];   /* VLSI: FIQ source bit handlers *//* * O S I n i t * * initialize uC/OS * * NOTE: this function must be called before OSStart() */void	OSInit(void){ const void	*pZERO = 0;		/* need a pointer to value of 0 */ int		 i;	/* initialize variables */	OSTime			= 0;			/* VLSI, org = 0L */	OSTCBHighRdy	= (OS_TCB *)0;	OSTCBCur		= (OS_TCB *)0;	OSTCBList		= (OS_TCB *)0;	OSIntNesting	= 0;	OSLockNesting	= 0;	OSRunning		= FALSE;		/* VLSI, org = 0 */	OSRdyGrp		= 0;	OSIdleCtr		= 0;			/* VLSI, org = 0L */	OSCtxSwCtr		= 0;    for (i = 0; i < NUMIRQS; i++)   /* VLSI - initialise IRQvectors */        IRQvectors[i] = DummyIRQ;    for (i = 0; i < NUMFIQS; i++)   /* VLSI - initialise FIQvectors */        FIQvectors[i] = DummyFIQ;    /* At the moment we do not check that the uC/OS IRQ handler is     * attached properly. There is no error return information from     * the OSInit function, and all that will happen is that no     * interrupts are processed.      */    (void)SWI_InstallHandler(0x46,0,IRQHandler) ;    /* TODO: uC/OS system FIQ handler to be coded */		for (i = 0; i < MAXbits; i++)		/* GIC 94Jul11 chg'ed 8 to MAXbits */		{		OSRdyTbl[i] = 0;		}	for (i = 0; i <= OS_LO_PRIO; i++) 	/* GIC 94Jul11 chg'ed 64 to OS_LO_PRIO and < to <= */		{		OSTCBPrioTbl[i] = (OS_TCB *)0;		}	for (i = 0; i < OS_MAX_TASKS; i++)	/* init list of free TCBs */		{		OSTCBTbl[i].OSTCBNext = &OSTCBTbl[i + 1];		}	OSTCBTbl[OS_MAX_TASKS].OSTCBNext	= (OS_TCB *)0;	/* last OS_TCB is for OSTaskIdle() */	OSTCBFreeList						= &OSTCBTbl[0];		for (i = 0; i < OS_MAX_EVENTS - 1; i++)	/* init list of free EVENT control blocks */		{		OSEventTbl[i].OSEventPtr = &OSEventTbl[i + 1];		}	OSEventTbl[OS_MAX_EVENTS - 1].OSEventPtr	= (OS_EVENT *)0;	OSEventFreeList								= &OSEventTbl[0];	for (i = 0; i < OS_MAX_QS - 1; i++)	/* init list of free QUEUE control blocks */		{		OSQTbl[i].OSQPtr = &OSQTbl[i + 1];		}	OSQTbl[OS_MAX_QS - 1].OSQPtr	= (OS_Q *)0;	OSQFreeList						= &OSQTbl[0];	/* create the idle task */	OSTaskCreate(OSTaskIdle,(void *)&pZERO, (void *)&OSIdleStk[OS_IDLE_STK_SIZE], OS_LO_PRIO);}/* * O S T a s k I d l e * * idle task */void	OSTaskIdle(void *data){	while(FOREVER)		{		OS_ENTER_CRITICAL();		OSIdleCtr++;		OS_EXIT_CRITICAL();		}} /* OSTaskIdle *//* * O S S t a r t * * start multitasking */void	OSStart(void){ uint	y; uint	x; uint	p;	y				= OSUnMapTbl[OSRdyGrp];		/* find the highest priority task */	x				= OSUnMapTbl[OSRdyTbl[y]];	p				= (y << 3) + x;	OSTCBHighRdy	= OSTCBPrioTbl[p];	/* point to highest priority task ready to run */	OSRunning		= TRUE;				/* VLSI org = 1 */	OSStartHighRdy();	/* enable interrupts and run the highest priority task */}/* * O S S c h e d * * uC/OS scheduler */void	OSSched(void){ uint			y;				/* VLSI org is 'register UBYTE y' */	OS_ENTER_CRITICAL();	/*	 * NOTE: following is a deviation from uC/OS manual. In the manual it	 *		 is:	 *			if((OSLockNesting | OSIntNesting) == 0)	 * GIC 94Jul11	 */	if (OSLockNesting == 0 && OSIntNesting == 0) /* VLSI task scheduling enabled and not interrupt level */		{		y				= OSUnMapTbl[OSRdyGrp];	/* get pointer to highest task ready to run */		OSTCBHighRdy	= OSTCBPrioTbl[(y << 3) + OSUnMapTbl[OSRdyTbl[y]]];		if (OSTCBHighRdy != OSTCBCur)			/* make sure this is not the current running task */			{			OSCtxSwCtr++;						/* increment context switch counter */			OSCtxSw();							/* VLSI perform context switch */			/* OS_TASK_SW(); is used in place of previous line *** missing GIC 94Jul11 */			}		}	OS_EXIT_CRITICAL();   }/* * O S S c h e d L o c k * * prevent scheduling */void	OSSchedLock(void){	OS_ENTER_CRITICAL();	OSLockNesting++;	/* increment lock nesting level */	OS_EXIT_CRITICAL();}/* * O S S c h e d U n l o c k * * allow scheduling */void	OSSchedUnlock(void){/* * NOTE: the following is equivalent to the code in the manual, but different */	OS_ENTER_CRITICAL();	if (OSLockNesting == 0)		{		OS_EXIT_CRITICAL();		return;		}	/* ELSE */	OSLockNesting--;	if ((OSLockNesting == 0)&&(OSIntNesting == 0))		{		OS_EXIT_CRITICAL();	/* scheduling re-enabled and not an ISR */		OSSched();			/* check if a higher priority task became ready */		}	else		{		OS_EXIT_CRITICAL();		}}/* * O S T C B I n i t * * find and initialize a TCB */int	OSTCBInit(uint	prio, void *pstk){	OS_TCB	*ptcb;	OS_ENTER_CRITICAL(); 	ptcb = OSTCBFreeList;		/* get a free TCB from TCB free list */	if (ptcb == (OS_TCB *)0)		{		OS_EXIT_CRITICAL();		/* no TCB available */		return(OS_NO_MORE_TCB);		}	/* ELSE */	OSTCBFreeList		= ptcb->OSTCBNext;	/* link to the next free */	OSTCBPrioTbl[prio]	= ptcb;	ptcb->OSTCBStkPtr	= pstk;				/* top of private stack */	ptcb->OSTCBPrio		= prio;				/* task priority */	ptcb->OSTCBStat		= OS_STAT_RDY;		/* task is ready to run */	ptcb->OSTCBDly		= 0;	ptcb->OSTCBX		= prio & 0x07;	ptcb->OSTCBBitX		= OSMapTbl[prio & 0x07];	ptcb->OSTCBY		= prio >> 3;	ptcb->OSTCBBitY		= OSMapTbl[prio >> 3];	ptcb->OSTCBEventPtr	= (OS_EVENT *)0;	ptcb->OSTCBNext		= OSTCBList;	if (OSTCBList == (OS_TCB *)0)	/* GIC chg'ed for clarification */		{		ptcb->OSTCBPrev = (OS_TCB *)0;		}	else		{		ptcb->OSTCBPrev = ptcb;		}	OSTCBList			 = ptcb;/* * NOTE: following needs to be changed if MAXbits is changed from 8 to something else */	OSRdyGrp			|= OSMapTbl[prio >> 3];	OSRdyTbl[prio >> 3] |= OSMapTbl[prio & 0x07];	OS_EXIT_CRITICAL(); return(OS_NO_ERR);}/* * O S I n t E n t e r */void	OSIntEnter( void ){#if 0 /* the current ARM implementation executes this with interrupts disabled */    OS_ENTER_CRITICAL();#endif	OSIntNesting++;		/* increment ISR nesting level */#if 0 /* see comment above */    OS_EXIT_CRITICAL();#endif}/* * O S I n t E x i t * * exit from interrupt * */int		OSIntExit(void){ uint	y;#if 0 /* see comment in OSIntEnter above */    OS_ENTER_CRITICAL();#endif	if (--OSIntNesting == 0 && OSLockNesting == 0)	/* reschedule if all ISR completed and not locked */		{		y = OSUnMapTbl[OSRdyGrp];		OSTCBHighRdy = OSTCBPrioTbl[(y << 3) + OSUnMapTbl[OSRdyTbl[y]]];		if (OSTCBHighRdy == OSTCBCur)	/* VLSI */			return(FALSE);	/* the highest priority task is the current task */		else			return(TRUE);	/* signal preemption to IRQTrap */		}#if 0 /* see comment in OSIntEnter above */    OS_EXIT_CRITICAL();#endif return(FALSE);}/* * O S T a s k C h a n g e P r i o * * change task priority * * NOTE: VLSI rearrange the logic so that the ELSE is implied */int		OSTaskChangePrio(uint oldp, uint newp){ OS_EVENT	*pevent;	/* VLSI org prefixed with 'register' */ OS_TCB		*ptcb;		/* VLSI org prefixed with 'register' */ int		 rdy;		/* VLSI org was type BOOLEAN */	OS_ENTER_CRITICAL();	/* first check that new priority not in use */	if (OSTCBPrioTbl[newp] != (OS_TCB *)0)	/* New priority must not already exist */		{		OS_EXIT_CRITICAL();

⌨️ 快捷键说明

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