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

📄 main.c

📁 Real Time Operating System for Hi-Tech C compiler.
💻 C
📖 第 1 页 / 共 2 页
字号:
/************************************************************ 
Copyright (C) 1995-2002 Pumpkin, Inc. and its
Licensor(s). Freely distributable.

$Source: C:\\RCS\\d\\salvo\\demo\\d1\\main.c,v $
$Author: aek $
$Revision: 3.16 $
$Date: 2003-07-17 23:47:22-07 $

Demo program runs 8 tasks simultaneously and uses the 
PICDEM-2's LED array to display useful information. 

Compiled with HI_TECH PIC C
Works with Microchip PIC16C64/65/67/77 & PIC18C452
Runs on Microchip PICDEM-2 demo board at 4MHz for 9600 bps.

************************************************************/

#include "main.h"
#include <salvo.h>

#if   defined(SYSE)
/* MPLAB-C18 requires that we explicitly place		*/
/*  const objects in ROM. Must come after header    */
/*  files ...                                       */
#define	const				rom const
#endif

/************************************************************
****                                                     ****
**                                                         **
Local #defines and function prototypes.

**                                                         **
****                                                     ****
************************************************************/

/* task and event handles */
#define	TASK_STATS_P		OSTCBP(7)
#define	TASK_DUMMY_P		OSTCBP(8)		
#define	SEM1_P				OSECBP(1)					
#define	SEM2_P				OSECBP(2)					
#define	SEM3_P				OSECBP(3)					
#define	SEM4_P				OSECBP(4)					
#define	SEM5_P				OSECBP(5)					


/* bitfields for flag */	
#define FLAG_MODE			0x01	/* delays (mode 1) or */
									/*  events (mode 2)	  */
#define FLAG_CALL_OSRPT		0x02	/* call OSRpt()		  */
#define FLAG_SHOW_CTXSWS	0x04	/* control '.'s		  */
#define FLAG_MODE_CHANGED	0x08	/* pass up to main	  */

/* function prototypes */
void ShowMode(void);
void TaskBlinkLED(void);
void TaskDummy(void);
void TaskRandom(void);
void TaskStats(void);
void TaskWaitAWhile(void);

/* external function prototypes */
extern void putch(char c);
extern void putstr(const char *c);
/* extern void putASCIIHex(char c); */
extern void InitTx(void);
extern void SndTxChar(void);
extern unsigned char RtnRoomInTxBuff(void);

/* bargraph LED patterns */
const char LEDs[9]       = { 0x00, 
					         0x80, 0xC0, 0xE0, 0xF0, 
					         0xF8, 0xFC, 0xFE, 0xFF };

/* semaphores associated with tasks 1-5. Entries 0-4 are	*/
/*  used by tasks 1-4 to wait on sems 1-4. Entries 0-5 are	*/
/*  used to randomly signal sems 1-5. 						*/ 					   
OStypeEcbP const semP[8]  = { SEM1_P, 
                              SEM2_P, 
                              SEM3_P, 
                              SEM4_P, 
                              SEM4_P, 
                              SEM5_P, 
                              0, 
                              0 };


/* priorities of tasks 0-5 */
const OStypePrio prio[6] = { 2, 3, 4, 5, 5, 1 };

/* splash screen */
const char strSplash[] = 
	NEWLINE
	"Salvo(TM) Demo #1:  (C)Copyright 1995-2002 Pumpkin, Inc.  All Rights Reserved." NEWLINE NEWLINE
	"Task |       Mode 1                      |          Mode 2       Sem PORT/LED" NEWLINE
	"  1  |  Run for a random   -+            |  Wait on specified     1      0" NEWLINE
	"  2  |   number of ticks,   | number     |   semaphore with a     2      1" NEWLINE
	"  3  |   then delay for a   |  of        |   timeout of random    3      2" NEWLINE
	"  4  |   random number of   |  eligible  |   ticks, then flash    4      3" NEWLINE
	"  5  |   ticks              |  tasks     |   LED for 20ms         4      4" NEWLINE
	"  6  |   \"\"                 |  shown on  |  Signal random sem,   1-5     5" NEWLINE
	"     |                      |  LED       |   flash LED for 20ms" NEWLINE
	"  7  |  Read S2 & S3        |  bargraph  |  Read S2 & S3, toggle LED     6" NEWLINE
	"  8  |  Dummy task         -+            |  Toggle LED when idling       7\n" NEWLINE
	"S1/'1': reset, S2/'2': display kernel status (toggle), S3/'3': change modes." NEWLINE
	"Each \'*\' represents 125 context switches, each \'.\' represents 125 idling" NEWLINE
	" function calls, each 80-char line 10,000. RS-232 @ 9600,N,8,1." NEWLINE NEWLINE; 
	
const char strMode1[] = " mode 1 (delays) ";
const char strMode2[] = " mode 2 (events) ";
const char strEnv1[]  = "\n\rTarget, Compiler, Ticks: ";
const char strEnv2[]  = STR_PROC_TYPE;

/* context-switching labels */
_OSLabel(TaskBlinkLED1)
_OSLabel(TaskDummy1)
_OSLabel(TaskRandom1)
_OSLabel(TaskRandom2)
_OSLabel(TaskRandom3)
_OSLabel(TaskRandom4)
_OSLabel(TaskRandom5)
_OSLabel(TaskStats1)
_OSLabel(TaskStats2)
_OSLabel(TaskStats3)
_OSLabel(TaskStats4)
_OSLabel(TaskStats5)
_OSLabel(TaskWaitAWhile1)
_OSLabel(TaskWaitAWhile2)


/************************************************************
****                                                     ****
**                                                         **
main()

This program illustrates a typical main() structure
for a Salvo application:  initialize Salvo, install the
system timer, create and start tasks, and then begin
multitasking.

A bunch of extra stuff is added in for display / diagnostic
purposes. Of special note is the calculation of time (in
cycles) between successive context switches. 

**                                                         **
****                                                     ****
************************************************************/
int main( void )
{
	InitTestHw();
	
	/* set PORT for output and	turn off all 	*/
	/*  PORT LEDs.								*/
	InitPORT();

	/* initialize Salvo.						*/
	OSInit();
	
	/* initialize RS-232 transmitter software. 	*/
	InitTx();		
	
	/* initialize timers and peripherals. 		*/
	Init();

	/* enable interrupts (UART is interrupt-	*/
	/*  driven.									*/
	OSEi(); 
		
	/* show splash screen						*/
	putstr(strSplash);

	/* setup the tasks with pseudo-random		*/
	/*  behavior and the key-reading and -acting*/
	/*  task ... 								 */
	for ( i = 1 ; i <= SIGNALING_TASKID ; i++ )
		OSCreateTask(TaskRandom, OSTCBP(i), prio[i-1]);
		
	OSCreateTask(TaskStats, TASK_STATS_P, 0);	
	OSCreateTask(TaskDummy, TASK_DUMMY_P, OSLOWEST_PRIO);	

	/* initialize all the semaphores to 0.		*/
	for ( i = 1 ; i <= OSEVENTS ; i++ )
		OSCreateSem(OSECBP(i), 0);
		
	/* initialize placeholders. */
	minCtxSw = 10000;
	maxCtxSw = 0;
	
	/* initialize vars used to keep track of	*/
	/*  context switches, etc.					*/
	j = DOTS_PER_CTXSW;
	k = DOTS_PER_CTXSW;
	flag = FLAG_SHOW_CTXSWS;
	
	/* enable TMR2 so that OSTimer() is called.	*/
	/*  didn't want to do this earlier because	*/
	/*  OSSched() wasn't being called and       */
	/*  putstr() takes > 100 system ticks to	*/
	/*  display splash screen.					*/
	EnableTMR2();
	
	
	/* satisfy PICC & PICC-18 callgraphs */
	#if defined(SYSA) || defined(SYSF)
	if (0)
		;
	#endif
		
	/* start multitasking.	*/
    for (;;)
    {
    	/* dispatch the current most-eligible	*/
    	/*  task.								*/
		#if !OSUSE_INLINE_OSSCHED
		OSSched();
		#else
		#include "sched.c"
		#endif
		
		/* complete the context-switching calc	*/
		/*  that was started in OSSchedHook().	*/
    	DisableTMR1();
		currTMR1 = TMR1;
		EnableTMR1();
		ctxSw = currTMR1 - prevTMR1;
		if ( ctxSw < 0 )
			ctxSw = -ctxSw;
			
		/* update min- and max- placeholders.	*/
		if ( maxCtxSw < ctxSw )
			maxCtxSw = ctxSw;
		if ( minCtxSw > ctxSw )
			minCtxSw = ctxSw;

		/* OSRpt() call depth is too deep to	*/
		/*  call from a task in a PIC ... also,	*/
		/*  disable calls to OSTimer() while 	*/
		/*  we're doing the dump.				*/
		if ( flag & FLAG_CALL_OSRPT ) {
			DisableTMR2();
			putstr(strEnv1);
			putstr(strEnv2);
			ShowMode();
			#if USE_PRINTF
			printf(".\n\rContext-switching times: "
			  "from %d to %d cycles", 
			  minCtxSw-TWEAK_CYCLE_COUNT, 
			  maxCtxSw-TWEAK_CYCLE_COUNT);
			OSRpt();
			#endif
			EnableTMR2();
			flag &= ~FLAG_CALL_OSRPT;
		}
		
		if ( flag & FLAG_MODE_CHANGED ) {
			flag &= ~FLAG_MODE_CHANGED;
			ShowMode();
		}
	}
}


/************************************************************
****                                                     ****
**                                                         **
OSIdlingHook()

Displays idle fn activity to the screen when required.

Also toggles LED, but only in mode 2.

**                                                         **
****                                                     ****
************************************************************/
void OSIdlingHook( void )
{
	if ( !--k && (flag & FLAG_SHOW_CTXSWS) ) {
		k = DOTS_PER_CTXSW;
		putch('.');
	}	
	
	if ( flag & FLAG_MODE )
		PORT ^= 0x80;
}


/************************************************************
****                                                     ****
**                                                         **
OSSchedDispatchHook()

In order to count the number of eligible tasks, we have
to do it inside the scheduler. 

**                                                         **
****                                                     ****
************************************************************/
void OSSchedDispatchHook ( void )
{  	
	OStypeTcbP tcbP;
	char i;
		
	/* count the current number of eligible	*/
	/*  tasks and display it via an LED 	*/
	/*  bargraph.							*/
	/* show them now, instead of after when	*/
	/*  when OSSched() runs, because odds	*/
	/*  of catching the eligible queue full	*/
	/*  are much better now than after the	*/
	/*  current task runs.					*/
	if ( !(flag & FLAG_MODE) ) {			
		i = 0;
		#if OSUSE_ARRAYS
		u.prioA = OSeligQP;
		if ( OSeligQP & 0x01 ) i++;
		if ( OSeligQP & 0x02 ) i++;
		if ( OSeligQP & 0x04 ) i++;
		if ( OSeligQP & 0x08 ) i++;
		if ( OSeligQP & 0x10 ) i++;
		if ( OSeligQP & 0x20 ) i++;
		if ( OSeligQP & 0x40 ) i++;
		if ( OSeligQP & 0x80 ) i++;
		#else
		tcbP = OSeligQP;
		for (;;)
			if ( tcbP != 0 ) {
				i++;
				tcbP = tcbP->nextTcbP;
			} 
			else
				break;
		#endif
		
		PORT = LEDs[i];
	}
	
	/* while we're at it, figure out how	*/
	/*  long the trip through the scheduler	*/
	/*  takes -- this is indicative of the	*/
	/*  time between context switches in	*/
	/*  this particular application.		*/
	/* Note that this measurement disregards*/
	/* the signaled event and delay queues.	*/
	DisableTMR1();
	prevTMR1 = TMR1;
	EnableTMR1();
}
		
	
/************************************************************
****                                                     ****
**                                                         **
OSSchedRtnHook()

For every 125 context switches, output a '.'. Note that we
do not count idle fn calls here -- just task context 
switches.

**                                                         **
****                                                     ****
************************************************************/
void OSSchedReturnHook( void )
{	
	if ( !--j && (flag & FLAG_SHOW_CTXSWS) ) {
		j = DOTS_PER_CTXSW;
		putch('*');
	}	
}
	

/************************************************************
****                                                     ****
**                                                         **
TaskDummy()

Doesn't do anything. Is used in mode 1 only so that up to
8 events can be eligible at one time, and can therefore
light up 8 LEDs on the bargraph. I.e. in mode 1 there is 
always 1 eligible task, and often more than 1, up to 8.

In mode 2 this task is stopped.

**                                                         **
****                                                     ****
************************************************************/
void TaskDummy( void )
{
	for (;;)
		OS_Yield(TaskDummy1);
}


/************************************************************
****                                                     ****
**                                                         **
TaskRandom()

In mode 1, the task(s) context-switches a semi-random number
of times, based on the upper bits of Timer 1. Then it delays
itself for a random time based on Timer 0.

In mode 2, tasks 1-5 wait on a particular semaphore. Once
the semaphore has been signalled, the LED corresponding to
the task is flashed for 20ms. Task 6 signals a random
semaphore based on Timer1, and then also flashes its LED.
The tasks wait with a pseudo-random timeout.

This is pretty funky.  Six different tasks use this task
structure -- taskIDs 1-5 are tasks that wait for a particular
semaphore, and taskID 6 signals (semi-randomly) a semaphore.

	Task 1 waits for semaphore   1
	Task 2 waits for semaphore   2 

⌨️ 快捷键说明

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