2

I want to build a program in C that enables / disables a passive matrix display. But my problem occurs before I can even implement one function of this display.

I have a simple switch connected to Port C pin 24, which is configured as INPUT with a pull-up resistor and debouncing input filter. When I toggle the switch the code enters an interrupt and toggles the "display" on or of depending on the state of the switch.

Everything works fine until I introduce a simple while(1) loop, which should handle everything I want to do. But every time I write the function called run, which only contains one while(1) loop and a single dummy operation __asm__("nop"), the while loop prevents the code from entering the interrupt.

This is my code:

void display_init(void) {
    sysclk_init();
    delay_init(sysclk_get_cpu_hz());
    pmc_set_writeprotect(false);
    pmc_enable_periph_clk(ID_PIOC);
    NVIC_EnableIRQ(PIOC_IRQn);
    REG_PIOC_PER = SWITCH;
    REG_PIOC_ODR = SWITCH;
    REG_PIOC_OWDR = SWITCH;
    REG_PIOC_PUER = SWITCH;
    REG_PIOC_IFER = SWITCH;
    REG_PIOC_DIFSR = SWITCH;
    REG_PIOC_LSR = SWITCH;
    REG_PIOC_REHLSR = SWITCH;

    //Clear input change register to avoid immediate interrupt
    REG_PIOC_ISR;
    REG_PIOC_IER = SWITCH;
    run();
}

void run() {
    while(1) {
        __asm__("nop"); //Dummy operation for debugging
    }
}

void PIOC_Handler(void) {
    REG_PIOC_ISR;
    if(REG_PIOC_PDSR & PIO_PC24) {
        __asm__("nop"); //Breakpoint
    } else {
        __asm__("nop"); //Breakpoint
    }
}

As far as I know, an interrupt stops everything executed at the current time and starts working on the interrupt code. My question is now: Why is the interrupt not stopping the while loop?

Before I recognized this problem, I had a simple condition in the while loop that checks whether 1 or 0 to equals 1 when I set this state to 0, so the condition was 1 == 0 which should equal false. The loop did not stop and continued to run even if the condition for this loop was false... Is it possible that while loops do not like to be used in parallel with interrupts?

EDIT:

void main(void) {
    board_init();
    display_init();
}

I don't have an Arduino setup() function because I'm using Atmel Studio to ensure working at low Level, to avoid unnecessary code and to keep memory usage as low as possible.

3
  • This is not an Arduino question - you are not using the Arduino software framework or tools, and you are not using classic Arduino hardware. Essentially what you have here is a software problem, in a more generic microcontroller context. Dec 31, 2016 at 18:25
  • How do you even know if the interrupt is hit or not? Also, consider the possibility that the interrupt was not being hit in the previous case, but the execution was falling through to it. Dec 31, 2016 at 18:29
  • 2
    Is it possible that while loops do not like to be used in parallel with interrupts? Of course not. Do you think if you use interrupts you can't use while loops? You may as well not use for loops. It is impossible to answer without seeing all of your code. Please make a minimal example that demonstrates what you are talking about.
    – Nick Gammon
    Dec 31, 2016 at 21:24

1 Answer 1

2

The while loop should have no effect on interrupts. Where does run() get called? We'll need to see the code that sets up and calls the code you've shown. But as a sanity check, you could try replacing the entire contents of run() with a ;, that is make it an empty function. Then add in an empty while loop (contains only a ;, no __asm__ code) and try again. Then replace the body of the while loop with __asm("nop")__ and try again. At which of the above steps does your interrupt fail? That should lead you in the right direction.

Update:
What does your main() function do after display_init() returns? Because that won't ever happen when run() runs forever.

The job of main() is to create the C/C++ run-time environment. That may not have been completed (enabling interrupts, for instance) when display_init() and run() get called, but gets completed shortly after they returns - if run() is allowed to end.

Without seeing your main(), we can't know enough to be more specific, but I'd suggest you move all of your code out of main() and down into the Arduino setup() function because, by the time it gets called, the run-time environment will be complete.

Update 2:

to avoid unnecessary code

If that is your entire main() function, you've left out the run-time environment setup and it's little wonder that your code behaves strangely. You've asked for help and we've made some suggestions: to show your entire code, not just selected pieces of it; and run your code in a standard way and let us know the result. Then you can optimize your code if you feel it's worth it to you. When you've done that test, and you still have questions, ask again. Until then, you're just asking us to guess. We did that. Once.

2
  • I call the run()method in the display_init() function at the top of my code. The init function is called by the main() function of the code. I tried it with an empty run() method. The interrupt worked as expected. But at the moment where I placed any type of while loop the interrupt fails. Even with an empty loop. Only if I replaced it with a while(0) loop it worked but with this the code is not working because it is not a loop anymore. Dec 31, 2016 at 13:43
  • 2
    Sounds like interrupts aren't enabled. Bear in mind that an empty run() method is likely to be optimized away by the compiler.
    – Nick Gammon
    Dec 31, 2016 at 21:25

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.