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.

dda
  • 1,595
  • 1
  • 12
  • 17

1 Answers1

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.

JRobert
  • 15,407
  • 3
  • 24
  • 51