![]() |
Re: Glitches Eliminated using Interrupt Context Saving, BUT ...
[This is in reply to WPILib and interrupt latency issue re: GTS sensor]
One way of simulating multiple levels of interrupt priority is to utilize multiple ISRs tied to through the same interrupt vector. static unsigned char slow_isr = 0; static unsigned char slow_isr_0 = 0; static unsigned char slow_isr_1 = 0; static unsigned char slow_isr_2 = 0; : static unsigned char slow_isr_n = 0; #pragma code #pragma interruptlow InterruptHandlerLow save=PROD void InterruptHandlerLow () { static unsigned char fast_isr; // check "fast" interrupts here, like gts or other // h/w time critical interrupts // "fast" interrupts only use trusted interrupt drivers // if "fast" interrupt serviced, set fast_isr flag // these drivers will be from a trusted source, such // as the default system drivers provided by the library. <appropriate code for "fast" devices goes here> // if we serviced a "fast" interrupt, return now. // if there is another interrupt pending, we'll come right back. if (fast_isr != 0) return; // No fast interrupts processed, are there any "slow" ones pending? // Now on to "slow" interrupt services // determine if or which isr flags are set // associated with "slow" type interrupt services, // such as the system clock timer and capture // them for the slow_isr routine's use/query. <appropriate code to check, accumulate flag and clr IF> // if slow isr routine is already running, then we're done - exit if (slow_isr != 0) return; // Turn interrupts back on and call // the "Slow" service routine. Hardware // dispatch of the h/w interrupt has occurred // so we won't get immediately vectored again // until the next interrupt. while (0==0) { slow_isr = 0xFF; // show we're running slow isr INTCONbits.GIEL = 1; // turn interrupts back on InterruptHandlerLow_Slow(); // process bottom half of slow isr INTCONbits.GIEL = 0; if (slow_isr_0 != 0) continue; if (slow_isr_1 != 0) continue; : slow_isr = 0; break; } return; } #pragma code #pragma interruptlow InterruptHandlerLow save=PROD, TABLAT, TBLPTR, section(".tmpdata"), section=("MATH_DATA") void InterruptHandlerLow_Slow() { while (0==0) // The only routines that can run while this // routine is executing is high priority interrupt // service routine and the low priority (fast) drivers. if (slow_isr_0 != 0) { slow_isr_0 = 0; <process interrupt> } if (slow_isr_1 != 0) { slow_isr_1 = 0; <process interrupt> } : // Ok, at this point we believe we've processed all the // pending slow type interrupts, time to leave! INTCONbits.GIEL = 0; // Check one more time with interrupts off, // to see if another slow device interrupted // requested service while or after we processed the // current batch... if (slow_isr_0 != 0) continue; if (slow_isr_1 != 0) continue; : // nope, no new slow isr requests pending... // Turn interrupts back on, this is a gamble in that interrupts // requesting slow isr service can happen now, but the problem is // restoring context just takes too long. We'll check again after // context is restored. INTCONbits.GIEL = 1; return; } } In this way interrupts requiring low interrupt latency are handled pretty much right away, even the save=PROD may not be needed. If the device interrupt is to be service by a user written routine, then it's servicing is deferred to the slow isr section. A small amount of application programmers interface needs to be documented for slow isr driver writers since the h/w bits such as the interrupt flag have already been cleared for it during fast device processing, but it will work and prevent the additional save context required from effecting latency. Essentially with this method you have two levels of IPL with minimal latency for the class of "fast" devices requiring minimal latency. Bud |
Re: Glitches Eliminated using Interrupt Context Saving, BUT ...
Hmm - recursive logic - you are turning interrupts on as you process the 'slow' ISR, and deferring the return-from-interrupt at the end of an original invocation of InterruptHandlerLow (). Very hairy indeed ... if your sample is from running code, I bet you debugged it using an ICE (in-circuit emulator)!
Could you not accomplish the same effect without the recursion, by simply calling 'slow' ISR routines using your technique of the separate _Slow() routine which has it's own #pragma for saving additional data sections? And how about checking for and servicing multiple interrupt sources during the same interrupt? Responding to Brad, I finally 'got' what he was waying - that he started this timer when the pulse began. I didn't implement that way because I was always planning to measure multiple pulse sources and didn't want to devote a separate timer to each. I see that this year's gear tooth sensors are the same as last year (well no, I haven't ready the documentation on them yet!!). Although our team is going with quadrature encoders, I see no reason why the pulse-measurement approach should be abandoned by everyone. |
Re: Glitches Eliminated using Interrupt Context Saving, BUT ...
As far as "custom" circuts go BaneBots this year is offering both encoders and an Encoder Divider Kit ($10.00), encoders are a little more. This would get you one signal line for forward, backward and another for a string pulses that which can be straight or divided. Link to Bane's First page http://www.banebots.com/c/FIRST
Good luck to all Biff |
Re: Glitches Eliminated using Interrupt Context Saving, BUT ...
Quote:
|
Re: Glitches Eliminated using Interrupt Context Saving, BUT ...
The sample code is only slightly recursive and only then to allow the fast isr to be called.
Q. Could you not accomplish the same effect without the recursion, by simply calling 'slow' ISR routines using your technique of the separate _Slow() routine which has it's own #pragma for saving additional data sections? No. But I'll leave you to ponder why. Think latency. If you want more info, ask and I'll explain. Q. And how about checking for and servicing multiple interrupt sources during the same interrupt? Actually the code is ambiguous as to whether only one interrupt is processed or multiple. With the slow isr, all currently pending interrupts need to be serviced or they will be lost otherwise since they have already been dispatched (cleared) in hardware. In the fast isr it comes down to how many times overlapping interrupts are present with the time required to check for them vs the exit/entrance time into the isr. If overlapping interrupts only occur in 1:n cases where n is fairly large, then you are chewing up processor bandwidth for no gain. As far as being hairy? Nah, after 3 decades of dealing with hardware this ain't hairy. Hairy is a 256bit ultrawide instruction word, 2 128bit input pipes, 1 256bit output pipe, 8-12 simultaneous operations, multi-delay branching all running at <10ns. Course that technology was 20 years ago now. Grins, Bud |
Re: Glitches Eliminated using Interrupt Context Saving, BUT ...
Thanks Alan, I've read the sensor manual now. And noted that the Gyro and Accelerometer are to be mailed to us.
Does anyone think that any rule prevents use of last year's gear tooth sensors in this year's robot?? Bud - yes, your routine is quite clever and provides a two-priority interrupt priority scheme, that is not quite as recursive as I had thought on first glance, and that would reduce jitter caused by ISRs that consume larger quantities of instruction cycles (by placing less-frequently-called ISRs containing large code-blocks inside your slow_isr loop). The result could be more accurate pulse-length measurements - the topic of this thread. Thanks for sharing the code with us. |
Re: Glitches Eliminated using Interrupt Context Saving, BUT ...
Quote:
|
Re: Glitches Eliminated using Interrupt Context Saving, BUT ...
To be even more clever...
Now that you have code executing asynchronously from user code driven by interrupts it is an easy matter to also add a general event handler, to say run something every 10ms or to run a routine every 10th time a sonar sensor completes a measurement... You can still starve off the real user code that is waiting for all this processing to complete, but it does make some things like collision detection a lot easier without having to poll and without further impacting interrupt latency. And besides, by the time slow isr is run you've already paid the penalty for saving off the .tmpdata and other sections. I happen to have an asynchronous event handler written and bench tested... Bud |
| All times are GMT -5. The time now is 20:45. |
Powered by vBulletin® Version 3.6.4
Copyright ©2000 - 2017, Jelsoft Enterprises Ltd.
Copyright © Chief Delphi