重新定义 stm32f3 的初始堆栈指针值
Redefining initial stack pointer value for stm32f3
我有一个 stm32f303 发现板,我想更多地了解链接和重定位过程。我正在编译和 运行 此处示例:https://github.com/mblythe86/stm32f3-discovery-basic-template
重置堆栈指针值在设置脚本 Device/startup_stm32f30x.s 的向量 table 中定义。原始值为 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。知道这里发生了什么吗?除了 vector table?
之外,还有其他管理初始堆栈指针的东西吗?
我的建议。
下载更用户友好的 IDE 和不错的调试器 GUI。例如环礁工作室。
停止使用在网上某处找到的内容 "templates"。这个使用史前 SPL 库 - STM 不再支持。使用 CubeMx 生成项目模板。
你有48k的内存但是分成了两个不同的内存区域。 40k SRAM(0x20000000 - 0x2000A000) 和 CCM RAM (0x10000000 - 0x10002000)
根据第 3 点。SRAM 的最后地址是 0x2000A000,因此当您将堆栈放在 0x2000A020 时——您会立即进入 HardHault 处理程序。 (它不是 WDG,因为在您的启动中所有 HF 都由一个函数处理)
您也可以将堆栈放在 CCM RAM 中。
这是最简单的配置 - ARM 内核有 2 个堆栈供用户和特权代码使用。
堆栈不必位于内存区域的末尾。我经常把它放在开头。当堆栈溢出时,它会调用 HF,让我有机会采取行动。如果堆栈位于 RAM 的末尾,它可能会悄无声息地溢出并覆盖存储在 RAM 中的数据
始终阅读 完整文档。数据表、参考手册和编程手册
我有一个 stm32f303 发现板,我想更多地了解链接和重定位过程。我正在编译和 运行 此处示例:https://github.com/mblythe86/stm32f3-discovery-basic-template
重置堆栈指针值在设置脚本 Device/startup_stm32f30x.s 的向量 table 中定义。原始值为 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。知道这里发生了什么吗?除了 vector table?
之外,还有其他管理初始堆栈指针的东西吗?我的建议。
下载更用户友好的 IDE 和不错的调试器 GUI。例如环礁工作室。
停止使用在网上某处找到的内容 "templates"。这个使用史前 SPL 库 - STM 不再支持。使用 CubeMx 生成项目模板。
你有48k的内存但是分成了两个不同的内存区域。 40k SRAM(0x20000000 - 0x2000A000) 和 CCM RAM (0x10000000 - 0x10002000)
根据第 3 点。SRAM 的最后地址是 0x2000A000,因此当您将堆栈放在 0x2000A020 时——您会立即进入 HardHault 处理程序。 (它不是 WDG,因为在您的启动中所有 HF 都由一个函数处理)
您也可以将堆栈放在 CCM RAM 中。
这是最简单的配置 - ARM 内核有 2 个堆栈供用户和特权代码使用。
堆栈不必位于内存区域的末尾。我经常把它放在开头。当堆栈溢出时,它会调用 HF,让我有机会采取行动。如果堆栈位于 RAM 的末尾,它可能会悄无声息地溢出并覆盖存储在 RAM 中的数据
始终阅读 完整文档。数据表、参考手册和编程手册