On Tue, Sep 4, 2012 at 5:59 AM, David Brown <da...@westcontrol.com> wrote:
> On 03/09/2012 19:54, JMGross wrote:
>> Also, saving the status register
>> and restoring it, will also restore the content of all other bits, not just 
>> GIE.
>
> True, but that won't matter.  Compilers do not usually track the state
> of status bits over a longer range than one instruction pattern.

This case did concern me, but I convinced myself it wasn't a big deal.
 If you use the intrinsics in mspgcc to modify the status register,
the compiler is told that condition code bits have been disrupted and
will recompute them if they are required later.  (That would not
happen within inline assembly.)

>> And finally, at least with MSPGCC 3.2.3, I found situations where the
>> compiler didn't like the status register being changed by the push
>> because of the influence it had on the reference to local variables.
>> (in cases where the optimizer optimized R4 as frame pointer away in
>> favor of R1). I didn't find a way to tell that R1 is changed in the course
>> of the assembly instruction.
>
> This sounds like an old bug in an old compiler version.

No, that's how it'll work.  Offsets to stack addressed objects are
calculated based on frame layout; uncoordinated changes to r1 or r4
(when used) or any other register that are done through asm
instructions will cause problems.  That's a "feature" you take
responsibility for when you use inline asm.  Also be aware that calls
to varargs functions, and use of alloca(), cause changes to r1 (though
under compiler control).

>>
>> Isolating the state of GIE and writing it into a global variable doesn't
>> allow nesting and also adds soem code overhead.
>>
>> So I have come up with a macro that uses a global counter to count
>> the nesting level. It will only perform an eint if the counter reaches 0
>> on block exit.
>> This of course assumes that interrupts are on outside the first atomic
>> block and that no dint/eint operations are uses within.
>>
>> unsigned int ATOMIC_CNT;
>> #define ATOMIC(x) do { __asm__ __volatile__ ("inc %0\n  dint\n
>> ":"=m"(ATOMIC_CNT):); x; __asm__ __volatile__ ("dec %0\n
>>    jnz .LA%=\n  eint\n .LA%=:":"=m"(ATOMIC_CNT):);}while(0)
>>
>
> Sometimes these sorts of solutions can be useful - but usually simpler
> methods are best.

FreeRTOS does something like that.  The pattern I prefer is:

{
  __istate_t istate;

  /* stuff */
  istate = __get_interrupt_state();
  __disable_interrupt();
  /* Preparation of critical section */
  do {
    /* stuff, possibly including break to end of critical section */
  } while (0);
  /* Cleanup after critical section */
  __set_interrupt_state(istate);
}

This has the benefit of being, I believe, portable among IAR, CCS, and
mspgcc.  (IAR because I took the intrinsic and type names and behavior
from an old IAR manual, though I haven't tried it on that platform;
CCS if you typedef unsigned int __istate_t; and mspgcc because I added
them.)  Further, a maintainer doesn't need to read MSP430 asm to
understand what it's intended to do, and the compiler has full
knowledge of your intent too.

>> The macros Peter posted are a good extension of the language
>> and ot less portabel than an intrinsic :)

I think that was supposed to read either "not less portable" or "no
less portable", which is(are) true.  Those macros do exactly what an
intrinsic would do in exactly the same way, but with a lot less effort
from the toolchain maintainer.

Peter

------------------------------------------------------------------------------
Live Security Virtual Conference
Exclusive live event will cover all the ways today's security and 
threat landscape has changed and how IT managers can respond. Discussions 
will include endpoint security, mobile security and the latest in malware 
threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/
_______________________________________________
Mspgcc-users mailing list
Mspgcc-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/mspgcc-users

Reply via email to