<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>

新聞中心

EEPW首頁(yè) > 嵌入式系統 > 設計應用 > ARM 中斷狀態(tài)和SVC狀態(tài)的堆棧切換 (異常)

ARM 中斷狀態(tài)和SVC狀態(tài)的堆棧切換 (異常)

作者: 時(shí)間:2016-11-20 來(lái)源:網(wǎng)絡(luò ) 收藏
基礎知識:

Arm的寄存器使用規則以及尋址指令:

本文引用地址:http://dyxdggzs.com/article/201611/318975.htm

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} 注意這個(gè)“!”的使用,在使用和不使用的情況下會(huì )有不一樣的效果,在后面的代碼中具體分析。

[SP-4] <­——R4

[SP-8] <——R3

[SP-12] <——R2

LDMFD出棧指令,相當于LDMIA

LDMFD SP!,{R6-R8}

R6 <——[SP]

R7 <——[SP+4]

R8 <——[SP+8]

補充說(shuō)明:

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

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

LDMDA/STMDADecrementAfter(先操作,后遞減)

LDMDB/STMDBDecrementBefore(先遞減,后操作)

•STMFD(Push)塊存儲-FullDescending stack [STMDB]

•LDMFD(Pop) 塊裝載-FullDescending stack [LDMIA]

這些使用規則以及默認的表達方法是給編譯器使用。但是在開(kāi)發(fā)底層語(yǔ)言的同時(shí),有必要知道這個(gè)么命名的規則和使用方法。初始化代碼和部分關(guān)鍵代碼是靠匯編實(shí)現。這些代碼的理解不免和匯編打交道。因此了解一下基本的匯編規則還是很有幫助。

Arm的工作模式:

Arm的工作模式以及相關(guān)寄存器設置:

1,用戶(hù)模式(usr)[10000]:ARM處理器正常的程序執行狀態(tài)

2,快速中斷模式(fiq)[10001]:用于高速數據傳輸或通道處理

3,外部中斷模式(irq)[10010]:用于通用的中斷處理

4,管理模式(svc)[10011]:操作系統使用的保護模式

5,中止模式(abt)[10111]:當數據或指令預取終止時(shí)進(jìn)入該模式,用于虛擬存

儲及存儲保護

6,未定義指令模式(und)[11011]:當未定義的指令執行時(shí)進(jìn)入該模式,用于支持硬件

協(xié)處理器的軟件仿真

7,系統模式(sys)[11111]:運行具有特權模式的操作系統任務(wù)

設置方法:

MRS R14,CPSR 讀取

MSR CPSR_c, R14 寫(xiě)入

以上幾種模式存在的意義在于不同模式下特殊的幾個(gè)寄存器使用是有區別的。再svc模式下堆棧指針為sp svc中斷模式下sp指針為 sp irq等。同樣lr連接寄存器的內容也是有不同的含義。再不同模式切換中,lr寄存器保存的地址是由硬件完成,但是表示的是不同模式下的下一條指令,既返模式切換后的返回地址。

每一種模式對應不同的bank register。中文官方翻譯不詳。但是每一種模式要擁有自己獨立的寄存器組。并且每一種模式使用和可見(jiàn)寄存器的數量也是不相同的。

模式切換過(guò)程中其實(shí)只針對spsr進(jìn)行操作,而未涉及cpsr是的操作。這個(gè)過(guò)程之所以這樣主要是參考ARM cortex A8的TRM。其中這樣描述離開(kāi)異常的情況:

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.

也就是說(shuō)離開(kāi)異常,從異常情況返回以后會(huì )自動(dòng)把spsr的內同拷貝到cpsr中。所以在執行BL Lr指令之前使用的堆棧其實(shí)并位切換。

Linux中初始化:

1, Svc模式的堆棧初始化:

堆棧的概念是給C 語(yǔ)言編譯以后的代碼使用,因此從head.S一直到C語(yǔ)言的執行,就是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這是以個(gè)地址。Linker會(huì )安排這個(gè)地址具體的數值。打開(kāi)Sysmap可以發(fā)現這個(gè)數值為:c0008123 t __switch_data

注釋 2:

將r3所指的內容依次裝入{r4– r6,sp},這個(gè)時(shí)候sp指針就有了具體的數值了。

注釋 3:

跳轉指令,指向C函數的start_kernel。這時(shí)候棧針開(kāi)始起效。因為C語(yǔ)言編譯出來(lái)的代碼參數傳遞,調用變量保存等都使用sp指針。這個(gè)指針僅僅是給初始化代碼所使用。在進(jìn)程的概念中還有進(jìn)程堆棧的概念。這時(shí)候的sp具體指向的是描述進(jìn)程結構的結構體task_info。

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

__asm__ (

"msr cpsr_c, %1nt"

"add r14, %0, %2nt"

"mov sp, r14nt"

"msr cpsr_c, %3nt"

"add r14, %0, %4nt"

"mov sp, r14nt"

"msr cpsr_c, %5nt"

"add r14, %0, %6nt"

"mov sp, r14nt"

"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

通過(guò)msr設置了cpsr寄存器。然后通過(guò)mov指令把具體的參數地址寫(xiě)入sp寄存器。

其中offsetof(struct stack, irq[0])這個(gè)表達式表示的是偏移量。既是在結構體中的偏移量。

其實(shí)在這個(gè)函數中初始化的irq堆棧只有4 bytes x 3。這么小的堆??臻g是否可以滿(mǎn)足中端的需求。答案是:可以。在中端進(jìn)入的函數中其實(shí)并沒(méi)有完全使用irq模式下sp_irq指向的堆??臻g。在進(jìn)入函數中馬上有利用了msr指令進(jìn)行了模式切換,切換到了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) 進(jìn)入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大小的空間。在后面的代碼中還會(huì )看到str lr, [sp, #8]保存了最后一個(gè)參數到sp_irq的空間中。這里要注意:stmia sp, {r0, lr}這條指令。沒(méi)有使用“!”號。這樣一來(lái)盡管指令執行后sp指針指向的地址不會(huì )自加。因此在正式切換到SVC模式之前sp_irq所指向的地址并沒(méi)有變化。這樣再次進(jìn)入中斷模式時(shí)候,sp_irq不需要調整,可以重復使用。

注釋 2:

參照ARM 的芯片設計手冊可以發(fā)現,離開(kāi)異常,從異常情況返回以后會(huì )自動(dòng)把spsr的內同拷貝到cpsr中。所以在執行BL Lr指令之前使用的堆棧其實(shí)并位切換。

這樣一來(lái)盡管是中斷的模式進(jìn)入系統,但是由中斷模式切換至SVC模式。在SVC模式中完成了中斷的后續相應和操作。

文章只是做了學(xué)習筆記已被后用,把這些思路羅列出來(lái)也給自己以后再回憶查找提供方便。

如果文章中有什么不對的地方,還請高手指正。



評論


技術(shù)專(zhuān)區

關(guān)閉
国产精品自在自线亚洲|国产精品无圣光一区二区|国产日产欧洲无码视频|久久久一本精品99久久K精品66|欧美人与动牲交片免费播放
<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>