浅析STM32H750启动文件

news2024/11/26 18:47:44

目录

概述

1 启动文件介绍

1.1 启动文件功能

1.2 汇编语言指令

 2 启动代码细节

2.1 分配栈空间

 2.2 分配堆空间

2.3 中断向量表

 2.4 复位程序

2.5 中断服务程序

2.5.1 CPU内部中断程序

2.5.2 CPU内部扩展中断程序

 2.6 用户堆栈初始化

3 总结


概述

本文以startup_stm32h750xx.s为例,介绍stm32h750的启动代码的内容,本文对启动的每一个环节实现的功能做了简要分析,了解ARM CM7内核是如何从启动代码中跳到用户程序中,执行用户程序。

1 启动文件介绍

1.1 启动文件功能

启动文件由汇编编写,是系统上电复位后第一个执行的程序。主要做了以下工作:

1)初始化堆栈指针SP=_initial_sp

2)初始化PC指针=Reset_Handler

3)初始化中断向量表

4)配置系统时钟

5)调用C库函数_main初始化用户堆栈,最终跳到C语言代码段

1.2 汇编语言指令

指令名称

作用

EQU

给数字常量取一个符号名,相当于C语言中的define

AREA

汇编一个新的代码段或者数据段

SPACE

分配内存空间

PRESERVE8

当前文件堆栈需按照8字节对齐

EXPORT

声明一个标号具有全局属性,可被外部的文件使用

DCD

以字为单位分配内存,要求4字节对齐,并要求初始化这些内存

PROC

定义子程序,与ENDP成对使用,表示子程序结束

WEAK

弱定义,如果外部文件声明了一个标号,则优先使用外部文件定义的标号, 如果外部文件没有定义也不出错。要注意的是:这个不是ARM的指令,是 编译器的,这里放在一起只是为了方便。

IMPORT

声明标号来自外部文件,跟C语言中的EXTERN关键字类似

B

跳转到一个标号

ALIGN

编译器对指令或者数据的存放地址进行对齐,一般需要跟一个立即数,缺省 表示4字节对齐。要注意的是:这个不是ARM的指令,是编译器的,这里 放在一起只是为了方便

END

到达文件的末尾,文件结束

IF,ELSE,ENDIF

汇编条件分支语句,类似C语言的if else

 2 启动代码细节

2.1 分配栈空间

代码第32~34行:

开辟栈的大小为0x400(1KB),名字为STACK,NOINIT即不初始化,可读可写,8(2^3)字节对齐。栈的作用是用于局部变量,函数调用,函数形参等的开销,栈的大小不能超过内部SRAM的大小。如果编写的程序比较大,定义的局部变量很多,那么就需要修改栈的大小。如果某一天,你写的程序出现了莫名奇怪的错误,并进入了硬fault的时候,这时你就要考虑下是不是栈不够大,溢出了。

 2.2 分配堆空间

代码第43~51行:

开辟堆的大小为0x200(512字节),名字为HEAP,NOINIT即不初始化,可读可写,8(2^3)字节对齐。

__heap_base: 表示对的起始地址

__heap_limit: 表示堆的结束地址, 堆是由低向高生长的,跟栈的生长方向相反

2.3 中断向量表

代码第54~58行:

定义一个数据段,名字为RESET,可读。并声明 __Vectors、__Vectors_End和__Vectors_Size这三个标号具有全局属性,可供外部的文件调用。

代码第230行:

__Vectors为向量表起始地址,__Vectors_End 为向量表结束地址,两个相减即可算出向量表大小。

 2.4 复位程序

代码第234~245行:

复位子程序是系统上电后第一个执行的程序,调用SystemInit()函数初始化系统时钟,然后调用C库函数_mian(),最终调用main函数去到C的世界。

WEAK:表示弱定义,如果外部文件优先定义了该标号则首先引用该标号,如果外部文件没有声明也不会出错。 这里表示复位子程序可以由用户在其他文件重新实现,这里并不是唯一的。

IMPORT:表示该标号来自外部文件,和C语言中的EXTERN关键字类似。这里表示SystemInit和__main这两个函数均来自外部的文件。

SystemInit()是一个标准的库函数,在system_stm32f7xx.c这个库文件中定义。主要作用是配置系统时钟,这里调用这个函数之后,配置系统时钟。

__main是一个标准的C库函数,主要作用是初始化用户堆栈,最终调用main函数调到C语言中。这就是为什么写的程序都有一个main函数的原因。 如果在这里不调用__main,那么程序最终就不会调用我们C文件里面的main,如果是调皮的用户就可以修改主函数的名称, 然后在这里面IMPORT你写的主函数名称即可。

2.5 中断服务程序

2.5.1 CPU内部中断程序

2.5.2 CPU内部扩展中断程序

在启动文件里定义中断服务函数,其是一个weak函数,真正的中断复服务程序需要在外部的C文件里面重新实现,这里只是提前占了一个位置而已。

代码292~434行: 定义所有的外部中断函数名

 2.6 用户堆栈初始化

代码587~596行:判断是否定义了__MICROLIB ,如果定义了则赋予标号__initial_sp(栈顶地址)、__heap_base(堆起始地址)、__heap_limit(堆结束地址)全局属性,可供外部文件调用。如果没有定义(实际的情况就是我们没定义__MICROLIB)则使用默认的C库,然后初始化用户堆栈大小,这部分有C库函数__main来完成,当初始化完堆栈之后,就调用main函数去到C的世界。

代码606行:对指令或者数据存放的地址进行对齐,后面会跟一个立即数。缺省表示4字节对齐

代码610行:文件结束

3 总结

ARM Cortex-M7(CM7)内核的启动流程如下:

  1. 复位向量表:当系统复位时,程序计数器(PC)被设置为复位向量表的起始地址。复位向量表包含一系列指令地址,用于初始化处理器和引导操作系统。

  2. 复位处理:在复位向量表中,第一个指令的地址是复位处理程序的入口点。复位处理程序执行一系列初始化操作,包括初始化处理器和外设。

  3. 初始化堆栈指针:在复位处理程序中,堆栈指针(SP)被初始化为堆栈的起始地址。堆栈用于存储函数调用时的局部变量和返回地址。

  4. 初始化全局指针:在复位处理程序中,全局指针(GP)被初始化为全局变量的起始地址。全局变量存储在数据段中,可以被程序的任何部分访问。

  5. 初始化中断向量表:中断向量表包含一系列中断处理程序的入口点。在复位处理程序中,中断向量表被初始化为默认的中断处理程序入口点。后续可以通过修改中断向量表的内容来注册新的中断处理程序。

  6. 启用中断:在复位处理程序中,中断控制器(例如NVIC)被初始化并使能中断。使能中断后,当发生中断时,处理器会跳转到相应的中断处理程序并执行。

  7. 进入主程序:完成上述初始化操作后,处理器会跳转到主程序的入口点,开始执行应用程序的代码。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1606796.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

GreatSQL 死锁案例分析

1.背景概述 客户业务发生死锁的报错,根据业务程序日志及业务流程,发现造成死锁的原因是:事务1 delete insert ,事务2 delete insert 2个事务交替执行导致的死锁;由于GAP锁阻塞了插入意向锁,并且当delete…

基于1-wire总线的多路温度监测系统

前言 在现代工业生产和环境监测中,温度是一个关键的参数,它直接影响到生产过程的稳定性和产品质量。为了确保温度控制在安全和有效的范围内,需要一种可靠且高效的多路温度监测系统。随着微电子技术和传感器技术的发展,基于1-Wire…

Redis中的订阅发布(二)

订阅与发布 订阅频道 每当客户端执行SUBSCRIBE命令订阅某个或某些频道的时候,服务器都会将客户端与被订阅的频道 在pubsub_channels字典中进行关联。 根据频道是否已经有其他订阅者,关联操作分为两种情况执行: 1.如果频道已经有其他订阅者&#xff0c…

从零实现诗词GPT大模型:数据集介绍和预处理

专栏规划: https://qibin.blog.csdn.net/article/details/137728228 本章将介绍该系列文章中使用的数据集,并且编写预处理代码,处理成咱们需要的格式。 一、数据集介绍 咱们使用的数据集名称是chinese-poetry,是一个在github上开源的中文诗…

雨润万物生,酒伴谷雨行

谷雨,是中国传统二十四节气之一 标志着中国农历的春季即将结束,夏季即将来临。在古代中国, 谷雨时节是农民开始播种、收获的时节,也是酿酒的好季节。谷雨时节,气温适宜、湿度较高,是酵母繁殖和发酵的好时候。 谷雨时节酿酒不仅仅是普通人们…

37-2 Python 的 requests 库发送 POST 请求

准备 sqlilabs 靶场: 构建完善的安全渗透测试环境:推荐工具、资源和下载链接_渗透测试靶机下载-CSDN博客 一、发送 POST 请求 首先使用bp对 sqlilabs 靶场的第12关抓个包,了解这个关卡是如何发包的 打开靶场:本地ip+ /sqli-labs-master/Less-12/ 先随便输入个账号登录如…

Postman之页面简介 V9.31.0

Postman之页面简介 V9.31.0 一、顶部栏二、左部栏三、中部栏四、下部栏 一、顶部栏 (1)new选项框,生成新建请求、集合、环境等 (2)import选项框,可以导入文件、文件夹、链接、文本信息等 (3&…

(2022级)成都工业学院数据库原理及应用实验四: SQL简单查询

写在前面 1、基于2022级软件工程/计算机科学与技术实验指导书 2、成品仅提供参考 3、如果成品不满足你的要求,请寻求其他的途径 运行环境 window11家庭版 Navicat Premium 16 Mysql 8.0.36 实验要求 在实验三的基础上完成下列查询: 1、查询所有…

穿越物联网的迷雾:深入理解MQTT协议

目录标题 1、MQTT简介核心特性 2、MQTT的工作原理通信过程 3、MQTT的消息质量(QoS)4、安全机制5、实践应用环境准备示例项目发布者客户端订阅者客户端 6、最佳实践7、结论8、参考资料 在物联网(IoT)的海洋中,数据像水流…

【ACM列表推荐会议 | EI稳定检索】2024年第四届人工智能、自动化与高性能计算国际会议(AIAHPC 2024)

2024年第四届人工智能、自动化与高性能计算国际会议(AIAHPC 2024) 2024 4th International Conference on Artificial Intelligence, Automation and High Performance Computing 2024第四届人工智能、自动化与高性能计算国际会议(AIAHPC 2024)将于20…

二叉树的最大深度 - LeetCode 热题 37

大家好!我是曾续缘😛 今天是《LeetCode 热题 100》系列 发车第 37 天 二叉树第 2 题 ❤️点赞 👍 收藏 ⭐再看,养成习惯 二叉树的最大深度 给定一个二叉树 root ,返回其最大深度。 二叉树的 最大深度 是指从根节点到最…

麒麟服务器操作系统自动化安装应答文件制作

原文链接:麒麟服务器操作系统自动化安装应答文件制作 Hello,大家好啊!今天我们将探讨如何为麒麟服务器操作系统制作自动化安装应答文件。在部署大量服务器时,自动化安装是提高效率和确保安装一致性的关键技术。通过使用应答文件&a…

【计算机网络】ip子网划分--超详细例题解析

Hello!这一篇主要是计算机网络中的ip地址子网划分的例题,这里例举了四个题型。保证即便从0也可以掌握!(前面是一些预备知识,不熟悉的小伙伴一定要看下学习下哦~) 这也是博主的学习过程,做题中仅仅我的理解哦。若文章中…

【k8s】:kubectl 命令设置简写启用自动补全功能

【k8s】:kubectl 命令设置简写&启用自动补全功能 1、设置kubectl命令简写2、启用kubectl自动补全功能 💖The Begin💖点点关注,收藏不迷路💖 Kubernetes(K8s)是一个强大的容器编排平台&#…

Grid Controller

完整、易于使用的基于网格的第一人称控制器,具有《格里姆洛克传奇》、《地下城大师》和《巫师》的风格。 网格控制器是一种基于网格的第一人称控制器,设置简单,但具有鲁棒性和通用性。不需要脚本。 特征: 实时或基于回合的移动 平滑移动或即时捕捉到网格位置 倾斜、下降和蹲…

DevOps(七)Jenkins发布第一个流水线任务

Jenkins的流水线(Pipeline)是一种强大的工具,用于定义和管理持续集成和持续交付(CI/CD)过程。它允许你以代码的形式(即"Pipeline as Code")定义整个构建、测试和部署流程,…

Linux中用户通过系统调用实现硬件驱动全流程

驱动全流程: 以基于设备树、Pinctrl、gpio子系统,打开一个字符设备为例: 1、通过系统调用open进入内核 当我们在用户空间调用open之后,应用程序会使用系统调用指令(在上图中可看到,ARM架构中软中断汇编指…

浏览器工作原理与实践--浏览上下文组:如何计算Chrome中渲染进程的个数

经常有朋友问到如何计算Chrome中渲染进程个数的问题,那么今天就来完整地解答这个问题。 在前面“04 | 导航流程”这一讲中我们介绍过了,在默认情况下,如果打开一个标签页,那么浏览器会默认为其创建一个渲染进程。不过我们在“04 |…

搜维尔科技:【工业仿真】煤矿机械安全事故VR警示教育系统

产品概述 搜维尔科技 煤矿机械安全事故VR警示教育系统 系统内容: 系统采用虚拟现实技术模拟矿井井下机械安全技术及事故,展现井下常见机械伤害事故,表现伤害事故的隐患点,能够模拟事故发生和发展过程;营造井下灾害发…

C#基于SSE传递消息给Vue前端实现即时单向通讯

一、简述 通常前端调用后端的API,调用到了,等待执行完,拿到返回的数据,进行渲染,流程就完事了。如果想要即时怎么办?如果你想问什么场景非要即时通讯,那可就很多了,比如在线聊天、实…