MCU的寄存器与内存的基本数据结构

主要记录 CPU Core 的寄存器模式的通用知识点与特性知识点,主要基于ARMv7M的CortexM3,或者ARMv8架构的。CortexM3不支持ARM指令,只支持绝大部分的Thumb-2指令集。

记住:CPU CORE的 StackPointers 、 链表数据结构,都是内存相关的数据操作。栈操作“好像”比链表操作更加基础(或者原始prime)或者更加的必不可少,因为CPU CORE有专门的StackPointers寄存器,诚然!但是不代表链表更差,他们只是在不同的领域各有所长,只不过栈操作更加必不可少,链表通常用于数据的有机组织(比如OS操作系统里的操作系统core对象的组织管理),构建操作系统的一个基本工具,同样十分重要。栈内存数据结构对于计算机系统好比衣食住行对于个人;链表内存数据结构对于计算机好比互联网网络、手机信号对于个人,有了它才能做更大的事情,也是必不可少的部分!

通用知识点记录

Stack Pointer 栈指针寄存器 (基于CortexM3)

栈术语相关的特性:

栈是一种先进后出的逻辑数据结构;

STM32F103的R13 Stack Pointer是一个栈指针寄存器,指向内存的栈区;

不同的MCU架构,可能有不同SP寄存器硬件层次的设计,比如CortexM3就有两个Stack Pointers: Main_SP和Process_SP,但是在任意时刻,只有一个SP(R3)在工作; Armv8-M架构甚至有4个StackPointers.

栈空间是MCU中内存(RAM)中划分的一片物理内存区域;

RAM中的栈空间,用于存储数据,比如重要的中间数据(C语言的局部变量)、函数调用地址、当然也可以存储重要的全局变量(比如FreeRTOS Kernel V10.5.1中PendSV中的任务切换中的 pxCurrentTCB)等;这里多说一句,因此,FreeRTOS Kernel V10.5.1 的 PendSV 中涉及到了 Main_SP和Process_SP不同的R13的PUSH和POP,所以pxCurrentTCB是新任务的栈区地址。

RTOS或者OS的任务切换,会切换StackPointer等所有CPU-Core寄存器,也包括StackPointer指向的内存栈区数据的一整套任务的context switch。但是函数调用不存在SP寄存器的切换,它只是纵向的PUSH和POP。尽管两者都是PUSH-POP,还是有本质区别的!

R15, Program Counter (PC)

程序指令计数寄存器,指向下一条需要执行的指令代码;

一般“正常程序”中不存在修改PC寄存器;

OS/RTOS中任务切换,是存在切换刷新PC寄存器,且必须;

PC寄存器,可读,可写;

R14, Link Register (LR)

在子函数中,LR链接寄存器,用来专门保存主函数的指令运行的地址位置。

当子函数或者子过程快要结束时,将LR寄存器的值存入PC寄存器,恢复到主函数的指令执行位置,会恢复到主函数中继续运行。在子函数或者子过程结束后,LR的值也会自动从栈区更新。

当调用子函数时,需要保存主函数的指令运行位置到LR寄存器中,否则主函数执行位置数据会丢失。主主函数的指令运行位置(即主函数的LR)则在退出主函数之后和进入子函数之前,被PUSH压栈,在从子函数切入主函数时,被POP出栈。

Armv8-M下的主要寄存器介绍

【引用:Introduction to the Armv8-M Architecture and its Programmers Model】

R13, Stack Pointer (SP)

R13 is the Stack Pointer (SP). It is used for accessing the stack memory, for example with PUSH and POP instructions. When the processor pushes new data onto the stack, it decrements the stack pointer and then writes the data to the memory location. Physically, there can be either two or four different stack pointers.

If the Security Extension is not implemented, then there are two stack pointers:

Main stack pointer, commonly referred to as MSP or SP_Main

The MSP is the default stack pointer used at reset, and is used for all exception handling.

Process stack pointer, commonly referred as PSP or SP_Process

The PSP is the alternative stack pointer that can only be used in thread mode, and is usually used for application tasks of the operating system (OS).

Stack pointer selection is determined by the special register called CONTROL. The SPSEL field in the CONTROL register can be programmed to select between stack pointers for thread mode stack operations as follows:

  • Set SPSEL to 0 to select MSP.
  • Set SPSEL to 1 to select PSP.

In normal program execution, only one of these stack pointers will be active. Though both MSP and PSP are 32-bit registers, the lowest two bits of the stack pointers are always zero, and writes to these two bits are ignored. The stack memory operations such as PUSH and POP are always 32-bit. Refer to Stack memory for more information about PUSH and POP operations with stack memory.

If an operating system is used, the stack for each of the application threads will be separated from each other. The PSP enables application threads to switch contexts without affecting the stack used by privileged code. The stack selected on an exception return is based on the SPSEL bit in the EXC_RETURN payload value which is automatically stacked on exception entry. This is shown in the following diagram:

Figure 1. PSP stacking and unstacking

Warning

Software must never place any data below the current stack pointer position. Stacking on exception entry can occur at any time (for example, in response to an interrupt) and can overwrite any data below the stack pointer.

If the Security Extension is implemented in a system, then there are four stack pointers:

  • Main Stack Pointer for Non-secure state (MSP_NS)
  • Process Stack Pointer for Non-secure state (PSP_NS)
  • Main Stack Pointer for Secure state (MSP_S)
  • Process Stack Pointer for Secure state (PSP_S)

The stack pointers are banked when the Security Extension is implemented. In both Secure and Non-secure states, the processor implements the main stack and the process stack, with a pointer for each held in independent registers. The _S and _NS suffixes identify whether the stack pointer is for the Secure state or Non-secure state.

The following table shows which stack pointer is banked between Secure and Non-secure states:

Stack Pointer

Secure State

Non-secure State

Main Stack Pointer

MSP_S

MSP_NS

Process Stack Pointer

PSP_S

PSP_NS

R15, Program Counter (PC)

R15 is the Program Counter (PC). It is readable and writable. A read returns the current instruction address + 4 while writing to a PC (for example using data processing instructions) causes a branch operation.

Since all instructions must be aligned to halfword or word addresses, the Least Significant Bit (LSB) of the PC is always zero. However, when using branch and memory read instructions to update the PC, you will need to set the LSB of new PC values to 1 to indicate the Thumb state. If the LSB of PC is not set to 1, then it results in a UsageFault or HardFault fault exception.

In high-level programming languages, including C and C++, the compiler automatically sets the LSB in branch targets. Out of reset, the PC is initialized by the value from reset vector address location as a part of the hardware startup sequence.

All the registers from the register bank can be accessed (read or write) using debug software when the processor is in halted Debug state.

R14, Link Register (LR)

R14 is also called the Link Register (LR). This holds the return address when calling a function or subroutine.

At the end of a function or subroutine, the callee function can return to the calling function and resume by loading the value of LR into the Program Counter (PC). When a function or subroutine call is made, the value of LR is updated automatically.

If a callee function needs to call another function, it needs to save the value of LR in the stack, otherwise the current value in LR will be lost when the function call is made. During exception entry, the LR is updated automatically to a special EXC_RETURN (exception return) payload value. At the end of the exception handler the software branches to the EXC_RETURN value in LR. The processor detects a branch to this special address and triggers the exception return process. This enables exception handlers to be written directly in C, without the need for an assembly wrapper around the body of the exception handler. Further details on the exception entry and exit process will be covered in the Armv8-M Exception Model User Guide.

  • 17
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值