DSPRelated.com
Forums

General Q: Interrupt vs. Polling

Started by Borrall Wonnell October 12, 2006
Hi all,

I haven't been able to find much literature regarding this topic, so I
figured I'd post a question.
An external device writes data to two buffers (A and B) in my DSP.  The
basic idea is:

Write a block of data to Buffer A
Interrupt DSP (indicate Buffer A is full)
Write block of data to Buffer B
Interrupt DSP (indicate Buffer B is full)
Repeat

The DSP processes data in buffer A while data is being written to
buffer B (and vice versa).  I have assumed that the DSP can process the
data before the next interrupt occurs.

As I see it, I can approach this in a couple of ways:
1) DSP processes all data within the ISR
2) Set a flag in the ISR and poll for the flag in a main (always
running) routine.

I don't like option #2 because it seems inefficient (spinning in a loop
until the flag is set).  Then again, doing all the work within the ISR
appears to be against standard practices; most recommendations are to
keep the ISR short.

Are there any other options that I've failed to consider?  This seems
like it would be a common problem for DSP designers.

"Borrall Wonnell" <dave_bonnell@hotmail.com> wrote in 
news:1160659215.518716.308330@i42g2000cwa.googlegroups.com:

> I don't like option #2 because it seems inefficient (spinning in a loop > until the flag is set). Then again, doing all the work within the ISR > appears to be against standard practices; most recommendations are to > keep the ISR short. > > Are there any other options that I've failed to consider? This seems > like it would be a common problem for DSP designers. >
The rule of thumb is to keep the ISR's short. Of course there will always be exceptions, but I've seen many more problems when programmers have a propensity to hang around in a long ISR. The reason for this rule of thumb involves considerations along the lines of "what happens when I'm in an ISR and I get another interrupt request?" Depending upon how much of the work the compiler is going to do for you, there can be alot of bookeeping and cleaning up to do. Also, different platforms are going to have different approaches to interrupt levels. -- Scott Reverse name to reply
If you do not have much else to do in the foreground, you can:
1. set a flag during the ISR to indicate data is available to the foreground
2. poll the flag,
3. conditionally do the job,
4. then sleep/halt till next interrupt.

If you have other things which might need servicing, you can repeat steps 2
& 3 above until all flags are clear, then go to sleep.

It may help to make declare all the flags as bits within a shared word to
speed up the testing.

while (1)
{
    if (flag)
        handlejobs();    // examine the bits, clear them & do jobs

    sleepTillInt();      // snooze till any interrupt
}

The function "handlejobs()" is a dummy placeholder for the
actual "if-then-else" code for your tests.

Sometimes a simple boolean flag is inadequate, particularly if foreground
servicing might be delayed due to other jobs.

If you use a byte or word as a counter the ISR can increment the count &
then the FG code can decrement it (ensure indivisibility during the
decrement operation) for each service performed until the count reaches
zero.

This guarantees that the FG will do N FG services for N interrupt
occurrences.  Then you can go back to sleep.

Hope this helps.
Jim A.
Borrall Wonnell wrote:

> Hi all, > > I haven't been able to find much literature regarding this topic, so I > figured I'd post a question. > An external device writes data to two buffers (A and B) in my DSP. The > basic idea is: > > Write a block of data to Buffer A > Interrupt DSP (indicate Buffer A is full) > Write block of data to Buffer B > Interrupt DSP (indicate Buffer B is full) > Repeat > > The DSP processes data in buffer A while data is being written to > buffer B (and vice versa). I have assumed that the DSP can process the > data before the next interrupt occurs.
I sense a "NOT _EXPLICITLY_ stated" assumption. The data to both buffers comes from *SAME* source and has *IDENTICAL* processing. I see a GOTCHA Is data really available as a buffer length BURST? OR Is data available on a byte/word/"much shorter than buffer" basis? I've not dealt explicitly with first, but have with second. In that case you have *3* tasks at different priorities Low priority -- foreground task (eg display output) Medium priority -- process last buffer *HIGH* priority -- get next piece of data while still "valid" this may be a paraphrase of Jim Adamthwaite's response.
> > As I see it, I can approach this in a couple of ways: > 1) DSP processes all data within the ISR > 2) Set a flag in the ISR and poll for the flag in a main (always > running) routine. > > I don't like option #2 because it seems inefficient (spinning in a loop > until the flag is set). Then again, doing all the work within the ISR > appears to be against standard practices; most recommendations are to > keep the ISR short. > > Are there any other options that I've failed to consider? This seems > like it would be a common problem for DSP designers. >
Jim Adamthwaite wrote:
> If you do not have much else to do in the foreground, you can: > 1. set a flag during the ISR to indicate data is available to the foreground > 2. poll the flag, > 3. conditionally do the job, > 4. then sleep/halt till next interrupt.
That pretty much nails it...at least, what I would like to do. It's the part about sleeping until next interrupt that's the problem. I can sleep for a specified (predefined) period of time, but I'm not so sure that I can wake up when an interrupt occurs.
> If you use a byte or word as a counter the ISR can increment the count & > then the FG code can decrement it (ensure indivisibility during the > decrement operation) for each service performed until the count reaches > zero. > This guarantees that the FG will do N FG services for N interrupt > occurrences. Then you can go back to sleep. >
It does guarantee N FG services, but not the data that's being worked on...unfortunately, my buffers will be overwritten after the next interrupt. It sounds dangerous, but I'll be ok as long as the data is serviced in a timely fashion. Cheers, Dave
Borrall Wonnell wrote:
> Hi all, > > I haven't been able to find much literature regarding this topic, so I > figured I'd post a question. > An external device writes data to two buffers (A and B) in my DSP. The > basic idea is: > > Write a block of data to Buffer A > Interrupt DSP (indicate Buffer A is full) > Write block of data to Buffer B > Interrupt DSP (indicate Buffer B is full) > Repeat > > The DSP processes data in buffer A while data is being written to > buffer B (and vice versa). I have assumed that the DSP can process the > data before the next interrupt occurs. > > As I see it, I can approach this in a couple of ways: > 1) DSP processes all data within the ISR > 2) Set a flag in the ISR and poll for the flag in a main (always > running) routine. > > I don't like option #2 because it seems inefficient (spinning in a loop > until the flag is set). Then again, doing all the work within the ISR > appears to be against standard practices; most recommendations are to > keep the ISR short. > > Are there any other options that I've failed to consider? This seems > like it would be a common problem for DSP designers. >
This is a typical problem in real-time programming, and there are a lot of good answers to it. I'm taking the liberty of cross-posting this to comp.arch.embedded, in hopes that you'll get a recommendation for a book that has most of them. Here are the common ones, in increasing order of complexity: 1. If _all_ you are going to do is process just that data then you could put it in the ISR. But then things will break when you implement the next interrupt-driven thing. You can make your ISR's nestable, but this can cause problems. The first problem is that your hardware may not agree with you about what interrupts have greater priority. The second problem is that _everything_ becomes an ISR, which requires significantly more care in coding. A corollary to the second problem is that most embedded software engineers shy away from nested ISRs, sometimes violently. 2. Setting flags in various ISR's and processing them in the main loop, as mentioned elsewhere, works well. Unfortunately it constrains _all_ of the processing to be as short as the shortest allowable response time. This can be a pain if someone comes along later and puts a big floating-point calculation in that low-priority task, thereby blowing the important stuff out of the water -- so it'll work, but it's best to only use it on small applications and with a tight, disciplined team. 3. You could use a preemptive RTOS, set a semaphore in the ISR and pend on it in your main loop. This is way overkill if you're only doing one interrupt-driven thing, but a real life saver if you're doing a number of things that are interrupt-driven, or periodic, or whatever. The nicest thing about an RTOS is that it does a great job of decoupling the important stuff from the less important stuff -- to the extent that in a team environment you can hand the less important stuff to lesser engineers, with all associated implied advantages. RTOS's don't have to cost much -- the July or August issue of Embedded Systems Design magazine had an article on a particularly light-weight preemptive RTOS. Micro-C/OS-II (AKA mucus) is quite cost-effective, also -- and if you're using a recent TI processor the tool chain will come with an RTOS. -- Tim Wescott Wescott Design Services http://www.wescottdesign.com Posting from Google? See http://cfaj.freeshell.org/google/ "Applied Control Theory for Embedded Systems" came out in April. See details at http://www.wescottdesign.com/actfes/actfes.html
"Borrall Wonnell" <dave_bonnell@hotmail.com> wrote in 
news:1160671679.254674.247900@h48g2000cwc.googlegroups.com:

> That pretty much nails it...at least, what I would like to do. It's > the part about sleeping until next interrupt that's the problem. I can > sleep for a specified (predefined) period of time, but I'm not so sure > that I can wake up when an interrupt occurs. > >
You don't really need to sleep. You can stay awake, and just loop through a very small and efficient check for your flags. -- Scott Reverse name to reply
Borrall Wonnell wrote:

> Jim Adamthwaite wrote: > >>If you do not have much else to do in the foreground, you can: >>1. set a flag during the ISR to indicate data is available to the foreground >>2. poll the flag, >>3. conditionally do the job, >>4. then sleep/halt till next interrupt. > > > That pretty much nails it...at least, what I would like to do. It's > the part about sleeping until next interrupt that's the problem. I can > sleep for a specified (predefined) period of time, but I'm not so sure > that I can wake up when an interrupt occurs. >
This depends on your processor. Many processors intended for embedded use have a "sleep" instruction that puts the processor in a low-power mode until an interrupt occurs. Some even have a way to configure just _what_ goes to sleep. You'll have to study your documentation. -- Tim Wescott Wescott Design Services http://www.wescottdesign.com Posting from Google? See http://cfaj.freeshell.org/google/ "Applied Control Theory for Embedded Systems" came out in April. See details at http://www.wescottdesign.com/actfes/actfes.html
> I sense a "NOT _EXPLICITLY_ stated" assumption. > The data to both buffers comes from > *SAME* source and has > *IDENTICAL* processing.
SORRY! Data to the buffers comes from the same source, and indeed has identical processing. Even more fun, the buffers are actually contiguous DSP memory.
> I see a GOTCHA > Is data really available as a buffer length BURST? > OR > Is data available on a byte/word/"much shorter than buffer" basis? >
Technically, the data is available on a word basis, as a PIC writes to DSP memory word-by-word. An interrupt informs the DSP that data is valid. However, the DSP is much better at processing blocks of data rather than streaming it through (it isn't capable of handling per-word interrupts at the required data rate). I'm using interrupts to prevent PIC-DSP synchronization issues.
> I've not dealt explicitly with first, but have with second. > In that case you have *3* tasks at different priorities > > Low priority -- foreground task (eg display output) > Medium priority -- process last buffer > *HIGH* priority -- get next piece of data while still "valid" >
That is a pretty fair statement. From a time perspective, I'd say that processing the last buffer is just as important as getting the next data. If I can't process the data before the next buffer is valid, then I'll constantly be falling behind the data acquisition process. Cheers, Dave
Borrall Wonnell wrote:

>>I sense a "NOT _EXPLICITLY_ stated" assumption. >> The data to both buffers comes from >> *SAME* source and has >> *IDENTICAL* processing. > > > SORRY! Data to the buffers comes from the same source, and indeed has > identical processing. Even more fun, the buffers are actually > contiguous DSP memory. > > > >>I see a GOTCHA >> Is data really available as a buffer length BURST? >> OR >> Is data available on a byte/word/"much shorter than buffer" basis? >> > > > Technically, the data is available on a word basis, as a PIC writes to > DSP memory word-by-word. An interrupt informs the DSP that data is > valid. However, the DSP is much better at processing blocks of data > rather than streaming it through (it isn't capable of handling per-word > interrupts at the required data rate). I'm using interrupts to prevent > PIC-DSP synchronization issues. > > >>I've not dealt explicitly with first, but have with second. >>In that case you have *3* tasks at different priorities >> >>Low priority -- foreground task (eg display output) >>Medium priority -- process last buffer >>*HIGH* priority -- get next piece of data while still "valid" >> > > > That is a pretty fair statement. From a time perspective, I'd say that > processing the last buffer is just as important as getting the next > data. If I can't process the data before the next buffer is valid, > then I'll constantly be falling behind the data acquisition process. > > Cheers, > Dave >
I wasn't claiming to provide *SOLUTIONS* . I just wanted to flag possible problems.