How to access the stack pointer from C?

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

How to access the stack pointer from C?

Jump to solution
11,953 Views
laszlomonda
Contributor IV

Hi there,

It was trivial to access the stack pointer from C for AVRs. The following code worked:

void __attribute__ ((__section__ (".init3"), __naked__)) move_sp(void) {
    SP -= sizeof(wormhole_t);
    message_ptr = (wormhole_t*)(SP + 1);
}

How can I access the stack pointer for the MK22FN512VLH12?

Thanks in advance!

- Laci

1 Solution
7,349 Views
mjbcswitzerland
Specialist V

Hi

Compiler independent C-only version for Cortex:

void *fnGetSP(void)
{
    volatile unsigned long var = 0;
    return (void *)((unsigned long)&var + 4);
}

If the variable is not set to 0 the code will generally be in-lined and result in the compiler directly generating a single instruction similar to
ADD R0, SP, #0x04

which is the SP value but I don't trust that because it may be slightly off when it optimises out the temporary variable (and the +4 may not be needed - making it compiler/optimisation dependent - although still accurate to one stack pointer location).

This code does generate a warning though because it uses the address of a temporary variable...

Regards

Mark

View solution in original post

0 Kudos
11 Replies
7,347 Views
BlackNight
NXP Employee
NXP Employee

Hi Laci,

I'm using this:

void* KIN1_GetPC(void)
{
#ifdef __GNUC__
  void *pc;

  __asm__ __volatile__ ("mov %0, pc" : "=r"(pc));
  return pc;
#else
  #warning "only for GCC"
  return NULL;
#endif
}

I hope this helps,

Erich

0 Kudos
7,348 Views
laszlomonda
Contributor IV

Thanks Erich,

Am I right that your function returns the PC, not the SP? Should I simply replace pc with sp in the assembly statement to adapt your function?

- Laci

0 Kudos
7,348 Views
laszlomonda
Contributor IV

BlackNight‌,

Your original suggestion contained pc, not sp. Can you confirm that the following is correct?

void* getSP(void)
{
    void *sp;
    __asm__ __volatile__ ("mov %0, sp" : "=r"(sp));
    return sp;
}

Alternatively, the following has also been suggested to me. I'm wondering whether it's also correct:

void* getSP(void)
{
    void *sp;
    __asm__ __volatile__ ("mrs %0, msp" : "=r"(sp));
    return sp;
}

Thank you!

- Laci

0 Kudos
7,349 Views
BlackNight
NXP Employee
NXP Employee

Hi Laci,

yes, this is what I'm using for getting the PC too.

Erich

0 Kudos
7,349 Views
laszlomonda
Contributor IV

BlackNight‌,

But which one? :smileyhappy: The 1st or the 2nd code code snippet that I pasted?

Thanks!

- Laci

0 Kudos
7,348 Views
BlackNight
NXP Employee
NXP Employee

Hi Laci,

simply try them out? :-).

I'm using the following:

void* KIN1_GetPC(void)
{
  void *pc;

  __asm__ __volatile__ ("mov %0, pc" : "=r"(pc));
  return pc;
}

Erich

7,348 Views
laszlomonda
Contributor IV

Thank you, Erich!

Usually, I can try suggested solutions, but in this case I wasn't even sure what should be the value of SP. I will make sure to use your version.

Thanks again!

- Laci

0 Kudos
7,350 Views
mjbcswitzerland
Specialist V

Hi

Compiler independent C-only version for Cortex:

void *fnGetSP(void)
{
    volatile unsigned long var = 0;
    return (void *)((unsigned long)&var + 4);
}

If the variable is not set to 0 the code will generally be in-lined and result in the compiler directly generating a single instruction similar to
ADD R0, SP, #0x04

which is the SP value but I don't trust that because it may be slightly off when it optimises out the temporary variable (and the +4 may not be needed - making it compiler/optimisation dependent - although still accurate to one stack pointer location).

This code does generate a warning though because it uses the address of a temporary variable...

Regards

Mark

0 Kudos
7,348 Views
laszlomonda
Contributor IV

Thanks Mark,

I love the simplicity of your solution, but I'm not in peace with the warning. Is there any way to disable this warning for this function?

0 Kudos
7,348 Views
mjbcswitzerland
Specialist V

Hi

Warning need to be disabled according to the compiler use - maybe a pragma can be added to quieten it.

Regards

Mark

0 Kudos
7,348 Views
bobpaddock
Senior Contributor III

Here is GCC example of how to selectively disable a warning per function.

The word 'diagnostic' may need to be replaced with 'error'.

Note that there are some warnings and errors that simply refuse to be turned off by pragma.

Using the GNU Compiler Collection (GCC): Diagnostic Pragmas 


void power_off( void )
{

USART_Shutdown();

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Winline"

POWER_OFF();

#pragma GCC diagnostic pop
}