CORTEXM4知识点总结文档格式.docx
《CORTEXM4知识点总结文档格式.docx》由会员分享,可在线阅读,更多相关《CORTEXM4知识点总结文档格式.docx(33页珍藏版)》请在冰豆网上搜索。
调试状态:
处理器被暂停后,就会进入调试状态,比如利用调试器触发断点,单步执行等。
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。
内核
性能
M0/M0+/M1
一般数据处理,IO控制人物
M3
高级数据处理、硬件除法
M4
SIMD、快速MAC饱和运算
3.3汇编指令简要介绍
3.3.1处理器内传送数据
MOV<
Rn目的寄存器>
<
Rm源寄存器>
源寄存器处可以是立即数,立即数为8位以下,9-16位用MOVW,32位的需要使用LDR伪指令。
使用浮点单元时可以使用VMOV指令。
3.3.2存储器访问指令
访问可分为读和写指令,另外根据读写的大小还有其他的延伸。
数据类型
加载(读)
存储(写)
8位无符号
LDRB
STRB
8位有符号
LDRSB
16位无符号
LDRH
STRH
16位有符号
LDRSH
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,<
reglist>
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#<
immed>
这样就可以进入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];
写回
读某一位:
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
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]
2]
Bit[1:
0]
3]
Bit[2:
4]
Bit[3:
5]
Bit[4:
6]
Bit[5:
Bit[7]
Bit[6:
7
无
这里要注意的是,异常编号和优先级并不是一个意思,异常编号仅仅是一个编号,就像是枚举一样,而优先级则是需要手动的进行设置的。
只有在分组优先级和子优先级完全一致时,异常编号才起作用,编号越小优先级越高。
另外,在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中断状态
中断状态:
inacti