#19026 - poslundc - Sat Apr 10, 2004 1:16 pm
gbawiz wrote: |
Hello all,
I have a question with regards to ISR interrupt routines.
In my app, I am using two timers, each with the ability to call the interrupt routine.
timer 1 deals with the general game timers such as the animation frame rate, counting, etc.. and the other deals with the audio.
The question I have is: what happens when the ISR is currently servcing the interrupt from timer 1 and then timer 2 generates and interrupt?
Is timer2 ignored?
or does the CPU wait till it finishes timer1 servicing then move onto 2
or does the interrupt for timer 1 get interrupted by timer 2 with timer 2 being serviced?
Thanks
GbaWIZ |
This depends on your interrupt handler.
If you use the one that comes with DKA, you can select in crt0.S whether you want to enable multiple interrupt support or not.
If you write your own ISR, by default a new interrupt can be triggered while your current interrupt is still running, so you should code your ISR to be able to handle it.
Dan.
#19030 - gbawiz - Sat Apr 10, 2004 1:41 pm
Thanks,
Well, im using my own ISR routine.
Basically what im attempting is to include an audio mixer engine which I created (nothing exciting), which makes use of the timer which indicates that the 2k mixing buffer needs refilling by counting the samples played.
The ISR performs the refilling.
So what you are saying is that each of the routines within the ISR can interrupt each other?
The app starts ok, a bit slower than usual, but then itseems to stall after a while. The stalling point is never the same when the app is run.
#19031 - poslundc - Sat Apr 10, 2004 1:45 pm
Make sure you are properly setting the correct interrupt-acknowledge bits when you complete your ISR. This is the kind of thing that can start making a system behave oddly when you support multiple interrupts.
Dan.
#19032 - gbawiz - Sat Apr 10, 2004 1:51 pm
I think this might have something to do with it:
------ within my ISR----------------
Code: |
if(REG_IF==INT_TIMER1){
REG_IF=(REG_IF|INT_TIMER1);
//do stuff related to timer 1
}
if(REG_IF==INT_TIMER2){
REG_IF=(REG_IF|INT_TIMER2);
//do stuff related to timer 2
}
|
#19064 - tepples - Sat Apr 10, 2004 9:08 pm
And what if REG_IF has more than one bit set at once?
The right way is to read the interrupts once as a bitfield and then test each bit:
Code: |
void isr(void)
{
int interrupts = REG_IF;
if(interrupts & INT_TIMER1)
{
/* whatever */
}
if(interrupts & INT_TIMER2)
{
/* whatever */
}
BIOS_IF |= interrupts; /* important: |= (or equals) not = */
REG_IF = interrupts; /* important: |= (or equals) not = */
} |
_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.
#19066 - poslundc - Sat Apr 10, 2004 9:10 pm
Why are you OR-ing with REG_IF before assigning the new value to it? You only need to acknowledge the current interrupt being serviced.
Dan.
#19068 - tepples - Sat Apr 10, 2004 9:16 pm
If two interrupts happen at once (two bits set in REG_IF), and I've serviced them both, then I need to acknowledge them both.
If you refer to the line that modifies BIOS_IF, that's necessary to get BIOS IntrWait() to work. IntrWait() checks *(volatile unsigned short int)0x03fffff8 (which may or may not be called BIOS_IF in your GBA header file) to see which interrupts happened. If IntrWait() does not work, then the program wastes current by spinning rather than halting.
_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.
#19075 - poslundc - Sat Apr 10, 2004 10:39 pm
Sorry tepples, my post was in response to gbawiz's post, not yours. For some reason yours didn't show up between his and mine, even after I posted it.
Dan.
#19142 - gbawiz - Sun Apr 11, 2004 11:27 pm
Thanks Tepples for the useful info, it seems to have worked as the app is no longer stalling and sound seems to be playing as required (although the app seems to have slowed down).
One thing about the interrupt triggers,
timers 1 and 2 can cause interrupts and they are serviced in this order.
What happens if timer2 causes interrupt while processing interrupt 1?
Quote: |
Poslundc:
If you write your own ISR, by default a new interrupt can be triggered while your current interrupt is still running, so you should code your ISR to be able to handle it.
|
my interrupts cannot be interrupted otherwize this causes major problems.
Do I have to disable other possible interrupts while processing the current one?
#19143 - poslundc - Sun Apr 11, 2004 11:41 pm
gbawiz wrote: |
my interrupts cannot be interrupted otherwize this causes major problems.
Do I have to disable other possible interrupts while processing the current one? |
Yes, you do, if it'll cause a problem like you say.
Dan.
#19145 - Gopher - Sun Apr 11, 2004 11:58 pm
Random question, when you disable interrupts, do their flags still get set in REG_IF?
_________________
"Only two things are infinite: the universe, and human stupidity. The first is debatable." -Albert Einstein
#19149 - torne - Mon Apr 12, 2004 2:18 am
It depends where you disable them. If you disable them in the CPU's status register, then yes, they are recorded; they just don't interrupt your program. If you disable them in the source place (e.g. disable VBLANK interrupts in the REG_DISPCNT) then no, they won't happen at all. If you disable them in REG_IE, I don't actually know. =)
#19151 - poslundc - Mon Apr 12, 2004 3:13 am
Someone once claimed that REG_IE acts as a mask, so that interrupts enabled in their control registers won't trigger, but will essentially queue up until their mask bit is set (or I suppose until interrupts are disabled). This would provide an effective method for temporarily disabling interrupts (eg. in time-critical code such as an HBlank ISR) without "missing" interrupts (eg. if you have a sound-mixer running).
Dan.
#19157 - torne - Mon Apr 12, 2004 1:32 pm
You can already do that just by disabling the I bit in the CPU status register; no interrupts will fire, but all will be collected normally, and will deliver when you set the I bit back on. The only reason you'd need to use REG_IE is if you wanted to turn off some and not others (and I still don't know if that works; perhaps someone should try it *grin*).