简单说明芯片的启动过程和程序执行过程

news2024/11/24 15:37:15

目录

1.芯片启动过程

2.启动代码

2.1 堆栈定义

2.2 向量表

2.3 复位程序

2.4 中断服务程序

3. 程序执行的过程

4.数据的存取


1.芯片启动过程

芯片启动是上电后先运行芯片内部的固有程序(也就是启动代码)。启动代码程序建立完运行环境之后,就会去读串口状态,就是用户下载程序用到的各个端口,判断用户是否正在使用端口准备下载程序。

如果用户正在下载程序,就按照用户要求,把用户程序下载到指定地址上。如果没有下载程序,芯片默认跳转到已有的用户程序入口,从而把芯片控制权交给用户程序。如果是没有用户程序的新芯片,则停留在读取串口状态的循环中。

启动代码通常都写在flash中,是系统一上电就执行的一段程序。它运行在任何用户C代码之前。上电之后,arm处理器处于arm态,运行于特权模式,同时系统所有中断被禁止,PC到地址0处取指令执行。

我们以Flash启动模式为例。上电后,地址0x0800 0000开始的程序被映射到地址0x0000 0000,然后程序从0x0000 0000开始执行。芯片会从地址0x0000 0000读取32位长度的值,并赋值给栈指针SP;然后从地址0x0000 0004读取32位长度的值复制给程序计数器指针PC,程序将会从PC指针内容处开始执行。

启动代码主要完成两方面的工作,一是初始化执行环境,例如中断向量表、堆栈、I/O等;二是初始化c库和用户应用程序。

2.启动代码

以STM32为例,我们来看一下从芯片上电到main函数的过程。主要步骤如下:

1. 初始化堆栈指针SP=_initial_sp,初始化PC=Reset_Handler

2. 初始化中断向量表

3. 配置系统时钟

4. 调用C库函数__main初始化用户堆栈,然后进入main函数

因为启动过程主要是由汇编完成的,因此STM32的启动的大部分内容都是在启动文件里。现在以startup_stm32f103xe.s为例(其他类型的启动文件原理是类似的)。

2.1 堆栈定义

1. 栈Stack

栈的作用是用于局部变量、函数调用、函数形参等保存,栈的大小不能超过内部SRAM的大小。当程序较大时,需要修改栈的大小,不然可能会出现HardFault的错误。

第33行:表示栈的大小为0x00000400(1KB),EQU是伪指令,相当于C中的define。

第35行:开辟一段可读可写数据空间,ARER伪指令表示下面将开始定义一个代码段或数据段。此处是定义数据段。ARER后面的关键字表示这个段的属性。段名为STACK,可以任意命名;NOINIT表示不初始化;READWRITE表示可读可写,ALIGN=3,表示按照8字节对齐。

第36行:SPACE用于分配带大小等于Stack_Size连续内存空间,单位为字节。

第37行:__initial_sp表示栈顶地址。栈是由高向低生长的。

2. Heap堆

堆主要用来动态内存的分配,像malloc()函数申请的内存就在堆中。

 开辟堆的大小为0x00000200(512字节),名字为HEAP,NOINIT即不初始化,可读可写,8字节对齐。__heap_base表示对的起始地址,__heap_limit表示堆的结束地址。

2.2 向量表

向量表是一个WORD(32位整数)数组,每个下标对应一种异常,该下标元素的值则是该ESR的入口地址。向量表在地址空间中的位置是可以设置的,通过NVIC中的一个重定位寄存器来指出向量表的地址。在复位后,该寄存器的值为0。因此,在地址0(即FLASH地址0)处必须包含一张向量表,用于初始化时的异常分配。值得注意的是这里有个另类:0号类型并不是什么入口地址,而是给出了复位后MSP的初值,后面会具体讲解。

第55行:定义一块代码段,段名字是RESET,READONLY表示只读。

第56-58行:使用EXPORT将3个标识符声明为可被外部引用,声明__Vectors、__Vectors_End和__Vectors_Size具有全局属性。

第60行:__Vectors表示向量起始地址,DCD表示分配1个4字节的空间。每行DCD都会生成一个4字节的二进制代码,中断向量表存放的实际上是中断服务程序的入口地址。当异常(也就是中断事件)发生时,CPU的中断系统会将相应的入口地址赋值给PC程序计数器,之后就开始执行中断服务程序。在60行之后,依次定义了中断服务程序的入口地址。

 第138行:__Vectors_End为向量表结束地址。

第139行:__Vectors_Size是向量表的大小,向量表的size由__Vectors_End减去__Vectors得到。

2.3 复位程序

复位程序是系统上电后执行的第一个程序,复位程序也是中断程序,只是比较特殊,所以特意单讲一下。

第 145行:定义了一个服务程序,PROC表示程序的开始。

第146行:使用EXPORT将Reset_Handler声明为可被外部引用,后面[WEAK]表示弱定义。弱定义的函数可以在外部文件重新定义,此时则使用外部文件定义的函数,如果外部文件没有定义,则引用此处定义的[WEAK]函数。这里也就是表示复位程序可以被用户在其他文件重新实现。这种写法在HAL库中是很常见的。

第147-148行:表示引用两个来自外部文件的标号,其中__main是一个标准的C库函数,主要用于初始化用户堆栈。这个由编译器完成,该函数最终会调用我们写的main函数,从而进入到我们的系统中。SystemInit()是一个库函数,主要用于 系统时钟配置和中断相关配置。

第149行:将SystemInit的地址从存储器中加载到寄存器R0中

第150行:跳转到R0中的地址(也就是SystemInit函数),并根据寄存器的LSE确定处理器的状态,还要把跳转前的下一条指令地址保存到LR。

第151-152行:同上面两行,从存储器中取出__main的地址加载到R0里,并跳转到R0中的地址去。152和150不同的是152行跳转到指定寄存器的地址后,不会返回。

第153行:和PROC对应,表示程序结束。

2.4 中断服务程序

平时要使用哪个中断,只需要编写相应的中断服务程序,只是启动文件把这些函数留出来了,但是内容是空的,真正的中断服务程序需要我们在外部的C文件里面重新实现,这里只是提前占了一个位置而已。

这部分没有需要讲的,和服务程序类似的,只需要注意'B.'语句,B表示跳转,这里跳转到一个'.',即表示无线循环。 

3. 程序执行的过程

单片机的程序运行过程分为取指令、分析指令和执行指令几个步骤。

(1)取指令:根据程序计数器PC中的值从程序存储器中读出指令,送到指令寄存器。

(2)分析指令:将指令寄存器中的指令操作码取出后进行译码,分析其指令性质。如指令要求操作数,则寻找操作数指令。

(3)执行指令:无非是把一条二进制代码,转换成数字信号(高低电平),操作逻辑门电路,就像我们的加法器一样输入输出。把经过逻辑门运算的结果输出,把单片机的相关引脚电平输出高或低。

单片机执行程序的过程实际上就是逐条指令地重复上述操作过程,直到遇到停机指令可循环等待指令。

例如:

开机时,程序计算器PC变为0000H。然后单片机在时序电路作用下自动进入执行程序过程。执行过程实际上就是取出指令(取出存储器中事先存放的指令阶段)和执行指令(分析和执行指令)的循环过程。

例如执行指令:MOV A,#0E0H,其机器码为74H E0H,该指令的功能是把操作数E0H送入累加器,0000H单元中已存放74H0001H单元中已存放E0H。当单片机开始运行时,首先是进入取指阶段,其次序是:

  • 程序计数器的内容(这时是0000H)送到地址寄存器;

  • 程序计数器的内容自动加1(变为0001H);

  • 地址寄存器的内容(0000H)通过内部地址总线送到存储器,以存储器中地址译码电跟,使地址为0000H的单元被选中;

  • CPU使读控制线有效;

  • 在读命令控制下被选中存储器单元的内容(此时应为74H)送到内部数据总线上,因为是取指阶段,所以该内容通过数据总线被送到指令寄存器。

4.数据的存取

对于单片机的程序执行时指令和数据的存放与读取,理解如下:

程序的代码段、.data段、.bss段、rodata段等都存放在Flash中。单片机上电后,初始化汇编代码将.data段、.bss段,复制到RAM中,并建立好堆栈,开始调用程序的main函数。

之后,便有了程序存储器,和数据存储器之分,运行时从Flash(即指令存储器,代码存储器)中读取指令 ,从RAM中读取与写入数据。RAM存在的意义就在于速度更快。

无论是单片机也好,PC也罢,存在的存储器金字塔都是一致的,速度的因素,成本的限制导致了一级级更快的存储器的更快速度与更高的成本。应该说,对于它们的理解,就是存储器金字塔的理解。

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

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

相关文章

微波基础介绍

1、什么是微波 大家在高中物理中都学过电磁波,可见光、微波都是电磁波波段,如下图所示,可见光谱只占有宽广的电磁波谱的一小部分: 而我们这次的主角微波,是频率范围300MHz到3THz的电磁波(1THz1000GHz&…

Clion结合CubeMX以Makefile编译和构建STM32以及OPENOCD调试嵌入式的优雅开发

目录 说在前面 Clion结合CubeMX以Makefile编译和构建STM32 新建目录和文件 串口打印问题解决,重定向fptuc失效. 说在前面 有稚晖君的一文,结果可能就让你对嵌入式开发更加易于上手。这是工具上的革新带给你的,这也是一个好的IDE带给开发人员不一样的优雅体验。…

〖Python网络爬虫实战㉗〗- Selenium案例实战(一)

订阅:新手可以订阅我的其他专栏。免费阶段订阅量1000 python项目实战 Python编程基础教程系列(零基础小白搬砖逆袭) 说明:本专栏持续更新中,目前专栏免费订阅,在转为付费专栏前订阅本专栏的,可以免费订阅付…

C++ 从代码到可以执行的过程(预编译、编译、汇编、链接)(以Linux为参考)

参考阿秀的学习笔记 测试代码 #include<iostream> using namespace std; #define PI 3.14 int main(){//测试代码cout<<PI<<endl;cout<<"hello world"<<endl;return 0; }预处理 处理内容 删除define&#xff0c;展开所有宏定义处理…

羡慕大劳星空顶?不如跟我一起使用 Jetpack compose 绘制一个星空背景(带流星动画)

前言 背景 作为一个自诩的电影爱好者&#xff0c;经常会在半夜看电影&#xff0c;看完后就会顺道去豆瓣标记一下看过&#xff0c;再看看别人对这个电影的理解。 某日深夜&#xff0c;看完电影后&#xff0c;顺手打开了豆瓣的 书影音记录 这个功能&#xff0c;起初并没有注意…

c++虚函数详解(多态特性)

1.c多态的概念 多态是c的特征之一 多态的分类&#xff1a;静态多态&#xff08;静态联编&#xff09;、动态多态&#xff08;动态联编&#xff09; 静态多态&#xff08;静态联编&#xff09;&#xff1a;函数入口地址 是在 编译阶段 确定&#xff08;运算符重载、函数重载&…

微信小程序自定义tabBar

1.app.json中tabBar里设置 "custom":true 设置好后就可使用自定义tabBar。 注意&#xff1a;list中的页面必须保存&#xff0c;且必须和自定义的tabBar页面数据一致 "tabBar": {"custom": true,"list": [{"pagePath": &q…

基于springboot篮球论坛系统

开发技术介绍 B/S架构 随着软件系统的不断改进和升级&#xff0c;B/S结构产品更为方便的特征体现地十分明显。对于一个中等偏大的公司来说&#xff0c;如果系统管理员每天要在很多台电脑之间来回查看&#xff0c;不断奔走&#xff0c;那么效率和工作量就会变得很低&#xff0…

【Redis】Redis实现点赞、点赞排行榜

目录 一、点赞 1、思路 2、代码实现 二、点赞排行榜 1、思路 2、代码实现 一、点赞 1、思路 在我们的项目中我们有时候会碰到这样的需求&#xff0c;比如实现一个博客系统&#xff0c;当用户访问到这篇博客时可以进行点赞&#xff0c;那么这个功能如何去实现呢&#xff…

Midjourney|文心一格 Prompt:完整参数列表、风格汇总、文生图词典合集

Midjourney|文心一格 Prompt&#xff1a;完整参数列表、风格汇总、文生图词典合集 1.Midjourney 完整参数列表 参数名称 调用方法使用案例注意事项V5V4V3niji版本在关键词后加空格&#xff0c;然后带上版本参数&#xff1a; --v 或者 —v –version 或者 —versionvibrant cali…

【密码学复习】第八讲 数字签名

数字签名&#xff08;Digital Signature&#xff09;&#xff0c;也称电子签名&#xff0c;是指附加在某一电子文档中的一组特定的符号或代码&#xff0c;它是利用数学方法对该电子文档进行关键信息提取并与用户私有信息进行混合运算而形成的&#xff0c;用于标识签发者的身份以…

SpringBoot学习之集成Swagger3(二十七)

一、Maven配置 注意swagger的版本号是3.0.0版本以上才可以,这里我们就选择3.0.0版本 完整的Maven配置如下(仅供参考): <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaL…

vulnhub渗透测试靶场练习1

靶场介绍 靶场名&#xff1a;Medium_socialnetwork 下载地址&#xff1a;https://www.vulnhub.com/entry/boredhackerblog-social-network,454/ 环境搭建 靶机建议选择VM VirtualBox,我一开始尝试使用VMware时会报错&#xff0c;所以改用VM VirtualBox&#xff0c;攻击机使用…

魔改车钥匙实现远程控车:(前传)在macOS上安装使用Arduino

前言 因为最近有个需求需要硬件支持&#xff0c;原本打算使用 Arduino Nano&#xff0c;后来在 Boot 大佬的建议下&#xff0c;买了某宇宙家的 ESP32C3 核心板&#xff0c;对比 Arduino Nano 价格便宜了一大半&#xff0c;而且自身就集成了 WIFI 和 BLE 模块&#xff0c;还不用…

(一)before initialization of D3D(初始化D3D之前你需要了解的D3D基础知识)

什么是D3D? D3D全称Direct X 3D,即一组API可以用来针对GPU编程,不过他最主要的作用是用来渲染(不过现在也有很多其他应用比如d3d11va[Direct X 3D 11 Video API]用来进行硬件加速解码) Tips:Direct X 3D主要用来渲染,既然我们说到可以针对GPU编程了,当然不只是渲染的工作可以…

国考省考行测:数量关系,牛吃草问题,比例问题

国考省考行测&#xff1a;数量关系&#xff0c;牛吃草问题 2022找工作是学历、能力和运气的超强结合体! 公务员特招重点就是专业技能&#xff0c;附带行测和申论&#xff0c;而常规国考省考最重要的还是申论和行测&#xff0c;所以大家认真准备吧&#xff0c;我讲一起屡屡申论…

〖Python网络爬虫实战㉘〗- Selenium案例实战(二)

订阅&#xff1a;新手可以订阅我的其他专栏。免费阶段订阅量1000 python项目实战 Python编程基础教程系列&#xff08;零基础小白搬砖逆袭) 说明&#xff1a;本专栏持续更新中&#xff0c;目前专栏免费订阅&#xff0c;在转为付费专栏前订阅本专栏的&#xff0c;可以免费订阅付…

图神经网络(处理点云)PPFNet的实现

文章说明&#xff1a; 1)参考资料&#xff1a;PYG官方文档。超链。 2)博主水平不高&#xff0c;如有错误还望批评指正。 3)我在百度网盘上传了这篇文章的jupyter notebook和有关文献。超链。提取码8848。 文章目录 前言文献阅读代码实操历史遗留问题 前言 本篇文章接上一篇文章…

今年的面试难度,我给跪了……

大家好&#xff0c;最近有不少小伙伴在后台留言&#xff0c;又得准备面试了&#xff0c;不知道从何下手&#xff01; 不论是跳槽涨薪&#xff0c;还是学习提升&#xff01;先给自己定一个小目标&#xff0c;然后再朝着目标去努力就完事儿了&#xff01; 为了帮大家节约时间&a…

【STM32G431RBTx】备战蓝桥杯嵌入式→决赛试题→第七届

文章目录 前言一、题目二、模块初始化三、代码实现interrupt.h:interrupt.h:main.h:main.h: 四、完成效果五、总结 前言 无 一、题目 二、模块初始化 1.LCD这里不用配置&#xff0c;直接使用提供的资源包就行 2.ADC:开启ADCsingle-ended 3.LED:开启PC8-15,PD2输出模式就行了…