C Programming with Interrupts: How to Avoid Polling and Optimize Processor Usage

AI Thread Summary
The discussion centers on optimizing C programming with interrupts on a PIC18F8722 microcontroller, specifically addressing concerns about unnecessary polling. The original code uses a polling loop to check for an interrupt flag, which can tie up processor resources. Suggestions include moving more functionality into the interrupt service routine (ISR) and utilizing function pointers to handle multiple interrupt actions. The use of the 'volatile' keyword is clarified as necessary to prevent compiler optimization issues with variables modified in the ISR. Overall, the conversation emphasizes the importance of minimizing polling to enhance processor efficiency while using interrupts effectively.
fractal01
Messages
13
Reaction score
1
Hi everyone~

I think that I have used polling here where I shouldn't have done. Does anyone have any ideas?
Code:
#include "p18f8722.h"
#include "timers.h"

    void configure_PB2_interrupt (void);
    void enable_global_interrupts(void);
    unsigned char PB2_pressed (void);
    void isr (void);

    volatile unsigned char int_occured = 0;
 
    #pragma code vector=0x08       
    void vector (void){
        _asm
        GOTO isr
        _endasm
    }
    #pragma code

    
    void main (void){
        ADCON1  = 0x0F;
        TRISB   = 0xFF;
        TRISF   = 0x00;

        configure_PB2_interrupt();

        while (1){
            while (!int_occured){
                    ;
                }
            int_occured = 1;
            if (PORTBbits.RB0 == 1){
                LATF = 0x00;
                }   
            }           
        }

    void configure_PB2_interrupt (void){
        INTCONbits.GIE  = 1;
        INTCONbits.INT0IE   = 1;
        INTCON2bits.INTEDG0 = 0;
    }
    

     #pragma interrupt isr
     void isr(void){
        INTCONbits.INT0IF = 0;
        LATF = 0x01;
        int_occured = 1;
    }
 
Last edited by a moderator:
Physics news on Phys.org
Is the code working (is your interrupt routine getting called) ? I haven't seen the "goto" syntax you're using in vector before (is goto an assembler macro?). Normally you'd have to get the address of your interrupt routine (pointer to function) and store it in the memory location used to branch to interrupt 8. There may be a library function that does this for you.

You could put more of the code in the interrupt routine, but unless this is a multi-tasking operating system, polling for the interrupt flag isn't going to cause problems, and there's nothing else to do. You could use a sleep() in the main polling loop, but again, there aren't any other tasks running unless you have a multi-tasking operating system.
 
You should explain what you want this code to do an what it is actually doing. I see you setting int_occured to 1 in the ISR. Should you be clearing it to 0 somewhere?
 
The code is supposed to be run on a pic18f8722. When one of the pushbuttons is pressed, then an interrupts should be generated. I am mainly worried about the polling. I shouldn't be doing this I don't think. I wrote this a few months ago and now I am looking I am confused at what I was doing! Is there another way that I could do this so that I am not polling the flags? My while loop looks very iffy since I got the polling which I am not sure if it defeats the objects of the interrupts, also I have the volatile variable in there too and it doesn't seem necessary. The friend I wrote it with is convinced it is fine since it did the task it was supposed to...

The asm bit it fine I think -just something we have been taught to use- it is assembly language. Thanks for your help!
 
fractal01 said:
I am mainly worried about the polling.
The polling for the interrupt flag is probably ok. You don't show the code for the main routine, so I'm not sure what the purpose of this program is.

If you wanted to run a series of functions from the interrupt routine (a different function with each interrupt), you could use a pointer to function (pfisr in this example) and update it as needed:

Code:
typedef void (* PFISR)(void);

static void isr0(void);
static void isr1(void);
static void isr2(void);

static volatile PFISR pfisr;

main()
/* .. */
    pfisr = isr0;

isr()
/* .. */
    (*pfisr)();

isr0()
    pfisr = isr1;
/* .. */

isr1()
    pfisr = isr2;
/* .. */

isr2()
    pfisr = isr0;
/* .. */
 
Last edited:
fractal01 said:
I have the volatile variable in there too and it doesn't seem necessary. The friend I wrote it with is convinced it is fine since it did the task it was supposed to...

The asm bit it fine I think -just something we have been taught to use- it is assembly language. Thanks for your help!

The 'volatile' is a hint to the compiler not to optimize out a variable that changes outside of normal program flow (in the ISR).

The asm goto is to move the start of the ISR code out of the high/low vector area. It's not really needed if you only have a high pri ISR but if you do have high and low vectors putting code directly at the vector would limit the size of the high ISR before it would overrun the low vector address.

0008H high
0018H low
 
rcgldr said:
The polling for the interrupt flag is probably ok. You don't show the code for the main routine, so I'm not sure what the purpose of this program is.

Using interrupts means that polling doesn't have to be used which ties up the processor repeatedly checking. Maybe it is different polling the interrupt flag...Is there any other way of writing the program to NOT include the polling there?
 
fractal01 said:
Using interrupts means that polling doesn't have to be used which ties up the processor repeatedly checking. Maybe it is different polling the interrupt flag...Is there any other way of writing the program to NOT include the polling there?
Yes, if you put all the code in the interrupt handler(s). The example I posted above shows how to have the interrupt call a different function each time an interrupt occurs, so that you can step through a sequence of functions, one per interrupt.

Still there's the issue that the main program doesn't have anything else to do, so it's just going to be looping anyway, unless there's a useful sleep() or waitforevent() (normally used by multi-threaded operating systems) type function.
 
Back
Top