admin管理员组文章数量:1608851
PC:Program Counter,是通用寄存器,但是有特殊用途,用来指向当前运行指令的下一条指令。
SP:Stack Pointer,堆栈指针,也是通用寄存器,用于入栈和出栈操作。
对于ARM7而言,是三级流水线结构,一条指令为4个字节大小,一条指令包含三个过程:Fetch(取指)、Decode(译指)、Execute(执行)。
CPU运行地址 = 当前PC值 = 当前程序执行位置 + 8;
对于ARM7而言,PC为R15,SP为R13。
PC不是指向正在执行的指令,而是始终指向下一个取指的指令。对于ARM7三级流水先结构和指令的三个过程,所以PC = 当前程序执行位置 + 8。
再造STM32—第十二部分:启动文件详解
https://blog.csdn/qq_38351824/article/details/89791784?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522164319801916780265483984%2522%252C%2522scm%2522%253A%252220140713.130102334…%2522%257D&request_id=164319801916780265483984&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2allsobaiduend~default-3-89791784.first_rank_v2_pc_rank_v29&utm_term=AREA++++STACK%2C+NOINIT%2C+READWRITE%2C+ALIGN%3D3&spm=1018.2226.3001.4187
STM32的中断向量表规定每一行必须是SP地址,第二行是复位中断入口地址,上电后,CPU首先就会读这两个值,分别存为SP和PC寄存器。上述流程第一行_initial_sp就是SP地址。 那么_initial_sp的值是怎么得到的呢?这是根据STM32的SRAM分配规则计算的,SRAM从规定的地址开始分别存付已初始全局和静态变量、未初化全局和静态变量、堆、栈,其中变量的长度是你写程序后就固定了,堆和栈的长度则是在启动代码中定义的,那么把它们加起来就会得于_initial_sp的值,编译后,_initial_sp就被替代为上述计算好的地址。
第二个问题,上电已经初始了SP,为什么后边又初始化堆栈?因为上电只是将_initial_sp值存入了SP寄存器,这只是一个栈顶指针,但堆的大小和栈的大小并没有初始化,所以在_main中要把在启动文件中定义好的值传给C库进行堆栈大小的初始化。无论是带系统的,还是裸机程序,都要管理堆栈的大小,这就是会产生堆栈溢出的原因。
另外,对于有MMU的系统,在进入保护模式后,地址切换到虚拟地址,还要对SP重新赋值,因为上电时的地址是实模式下真实的物理地址,而MMU是虚拟线性地址
文链接:https://blog.csdn/qq_23899395/article/details/90344731
STM32上电复位与手动复位介绍----执行复位中断处理函数
上电复位:STM32的复位引脚低电平有效,但是低电平、高电平在电气特性中有一定的范围,刚上电瞬间,复位电路电容两端没电为0V,此时复位引脚处于低电平状态,同时电容一直在充电, 当电容电压上升到一定值时,复位引脚就变成高电平。
手动复位:按下按键,电容两端和地直接相连,电容放电,放电到低电平电压时,产生复位信号
原文链接 https://blog.csdn/weixin_42957722/article/details/105029395
STM32启动过程分析
原文链接:https://blog.csdn/luobeihai/article/details/117595762
1.1 STM32的程序在flash上的存储结构
1.2 STM32的数据在SRAM上的存储结构
2. STM32启动过程概述
STM32 启动过程主要指的是,系统上电后 CPU 执行的第一条指令,到调用用户写的 main 函数的这一段过程。具体启动过程的步骤和所完成的工作是:
(1) 上电复位,硬件设置 SP、PC 的值
(2) 找到了 Reset_Handler 的地址后,CPU 就从这里开始取指令运行程序;
(3) 调用 SystemInit 函数,设置系统时钟;
(4) 调用 __main 函数,软件对 SP 寄存器赋值,完成数据段的重定位、清除 bss 段,初始化栈空间等工作;
(5) 最终 __main 函数会调用用户的 main 函数,进入到用户程序
对于 Cortex-M3 内核,ARM 规定向量表的起始位置存放的是栈顶指针 MSP 的地址值,紧接着存放的是复位中断入口函数的地址。当刚上电的时候,硬件会根据向量表的地址找到向量表的具体位置(对于向量表的地址是可以通过 NVIC 中的一个重定位寄存器来设置的,复位时该寄存器的值为0),然后会根据向量表中的这两个数据,设置 SP、PC 的值,这时 CPU 就会从复位中断的入口函数开始取指令运行程序
汇编指令
import,标识符表明要调用的函数为本模块外部定义的
export,标识符表示本模块中定时的符号可以为外部模块使用
DCD
数据定义( Data Definition )伪指令
数据定义伪指令一般用于为特定的数据分配存储单元,同时可完成已分配存储单元的初始化。
DCD ( DCDU ) 用于分配一片连续的字存储单元并用指定的数据初始化。
汇编proto、proc、invoke伪指令与函数声明、函数定义、函数调用
一、proto伪指令–函数声明
功能和高级语言中的函数声明一样,在代码最前面写函数声明,在后面写函数定义
proto伪指令的格式
函数名 proto [距离] [语言] [参数1]:数据类型,[参数2]:数据类型,……
代码示例:
Asm_Function_1 proto stdcall arg1:dword,arg2:dword
二、proc伪指令–函数定义
使用proto指令用来函数声明,使用proc函数用来函数定义。使用规则和proto指令一样
代码示例:
proc stdcall arg1:dword,arg2:dword
函数体代码块...
Asm_Function_1 endp
注意事项:
函数定义语句和proto一样,写完函数体代码之后需要以[函数名] endp结束函数定义
但proc和proto搭配使用时,proto可以省略参数名,但proc不能省略。(和C中的规则一模一样)
三、invoke伪指令–函数调用
使用invoke伪指令会帮你完成参数校检和压参操作,也就是说不用写压参的push指令。直接和高级语言一样直接调用函数即可
invoke伪指令的格式
invoke 函数名[,参数1][,参数2]……
代码示例:
invoke Asm_Function_1,100,0x100
注意事项:
函数名称和参数,参数和参数之间都用 空格 隔开
原文链接:https://blog.csdn/u011770174/article/details/77914375
https://wwwblogs/yangguang-it/p/6746065.html
启动文件由汇编编写,是系统上电复位后第一个执行的程序。主要做了以下工作:
1、 初始化堆栈指针 SP=_initial_sp (差点把初始化堆栈指针跟初始化堆栈搞混·)
2、 初始化 PC 指针=Reset_Handler
3、 初始化中断向量表
4、 配置系统时钟
5、 调用 C 库函数_main 初始化用户堆栈,从而最终调用 main 函数去到 C 的世界
WEAK:表示弱定义,如果外部文件优先定义了该标号则首先引用该标号,如果外部
文件没有声明也不会出错。这里表示复位子程序可以由用户在其他文件重新实现,这里并
不是唯一的。
IMPORT:表示该标号来自外部文件,跟 C 语言中的 EXTERN 关键字类似。这里表
示 SystemInit 和__main 这两个函数均来自外部的文件。
SystemInit()是一个标准的库函数,在 system_stm32f4xx.c 这个库文件总定义。主要作
用是配置系统时钟,这里调用这个函数之后, F429 的系统时钟配被配置为 180M。
__main 是一个标准的 C 库函数,主要作用是初始化用户堆栈,最终调用 main 函数去
到 C 的世界。这就是为什么我们写的程序都有一个 main 函数的原因。如果我们在这里不
调用__main,那么程序最终就不会调用我们 C 文件里面的 main,如果是调皮的用户就可以
修改主函数的名称,然后在这里面 IMPORT 你写的主函数名称即可。
你可能会说,_main函数我们也没有写啊,为什么不报错,这个_main函数是MDK编译器自动给我生成的,不用用户操心。
在启动文件里面已经帮我们写好所有中断的中断服务函数,跟我们平时写的中断服务
函数不一样的就是这些函数都是空的,真正的中断复服务程序需要我们在外部的 C 文件里
面重新实现,这里只是提前占了一个位置而已。
如果我们在使用某个外设的时候,开启了某个中断,但是又忘记编写配套的中断服务
程序或者函数名写错,那当中断来临的时,程序就会跳转到启动文件预先写好的空的中断
服务程序中,并且在这个空函数中无线循环,即程序就死在这里。
下面这段话引用自《 CM3 权威指南 CnR2》 3.8—复位序列,CM4 的复位序列跟 CM3 一样。 —秉火
注。
在离开复位状态后, CM3 做的第一件事就是读取下列两个 32 位整数的值:
1、 从地址 0x0000,0000 处取出 MSP 的初始值。
2、 从地址 0x0000,0004 处取出 PC 的初始值——这个值是复位向量, LSB 必须是1。 然后从这个值所 对应的地址处取指。
版权声明:本文标题:stm32的启动文件详解 Reset_Handler做了什么工作 疑问--初始化pc指针的操作在哪里 ---硬件设置SP 和 PC的值 内容由热心网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:https://m.elefans.com/dianzi/1728553975a1163614.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论