CORTEXM4知识点总结.docx
《CORTEXM4知识点总结.docx》由会员分享,可在线阅读,更多相关《CORTEXM4知识点总结.docx(39页珍藏版)》请在冰豆网上搜索。
![CORTEXM4知识点总结.docx](https://file1.bdocx.com/fileroot1/2023-2/28/e77e522d-4124-4f4b-9d2a-2027c25fd67a/e77e522d-4124-4f4b-9d2a-2027c25fd67a1.gif)
CORTEXM4知识点总结
Cortex-M4内核知识点总结
余
明
1ARM处理器简介
ARM处理器的种类很多,从手机上的高端处理器芯片到面向微控制器的芯片,都有ARM的身影。
2011年基于ARM处理器的芯片的出货量已经到达79亿。
这一章首先对ARM处理器有个简单的了解。
在早期的时候,ARM处理器使用后缀表明特性。
例如ARM7TDMI,T表示支持Thumb指令,D表示JTAG,M表示快速乘法器,I则表示嵌入式ICE模块。
近几年,ARM改变处理器的命名方式,统一使用了Cortex处理器的名称。
Cortex处理器下分为三类:
·Cortex-A系列:
需要处理高端嵌入式系统等复杂应用的应用处理器
·Cortex-R系列:
实时、高性能的处理器,面向较高端的实时市场
·Cortex-M系列:
面向微控制器和混合信号设计等小型应用,注重低成本、低功耗。
不同系列的处理器使用不同版本的架构
Cortex-A系列
ARMv7-A架构
Cortex-R系列
ARMv7-R架构
Cortex-M系列
ARMv7-M、ARMv6-M
在Cortex-M系列中,进一步都处理器进行了划分
处理器
功能
架构
Cortex-M0、Cortex-M0+
低功耗
ARMv6-M
Cortex-M1
FPGA
ARMv6-M
Cortex-M3
微控制器
ARMv7-M
Cortex-M4
增加DSP
ARMv7E-M
2架构
2.1架构简介
Cortex-M3和Cortex-M4处理器都是基于ARMv7-M架构。
最初ARMv-7M架构是随着Cortex-M3处理器一同引进的,而在Cortex-M4发布时,架构中又额外增加了新的指令和特性,改进后的架构有时也被称为ARMv7E-M。
2.2编程模型
2.2.1操作模式和状态
Cortex-M4处理器包括两种操作状态和模式,还有两种访问等级。
1.操作状态
·调试状态:
处理器被暂停后,就会进入调试状态,比如利用调试器触发断点,单步执行等。
·Thumb状态:
处理器执行程序代码,它就是处在Thumb状态,因为Cortex-M4用的是Thumb指令,所以称为Thumb状态,并且在Cortex-M处理器中已经不支持ARM指令,也就不存在ARM状态。
2.操作模式
·处理模式:
执行中断服务程序等异常处理。
在处理模式下,处理器总是具有特权访问等级。
·线程模式:
执行普通的程序代码。
3.访问等级
·特权访问等级:
可以访问处理器中的所有资源。
·非特权访问等级:
有些存储器区域无法访问,有些操作也无法使用。
访问等级有特殊寄存器CONTROL控制。
软件可将处理器从特权访问等级转换至非特权访问等级,但反之无法直接转换,需要借助异常机制。
处理器的操作模式和状态可由图1.1来表示,在上电后,默认处于特权线程模式下的Thumb状态。
2.2.2寄存器
对于ARM架构来讲,处理存储器中的数据时,需将其从存储器加载到寄存器中,处理完毕后,若有必要,还可以再写回存储器。
这种方式被称作“加载-存储架构”(LOAD-STORE)。
Cortex-M4处理器的寄存器组中有16个寄存器,其中包括13个通用寄存器和3个有特殊用途的寄存器。
1通用寄存器R0-R12
R0-R7被称作低寄存器,许多16位指令只能访问低寄存器。
R8-R12称作高寄存器,可用32位指令和几个16位指令访问。
R0-R12初始值未定义。
2栈指针R13
R13为栈指针,可通过PUSH和POP操作实现栈存储的访问。
栈指针包括两个:
主栈指针MSP和进程栈指针PSP。
MSP为默认指针,复位后或处理模式时只能是MSP,而PSP只能在线程模式使用。
栈指针的选择有CONTROL寄存器控制。
MSP和PSP的最低两位必须是0,也就是栈指针的地址操作必须4字节对齐。
3链接寄存器(LR)R14
用于函数或子程序调用时返回地址的保存,在异常中则用来保存进异常前状态信息,包括系统模式、栈指针模式等。
异常返回时参考LR中的信息返回到相应状态。
4程序计数器(PC)R15
R15为程序计数器,读操作返回当前地址加4,写操作引起跳转。
2.2.3特殊寄存器
特殊寄存器有三类:
程序状态寄存器、中断/异常屏蔽寄存器、处理器控制寄存器。
1程序状态寄存器:
应用PSR(APSR)、执行PSR(EPSR)、中断PSR(IPSR)。
三个寄存器可以单独访问,也可以组合到一个寄存器中访问。
在APSR中包含N(负标志)、Z(零标志)、C(进位标志)、V(溢出标志)、Q(饱和标志)和GE(大于或等于标志,只在M4中有)。
IPSR中是中断号,只读。
EPSR中,T为表示Thumb状态,由于M4支持Thumb状态,不支持ARM状态,T位始终为1。
ICI是中断继续指令位,保存的是中断被打断时的信息。
IT指令时IF-THEN指令,用于条件执行。
2PRIMASK、FAULTMASK、和BASEPRI寄存器:
这三个寄存器只能在特权模式下使用。
PRIMASK可屏蔽除NMI和HardFault之外的所有异常。
FAULTMASK还可屏蔽HardFault。
BASEPRI可以根据设置屏蔽低优先级的中断,可控制8个或16个中断,相应的改寄存器的宽度为3位或4位。
3CONTROL寄存器
CONTROL寄存器主要有以下几项作用:
·线程模式下的访问等级
·指针的选择
·当前代码是否使用了浮点单元
分别对应了寄存器的低三位
位
功能
nPRIV(第0位)
0对应特权等级,1为非特权等级
SPSEL(第1位)
0对应主栈指针,1为进程栈指针,处理模式下始终为0。
FPCA(第2位)
0未使用浮点,1使用了浮点
2.2.4浮点寄存器
1S0-S31和D0-D15
S0-S31都为32位寄存器,也可以D0-D15的方式成对访问,但M4不支持双精度浮点运算,只是可以传输双精度数据。
2浮点状态和控制寄存器(FPSCR)
FPSCR两个功能
·提供浮点运算结果的状态信息,如负标志、进位标志等。
·定义一些浮点运算动作,如何舍入等
3经过存储器映射的浮点单元控制寄存器(CPACR)
该寄存器经过了映射,也就是说需要通过通用寄存器加载进行设置,寄存器的功能是可以设置浮点单元的访问权限,拒绝访问、特权访问,全访问。
2.3存储器系统
2.3.1存储器系统特性
·4GB线性地址空间
·架构定义的存储器映射。
4GB的存储器空间被划分为多个区域,用于预定义的存储器和外设。
·支持大端和小端的存储器系统。
·位段访问。
·写缓冲
·存储器保护单元MPU
·非对齐传输支持
2.3.2存储器映射
CORTEX-M处理器的4GB地址空间被分为了多个存储器区域,如图所示。
区域根据各自典型用法进行划分,他们主要用于:
·程序代码访问(如CODE区域)
·数据访问(如SRAM区域)
·外设(如外设区域)
某款芯片的存储器映射分配
一般Code放在Flash当中,数据放在RAM中。
数据在RAM存放有一定的顺序,可以分为数据段,BSS段、堆和栈区域。
·数据段,存储在内存的底部,包含初始化的全局变量和静态变量。
·BSS段,未初始化的数据。
·堆,C函数自动分配存储器区域,例如alloc()和malloc()。
·栈,用于临时数据存储,局部变量,函数调用
2.3.3栈存储
同几乎所有的处理器架构一样,Cortex-M处理器在运行时需要栈存储和栈指针R13。
ARM处理器将系统主存储器用于栈空间操作,使用PUSH指令往栈中存储数据以及POP指令从栈中提取数据。
处理器使用的是满递减的模型,栈指针是向下增长的。
处理器启动后,SP被设置为栈存储空间的最后的位置,也就是最低位置,PUSH时,SP指针首先减小,然后将数据压入栈中。
POP的时候相反,先将当前SP所指的数据出栈,然后再修改SP,SP此时增大。
可用下面两幅图加以理解,
栈中主要用于:
·存储局部变量
·异常产生时保存处理器状态(LR、xPSR)和寄存器数值
·函数调用时
2.4复位和复位流程
对于典型的Cortex-M处理器,复位类型有三种:
·上电复位。
复位微控制器中所有部分。
·系统复位。
只会复位处理器和外设,不包括处理的调试支持部件
·处理器复位。
只复位处理器。
在复位后以及处理器开始执行程序前,处理器会从存储器中读出头两个字节。
第一个字表示主栈指针的初始值。
第二个字代表复位处理起始地址的复位向量。
处理器读出这两个自己后,就会将这些数值赋给MSP和PC。
之前在栈存储时讲到过,Cortex-M处理器的栈操作时基于满递减的,所以SP的初始值应该设置在栈顶的位置。
例如,若存储器区域为0x20007C000~0x20007FFF(1KB),初始的栈指针就应该为0x20008000。
另外,对于Cortex-M处理器,向量表中向量地址的最低位应该为1,以代表他们为Thumb状态。
对于下图中的例子,复位向量为0x101,而启动代码是从0x100开始的。
在取出复位向量后。
Cortex-M处理器就可以从复位向量地址处执行程序,并开始正常操作。
3指令集
CORTEX-M4使用的是Thumb-2指令集,不支持ARM指令集,Thumb指令集是ARM指令集的子集,但是Thumb-2技术已经不再支持ARM状态。
CORTEX-M处理器间的一个区别就是指令集特性。
为了将回路面积降到最低,CORTEXM0、CORTEXM0+、CORTEXM1处理器只支持多数16位指令和部分32位指令,CORTEX-M3支持的32位指令更多。
CORTEX处理器支持剩下的SIMD(单指令多数据)等DSP提升指令集可选的浮点指令。
3.1CM4指令集特点
CM4处理器使用ARMv7-M架构,指令集为Thumb指令集中的Thumb-2技术,具有如下特点
·16位与32位混合指令
·加载/存储指令集,不能直接操作存储器。
·指令长度可变,使用16/32位由功能决定,优先使用16位。
·DSP指令,CM4中为单精度,CM7中可以双精度
3.2Cortex-M处理器间的指令集比较
Cortex-M处理器的架构有三类,ARMv6-M,ARMv7-M,ARMv7E-M。
内核
性能
ARMv6-M
M0/M0+/M1
一般数据处理,IO控制人物
ARMv7-M
M3
高级数据处理、硬件除法
ARMv7E-M
M4
SIMD、快速MAC饱和运算
3.3汇编指令简要介绍
3.3.1处理器内传送数据
MOV
源寄存器处可以是立即数,立即数为8位以下,9-16位用MOVW,32位的需要使用LDR伪指令。
使用浮点单元时可以使用VMOV指令。
3.3.2存储器访问指令
访问可分为读和写指令,另外根据读写的大小还有其他的延伸。
数据类型
加载(读)
存储(写)
8位无符号
LDRB
STRB
8位有符号
LDRSB
STRB
16位无符号
LDRH
STRH
16位有符号
LDRSH
STRH
32位
LDR
STR
多个32位
LDM
STM
64位
LDRD
STRD
栈操作
PUSH
POP
介绍几个较为重要的
1LDR/STR
LDRRd,[Rn,#offset]从存储器Rn+offset处读取字,读取到Rd中
STRRd,[Rn,#offset]向存储器Rn+offset处存储字,数据来自Rd。
LDRR0,[R1,#0X08]从存储器R1+0x08处读取字,放到R0中
支持写回功能,加!
即可,上面可以写成
LDRR0,[R1,#0X08]!
这样表示存储器位置的R1被更新为R1+0x08
2LDM/STM读/写多个字
上述命令是为了从存储器中读写多个字。
一般会加后缀配合使用
LDMIARn,
Rn是存储器位置,reglist是寄存器列表,从Rn所指的存储器位置读取数据,放入寄存器中,每次读取完成后,地址就会自动加4。
作用相当于POP。
另外要注意的是,先读取的数据放置在低寄存器中,后读取的数据放置到高寄存器。
STMIARn,
Rn是存储器位置,reglist是寄存器列表,向Rn所指的存储器位置存储数据,每次存储前,地址自动减4。
相当于PUSH操作。
另要注意的是,先存储高寄存器的数据,后存储低寄存器的数据。
同样,这两个指令都可以通过!
表示写回操作,更新寄存器所指的存储器位置
3压栈与出栈PUSH/POP
PUSH和POP和上面的LDMIA和STMDB是相同的。
3.3.3算数运算
加:
ADC
减:
SUB
乘:
MUL
除:
DIV
对此不做详细介绍
3.3.4逻辑运算
与:
AND
或:
ORR
位清除:
BIC
按位异或:
EOR
按位或非:
ORN
3.3.5移位
算数右移:
ASR
逻辑左移:
LSL
逻辑右移:
LSR
循环右移:
ROR
3.3.6异常相关指令
之前说过,M4可以有特权模式和非特权模式,并且非特权模式不能直接转换到特权模式,只能在异常中修改CONTROL寄存器。
这里就可以通过SVC指令来进入异常。
SVC#
这样就可以进入SVC中断中,然后修改CONTROL寄存器。
要注意的是,调用SVC指令后,需尽快进入中断中,如果有其他高优先级的中断打断了SVC,就会引起HardFault。
CPS指令使用时需要带上后缀:
IE(中断使能),ID(中断禁止),还需指定要设置的中断屏蔽寄存器,如之前讲到的PRIMASK和FAULTMASK
指令
操作
CPSIEI
使能中断(清除PRIMASK)
CPSIDI
禁止中断(设置PRIMASK),除NMI和HardFault
CPSIEF
使能中断(清除FAULTMASK)
CPSIDF
禁止中断(设置FAULTMASK),除NMI
4存储器系统
4.1存储器外设
哈佛结构,程序存储器和数据存储器分开,也就是指令和数据可以同时访问。
1、在第一章中的存储器映射图中,0-0.5G为代码段,主要用于程序代码,改区域一般也允许数据访问。
一般此处为Flash。
在keil中,代码编译后,整个代码分为几部分:
Code(代码),RO-data(只读数据),RW-data,(初始化的可读写变量大小),ZI-data(ZeroInitialize)未初始化的可读写变量大小,它会被自动初始化为0。
ZI-data不会被算到代码里,因为它不会被初始化。
简单来说呢就是在烧写的时候FLASH中的被占用的空间为:
Code+RO-data+RW-data。
程序运行的时候,芯片内部RAM使用的空间为:
RW-data+ZI-data
2、0.5G-1G范围内是SRAM,主要用于连接SRAM,其大都为片上SRAM,不过对存储器的类型没有什么限制。
若支持可选的位段特性,则SRAM区域的第一个1MB可位寻址,还可以在这块区域中执行程序代码。
3、1G-1.5G是外设区域,多用于片上外设,和SRAM区域类似,也可以放置程序代码,若支持可选的位段特性,则外设区域的第一个1MB是可选的。
4、1.5G-2.5G空间为外部RAM空间
5、2G-3G空间为设备空间,用于片外外设。
6、3G-4G空间为系统空间。
4.2Bootloader
芯片设计人员将Bootloader放入系统中的原因是多方面的。
例如:
·提供Flash编程功能,这样就可以利用一个简单的UART接口来编程Flash,或者当程序运行时,在自己的应用程序中编程Flash存储器的某些部分。
·提供通信协议栈等额外的固件,可被软件开发人员通过API调用。
·提供芯片内置的自检功能(BIST)
比如在1601中,提供一个4K的info区,和128K的main区,4K的info区就是一个bootloader,提供SPI下载功能,利用拨码开关可以设置从哪里启动,mode=0时从info区启动,mode=1时从main区启动,并且main区分两部分,软件可设置从低64K启动还是从高64K启动。
这里设计存储器重映射的问题,系统启动时是从0X00开始的,不管是Bootloader还是用户flash,都得从0x00开始,然后0x04放的reset_handler的地址,mode=0,那infor区就被映射到了0x00,mode=1,main区就被映射到了0x00。
4.3位段操作
对存储器中某一位操作是如何实现的呢?
先来看看普通模式下,
写某一位:
LDRR0,=0X200000000;设置地址
LDRR1,[R0];读数据
ORR.WR1,#0X04;修改第2位
STRR1,[R0];写回
读某一位:
LDRR0,=0X200000000;设置地址
LDRR1,[R0];读数据
UBFX.WR1,R1,#2,#1;提取第2位
这种操作无法保证原子性,比如输出端口的第0位被主程序使用,而第一位被中断使用,这样有可能出现数据冲突。
位段操作模式下,这种现象可以避免,因为位段操作是在硬件等级下修改的。
位段操作只在两个区域支持,SRAM的第1MB,外设区域的第1MB。
每1MB会对应一个32M的区域,只需操作这32M的某个字,就能对应那1MB区域的某一位。
例如写0x22000008为1,就设置了0x20000000第3位为1。
在指令上也会更加简化。
位段写操作
LDRR0,=0X2200000;设置add
MOVR1,#1;要写的数据
STRR1,[R0];写
设置了位段操作模式,对应的32MB区域将不能再使用。
4.4存储器大小端
大小端指的是数据存储时的顺序问题。
大端指的是高字节的数据放在低地址中,低字节放在高地址中,这种方式符合人类思维。
小端则是低字节放在低地址中,高字节放在高地址中,这种方式更符合计算机思维。
例如将0x12345678放到存储器0x2000-0x2003地址处
大端方式
地址
0x2003
0x2002
0x2001
0x2000
数据
0x78
0x56
0x34
0x12
小端方式
地址
0x2004
0x2003
0x2002
0x2001
数据
0x12
0x34
0x56
0x78
CM4处理器同时支持小端和大端的存储器系统。
CM的微控制器大多是小端的。
5异常和中断
5.1中断简介
所有的CORTEX-M处理器都会提供一个用于中断处理的嵌套向量中断控制器,也就是NVIC。
中断也属于异常的一种,其他异常包括如错误异常和其他用于OS支持的系统异常。
M4的NVIC支持最多240个IRQ(中断请求),1个不可屏蔽中断(NMI),1个SysTick(系统节拍)定时中断及多个系统异常。
异常编号
异常类型
优先级
描述
1
复位
-3
复位
2
NMI
-2
不可屏蔽中断
3
硬件错误
-1
硬件错误
4
MemManage错误
可编程
存储器管理错误
5
总线错误
可编程
总线错误
6
使用错误
可编程
程序错误
7-10
保留
11
SVC
可编程
请求管理调用
12
调试监控
可编程
调试监控
13
保留
14
PendSV
可编程
一般用于上下文切换
15
SYSTICK
可编程
系统节拍定时器
16
外部中断#0
可编程
片上外设或外部中断源产生
17
外部中断#1
可编程
…
…
…
255
外部中断#239
可编程
除了前3个异常的优先级是固定的,其余异常都可以修改优先级。
5.2异常类型
编号1-15为系统异常,16及以上的则为中断输入。
5.3中断管理
为了简化中断和异常管理,CMSIS-Core提供了多个访问函数。
函数
用法
VoidNVIC_EnableIRQ(IRQn_TypeIRQn)
使能外部中断
VoidNVIC_DisableIRQ(IRQn_TypeIRQn)
禁止外部中断
VoidNVIC_SetPriority(IRQn_TypeIRQn,uint32_tpriority)
设置中断的优先级
Void_enable_irq(void)
清除PRIMASK使能中断
Void_disable_irq(void)
设置PRIMASK禁止所有中断
VoidNVIC_SetPriorityGrouping(uint32_tpriorityGroup)
设置优先级分组
复位后,所有中断都处于禁止状态,且默认的优先级为0。
在使用任何一个中断之前需要
·设置所需中断的优先级(可选)
·使能外设中的可以触发中断的中断产生控制
·使能NVIC中的中断
在M4中,中断优先级共8位宽,但芯片厂商可进行设置,范围是3-8位。
中断优先级分为两个部分,分组优先级(也叫抢占优先级)和子优先级。
处理器首先判断的是分组优先级,分组优先级高的会被首先处理,若分组优先级相同,再比较子优先级。
8为宽的优先级如何分配抢占优先级和分组优先级,可由寄存器设置。
如下表
优先级分组
抢占优先级域
分组优先级域
0(默认)
Bit[7:
1]
Bit[0]
1
Bit[7:
2]
Bit[1:
0]
2
Bit[7:
3]
Bit[2:
0]
3
Bit[7:
4]
Bit[3:
0]
4
Bit[7:
5]
Bit[4:
0]
5
Bit[7:
6]
Bit[5:
0]
6
Bit[7]
Bit[6:
0]
7
无
Bit[7:
0]
这里要注意的是,异常编号和优先级并不是一个意思,异常编号仅仅是一个编号,就像是枚举一样,而优先级则是需要手动的进行设置的。
只有在分组优先级和子优先级完全一致时,异常编号才起作用,编号越小优先级越高。
另外,在M4内核中,还提供了中断向量重定位功能。
向量表重定位功能提供了一个名为向量表偏移寄存器(VTOR)的可编程寄存器。
前面提到的Bootloder就可以使用此项功能来完成。
5.4异常或中断屏蔽寄存器
5.4.1PRIMASK
PRIMASK用于禁止除NMI和HardFault外的所有异常,只能在特权状态访问如:
CPSIEI;清除PRIMASK(使能中断)
CPSIDI;设置PRIMASK(禁止中断)
5.4.2FAULMASK(M0中无)
FAULMASK用于禁止除NMI外的所有异常,只能在特权访问,如:
CPSIEF;清除FAULMASK
COSIDF;设置FAULMASK
5.4.3BASEPRI(M0中无)
BASEPRI可禁止优先级低于某特定等级的中断,只能在特权状态访问,如:
_set_BASEPRI(0X60);//禁止优先级在0x60-0xFF间的中断
_set_BASEPRI(0X0);//取消BASEPRI屏蔽
5.5中断状态及中断行为
5.5.1中断状态
中断状态:
inactive,pending,active,