DSPRelated.com
Forums

Genreral Question for DSP BlackFin

Started by raul June 30, 2005
Hi All,

I am quite new to the DSP programming. There is an ongoing debate at my
place regarding the way to use the ISR as part of the program flow.
Could it really be reasonable to put a lot of work inside the ISR? Is
it different from working in an OS like VxWorks? What are the pros and
cons in doing a lot of work inside the ISR - speaking about the
BlackFin Familly?
I will really appreciate your answers to that theoretical question.

Thanks, 
Raul D. S.

"raul" <david_segal@hotmail.com> wrote in message 
news:1120107555.162903.145020@g44g2000cwa.googlegroups.com...
> Hi All, > > I am quite new to the DSP programming. There is an ongoing debate at my > place regarding the way to use the ISR as part of the program flow. > Could it really be reasonable to put a lot of work inside the ISR? Is > it different from working in an OS like VxWorks? What are the pros and > cons in doing a lot of work inside the ISR - speaking about the > BlackFin Familly? > I will really appreciate your answers to that theoretical question.
In my work, I do sample-based audio processing, so most of the work (and all of the critical work) is done in an ISR (the sample interrupt). Since that is the most critical processing to be done, it makes sense to give it the highest priority, which is to execute it immediately in the ISR--as soon as an audio sample is received, it is processed and output. If in your system you have other key tasks that can't afford to be "starved out", then you may need to limit how much work is done in the ISRs. To me, this is not really a theoretical question, but a practical one. I say do whatever you need to make sure the important work gets done and the background tasks execute at a reasonable rate, regardless of what this means philosophically.
Thanks a lot.
It seems that I'm using the DSP in a way that resemble yours. Now I'm
considering if to plunge into the assembler or first code a first
version in C and debug first it in a lower sample rate than I will use
at the end. What do you think,
Raul.

Jon Harris wrote:
> "raul" <david_segal@hotmail.com> wrote in message > news:1120107555.162903.145020@g44g2000cwa.googlegroups.com... > > Hi All, > > > > I am quite new to the DSP programming. There is an ongoing debate at my > > place regarding the way to use the ISR as part of the program flow. > > Could it really be reasonable to put a lot of work inside the ISR? Is > > it different from working in an OS like VxWorks? What are the pros and > > cons in doing a lot of work inside the ISR - speaking about the > > BlackFin Familly? > > I will really appreciate your answers to that theoretical question. > > In my work, I do sample-based audio processing, so most of the work (and all of > the critical work) is done in an ISR (the sample interrupt). Since that is the > most critical processing to be done, it makes sense to give it the highest > priority, which is to execute it immediately in the ISR--as soon as an audio > sample is received, it is processed and output. If in your system you have > other key tasks that can't afford to be "starved out", then you may need to > limit how much work is done in the ISRs. > > To me, this is not really a theoretical question, but a practical one. I say do > whatever you need to make sure the important work gets done and the background > tasks execute at a reasonable rate, regardless of what this means > philosophically.
raul wrote:
> Thanks a lot. > It seems that I'm using the DSP in a way that resemble yours. Now I'm > considering if to plunge into the assembler or first code a first > version in C and debug first it in a lower sample rate than I will use > at the end. What do you think, > Raul.
You may find that C is fast enough. If your compiler makes use of the special DSP functions (MAC, zero-overhead loop, etc.) it may well be. If the throughput falls short, profile the code and hand optimize those parts that use the most time. That's unlikely to be as much as a quarter of the whole. 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 message 
news:ueSdnXK5ccuNiVnfRVn-iQ@rcn.net...
> raul wrote: >> Thanks a lot. >> It seems that I'm using the DSP in a way that resemble yours. Now I'm >> considering if to plunge into the assembler or first code a first >> version in C and debug first it in a lower sample rate than I will use >> at the end. What do you think, >> Raul. > > You may find that C is fast enough. If your compiler makes use of the special > DSP functions (MAC, zero-overhead loop, etc.) it may well be. If the > throughput falls short, profile the code and hand optimize those parts that > use the most time. That's unlikely to be as much as a quarter of the whole.
I agree with Jerry. It is much easier to develop and debug in C and then optimize the critical parts later. Doing it this way also allows you to look at the compiled assembly results for a starting point for optimization. One thing to watch out for, the built-in interrupt handlers can add quite a bit of overhead, especially if your interrupts happen frequently. They assume that everything has to be saved, but writing your own, you can make assumptions to save cycles. But that again is something to look at after everything is coded and debugged.
Jon Harris wrote:

> "Jerry Avins" <jya@ieee.org> wrote in message > news:ueSdnXK5ccuNiVnfRVn-iQ@rcn.net... > >>raul wrote: >> >>>Thanks a lot. >>>It seems that I'm using the DSP in a way that resemble yours. Now I'm >>>considering if to plunge into the assembler or first code a first >>>version in C and debug first it in a lower sample rate than I will use >>>at the end. What do you think, >>>Raul. >> >>You may find that C is fast enough. If your compiler makes use of the special >>DSP functions (MAC, zero-overhead loop, etc.) it may well be. If the >>throughput falls short, profile the code and hand optimize those parts that >>use the most time. That's unlikely to be as much as a quarter of the whole. > > > I agree with Jerry. It is much easier to develop and debug in C and then > optimize the critical parts later. Doing it this way also allows you to look at > the compiled assembly results for a starting point for optimization. One thing > to watch out for, the built-in interrupt handlers can add quite a bit of > overhead, especially if your interrupts happen frequently. They assume that > everything has to be saved, but writing your own, you can make assumptions to > save cycles. But that again is something to look at after everything is coded > and debugged. > >
If you're going to code the ISR in C then you probably need to let the built-in interrupt handlers save all that stuff. 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. -- ------------------------------------------- Tim Wescott Wescott Design Services http://www.wescottdesign.com
"Tim Wescott" <tim@seemywebsite.com> wrote in message 
news:11c88fuqoajoi51@corp.supernews.com...
> Jon Harris wrote: > >>>raul wrote: >>> >>>>Thanks a lot. >>>>It seems that I'm using the DSP in a way that resemble yours. Now I'm >>>>considering if to plunge into the assembler or first code a first >>>>version in C and debug first it in a lower sample rate than I will use >>>>at the end. What do you think, >>>>Raul. >>> >>>You may find that C is fast enough. If your compiler makes use of the special >>>DSP functions (MAC, zero-overhead loop, etc.) it may well be. If the >>>throughput falls short, profile the code and hand optimize those parts that >>>use the most time. That's unlikely to be as much as a quarter of the whole. >> >> >> I agree with Jerry. It is much easier to develop and debug in C and then >> optimize the critical parts later. Doing it this way also allows you to look >> at the compiled assembly results for a starting point for optimization. One >> thing to watch out for, the built-in interrupt handlers can add quite a bit >> of overhead, especially if your interrupts happen frequently. They assume >> that everything has to be saved, but writing your own, you can make >> assumptions to save cycles. But that again is something to look at after >> everything is coded and debugged. > If you're going to code the ISR in C then you probably need to let the > built-in interrupt handlers save all that stuff.
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.
Good additions, Tim. I think the key point which you brought out is the number of threads and how time-critical they are. With a well-defined task such as sample-based audio processing and no time-critical background tasks, the big ISR is the way to go. With more than one time-critical task, small ISRs would work better. For me, it's OK that the ISR starve out all other processing, because it is the only time-critical task. But if I needed to respond to some other event very quickly, the big ISR could hinder that.
"Jon Harris" <jon99_harris7@hotmail.com> wrote in
news:hOVwe.8093$Iv6.1067@trnddc03: 

> "Tim Wescott" <tim@seemywebsite.com> wrote in message > news:11c88fuqoajoi51@corp.supernews.com... >> Jon Harris wrote: >> >>>>raul wrote: >>>> >>>>>Thanks a lot. >>>>>It seems that I'm using the DSP in a way that resemble yours. Now >>>>>I'm considering if to plunge into the assembler or first code a >>>>>first version in C and debug first it in a lower sample rate than I >>>>>will use at the end. What do you think, >>>>>Raul. >>>> >>>>You may find that C is fast enough. If your compiler makes use of >>>>the special DSP functions (MAC, zero-overhead loop, etc.) it may >>>>well be. If the throughput falls short, profile the code and hand >>>>optimize those parts that use the most time. That's unlikely to be >>>>as much as a quarter of the whole. >>> >>> >>> I agree with Jerry. It is much easier to develop and debug in C and >>> then optimize the critical parts later. Doing it this way also >>> allows you to look at the compiled assembly results for a starting >>> point for optimization. One thing to watch out for, the built-in >>> interrupt handlers can add quite a bit of overhead, especially if >>> your interrupts happen frequently. They assume that everything has >>> to be saved, but writing your own, you can make assumptions to save >>> cycles. But that again is something to look at after everything is >>> coded and debugged. >> If you're going to code the ISR in C then you probably need to let >> the built-in interrupt handlers save all that stuff. > > 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. > > Good additions, Tim. I think the key point which you brought out is > the number of threads and how time-critical they are. With a > well-defined task such as sample-based audio processing and no > time-critical background tasks, the big ISR is the way to go. With > more than one time-critical task, small ISRs would work better. For > me, it's OK that the ISR starve out all other processing, because it > is the only time-critical task. But if I needed to respond to some > other event very quickly, the big ISR could hinder that. > > >
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. 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. - Al Clark Danville Signal Processing, Inc. -------------------------------------------------------------------- Purveyors of Fine DSP Hardware and other Cool Stuff Available at http://www.danvillesignal.com
Al Clark wrote:
> "Jon Harris" <jon99_harris7@hotmail.com> wrote in > news:hOVwe.8093$Iv6.1067@trnddc03: > > >>"Tim Wescott" <tim@seemywebsite.com> wrote in message >>news:11c88fuqoajoi51@corp.supernews.com... >> >>>Jon Harris wrote: >>> >>> >>>>>raul wrote: >>>>> >>>>> >>>>>>Thanks a lot. >>>>>>It seems that I'm using the DSP in a way that resemble yours. Now >>>>>>I'm considering if to plunge into the assembler or first code a >>>>>>first version in C and debug first it in a lower sample rate than I >>>>>>will use at the end. What do you think, >>>>>>Raul. >>>>> >>>>>You may find that C is fast enough. If your compiler makes use of >>>>>the special DSP functions (MAC, zero-overhead loop, etc.) it may >>>>>well be. If the throughput falls short, profile the code and hand >>>>>optimize those parts that use the most time. That's unlikely to be >>>>>as much as a quarter of the whole. >>>> >>>> >>>>I agree with Jerry. It is much easier to develop and debug in C and >>>>then optimize the critical parts later. Doing it this way also >>>>allows you to look at the compiled assembly results for a starting >>>>point for optimization. One thing to watch out for, the built-in >>>>interrupt handlers can add quite a bit of overhead, especially if >>>>your interrupts happen frequently. They assume that everything has >>>>to be saved, but writing your own, you can make assumptions to save >>>>cycles. But that again is something to look at after everything is >>>>coded and debugged. >>> >>>If you're going to code the ISR in C then you probably need to let >>>the built-in interrupt handlers save all that stuff. >> >>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. >> >>Good additions, Tim. I think the key point which you brought out is >>the number of threads and how time-critical they are. With a >>well-defined task such as sample-based audio processing and no >>time-critical background tasks, the big ISR is the way to go. With >>more than one time-critical task, small ISRs would work better. For >>me, it's OK that the ISR starve out all other processing, because it >>is the only time-critical task. But if I needed to respond to some >>other event very quickly, the big ISR could hinder that. >> >> >> > > > 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. > > 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.
Yet another factor that favors doing little in the ISR is the need to be sure that all functions used in it are either reentrant or not used outside it. The fewer functions used, the fewer need to be investigated and perhaps rewritten. 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" <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!
> 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. 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.