【问题标题】:Redefining initial stack pointer value for stm32f3重新定义 stm32f3 的初始堆栈指针值
【发布时间】:2020-03-09 09:03:28
【问题描述】:

我有一个 stm32f303 发现板,我正在尝试更多地了解链接和重定位过程。我在这里编译和运行这个例子:https://github.com/mblythe86/stm32f3-discovery-basic-template

复位堆栈指针值在设置脚本Device/startup_stm32f30x.s的向量表中定义。原始值为 0x2000A000(即初始 SRAM 地址 + 32K)。 我可以看到分配给 SRAM 的唯一其他内容是 .data 和 .bss 部分:

 2 .data         0000004c  20000000  08000e94  00020000  2**2
                  CONTENTS, ALLOC, LOAD, DATA
  3 .bss          00000040  2000004c  08000ee0  0002004c  2**2
                  ALLOC

所以(忽略堆栈)从地址 0x2000008c 到 0x40000000 的所有内容都应该免费供我使用,就 SRAM 而言?

我尝试在启动脚本中将初始堆栈指针值减少 32 个字节(从 0x2000A000 到 0x20009FD0),然后我们编译并运行一切正常。

我尝试将初始堆栈指针值增加 32 个字节(从 0x2000A000 到 0x2000A020)并且事情停止工作。

运行 GDB 并在 SystemInit 函数处中断,导致问题的反汇编如下所示:

08000c18 <SystemInit>:
 8000c18:   b580        push    {r7, lr}
 8000c1a:   af00        add r7, sp, #0
 8000c1c:   4a1f        ldr r2, [pc, #124]  ; (8000c9c <SystemInit+0x84>)
 8000c1e:   4b1f        ldr r3, [pc, #124]  ; (8000c9c <SystemInit+0x84>)
 8000c20:   f8d3 3088   ldr.w   r3, [r3, #136]  ; 0x88

此时我们触发某种异常并跳转到WWDG_IRQHandler。 ldr.w指令中r3的值是0xe000ed00,好像是外围设备总线上的东西?

对我来说令人困惑的部分是这部分代码以及所有寄存器和内存地址在原始版本中都是相同的(当然堆栈指针值除外),包括 ldr.w 内存访问0xe000ed00 + 0x88。知道这里发生了什么吗?除了向量表,还有什么东西可以管理初始栈指针吗?

【问题讨论】:

  • STM32F303VCT6 微控制器在 LQFP100 封装中具有 256 KB 闪存和 48 KB RAM
  • 你绝对不能使用 0x2000008c - 0x40000000
  • ST 记录的 sram 从 0x20000000 到 0x2000BFFF
  • 0xe000ed00 应该在 arm 文档中。
  • 是的,确认,它在 arm 文档中。

标签: c linker arm stm32 ld


【解决方案1】:

我的建议。

  1. 下载一个对用户更友好的 IDE,它带有不错的调试器 GUI。例如 atollic 工作室。

  2. 停止使用在网上某处找到的“模板”。这个使用史前 SPL 库 - STM 不再支持。使用 CubeMx 生成项目模板。

  3. 您有 48k 的 RAM,但分为两个不同的内存区域。 40k SRAM(0x20000000 - 0x2000A000) 和 CCM RAM (0x10000000 - 0x10002000)

  4. 根据第 3 点。SRAM 的最后一个地址是 0x2000A000,因此当您将堆栈放置在 0x2000A020 时 - 您会立即进入 HardHault 处理程序。 (这不是 WDG,因为在您的启动中,所有 HF 都由一个函数处理)

  5. 您还可以将堆栈放在 CCM RAM 中。

  6. 这是最简单的配置 - ARM 内核有 2 个供用户使用的堆栈和特权代码。

  7. 堆栈不必位于内存区域的末尾。我经常把它放在开头。当堆栈溢出时,它会调用 HF,让我有机会采取行动。如果堆栈位于 RAM 的末尾,它可能会静默溢出,覆盖存储在 RAM 中的数据

  8. 请务必阅读完整文档。数据表、参考手册和编程手册

【讨论】:

  • 有趣的 DV - 有什么理由吗?心情不好或报复
  • 我认为关于 IDE 使用的观点与问题无关(我没有提到我使用哪个 IDE...)而且我还没有找到更有用的 gui比也适用于桌面 linux 开发的 GDB TUI。但是您确实解决了我的问题并解释了为什么它会导致我看到的异常,因此我将其作为公认的答案。我猜异常处理程序是由指令地址 8000c18 处的初始堆栈推送触发的?你知道为什么 PC 直到 4 条指令后才跳转到处理程序吗?
  • 啊,可能是因为CPU是流水线的,需要几个周期才能执行原来的push?
  • infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0439b/… 表示此处执行推送需要 3 个周期,因此获取和解码的加上 2 个周期似乎与故障处理正确一致。
  • @MatthewHampsey 管道在这里很重要。它只是使 HF 不精确。异常到达时正在刷新管道。对于 uC 开发来说,好的 IDE 也很重要。 Atollic 有许多非常方便的调试插件,例如 HF 分析器(它可以节省大量时间)、RTOS 感知调试等。
猜你喜欢
  • 1970-01-01
  • 2012-07-21
  • 2016-01-21
  • 2017-09-24
  • 2022-01-27
  • 2021-11-28
  • 2016-11-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多