manually write to stack

キャンセル
次の結果を表示 
表示  限定  | 次の代わりに検索 
もしかして: 

manually write to stack

ソリューションへジャンプ
999件の閲覧回数
dementeddigital
Contributor II

I'm working on a module to monitor the stack usage in my KE06 project (in KDS).  The concept is:

 

To detect the peak stack usage, the initialization function writes 0x00 to each unused memory location in the stack.  It writes from the bottom of the stack up to the stack pointer.  Then when the stack monitor function is called, it goes through the stack and it counts the locations still with 0x00 (presumably these were unused).  It calculates the percentage of the stack used and saves this in a variable for “live” viewing via CAN.  This same strategy is used (and works well) on other projects.  I’m getting a hard fault here during the initialization, however.

 

In the debugger, the stack pointer resolves correctly.  I get one single write to the bottom of the stack, and on the second write it hard faults.  Any thoughts as to why?

 

#define STACK_START_ADDR              0x20002C00  // MCU stack starting address

#define STACK_TOP_ADDR                0x20003000  // MCU stack top address (see Memory mapping)

#define STACK_ERASED_VALUE            0x00        // Value used to identify erase stack memory

 

void STACK_Initialize( void )

{

    uint32 u32Addr;

      register uint32 sp asm ("sp");

    for ( u32Addr=STACK_START_ADDR; u32Addr < sp; u32Addr++ )  // Fill unused stack with erased values

    {

        *(uint32*)u32Addr = STACK_ERASED_VALUE;   //<----hard faults here the the second time through the loop

    }

}

 

1 解決策
842件の閲覧回数
ndavies
Contributor V

I'm not sure if this is your issue:

Your for loop isn't doing what you expect. You have incorrectly used the pointer.  You have defined uint32 u32Addr. It should be defined as uint32 *u32Addr. Without the * in the definition, u32Addr is only incremented by one during the u32Addr++ in the for loop. By adding the * to the definition, the compiler then understands u32Addr is a pointer and gets incremented by 4 when you do the post increment in the for loop. It should also remove the need for the cast in the for loops assignment.

Your for loop will cause 4 times as many writes as needed, misaligned writes for 3 out of 4 of the writes and corrupts your stack on the last 2 or 3 writes. You are doing a 4 byte write but only incrementing the not properly defined pointer by 1 byte.

元の投稿で解決策を見る

3 返答(返信)
843件の閲覧回数
ndavies
Contributor V

I'm not sure if this is your issue:

Your for loop isn't doing what you expect. You have incorrectly used the pointer.  You have defined uint32 u32Addr. It should be defined as uint32 *u32Addr. Without the * in the definition, u32Addr is only incremented by one during the u32Addr++ in the for loop. By adding the * to the definition, the compiler then understands u32Addr is a pointer and gets incremented by 4 when you do the post increment in the for loop. It should also remove the need for the cast in the for loops assignment.

Your for loop will cause 4 times as many writes as needed, misaligned writes for 3 out of 4 of the writes and corrupts your stack on the last 2 or 3 writes. You are doing a 4 byte write but only incrementing the not properly defined pointer by 1 byte.

842件の閲覧回数
dementeddigital
Contributor II

Yes, this is exactly the issue.  I found it yesterday just before I went home, and your comment confirms it.

I fixed it by incrementing by 4 in the loop, but I see now _why_ the compiler didn't handle it the way I wanted.  I'll adjust the pointer definition and go back to incrementing by 1.

Thanks for the reply!  Very helpful!

0 件の賞賛
842件の閲覧回数
bobpaddock
Senior Contributor III

Are interrupts turned off?

Using the correct stack for your part?

For GCC:
static __inline__ void *sp_get(void)
{
void *sp;

__asm__ __volatile__ ("mrs %0, msp" : "=r"(sp));

return( sp );
}

Replace msp with psp if using other stack.

A version in pure C that makes Lint explode for returning the address of a local variable:

/*
* void *CheckStackDepth( void )
* {
* volatile uint32_t dummy; // Put a variable on the stack
* return( (void *) &dummy ); // Return its address - therefore the (approx.) present SP value
* }
*/

Obscure GCC syntax for setting Link and Stack pointers:


static __inline__ void psp_set( void *setval )
{
__asm__ volatile ("msr psp, %[value]\n\t""dmb\n\t""dsb\n\t""isb\n\t"::[value]"r"(setval):);
__asm__ volatile ("" ::: "memory");
}

static __inline__ void lr_set(uint32_t setval)
{ __asm__ volatile ("mov lr, %[value]\n\t"::[value]"r"(setval):);
__asm__ volatile ("" ::: "memory");
}

Unless debugging is an obsession disable interrupts when doing any of the above operations:

See atomic.h.zip in this tread for the GCC ARM code to do save/restore of the IRQ state.

https://community.nxp.com/message/816609?commentID=816609#comment-816609 

0 件の賞賛