Odd interrupt execution.

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Odd interrupt execution.

771 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by rogerwilson on Fri May 24 02:56:33 MST 2013
[FONT=Arial]I have a piece of code which is basically:[/FONT]

[FONT=Courier New]#include rit.h[/FONT]

[FONT=Courier New]extern volatile rit_counter1;[/FONT]
[FONT=Courier New]extern volatile rit_counter2;[/FONT]

[FONT=Courier New]while (1) {[/FONT]

[FONT=Courier New]if (rit_counter1 >= 1) {[/FONT]
[FONT=Courier New]   some stuff ...[/FONT]
[FONT=Courier New]   rit_counter1 = 0;[/FONT]
[FONT=Courier New]}[/FONT]

[FONT=Courier New]if (rit_counter2 >= interval) {[/FONT]
[FONT=Courier New]      some other stuff ...[/FONT]
[FONT=Courier New]      rit_counter2 = 0;[/FONT]
[FONT=Courier New]}[/FONT]

[FONT=Arial]'interval' is setup elsewhere to be 4.[/FONT]
[FONT=Arial]The rit_counter variables are incremented in the RIT ISR i.e.[/FONT]

[FONT=Courier New]volatile uint32_t rit_counter1 = 0;[/FONT]
[FONT=Courier New]volatile uint32_t rit_counter2 = 0;[/FONT]

[FONT=Courier New]void RIT_IRQHandler (void)[/FONT]
[FONT=Courier New]{   [/FONT]
[FONT=Courier New]  rit_counter1++;[/FONT]
[FONT=Courier New]  rit_counter2 ++;[/FONT]
[FONT=Courier New]  LPC_RIT->RICTRL |= (0x1<<0);[/FONT]
[FONT=Courier New]return;[/FONT]
[FONT=Courier New]}[/FONT]

[FONT=Arial]Whilst developing the code (optimisation off) there were times when only the second "if" section would run. I never got to the bottom of why but with a bit of fiddling about and apparently needless modifications it went away and I have some perfectly good working code. If however the optimisation level is anything but -O0, the code behaves very oddly. The first "if"statement never runs and the second "if" statement seems to run at twice the frequency it should.[/FONT]

[FONT=Arial]Does anyone have any view on why this might be please? Is there anything inherent in the way I'm using the RIT interrupt and 2 similar but separate variales to control the execution that's in some way dodgy?[/FONT]

[FONT=Arial]TIA,[/FONT]

[FONT=Arial]Rog.[/FONT]
0 Kudos
17 Replies

755 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by rogerwilson on Wed Jun 12 16:31:00 MST 2013
R2D2,

Thanks again for taking the time to help me with this.

I'd never thought of the ISR being left early due to optimisation. Great analysis, explanation and good advice.

The Force is a tiny bit stronger now!

Rog.
0 Kudos

755 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by R2D2 on Wed Jun 12 15:17:46 MST 2013

Quote: rogerwilson
[FONT=Arial][SIZE=2]Thanks for sending me your version. After a lot of head scratching I finally noticed you'd moved the line:[/SIZE][/FONT]

[FONT=Arial][SIZE=2][COLOR=#0000c0][COLOR=#0000c0]LPC_RIT->RICTRL[/COLOR][/COLOR] |= (0x1<<0);        [COLOR=#3f7f5f][COLOR=#3f7f5f]/* clear interrupt flag */[/COLOR][/COLOR][/SIZE][/FONT]

[FONT=Arial][SIZE=2][COLOR=black]from the bottom of RIT_IRQHandler to the top i.e. last instruction to first instruction[/COLOR][/SIZE][/FONT]



Forgot to mention that, it's an automatism :)

The rule is: Clear Interrupts as soon as possible.


Quote: rogerwilson
[FONT=Arial][SIZE=2]If you have any ideas at all about why this might be the case, I'd love to hear them as this is totally weird!![/SIZE][/FONT]


Clearing interrupts early (first line, if possible) is avoiding several problems.

If your interrupt is triggered again while you are still in ISR this interrupt isn't lost. This problem occurs in a long ISR, with fast interrupts...

You are obviously not losing interrupts, you are winning new interrupts :)

If you are clearing the interrupt in the last line of ISR, this instruction can be too late. With optimization you are leaving the ISR before the interrupt is cleared. As result the ISR is executed again. I think that's your problem. A little bit more time can avoid this, but the best way to clear an interrupt is at the first line.

Note: A __DSB() (http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0552a/CHDDGICF.html) after clearing the interrupt should avoid this problem also.
0 Kudos

755 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by rogerwilson on Wed Jun 12 14:36:19 MST 2013
[FONT=Arial][SIZE=2]R2D2,[/SIZE][/FONT]
[FONT=Arial][SIZE=2][/SIZE][/FONT]
[FONT=Arial][SIZE=2]Thanks for sending me your version. After a lot of head scratching I finally noticed you'd moved the line:[/SIZE][/FONT]
[FONT=Arial][SIZE=2][/SIZE][/FONT]
[FONT=Arial][SIZE=2][COLOR=#0000c0][COLOR=#0000c0]LPC_RIT->RICTRL[/COLOR][/COLOR] |= (0x1<<0);[COLOR=#3f7f5f][COLOR=#3f7f5f]/* clear interrupt flag */[/COLOR][/COLOR][/SIZE][/FONT]
[FONT=Arial][SIZE=2][COLOR=#3f7f5f][/COLOR][/SIZE][/FONT]
[FONT=Arial][SIZE=2][COLOR=black]from the bottom of RIT_IRQHandler to the top i.e. last instruction to first instruction. For a reason I can't understand, this makes all the difference. With this line as the last instruction, the wrong frequency is generated with -Os. With it as the first instruction, it works.[/COLOR][/SIZE][/FONT]
[FONT=Arial][SIZE=2][/SIZE][/FONT]
[FONT=Arial][SIZE=2]If you have any ideas at all about why this might be the case, I'd love to hear them as this is totally weird!![/SIZE][/FONT]
[FONT=Arial][SIZE=2][/SIZE][/FONT]
[FONT=Arial][SIZE=2]Rog.[/SIZE][/FONT]
0 Kudos

755 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by R2D2 on Tue Jun 11 14:22:38 MST 2013

Quote: rogerwilson
...and sending them to me for comparison please?



I've just changed your Debug connection from JTAG to SWD and changed output functions to macros. But anyway, I'll export and post it in in a few minutes...

And here it is: [ATTACH]1052[/ATTACH]

Note: It's compiled against Standard CMSIS V2, so it's running with 100MHz. Hardware: LPCXpresso1769.
0 Kudos

755 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by rogerwilson on Tue Jun 11 14:03:22 MST 2013
I've upgraded to 5.2.4 [2122] and again cannot see any different behaviour. 30Hz or 60Hz depending on -O0 or -O1.

LPC1768 / LPCXpresso v5.2.4 [Build 2122] / Red Probe +

This is by altering the optimisation level within the same (Debug) configuration i.e. nothing else changes between tests.

You say that you've been able to produce 120 / 30Hz irrespective of the optimisation level. Is there a way of encapsulating the project settings that you've used and sending them to me for comparison please?

Thanks,

Rog.
0 Kudos

755 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by rogerwilson on Mon Jun 10 04:58:30 MST 2013
Even staying with Debug and changing the optimisation level within just Debug also produces the wrong frequency.

Maybe I should try a later version after all!
0 Kudos

755 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by rogerwilson on Mon Jun 10 04:54:39 MST 2013
Hello R2D2,

I have the usual 2 configurations (Debug and Release) where the optimisation levels are set.

Interestingly I've got version 5.0.14 Build 1109 rather than your later version but can't think that's got anything to do with it.
0 Kudos

755 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by R2D2 on Mon Jun 10 04:32:52 MST 2013

Quote: rogerwilson
R2D2,

I've run exactly what you suggested.



  No. My LPC1769 and LPCXpresso v5.2.4 [Build 2122] and LPC-Link SWD are generating always 120/30Hz.

How do you switch your optimization? In Debug mode?
0 Kudos

755 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by rogerwilson on Mon Jun 10 04:21:12 MST 2013
R2D2,

Thanks for the code suggestion. I've run exactly what you suggested. The behaviour is exactly the same in that with -O0 the LED frequencies are 120Hz and 30Hz (correct) but with -O1 they are120Hz and 60Hz i.e. the 2 x frequency phenomena is still there.

Thanks ,

Rog.
0 Kudos

755 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by R2D2 on Fri Jun 07 15:26:49 MST 2013

Quote: rogerwilson
If anyone else can suggest anything, I'd be grateful.



First you have to decide if that's a RIT mystery or a PIN mystery
Therefore I would suggest to use a simple macro to toggle your LEDs. If that's working with different optimization levels your mystery is a PIN mystery.

//LED1
#define LED1_PIN     (1 << 6)
#define LED1_PORT     LPC_GPIO2
#define LED1_ON     LED1_PORT->FIOSET =LED1_PIN
#define LED1_OFF    LED1_PORT->FIOCLR =LED1_PIN
#define LED1_TOG    LED1_PORT->FIOPIN^=LED1_PIN

//LED2
#define LED2_PIN     (1 << 5)
#define LED2_PORT     LPC_GPIO2
#define LED2_ON     LED2_PORT->FIOSET =LED2_PIN
#define LED2_OFF    LED2_PORT->FIOCLR =LED2_PIN
#define LED2_TOG    LED2_PORT->FIOPIN^=LED2_PIN

...

int main(void) {
...
    LED1_PORT->FIODIR |= LED1_PIN;    //set LED1 output
    LED2_PORT->FIODIR |= LED2_PIN;    //set LED2 output
...

while (1) {

        // Toggle Info LED (D2) every RIT tick (4.17ms).
        if (rit_counter_switch_flag == 1) {
           [COLOR=Red] LED1_TOG;[/COLOR]
            //info_led ((info_led_flash & 0x02) >> 1);
            info_led_flash ++;                            // Flash frequency = Rate / 4 (i.e. 60Hz)
            rit_counter_switch_flag = 0;
        }

        // Toggle Error LED (D1) every 4 RIT ticks (16.7ms)
        if (rit_counter_demand_flag == 1) {
          [COLOR=Red]  LED2_TOG;[/COLOR]
            //error_led ((error_led_flash & 0x02) >> 1);
            error_led_flash ++;                            // Flash frequency = Rate / 4 (i.e. 15Hz)
            rit_counter_demand_flag = 0;
        }
This should produce 120Hz and 30Hz signals.
0 Kudos

755 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by rogerwilson on Fri Jun 07 14:10:31 MST 2013
In accordance with R2D2's suggestion, I've put together a cut-down version of my code (attached) that still shows the strange RIT problem. Basically the code should now enter one "if" every 4.16ms (240Hz) and the other "if" every 16.7ms (60Hz). Two LEDS are toggled at a quarter frequency (60Hz and 15Hz).

When the code is compiled with optimisation set to -O0 it works OK. With optimisation set to -O1, the higher speed LED still flashes at 60Hz but the slower LED flashes at 30Hz rather than 15Hz.

This is slightly different to the behaviour of the original code as the faster "if" would never be entered at all and the slower "if" would also run at 2 x the intended frequency. However the strangeness is surely linked so still relevant.

Being fairly new to C coding, I suspect there's something simple that I've not done but I can't see anything. If anyone else can suggest anything, I'd be grateful. Thanks.

Roger.
0 Kudos

755 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by cfb on Fri May 24 19:03:42 MST 2013

Quote: rogerwilson
With -O0 all works OK but with anything else the first "if" never executes and the other one goes at twice the frequency.

Do you have to use optimization other than -O0?

Otherwise, compare the relevant assembler code generated for -O0 and an optimization level that is problematic - that might give you a clue as to what is happening.
0 Kudos

755 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by R2D2 on Fri May 24 12:00:21 MST 2013
Perhaps you want to create and export a nice little new LPCXpresso project with your basic mystery?

Let's see if my good old Tektronix is also a MythBuster :)
0 Kudos

755 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by rogerwilson on Fri May 24 11:45:22 MST 2013
R2,

I moved the comparisons and created flags for the main code but no change in behaviour. With -O0 all works OK but with anything else the first "if" never executes and the other one goes at twice the frequency.

A mystery!

Thanks for your suggestions.

Rog.
0 Kudos

755 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by R2D2 on Fri May 24 06:20:53 MST 2013
240Hz isn't a speed that should cause problems.

However, I would suggest to move comparisons in your ISR and use a (volatile) flag.

[FONT=Courier New]if (rit_counter1 >= ...[/FONT]
{
  rit_flag1 =1;
}
I'm not sure how RITENBR is changing overall behaviour, so I would disable it. Switching and scoping GPIOs with rit flags in your main could help you also.
What's  happening if you run a release build?
0 Kudos

755 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by rogerwilson on Fri May 24 05:44:36 MST 2013
Thanks R2,

I (obviously) hadn't spooted the rogue return - thanks. However it doesn't seem to make any difference.
It is a runtime problem with the RIT or moreover how I'm using the 2 variables to control the flow.
The RIT is set-up to interrupt every 4.17ms (240Hz):

void init_rit (uint32_t TimerInterval)
{
LPC_SC->PCONP |= RIT_POWERON;
LPC->RICTRL = 0x00000006;
rit_counter1 = 0;
rit_counter2 = 0;
LPC_RIT->RICOMPVAL = TimerInterval;
NVIC_EnableIRQ(RIT_IRQn);
return;
}

void enable_rit (void)
{LPC_RIT->RICTRL = 0x0000000E;
return;
}

init_rit(104165);
enable_rit();

Thanks again for your interest.

Rog.
0 Kudos

755 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by R2D2 on Fri May 24 04:14:57 MST 2013

Quote: rogerwilson

[FONT=Courier New]void RIT_IRQHandler (void)[/FONT]
[FONT=Courier New]{   [/FONT]
[FONT=Courier New]  rit_counter1++;[/FONT]
[FONT=Courier New]  rit_counter2 ++;[/FONT]
[FONT=Courier New]  LPC_RIT->RICTRL |= (0x1<<0);[/FONT][COLOR=Red]
  [FONT=Courier New]return;[/FONT][/COLOR]
[FONT=Courier New]}[/FONT]
 


Wrong is of course this return in your ISR.

Without project (especially RIT setup) it's difficult to guess what's your problem. My first guess would be a runtime problem with a fast RIT?
0 Kudos