ARMv7-M4处理器系列文章-2 编程模型

  • 概述

本文主要记录M4处理器的编程模型,其中会聊到寄存器组,处理器模式,软件执行特权等。

  • 处理器模式

  1. 线程模式:当处理器复位或者异常处理结束后,就会进入线程模式,在线程模式下,主要运行的用户应用软件。

  2. 处理模式:用来处理各种异常。

  • 软件执行特权

  1. 特权级别:执行在特权级别的软件可以访问系统所有资源和指令

  2. 非特权级别:顾名思义是一些非特权程序执行级别,这类程序不能访问系统时钟,NVIC或者SCB;会限制使用一些特殊指令,甚至严格控制内存和外设的访问。

从Linux角度看,这两种级别类似于内核态和用户态。

区分这两种软件执行级别的出发点不难看出,就是对关键区域的保护。

那问题来了,怎么控制区分软件执行特权呢?先把该问题暂且搁置起来,我们先聊聊处理器的寄存器组。

  • 寄存器组

处理器是对指令的处理,其中主要一个模块是ALU,为了不影响处理速度,需要有一个地方可以快速及时为ALU提供数据源或者保存结果,那这个地方就是寄存器组,先来一张框图,然后一一详细聊聊每个寄存器的用途。

 

  1. R0~R12:13个通用目的寄存器,R0~R7是低寄存器,因为有的16位指令只能访问低寄存器;高寄存器可以被32位指令和几个16位指令访问。

  2. R13:被栈指针,物理上其实有两个栈指针:MSP和PSP;通过PUSH和POP指令对栈操作结束后,R13指针会被调整。因为是32位存储系统,SP指针最低两位为0,保存的地址必须32位字节对齐。 带着问题我们深入理解哈这个栈指针:怎么区分这两个寄存器呢?或者为什么有两个栈指针? 因为处理器有处理模式和线程模式,物理上要区分栈指针; 另外通过Control寄存器的bit[1]SPSEL位可以标识具体使用的哪个栈指针: SPSEL=0,标识使用MSP指针。 SPSEL=1,标识使用PSP指针。 最后,系统复位是运行在处理模式,因此MSP的复位值为是从存储器的第一个32位的字中取出来。PSP是不确定。

  3. LR:当从子程序、函数调用和异常返回时,用来保存返回地址;当函数A调用另外一个函数B或者子程序时,首先会将LR的数值保存在栈中,结束调用后,把栈中LR的值加载给PC值,程序得以继续执行。 在处理异常期间,LR会被自动更新为EXC_RETURN数值,然后该数值会在异常处理结束时触发异常返回。 一旦复位,LR初始化为0xFFFFFFFF。

  4. PC:程序计数器,包含当前程序地址,如果读该寄存器,返回当前指令地址加4,如果写该寄存器则引起程序跳转。有一点需要提醒:因为指令必须是半字或字对齐,因此PC的bit0为0,但是当更新PC时,必须设置bit0为1,表示Thumb状态。在C/C++编程时,编译器会自动将跳转目前的bit0置位。一旦复位,PC初始化为复位向量地址,该值保存在0x00000004地址中。

  5. 程序状态寄存器PSR:顾名思义,程序在处理器运行的结果如何,就需要该寄存器呈现给用户。PSR属于特殊寄存器,没有经过存储器映射,因此可使用MSR和MRS等特殊寄存器访问指令来进行访问。 运行的程序大概分为:用户应用程序,中断处理程序和异常处理程序。因此PSR也分为:

APSR:应用程序状态寄存器,仅表示前面指令执行状态。寄存器各个字段描述如下图

Bits

名字

功能

31

N

负标志

30

Z

零标志

29

C

进位标志

28

V

溢出标志

27

Q

饱和标志

19:16

GE[3:0]

大于等于标志

IPSR:中断程序状态寄存器。保存当前的中断号,可指示当前执行的异常和中断向量入口。。当异常开始和结束是,处理器会写IPSR,软件只能读该寄存器,写被忽略。

ISR_NUMBER

功能

0

线程模式

1

Reserved

2

NMI

3

HardFault

4

MemManage

5

BusFault

6

UsageFault

....

11

SVCall

12

for debug

13

Reserved

14

PendSv

15

SysTick

16

IRQ0

当系统复位后,系统处于线程模式,因此ISR_Number写为0。 EPSR:异常程序状态寄存器。EPSR寄存器包含Thumb状态标志位,IF-Then指令和ICI字段。软件直接读写该寄存器返回0,写被忽略。 ICI字段的理解:在LDM、STM,PUSH和POP指令操作时,发生中断,处理暂时停止四个指令执行,然后保存四个指令的操作数到EPSR[15:12]字段。当中断执行结束后,从EPSR[15:12]恢复操作数继续执行四个指令。

  1. 异常屏蔽寄存器:PRIMASK寄存器,BASEPRI寄存器,FAULTMASK寄存器。

  • PRIMASK寄存器:主要屏蔽除NMI和Hardfault之外的所有的异常。在时间要求严格的进程中禁止所有中断:运行完进程后,重新使能中能。实际是将当前异常优先级提升为0.

  • FAULTMASK寄存器器:屏蔽除NMI外的所有异常,从任何异常处理返回时,处理器自动清零该位。

  • BASEPRI寄存器:设置被屏蔽中断的的优先级。只会处理比该优先级更高的异常。0时,无效。

  1. Control寄存器:选择栈指针,线程模式的访问等级,是否使用浮点单元。该寄存器可以用来区分特权模式和非特权模式。回复最初的问题了。

位域

功能

nPRIV

定义线程模式下的特权级别:0:特权模式;1:非特权模式

SPSEL

定义当前使用的哪个栈指针;0:MSP为当前栈指针;1:PSP为当前栈指针。

FPCA

指示当前是否为浮点指针执行,0:非浮点单元运行。1:浮点单元运行。

  • 总结:通过本节文章的浅析,主要掌握处理器编程模式中的处理器模式,特权访问模式,以及寄存器组。嵌入式编程晋级必须掌握的知识点。后续章节会重点剖析。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值