cancel
Showing results for 
Search instead for 
Did you mean: 

Using end of memory address as process stack pointer value causing INVPC hard fault.

ASay.1
Associate II

In STM32L432KC(arm cortex-m4+FPU) there are two ram memory blocks. Following is a snippet from the linker script I use.

_e_ram2_stack = ORIGIN(RAM2) + LENGTH(RAM2);
_e_ram_stack = ORIGIN(RAM ) + LENGTH(RAM );
...

RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 64K
RAM2 (xrw) : ORIGIN = 0x10000000, LENGTH = 16K

I can set main stack pointer(MSP) to use `_e_ram_stack` or `_e_ram2_stack` without problem. However when I try to set thread mode to use process stack pointer(PSP) I start to get `INVPC` hard fault on SysTick interrupt return `pop {r7, pc}` instruction.

If I subtract 112 from `_e_ram_stack` or `_e_ram2_stack`, only then I can start using PSP without problem. Something is preventing the use of end of memory address as top of the stack for PSP, but I couldn't find anything related to that in ARMv7-m architecture manual.

Following is the only change I did in the project code of STM32CubeIDE. Main program is just a dummy while(1) loop and only SysTick interrupt is enabled.

Reset_Handler:
ldr sp, =_e_ram_stack

ldr r0, =_e_ram2_stack
msr psp, r0

ldr r1, =2
msr control, r1

isb

Disassembly and register values are as following:

On SysTick interrupt handler entry:
wQkWY

 

On SysTick interrupt handler exit(`pop {r7,pc}` causes hardfault):
RCcCK

 

On Hard Fault exception entry:

3XPY1

 

1 ACCEPTED SOLUTION

Accepted Solutions
ASay.1
Associate II

In STM32L432KC data sheet in section 3.5 Embedded SRAM.

STM32L432xx devices feature 64 Kbyte of embedded SRAM. This SRAM is split into two blocks:

48 Kbyte mapped at address 0x2000 0000 (SRAM1)

16 Kbyte located at address 0x1000 0000 with hardware parity check (SRAM2). This memory is also mapped at address 0x2000 C000, offering a contiguous address space with the SRAM1

So the problem is in the linker script RAM length is given as the total of RAM1 and RAM2. And RAM2 is also mapped to be accessible after RAM1.

Linker script in the original post leads to _e_ram2_stack being equal to _e_ram_stack after mapping. So MSP and PSP is using same memory location.

The fix:

_e_ram1_stack  = ORIGIN(RAM1) + LENGTH(RAM1);
_e_ram2_stack  = ORIGIN(RAM2) + LENGTH(RAM2);
...   
RAM1   (xrw)    : ORIGIN = 0x20000000,   LENGTH = 48K # was 64K in original script
RAM2   (xrw)    : ORIGIN = 0x10000000,   LENGTH = 16K

View solution in original post

1 REPLY 1
ASay.1
Associate II

In STM32L432KC data sheet in section 3.5 Embedded SRAM.

STM32L432xx devices feature 64 Kbyte of embedded SRAM. This SRAM is split into two blocks:

48 Kbyte mapped at address 0x2000 0000 (SRAM1)

16 Kbyte located at address 0x1000 0000 with hardware parity check (SRAM2). This memory is also mapped at address 0x2000 C000, offering a contiguous address space with the SRAM1

So the problem is in the linker script RAM length is given as the total of RAM1 and RAM2. And RAM2 is also mapped to be accessible after RAM1.

Linker script in the original post leads to _e_ram2_stack being equal to _e_ram_stack after mapping. So MSP and PSP is using same memory location.

The fix:

_e_ram1_stack  = ORIGIN(RAM1) + LENGTH(RAM1);
_e_ram2_stack  = ORIGIN(RAM2) + LENGTH(RAM2);
...   
RAM1   (xrw)    : ORIGIN = 0x20000000,   LENGTH = 48K # was 64K in original script
RAM2   (xrw)    : ORIGIN = 0x10000000,   LENGTH = 16K