santosgcot
santosgcot

Reputation: 36

Arduino Uno INTF0 flag not being set without main() function in WOKWI

The code can be found in Checking INTF0 Without ISR

The code works as expected when the main() function is present but it does not when main() function is left out of the code. I do not want to use the ISR handling as many had already suggested. Does someone can point me to what I am not seeing? Thanks in advance.

        #include <avr/io.h>
    // This is just an example.
    // Pushbutton without bouncing connected between ground and INT0 pin - D2.
    // LED connected betwwen ground(cathode) and D8-B0 (anode).
    // LED state toggles each time pushbutton is pressed.
    // Not using IRS in order to avoid its overhead.
    // Polling INTF0 flag state.
    // Code works as expected when main() function is present.
    // Otherwise it fails.
    // Cannot use main() function in the final code because it avoids the 
    // Arduino initialization needed by other project libraries  
    #define LED_PIN PB0          // LED pin
    #define NO_MAIN            // comment to use main()
    #ifndef NO_MAIN
    int main() {
        setup();
        while (true) {
            loop();
        }
        return 0;
    }
    #endif
    void setup() {
        // Set LED_PIN as output
        DDRB |= (1 << LED_PIN);
        // Enable pull-up resistor on INT0 (PD2)
        PORTD |= (1 << PD2);
        // Configure INT0 to trigger on falling edge
        EICRA |= (1 << ISC01);  // Falling edge trigger
        EICRA &= ~(1 << ISC00);
        // Enable INT0 interrupt (this enables the flag, not the ISR)
        EIMSK |= (1 << INT0);
    }
    void loop() {
        // Poll INTF0 flag in the main loop
        if (EIFR & (1 << INTF0)) {
            // Clear the INTF0 flag by writing 1 to it
            EIFR |= (1 << INTF0);
            // Toggle LED
            PORTB ^= (1 << LED_PIN);
        }
    }

Upvotes: 0

Views: 38

Answers (2)

santosgcot
santosgcot

Reputation: 36

After some research, I concluded that the Arduino framework somehow prevents polling the External Interrupt flag (INTF0). The same hardware and code worked flawlessly when the main function was explicitly defined. This issue was solved by placing a cli() function call at the last line of setup() function.

Upvotes: 0

emacs drives me nuts
emacs drives me nuts

Reputation: 4003

Some notes on the code:

  1. Depending on the event source, a proper debouncing might be required, e.g. when using a switch or button or similar input devices. When a switch is bouncing, you may get several events in fast succession, and when their number is even, the LED will appear as if it dod not change.

  2. In order to reset a flag bit, the code is like EIFR = 1 << INTF0 in almost all cases. EIFR |= (1 << INTF0) will inadvertently reset all flags that are set in EIFR.

  3. On modern AVRs, toggling a port register is achieved by PINB = 1 << LED_PIN. Advantage is that it is faster, smaller code, and most importantly it is atomic, which PORTB ^= (1 << LED_PIN) is not.

Upvotes: 0

Related Questions