您的位置 首页 IC

ARM 中止状况和SVC状况的仓库切换 (反常)

基础知识:Arm的寄存器使用规则以及寻址指令:R13Sp堆栈寄存器R14Lr连接寄存器R15PC程序计数器多寄存器寻址:LDMIAR0!,{R1…

基础知识:

Arm的存放器运用规矩以及寻址指令:

R13 Sp 仓库存放器

R14 Lr 衔接存放器

R15 PC 程序计数器

存放器寻址

LDMIA R0!,{R1-R4}

碑文今后的作用

R1 <——[R0]

R2 <——[R0+4]

R3 <——[R0+8]

R4 <——[R0+12]

仓库寻址:

STMFD入栈指令,相当于STMDB

STMFD SP!,{R2-R4} 留意这个“!”的运用,在运用和不运用的状况下会有不一样的作用,在后面的代码中详细分析。

[SP-4] <­——R4

[SP-8] <——R3

[SP-12] <——R2

LDMFD出栈指令,相当于LDMIA

LDMFD SP!,{R6-R8}

R6 <——[SP]

R7 <——[SP+4]

R8 <——[SP+8]

弥补阐明:

LDMIA/STMIAIncrementAfter (先操作,后添加)

LDMIB/STMIBIncrementBefore(先添加,后操作)

LDMDA/STMDADecrementAfter(先操作,后递减)

LDMDB/STMDBDecrementBefore(先递减,后操作)

•STMFD(Push)块存储-FullDescending stack [STMDB]

•LDMFD(Pop) 块装载-FullDescending stack [LDMIA]

这些运用规矩以及默许的表达办法是给编译器运用。可是在开发底层言语的一起,有必要知道这个么命名的规矩和运用办法。初始化代码和部分要害代码是靠汇编完结。这些代码的了解难免和汇编打交道。因而了解一下根本的汇编规矩仍是很有协助。

Arm的作业形式:

Arm的作业形式以及相关存放器设置:

1,用户形式(usr)[10000]:ARM处理器正常的程序碑文状况

2,快速间断形式(fiq)[10001]:用于高速数据传输或通道处理

3,外部间断形式(irq)[10010]:用于通用的间断处理

4,管理形式(svc)[10011]:操作体系运用的保护形式

5,间断形式(abt)[10111]:当数据或指令预取停止时进入该形式,用于虚拟存

储及存储保护

6,未定义指令形式(und)[11011]:当未定义的指令碑文时进入该形式,用于支撑硬件

协处理器的软件仿真

7,体系形式(sys)[11111]:运转具有特权形式的操作体系使命

设置办法:

MRS R14,CPSR 读取

MSR CPSR_c, R14 写入

以上几种形式存在的意义在于不同形式下特别的几个存放器运用是有差异的。再svc形式下仓库指针为sp svc间断形式下sp指针为 sp irq等。相同lr衔接存放器的内容也是有不同的意义。再不同形式切换中,lr存放器保存的地址是由硬件完结,可是一共的是不同形式下的下一条指令,既返形式切换后的回来地址。

每一种形式对应不同的bank register。中文官方翻译不详。可是每一种形式要具有自己独立的存放器组。而且每一种形式运用和可见存放器的数量也是不相同的。

形式切换进程中其实只针对spsr进行操作,而未触及cpsr是的操作。这个进程之所以这样主要是参阅ARM cortex A8的TRM。其间这样描绘脱离反常的状况:

Typically the return instruction is an arithmetic orlogical operation with the S bit set to

1 and rd = r15, so the core copies the SPSR back to theCPSR.

也便是说脱离反常,从反常状况回来今后会主动把spsr的内同拷贝到cpsr中。所以在碑文BL Lr指令之前运用的仓库其实并位切换。

Linux中初始化:

1, Svc形式的仓库初始化:

仓库的概念是给C 言语编译今后的代码运用,因而从head.S一直到C言语的碑文,便是start_kernel。

__mmap_switched:

@注释 1:

adr r3, __switch_data + 4

ldmia r3!, {r4, r5, r6, r7}

cmp r4, r5 @ Copy datasegment if needed

1: cmpne r5, r6

ldrne fp, [r4], #4

strne fp, [r5], #4

bne 1b

mov fp, #0 @ Clear BSS(and zero fp)

1: cmp r6, r7

strcc fp, [r6],#4

bcc 1b

@注释 2:

ldmia r3, {r4, r5, r6, r7, sp}

str r9, [r4] @ Saveprocessor ID

str r1, [r5] @ Savemachine type

str r2, [r6] @ Saveatags pointer

bic r4, r0, #CR_A @ ClearA bit

stmia r7, {r0, r4} @Save control register values

@注释 3:

b start_kernel

ENDPROC(__mmap_switched)

注释1:

__switch_data这是以个地址。Linker会组织这个地址详细的数值。翻开Sysmap能够发现这个数值为:c0008123 t __switch_data

注释 2:

将r3所指的内容顺次装入{r4– r6,sp},这个时分sp指针就有了详细的数值了。

注释 3:

跳转指令,指向C函数的start_kernel。这时分栈针开端起效。由于C言语编译出来的代码参数传递,调用变量保存等都运用sp指针。这个指针仅仅是给初始化代码所运用。在进程的概念中还有进程仓库的概念。这时分的sp详细指向的是描绘进程结构的结构体task_info。

2,irq以及其他形式的初始化:

__asm__ (

“msr cpsr_c, %1\n\t”

“add r14, %0, %2\n\t”

“mov sp, r14\n\t”

“msr cpsr_c, %3\n\t”

“add r14, %0, %4\n\t”

“mov sp, r14\n\t”

“msr cpsr_c, %5\n\t”

“add r14, %0, %6\n\t”

“mov sp, r14\n\t”

“msr cpsr_c, %7″

:

: “r” (stk),

PLC (PSR_F_BIT | PSR_I_BIT | IRQ_MODE),

“I” (offsetof(struct stack,irq[0])),

PLC (PSR_F_BIT | PSR_I_BIT | ABT_MODE),

“I” (offsetof(struct stack,abt[0])),

PLC (PSR_F_BIT | PSR_I_BIT | UND_MODE),

“I” (offsetof(struct stack,und[0])),

PLC (PSR_F_BIT | PSR_I_BIT | SVC_MODE)

: “r14”);

函数:cpu_init()文件:setup.c

经过msr设置了cpsr存放器。然后经过mov指令把详细的参数地址写入sp存放器。

其间offsetof(struct stack, irq[0])这个表达式一共的是偏移量。既是在结构体中的偏移量。

其实在这个函数中初始化的irq仓库只要4 bytes x 3。这么小的仓库空间是否能够分量中端的需求。答案是:能够。在中端进入的函数中其实并没有彻底运用irq形式下sp_irq指向的仓库空间。在进入函数中马上有利用了msr指令进行了形式切换,切换到了svc形式。而且抛弃了irq的形式。从中端回来也是从svc形式回来,而非irq形式。

代码:

vector_\name:

.if \correction

sub lr, lr, #\correction

.endif

@

@ Save r0, lr_(parent PC) and spsr_

@ (parent CPSR)

@

@ 注释 1:

stmia sp, {r0, lr} @ save r0,lr

mrs lr, spsr

str lr, [sp, #8] @ save spsr

@

@ Prepare for SVC32 mode. IRQs remain disabled.

@

mrs r0, cpsr

eor r0, r0, #(\mode ^ SVC_MODE) 进入SVC形式

msr spsr_cxsf, r0

@

@ the branch table mustimmediately follow this code

@

and lr, lr, #0x0f

mov r0, sp

ldr lr, [pc, lr, lsl #2]

@注释 2:

movs pc, lr @ branch tohandler in SVC mode

参照ARM的参阅

ENDPROC(vector_\name)

注释 1 :

保存irq形式下的sp和lr指针到前面初始的sp_irq中。记住只要4 bytes x 3巨细的空间。在后面的代码中还会看到str lr, [sp, #8]保存了最终一个参数到sp_irq的空间中。这儿要留意:stmia sp, {r0, lr}这条指令。没有运用“!”号。这样一来虽然指令碑文后sp指针指向的地址不会自加。因而在正式切换到SVC形式之前sp_irq所指向的地址并没有改变。这样再次进入间断形式时分,sp_irq不需要调整,能够重复运用。

注释 2:

参照ARM 的芯片规划手册能够发现,脱离反常,从反常状况回来今后会主动把spsr的内同拷贝到cpsr中。所以在碑文BL Lr指令之前运用的仓库其实并位切换。

这样一来虽然是间断的形式进入体系,可是由间断形式切换至SVC形式。在SVC形式中完结了间断的后续相应和操作。

文章仅仅做了学习笔记已被后用,把这些思路罗列出来也给自己今后再回想查找提供方便。

假如文章中有什么不对的当地,还请高手纠正。

声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/bandaoti/264473.html

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱: kf@86ic.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部