使用内存地址末尾作为进程堆栈指针值导致 INVPC 硬故障

问题描述 投票:0回答:1

在STM32L432KC(arm cortex-m4+FPU)中有两个RAM内存块。以下是我使用的链接器脚本的片段。

_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

我可以设置主堆栈指针(MSP)来使用

_e_ram_stack
_e_ram2_stack
,没有问题。然而,当我尝试设置线程模式以使用进程堆栈指针(PSP)时,我开始在 SysTick 中断返回
INVPC
指令上遇到
pop {r7, pc}
硬故障。

如果我从

_e_ram_stack
_e_ram2_stack
中减去112,那么我就可以毫无问题地开始使用PSP。有些东西阻止使用内存结束地址作为 PSP 的堆栈顶部,但我在 ARMv7-m 架构手册中找不到与此相关的任何内容。

以下是我在STM32CubeIDE的项目代码中所做的唯一更改。主程序只是一个虚拟的 while(1) 循环,并且仅启用 SysTick 中断。

Reset_Handler:
  ldr   sp, =_e_ram_stack

  ldr r0, =_e_ram2_stack
  msr psp, r0

  ldr r1, =2
  msr control, r1

  isb

拆解及寄存器值如下:

在 SysTick 中断处理程序入口:

SysTick 中断处理程序退出时(

pop {r7,pc}
导致硬故障):

硬故障异常条目:

stm32 armv7 stack-pointer hardfault
1个回答
0
投票

STM32L432KC 数据手册第 3.5 节嵌入式 SRAM。

STM32L432xx 器件具有 64 KB 嵌入式 SRAM。这个静态随机存储器是 分成两块:

48 KB 映射到地址 0x2000 0000 (SRAM1)

16 KB 位于地址 0x1000 0000,带硬件奇偶校验 (静态随机存储器2)。该内存也映射到地址 0x2000 C000,提供 与 SRAM1 的连续地址空间

所以问题出在链接描述文件中,RAM 长度是 RAM1 和 RAM2 的总和。 RAM2 也被映射为在 RAM1 之后可访问。

原帖中的链接器脚本导致映射后

_e_ram2_stack

 等于 
_e_ram_stack
。所以 MSP 和 PSP 使用相同的内存位置。

修复:

_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
    
© www.soinside.com 2019 - 2024. All rights reserved.