读 “cortexM3” 权威指南 小记(一)

AHB      先进高性能总线     CPI      每条指令的周期数    ETM      嵌入式跟踪宏单元     MMU     存储器管理单元    NMI      不可屏蔽中断

APB      先进外设总线       IDE       集成开发环境     IRQ       中断请求(通常是指外部中断的请求)  LSB       最低有效位    MSB      最高有效位 

NVIC      嵌套向量中断控制器 

1,前言

Cortex ‐ M3处理器内核是单片机的中央处理单元(CPU )。完整的基于CM3 的MCU还需要多其它组件。在芯片制造商得到CM3 处理器内核的使用授权后,它们就可以把CM3 内核用自己的硅片设计中,添加存储器,外设,I/O 以及其它功能块。

ARM 处理器一直支持两种形式上相对独立的指令集,它们分别是: 
1。   32位的ARM 指令集。对应处理器状态:ARM 状态 
2。   16位的Thumb 指令集。对应处理器状态:Thumb 状态    实际上,Thumb 指令集在功能上是ARM 指令集的一个子集,
但它能带来更高的代码密度,给目标代码减肥。这对于要勒紧裤腰带的应用还是很经济的。

后来的 基于“cortex M3”内核的处理器 基本采用的新的指令集Thumb‐2(Thumb‐2是16位Thumb 指令集的一个超集)

Cortex ‐ M3勇敢地拒绝了32位ARM 指令集,却把自己的处理能力以身相许般地全托给Thumb ‐ 2 指令集。这可能有些令人意外,但事实上这却见证了Cortex ‐ M3的用情专
一:在内核水平上,就已经为适应单片机和小内存器件而抉择、取舍过了。但她没有嫁错郎, 因为Thumb ‐ 2 完全胜任在这个领域挑大梁。不过,这也意味着Cortex ‐ M3作为新生代处理器,不是向后兼容的。因此,为ARM7写的ARM 汇编语言程序不能直接移植到CM3 上来。不过,CM3 支持绝大多数传统的Thumb 指令,因此用Thumb 指令写的汇编程序就从善如流了

2.Cortex-M3概览

Cort ex‐ M3是一个32位处理器内核,CM3 采用了哈佛结构,拥有独立的指令总线和数据总线,可以让取指与数据访问并行不悖。

Cortex ‐ M3处理器拥有 R0‐R15 的寄存器组。其中 R13 作为堆栈指针 SP 。SP 有两个,但在同一刻只能有一个可以看到,这也就是所谓的“banked ”寄存器。

 

R0‐ R12 都是32位通用寄存器,用于数据操作。但是注意:绝大多数16位Thumb 指令只能访问R0‐ R7,而 32位Thumb ‐ 2 指令可以访问所有寄存器。

Cortex ‐ M3拥有两个堆栈指针,然而它们是 banked ,因此任一时刻只能使用其中的一个。 
1. 主堆栈指针(MSP):复位后缺省使用的堆栈指针,用于操作系统内核以及异常处理例程(包括中断服务例程) 
2.  进程堆栈指针(PSP):由用户的应用程序代码使用。堆栈指针的最低两位永远是0,这意味着堆栈总是4字节对齐的。

在ARM 编程领域中,凡是打断程序顺序执行的事件,都被称为异常(exception) 。除了外部中断外,当有指令执行了“非法操作”,或者访问被禁的内存区间,因各种错误产生的fault ,以及不可屏蔽中断发生时,都会打断程序的执行,这些情况统称为异常。在不严格的上下文中,异常与中断也可以混用。另外,程序代码也可以主动请求进入
异常状态的(常用于系统调用)。

Cortex ‐ M3还在内核水平上搭载了若干特殊功能寄存器,包括 
  程序状态字寄存器组(PSRs ) 
  中断屏蔽寄存器组(PRIMASK,   FAULTMASK,  BASEPRI) 
  控制寄存器(CONTROL )

 
xPSR              记录ALU 标志(0 标志,进位标志,负数标志,溢出标志),执行状态,以及当前正服务的中断号 
PRIMASK        除能所有的中断——当然了,不可屏蔽中断(NMI )才不甩它呢。 
FAULTMASK    除能所有的fault ——NMI 依然不受影响,而且被除能的 faults 会“上访”,
BASEPRI         除能所有优先级不高于某个具体数值的中断。 
CONTROL       定义特权状态(见后续章节对特权的叙述),并且决定使用哪一个堆栈指针 

3.堆栈指针

堆栈指针用于访问堆栈,并且PUSH指令和POP 指令默认使用SP指针

在Cortex ‐ M3中,有专门的指令负责堆栈操作——PUSH和POP 。它俩的汇编语言语法
如下例所演示 
  PUSH {R0}   ; *(--R13)=R0 。R13 是long* 的指针   向下生长的满栈
  POP  {R0}   ; R0= *R13++

PUSH 和POP 还
能一次操作多个寄存器,如下所示: 
subroutine_1
PUSH   {R0-R7, R12, R14}   ;  保存寄存器列表
…         ;  执行处理
POP {R0-R7, R12, R14}     ;  恢复寄存器列表
BX R14        ; 返回到主调函数

  MSP 和PSP 都被称为R13/SP 。不过,我们可以通过MRS/MSR指令来指名道姓地访问具体的堆栈指针。 
  MSP,亦写作 SP_main ,这是复位后缺省使用堆栈指针,服务于操作系统内核和异常服务例程;而PSP,亦写作SP_process ,典型地用于普通的用户线程中。

(连接寄存器R14)LR 用于在调用子程序时存储返回地址

R15 是程序计数器,在汇编代码中你也可以使用名字“PC”来访问它。因为CM3 内部
用了指令流水线,读PC时返回的值是当前指令的地址+4。比如说: 0x1000:  MOV  R0,  PC  ;  R0 = 0x1004 

Cortex ‐ M3中的特殊功能寄存器包括: 
z   程序状态寄存器组(PSRs 或曰xPSR ) 
z   中断屏蔽寄存器组(PRIMASK,   FAULTMASK,以及BASEPRI) 
z   控制寄存器(CONTROL ) 
它们只能被专用的MSR 和MRS 指令访问,而且它们也没有存储器地址。 
MRS  <gp_reg>,  <special_reg> ; 读特殊功能寄存器的值到通用寄存器
MSR  <special_reg>, <gp_reg>  ; 写通用寄存器的值到特殊功能寄存器

只有在特权级下,才允许访问这3 个寄存器。 
 
  PRIMASK, FAULTMASK 和 BASEPRI 这三个特殊功能寄存器用于控制异常的使能和除能。
 只有在特权级下,才允许访问这3 个寄存器,其实,为了快速地开关中断,CM3还专门设置了一条CPS指令,有4种用法 
  CPSID I   ;PRIMASK=1,  ;关中断
  CPSIE I  ;PRIMASK=0,  ;开中断
  CPSID F  ;FAULTMASK=1,  ;关异常
  CPSIE F  ;FAULTMASK=0  ;开异常

控制寄存器用于定义特权级别,还用于选择当前使用哪个堆栈指针

向量表 s
当一个发生的异常被CM3 内核接受,对应的异常 handler就会执行。为了决定 handler的入口地址,CM3 使用了“向量表查表机制”。这里使用一张向量表。向量表其实是一个WORD32位整数)数组,每个下标对应一种异常,该下标元素的值则是该异常handler的入口地址。向量表的存储位置是可以设置的,通过NVIC 中的一个重定位寄存器来指出向量表的地址。在复位后,该寄存器的值为 0 。因此,在地址 0 处必须包含一张向量表,用于初始时的异常分配

堆栈的基本操作
  笼统地讲,堆栈操作就是对内存的读写操作,但是其地址由SP 给出。寄存器的数据通过PUSH 操作存入堆栈,以后用POP 操作从堆栈中取回。在PUSH 与POP 的操作中,SP 的
值会按堆栈的使用法则自动调整,以保证后续的PUSH不会破坏先前  PUSH进去的内容。 堆栈的功能就是把寄存器的数据放入内存,以便将来能恢复之——当一个任务或一段子
程序执行完毕后恢复。正常情况下,PUSH与POP 必须成对使用,而且参与的寄存器,不论是身份还是先后顺序都必须完全一致。当PUSH/POP 指令执行时,SP 指针的值也根着自减/自增。 
  … (主程序) 
  ; R0=X, R1=Y, R2=Z
 BL  Fx1
  
 Fx1
  PUSH {R0 } ;把R0存入栈 &  调整SP
  PUSH {R1} ;把R1存入栈 &  调整SP
  PUSH {R2} ;把R2存入栈 &  调整SP
  …    ;执行Fx1 的功能,中途可以改变R0-R2 的值
  POP  {R2} ;恢复R2早先的值 &  再次调整SP
  POP  {R1} ;恢复R1早先的值 &  再次调整SP
  POP  {R0} ;恢复R0早先的值 &  再次调整SP
  BX  LR  ;返回
 
 ;回到主程序 

  ;R0=X, R1=Y, R2=Z (调用Fx1 的前后R0-R2 的值没有被改变)

原文地址:https://www.cnblogs.com/darren-715/p/3465676.html