• Cortex-M3/M4基础


    一、Cortex-M3/M4 通用寄存器

    1、我们首先来了解一下M3/M4的寄存器,M4比M3多了一个浮点单元FPU。其他的部分基本和M3是一样的。

    2、Cortex-M3/M4系列处理器拥有通用寄存器R0-R15以及一些特殊功能的寄存器。

    3、R0‐ R12 是最“通用目的”的。

    4、但是绝大多数的 16 位指令只能使用 R0‐ R7(低组寄存器),而 32 位的 Thumb‐ 2 指令则可以访问所有通用寄存器。这里提到Thumb-2指令,我简单地介绍一下。

    Thumb-2是一种精简指令集(RISC)架构,最初由ARM公司开发,并广泛用于ARM处理器上。Thumb-2指令集是ARM指令集的一个扩展,旨在提高代码密度和执行效率

    Thumb-2指令集提供了两种指令集状态:Thumb状态和Thumb-2状态。在Thumb状态下,指令长度为16位,相对于32位的ARM指令来说,代码密度更高。在Thumb-2状态下,指令长度可以是16位或32位,这样就可以运行更复杂的指令,提高程序的执行效率。

    Thumb-2指令集具有以下特点:

    1. 兼容性:Thumb-2指令集能够与之前的Thumb指令集和ARM指令集兼容,既可以在Thumb状态下执行16位指令,也可以在Thumb-2状态下执行32位指令。
    2. 代码密度:Thumb-2指令集通过使用16位指令来减小代码大小,从而提高代码密度。这对于存储空间受限或带宽有限的嵌入式系统尤为重要。
    3. 执行效率:Thumb-2指令集在Thumb-2状态下可以执行更复杂的指令,包括对大多数ARM指令的支持,从而提高执行效率和系统性能。

    总而言之,Thumb-2指令集是ARM处理器上一种具有代码密度和执行效率优势的指令集,适用于各种嵌入式系统和移动设备应用。

     5、特殊功能寄存器有预定义的功能,而且必须通过专用的指令来访问, Cortex-M3/M4 的通用寄存器如图所示。

    基于上图,我将逐一讲解各种寄存器的作用。

    1)通用目的寄存器 R0-R7

    R0‐ R7 也被称为低组寄存器。所有指令都能访问它们。它们的字长全是 32 位,复位后的初始值是不可预料的。
    2)通用目的寄存器 R8-R12

    R8‐ R12 也被称为高组寄存器。这是因为只有很少的 16 位 Thumb 指令能访问它们,32位的指令则不受限制。它们也是 32 位字长,且复位后的初始值是不可预料的。

    3)堆栈指针 R13

    R13 是堆栈指针。在 CM3/CM4 处理器内核中共有两个堆栈指针,于是也就支持两个堆栈。当引用 R13(或写作 SP)时,你引用到的是当前正在使用的那一个,另一个必须用特殊的指令来访问( MRS,MSR 指令)。这两个堆栈指针分别是:


    (1)、主堆栈指针(MSP),或写作 SP_main。这是缺省的堆栈指针,它由 OS 内核、异常服务例程以及所有需要特权访问的应用程序代码来使用。


    (2)、进程堆栈指针(PSP),或写作 SP_process。用于常规的应用程序代码(不处于异常用例程中时)。要注意的是,并不是每个应用都必须用齐两个堆栈指针。简单的应用程序只使MSP 就够了。堆栈指针用于访问堆栈,并且 PUSH 指令和 POP 指令默认使用 SP


    4)连接寄存器 R14
    1、R 1 4 是连接寄存器( L R)。在一个汇编程序中,你可以把它写作 b o t h LR 和 R14。

    2、LR 用于在调用子程序时存储返回地址。例如,当你在使用 BL(分支并连接, Branch and Link)指令时,就自动填充 LR 的值。尽管 PC 的 LSB 总是 0(因为代码至少是字对齐的), LR 的 LSB 却是可读可写的。这是历史遗留的产物。在以前,由位 0 来指示 ARM/Thumb 状态。因为其它有些 ARM 处理器支持 ARM 和 Thumb 状态并存,为了方便汇编程序移植, CM3/CM4 需要允许 LSB 可读可写。

    5)程序计数器 R15
    1、R15 是程序计数器,在汇编代码中你也可以使用名字“PC”来访问它。
    2、因为 CM3/CM4内部使用了指令流水线,读 PC 时返回的值是当前指令的地址+4。

    例如:

    ox1000: MOV   R0,  PC   ;    R0 = 0x1004

    3、如果向 PC 中写数据,就会引起一次程序的分支(但是不更新 LR 寄存器)。CM3/CM4中的指令至少是半字对齐的,所以 PC 的 LSB 总是读回 0。

    4、在分支时,无论是直接写 PC 的值还是使用分支指令,都必须保证加载到 PC 的数值是奇数(即 LSB=1),用以表明这是在 Thumb 状态下执行。倘若写了 0,则视为企图转入 ARM 模式,将产生一个 fault异常。

    6)特殊功能寄存器组

    1、程序状态寄存器组( PSRs 或者 xPSR)

    2、中断屏蔽寄存器组( PRIMASK, FAULTMASK,以及 BASEPRI)

    3、控制寄存器( CONTROL)

    注意:它们只能被专用的 MSR 和 MRS 指令访问,而且它们也没有存储器地址

    MRS
    MSR
    ,
    ,

    ; 读特殊功能寄存器的值到通用寄存器
    ; 写通用寄存器的值到特殊功能寄存器

     7)程序状态寄存器(PSRs 或曰 PSR)

    1、应用程序 PSR( APSR)

    2、中断号 PSR( IPSR)

    3、执行 PSR( EP SR)

    说明:通过 M RS / M S R 指令,这 3 个 PSR s 既可以单独访问,也可以组合访问( 2 个组合, 3 个组合都可以)。当使用三合一的方式访问时,应使用名字“ xPSR”或者“ PSR”。三个寄存器的各个位的含义如下图。

    PRIMASK,FAULTMASK 和 BASEPRI
    这三个寄存器很重要,这三个寄存器用于控制异常的使能和除能,这三个寄存器的介绍如下图:


     

     说明:对于时间‐关键任务而言, PRIMASK 和 BASEPRI 对于暂时关闭中断是非常重要的。 而
    FAULTMASK 则可以被 OS 用于暂时关闭 fault 处理机能,这种处理在某个任务崩溃时可能需要。因为在任务崩溃时,常常伴随着一大堆 faults。在系统料理“后事”时,通常不再需要响应这些 fault——人死帐清。总之 FAULTMASK 就是专门留给 OS 用的。

    要访问 PRIMASK, FAULTMASK 以及 BASEPRI,同样要使用 MRS/MSR 指令,如:

    MRS R0,
    MRS R0,
    MRS R0,
    MSR BASEPRI,
    MSR FAULTMASK,
    MSR PRIMASK,
    BASEPRI
    FAULTMASK
    PRIMASK
    R0
    R0
    R0
    ; 读取 BASEPRI 到 R0 中
    ; 同上
    ; 同上
    ; 写入 R0 到 BASEPRI 中
    ; 同上
    ; 同上

    只有在特权级下,才允许访问这 3 个寄存器, 为了快速地开关中断, CM3/CM4 还专门设置了一条 CPS 指令,有 4 种用法,这四种用法非常重要,我们在移植 UCOS 操作系统的时候就是用这下面的方法来开关中断的。

    CPSIDI;PRIMASK=1,; 关中断
    CPSIEI;PRIMASK=0,; 开中断
    CPSIDF;FAULTMASK=1, ; 关异常
    CPSIEF;FAULTMASK=0; 开异常

     8)控制寄存器(CONTROL)

    CONTROL 寄存器用于定义特权级别和堆栈指针的使用, CONTROL 寄存器如下表 所示,注
    意 CONTROL[2]只有 Cortex-M4 才有。

     CONTROL[2]
    Cortex-M4 中有 FPU 单元如果我们使用了 FPU,那么在处理异常时就需要保存 FPU 环境, 此位用来指示是否需要保存浮点环境。

     CONTROL[1]
    在 Cortex‐ M3 的 handler 模式中, CONTROL[1]总是 0。在线程模式中则可以为 0 或1。仅当处于特权级的线程模式下,此位才可写,其它场合下禁止写此位。改变处理器的模式也有其它的方式:在异常返回时,通过修改 LR 的位 2,也能实现模式切换。

    CONTROL[0]
    仅当在特权级下操作时才允许写该位。一旦进入了用户级,唯一返回特权级的途径,就是触发一个(软)中断,再由服务例程改写该位。 CONTROL 寄存器也是通过 MRS 和 MSR 指令来操作的:
     

    MRSR0,CONTROL
    MSRCONTROL,R0

     9)EXC_RETURN

    在进入异常服务程序后, L R 的值被自动更新为特殊的 EXC_RETURN,对于 Cortex-M4
    来说这是一个高 27 位全为 1 的值(M3 是高 28 位都为 1)。 M4 中[4:0]位有意义,在 M3 中[3:0]
    有意义,并且和 M4 中的相同, EXC_RETURN 位段如表 2.1.4 所示。
    注意! EXC_RETURN 的 bit4 非常重要,我们可以根据此位的值来获知硬件会对哪些寄存器进
    行自动压入栈和出栈处理。

    二、操作模式和特权级别

    1、Cortex-M3/CM4 处理器支持两种处理器的操作模式,还支持两级特权操作。

    2、两种操作模式分别为: 处理者模式 (handler mode)和线程模式(thread mode)。引入两个模式的本意,是用于区别普通应用程序的代码和异常服务例程的代码——包括中断服务例程的代码。

    3、Cortex-M3/M4 的另一个侧面则是特权的分级——特权级和用户级。这可以提供一种存储器访问的保护机制,使得普通的用户程序代码不能意外地,甚至是恶意地执行涉及到要害的操作。处
    理器支持两种特权级,如表 2.2.1 所示,这也是一个基本的安全模型。

     说明:在 CM3/CM4 运行主应用程序时(线程模式),既可以使用特权级,也可以使用用户级;但是异常服务例程必须在特权级下执行。复位后,处理器默认进入线程模式,特权级访问。在特权级下,程序可以访问所有范围的存储器(如果有 MPU,还要在 MPU 规定的禁地之外),并且可以执行所有指令。

    在特权级下的程序可以为所欲为,但也可能会把自己给玩进去——切换到用户级。一旦进入用户级,再想回来就得走“法律程序”了——用户级的程序不能简简单单地试图改写CONTROL 寄存器就回到特权级, 事实上,从用户级到特权级的唯一途径就是异常如果在程序执行过程中触发了一个异常,处理器总是先切换入特权级,并且在异常服务例程执行完毕退出时,返回先前的状态。
     

  • 相关阅读:
    简单公式
    永久删除的文件如何恢复?只需4个步骤
    单调栈问题---(每日温度,下一个更大元素Ⅰ)
    Linux网络编程开放资料
    金仓数据库KingbaseES物理备份恢复命令选项(stanza-upgrade命令)
    数字时代的自我呈现:探索个人形象打造的创新工具——FaceChain深度学习模型工具
    无主复制系统(2)-读写quorum
    多线程之线程安全集合类
    1166 Summit – PAT甲级真题
    【git】Git 指令统计代码行数
  • 原文地址:https://blog.csdn.net/m0_73931287/article/details/132942318