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

目录

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也罢,存在的存储器金字塔都是一致的,速度的因素,成本的限制导致了一级级更快的存储器的更快速度与更高的成本。应该说,对于它们的理解,就是存储器金字塔的理解。

  • 2
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 28335系列是德州仪器(TI)的一款数字信号控制器(DSC)芯片,它广泛应用于工业控制领域。利用bin文件进行程序升级是指使用特定的软件工具,通过将新的程序代码以二进制格式保存为bin文件,并将其烧写到28335芯片的非易失性存储器中,从而实现对芯片程序的更新。 具体步骤如下: 1. 准备bin文件和烧写工具:将需要升级的新程序代码保存为bin文件,并下载安装28335芯片的烧写工具。 2. 连接电脑和开发板:将28335芯片所在的开发板通过USB线缆或其他通信接口与电脑相连。 3. 打开烧写工具:运行已安装的烧写工具,并选择正确的型号和连接方式,以确保与开发板的通信正常。 4. 选择bin文件:在烧写工具中导入先前准备的bin文件,并确保软件能够正确识别bin文件的格式和内容。 5. 设置烧写参数:根据具体需求,在烧写工具中设置目标地址、数据校验方式等相关参数。 6. 开始烧写:点击烧写按钮,烧写工具将开始将bin文件的内容写入28335芯片的非易失性存储器中。 7. 等待烧写完成:等待烧写过程完成,期间要保持设备的电源稳定,并避免进行其他操作。 8. 验证程序升级:烧写完成后,可以使用对应的开发工具或设备来验证芯片的新程序是否成功升级。 需要注意的是,在进行程序升级时,应确保选择正确的bin文件,避免错误的程序代码或版本升级,以免造成系统故障。另外,还需要遵守相关协议和安全规范,确保数据的完整性和机密性。 ### 回答2: 要使用bin文件进行程序升级,首先要确保bin文件是正确的升级文件,并与要升级的程序版本相匹配。然后按照以下步骤进行升级。 1. 准备工作:将bin文件保存到计算机或存储介质的合适位置。 2. 连接设备:将需要升级的设备与计算机连接,可以使用USB、串口或其他适配器进行连接。 3. 打开升级工具:启动适配设备的升级工具软件,通常会有一个界面显示升级程序的当前版本和设备连接状态。 4. 导入bin文件:在升级工具中找到bin文件导入选项,选择相应的bin文件进行导入,确认bin文件是否正确。 5. 进行升级:通过升级工具的操作,选择升级设备并开始升级。升级过程中可能会有进度条显示升级进度。 6. 等待升级完成:等待升级工具提示升级完成或设备自动重启。升级完成后,设备应该能正常运行新版本的程序。 在整个升级过程中,需要注意以下几点: - 确保设备与计算机连接的稳定性,充分充电或给设备提供足够的电源供应。 - 正确选择升级工具和操作步骤,遵循升级工具提供的说明和警告。 - 不要中断升级过程,避免设备或计算机突然断电或拔出连接线。 - 如果出现升级失败或设备无法正常运行的情况,尝试使用备份的原始程序进行恢复或联系设备厂商进行技术支持。 总之,使用bin文件进行程序升级需要谨慎操作,确保文件正确性和升级过程的稳定性,以确保设备能够正常更新并运行新版本的程序。 ### 回答3: 利用bin文件进行程序升级是一种常见的方法。bin文件是一种二进制文件,可以包含程序的执行代码和相关数据。在升级过程中,我们首先需要获取到最新版本的bin文件,通常是由软件开发商或者制造商提供的。 升级程序的过程如下:首先,我们需要将原始的bin文件备份到安全的位置,以便出现问题时可以还原。然后,我们将新的bin文件下载到设备或计算机上,通常可以通过USB、SD卡或者网络进行传输。接下来,我们需要打开升级工具或者升级界面,一般由设备或者软件内部提供。在升级界面中,我们可以选择要升级的设备或者程序,并将下载的bin文件加载到界面中。在确认设置无误后,点击“开始升级”按钮,升级程序会自动开始执行。 在升级过程中,会有一系列的验证和检查,例如文件校验、设备连接、权限验证等,以确保升级的可行性和安全性。升级过程中可能会出现进度条或者提示信息,我们需要耐心等待升级完成。如果升级成功,设备或者程序会自动重启,并加载新的bin文件。如果升级失败,我们可以根据提示信息进行故障排查,比如检查网络连接、更新升级工具或者联系软件供应商,以寻找解决方法。 总的来说,利用bin文件进行程序升级是一种相对简单和快捷的方式。通过备份原始文件、下载新的bin文件、选择设备并进行升级,我们可以实现程序的更新和优化,以获得更好的使用体验和功能改进。但升级过程中需要注意安全性,避免恶意软件或不稳定的bin文件对设备或系统造成损害。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值