|
|
View previous topic :: View next topic |
Author |
Message |
Prashant Patel
Joined: 19 Jul 2004 Posts: 33
|
Handling Interrupt while ISR of other Interrupt running |
Posted: Thu Dec 30, 2004 4:03 pm |
|
|
Hi..Anybody want to take closer look !!
I am using 18F4525 using 40Mhz. We have following three interrupts.
Interrupt Timer0---->Every 6.5 mSec
Interrupt Timer1---->Every 6.5 mSec
Interrupt CCP2-----> Every 2 mSec
Sometimes while one ISR is running, the other timer overflows. And it
does not execute that another ISR. What I want is at the end of the
each ISR, I want to check the flags of other two ISRs and execute the
the required code accordingly.
How it can be possible?
I have tried to use the fast interrupt for Timer0 but everytime the registers
used are changed, How can we decide which registers to be stored and restored?
Following is the example of, How I stored and Restored the registers used. But
when I compile the code those registers used are changed. I don't know much
of the assembly. It is wasting more than one week for this to these interrupts
handling but still no results.
Here I found that registers 0x0, 0x1, 0x2, 0x3, 0x56, 0x57, 0x58, 0x59, 0x49,
0x4a are used.
All are int8....
Quote: |
save_scratch0 = *0;
save_scratch1 = *1;
save_scratch2 = *2;
save_scratch3 = *3;
save_scratch56 = *0x56;
save_scratch57 = *0x57;
save_scratch58 = *0x58;
save_scratch59 = *0x59;
save_scratch49 = *0x49;
save_scratch4a = *0x4a;
// ISR code goes here
*0 = save_scratch0;
*1 = save_scratch1;
*2 = save_scratch2;
*3 = save_scratch3;
*0x56=save_scratch56;
*0x57=save_scratch57;
*0x58=save_scratch58;
*0x59=save_scratch59;
*0x49=save_scratch49;
*0x4a=save_scratch4a;
|
|
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Fri Dec 31, 2004 4:50 am |
|
|
Before discussing all kind of low level tricks like interrupt priorities and fast interrupts, lets have a look at your problem from a higher level:
Quote: | I am using 18F4525 using 40Mhz. We have following three interrupts.
Interrupt Timer0---->Every 6.5 mSec
Interrupt Timer1---->Every 6.5 mSec
Interrupt CCP2-----> Every 2 mSec
Sometimes while one ISR is running, the other timer overflows. And it
does not execute that another ISR. | What you are describing here is a situation where the execution time of all three interrupts together is taking more than 2 ms. Running at 40MHz this means that your interrupts are executing at least 20,000 instructions... a huge number!!
In my code a typical ISR on the PIC18 takes about 80 to 500 instruction cycles, this includes saving and restoring the registers.
Rule number 1 when using interrupts:
Always try to make your interrupt routines as fast as possible.
In your previous thread you showed some code which was easy to optimize just by removing the float variables. Considering that you are still saving the registers in the 0x4a to 0x56 range I assume these float variables are still there. I checked my suggestions in that thread and spotted an error, I forgot to paste a line of code and without that change the float calculations are still there. See my updated response in that other thread.
My suggestion to you is to optimize your code so all three interrupts together will execute within a 2ms time span. Forget about all little smart tweaking options right now and concentrate on the big issue why your code is taking such an incredible long time to execute. First of all, get rid of the float variables. |
|
|
Prashant Patel
Joined: 19 Jul 2004 Posts: 33
|
|
Posted: Sat Jan 01, 2005 9:59 pm |
|
|
Hi...ckielstra
In my previous thread, you said to use inbuilt PWM to generate the
frequency of 1Hz to 2KHz using 16KHz Oscillator.
You said:
Quote: |
Let's just assume you bring down the clock frequency to 16kHz, then the hardware PWM circuits can be used!
|
How we can achieve low frequency range ? I think minimum possible is 976Hz.
(1/16000000)*4*16*256= 1024 us or 976.5625 KHz
I have also changed that line you have modified last in my previous thread.
Let me explain you all three interrupts in detail because after this I need to add another
two interrupts. I don't know, How it will be possible. I am working on this issue for last 10 to 15 days. But no result. I have also posted the code for all three interrupts.
Quote: |
Interrupt Timer0(16 bit)---->Generating 1 Hz to 2 KHz(May be 3KHz in the future)
Interrupt Timer3(16 bit)---->For extending the CCP2 frequency Capture time
Interrupt CCP2----->Capturing the input frequency of 1Hz to 2KHz with max possible
capture is CCP_CAPTURE_DIV_4
|
There are three possible way, we have.....
1. As you said reducing the ISR code size. I don't know, How can I reduce the
following ISR code. If we can solve by this then it would be greate.
2. fast interrupts
I have tried to store and restore the registers used but I think they are changed
everytime I compile and disturbing the functionality.
3. Check the other interrupts flags at the end of the ISR and serve there.
Here are the interrupts:
Quote: |
#INT_RTCC //fast : RTCC_DIV_2 for generating 1Hz to 2KHz
void timer0_isr() {
/*
save_scratch0 = *0; // Save working register 0
save_scratch1 = *1; // Save working register 1
save_scratch2 = *2; // Save working register 2
save_scratch3 = *3; // Save working register 3
save_scratch43 = *43; // Save working register 43
save_scratch44 = *44; // Save working register 44
*/
if(FinalAFM>0)
{
//Changing from (high to low) and (low to high)
if(ChangeStatus==1)
{
if(HighPulse==0)
{
HighPulse=1;
output_high(PIN_C5);
}
else
{
HighPulse=0;
output_low(PIN_C5);
}//if(HighPulse==1)
ChangeStatus=0;
}//if(ChangeStatus==1)
//For getting new changed frequency
if(ChangePulse==1)
{
TimerCyH = (int32)(625000/FinalAFM);
TimerCyL=TimerCyH;
ChangePulse=0;
}//if(ChangePulse==1)
// This is for setting timer. As TimerCyH and TimerCyL is more than 65536
// I must use this code
//If I write this inside main then Timer value will not be exact.
if(TimerCyH>0)
{
if(TimerCyH>=65536)
{
TimerCyH = TimerCyH-65536;
set_timer0(0);
}
else
{
set_timer0(65535-(int16)TimerCyH);
TimerCyH=0;
ChangeStatus=1;
}//if(TimerCyH>=65536)
}
else if(TimerCyL>0)
{
if(TimerCyL>=65536)
{
TimerCyL = TimerCyL-65536;
set_timer0(0);
}
else
{
set_timer0(65535-(int16)TimerCyL);
TimerCyL=0;
ChangePulse=1;
ChangeStatus=1;
}//if(TimerCyL>=65536)
}//if(TimerCyH>0)
}
else
{
HighPulse=0;
output_low(PIN_C5);
}//if(FinalAFM!=0)
/*
*0 = save_scratch0; // restore working register 0
*1 = save_scratch1; // restore working register 1
*2 = save_scratch2; // restore working register 2
*3 = save_scratch3; // restore working register 3
*43 = save_scratch43; // restore working register 43
*44 = save_scratch44; // restore working register 44
*/
}//timer0_isr
###########################################################
#int_ccp2 // for CCP_CAPTURE_DIV_4
void ccp2_isr()
{
TimerCycle = make32(counttimer3,get_timer3());
set_timer3(0);
AFMFreq = (int16)(40000000/TimerCycle); //for 40MHz
counttimer3=0;
}//#int_ccp2
##############################################################
#INT_TIMER3 //for extending the CCP2
void timer3_isr() {
counttimer3++;
}
|
|
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Mon Jan 03, 2005 5:09 am |
|
|
Quote: | In my previous thread, you said to use inbuilt PWM to generate the
frequency of 1Hz to 2KHz using 16KHz Oscillator.
You said:
Quote:
Let's just assume you bring down the clock frequency to 16kHz, then the hardware PWM circuits can be used!
How we can achieve low frequency range ? I think minimum possible is 976Hz.
(1/16000000)*4*16*256= 1024 us or 976.5625 KHz
| You are mixing MHz and kHz. With a clock frequency of 16kHz the PWM hardware has a lowest frequency of 0,976Hz.
This solutions comes with a whole bunch of other limitations and as I have no clue as to what your other specifications are this might not be a good option. I just wanted to show you there are often more solutions than the obvious one of adding more processing power.
You posted only part of your program and not a whole working example so I used the main routine from your previous thread.
Looking at the generated code you can see the int32/int32 division is taking the major part of the processing time; about 1200 cycles. There are two of these divisions present in your code. So with all 3 interrupts active at the same time you would have to execute about 3000 instructions.
Running at 40MHz and an interrupt every 2ms, you have time for 20,000 instructions available. Considering that your interrupt routines require a maximum of about 3000 cycles in 2 ms. I don't see why you should have any problems in interrupts being missed.
Are you sure your processor is running at 40MHz? |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|