Home arrow Support arrow Forums

Luminary Micro Forums

<< Start < Prev 1 2 Next > End >>

blechman

Senior Boarder
Click here to see the profile of this user

2008/08/12 13:46

stack pointer access?

I am have a bug that I'm trying to track down. I need to know the PC value at the point when an interrupt occurs. In the interrupt routine I need to get the return PC from the stack correct? I'm looking through the documentation and having trouble figuring out how to access the stack pointer to retrieve and send the interrupted PC value. I am using the IAR ARM C compiler, and the LM3s618. How do I get access to the stack pointer? Which offset from the SP will the PC address be?

thanks,

Brian

login or register to reply

ravaz

Platinum Boarder
Click here to see the profile of this user

2008/08/13 11:27

Re:stack pointer access?

Yes, you must get it from the stack. Just pay attention to use the correct stack pointer. The interrupts always use the main stack pointer and the user code can use the process or the main stack pointer.

Once you know which stack pointer you user code is using you will find the PC at StackPointer + 24.

In case you must get the process stack pointer you must use the following instruction:

mrs r0, psp

This instruction will load the current process stack pointer to the register r0.

To load then the PC to the register r0 you can then use (assuming the correct stack pointer is stored in r0 before):

ldr r0, [r0, #24]


Hope can help,


Ravaz

Post edited by: ravaz, at: 2008/08/13 19:45

login or register to reply

blechman

Senior Boarder
Click here to see the profile of this user

2008/08/13 12:54

Re:stack pointer access?

Thanks ravaz,

I think your suggestion takes me in a new direction. Although I use the IAR C compiler, so I'd have to try somethig like:

__asm ("ldr R4, [SP,#24]");

to get the same result. Is MRS a thumb command? Is it supported by the cortex M3?

Though I did try the above in a serial port ineterrupt service routine, but the printout is 0x0, so that must not be correct. Basically I want to send a character to the mcu, which causes an interrupt, so the PC is saved and branges to the interrupt handler, then the handler finds that saved PC and prints it out to the serial port so I can find out where the PC was before the interrupt. Havn't gotten it yet so still open to suggestions...

by the way, wouldn't the code be:

mrs psp,r0 as opposed to msr psp,r0

How would I check to see which stack the user code is using?

Thanks agian for any help.

Brian

login or register to reply

blechman

Senior Boarder
Click here to see the profile of this user

2008/08/13 16:53

Re:stack pointer access?

Hello all... I just got the problem solved with help from Luminary's tech support:

In my ISR i used the inline assembler:

__asm("MOV r0, sp");
__asm("BL StackAccess");

to pass the Stack Pointer to a function:

void StackAccess(unsigned long *sptr)
{
printf(" pc = 0x%08Xn", sptr[6]);
}

which prints out the value of the PC (offset from the current stack pointer by 24).

I thought this was very helpful and wanted to share with all.

Thanks!

login or register to reply

ravaz

Platinum Boarder
Click here to see the profile of this user

2008/08/13 19:49

Re:stack pointer access?

Yes you are right I did a mistake on the first instruction, the one use to load the stack pointer.

Mean while you can do the following in order to load the correct stack pointer entering an interrupt (from the Cortex-m3 insider guide)

tst lr, #0x4 ; Test EXC_RETURN number in LR bit 2
ite EQ ; if zero (equal) then
mrseq R0, MSP ; Main Stack was used, put MSP in R0
mrsne R0, PSP ; else, Process Stack was used, put PSP
bl StackAccess ; call the printout routine


Regards.

login or register to reply

joseph_yiu

Senior Boarder
Click here to see the profile of this user

2008/08/14 04:41

Re:stack pointer access?

Hi Brian,

You need to be careful the inline assembler solution.
If you have local variables inside your interrupt service routine, the C compiler might adjust the stack pointer to reserve space for local variable. So when __asm("MOV r0, sp") is executed, the stack pointer value at that time might be different from the stack pointer value when the ISR is entered.

Another issue pointed out by Ravaz is that the stack frame could be on the process stack. In that case the __asm("MOV r0, sp") will not be able to get the correct stack frame because interrupt handlers use the main stack.

In general it is best to implement an assembly wrapper code to extract the correct stack point, and then past it to the C handler as a pointer. For example (only tested on ARM/KEIL tools. Not sure about the best way to code it in IAR C compiler.)

Code:

  __asm void exception_handler_asm(void) { IMPORT hard_fault_handler_c TST LR#4 ITE EQ MRSEQ R0MSP MRSNE R0PSP B exception_handler_c


In side your C handler, you can extract the stacked PC value by the pointer:
Code:

  void hard_fault_handler_c(unsigned int exception_args) {  stacked_pc = ((unsigned longexception_args[6]); }



I had put the latest version of the Cortex-M3 guide errata note in the ARM forums (http://forums.arm.com) under "Misc".

regards,
Joseph

Post edited by: joseph_yiu, at: 2008/08/14 04:43

login or register to reply
<< Start < Prev 1 2 Next > End >>