Thanks Peter - yesterday I was saying "if only there was a way to enter LPM4 
and enable interrupts at the same time in an atomic way" - stupidly I did not 
even think about the mechanism behind eint and LPM4 macros and that I can just 
combine them in one atomic operation. 

As for forums, in the future I will post there, but I do detest having to sign 
up for yet another forum.

Thanks,

- Wayne

-----Original Message-----
From: pabi...@gmail.com [mailto:pabi...@gmail.com] On Behalf Of Peter Bigot
Sent: Tuesday, 6 December 2011 10:29 AM
To: Eric Decker
Cc: Sergio Campamá; Wayne Uroda; mspgcc-users@lists.sourceforge.net
Subject: Re: [Mspgcc-users] Enter LPM4 without missing the wakeup interrupt

On Mon, Dec 5, 2011 at 6:22 PM, Eric Decker <cire...@gmail.com> wrote:
> On Mon, Dec 5, 2011 at 4:05 PM, Sergio Campamá <scamp...@ing.puc.cl> wrote:
>
>> Hello Wayne,
>>
>> The only difference between LPM3 and LPM4 is that the ACLK is stopped in
>> LPM4, so moving onto LPM3 won't solve your problem. What is the P1.1
>> connected to? If you wanted to wake the system up from LPM4 when there is
>> an interrupt on P1.1, you could do this: (I believe that you want to sleep
>> only if the pin is down)
>>
>> void function(){
>>        P1IES &= BIT1;
>>        P1IFG &= BIT1;
>>        P1IE |= BIT1;
>>
>>
>>        while(1){
>>                sleep_if_down()
>>                //do work
>>        }
>> }
>>
>> __attribute__((critical)) void sleep_if_down(){
>>        if(! P1IN && BIT1){
>>                LPM4();
>>        }
>> }
>>
>> interrupt(PORT1_VECTOR) PORT1_ISR(){
>>        //wake up from LPM4
>>        P1IFG &= BIT1;
>>        _BIC_SR_IRQ(LPM4_bits);
>> }
>>
>> What this does is that it checks if the P1.1 is down, if it is, it enters
>> LPM4. Now, the __attribute__((critical)) part tells the compiler (I learned
>> this in this mailing-list) to disable interrupts while in the function. So
>> you won't handle the interrupt until after the comparison is made.
>>
>
> Have you looked explicitly at the code generated for the above?
>
> If I understand critical correctly, it basically disables interrupts
>  during the routine.

I believe that's what it does.  It often saves one word by putting the
disable into the prolog where the compiler can skip generating the
"nop" that usually has to follow it, and another by using "reti"
instead of "ret".  It's still more opaque than I prefer.

The pattern I use for this sort of thing is:

volatile int vflag;  // global variable, only modified when interrupts disabled
  // ...
  while (1) {
    __disable_interrupt();
    if (! vflag) {
      // Sleep in LPM4 until interrupt
      __bis_status_register(LPM4_bits | GIE);
      // interrupts are enabled at this point, so jump out of disable region
      continue;
    }
    // acknowledge the state by clearing it
    vflag = 0;
    // do atomic handling here
    __enable_interrupt();
    // do non-atomic handling here

One key point code feature is that by invoking the intrinsic with its
arguments explicitly rather than using syntactic sugar macros, you
(and whoever maintains your code after you) know that you're enabling
interrupts, which is kinda important, if whatever you're waiting for
is signalled by an interrupt.  From what I see (and consistent with
what Eric said), "LPM4()" will not touch the interrupt flag, leaving
you with that race condition you mentioned if you left interrupts
enabled, and leaving you locked out if you didn't.

__disable_interrupt, __enable_interrupt, and __bis_status_register are
intrinsics the spelling of which may be different depending on your
compiler.  You would also use:

    // set vflag if condition holds
    if (vflag) {
      __bic_SR_register_on_exit(LPM4_bits);
    }

in your interrupt handler.

Finally, the 20111205 release supports:

  __istate_t istate = __get_interrupt_state();
  __disable_interrupt();
  // do stuff here
  __set_interrupt_state(istate);

so you can disable interrupts then restore them to whatever state they
were at on entry.

If anybody isn't aware of http://www.43oh.com/forum/, I recommend that
site for questions of this sort.

>   Which means that when you go asleep (LPM4)
> interrupts will be disabled and the cpu goes away forever because it can't
> take the Port1 interrupt.
>
> I believe you have to have interrupts enabled when you do the LPM4.   Which
> gets back to Wayne's critical region/race condition issue.
>
>
> eric
>
>
>
>> You don't have to setup the IE and IES all the time, just the first time,
>> that's why I took it out of the while, and the IFG gets cleared in the
>> interrupt vector, no need to do it again.
>>
>> I hope this helps. Best regards,
>> ---------------------------------------
>> Sergio Campamá
>> sergiocamp...@gmail.com
>>
>>
>>
>>
>> On Dec 5, 2011, at 8:40 PM, Wayne Uroda wrote:
>>
>> > I have a question which isn't technically related to MSPGCC (more of a
>> msp430 question) but I thought one of you smart people might know.
>> >
>> > Imagine the following scenario:
>> >
>> > /* 1*/        while (1)
>> > /* 2*/        {
>> > /* 3*/                if (!port1.in.pin1)
>> > /* 4*/                {
>> > /* 5*/                        // Enable interrupt (rising edge) for pin
>> 1.1
>> > /* 6*/                        port1.ies.pin1 = 0;
>> > /* 7*/                        port1.ifg.pin1 = 0;
>> > /* 8*/                        port1.ie.pin1 = 1;
>> > /* 9*/
>> > /*10*/                        // Enter sleep mode, but only if the pin
>> is still not high
>> > /*11*/                        if (!port1.in.pin1)
>> > /*12*/                        {
>> > /*13*/                                LPM4();
>> > /*14*/                        }
>> > /*15*/                }
>> > /*16*/
>> > /*17*/                // Awake
>> > /*18*/                // Do real work here
>> > /*19*/        }
>> >
>> > The ISR for port1 interrupt just wakes up the processor from LPM4 and
>> clears the IFG for pin 1.1.
>> >
>> > The problem I see is that there is a small window (between the execution
>> of line 11 and line 13) where pin1.1 can go high, have the ISR handled and
>> the IFG cleared, and then the system can incorrectly go into LPM4 even
>> though pin1.1 is high.
>> >
>> > My thoughts are that the only way around this is to avoid using LPM4 and
>> poll the state of pin 1.1, which is what I have done in previous designs.
>> As far as I know there is no way to atomically enter LPM4 and enable
>> interrupts so that the pending pin1.1 IFG can be handled AFTER entering
>> LPM4, thus bringing the system out of LPM4.
>> >
>> > Has anybody come up against this? Is using LPM3 the best/only workaround?
>> >
>> > I am using 1 family chips, MSP430F148 in particular.
>> >
>> > Thanks,
>> >
>> > - Wayne
>> >
>> >
>> ------------------------------------------------------------------------------
>> > All the data continuously generated in your IT infrastructure
>> > contains a definitive record of customers, application performance,
>> > security threats, fraudulent activity, and more. Splunk takes this
>> > data and makes sense of it. IT sense. And common sense.
>> > http://p.sf.net/sfu/splunk-novd2d
>> > _______________________________________________
>> > Mspgcc-users mailing list
>> > Mspgcc-users@lists.sourceforge.net
>> > https://lists.sourceforge.net/lists/listinfo/mspgcc-users
>>
>>
>>
>> ------------------------------------------------------------------------------
>> All the data continuously generated in your IT infrastructure
>> contains a definitive record of customers, application performance,
>> security threats, fraudulent activity, and more. Splunk takes this
>> data and makes sense of it. IT sense. And common sense.
>> http://p.sf.net/sfu/splunk-novd2d
>> _______________________________________________
>> Mspgcc-users mailing list
>> Mspgcc-users@lists.sourceforge.net
>> https://lists.sourceforge.net/lists/listinfo/mspgcc-users
>>
>
>
>
> --
> Eric B. Decker
> Senior (over 50 :-) Researcher
>
> ------------------------------------------------------------------------------
> All the data continuously generated in your IT infrastructure
> contains a definitive record of customers, application performance,
> security threats, fraudulent activity, and more. Splunk takes this
> data and makes sense of it. IT sense. And common sense.
> http://p.sf.net/sfu/splunk-novd2d
> _______________________________________________
> Mspgcc-users mailing list
> Mspgcc-users@lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/mspgcc-users
>

------------------------------------------------------------------------------
All the data continuously generated in your IT infrastructure 
contains a definitive record of customers, application performance, 
security threats, fraudulent activity, and more. Splunk takes this 
data and makes sense of it. IT sense. And common sense.
http://p.sf.net/sfu/splunk-novd2d
_______________________________________________
Mspgcc-users mailing list
Mspgcc-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/mspgcc-users

Reply via email to