📄 main.c
字号:
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 + -