[Icc-430] Reading MSP-430 status register from C....
Andrew Kalman
aek at pumpkininc.com
Tue Apr 15 09:41:30 PDT 2008
In IAR EW430, Salvo 4 uses:
static istate_t s;
void OSDisableHook(void)
{
s = __get_interrupt_state();
__disable_interrupt()'
}
void OSEnableHook(void)
{
__set_interrupt_state(s);
}
Works for all situations (including functions called from ISR).
--Andrew
>Kris/Len,
>
> KRIS, you've got it exactly! I'm keeping my fingers crossed hoping
>that Richard can find a way to implement the SR access intrinsics:
>
>unsigned short __get_SR_register(void);
>unsigned short __get_SR_register_on_exit(void);
>
> With these, the problem yields to a clean and efficient solution.
>
> LEN, I also support your desire to get the asm<->C variable access
>stuff fixed so that when future issues arise we have better tools to
>tackle them with!
>
> Kirk Bailey
> bailey at peak.org
>
>> 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
>>
>> _______________________________________________
>> Icc-430 mailing list
>> Icc-430 at imagecraft.com
>> http://dragonsgate.net/mailman/listinfo/icc-430
>>
>
>
>_______________________________________________
>Icc-430 mailing list
>Icc-430 at imagecraft.com
>http://dragonsgate.net/mailman/listinfo/icc-430
--
______________________________________
Andrew E. Kalman, Ph.D. aek at pumpkininc.com
More information about the Icc-430
mailing list