Cortex-M软件结构

一 程序映像

程序映像指的是程序存储器,对于大多数芯片来讲,一般为flash,flash中不仅存储了用户的程序代码还有其它多种软件部分:

  • 向量表
  • 复位处理/启动代码
  • C启动代码
  • 应用代码
  • C运行时库函数
  • 其它数据

1 向量表

ARM Cortex-M处理器的向量表中包含每个异常和中断的起始地址,而对于Cortex-M0和Cortex-M0+处理器复位后,向量表定义在存储器空间的起始位置(地址为0x00000000),向量表的第一个字节还定义了主栈指针的初始值,向量表是和设备相关的(取决于所支持的异常),向量表一般是定义在启动代码中。

2 复位处理/启动代码

复位处理是可选的,若没有复位处理,则会直接执行C启动代码。复位处理中的代码在处理器从复位中退出时会立刻执行,有些情况下其中还会存在一些硬件初始化代码。对于使用CMSIS-CORE(Cortex-M处理器用的软件架构)的工程,复位处理执行SystemInit()函数,其会在跳转到C启动代码前设置时钟和PLL。
启动代码一般由微控制器厂商提供,有时还会在工具链软件中,其可能是C代码或汇编代码。

3 C启动代码

若使用C/C++或其他高级语言编程,处理器需要执行一些程序代码以设置程序执行环境(如设置全局变量以及SRAM中的初始值),对于加载时未初始化的数据存储器中的变量,需要将他们初始化为0.若应用需要使用malloc()等C函数,C启动代码还需要初始化堆存储的数据变量,初始化后,C启动代码会跳转到main程序开头。
C启动代码会被工具链自动生成,因此是和工具链相关的,如果是完全用汇编编写的程序,则可能会不存在启动代码。对于ARM编译器,C启动代码的标号为__main,而GNU C编译器生成的启动代码标号一般为_start.

4 应用代码

应用代码一般是从main()开始的,其中包括用以执行所需任务的应用程序代码生成的指令,除了指令序列外,还有其它类型的数据:

  • 变量初始值:函数或子例程中的局部变量需要被初始化,在程序执行期间会设置这些初始值。
  • 程序代码中的常量,应用代码中的常量数据有多种:数据值、地址或外设寄存器以及常量字符串等。这些数据一般被称为文本数据,且在程序映像中会以多个名为文本池的形式分组出现。
  • 有些应用可能还包含查找表、图形映像数据(如位图)等其他常量数据。

5 C库代码

在使用某些C/C++函数时,C库代码会被连接器插入程序映像中。另外,在进行浮点运算和除法等数据处理任务时可能也会包含C库代码。Cortex-M0和Cortex-M0+处理器不支持除法指令,除法运算一般由C库中的除法函数执行。
为了应对不同用途,有些开发工具会提供各种版本的C库。例如,对于Keil MDK或ARM Development Studio 5(DS-5),可以选择使用名为Microlib的特殊版本的C库。Microlib面向微控制器应用,并且体积非常小,但是无法提供标准C库的所有特性。对于不需要很高的数据处理能力且存储器需求非常紧张的应用,Microlib是降低代码大小的好方法。
对于不同的应用,C库代码可能不会出现在简单的C应用(无C库函数调用)或纯汇编语言工程中。

向量表必须放在存储器映像的开头处,程序映像的其他部分就有没有什么限制了。有些情况下,若程序存储器中各部分的布局有特殊的要求,则可以利用连接器脚本控制程序映像的生成。

6 其他数据

程序映像中还包含其它数据,例如全局变量和静态变量的初始值。

二 SRAM中的数据

处理器中的SRAM包含:

  • 数据空间
  • 栈空间
  • 堆空间

1 数据空间

存储在RAM的末端,通常包含全局和静态变量。局部变量可以存储在处理器的寄存器中,或者放在栈中以减少RAM的使用,未使用函数中的局部变量不会占空存储器空间。

2 栈空间

栈空间,包括临时数据存储空间(一般的栈PUSH和POP操作)、局部变量的存储空间、函数调用时的参数传递、以及异常流程中的寄存器保存等。
Thumb指令集在处理器数据访问时非常高效,其使用栈指针(SP)相关的寻址模式,并且在很小的指令开销下就可以访问栈存储中的这些数据。

3 堆空间

堆存储是可选的,用于C函数中存储器空间的动态分配,如 alloc()或malloc()和其他使用这个功能的函数。为了保证这些函数能够正确分配存储空间,C启动代码需要初始化堆存储及其控制变量。

4 RAM空间分布

对于RAM处理器,还可以将程序代码赋值到内存中并从这里开始执行,但是对于多数微控制器应用,程序一般从Flash等非易失性存储器中开始执行。
将这些数据放到SRAM中的方法有很多种,一般是和工具链相关的。对于不具备OS的简单应用SRAM中存储器分布情况如下图。
在这里插入图片描述
对于有嵌入式OS的微控制器系统,每个任务的栈都是独立的。许多OS都允许软件开发人员定义每个任务/线程所需的栈大小,有些OS可能会将RAM分分割成多个部分,并将每个部分分配给一个任务,其中都包含各自的数据、栈和堆。

具有RTOS的多数系统都会使用下图左侧的数据布局,这里的全局和静态变量以及堆存储都是共用的。
在这里插入图片描述

三 微控制器启动流程

在这里插入图片描述

有些微控制器会包含一个独立的ROM,其中存储一段BootLoader程序,该程序会在微控制器执行Flash存储器中的用户程序前启动。这个过程是可选的,如果没有这段代码那么硬件复位之后,微控制器从向量表的首地址处取出一个字大小的数据,该数据就是栈指针。然后开始执行复位向量。

在这里插入图片描述
当处理器被复位之后,首先从0x0000 0000地址处读取两个字,第一个字为栈顶指针,第二个字为复位向量,决定程序执行的起始地址(复位处理)。
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值