Interrupt not interrrupting

22 Feb 2010

Am I going nuts!!!  I'm trying to step through a table at a particular rate and to achieve this I've  set up a ticker interrupt.  The following code is a fragment of the original but is the minimum program to illustrate the problem of the "while (!sl_flag)" loop waiting for the interrupt "sl_flag " and totally ignoring it. The program hangs in the "while" loop, never reaching the print statements.

#include "mbed.h"
#include "MobileLCD.h"

MobileLCD lcd(p11, p12, p13, p10, p9);

Ticker slice;      //specify slice interrupt
DigitalOut led1(LED1);  //is something happening led

const int table[20] = {
    0,70,139,208,276,342,407,469,530,588,643,695,743,788,829,866,899,
    927,951,970
    };

int sl_flag = 0;
int fout = 0;
int q = 0;

void slice_flag() {
    sl_flag = 1;
    led1 = !led1; //see something happening!!
}

int main(){
    slice.attach(&slice_flag,0.5);  //set up slice interrupt for this note
    while(1) {
        for(int i=0;i<20;i++) {   
            fout = table[i];
            while (!sl_flag);  //wait for interrupt 
            sl_flag = 0;    //reset flag for next time round
                    //print stuff to show what's happening i.e. debug
            lcd.locate(0,5); lcd.printf("             "); //clear print area
            lcd.locate(0,5); lcd.printf("%d  %d",i, fout);
        }
    }
}

However, if I give the "while" loop something frivolous to do while it is waiting, it spots the interrupt and executes properly and the printfs show everything counting nicely.

         while (!sl_flag) {q++; lcd.locate(0,9) ; lcd.printf("%d  ",q);}

Is there something wrong with my code or is the compiler optimising a bit too much?

The fragment is slowed right down so I can see things happening (or not). At full speed, there are no printfs and the ticker period is ~40us. Which brings me to the next question. What is the minimum period and resolution for Ticker - can it cope with float numbers - with 43.5us, for instance?

Pip

22 Feb 2010 . Edited: 22 Feb 2010

Yep, most likely it's the optimizer at work. Change int sl_flag to volatile int sl_flag, that should fix it.
You can also use __WFI(); in the loop body to reduce processor usage.

22 Feb 2010

Thanks Igor, converting to volatile did it. What do you mean by "You can also use __WFI(); in the loop body to reduce processor usage" ?

22 Feb 2010

__WFI() is a macro that expands to the instruction WFI, Wait For Interrupt. It makes the CPU stop execution and go to sleep until it receives an interrupt. So, if you make your code to be:

while (!sl_flag) { __WFI(); }

it should reduce power usage.

22 Feb 2010

Interesting. However, during this delay the DtoA output on pin 18 is driving. With the CPU stopped, what happens to the output at the pin?

22 Feb 2010

Unless you explicitly turn off the peripheral (in your case the DAC), sleep mode won't affect it.