Hi David,

What is exactly wrong with my code?

Thanks by the way for __get_PSP and all your help.

This is what it looks like on my end:
__STATIC_INLINE uint32_t __get_PSP(void)
{
  register uint32_t __regProcessStackPointer  __ASM("psp");
  return(__regProcessStackPointer);
}
in
C:\Program Files (x86)\Atmel\Atmel Toolchain\ARM
GCC\Native\4.8.1443\CMSIS_Atmel\CMSIS\Include\core_cmFunc.h

Which for me looks a lot like my code except for volatile.

Actually I already had inline asm version, but I prefer to use C if I can:
unsigned int GetStackPointer()
{
//asm volatile ("mov %0, r13" : "=l" (sp));
volatile register unsigned int sp asm("r13");
return sp;
}


So why volatile?
Because it generates smaller code:

    while (1)
    {
        unsigned int sp=GetStackPointer();
        sum+=sp;
  400270: 9b01      ldr r3, [sp, #4]
  400272: 446b      add r3, sp
  400274: 9301      str r3, [sp, #4]
  400276: e7fb      b.n 400270 <main+0xc>

Without it:

    //volatile
    register unsigned int sp asm("r13");
    return sp;
  400270: 466a      mov r2, sp
    volatile
    uint32_t sum=0;
    while (1)
    {
        unsigned int sp=GetStackPointer();
        sum+=sp;
  400272: 9b01      ldr r3, [sp, #4]
  400274: 4413      add r3, r2
  400276: 9301      str r3, [sp, #4]
  400278: e7fb      b.n 400272 <main+0xe>
the code gets bigger.


__builtin_frame_address(0) returns r7 not sp. Which should be te same, but
forces the use of r7:

  400264: b580      push {r7, lr}
  400266: b082      sub sp, #8
  400268: af00      add r7, sp, #0

My version doesn't have this:
  400264: b500      push {lr}
  400266: b083      sub sp, #12


Here's te complete test case with code size statistics, in case someone
want's to try it with different compiler versions...


#include "sam.h"

static inline unsigned int GetStackPointer() {
    volatile register unsigned int sp asm("r13");
    return sp;
}
static inline unsigned int GetStackPointerAsm() {
    register uint32_t sp;
    asm volatile ("mov %0, r13" : "=l" (sp));
    return sp;
}
static inline unsigned int GetStackPointerNV() {
    register unsigned int sp asm("r13");
    return sp;
}

__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t
GetStackPointerAsm2(void)
{
    register uint32_t result;
    __ASM volatile ("MRS %0, psp\n"  : "=r" (result) );
    return(result);
}
static inline uint32_t GetStackPointerAsm3(void)
{
    uint32_t sp;
    asm volatile("mov %0, r13" : "=r" (sp));
    return sp;
}

int main(void)
{
    SystemInit();

    volatile uint32_t sum=0;
    while (1) {
        ///                                  Program Memory Usage
        sum+=GetStackPointer();          /// 2080 bytes
        //sum+=GetStackPointerAsm();       /// 2084 bytes
        //sum+=GetStackPointerAsm2();      /// 2084 bytes
        //sum+=GetStackPointerAsm3();      /// 2084 bytes
        //sum+=GetStackPointerNV();        /// 2084 bytes
        //sum+=__get_PSP();                /// 2084 bytes
        //sum+=__builtin_frame_address(0); /// 2084 bytes
    }
}

I agree that the use of volatile is a hack, but that's the best solution I
had found back when I wrote it.


We might consider moving the discussion off the list, since it no longer
AVR related.


Best regards,
Szikra Istvan

On Thu, Nov 9, 2017 at 10:26 AM, David Brown <da...@westcontrol.com> wrote:

> On 09/11/17 04:57, Szikra Istvan wrote:
> > Hi
> >
> > Thanks for the SP, I missed that.
> > And apparently Atmel Studio also cannot find it, and underlines it with
> > red error marker.
> > It does compile, and I have found it in avr/common.h, it's probably a
> > problem with __AVR_ARCH__ handling by AS...
> > I guess that's what I get for trusting the IDE:)
> >
> > I know that just reading SP is not enough, I do also use stack
> > watermarking. It's just an additional diagnostic information.
> > Note: SP can also be used to re-mark the unused stack to trace stack
> > usage over time...
> > (or mark stack on platforms without .init* sections.)
> >
> > Note #999:
> > "the problem is in your code."
> > This isn't actually my code. My code was written for ARM and looked
> > something like this:
> > unsigned int GetStackPointer() {
> >     volatile register unsigned int sp asm("r13");
> >     return sp;
> > }
> > that someone ported to AVR, and now I'm fixing it... ;)
> >
>
> That code is wrong for the ARM too.  You should not fix a variable to an
> assembly register that is used specifically by the compiler.
>
> Depending on the ARM in question, you should probably use a CMSIS
> function like _get_PSP().  The standard definition for gcc and Cortex-M is:
>
> __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_PSP(void)
> {
>   register uint32_t result;
>
>   __ASM volatile ("MRS %0, psp\n"  : "=r" (result) );
>   return(result);
> }
>
>
> Just to read the r13 register, the code would be something like this (I
> haven't checked the details here) :
>
> static inline uint32_t GetStackPointer(void)
> {
>         uint32_t sp;
>         asm volatile("mov %0, r13" : "=r" (sp));
>         return sp;
> }
>
>
> And you can probably just use __builtin_frame_address() - that should,
> in theory, work on the AVR and the ARM (I have not tested it on either
> target).
>
>
>
>
_______________________________________________
AVR-GCC-list mailing list
AVR-GCC-list@nongnu.org
https://lists.nongnu.org/mailman/listinfo/avr-gcc-list

Reply via email to