|
|
View previous topic :: View next topic |
Author |
Message |
XachSB
Joined: 23 Jun 2009 Posts: 2
|
Sleep on Interrupts |
Posted: Tue Jun 23, 2009 9:49 pm |
|
|
Hi,
I am working on an application that requires calling a timing interrupt repetitively and at a rate of around 32Khz. I am running my PIC at 40Mhz (With my clock setup this gives me 10 Mhz for my timer). According to my calculations I should have plenty of free time, but I seem to be hitting a threshold much earlier then expected. I noticed in the C/ASM List that sleep is called when an interrupt is called:
Code: |
.................... //===================================
.................... // Interrupt Service Routines
.................... //===================================
.................... #int_ext //External interrupt from index channel (hall effect or opto-sensor)
.................... void indexInterrupt()
0B44: SLEEP
.................... {
.................... int16 period;
.................... int tempLBPeriod; //Holds value before assigning it.
.................... period = get_timer1(); //Get period from timer 1
|
Why is sleep called when the microcontroller first handles the interrupt? Could this be a reason for my time loss?
Thanks,
Zach |
|
|
FvM
Joined: 27 Aug 2008 Posts: 2337 Location: Germany
|
|
Posted: Wed Jun 24, 2009 1:49 am |
|
|
No asm code is shown in a CCS listing before the opening bracket. This looks like a kind of corrupted listing. Apart from this, the processor would never recover from a sleep inside an ISR, excecpt by a watchog reset. |
|
|
Ttelmah Guest
|
|
Posted: Wed Jun 24, 2009 2:35 am |
|
|
It is possible to get a listing like this, but the 'sleep' is not in the ISR. The ISR code comes latter, at a different address. Need to see more of the listing to make sure. The sleep is not the problem.
32KHz, is pushing the ISR rate. There is a _massive_ overhead to calling an ISR. Typically about 60+ instructions to call, and return from an ISR. This is the code to save the registers in use in the 'main' code, poll which ISR has actually occurred, call the ISR routine, return from the ISR, clear the interrupt flag, restore the registers, and then return. Even at 40Mhz, this overhead will 'cost' about 6uSec. With only 30uSec available, this becomes very significant. Generally, to go this fast, _will_ require you to start thinking very carefully. First, the _fastest_ way, will not be to use a ISR at all. Use the interrupt, but not an ISR. Disable interrupts, and poll the interrupt flag. This can bring response times down to only typically three instruction times 'worst case'. Much faster than using the hardware interrupt, which has a 'best case' response in the same order, even with no register handling at all. To use the hardware interrupt (only worth doing, if you _must_ perform other tasks at the same time), to get this sort of speed, you will _need_ to 'go custom', and look through the generated assembler for the interupt, and work out for yourself, exactly which registers are actually used in your code. Then use the 'global' interrupt handler (which is normally generated invisibly for you, and contains the main overhead), and save just the registers you need, call your handler, clear the interrupt flag yourself, restore the registers, and return. Hardware interrupts are _not_ the fastest way to make the processor work. The 'point' is allowing you to have events handled while other code is going on, not 'speed'.
I have posted in the past example code for doing generating a custom global interrupt, handling a few events, faster than the default, and a search should find this.
Best Wishes |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Wed Jun 24, 2009 3:02 pm |
|
|
Here is a way to duplicate the original poster's results.
Put the #int_ext routine below the main() code, and put a function
prototype for it above main(). Then the SLEEP instruction that CCS puts
at the end of main() will appear to be part of the #int_ext routine, but it's
not really. It's just a quirk of the .LST file formatting.
Code: |
.................... void main()
.................... {
*
00A8: CLRF FF8
00AA: BCF FD0.7
00AC: BSF 08.7
00AE: CLRF FEA
00B0: CLRF FE9
00B2: BSF FC1.0
00B4: BSF FC1.1
00B6: BSF FC1.2
00B8: BCF FC1.3
....................
.................... while(1);
00BA: BRA 00BA
.................... }
.................... //----------------
....................
.................... #int_ext
.................... void ext_isr(void)
00BC: SLEEP
.................... {
.................... char c;
.................... c = 0x55;
*
009E: MOVLW 55
00A0: MOVWF 18
.................... }
|
Code: |
#include <18F452.h>
#fuses XT,NOWDT,PUT,BROWNOUT,NOLVP
#use delay(clock=4000000)
#int_ext
void ext_isr(void);
//===============================
void main()
{
while(1);
}
//----------------------------
#int_ext
void ext_isr(void)
{
char c;
c = 0x55;
} |
|
|
|
|
|
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
|