通用裸机-arm汇编和cpu运行模式

发布者:悦耳旋律最新更新时间:2024-07-03 来源: elecfans关键字:arm汇编  cpu  运行模式 手机看文章 扫描二维码
随时随地手机看文章

    ldr sp, =0X80200000 /* 设置SVC模式下的栈首地址为0X80200000,大小为2MB */

4.2.2 SPSR

除了 User 和 Sys 这两个模式以外,其他 7 个模式每个都配备了一个专用的物理状态寄存器,叫做 SPSR(备份程序状态寄存器),当特定的异常中断发生时,SPSR 寄存器用来保存当前程序状态寄存器(CPSR)的值,当异常退出以后可以用 SPSR 中保存的值来恢复 CPSR。User 和 Sys 这两个模式不是异常模式,所以并没有配备 SPSR,因此不能在 User 和Sys 模式下访问 SPSR。


5 CP15协处理器

CP15 协处理器一般用于存储系统管理,但是在中断中也会使用到,比如进入reset复位异常向量时,需要利用协处理器命令进行ICache DCache的开关。CP15 协处理器一共有16 个 32 位寄存器(C0-C15),MRC和MCR用来访问CP15协处理器。


MRC: 将 CP15 协处理器中的寄存器数据读到 ARM 寄存器中。 MCR: 将 ARM 寄存器的数据写入到 CP15 协处理器寄存器中。 格式如下:


MCR{cond} p15, , , , ,

cond:指令执行的条件码,如果忽略的话就表示无条件执行。 opc1:协处理器要执行的操作码。 Rt:ARM 源寄存器,要写入到 CP15 寄存器的数据就保存在此寄存器中。 CRn:CP15 协处理器的目标寄存器。 CRm:协处理器中附加的目标寄存器或者源操作数寄存器,如果不需要附加信息就将CRm 设置为 C0,否则结果不可预测。 opc2:可选的协处理器特定操作码,当不需要的时候要设置为 0


例如:


MRC p15, 0, r0, c0, c0, 0 //将 CP15 中 C0 寄存器的值读取到 R0 寄存器

5.1 c0寄存器(MIDR)

使用 MRC 或者 MCR 指令访问 c0-c15 寄存器的时候,指令中的 CRn、opc1、CRm 和 opc2 通过不同的搭配,其得到的寄存器含义不同:

当CRn=c0,opc1=0,CRm=c0,opc2=0 的时候就表示此时的 c0 就是 MIDR 寄存器,也就是主 ID 寄存器,这个也是 c0 的基本作用。来看下c0作为MDIR寄存器时的含义:

bit31:24:厂商编号,0X41,ARM。 bit23:20:内核架构的主版本号,ARM 内核版本一般使用 rnpn 来表示,比如 r0p1,其中 r0 后面的 0 就是内核架构主版本号。 bit19:16:架构代码,0XF,ARMv7 架构。 bit15:4:内核版本号,0XC07,Cortex-A7 MPCore 内核。 bit3:0:内核架构的次版本号,rnpn 中的 pn,比如 r0p1 中 p1 后面的 1 就是次版本号。


5.2 c1寄存器(SCTLR)

CRn=c1,opc1=0,CRm=c0,opc2=0 的时候就表示此时的 c1 就是 SCTLR 寄存器,也就是系统控制寄存器,这个是 c1 的基本作用。 SCTLR 寄存器主要是完成控制功能的,比如使能或者禁止 MMU、I/D Cache 等。 SCTLR 寄存器展开如下:

bit13:V , 中断向量表基地址选择位,为 0 的话中断向量表基地址为 0X00000000,软件可以使用 VBAR 来重映射此基地址,也就是中断向量表重定位。为 1 的话中断向量表基地址为0XFFFF0000,此基地址不能被重映射。 bit12:I,I Cache 使能位,为 0 的话关闭 I Cache,为 1 的话使能 I Cache。 bit11:Z,分支预测使能位,如果开启 MMU 的话,此位也会使能。 bit10:SW,SWP 和 SWPB 使能位,当为 0 的话关闭 SWP 和 SWPB 指令,当为 1 的时候就使能 SWP 和 SWPB 指令。 bit9:3:未使用,保留。 bit2:C,D Cache 和缓存一致性使能位,为 0 的时候禁止 D Cache 和缓存一致性,为 1 时使能。 bit1:A,内存对齐检查使能位,为 0 的时候关闭内存对齐检查,为 1 的时候使能内存对齐检查。 bit0:M,MMU 使能位,为 0 的时候禁止 MMU,为 1 的时候使能 MMU。 举个读写SCTLR的例子:


MRC p15, 0, , c1, c0, 0 ;读取 SCTLR 寄存器,数据保存到 Rt 中。


MCR p15, 0, , c1, c0, 0 ;将 Rt 中的数据写到 SCTLR(c1)寄存器中。

再来一个关闭MMU,ICache,DCache的例子:


mrc     p15, 0, r0, c1, c0, 0     /* 读取CP15的C1寄存器到R0中                           */

bic     r0,  r0, #(0x1 << 12)     /* 清除C1寄存器的bit12位(I位),关闭I Cache               */

bic     r0,  r0, #(0x1 <<  2)     /* 清除C1寄存器的bit2(C位),关闭D Cache                 */

bic     r0,  r0, #0x2             /* 清除C1寄存器的bit1(A位),关闭对齐                      */

bic     r0,  r0, #(0x1 << 11)     /* 清除C1寄存器的bit11(Z位),关闭分支预测                   */

bic     r0,  r0, #0x1             /* 清除C1寄存器的bit0(M位),关闭MMU                     */

mcr     p15, 0, r0, c1, c0, 0     /* 将r0寄存器中的值写入到CP15的C1寄存器中                    */

5.3 c12寄存器(VBAR)


CRn=c12,opc1=0,CRm=c0,opc2=0 的时候就表示此时 c12 为 VBAR 寄存器,也就是中断向量表基地址寄存器


比如代码链接到DDR的某个位置作为起始地址,起始地址为0X87800000,而中断向量表肯定要放到最前面,也就是 0X87800000 这个地址处。所以就需要设置 VBAR 为 0X87800000,设置命令如下:


dsb

isb

ldr r0, =0x87800000 ; r0=0x87800000

MCR p15, 0, r0, c12, c0, 0 ;将 r0 里面的数据写入到 c12 中,即 c12=0X87800000

dsb

isb

5.3 c15寄存器(CBAR)



CBAR寄存器中保存了GIC(Generic Interrupt Controller)的基地址。GIC基地址偏移0x1000是分发器 block, 偏移0x2000是CPU 接口端 block。


MRC p15, 4, r1, c15, c0, 0 ; 获取 GIC 基础地址,基地址保存在 r1 中

6 参考链接

armv7都是32位处理器,典型的有CorTex-A A7 A8 A9 A15 A17。armv8采用64位处理器,典型的比如手机处理器,有Cortex A53 A76 A77都是64位架构。 https://developer.arm.com/documentation/ddi0406/cd?lang=en

https://developer.arm.com/documentation/den0013/d/?lang=en

https://developer.arm.com/documentation/ddi0464/latest/

7 附件1:armv7裸机启动汇编示例:


.global _start                  /* 全局标号 */


_start:

    ldr pc, =Reset_Handler      /* 复位中断                     */  

    ldr pc, =Undefined_Handler  /* 未定义中断                    */

    ldr pc, =SVC_Handler        /* SVC(Supervisor)中断        */

    ldr pc, =PrefAbort_Handler  /* 预取终止中断                   */

    ldr pc, =DataAbort_Handler  /* 数据终止中断                   */

    ldr pc, =NotUsed_Handler    /* 未使用中断                    */

    ldr pc, =IRQ_Handler        /* IRQ中断                    */

    ldr pc, =FIQ_Handler        /* FIQ(快速中断)未定义中断           */


/* 复位中断 */  

Reset_Handler:


    cpsid i                     /* 关闭全局中断 */


    /* 关闭I,DCache和MMU 

     * 采取读-改-写的方式。

     */

    mrc     p15, 0, r0, c1, c0, 0     /* 读取CP15的C1寄存器到R0中                           */

    bic     r0,  r0, #(0x1 << 12)     /* 清除C1寄存器的bit12位(I位),关闭I Cache               */

    bic     r0,  r0, #(0x1 <<  2)     /* 清除C1寄存器的bit2(C位),关闭D Cache                 */

    bic     r0,  r0, #0x2             /* 清除C1寄存器的bit1(A位),关闭对齐                      */

    bic     r0,  r0, #(0x1 << 11)     /* 清除C1寄存器的bit11(Z位),关闭分支预测                   */

    bic     r0,  r0, #0x1             /* 清除C1寄存器的bit0(M位),关闭MMU                     */

    mcr     p15, 0, r0, c1, c0, 0     /* 将r0寄存器中的值写入到CP15的C1寄存器中                    */



#if 0

    /* 汇编版本设置中断向量表偏移 */

    ldr r0, =0X87800000


    dsb

    isb

    mcr p15, 0, r0, c12, c0, 0

    dsb

    isb

#endif


    /* 设置各个模式下的栈指针,

     * 注意:IMX6UL的堆栈是向下增长的!

     * 堆栈指针地址一定要是4字节地址对齐的!!!

     * DDR范围:0X80000000~0X9FFFFFFF

     */

    /* 进入IRQ模式 */

    mrs r0, cpsr

    bic r0, r0, #0x1f   /* 将r0寄存器中的低5位清零,也就是cpsr的M0~M4  */

    orr r0, r0, #0x12   /* r0或上0x13,表示使用IRQ模式                   */

    msr cpsr, r0        /* 将r0 的数据写入到cpsr_c中                    */

    ldr sp, =0x80600000 /* 设置IRQ模式下的栈首地址为0X80600000,大小为2MB */


    /* 进入SYS模式 */

    mrs r0, cpsr

    bic r0, r0, #0x1f   /* 将r0寄存器中的低5位清零,也就是cpsr的M0~M4  */

    orr r0, r0, #0x1f   /* r0或上0x13,表示使用SYS模式                   */

    msr cpsr, r0        /* 将r0 的数据写入到cpsr_c中                    */

    ldr sp, =0x80400000 /* 设置SYS模式下的栈首地址为0X80400000,大小为2MB */


    /* 进入SVC模式 */

    mrs r0, cpsr

    bic r0, r0, #0x1f   /* 将r0寄存器中的低5位清零,也就是cpsr的M0~M4  */

    orr r0, r0, #0x13   /* r0或上0x13,表示使用SVC模式                   */

    msr cpsr, r0        /* 将r0 的数据写入到cpsr_c中                    */

    ldr sp, =0X80200000 /* 设置SVC模式下的栈首地址为0X80200000,大小为2MB */


    cpsie i             /* 打开全局中断 */

#if 0

    /* 使能IRQ中断 */

    mrs r0, cpsr        /* 读取cpsr寄存器值到r0中           */

    bic r0, r0, #0x80   /* 将r0寄存器中bit7清零,也就是CPSR中的I位清零,表示允许IRQ中断 */

    msr cpsr, r0        /* 将r0重新写入到cpsr中            */

#endif


    b main              /* 跳转到main函数                */


/* 未定义中断 */

Undefined_Handler:

    ldr r0, =Undefined_Handler

    bx r0


/* SVC中断 */

SVC_Handler:

    ldr r0, =SVC_Handler

    bx r0


/* 预取终止中断 */

PrefAbort_Handler:

    ldr r0, =PrefAbort_Handler  

    bx r0


/* 数据终止中断 */

DataAbort_Handler:

    ldr r0, =DataAbort_Handler

    bx r0


/* 未使用的中断 */

NotUsed_Handler:


    ldr r0, =NotUsed_Handler

    bx r0


IRQ_Handler:

    push {lr}                   /* 保存lr地址 */

    push {r0-r3, r12}           /* 保存r0-r3,r12寄存器 */


    mrs r0, spsr                /* 读取spsr寄存器 */

    push {r0}                   /* 保存spsr寄存器 */


    mrc p15, 4, r1, c15, c0, 0 /* 从CP15的C0寄存器内的值到R1寄存器中

[1] [2] [3] [4] [5] [6] [7] [8]
关键字:arm汇编  cpu  运行模式 引用地址:通用裸机-arm汇编和cpu运行模式

上一篇:通用裸机-传感器-1-DHT11温湿度sensor
下一篇:IMX6ULL裸机-4-ADC控制器

推荐阅读最新更新时间:2024-11-13 16:50

美国制裁中兴后 中国CPU自主可控“核心三要素”发布
    “美国对中国芯片的制裁,让我们更加坚定自主创新的道路,我们需要加紧发展国产自主的国产软硬件基础。”4月19日,在万寿宾馆举行的关键信息基础设施自主安全创新论坛上,中国工程院院士倪光南语调不高,语气坚决。   此外,CTF计算机安全为专委会主任严明、国家工程院院士沈昌祥、国家高性能集成电路(上海)设计中心副主任田斌、龙芯中科技术有限公司总裁胡伟武等出席并先后进行了报告。各专家对处理器自主可控标准进行了深度剖析和解读,并正式发布了CPU自主可控的“核心三要素”,给鱼龙混杂的CPU市场确立了评判标准。   发展自主可控信息基础设施迫在眉睫   “曾几何时,谷歌(1072.96, -14.74, -1.36%)退出中国市场,那时候
[半导体设计/制造]
ARM汇编中伪指令的介绍
伪指令没有相对应的操作码,他们所完成的操作称为伪操作。 伪指令在源程序中的作用是为完成汇编程序作各种准备工作的,这些伪指令仅在汇编过程中起作用,一旦汇编结束,伪指令的使命就完成(就如你睡觉她为你铺床,铺在哪儿和铺床技巧由她安排,但她不陪你睡觉,铺好了就走 :-( )。   在 ARM 的汇编程序中,有如下几种伪指令:符号定义伪指令、数据定义伪指令、汇编控制伪指令、宏指令以及其他伪指令。   符号定义( Symbol Definition )伪指令   符号定义伪指令用于定义 ARM 汇编程序中的变量、对变量赋值以及定义寄存器的别名等操作。   常见的符号定义伪指令有如下几种:    用于定义全局变量的 GBLA 、
[单片机]
ARM汇编指令集之六——加载/存储指令
ARM微处理器支持加载/存储指令用于在寄存器和存储器之间传送数据,加载指令用于将存储器中的数据传送到寄存器,存储指令则完成相反的操作。常用的加载存储指令如下: 1、LDR指令 LDR指令的格式为: LDR{条件} 目的寄存器, 存储器地址 LDR指令用于从存储器中将一个32位的字数据传送到目的寄存器中。该指令通常用于从存储器中读取32位的字数据到通用寄存器,然后对数据进行处理。当程序计数器PC作为目的寄存器时,指令从存储器中读取的字数据被当作目的地址,从而可以实现程序流程的跳转。该指令在程序设计中比较常用,且寻址方式灵活多样,请读者认真掌握。 指令示例: LDR R0, ;将存储器地址为R1的字
[单片机]
UCOS-II中OS_CPU_IRQ_ISR移植过程分析
简介:在讨论ARM的移植过程中,我觉得首先应该搞清楚每一种情况下CPU的工作模式,同时搞清楚寄存器的特殊性,同时搞清楚中断处理的一般过程。 在uc/os-II的移植过程中存在一个通用的irq中断处理函数,其中的实现过程如下: OS_CPU_IRQ_ISR STMFD SP!, {R1-R3} ; We will use R1-R3 as temporary registers MOV R1, SP ADD SP, SP, #12 ;Adjust IRQ stack pointer SUB R2, LR, #4 ;Adjust PC for return address to task MRS R3, SPSR ; Copy
[单片机]
arm汇编实现的跑马灯实验
平台:fs2410 用arm汇编编写的跑马灯单文件可以很好运行,不需要包其他的头文件和一些初始化函数。 GPFCON EQU 0x56000050 GPFDAT EQU 0x56000054 GPFUP EQU 0x56000058 EXPORT LEDTEST AREA LEDTESTASM,CO DE,READONLY ;定义了一个代码段,段名为LEDTESTASM,属性只读 LEDTEST ;设置GPF4-GPF7为output ldr r0,=GPFCON ldr r1,=0x5500 str r1, ;禁止GPF4-GPF7端口的上拉电阻 ldr
[单片机]
基于LPC2138CPU芯片实现开关寿命自动测试系统的设计
各种各样的开关电器被应用在航空、航天、交通及一般工业或民用领域,比如微动开关、按钮开关、转换开关、电源开关等。无论何种开关,都是常开触头和常闭触头的组合,这些触头被用来闭合或断开电路。触头经过一定时间的动作以后,会逐渐丧失正常的开闭功能,比如接触不良、触头不动作等,因此任何开关都存在使用寿命。运用在一般工业及民用领域的开关电器,对开关的寿命没有严格的要求,但如果开关被应用到航空、航天和交通等领域时,开关是否良好直接关系到飞机、轮船和汽车运行时的安全,所以必须对开关的寿命提出严格的要求,要求开关制造商标明开关的触头能正常开闭的次数,因此开关制造商在开关出厂前有必要对同一批号的产品进行抽查测试,以掌握开关的确切寿命。 1 开关寿命
[单片机]
基于LPC2138<font color='red'>CPU</font>芯片实现开关寿命自动测试系统的设计
Intel CPU工艺上演奇迹:6个季度内实现“1.8nm”量产
在先进工艺上,Intel这两年被三星、台积电领先了,但在CEO基辛格的带领下,Intel目标是2025年重新成为半导体领导者,还定下了4年内掌握5代CPU工艺的宏大目标,如今已经是2023年了,距离目标只有2年。 这五种工艺是Intel 7、Intel 4、Intel 3、Intel 20A(等效2nm,其中A代表埃米,1nm=10埃米,下同)、18A(等效1.8nm),其中Intel 7就是当前13代、12代酷睿量产的工艺。 Intel 4工艺会由14代酷睿首发,不过随着PC需求的下滑,Intel今年的策略也变了,Intel 4工艺至少要到2023年下半年才能量产了。 Intel 20A计划2024上半年准备投
[半导体设计/制造]
Intel <font color='red'>CPU</font>工艺上演奇迹:6个季度内实现“1.8nm”量产
UCOS-II中OS_CPU_IRQ_ISR移植过程分析
在uc/os-II的移植过程中存在一个通用的irq中断处理函数,其中的实现过程如下: OS_CPU_IRQ_ISR STMFD SP!, {R1-R3} ; We will use R1-R3 as temporary registers MOV R1, SP ADD SP, SP, #12 ;Adjust IRQ stack pointer SUB R2, LR, #4 ;Adjust PC for return address to task MRS R3, SPSR ; Copy SPSR (Task CPSR) MSR CPSR_cxsf, #SVCMODE|NOINT ;Change to
[单片机]
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved