【STM32Cube开发记录】5-核心寄存器和存储器映射

1. 寄存器

Cortex-M系列的MCU都有15个通用的32位寄存器。有几个有特殊用途也有别的名字。

  • R0~R12:可用作ARM指令的操作数。
  • R13:  SP (堆栈指针)。MSP是主堆栈指针,通常用于处理异常、中断以及初始化系统。PSP是进程堆栈指针,也被称为线程堆栈指针。每个线程或进程都有一个独立的PSP,用于管理其自己的堆栈。当处理器从处理一个中断返回到线程的上下文时,PSP通常用于恢复线程级别的堆栈。这使得不同的线程可以并发运行,每个线程都有自己的堆栈。
  • R14:LR(链接寄存器)。通常用于存储函数调用的返回地址。当一个函数被调用时,当前函数的返回地址被保存在LR寄存器中,以便在函数返回时能够回到调用点。
  • R15:PC(程序计数器)。包含了当前执行指令的内存地址,即下一条将要执行的指令的地址。PC是用来控制程序的执行顺序,它不是通用寄存器,而是用于处理指令跳转的目的。
  • PSR:程序状态寄存器,包含多种状态信息,包括处理器的当前程序状态、优先级、中断状态等。
  • PRIMASK: 用于屏蔽所有可屏蔽的中断。1 表示屏蔽中断,0 表示允许中断。
  • FAULTMASK: 用于屏蔽所有异常,包括硬故障。1 表示屏蔽所有异常,0 表示允许异常。
  • BASEPRI: 用于设置中断屏蔽的优先级阈值。所有优先级高于 BASEPRI 的中断将被屏蔽。
  • CONTROL:控制寄存器,用于控制处理器的特定功能,比如选择堆栈指针、切换到特权级或者非特权级等。
  • (FPU)S0-S31: 32 个 32 位的单精度浮点寄存器。用于存储浮点数操作数和结果。这些寄存器也可以作为 SIMD (单指令多数据) 运算的寄存器。
  • (FPU)FPSCR: 32 位寄存器,包含浮点运算的状态标志、控制位和例外标志。

寄存器也可以分为参数(或暂存)寄存器和变量寄存器。参数寄存器用于在函数之间传递参数,变量寄存器用于函数中存储和处理变量值。在Cortex-M处理器中,寄存器的用途通常不以参数寄存器和变量寄存器的方式明确划分,而是由程序员和编译器来管理。

2. 存储器映射

ARM 定义了一个标准化的内存地址空间,适用于所有 Cortex-M 内核,确保不同制造商之间的代码可移植性。地址空间宽度为 4GB,并按不同逻辑功能组织成若干子区域。这4GB本身并不具有所谓的内存地址信息的,是由厂商或用户进行分配的。给存储器分配的这个过程就是存储器映射。几个重要的存储器映射。下面介绍这些子区域:

2.1 Code Area

  • Flash

一共512MB,地址从0x00000000开始,但是我们的代码是放到0x8000000开始的Flash区,比如我们的F103C8T6,一共512KB。

  • System memory

里面存的是 ST 出厂时 烧 写 好 的 isp 自 举 程 序 ( 即 Bootloader),用户无法改动。串口下载的时候需要用到这部分程序。

  • Option bytes

用 于 配 置 读 写 保 护 、 BOR 级别、软件/硬件看门狗以及器件处于待机或停止模式下的复位。当芯片不小心被锁住之后,我们可以从 RAM 里面启动来修改这部分相应的寄存器位。

  • Boot configuration

由boot引脚选择映射主Flash,系统存储器还是SRAM。

2.2 SRAM

STM32微控制器中的SRAM(Static Random Access Memory,静态随机存取存储器)扮演着几个关键角色,其作用如下:

1. 临时数据存储:SRAM用于存储临时数据和变量,这些数据在程序执行过程中需要快速访问和修改。
2. 高速缓存:SRAM可以作为CPU的缓存,提高数据访问速度,因为SRAM的访问速度通常比闪存(Flash)快得多。
3. 中断服务例程:当微控制器响应中断时,中断服务例程(ISR)可能会使用SRAM来存储局部变量,这些变量只在中断处理期间使用。
4. 堆栈:SRAM用于存储程序的调用堆栈,即在函数调用过程中保存返回地址和局部变量。
5. 数据缓冲:在数据传输过程中,SRAM可以作为缓冲区,暂存从外部设备接收的数据或待发送的数据。
6. 配置数据:某些STM32微控制器使用SRAM来存储配置数据,这些数据在系统启动时加载,可能影响系统的运行模式或行为。
7. 实时性能:由于SRAM的读写速度快,它对于需要实时性能的应用至关重要,比如工业控制系统或实时操作系统。
8. 易失性存储:SRAM是易失性的,意味着在断电后数据会丢失。这使得SRAM适合存储那些在系统运行期间需要频繁修改的数据。
9. 低功耗:与动态随机存取存储器(DRAM)相比,SRAM在保持数据时不需要刷新周期,因此功耗较低。
10. 系统初始化:在系统启动过程中,SRAM可能用于存储引导加载程序(Bootloader)的临时数据,直到程序从Flash加载到SRAM并开始执行。

SRAM的区域从地址 0x2000 0000 开始,并可能扩展到 0x3FFF FFFF。但是,实际的结束地址取决于内部SRAM的有效量。例如,对于具有64KB SRAM的MCU,最终地址为0x2000 FFFF。尝试访问此区域之外的位置将导致总线故障异常

位带操作

因为STM32一次只能操作8位,16位,32位。不支持操作单独的位。比如如果想要控制某个寄存的一位置0还是置1,需要先把整个寄存器读出来,然后改写,改写之后再写回去。这样效率就比较低:

uint8_t temp = 0; 
temp |= 0x4; 
temp &= ~0x4;

分析上述代码的汇编

# temp |= 0x4; 
ldrb r3, [r7, #7] //从内存地址r7+7加载temp的值到r3里
orr.w r3, r3, #4  //对寄存器r3进行逻辑或的操作,将bit3设置为1
strb r3, [r7, #7] //将寄存器r3的值写回内存地址r7 + 7,更新temp的值
# temp &= ~0x4;
ldrb r3, [r7, #7] //从内存地址r7+7加载temp的值到r3里
bic.w r3, r3, #4  //对寄存器r3进行逻辑与的操作,将bit3设置为0
strb r3, [r7, #7] //将寄存器r3的值写回内存地址r7 + 7,更新temp的值

这样的操作需要三条指令,获取值,然后修改,然后存储。这样会导致两个问题,第一,与这三条指令相关的CPU周期被浪费掉了。第二,如果是并发的执行这个代码,另一个任务可能会在完成修改值之前影响内存的内容。
位带操作就是将内存中特定区域的每个位映射到bit-band区域的字中。从而实现对该位的访问。因为就可以一次性操作32位了,想要写1还是0,直接对这个32位操作就行了。别名字的位[31:1]在 bit-band 位上不起作用。写入 0x01 与写入 0xFF 的效果相同。写入 0x00 与写入 0x0E 的效果相同。读别名区的一个字返回 0x01 或 0x00。0x01 表示 bit-band 区中的目标位置位。0x00 表示 目标位清零。位[31:1]将为 0。

比如对0x20000000(前8位)映射到0x2200001c的地方。如果需要修改0x20000000的第2位,可以访问0x20000008

 计算位带区域的公式如下:

bit_band_address = alias_region_base + (region_base_offset x 32) + (bit_number x 4)
比如上面的映射bit2
alias_region_base = 0x22000000

region_base_offset = 0x20000000 - 0x20000000 = 0
bit_band_address = 0x22000000 + 0 * 32 + (0x2 *0x4) = 0x22000008

ARM为基于Cortex-M3/4的MCU定义了两个bit-banding区域,每个区域宽度为1MB,映射到32Mbit的bit-banding别名区域。一个在SRAM,一个在外设里。

2.3 peripherals(外设)

片内外设的地址。比如我们想操作GPIOA的输出寄存器GPIO->ODR,从0x4002 0014(前面那个寄存器的地址)开始映射。如果我们想修改GPIOA的PIN5脚的状态,使用前面的公式(从上图看出bit-band别名区域基地址)
alias_region_base = 0x42000000
region_base_offset = 0x40020014 - 0x40000000 = 0x20014
bit_band_address = 0x42000000 + 0x20014*32 + (0x5 x 0x4) = 0x42400294
可以在C代码中实现这个操作

#define BITBAND_PERI_BASE 0x40000000
#define ALIAS_PERI_BASE 0x42000000
#define BITBAND_PERI(a,b) ((ALIAS_PERI_BASE + ((uint32_t)a-BITBAND_PERI_BASE)*32 + (b*4)))

#define GPIOA_PERH_ADDR 0x40020000    //GPIOA的地址
#define ODR_ADDR_OFF 0x14             //GPIOA的ODR相对GPIOA的偏移

uint32_t *GPIOA_ODR = GPIOA_PERH_ADDR + ODR_ADDR_OFF //GPIOA的ODR地址
uint32_t *GPIOA_PIN5 = BITBAND_PERI(GPIOA_ODR, 5)    //GPIOA的ODR的第5位在bit-banding 别名地址

*GPIOA_PIN5 = 0x1

2.4 External RAM & External Device

这2GB用于外接SRAM或Flash,Cortex-M设备可以通过EMI/FSMC接口执行代码和进行外部存储器的数据读写,从而扩展内部内存资源。

2.5 Private Internal peripherals and External peripherals

对 ITM、NVIC、FPB、DWT、MPU 的访问在处理器内部专用外 设总线上执行。对 TPIU、ETM 和 PPB 存储器映射的系统区域的 访问在外部专用外设总线上执行。

 2.6 Vendor Specific

厂商系统外设的系统部分。

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值