Cortex M3映射从0x00000000地址开始,0地址不是堆栈指针吗?能从这开始执行吗?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Cortex M3映射从0x00000000地址开始,0地址不是堆栈指针吗?能从这开始执行吗?相关的知识,希望对你有一定的参考价值。

Cortex M3映射从0x00000000地址开始

cortex-m3上电后,第一步就是去0x00000000地址中获取该内存中的数据,0x00000000地址保存的数据是栈顶地址(__initial_sp),得到这个地址后,cpu才能分配堆栈,分配堆栈是cortex-m3启动的第一步,所以要从0x00000000地址开始;

堆栈分配完后,开始执行中断向量表(0x00000004地址开始);

Cortex M3堆栈的分配是在SRAM中(即0x20000000地址开始),0x00000000地址是flash空间,用于保存BOOT/CODE代码;

所以,0x0地址不是堆栈指针,而是0x0这个地址保存着堆栈栈顶的指针;

参考技术A 不仅仅cortex m3,多数单片机都是0x000.... 是开始执行地址,系统一上电 pc指针的默认值,0x0000....这个位置上只有一条指令,就是无条件跳转,跳转到真正的程序地址 参考技术B 尽管有点晚。。。就当是为以后被这个问题困扰的孩子做贡献了。。。。我的理解是地址0是堆栈指针,下一个地址才是复位向量,M3复位后会一次读取两个字,同时读取地址0和4,是为了防止复位后一旦发生立即异常,环境依然有堆栈可以保存。 参考技术C 0x00地址就是Flash的第一个地址。MCU执行代码会从这里开始。不是堆栈的 参考技术D 不知道。。。

ARM Cortex M3上的GCC:从特定地址调用函数

我需要从特定地址(例如Double function indirection in C)调用函数,但不完全相同。我可以从映射表中提取指针并操纵动态生成的函数指针,我宁愿避免使用它们。例如,我想避免这种类型的电话:

((int)(*)(void*)) compute_volume = ((int)(*)(void*)) 0x20001000;

int vol = (*compute_volume)();

相反,我宁愿使用某种链接器提供的符号或其他方法来实现以下功能,除了compute_volume()函数由不同的图像提供,可能是这样的:

extern int compute_volume(void);

vol = compute_volume();

换句话说,我打算将我的代码分成多个图像,从而减少每次符号或计算更改时修改或覆盖闪存的需要。

有什么建议/想法吗?

答案

您可以定义跳转表,该跳转表总是位于相同的闪存区域中(您可以在我认为的代码中在链接器和编译指示中定义该区域),并在调用时跳转到所需的函数。

在固件第一部分中,您只定义了指向“传递”函数地址的符号(如果您始终将它保存在同一区域中,它将使未来的更新变得更容易)。在固件第二部分中,您将创建跳转表,该跳转表位于您在固件第I部分中引用的地址空间中并调用实际功能。

我不是100%确定我已经正确描述了它,但这应该给你一些概念如何解决你的问题。提供的环Ø应该可以帮助您将跳转表代码放在一个地方。

以上是关于Cortex M3映射从0x00000000地址开始,0地址不是堆栈指针吗?能从这开始执行吗?的主要内容,如果未能解决你的问题,请参考以下文章

stm32和cortex M3学习内核简单总结

单片机行业经常提到的M0 M1 M2 M3 M4 M7指的是啥

stm32 学习困惑

Cortex M3内核架构

ARM基础教程 | 深入 Cortex‐M3 的 Faults异常

Cortex M3处于特权模式