通用裸机-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控制器

推荐阅读最新更新时间:2026-03-10 07:31

2440裸机编程之八 UART通用异步收发
S3C2440A 内部集成的UART(通用异步收发器)单元提供三个独立的异步串行I/O端口,也就是通常所说的串口。串口是用途广泛的通讯口,很多工业现场总线都以串口为基础。在这里,串口不仅可以用来与外部设备进行数据通讯,还可以用来观察系统的运行状况,例如前面已经使用过的利用串口终端工具观察程序运行情况的方法。 S3C2440A 的UART 单元提供三个独立的异步串行I/O 端口,每个都可以在中断或DMA 两种模式下工作。它们支持的最高波特率为115. 2 kbps。每个UART 通道包含2 个64 位FIFO 分别供接收和发送使用。 S3C2440A 的UART 具有以下可配置的参数项目:可编程的波特率,红外收/发模式,l 或2
[单片机]
2440<font color='red'>裸机</font>编程之八 UART<font color='red'>通用</font>异步收发
TI发布创新型宽VIN DC/DC控制器,可支持最高65V运行模式
2016年3月29日,北京讯 近日,德州仪器 (TI) 推出了一款2.2MHz、双通道同步降压转换器;这款器件特有区别于其它产品的一套特性 专门设计用于大幅降低汽车信息娱乐和高端集群电源系统等高压DC/DC降压应用中的电磁干扰 (EMI) 和高频噪声。LM5140-Q1控制器包含支持相位交错的双输出,并且提供能够加快生产速度的可润湿侧翼封装。将LM5140-Q1与TI的WEBENCH 汽车设计工具结合在一起使用时,更能够使工程师们加快汽车设计的上市时间。 LM5140-Q1主要特性和优势: 3.8V至65V的宽运行范围能够处理针对12V/24V铅酸电池和新兴的48V锂离子汽车用电池的怠速熄火系统和抛负载情况。 具
[电源管理]
P-NET现场总线技术的结构、系统特点、运行模式及应用
1 引 言   P-NET现场总线技术由丹麦Proces-Data A/S公司研究并开发,是一种全世界通用的开放型标准化总线。它可以将生产过程的各个部分,如过程控制计算机、传感器、执行器、I/O模块、小型可编程控制器等,通过共用一根双芯电缆加以连接。与传统布线相比,P-NET现场总线技术在工业控制应用中具有很大的优势,它将简化设计和安装,减少布线的数量和费用,避免各种设备故障的发生,实现更直接也更广泛的使用功能。     2 网络系统     P-NET是一种多层网络结构,如图1所示。          图1 P-NET网络结构图   其特点:   (1) 多层的网络结构,方便系统组态,提高系统的安全性和冗余性。   (2) 分
[嵌入式]
新工业革命将要颠覆家电企业的运行模式
    3D打印无疑成为今年CES上最受关注的热点话题之一,而随着全球产业界对这一制造模式的逐步实践,这场新工业革命正不断冲击着传统的制造模式和组织模式。在笔者看来,3D打印的兴起是互联网时代日益多元化、个性化的消费需求催生的生产模式变革,并且这一变革将直接颠覆企业原先的组织模式。   互联网时代的兴起意味着消费民主化时代的到来,此时用户需求日益个性化、多样化,而用户期望需求被满足的速度则不断加快。从用户需求角度看,相对差异化的用户需求使得企业此前依靠几款产品便可开拓市场的模式失效了,这逼迫企业不得不探索新的发展模式,通过深入分析用户需求数据“定制”产品成为新形势下的探索,这也意味着个性化的消费需求正在颠覆原有的大规模制造模式,根据
[家用电子]
嵌入式开发学习(4)<ARM汇编指令集详解>
数据传送指令:   MOV 两个寄存器之间传递。例 MOV r1,r0,将寄存器r0中的内容赋值给r1。   MVN 同MOV用法一样,区别是MOV是原值传递,而MVN是按位取反后传递。 算数运算指令:   ADD SUB RSB ADC SBC RSC 逻辑指令:   AND ORR EOR BIC   BIC的用法:BIC r0,r1,#0x1f,将r1中的数的bit0到bit4清零后赋值给r0;为什么是bit0到bit4呢,这个是由#0x1f来决定,#0x1f有五个bit位是1。如写成#0xf,就有四个bit位是0。 比较指令:   CMP CMN TST TEQ 比较指令用来比较两个寄存器中的数。特点:比较指令不用后加S后
[单片机]
嵌入式开发学习(3)<ARM汇编指令集语法>
汇编指令分为指令和伪指令 指令:针对于CPU设计的指令。作用在CPU上。 伪指令:针对于编译器设计的指令。作用在编译器上,用来知道编译过程,经过编译后伪指令最终不会生成机器码。要知道,汇编指令是机器指令的助记符,最终要通过编译器翻译成CPU能直接识别的由01组成的代码(机器码)。 LDR/STR架构: ARM采用RISC架构,CPU不能直接操作内存中的内容,而需要先将内存中的内容加载到CPU中的通用寄存器中才能被CPU处理。 LDR(load register)指令将内存中的内容加载的通用寄存器中。 STR(store register)指令与LDR指令相反,将寄存器中的内容存入到内存中。 CPU通过LDR指令和STR指令实现内存
[单片机]
嵌入式开发学习(3)<<font color='red'>ARM汇编</font>指令集语法>
10.ARM汇编的学习
ARM汇编的学习是很必要,学习ARM汇编不是要以后用汇编去写程序,而是要去看得懂,且进行修改就可以了。因为在后面的有关内核和bootloader的工程里,会有部分的代码是汇编程序编写的。在bootloader中,系统一旦上电,第一个运行的程序,需要对cpu、协处理器进行初始化,此时还没有C语言运行的环境,因为没有堆栈等条件。在内核里也是同样的道理。之所以要使用汇编,是因为它公认的高效性,在系统刚上电,或者在一个程序里需要高效的程序语言的时候,就会考虑用汇编来实现。就像C语言,它可以嵌入汇编代码,来提高运行效率。 总结:两个会使用汇编的地方 启动代码。 效率要求高的地方。 ARM汇编分类: 目前常用的ARM汇编指令有两种:
[单片机]
10.<font color='red'>ARM汇编</font>的学习
arm学习笔记五(c/c++与arm汇编混合编程)
常见方式: 1 在c/c++程序中嵌入汇编指令 语法格式: __asm { 汇编语言程序 } 2 在汇编程序中访问c/c++定义的全局变量 示例代码如下: test.c #include stdio.h int gVar_1=12; extern asmDouble(void) int main(void){ printf( original value of gVar_1 is %d ,gVar_1); admDouble(); printf( modified value of gVar_1 is %d ,gVar_1); return 0; } test.s AREA asmfil
[单片机]
小广播
最新单片机文章
何立民专栏 单片机及嵌入式宝典

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

厂商技术中心

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

 
机器人开发圈

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