EmbeddedRelated.com
Forums
The 2024 Embedded Online Conference

Reading status register

Started by Mike Raines August 4, 2009
Folks,

I'm trying to read the status register to see if the cpu is off while inside the SYSNMI ISR. I have tried if (SR & CPUOFF) and if (R2 & CPUOFF) and the compiler doesn't recognize SR or R2. I'm sure this is simple. What am I missing? MSP430F5438 chip...
Thanks,
Mike Raines

Beginning Microcontrollers with the MSP430

You do not mean the current content of SR. Do you?
If you use the CPU to read the current content of SR, I can guarantee that the CPUOFF bit is 0.

The content of SR before the interrupt is saved in the stack.

--- In m..., "Mike Raines" wrote:
>
> Folks,
>
> I'm trying to read the status register to see if the cpu is off while inside the SYSNMI ISR. I have tried if (SR & CPUOFF) and if (R2 & CPUOFF) and the compiler doesn't recognize SR or R2. I'm sure this is simple. What am I missing? MSP430F5438 chip...
> Thanks,
> Mike Raines
>
On Tue, 04 Aug 2009 15:02:14 +0100, Mike Raines
wrote:

> Folks,
>
> I'm trying to read the status register to see if the cpu is off while
> inside the SYSNMI ISR.

If you are executing, then the CPU cannot be "off". Or else it wouldn't
run. Am I being totally thick here? No, I don't think so.

> I have tried if (SR & CPUOFF) and if (R2 & CPUOFF) and the compiler
> doesn't recognize SR or R2.

Of course it doesn't.

> I'm sure this is simple. What am I missing? MSP430F5438 chip...

Try looking at the intrinsic functions for your compiler. I do not
believe you wish to read R2 directly because, if you're executing, the CPU
CANNOT BE OFF!

-- Paul.
Mike Raines wrote:
> Folks,
>
> I'm trying to read the status register to see if the cpu is off while inside the SYSNMI ISR. I have tried if (SR & CPUOFF) and if (R2 & CPUOFF) and the compiler doesn't recognize SR or R2. I'm sure this is simple. What am I missing? MSP430F5438 chip...
>

As pointed out, the cpu is running in the interrupt. The condition of
LPM is on the stack and gets popped back at the interrupt exit. I don't
know about your compiler but for mspgcc there is READ_SP. It assembles to:
mov r1, r15;

So you can:
if( READ_SP & CPUOFF)

to see if you will be in LPM.

Best, Dan.

Hi,

> Mike Raines wrote:
> > Folks,
> >
> > I'm trying to read the status register to see if the cpu is off while
> inside the SYSNMI ISR. I have tried if (SR & CPUOFF) and if (R2 & CPUOFF)
> and the compiler doesn't recognize SR or R2. I'm sure this is simple.
> What am I missing? MSP430F5438 chip...
> >
>
> As pointed out, the cpu is running in the interrupt. The condition of
> LPM is on the stack and gets popped back at the interrupt exit. I don't
> know about your compiler but for mspgcc there is READ_SP. It assembles to:
> mov r1, r15;
>
> So you can:
> if( READ_SP & CPUOFF)

I think you're just testing a bit in the stack pointer. That's not what you
want to do. You need to read a value offset from the stack pointer--doing
so is inherently non-portable. There are intrinsic functions to do this for
you which will account for the current stack pointer and the stack pointer
on entry to the ISR.

--
Paul Curtis, Rowley Associates Ltd http://www.rowley.co.uk
CrossWorks V2 is out for LPC1700, LPC3100, LPC3200, SAM9, and more!
Paul Curtis wrote:
> Hi,
>
>
>> Mike Raines wrote:
>>
>>> Folks,
>>>
>>> I'm trying to read the status register to see if the cpu is off while
>>>
>> inside the SYSNMI ISR. I have tried if (SR & CPUOFF) and if (R2 & CPUOFF)
>> and the compiler doesn't recognize SR or R2. I'm sure this is simple.
>> What am I missing? MSP430F5438 chip...
>>
>> As pointed out, the cpu is running in the interrupt. The condition of
>> LPM is on the stack and gets popped back at the interrupt exit. I don't
>> know about your compiler but for mspgcc there is READ_SP. It assembles to:
>> mov r1, r15;
>>
>> So you can:
>> if( READ_SP & CPUOFF)
>>
>
> I think you're just testing a bit in the stack pointer. That's not what you
> want to do. You need to read a value offset from the stack pointer--doing
> so is inherently non-portable. There are intrinsic functions to do this for
> you which will account for the current stack pointer and the stack pointer
> on entry to the ISR.
>

Hi Paul,
Thanks. And it occurred to me after posting. I don't know what that
function is in mspgcc so I would end up hacking one. But I'm not sure
about the rest. I take it the offset is about using an extended memory
device like the MSP430F543x? Is that what the .L__FrameOffset_ is for?
(I have not used a device past 64k yet).

But for a <64k device shouldn't 'if( *(int*)READ_SP & CPUOFF )' work fine?

And yes! by declaring my int pointer unsigned I get clrc, rrc!

It just doesn't feel right that whatever was sitting in the carry flag
gets shifted in for a signed int.

Best, Dan.

On Tue, 04 Aug 2009 18:31:20 +0100, Dan Bloomquist
wrote:

>>> So you can:
>>> if( READ_SP & CPUOFF)
>>
>> I think you're just testing a bit in the stack pointer. That's not
>> what you
>> want to do. You need to read a value offset from the stack
>> pointer--doing
>> so is inherently non-portable. There are intrinsic functions to do
>> this for you which will account for the current stack pointer and the
>> stack pointer on entry to the ISR.
>> Hi Paul,
> Thanks. And it occurred to me after posting. I don't know what that
> function is in mspgcc so I would end up hacking one. But I'm not sure
> about the rest. I take it the offset is about using an extended memory
> device like the MSP430F543x? Is that what the .L__FrameOffset_ is for?

Who knows? I've no interest in MSPGCC. ;-)

> (I have not used a device past 64k yet).
>
> But for a <64k device shouldn't 'if( *(int*)READ_SP & CPUOFF )' work
> fine?

No. Consider a function with a local that is addressed--SP will (usually)
be decremented by two on entry to the function to make a stack frame,
hence *SP or 2(SP) does not get you the saved SR and return address, it
would now be 2(SP) and 4(SP). Even worse, if in your C code you needed to
call a function which requires arguments on the stack *and* you want to
read what's in the stack frame, then those 2(SP) and 4(SP) refrences have
to change (depending on how much is currently pushed on to the stack, aka
the stack adjustment).

> And yes! by declaring my int pointer unsigned I get clrc, rrc!

That's fine. And shifting an int is (in fact) inherently non-portable.

> It just doesn't feel right that whatever was sitting in the carry flag
> gets shifted in for a signed int.

If you read the C standard you will find that shifting a signed integer
can result in an aritmetic shift (shift sign bit in) *or* a logical shift
(shift a zero bit in).

How portable is that? Is it any wonder that there are brittle programs in
this world when users assume a specific type of shift?

-- Paul.
Thanks to all who replied and either pointed out the faults in my algorithm or pointed to a better way.
I checked the intrinsic functions for IAR (full) and am using "if (__get_SR_register_on_exit() & CPUOFF) "
to determine if I will be asleep when exiting the ISR.

Thanks again. Great bunch of Guys,
Mike Raines

________________________________
From: m... [mailto:m...] On Behalf Of Dan Bloomquist
Sent: Tuesday, August 04, 2009 1:31 PM
To: m...
Subject: Re: [msp430] Reading status register

Paul Curtis wrote:
> Hi,
>> Mike Raines wrote:
>>
>>> Folks,
>>>
>>> I'm trying to read the status register to see if the cpu is off while
>>>
>> inside the SYSNMI ISR. I have tried if (SR & CPUOFF) and if (R2 & CPUOFF)
>> and the compiler doesn't recognize SR or R2. I'm sure this is simple.
>> What am I missing? MSP430F5438 chip...
>>
>> As pointed out, the cpu is running in the interrupt. The condition of
>> LPM is on the stack and gets popped back at the interrupt exit. I don't
>> know about your compiler but for mspgcc there is READ_SP. It assembles to:
>> mov r1, r15;
>>
>> So you can:
>> if( READ_SP & CPUOFF)
>> I think you're just testing a bit in the stack pointer. That's not what you
> want to do. You need to read a value offset from the stack pointer--doing
> so is inherently non-portable. There are intrinsic functions to do this for
> you which will account for the current stack pointer and the stack pointer
> on entry to the ISR.
>

Hi Paul,
Thanks. And it occurred to me after posting. I don't know what that
function is in mspgcc so I would end up hacking one. But I'm not sure
about the rest. I take it the offset is about using an extended memory
device like the MSP430F543x? Is that what the .L__FrameOffset_ is for?
(I have not used a device past 64k yet).

But for a <64k device shouldn't 'if( *(int*)READ_SP & CPUOFF )' work fine?

And yes! by declaring my int pointer unsigned I get clrc, rrc!

It just doesn't feel right that whatever was sitting in the carry flag
gets shifted in for a signed int.

Best, Dan.



Paul Curtis wrote:
> On Tue, 04 Aug 2009 18:31:20 +0100, Dan Bloomquist
> wrote:
>
>
>> (I have not used a device past 64k yet).
>>
>> But for a <64k device shouldn't 'if( *(int*)READ_SP & CPUOFF )' work
>> fine?
>>
>
> No. Consider a function with a local that is addressed--SP will (usually)
> be decremented by two on entry to the function to make a stack frame,
> hence *SP or 2(SP) does not get you the saved SR and return address, it
> would now be 2(SP) and 4(SP). Even worse, if in your C code you needed to
> call a function which requires arguments on the stack *and* you want to
> read what's in the stack frame, then those 2(SP) and 4(SP) refrences have
> to change (depending on how much is currently pushed on to the stack, aka
> the stack adjustment).
>

So I did a test, the lights came on. .L__FrameOffset_ is an assembler
directive to offset the SP according to what is pushed on the stack in a
call. In one interrupt, no pushes I get:
LPM3_EXIT;
279a: b1 c0 d0 00 bic #208, 0(r1) ;#0x00d0

And with an r15 push I get:
LPM3_EXIT;
2758: b1 c0 d0 00 bic #208, 2(r1) ;#0x00d0
275c: 02 00

I could not find a __get_SR_register_on_exit but it would look like:

#define GET_SR_ON_EXIT \
({ \
uint16_t __x; \
__asm__ __volatile__( \
"mov .L__FrameOffset_" __FUNCTION__ "(r1), r15" \
: "=r" ((uint16_t) __x) \
:); \
__x; \
})
It compiles:
GET_SR_ON_EXIT;
2790: 1f 41 02 00 mov 2(r1), r15 ;

Thanks, Dan.

On Tue, 04 Aug 2009 20:13:46 +0100, Dan Bloomquist
wrote:

> Paul Curtis wrote:
>> On Tue, 04 Aug 2009 18:31:20 +0100, Dan Bloomquist
>> wrote:
>>> (I have not used a device past 64k yet).
>>>
>>> But for a <64k device shouldn't 'if( *(int*)READ_SP & CPUOFF )' work
>>> fine?
>>> No. Consider a function with a local that is addressed--SP will
>> (usually)
>> be decremented by two on entry to the function to make a stack frame,
>> hence *SP or 2(SP) does not get you the saved SR and return address, it
>> would now be 2(SP) and 4(SP). Even worse, if in your C code you needed
>> to
>> call a function which requires arguments on the stack *and* you want to
>> read what's in the stack frame, then those 2(SP) and 4(SP) refrences
>> have
>> to change (depending on how much is currently pushed on to the stack,
>> aka
>> the stack adjustment).
>> So I did a test, the lights came on. .L__FrameOffset_ is an assembler
> directive to offset the SP according to what is pushed on the stack in a
> call. In one interrupt, no pushes I get:
> LPM3_EXIT;
> 279a: b1 c0 d0 00 bic #208, 0(r1) ;#0x00d0
>
> And with an r15 push I get:
> LPM3_EXIT;
> 2758: b1 c0 d0 00 bic #208, 2(r1) ;#0x00d0
> 275c: 02 00

This only works if the stack pointer is not adjusted after the stack frame
is created during execution of the function--a big ask.

> I could not find a __get_SR_register_on_exit but it would look like:
>
> #define GET_SR_ON_EXIT \
> ({ \
> uint16_t __x; \
> __asm__ __volatile__( \
> "mov .L__FrameOffset_" __FUNCTION__ "(r1), r15" \
> : "=r" ((uint16_t) __x) \
> :); \
> __x; \
> })

I don't believe this definition is correct; for a start, the =r constraint
assigns x to *some* register, might be r15, might not. It might work out
for some functions, but won't for others. (Why use the =r constraint if
there is no constraint in the assembly template text?)

> It compiles:
> GET_SR_ON_EXIT;
> 2790: 1f 41 02 00 mov 2(r1), r15 ;

Like I said, lucky. This time.

You are not alone in getting this wrong--even Luminary (now owned by TI)
got this stuff wrong with GCC and shipped it. I'm not sure anybody
bothered to test their broken code on GCC because Michael has spent a few
days correcting the "canned examples that just work!" that don't.

-- Paul.

The 2024 Embedded Online Conference