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

📄 main.c

📁 Real Time Operating System for Hi-Tech C compiler.
💻 C
📖 第 1 页 / 共 2 页
字号:
	Task 3 waits for semaphore   3 
	Task 4 waits for semaphore   4 (!) 
	Task 5 waits for semaphore   4 (!) 
	Task 6 signals semaphores  1-5 (!)

NOTE that the argument to OS_Delay() must never be 0, as
that is equivalent to OS_Stop().  Hence the add to guarantee
that OS_Delay()'s argument is at least 1.

NOTE that without the delay for mode 2, the other tasks
would never run, as task 6 has the highest priority. 

NOTE the need to re-obtain the taskID after each context
switch -- the need to do it in OS_WaitSem() is subtle.

NOTE each task successfully waits the semaphore, even when
we switch to mode 1, because the task runs again within the
OS_WaitSem() construct after having waited for an unavail-
able task, regardless of the mode.

**                                                         **
****                                                     ****
************************************************************/
void TaskRandom ( void )
{
	static char i;
	OStypeEcbP  ecbP;
	
	
	for (;;) {
		/* mode 1 -- simple running. 	 			*/
		if ( !(flag & FLAG_MODE) ) {
			for ( i = 0 ; i < TMR1H ; i++ )
				OS_Yield(TaskRandom1);
				
			OS_Delay((TMR0 & DELAY_MASK) + 1, TaskRandom2);
		}	
			
		/* mode 2 -- semaphores in play. 			*/
		else {	
			
			/* different tasks do different	things 	*/
			/*  ...  1 <= i <= SIGNALING_TASKID 	*/
			/*  since that's how TaskRandom() was	*/
			/*  created.							*/
			i = OStID(OScTcbP);
			
			/*  Code will fail if an out-of-bounds	*/
			/*  event is signaled ... therefore		*/
			/*  table lookup and null ptr test are	*/
			/*  employed.							*/
			if ( i == SIGNALING_TASKID ) {
				ecbP = (OStypeEcbP) semP[TMR1L & 0x07];
				if ( ecbP )
					OSSignalSem(ecbP);
				PORT ^= 0x20;
				OS_Delay(2, TaskRandom3);
			}
			/* here one of the waiting tasks waits	*/
			/*  the appropriate semaphore. Note how */
			/*  i is assigned the tID.				*/
			else {	
				OS_WaitSem((OStypeEcbP) semP[(i = OStID(OScTcbP))-1], 
				  32 + (TMR1L & 0x3F), TaskRandom4);
		
				/* flash (correct) LED for 20ms. 	*/
				/*  i _is_ defined prior to 		*/
				/*  OS_Delay()!						*/
				PORT |= 0x01 << (i-1);
				OS_Delay(2, TaskRandom5);
				PORT &= ~(0x01 << (OStID(OScTcbP)-1));
			}
		}
	}
}


/************************************************************
****                                                     ****
**                                                         **
TaskStats()

Monitors S2 and S3 keys and displays task stats (S2) or
toggle operating mode (S3) when a key is pressed.

Note that this task delays instead of simply yielding when
waiting for keys to be released.  That's because it's the
highest-priority task, and without a delay it will hog
the processor and prevent lower-priority tasks from context-
switching.

**                                                         **
****                                                     ****
************************************************************/
void DoS2Action ( void )
{
	/* if we're showing the '.'s, we	*/
	/*  must suppress them in order to	*/
	/*  freeze OSRpt()'s output.		*/
	if ( flag & FLAG_SHOW_CTXSWS ) {
		flag &= ~FLAG_SHOW_CTXSWS;
		flag |= FLAG_CALL_OSRPT;
	}
	/* o/wise we can start showing the	*/
	/*  '.'s again.						*/
	else {
		flag |= FLAG_SHOW_CTXSWS;
	}
}


void DoS3Action ( void )
{
	/* toggle mode and force an update.	*/
	flag ^= FLAG_MODE;
	flag |= FLAG_MODE_CHANGED;
	
	/* Restart TaskDummy() for mode 1,	*/
	/*  stop it for mode 2.				*/
	if ( !(flag & FLAG_MODE) ) {
		OSStartTask(TASK_DUMMY_P);
	}
	else
		OSStopTask(TASK_DUMMY_P);

	/* clear LEDs 'cause we've changed	*/
	/*  modes.							*/
	PORT = 0x00;
}


void TaskStats ( void )
{
	/* cheezy way to avoid keybounce when starting	*/
	/*  up ...										*/
	OS_Delay(20, TaskStats1);

	for (;;) {
	
		/* toggle LED6 only if we're in mode 2		*/
		if ( flag & FLAG_MODE )
			PORT ^= 0x40;
			
		#if USE_HDWR_KEYS			
		/* keypress means user wants to see stats.	*/
		if ( !keyS2 || !keyS3 ) {
		
			/* wait key bounce period of 30ms.		*/
			OS_Delay(3, TaskStats2);
		
			/* if key is still pressed, then it's	*/
			/*  valid.								*/
			if ( !keyS2 ) {
			
				/* now we need to wait until S2		*/
				/*  is released.					*/
				for (;;) {
				
					OS_Delay(1, TaskStats3);
					if ( keyS2 )
						break;
				}
				
				/* now act on S2 keypress           */
				DoS2Action();				
			}
			
			/* repeat for S3						*/
			if ( !keyS3 ) {
			
				for (;;) {
					OS_Delay(1, TaskStats4);
					if ( keyS3 )
						break;
				}
				
				/* now act on S2 keypress           */
				DoS3Action();
			}
		}
		#else
		if ( 0 ) { ; }
		#endif
		
		/* no keypress -- check for RX command      */
		else {
		
			/* Since we're already context-switching*/
			/*  with OS_Delay(), it's more efficient*/
			/*  to simply poll a global variable    */
			/*  than to set up a message and signal */
			/*  it from the ISR.                    */
			switch ( rxChar ) {
			
				/* restart application */
				case '1':
					Reset();
					break;
				
				/* mimic S2 or S3 keypress */
				case '2':
				case '3':
					if ( rxChar == '2' )
						DoS2Action();
					else
						DoS3Action();
					break;
					
				/* unsupported commands */
				default:
					break;
			}
			
			/* protection is required */
			OSDi();
			rxChar = 0;
			OSEi();
		}
		
		/* check key(s) again 20ms from now.		*/	
		OS_Delay(2, TaskStats5);
	}
}


/************************************************************
****                                                     ****
**                                                         **
ShowMode()

Utility function used in more than one place ...
**                                                         **
****                                                     ****
************************************************************/
void ShowMode( void )
{
	if ( !(flag & FLAG_MODE) )
		putstr(strMode1);
	else
		putstr(strMode2);
}


/************************************************************
****                                                     ****
**                                                         **
intVector()

Periodic interrupt via Timer2 occurs every bit time.  TMR2
is reloaded automatically from period register PR2.  Clear 
the interrupt flag, handle async char transmission, and call 
Salvo's timer routine.


**                                                         **
****                                                     ****
************************************************************/
#if defined(SYSA) || defined(SYSF) /* PIC16 or PIC18 */

#if !OSUSE_INLINE_OSTIMER
#include "timer.c"
#endif


/* needed if calling Salvo services from ISR */
#pragma interrupt_level 0

void interrupt IntVector( void )
{
	if ( bitTMR2IE && bitTMR2IF )	{
		/* Clear TMR2's	interrupt flag.			*/
		bitTMR2IF = 0;
					
		/* Salvo's prescalar is set to 5 in		*/
		/*  salvocfg.h, so timer ticks at		*/
		/*  500Hz / 5, or 100Hz, or every 10ms.	*/
		#if !OSUSE_INLINE_OSTIMER
		OSTimer();
		#else
		#include "timer.c"
		#endif
	}

	/* send the valid char, then check if		*/
	/*  it was NL (the last char) -- if so,		*/
	/*  shut down the transmitter, else			*/
	/*  advance the pointer.					*/
	if ( bitTXIF && txCount )	{

		TXREG = txBuff[txOutPtr++];
		
		if ( txOutPtr > TX_BUFF_SIZE-1 )
			txOutPtr = 0;
			
		txCount--;

		if ( txCount == 0 )
			bitTXIE = 0;	
				
	} /* if */	
	
	/* when a single-character command is       */
	/*  received, store it in rxChar and echo   */
	/*  it to the terminal.                     */
	if ( bitRCIF && bitRCIE ) {
	
		/* clear RCIF flag, get char */
		rxChar = RCREG;
			
		/* echo received char */
		while ( !bitTRMT ) ;
        TXREG = rxChar;
        	
	} /* if */
}


#elif defined(SYSE) /* PIC18 */

#if !OSUSE_INLINE_OSTIMER
#include "timer.c"
#endif


void IntVector ( void );

/* locator for high-priority ISR */
#pragma code highVector = 0x08
void athighVector ( void )
{
	_asm GOTO IntVector _endasm
}
#pragma code /* end of ISR locator */

#pragma interrupt IntVector save=section(".tmpdata"),PROD
void IntVector( void )
{
    if ( bitTMR2IE && bitTMR2IF )
    {
        bitTMR2IF = 0;
			
  		#if !OSUSE_INLINE_OSTIMER
		OSTimer();
		#else
		#include "timer.c"
		#endif
    } /* if */

	if ( bitTXIF && txCount )	{

		TXREG = txBuff[txOutPtr++];
		
		if ( txOutPtr > TX_BUFF_SIZE-1 )
			txOutPtr = 0;
			
		txCount--;

		if ( txCount == 0 )
			bitTXIE = 0;	
				
	} /* if */	
	
	if ( bitRCIF && bitRCIE ) {
	
		/* clear RCIF flag, get char */
		rxChar = RCREG;
			
		/* echo received char */
		while ( !bitTRMT ) ;
        TXREG = rxChar;
        	
	} /* if */
}

#elif defined(SYST) /* M68HC11 */ 

#pragma interrupt_handler intVector

void intVector ( void )
{
	/* clear RTIF */
	TFLG2 |= 0b01000000;
	
	#if !OSUSE_INLINE_OSTIMER
	OSTimer();
	#else
	#include "timer.c"
	#endif
	
	/* Tx and Rx are done using BUFFALO's    */
	/*  utility subroutines ...              */
	
	/* poll the Rx UART by calling BUFFALO's */
	/*  INPUT utility subroutine @ FFACh.    */
	/*  Avoid overwriting received char.     */
	asm(" jsr 0xFFAC");
	asm(" staa _tmpRxChar");
	if ( tmpRxChar != 0 )
		rxChar = tmpRxChar;
}                      


#pragma abs_address:0x00EB	   /* RTI BUFFALO 3.4 EVB11  */

	asm(" jmp _intVector");	   

#pragma end_abs_address


#endif /* #if defined(SYSA) ... */


⌨️ 快捷键说明

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