本文首发于稀土掘金。该平台的作者 逐光而行 也是本人。
Cortex-M3内核原理
Cortex-M3微处理器内部结构
处理器体系结构
处理器内核
内核主要包括:
- CPU
- NVIC(Nested Vector Interrupted Controller)(嵌套向量中断控制器)
- 系统时钟(SYSTICK)
- 存储器保护单元(MPU)
- 总线矩阵
总线结构
总线分类:
- AHB(advanced high performance bus)
支持突发模式数据传输和事务分割
- ASB(system)
较老的格式,已被AHB替代
- APB(peripheral)
用于较低性能外设的简单连接,一般是二级总线
总线地址范围
cortex-v3采用哈佛结构。
哈佛结构:程序指令与数据分开存储的存储器结构
- I-Code指令总线基于AHB-Lite总线协议的32位总线,默认映射到 0x00000000~0x1FFFFFFF内存地址段,主要用于取值操作。
- D-Code指令总线基于AHB-Lite总线协议的32位总线,默认映射到 0x00000000~0x1FFFFFFF内存地址段,主要用于数据访问操作。
- 通过上述两条总线能并行实现对应地址段中对应闪存存储器中指令与数据的访问。
- 系统总线 基于AHB‐Lite总线协议的32位总线,默认映射到0x20000000~0xDFFFFFFF和0xE0100000~0xFFFFFFFF两个内存地址段,用于访问内存和外设,即SRAM,片上外设,片外RAM,片外扩展设备以及系统级存储区。
- 外设总线 基于APB总线协议的32位总线,用于访问私有外设,默认映射到0xE0040000~0xE00FFFFF内存地址段。由于TPIU、ETM以及ROM表占用部分空间,实际可用地址区间为0xE0042000~0xE00FF000。
寄存器
寄存器组介绍
- 绝大多数16 位Thumb 指令只能访问R0‐R7,而32 位Thumb‐2 指令可以访问所有寄存器。
关于R13:任意时刻只能使用两个堆栈指针中的一个
- MSP(main):用于复位(置零)后缺省使用的
- PSP(process stack):由用户的应用程序代码使用
- 注:堆栈总是4字节对齐的。因为R13的最低两位被硬线连接到0,故堆栈指针的最低两位永远是0
- 关于R14(连接寄存器):把返回地址直接存储在寄存器中
关于R15(PC):
- Cortex-M3中的指令是隶属于Thumb2指令集,且至少是半字对齐的,所以PC的LSB总是读回0。
- 在编写分支指令时,无论是直接写PC的值还是使用分支指令,都必须保证加载到PC的数值是奇数(即LSB=1),用以表明当前指令在Thumb-2状态下执行。
- Cortex-M3内部使用了指令流水线,读取PC内容时返回的值是当前指令的地址+4
如:0x1000: MOV R0, PC;R0 = 0x1004
三类特殊功能寄存器
- program status register
中断屏蔽寄存器(PRIMASK,FAULTMASK,BASEPRI)
- PRIMASK:1bit;1表示关中断,只剩NMI和硬fault可以响应。
- FAULTMASK:1bit;1表示只有NMI可响应。
- BASEPR:最多9bits。定义了一个基准(阈值)。所有优先级大于改制的中断都将被关闭(因为数字越小越优先,数字越大越靠后)
- CONTROL
有两位
- CONTROL\[0]:
- 赋0表示特权级的线程模式,赋1表示用户级的线程模式
- **写操作:仅在特权级操作下被允许**
- **用户级返回特权级**的唯一途径:**触发中断异常**,再由中断服务例程改写该位。
- Handler模式永远是特权级的。
- CONTROL\[1]:表示堆栈指针的选择
- 0表示选MSP,1表示选PSP(Handler模式下只准选MSP)
- **写操作:尽在特权级的线程模式下被允许**
存储空间分配
- 32位处理器,支持4GB存储空间
- 预定义存储器映射和总线配置
- 支持非对齐访问和互斥访问
- 支持小端和大端两种存储格式(默认小端)
注:指令预取、配置控制存储空间访问、私有外设总线区0xE000_0000至 0xE00F_FFFF永远是小端模式
- 支持bit-band操作
cortex-m3微处理器固定的存储映射如下:
位带操作(bit-band)
概念
将多个MB别名区的访问映射为对某1MBbit-band区的访问。
映射公式:
bit_word_addr =
bit_band_alias_base + (byte_offset×32) + (bit_number×4)
– bit_word_addr 是别名存储器区中字的地址,它映射到某个目标位。
– bit_band_alias_base 是别名区的基址,即起始地址。
– byte_offset 是包含目标位的字节在位带区里的序号。
– bit_number 是位带区目标位所在字节中的位置(0-7)。
用途
- 方便对串行接口器件操作
- 简化跳转的判断
- 并发控制
实操————c语言程序
c编译器并没有直接支持位带操作。它并不知道同一块内存能够使用不同的地址来访问,也不知道对位带别名区的访问只对LSB 有效。
想要在c中用位带操作,可#define一个位带别名区的地址。
如:
#define DEVICE_REG0 *((volatile unsigned long *) (0x40000000))
#define DEVICE_REG0_BIT0 *((volatile unsigned long *) (0x42000000))
#define DEVICE_REG0_BIT1 *((volatile unsigned long *) (0x42000004))
注:要访问的变量必须使用volatile定义