[Icc-430] Reading MSP-430 status register from C....

Kris Heidenstrom kris at abbey.co.nz
Mon Apr 14 21:42:27 PDT 2008


Kirk Bailey (bailey at peak.org) wrote:

 > For the current issue I need to read the GIE bit, but
 > there are other situations where it is useful to be
 > able to examine other status bits.
 >
 > Basically what I'm trying to do is implement two
 > primitives:
 >
 > 1. Enter-Monitor (read current GIE status, set GIE to 0)
 > This primitive is where I need to be able to read the
 > SR, followed by a _DINT() /* or _BIC_SR(GIE) */.
 > Depending on the application it may also be useful to
 > isolate the GIE bit by itself in the saved copy to
 > avoid over-writing some of the other flags in the SR
 > during the later execution of the  "exit" primitive.
 >
 > 2. Exit-Monitor (restore saved GIE status)
 > This translates into a _BIS_SR(saved_GIE_status)

Yes we have the same issue with icc430. It's common in
embedded programming to do what you describe. You need
to make sure that interrupts are disabled during certain
critical sections, but you don't want to lock out
interrupts unnecessarily.

If your function just enables interrupts explicitly at
the end of each critical section, then you have to ensure
that the function will never be called in a situation
where interrupts are disabled and must stay disabled,
because the function will explicitly enable them. This
might be a workable approach as long as it's clearly
documented and explained.

But of course the cleanest solution is the traditional one:

   push (or otherwise save) the status register
   explicitly disable interrupts
   do the critical stuff
   restore the status register from the saved value.

With this method it doesn't matter whether interrupts
were disabled on entry to the function or not, because
the code never enables them if they weren't already
enabled, but only forces interrupts off during critical
section(s).

We have tried to convince icc430 to do this efficiently
by defining an automatic local variable to hold the status
register value, and accessing it using asm statements, but
it doesn't work because the compiler thinks the local
variable has no scope (because it is only accessed from
asm statements and the compiler just passes those on to
the assembler without looking at them) so the compiler
will reuse the register allocated to the local variable
for other variables. This was what we tried:

void myfunction(void) {
   auto saved_sr;
   asm ("mov  r2,saved_sr");  /* Save SR */
   /* Non-critical code can go here */
   asm ("dint");
   asm ("nop"); /* (if needed) */
   /* Critical code */
   asm ("mov  saved_sr,r2");  / Restore SR */
   /* Non-critical code */
   asm ("dint");
   asm ("nop"); /* (if needed) */
   /* Critical code */
   asm ("mov  saved_sr,r2");
   /* Non-critical code */
   /* ... more if wanted ... */
   /* Must exit with interrupt flag as on entry */
   asm ("mov  saved_sr,r2");
   /* Non-critical code */
   return;
   }

This would be fairly efficient and would have the
advantage that you only need to save the status register
in the local variable _once_, near the start of the
function (which would be an improvement over the common
approach of pushing SR onto the stack before _each_ DINT
and popping it after the critical section), but we have
not been able to get it to work with icc430.

At the moment we're using function calls to get and
set the status register. This is inefficient, and
ironically that inefficiency affects the very code
that you want to be as efficient as possible. :-(

I would appreciate a formally sanctioned way to deal
with this common embedded programming situation.

Kris
-- 
Kris Heidenstrom       Embedded systems designer / programmer
kris at abbey.co.nz       Abbey Systems Ltd - Telemetry Specialists
Wellington NEW ZEALAND  Voice +64-4-385-6611  Fax +64-4-385-6848



More information about the Icc-430 mailing list