DSPRelated.com
Forums

Genreral Question for DSP BlackFin

Started by raul June 30, 2005
Jon Harris wrote:

  ...

> So is the background task (i.e. the code that was interrupted) continually > polling for this flag to be set? If it has other low-priority work to do, might > that prevent it from seeing the flag and starting on the important processing? > Or maybe you are assuming some type of RTOS/scheduler? I'm thinking about the > case when the sample interrupt processing takes e.g. >90% of the sample period > to complete and must be finished before the next sample arrives. > > It's because of issues like these that I like to just do the work in the ISR. > The idea of setting a flag to tell some other process to start doing something > important when you could just start doing it immediately always seemed a bit > awkward to me. But I do understand that it has its places, especially with > multi-threaded scenarios, and in fact I use that method frequently in my > embedded control code, but not with the DSPs.
When I can afford to be blind the whole time, I like the interrupt routine to do the whole task too, subject to the reentry issue I raised earlier. If there's also a very simple and short interrupt service, I allow the long routine to itself be interrupted. Nested interrupts frighten some programmers, but I never had a problem with them. In the simplest of scenarios, the whole program is a single interrupt routine. Some periodic element -- an ADC or even a timer -- issues an interrupt, then each task executes in sequence, then the processor returns and idles, waiting for the next interrupt. When the scheduling allows it, that's about as simple as it can get. Jerry -- Engineering is the art of making what you want from things you can get. �����������������������������������������������������������������������
"Jerry Avins" <jya@ieee.org> wrote in message 
news:JsadnVq06OWBIFnfRVn-1A@rcn.net...
> Jon Harris wrote: > >> So is the background task (i.e. the code that was interrupted) continually >> polling for this flag to be set? If it has other low-priority work to do, >> might that prevent it from seeing the flag and starting on the important >> processing? Or maybe you are assuming some type of RTOS/scheduler? I'm >> thinking about the case when the sample interrupt processing takes e.g. >90% >> of the sample period to complete and must be finished before the next sample >> arrives. >> >> It's because of issues like these that I like to just do the work in the ISR. >> The idea of setting a flag to tell some other process to start doing >> something important when you could just start doing it immediately always >> seemed a bit awkward to me. But I do understand that it has its places, >> especially with multi-threaded scenarios, and in fact I use that method >> frequently in my embedded control code, but not with the DSPs. > > When I can afford to be blind the whole time, I like the interrupt routine to > do the whole task too, subject to the reentry issue I raised earlier.
Could you expound on the reentry issue? I didn't get it the first time around.
> In the simplest of scenarios, the whole program is a single interrupt routine. > Some periodic element -- an ADC or even a timer -- issues an interrupt, then > each task executes in sequence, then the processor returns and idles, waiting > for the next interrupt. When the scheduling allows it, that's about as simple > as it can get.
Replace the idle with some background housekeeping tasks in a loop, and that's pretty much what I have--very simple, clean and efficient.
"Jon Harris" <jon99_harris7@hotmail.com> wrote in
news:2w2xe.16295$gm6.6919@trnddc05: 

> "Al Clark" <dsp@danvillesignal.com> wrote in message > news:Xns968585E20ED8Faclarkdanvillesignal@66.133.129.71... >> "Jon Harris" <jon99_harris7@hotmail.com> wrote in >> news:hOVwe.8093$Iv6.1067@trnddc03: >> >>> Agree. >>> >>>> An alternative way of designing these things that gives you more >>>> flexibility for growth is to minimize the amount of stuff in the >>>> ISR and set a flag (or a semiphore, if you're using an RTOS). Then >>>> your task loop (or your task's loop) can execute the rest of the >>>> code as soon as the flag indicates "true". >>>> >>>> I have coded both ways. The "big ISR" method works well if you >>>> have a very well defined job for the processor and the processor >>>> doesn't need more than one or two threads. If the processor needs >>>> to do a bunch of different stuff, _particularly_ if you have >>>> asynchronous time-critical jobs to perform, then the "small ISR" >>>> method avoids a great deal of headaches. >>> >> >> I agree with Tim's approach. I almost always write short ISRs and use >> a flag variable. >> >> Most of the time, I don't use nested interrupts. This keeps the stuff >> I have to save very small since interrupts can't interrupt each >> other. I also use assembly language extensively so the overhead is >> extremely small for an ISR. In the SHARC case, it means switching to >> secondary registers and pushing/popping STS, maybe turning off SIMD >> mode and RTI, basically 4 instructions. > > If it's an external interrupt, then STS gets pushed/popped > automatically. And you can use the MMASK register to automatically > switch register sets and clear SIMD. Then it gets really effeicient! >
External IRQs & Timer Expired do not need the PUSH/POP STS instructions but SPORTs do. I have never paid attention to MMASK. This is really cool! I guess I don't really need to disable SIMD during an ISR. I think its time to read the manuals cover to cover again.
>> Short ISRs also are important when nesting is not used since another >> pending interrupt is not going to be serviced until the current one >> is done. >> >> The advantage to this method is that the device driver code is >> largely independent of the signal processing and other application >> code. I think this makes everything a little more portable. >> >> I understand Jon's point, but in most cases the overhead for the flag >> method is very minimal. This means that an application with a single >> critical task is going to execute about the same with either method. > > So is the background task (i.e. the code that was interrupted) > continually polling for this flag to be set? If it has other > low-priority work to do, might that prevent it from seeing the flag > and starting on the important processing? Or maybe you are assuming > some type of RTOS/scheduler? I'm thinking about the case when the > sample interrupt processing takes e.g. >90% of the sample period to > complete and must be finished before the next sample arrives.
I sometimes use a crude scheduler for lower priority functions. I understand that if all your program does is wait for a sample, execute an algorithm and send it somewhere that you can do everything in the ISR. I have certainly written programs like this as well, but in recent years, I have moved away from this approach since the benefits are at best small for the cases where the big simple ISR works well. Most of my applications need to do general purpose stuff as well. In our case, we have multiple dsp boards and I/O modules and more being created all the time. The flag method makes it easier to write a basic shell structure with various I/O drivers. This makes adding the signal processing section fairly straightforward since the other stuff is largely independent and already working.
> > It's because of issues like these that I like to just do the work in > the ISR. The idea of setting a flag to tell some other process to > start doing something important when you could just start doing it > immediately always seemed a bit awkward to me. But I do understand > that it has its places, especially with multi-threaded scenarios, and > in fact I use that method frequently in my embedded control code, but > not with the DSPs. >
-- Al Clark Danville Signal Processing, Inc. -------------------------------------------------------------------- Purveyors of Fine DSP Hardware and other Cool Stuff Available at http://www.danvillesignal.com
Jerry Avins <jya@ieee.org> wrote in news:JsadnVq06OWBIFnfRVn-1A@rcn.net:

> Jon Harris wrote: > > ... > >> So is the background task (i.e. the code that was interrupted) >> continually polling for this flag to be set? If it has other >> low-priority work to do, might that prevent it from seeing the flag >> and starting on the important processing? Or maybe you are assuming >> some type of RTOS/scheduler? I'm thinking about the case when the >> sample interrupt processing takes e.g. >90% of the sample period to >> complete and must be finished before the next sample arrives. >> >> It's because of issues like these that I like to just do the work in >> the ISR. The idea of setting a flag to tell some other process to >> start doing something important when you could just start doing it >> immediately always seemed a bit awkward to me. But I do understand >> that it has its places, especially with multi-threaded scenarios, and >> in fact I use that method frequently in my embedded control code, but >> not with the DSPs. > > When I can afford to be blind the whole time, I like the interrupt > routine to do the whole task too, subject to the reentry issue I > raised earlier. If there's also a very simple and short interrupt > service, I allow the long routine to itself be interrupted. Nested > interrupts frighten some programmers, but I never had a problem with > them.
I usually like to avoid nested interrupts with ADI DSPs. These DSPs have an alternate set of registers and pointers (DAGs) that can be quickly switched. If you use the alternate registers and DAGs almost nothing has to be preserved when entering an ISR (assuming no nesting). The only issue with nesting is that the higher priority ISRs have to save all the registers that are used by lower priority ISRs. Its not scary, its just less efficient and more stuff to pay attention to. One of my complaints with C compilers is that they tend to assume that something might be used and therefore they tend to preserve way too many resources before the ISR does any real work.
> > In the simplest of scenarios, the whole program is a single interrupt > routine. Some periodic element -- an ADC or even a timer -- issues an > interrupt, then each task executes in sequence, then the processor > returns and idles, waiting for the next interrupt. When the scheduling > allows it, that's about as simple as it can get. > > Jerry
-- Al Clark Danville Signal Processing, Inc. -------------------------------------------------------------------- Purveyors of Fine DSP Hardware and other Cool Stuff Available at http://www.danvillesignal.com
Jon,

Could you send me an email sometime? 

-- 
Al Clark
Danville Signal Processing, Inc.
--------------------------------------------------------------------
Purveyors of Fine DSP Hardware and other Cool Stuff
Available at http://www.danvillesignal.com
Jon Harris wrote:

   ...

>>When I can afford to be blind the whole time, I like the interrupt routine to >>do the whole task too, subject to the reentry issue I raised earlier. > > > Could you expound on the reentry issue? I didn't get it the first time around.
I should have written "reentrancy". A routine is reentrant if it can be suspended, started over from the beginning, and then finish the original action properly. The simplest example I can think of off hand is a double-precision arithmetic routine that needs temporary storage of intermediate values. Barring the use of registers, RAM locations written into the code for the storage will probably allow the fastest execution. If the computation is interrupted, and the interrupt routine uses the same arithmetic, those locations will be clobbered. There's too much code like that in math libraries to safely ignore the issue. The cure is to duplicate the code with new temporary storage addresses for use in the interrupt code (ugly!), rewrite the code to use the stack (maybe slow) or registers (if available; more to push when the interrupt hits). Good libraries address the issue. If a library writer answers "Yes" when I ask if the code is reentrant, I trust her/him. If they ask, "What's that?", I worry.
>>In the simplest of scenarios, the whole program is a single interrupt routine. >>Some periodic element -- an ADC or even a timer -- issues an interrupt, then >>each task executes in sequence, then the processor returns and idles, waiting >>for the next interrupt. When the scheduling allows it, that's about as simple >>as it can get. > > > Replace the idle with some background housekeeping tasks in a loop, and that's > pretty much what I have--very simple, clean and efficient.
Yes. You can go a step further, too. In one project, I had a bunch of interrupts connected but disabled. At the beginning of each loop, the interrupt flag register was read to see which tasks needed service, and their entry points were loaded into the dispatch table in priority order, subject to time availability. The bulk of the service loop was executed via the dynamic dispatch table, while the fixed part of the loop covered only housekeeping. If the shoe fits, .... Jerry -- Engineering is the art of making what you want from things you can get. &#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;
Al Clark wrote:

   ...

> I usually like to avoid nested interrupts with ADI DSPs. These DSPs have > an alternate set of registers and pointers (DAGs) that can be quickly > switched. If you use the alternate registers and DAGs almost nothing has > to be preserved when entering an ISR (assuming no nesting). The only > issue with nesting is that the higher priority ISRs have to save all the > registers that are used by lower priority ISRs. Its not scary, its just > less efficient and more stuff to pay attention to.
I get you. I learned that with a Z-80.
> One of my complaints with C compilers is that they tend to assume that > something might be used and therefore they tend to preserve way too many > resources before the ISR does any real work.
Could a compiler that makes modules assume anything else? You can determine the resources in use only by analyzing all the code. ... Jerry -- Engineering is the art of making what you want from things you can get. &#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;
Jerry Avins <jya@ieee.org> wrote in news:-Pqdnaq_lOTuyFjfRVn-1Q@rcn.net:

> Al Clark wrote: > > ... > >> I usually like to avoid nested interrupts with ADI DSPs. These DSPs >> have an alternate set of registers and pointers (DAGs) that can be >> quickly switched. If you use the alternate registers and DAGs almost >> nothing has to be preserved when entering an ISR (assuming no >> nesting). The only issue with nesting is that the higher priority >> ISRs have to save all the registers that are used by lower priority >> ISRs. Its not scary, its just less efficient and more stuff to pay >> attention to. > > I get you. I learned that with a Z-80. > >> One of my complaints with C compilers is that they tend to assume >> that something might be used and therefore they tend to preserve way >> too many resources before the ISR does any real work. > > Could a compiler that makes modules assume anything else? You can > determine the resources in use only by analyzing all the code. > > .
If nesting is not allowed, I think it could be very simple for the compiler assuming secondary registers are in play. I agree that it gets ugly for the compiler in the nested case. ..
> > Jerry
-- Al Clark Danville Signal Processing, Inc. -------------------------------------------------------------------- Purveyors of Fine DSP Hardware and other Cool Stuff Available at http://www.danvillesignal.com
"Jerry Avins" <jya@ieee.org> wrote in message 
news:-Pqdnaq_lOTuyFjfRVn-1Q@rcn.net...
> Al Clark wrote: > > ... > >> I usually like to avoid nested interrupts with ADI DSPs. These DSPs have an >> alternate set of registers and pointers (DAGs) that can be quickly switched. >> If you use the alternate registers and DAGs almost nothing has to be >> preserved when entering an ISR (assuming no nesting). The only issue with >> nesting is that the higher priority ISRs have to save all the registers that >> are used by lower priority ISRs. Its not scary, its just less efficient and >> more stuff to pay attention to. > > I get you. I learned that with a Z-80. > >> One of my complaints with C compilers is that they tend to assume that >> something might be used and therefore they tend to preserve way too many >> resources before the ISR does any real work. > > Could a compiler that makes modules assume anything else? You can determine > the resources in use only by analyzing all the code.
Yeah, the compiler has to error on the side of saving too much. Save too much and you have some (hopefully minor) inefficiencies. Save too little, and you have a obscure, intermittent, hard to find bug! -- Jon Harris SPAM blocker in place: Remove 99 (but leave 7) to reply
"Jerry Avins" <jya@ieee.org> wrote in message 
news:qeOdnVBsgbyiyVjfRVn-tQ@rcn.net...
> Jon Harris wrote: > >> Could you expound on the reentry issue? I didn't get it the first time >> around. > > I should have written "reentrancy". A routine is reentrant if it can be > suspended, started over from the beginning, and then finish the original > action properly. The simplest example I can think of off hand is a > double-precision arithmetic routine that needs temporary storage of > intermediate values. Barring the use of registers, RAM locations written into > the code for the storage will probably allow the fastest execution. If the > computation is interrupted, and the interrupt routine uses the same > arithmetic, those locations will be clobbered.
OK, I see. The code I've seen uses the stack for temporary variables, so that nicely solves the problem of RAM locations getting clobbered.
> There's too much code like that in math libraries to safely ignore the issue. > The cure is to duplicate the code with new temporary storage addresses for use > in the interrupt code (ugly!), rewrite the code to use the stack (maybe slow) > or registers (if available; more to push when the interrupt hits). Good > libraries address the issue. If a library writer answers "Yes" when I ask if > the code is reentrant, I trust her/him. If they ask, "What's that?", I worry.
Fortunately, I have been dealing with fairly mature professionally-created math libraries, so haven't run into this. C code tends to work this way be default (a functions local variables are stored on the stack). With C, you'd have to go out of your way to screw it up (use global variables). I don't know about other languages. And in my environment, the stack is as fast as any other RAM location (actually faster on one platform I've used). Maybe I'm just lucky!