Electronics & Programming

develissimo

Open Source electronics development and programming

  • You are not logged in.
  • Root
  • » MSPGCC
  • » [Mspgcc-users] Race Condition Bug in MSP430 Interrupt Hardware? [RSS Feed]

#1 March 18, 2008 20:21:44

R D.
Registered: 2009-11-02
Reputation: +  0  -
Profile   Send e-mail  

[Mspgcc-users] Race Condition Bug in MSP430 Interrupt Hardware?


Hi all, I have come across what appears to be a bug in the MSP430 interrupt
hardware.
I would appreciate critiques and comments.


The specific case is where interrupts are disabled upon exit from an
interrupt handler:
Why should this not happen? An interrupt should only occur when interrupts
are enabled. So upon exit from the ISR, the previous state (interrupts
enabled)
should be restored.


Bug:
Consider code that looks like this:
:
code_where_interrupts_are_enabled();
:
_DINT();
_NOP();

If an interrupt occurs before the _DINT(); that is well and good since
interrupts are enabled and upon exit from the ISR,
the state is enabled.

Interrupts cannot occur after the _DINT(); since interrupts are disabled.


HOWEVER, it seems that an interrupt occurring sometime during (or
immediately before) the execution of _DINT();
is serviced by an ISR but within the value of the status register pushed on
the stack, the GIE bit is not set.
So upon exit from the ISR, using an RETI instruction, the popped value has
interrupts disabled.


Is this a problem?
----------------------------------------------------------------------------
Not for most people. If you explicitly disabled interrupts using _DINT();
then your eventual goal is to
have interrupts disabled, and this will be the case after the ISR.


When is it a problem?
----------------------------------------------------------------------------
If from an ISR, you want to force another interrupt after the completion of
the current ISR, you will be out of luck.
Since upon exit from the ISR, interrupts are disabled.

* There may be other cases that I haven't thought about.



Here is a code listing illustrating the problem. It is a simple busy loop
that performs _DINT(); and _EINT();
There is a simple timer interrupt that fires periodically. The timer clock
is driven from ACLK.
This will run for some time before an error occurs.
An error is detected within the ISR by examining the
value of the status register that was pushed on the stack as the interrupt
was serviced.
By the semantics of interrupts, this status word should have GIE enabled.
The error is flagged when GIE is not enabled.




Code Listing illustrating problem. On my MSP430x1611 the error gets flagged
after about half a minute of free running.
----------------------------------------------------------------------------------------------------------


#include <io.h>
#include <signal.h>
#include <isr_compat.h>
#include <util.h>


#define R_LED BIT4
#define G_LED BIT5
#define B_LED BIT6
#define Y_LED BIT7

#define IDLE_LED (G_LED)
#define ERROR_LED (Y_LED)

#define ERROR_INDICATE_ON() P5OUT |= ERROR_LED;
#define ERROR_INDICATE_OFF() P5OUT &= ~ERROR_LED;

#define INTERRUPT_BEGIN() P5OUT |= R_LED;
#define INTERRUPT_END() P5OUT &= ~R_LED;


#define _GET_SR_IRQ \
({ \
uint16_t __x; \
__asm__ __volatile__( \
"mov .L__FrameOffset_" __FUNCTION__ "(r1), %0" \
: "=r" ((uint16_t) __x) \
:); \
__x; \
})



interrupt ( TIMERA1_VECTOR ) isr_counter_rollover(void)
{
uint16_t status;

INTERRUPT_BEGIN();
/* This reads and resets it */
status = TAIV;

delayms(1);


status = _GET_SR_IRQ ;
if (!(status & GIE)) {
ERROR_INDICATE_ON();
}

INTERRUPT_END();

}




int main(void)
{
int i;

WDTCTL = WDTPW|WDTHOLD; //Init watchdog timer

while ((IFG1 & OFIFG) != 0) {
// Wait for LF Osc to startup
IFG1 &= ~OFIFG;
delayms(100);
}




P5DIR = (BIT4|BIT5|BIT6|BIT7);



// --------------------------------------------------
// Set up a timer interrupt on timer A.
// The timer is driven from the 32 kHz clock.
// --------------------------------------------------
/* 1. Setup up max count */
TACCR0 = 512; /* Interrupt every 15 ms */
/* 2. Set synchronous */
TACCTL0 = SCS;
/* 3. Set up options. 32kHz source, Interrupt enable,
continous, clear. */
TACTL = TASSEL_ACLK | TAIE | MC_UPTO_CCR0 | TACLR;


_EINT(); // Enable interrupts
// --------------------------------------------------


while (1) { //main loop, never ends...
for (i=0; i<512; i++) {
if (i == 0)
P5OUT |= IDLE_LED;
else if (i == 256)
P5OUT &= ~IDLE_LED;

_DINT(); _NOP();
delayms(1);
_EINT(); _NOP();

}
}


}

Offline

#2 March 18, 2008 22:12:13

Hardy G.
Registered: 2009-11-02
Reputation: +  0  -
Profile   Send e-mail  

[Mspgcc-users] Race Condition Bug in MSP430 Interrupt Hardware?


R Develop wrote:Hi all, I have come across what appears to be a bug in the MSP430interrupt hardware.I would appreciate critiques and comments.Hi,I guess, that the situation is possible and not illegal. Read 2.2.3 inslau049f.pdf, "Interrupt Acceptance":"
1) Any currently executing instruction is completed.
"I'm interpreting this as follows: the interrupt detection andinstruction execution are asynchronous. If this is true, it is possiblethat1. the interrupt occurs at the beginning of the DINT (GIE=0),
2. because DINT is already in the pipeline, it will be executed
3. SR with GIE=0 is pushed onto the stack as a consequence
4. the interrupt handler is called with GIE=0

> When is it a problem?
>
> If from an ISR, you want to force another interrupt after the completion
> of the current ISR, you will be out of luck.
> Since upon exit from the ISR, interrupts are disabled.Good point. In this case you will not get two consecutive interrupthandlers. How to get the intended behavior? Further reading in 2.2.3leads to "Interrupt Nesting", which says"Interrupt nesting is enabled if the GIE bit is set inside an interruptservice routine. When interrupt nesting is enabled, any interruptoccurring during an interrupt service routine will interrupt theroutine, regardless of the interrupt priorities."If the last (but one?) instruction of the interrupt handler would be anEINT (GIE=1), it would give the chained interrupt handler the chance tobe called consecutively after (or better in between) the first handler.Price in this case would be some bytes extra on the stack.

Not sure if I'm right, because not tested...

HardyPS: last but one instruction, because on many microprocessors theinstruction directly after the EINT will be executed in any case withoutinterrupt acceptance

Offline

  • Root
  • » MSPGCC
  • » [Mspgcc-users] Race Condition Bug in MSP430 Interrupt Hardware? [RSS Feed]

Board footer

Moderator control

Enjoy the 16th of December
PoweredBy

The Forums are managed by develissimo stuff members, if you find any issues or misplaced content please help us to fix it. Thank you! Tell us via Contact Options
Leave a Message
Welcome to Develissimo Live Support