ARMCortexM3学习

ARMCortexM3 on FPGA及Keil调试

Posted by Florian on February 26, 2019

ARM Cortex-M3简介

Cortex-M3是ARM于2005年发布的第一个Cortex处理器,使用32位架构,寄存器组中的内部寄存器,数据通路以及总线接口都是32位的。Cortex-M处理器使用的指令集架构为Thumb ISA,其基于Thumb-2技术并同时支持16位和32位指令。

我为什么学习ARM Cortex-M3

感谢ARMDesignStart FPGA项目,让我可以有机会学习研究M3,这也是以后学习RISC-V的一个过渡。

当然还有项目需要。。这就不谈。

参考书目

首先是ARM公司专家Joseph Yiu的《ARM Cortex-M3与ARM Cortex-M4权威指南》第3版

还有一本经典的白算盘书,David A.Patterson和John L.Hennessy合著的《计算机组成与设计-硬件软件接口》ARM第5版

还有一些参考资料是ARMDesignStart FPGA项目的文档,在网站上可以免费下载

一些概述

首先是Cortex-M3处理器框图

Cortex-M3具有三级流水线(取指、译码和执行),基于哈佛总线架构,取指令和数据访问可以同时进行

随着Thumb-2技术的引入,Cortex-M处理器无须状态切换

存储器系统

  • 程序存储器,一般是Flash
  • 数据存储器,一般是SRAM
  • 外设

总线接口协议为AHB Lite,用于程序存储器和系统总线接口

中断控制器NVIC(后面补充)

Cortex-M3的优点很多,性能强大,低功耗,易于使用(调试方便),可扩展性和兼容性好

指令集

ARM Cortex-M处理器都基于Thumb-2技术,允许在一种操作状态下混合使用16位和32位指令

从使用中学习指令,学过微机原理以后对基本的指令还是比较清楚

C和汇编混合编程

存储器系统

存储器映射

存储器空间在架构上被划分为SRAM、代码、外设、RAM、设备、系统等多个存储器区域

程序不允许在外设、设备和系统存储器区域中执行

处理器和存储器、外设的连接

AHB Lite(主要总线接口) & APB(私有外设总线,主要用于调试)

程序存储器一般会被连接到I-CODE和D-CODE总线,而SRAM和外设会被连到系统总线,如图

可以利用I-CODE和D-CODE接口实现Flash访问加速器,这样处理器可以比Flash存储器的访问速度快

总线系统中还可以用总线矩阵、多层AHB等技术

注意:虽然使用SRAM和RAM作为存储器区域的名称,但连接到处理器的存储器种类(即物理意义上的存储器)是没有限制的

大端 or 小端?

大端,高低低高

小端,高高低低

在Cortex-M处理器中:

  • 取指总是处于小端模式
  • 对包括系统控制空间(SCS)、调试部件和私有外设总线(PPB)在内的0xE0000000~0xE00FFFFF区域的访问总是小端的

位段操作

利用位段操作,一次load/store操作可以访问一个位(而不是一个字节,一般来说一个地址对应的是8bit=1byte)

在Cortex-M3中,两个名为位段区域的预定义存储器区域支持这种操作,其一位于SRAM区域的第一个1MB,另一个位于外设区域的第一个1MB

使用位段别名地址时,每个位都可以通过对应的字对齐地址的最低位(LSB)单独访问

通过两种方式的汇编代码解释其区别

例如,要设置地址0x20000000处字数据的第2位,不使用位段,汇编代码可以这样写

LDR R0, =0x20000000

LDR R1, [R0]

ORR.W R1, #0x4

STR R1, [R0]

而使用位段时,可以这样写

LDR R0, =0x22000008

MOV R1, #1

STR R1, [R0]

这个0x22000008是什么意思呢?

请看下图

由图中对应关系知道,0x22000008对应的位段区域是地址0x20000000 的bit[2]

当访问位段别名地址(0x22000008)时,该地址就会被重映射到位段地址(0x20000000 bit[2])

对于读,字被读出且选定位的位置被移到读返回数据的LSB

对于写,待写的位数据被移到所需的位置,然后执行读-修改-写操作

可进行位段操作的SRAM区域(0x20000000~0x200FFFFF) 和 外设区域(0x40000000~0x400FFFFF),大小都是1MB

可以应用于串行数据传输(涉及到的操作都是基于1bit的)

微控制器中的存储器系统

将Bootloader放入系统的作用

  • 提供Flash编程功能,可以利用一个简单的UART接口来编程Flash
  • 提供通信协议栈等额外的固件,可被软件开发人员通过API调用
  • 提供芯片内置的自检功能(BIST)

存储器重映射:对于Bootloader不是位于地址0的情况

异常和中断

中断一般是由硬件(外设、外部输入引脚)产生的事件,会引起程序流偏离正常的流程。当外设或硬件需要处理器的服务时,一般会出现下面的流程:

  • 外设确认到处理器的中断请求
  • 处理器暂停执行当前任务
  • 处理器执行外设的中断服务程序(ISR),如有必要可以选择由软件清除中断请求
  • 处理器继续执行之前暂停的任务

优先级的定义

对于Cortex-M处理器异常是否能被处理器接受以及何时被处理器接受并执行异常处理,是由异常的优先级和处理器当前的优先级决定的。更高优先级的异常可以抢占低优先级的异常,这就是异常/中断嵌套

Cortex-M3在设计上具有3个固定的最高优先级以及256个可编程优先级(最多128个抢占等级)

中断优先级由优先级寄存器控制,宽度为3~8位

为什么8位优先级配置寄存器只有128个抢占等级?因为另外128个等级是子优先级,类似于排字典序的时候,当抢占等级相同时才比较子优先级

向量表和重定位

当处理器接受某异常请求后,需要确定该异常处理的起始地址。该信息位于存储器内的向量表中,向量表默认从地址0开始,向量地址为异常编号乘4

什么是重定位?

一般情况下起始地址(0x00000000)处为启动存储器,它可以为Flash存储器或ROM设备,并且在运行时不能对他们进行修改。不过,有些应用可能需要在运行时修改或定义向量表。为了进行这种处理,Cortex-M3实现了向量表重定位的特性

重定位可以用于多种情形

具有Boot Loader的设备,应用程序加载到RAM,动态修改向量表

中断输入和挂起

每个中断都有多种属性

  • 每个中断都可被禁止或使能
  • 每个中断都可被挂起或解除挂起
  • 每个中断都可处于活跃或非活跃状态

NVIC中包含了多个可编程寄存器,它们可用于中断使能控制,挂起状态和只读的活跃状态位

挂起状态是中断被置于一种等待处理器处理的状态

关于这个问题有很多种情况,具体参见《权威指南》P170

异常流程简介

接受异常请求

当满足下列条件,处理器会接受请求

  • 处理器正在运行
  • 异常处于使能状态
  • 异常的优先级高于当前等级
  • 异常未被异常屏蔽寄存器屏蔽

异常进入流程

  1. 多个寄存器和返回地址被压入当前使用的栈
  2. 去除异常向量(异常处理/ISR的起始地址)
  3. 取出待执行异常处理的指令
  4. 更新多个NVIC寄存器和内核寄存器

执行异常处理

处理器处于处理模式

  • 栈操作使用主栈指针(MSP)
  • 处理器运行在特权访问等级

如果更高优先级的异常产生, 处理器会接受新的中断,这种情况为异常嵌套

异常处理的结尾,程序代码执行的返回会引起EXC_RETURN数值被加载到程序计数器(PC)中,并触发异常返回机制

NVIC寄存器细节

留着以后用的时候再研究…

Keil

Keil MDK编译流程如图