How to access the stack pointer from C?

取消
显示结果 
显示  仅  | 搜索替代 
您的意思是: 
已解决

How to access the stack pointer from C?

跳至解决方案
12,210 次查看
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 解答
7,606 次查看
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 项奖励
11 回复数
7,604 次查看
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 项奖励
7,605 次查看
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 项奖励
7,605 次查看
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 项奖励
7,606 次查看
BlackNight
NXP Employee
NXP Employee

Hi Laci,

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

Erich

0 项奖励
7,606 次查看
laszlomonda
Contributor IV

BlackNight‌,

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

Thanks!

- Laci

0 项奖励
7,605 次查看
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,605 次查看
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 项奖励
7,607 次查看
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 项奖励
7,605 次查看
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 项奖励
7,605 次查看
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 项奖励
7,605 次查看
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
}