Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/69.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 重新定义stm32f3的初始堆栈指针值_C_Linker_Arm_Stm32_Ld - Fatal编程技术网

C 重新定义stm32f3的初始堆栈指针值

C 重新定义stm32f3的初始堆栈指针值,c,linker,arm,stm32,ld,C,Linker,Arm,Stm32,Ld,我有一个stm32f303发现板,我正试图更多地理解链接和重新定位过程。我在这里编译并运行此示例: 重置堆栈指针值在设置脚本Device/startup_stm32f0x.s的向量表中定义。原始值为0x2000A000(即初始SRAM地址+32K)。 我能看到的唯一分配给SRAM的其他内容是.data和.bss部分: 2 .data 0000004c 20000000 08000e94 00020000 2**2 CONTENTS,

我有一个stm32f303发现板,我正试图更多地理解链接和重新定位过程。我在这里编译并运行此示例:

重置堆栈指针值在设置脚本Device/startup_stm32f0x.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
所以(忽略堆栈)从地址0x200008c到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
08000c18:
8000c18:b580推送{r7,lr}
8000c1a:af00添加r7,sp,#0
8000c1c:4a1f ldr r2,[pc,#124];(8000c9c)
8000c1e:4b1f ldr r3,[pc,#124];(8000c9c)
8000c20:F8D33088 ldr.w r3[r3,#136];0x88
在这一点上,我们触发某种异常并跳转到
WWDG_IRQHandler
。ldr.w指令中r3的值为0xe000ed00,这似乎是外围设备总线上的某个东西

让我困惑的是,这段代码以及所有寄存器和内存地址在运行的原始版本中都是相同的(当然,堆栈指针值除外),包括0xe000ed00+0x88处的ldr.w内存访问。知道这是怎么回事吗?除了向量表之外,还有其他管理初始堆栈指针的方法吗?

我的建议

  • 下载一个更用户友好的IDE和体面的调试器GUI。例如Atolic studio

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

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

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

  • 您还可以将堆栈放置在CCM RAM中

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

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

  • 始终阅读完整的文档。数据表、参考手册和编程手册


  • STM32F303VCT6微控制器,在LQFP100包中具有256千字节的闪存和48千字节的RAM。您绝对不能使用0x200008C-0x40000000。您的sram从0x20000000到0x2000BFFF,如ST0xe000ed00所述,应在arm文档中。是的,已确认,它在arm文档中。有趣的DV-任何原因?心情不好或报复我认为IDE的使用与这个问题无关(我没有提到我使用哪一个IDE…),我还没有找到一个比GDB TUI更有用的gui,它也适用于桌面linux开发。但是你确实解决了我的问题,并解释了为什么它会导致我看到的异常,因此,我将把这作为公认的答案。我猜异常处理程序是由指令地址8000c18处的初始堆栈推送触发的?你知道为什么PC在4条指令之后才跳转到处理程序吗?啊,可能是因为CPU是流水线的,执行原始推送需要几个周期?将在此处指示执行推送的3个周期,因此,再加上2个用于获取和解码的周期似乎与故障处理完全一致。@MatthewHampsey这里的管道问题。它只是使高频不精确。异常到达时正在刷新管道。对于uC开发来说,良好的IDE也很重要。Atolic有许多非常方便的调试插件,如HF分析仪(它节省了大量时间)、RTOS感知调试等。