?? vxw_pt5.html
字號:
<p><hr WIDTH="50%"><a NAME="5.9-F"></a><p>Q: What is the syntax of "taskSpawn" for spawning a method of anobject (C++) as a task.<p>A: I use the following code snippets to spawn a method as a task. Dont forgetthe '(int)this' for the first parameter.<pre>//start sampling data count and timestamptimeCodeGather = true;tid = taskSpawn("tTimestamp", 250, 0, 20000, (FUNCPTR)TimeStamp::addNewTimeStamp, (int)this, 0, 0, 0, 0, 0, 0, 0, 0, 0);void TimeStamp::stopTimeCodeGatheringTask(){//## begin TimeStamp::stopTimeCodeGatheringTask%1945920847.body preserve=yes int rd; char tmpbuf[20]; if (timeCodeGather) { //stop timecode gathering task taskDelete(tid);........</pre>From: Bob, Bob@dskti.com)<p><hr WIDTH="50%"><a NAME="5.9-G"></a><p>Q: How can I detect a stack overflow?<p>A: In the past I used the next code (typically for x86 targets):<pre>int switchHandler(WIND_TCB *pOldTcb, WIND_TCB *pNewTcb){ if ((pOldTcb->regs.esp < (ULONG)pOldTcb->pStackLimit) || (!(pOldTcb->options & VX_NO_STACK_FILL) && ((int)*(int *)(pOldTcb->pStackLimit) != 0xeeeeeeee))) { logMsg("Stack overflow task 0x%08x\n", (int)pOldTcb,0,0,0,0,0); taskSuspend((int)pOldTcb); /* __asm__("int $12"); */ } return 0;}int start_application(void){ /* Enable kind of dynamic stack checking */ if (taskSwitchHookAdd(switchHandler) == ERROR) { printf("taskSwitchHookAdd error\n"); return ERROR; } ...}</pre>(From: Gerald van Kampen, kam@oce.nl)<p><hr WIDTH="50%"><a NAME="5.9-H"></a><p>Q: I want to block a task until all children are in a certain state(initialised, finished, etc.).<p>A: This can be done using semaphores:<blockquote><pre>/* * Global semaphore used by each terminating child CSP task. */SEM_ID childFinished;/* * A child task. */void child (void){ /* Normal child like activities. */ semGive (childFinished);}#define NUM_CHILDREN 5/* * Parent task. */void parent (void){ int childCount = 0; /* * Use a FIFO if you are more interested in speed than the order that * tasks will be blocked in. */ if ((childFinished = semCCreate (SEM_Q_FIFO, NUM_CHILDREN)) == NULL) { /* We're not in the mood for creating children :-( */ return; } /* Spawn children, the fun part ;-) */ do { /* Wait for all the children to complete their chores */ semTake (childFinished, WAIT_FOREVER); } while (++childCount < NUM_CHILDREN); /* Tidy up after children (usual parental type stuff) */ semDelete (childFinshed);}</pre>(From: Alex Goodyear, spamless.agood@jet.uk)</blockquote><p><hr WIDTH="60%"><p><h3><a NAME="5.10"><center>5.10 Time measurement</center></a></h3><a NAME="5.10-A"></a>Q: I would like to know how to measure the system time at a specificmoment, then at another moment, only a few milliseconds later, todetermine elapsed time.<br>I have tried clock_gettime(), but this is no good. I have checked theclock resolution and it is at 60 ticks per second.<p>A: The following was written by Fred Roeber (froeber@bbn.com) in thenewsgroup:<p>The easiest/best way to measure detailed elapsed time is to useany "timestamp" driver that may be supplied as part of your board'sBSP. The timestamp driver is a generic name for a high resolutiontiming factility that is intended for WindView use but can also beused by user applications. The documentation for creating/using thetimestamp facility is in Appendix G of the WindView manual and thefunctions are defined in h/drv/timer/timerDev.h (see sysTimestamp...).<p>Many BSPs come with timestamp driver support even if you don't buyWindView. You can add the configuration option INCLUDE_TIMESTAMP tobuild it into your system. You can then call sysTimestampEnable tostart it up and sysTimestampLock to read detailed time values. Youcan call sysTimestampPeriod to find out how often the timer rollsover and sysTimestampFreq to see the rate it ticks at (which is oftenfast enough to provide microsecond resolution).<p>The reason I prefer this approach to cranking up the clockrate is that you typically get much higher resolution values withoutbogging down the system with all the overhead of frequent timerinterrupts.<p>As with most things in VxWorks, caveats are needed in applying a genericfacility to specific boards. First, not all boards have timestampdriver support. Second, on those that do, the timestamp sometimeshas a pretty small period (it rolls over frequently). For instance,on the PPC platform, the "standard" timestamp driver derives thetimestamps from the decrementer timer which is also used for the systemclock. This means the time value rolls over at the rate the systemclock rate; making it pretty useless for measuring things with a longduration.<p>There is an alternative timer for some PPC boards that uses the Z8536chip. The other day, we needed to time startup code on our Radstone PPCboard and I found that with a little work the PPC timestamp functionsfit the bill nicely. The ppcZ8536Timer.c can be rewritten such that itonly provides auxilliary clock and timestamp support (with no systemclock support - that comes from ppcDecTimer.c). By using the 16 bittimers 1 and 2 in "linked" mode it was possible to get a nice 32 bittimer that rolled over every 20 minutes in our case. We left timer 3 onthe chip for auxilliary clock support. The original timestampfunctionality in the driver was, unfortunately, fairly well broken butnot unsalvageable. Just trying to point out that in some (all?) cases youhave to be careful when using VxWorks drivers.<p>Caveats aside, people should really consider the timestamp routines.They can often provide good timing insight with minimum trouble. Fred<p><hr WIDTH="50%"><a NAME="5.10-B"></a><p>Q: When I create a timer function my program crashes after the timespecified instead of executing the function I specified. What is happening?<p>A: One thing to watch out for (it got me) is that your handler for the timeris executed IN THE CONTEXT OF THE TASK THAT CREATED IT. If the timer wascreated by some startup task which has since died and gone away, then thiswill quite likely crash your system the first time that the timer callbackfunction is activated!<br>(From: Will Fookes, will@noSpam.wfookes.co.uk)<p><hr WIDTH="50%"><a NAME="5.10-C"></a><p>Q: How do I determine the number of ticks remaining in a watchdog timer?<p>A: I got this code from my FAE a few years ago. You will have tosearch for what you need to include for the state #defines andthe OBJ_VERIFY() macro.<pre>typedef struct{ int Ticks; int State; /* OUT_OF_Q, IN_Q, DEAD */} WD_INFO, *pWD_INFO;STATUS wdGetInfo ( WDOG_ID wdId, pWD_INFO wdInf ){ FAST int lock = 0; int ticks = 0; int state = 0; /* LOCK INTERRUPTS */ lock = intLock (); /*Verify watchdog ID */ if (OBJ_VERIFY (wdId, wdClassId) != OK) { /* UNLOCK INTERRUPTS */ intUNLOCK (lock); return ERROR; } /* record state */ state = (int) wdId->status; /*If not in queue then ticks are zero*/ if (state == WDOG_IN_Q) { ticks = Q_KEY (&tickQHead, &wdId->tickNode, 1); //ticks = 0; } else { ticks = 0; } /* UNLOCK INTERRUPTS */ intUNLOCK (lock); /* fill structure */ wdInf->Ticks = ticks; wdInf->State = state & 0x3; return OK;}</pre><br>(From: Bruce, intmainNOinSPAM@yahoo.com.invalid)<p><hr WIDTH="50%"><a NAME="5.10-D"></a><p>Q: Errors in the time modules.<p>A: taskDelay(-1) shows another bug in the vxWorks timer/tick code.It has the (side) effect of setting vxTicks to zero.This corrupts the localtime (and probably other things).<br>In fact taskDelay(x) will have the same effect if vxTicks + x >=0x100000000.<br>If the system clock rate is 100Hz this happens after about 500 days (becausevxTicks wraps). At faster clock rates it will happen sooner.Anyone trying for several years uptime?<p>Oh there is an undocumented upper limit on the clock rate. At rates above4294 select() will fail to convert its 'usec' time into the correct number ofticks.<br>From: David Laight <dsl@tadpole.co.uk><p><hr WIDTH="50%"><a NAME="5.10-E"></a><p>Q: How can I create a repeat with a small delay without using busy-waiting?<p>A: The reason for not using busy-waitingis to allow other tasks to make use of the spare CPU cycles. But you mustremember that context switching is quite a slow operation. Two task-swapsevery 20usec for 1ms.means 100 task swaps per millisecond which worksout equivalent to a task-switching tick rate of 100 kHz. Which wouldundoubtedly bog down the CPU pretty badly, and so not produce the desiredsaving, to put it mildly...<br>The 'correct' way to achieve this goal is to use an interrupt driven offa hardware timer. Do it something like this:<ul><li>In the driver function:<ol><li>Set timer: delay = 20 usec, repeated count-downs, trigger an interrupteach time it hits zero.</li><li>Wait for the interrupt to finish by sleeping on a previously-allocatedbinary semaphore.</li></ol></li><li>In the interrupt that is attached to the hardware timer<ol><li>Do your business.</li><li>Decrement the count.</li><li>If there's more business to do (count non-zero) reset the timer tointerrupt in another 20 usec, else halt the timer and semGive the semaphorethat the foreground is waiting on.</li></ol></li></ul>This solution then has the advantage that a) the 20usec. intervals areaccurately timed by hardware rather than approximated by delay loopsthat will themselves be subject to interrupts and b) any spare CPU cyclesare given to another task, but the task that has called into the driver onlygets put to sleep once and woken up once.<br>Note that as described above, there will be a wasted 20usec delay at thestart while waiting for the timer to first count down. You could perhaps dothe first time from the foreground driver code at the same time asyou set the timer going. Perfection is left as an exercise for the reader :-)<br>(From: Dave Korn)<p><hr WIDTH="50%"><a NAME="5.10-F"></a><p>Q: How can I monitor the processor-load?<p>A: The code we use for CPU monitoring is <A HREF="cpuLoad.c">here</A> - I've probably missed the odd definition from earlier in the file but I think they should be pretty self-explanatory. It creates a task at priority 255 = idle task level, which eats CPU and times itself. The routine <code>getCpu()</code> returns a doubewhich is CPU loading as a %. You have to run the initialise function at ahigh priority so it gets its autocalibration done properly.<br>(From: Andrew Johnson, anj@aps.anl.gov)<p><a NAME="5.10-F2"></a>Another example.<br>Based on a discussion about this subject that I read here a few weeks ago, Iwrote <A href="CPUIdleMonitor.c">this</A> idle time monitor that I have been testing. It seems to workvery well.<br>You can add it to you build, then start it with nothing running<pre>-> startCPUIdleMonitor</pre>then spawn the task that prints the CPU Idle Time<pre>-> period 10, getCPUIdlefloat</pre><br>You will need to adjust the ZERO_LOAD_IDLE_COUNTER for your CPU. For my50Mhz 860T it is around 377000<br>From: RonnoBonno, RHNAssociates@yahoo.com)<p><hr WIDTH="50%"><a NAME="5.10-G"></a><p>Q: Can you give an example on how to use timers?<p>A: Take a look at <A HREF="timerDemo.c">this</A> code. It should work withoutmodifications.<br>From: Michel Hendriks, m.hendriksNOSPAM@pijnenburg.nl)<p><hr WIDTH="50%"><a NAME="5.10-H"></a><p>Q: I noticed a rollover in the SNMP variable sysUpTime after around 2,5 days.<p>A: This can be fixed by editing snmpSystem.h which is supplied as sourcewith WindNet, and calculating sysUpTime yourself rather than relying onthe value from m2SysGroupInfoGet().<br>(From: Will Fookes, will@noSpam.wfookes.co.uk)<p><hr WIDTH="50%"><a NAME="5.10-I"></a><p>Q: When a timer expires, the connected routine will execute in whichtask context ?<p>A: The POSIX timer will execute in task context, same task that created thetimer using POSIX signal mechanism, and you can taskLock() from within.<br>In contrast Wind WatchDog (wdLib) will do a similar service, but morelight-weight, and will call the handler routing in interrupt context.<br>(From: Leonid Rosenboim)<p><hr WIDTH="60%"><p><h3><a NAME="5.11"><center>5.11 Wind Web Server related items</center></a></h3><a NAME="5.11-A"></a>
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -