3800个字彻底弄清cortex
 
- arm内核发展历史
 - cortexM0系列芯片系统框图
 - 通用寄存器
 - m0特殊寄存器
 - m3/m4/m7特殊寄存器 
  
- MSP和PSP
 - xPSR
 - PRIMASK
 - CONTROL
 - FAULTMASK
 - BASEPRI
 
  - 栈空间操作
 - 异常和中断 
   
 - NVIC可嵌套向量中断控制器
 - 系统操作寄存器 
  
- NVIC寄存器
 - 系统控制块SCB寄存器
 - SysTick寄存器
 
  - cortex-m0启动流程
 - 中断向量表
 - 大小端
 - 堆栈 
   
 - 杂项指令集
 - M0/M3/M4/M7区别
 - M3系统框图
 - M3快速开关中断汇编指令
 - M3内核CONTROL寄存器
 - 异常和中断
 - MPU存储器保护单元
 
 
arm内核发展历史
 
| arm内核 | 架构 | 
|---|
| arm7 | armv6 | 
| cortex-m0 | armv6-m | 
| cortex-m0+ | armv6-m | 
| cortex-m3 | armv7-m | 
| cortex-m4 | armv7-m | 
| cortex-m7 | armv7-m | 
| arm9 | ARMv6 | 
| arm11 | ARMv6 | 
| arm12 | ARMv6 | 
| cortex-a7 | armv7-a | 
| cortex-a8 | armv7-a | 
| cortex-a9 | armv7-a | 
| cortex-a15 | armv7-a | 
| cortex-A17 | armv7-a | 
| cortex-A53 | armv8 | 
| cortex-A57 | armv8 | 
| cortex-A72 | armv8 | 
 
cortexM0系列芯片系统框图
 

 
系统中包括:
 
- 中断控制器
 - M0内核
 - AHB总线
 - 存储器和外设
 - 电源管理
 - 时钟树
 - 调试系统
 
 
通用寄存器
 
| R0 | R1 | R2 | R3 | R4 | R5 | R6 | R7 | R8 | R9 | R10 | R11 | R12 | 
 
m0特殊寄存器
 
| SP(R13) | LR(R14) | PC(R15) | CONTROL | xPSR | PRIMASK | 
 
m3/m4/m7特殊寄存器
 
| SP(R13) | LR(R14) | PC(R15) | CONTROL | xPSR | PRIMASK | FAULTMASK | BASEPRI | 
 
MSP和PSP
 
msp中断中会使用,psp用于线程栈使用,通过配置CONTROL寄存器切换。
系统复位后默认使用msp,中断中也使用msp。
 
xPSR
 
IPSR可以用来判断当前处于什么中断。
 
PRIMASK
 
中断屏蔽寄存器,写1屏蔽所有中断(除了不可屏蔽中断和hardfault)
 
CONTROL
 
第1bit写1表示切换成PSP
 
FAULTMASK
 
屏蔽所有的fault (NMI不受影响)
 
BASEPRI
 
屏蔽所有优先级不高于某个具体数值的中断
 
栈空间操作
 
栈向下递减
栈指针始终指向栈的最后一个数据,每次执行数据存储前(push),SP会首先减小
 
异常和中断
 
 
 m0最多支持32个外部中断
 
 
系统异常
 
 
 主要用于操作系统和错误处理
 
 
| 异常类型 | 异常编号 | 说明 | 
|---|
| reset | 1 | 上电复位、系统复位 | 
| NMI | 2 | 不可屏蔽中断 | 
| hardfault | 3 | 硬件错误 | 
| SVCall | 11 | 系统调用 | 
| PendSV | 13 | 挂起系统调用 | 
| systick | 15 | 系统滴答 | 
 
NVIC可嵌套向量中断控制器
 
- 中断可嵌套
 - 相同优先级的中断不可嵌套
 - 相同中断不可嵌套
 
 
系统操作寄存器
 
实际上是许多的系统管理的寄存器
 
| 地址范围 | 寄存器说明 | 
|---|
| 0xE000E008 - 0xE000E00F | System Control Block Table | 
| 0xE000E010 - 0xE000E01F | 预留 | 
| 0xE000E010 - 0xE000E01F | SysTick操作寄存器 | 
| 0xE000E100 - 0xE000E4EF | NVIC操作寄存器 | 
| 0xE000ED00 - 0xE000ED3F | 系统控制块 | 
| 0xE000EF00 - 0xE000EF03 | NVIC | 
 
NVIC寄存器
 
| 地址 | 寄存器名称 | 说明 | 
|---|
| 0xE000E100 | ISER | 中断使能寄存器 | 
| 0xE000E180 | ICER | 中断失能寄存器 | 
| 0xE000E200 | ISPR | 中断挂起寄存器 | 
| 0xE000E280 | ICPR | 清除挂起中断的寄存器 | 
| 0xE000E400 - 0xE000E41C | IPR0-7 | 中断优先级配置寄存器 | 
 
系统控制块SCB寄存器
 
| 地址 | 寄存器名称 | 说明 | 
|---|
| 0xE000ED00 | CPUID | CPUID | 
| 0xE000ED04 | ICSR | 中断控制和状态寄存器 | 
| 0xE000ED0C | AIRCR | 应用中断和复位的寄存器 | 
| 0xE000ED10 | SCR | 系统控制寄存器 | 
| 0xE000ED14 | CCR | 配置控制寄存器 | 
| 0xE000ED1C | SHPR2 | System Handler Priority Register 2 | 
| 0xE000ED20 | SHPR3 | System Handler Priority Register 3 | 
 
SysTick寄存器
 
| 地址 | 寄存器名称 | 说明 | 
|---|
| 0xE000E010 | SYST_CSR | SysTick控制和状态寄存器 | 
| 0xE000E014 | SYST_RVR | SysTick重载寄存器 | 
| 0xE000E018 | SYST_CVR | SysTick当前值寄存器 | 
| 0xE000E01C | SYST_CALIB | SysTick校准寄存器 | 
 
cortex-m0启动流程
 
- 程序从0x00000000地址开始执行
 - m0从程序bin文件的开始处第2个word运行reset_handler
 - reset_handler函数开始执行一些必要的初始化(ramfunc函数复制,堆初始化,全局、静态变量初始化等)
 - 跳转到main函数中
 
 
中断向量表
 
| sp指针 | 
| resetHandler地址 | 
| NMIHandler地址 | 
| hardfault地址 | 
| reserved | 
| systickHandler地址 | 
| ...... | 
 
大小端
 
m0支持大端模式和小端模式,不过一般芯片公司选择小端模式。
 
堆栈
 
堆向上增长
栈向下增长
 
压栈的寄存器
 
 
杂项指令集
 
| 指令 | 说明 | 
|---|
| BKPT | 断点 | 
| CPSID | 关闭总中断 | 
| CPSIE | 打开总中断 | 
| DMB | 数据存储器隔离 仅当所有在它前面的存储器访问操作都执行完毕后,才开始后面的存储器访问操作 | 
| DSB | 数据同步隔离,比DMB更严格:仅当所有在它前面的存储器访问操作都执行完毕后,才开始后面的指令 | 
| ISB | 指令同步隔离,最严格: 会清洗流水线,保证所有它前面的指令都执行完毕之后,才执行后面的指令。 | 
| MRS | 从特殊寄存器读取数据到通用寄存器 | 
| MSR | 从通用寄存器读取数据到特殊寄存器 | 
| NOP | 空转指令 | 
| SEV | 产生event | 
| SVC | 产生SVC系统调用中断 | 
| WFE | 等待event | 
| WFI | 等待中断 | 
 
M0/M3/M4/M7区别
 
M0 armv6-M架构
 
M3 armv7-M架构
 多了basepri寄存器可以阻止某优先级或更低的优先级的中断。
 faultmask寄存器提供了更多的错误管理特性。
 CONTROL寄存器的bit0用于决定是特权模式还是用户线程模式
 32为thumb指令
 位段特性
 位域处理
 多处理器支持
 最多240个中断
 硬件除法
 存储器保护单元
 更多的调试和跟踪特性
 
M4 armv7-M架构
 浮点特性
 SIMD指令(单周期多指令)
 饱和算法
 单周期MAC(MAC乘法累加)
 
 
M3系统框图
 

 
M3快速开关中断汇编指令
 
| 指令 | 效果 | 说明 | 
|---|
| CPSID I | PRIMASK=1 | 关中断 | 
| CPSIE I | PRIMASK=0 | 开中断 | 
| CPSID F | FAULTMASK=1 | 关异常 | 
| CPSIE F | FAULTMASK=0 | 开异常 | 
 
M3内核CONTROL寄存器
 
- CONTROL[1]
 堆栈指针选择
 0=选择主堆栈指针 MSP(复位后缺省值)
 1=选择进程堆栈指针 PSP
 在线程或基础级(没有在响应异常——译注),可以使用 PSP。在 handler 模式下,只允许使用 MSP,所以此时不得往该位写 1。 - CONTROL[0]
 0=特权级的线程模式
 1=用户级的线程模式
 Handler 模式永远都是特权级的。 
 
异常和中断
 
 
 Cortex‐M3 支持大量异常,包括 16‐4‐1=11 个系统异常,和最多 240 个外部中断——简称 IRQ。
 
 
| 编号 | 类型 | 优先级 | 简介 | 
|---|
| 0 | N/A | N/A | 没有异常在运行 | 
| 1 | 复位 | -3(最高) | 复位 | 
| 2 | NMI | -2 | 不可屏蔽中断(来自外部 NMI 输入脚) | 
| 3 | 硬(hard) fault | -1 | 所有被除能的 fault,都将“上访”成硬 fault。除能的原因包括当前被禁用,或者 FAULTMASK 被置位。 | 
| 4 | MemManage | 可编程 | fault | 
| 5 | 存储器管理fault | 可编程 | MPU 访问犯规以及访问非法位置均可引发。企图在“非执行区”取指也会引发此 fault总线 fault从总线系统收到了错误响应,原因可以是预取流产(Abort)或数据流产,或者企图访问协处理器 | 
| 6 | 用法(usage) | 可编程 | Fault | 
| 7-10 | 保留 | N/A | N/A | 
| 11 | SVCall | 可编程 | 执行系统服务调用指令(SVC)引发的异常 | 
| 12 | 调试监视器 | 可编程 | 调试监视器(断点,数据观察点,或者是外部调试请求 | 
| 13 | 保留 | N/A | N/A | 
| 14 | PendSV | 可编程 | 为系统设备而设的“可悬挂请求”(pendable request) | 
| 15 | SysTick | 可编程 | 系统滴答定时器(也就是周期性溢出的时基定时器——译注) | 
| 16 | IRQ | #0 | 可编程 | 
| 17 | IRQ | #1 | 可编程 | 
| … | … | … | … | 
| 255 | IRQ | #239 | 可编程 | 
 
MPU存储器保护单元
 
Cortex‐M3 有一个可选的存储器保护单元。配上它之后,就可以对特权级访问和用户级访问分别施加不同的访问限制。当检测到犯规(violated)时,MPU 就会产生一个 fault 异常,可以由 fault异常的服务例程来分析该错误,并且在可能时改正它。MPU 有很多玩法。最常见的就是由操作系统使用 MPU,以使特权级代码的数据,包括操作系统本身的数据不被其它用户程序弄坏。MPU 在保护内存时是按区管理的(“区”的原文是 region,以后不再中译此名词——译注)。它可以把某些内存 region 设置成只读,从而避免了那里的内容意外被更改;还可以在多任务系统中把不同任务之间的数据区隔离。一句话,它会使嵌入式系统变得更加健壮,更加可靠(很多行业标准,尤其是航空的,就规定了必须使用 MPU 来行使保护职能——译注)。