www.久久久久|狼友网站av天堂|精品国产无码a片|一级av色欲av|91在线播放视频|亚洲无码主播在线|国产精品草久在线|明星AV网站在线|污污内射久久一区|婷婷综合视频网站

當(dāng)前位置:首頁(yè) > 嵌入式 > 嵌入式軟件
[導(dǎo)讀]linux-2.6.26內(nèi)核中ARM中斷實(shí)現(xiàn)詳解(2)

三、中斷處理過(guò)程

這一節(jié)將以S3C2410為例,描述linux-2.6.26內(nèi)核中,從中斷開(kāi)始,中斷是如何一步一步執(zhí)行到我們注冊(cè)函數(shù)的。

3.1 中斷向量表 archarmkernelentry-armv.S

__vectors_STart:

swi SYS_ERROR0

b vector_und + stubs_offset

ldr pc, .LCvswi + stubs_offset

b vector_pa^ + stubs_offset

b vector_da^ + stubs_offset

b vector_addrexcptn + stubs_offset

b vector_IRq + stubs_offset

b vector_fiq + stubs_offset

.globl __vectors_end

__vectors_end:

中斷發(fā)生后,跳轉(zhuǎn)到b vector_irq + stubs_offset的位置執(zhí)行。注意現(xiàn)在的向量表的初始位置是0xffff0000。

3.2 中斷跳轉(zhuǎn)的入口位置 archarmkernelentry-armv.S

.globl __stubs_start

__stubs_start:

/*

* Interrupt dispatcher

*/

vector_stub irq, IRQ_MODE, 4 @IRQ_MODE在includeasmptrace.h中定義:0x12

.lONg __irq_usr @ 0 (USR_26 / USR_32)

.long __irq_invalid @ 1 (FIQ_26 / FIQ_32)

.long __irq_invalid @ 2 (IRQ_26 / IRQ_32)

.long __irq_svc @ 3 (SVC_26 / SVC_32)

.long __irq_invalid @ 4

.long __irq_invalid @ 5

.long __irq_invalid @ 6

.long __irq_invalid @ 7

.long __irq_invalid @ 8

.long __irq_invalid @ 9

.long __irq_invalid @ a

.long __irq_invalid @ b

.long __irq_invalid @ c

.long __irq_invalid @ d

.long __irq_invalid @ e

.long __irq_invalid @ f

上面代碼中vector_stub宏的定義為:

.macro vector_stub, name, mode, correcTIon=0

.align 5

vector_nAME:

.if correction

sub lr, lr, #correction

.endif

@

@ Save r0, lr_ (parent PC) and spsr_

@ (parent CPSR)

@

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)

msr spsr_cxsf, r0 @為后面進(jìn)入svc模式做準(zhǔn)備

@

@ the branch table must immediately follow this code

@

and lr, lr, #0x0f @進(jìn)入中斷前的mode的后4位

@#define USR_MODE 0x00000010

@#define FIQ_MODE 0x00000011

@#define IRQ_MODE 0x00000012

@#define SVC_MODE 0x00000013

@#define ABT_MODE 0x00000017

@#define UND_MODE 0x0000001b

@#define SYSTEM_MODE 0x0000001f

mov r0, sp

ldr lr, [pc, lr, lsl #2] @如果進(jìn)入中斷前是usr,則取出PC+4*0的內(nèi)容,即__irq_usr @如果進(jìn)入中斷前是svc,則取出PC+4*3的內(nèi)容,即__irq_svc

movs pc, lr @ 當(dāng)指令的目標(biāo)寄存器是PC,且指令以S結(jié)束,則它會(huì)把@ spsr的值恢復(fù)給cpsr branch to handler in SVC mode

.endm

.globl __stubs_start

__stubs_start:

/*

* Interrupt dispatcher

*/

vector_stub irq, IRQ_MODE, 4

.long __irq_usr @ 0 (USR_26 / USR_32)

.long __irq_invalid @ 1 (FIQ_26 / FIQ_32)

.long __irq_invalid @ 2 (IRQ_26 / IRQ_32)

.long __irq_svc @ 3 (SVC_26 / SVC_32)

用“irq, IRQ_MODE, 4”代替宏vector_stub中的“name, mode, correction”,找到了我們中斷處理的入口位置為vector_irq(宏里面的vector_name)。

從上面代碼中的注釋可以看出,根據(jù)進(jìn)入中斷前的工作模式不同,程序下一步將跳轉(zhuǎn)到_irq_usr 、或__irq_svc等位置。我們先選擇__irq_usr作為下一步跟蹤的目標(biāo)。

3.3 __irq_usr的實(shí)現(xiàn) archarmkernelentry-armv.S

__irq_usr:

usr_entry @后面有解釋

kuser_cmpxchg_check

#ifdef CONFIG_TRACE_IRQFLAGS

bl trace_hardirqs_off

#endif

get_thread_info tsk @獲取當(dāng)前進(jìn)程的進(jìn)程描述符中的成員變量thread_info的地址,并將該地址保存到寄存器tsk等于r9(在entry-header.S中定義)

#ifdef CONFIG_PREEMPT//如果定義了搶占,增加搶占數(shù)值

ldr r8, [tsk, #TI_PREEMPT] @ get preempt count

add r7, r8, #1 @ increment it

str r7, [tsk, #TI_PREEMPT]

#endif

irq_handler @中斷處理,我們最關(guān)心的地方,3.4節(jié)有實(shí)現(xiàn)過(guò)程。

#ifdef CONFIG_PREEMPT

ldr r0, [tsk, #TI_PREEMPT]

str r8, [tsk, #TI_PREEMPT]

teq r0, r7

strne r0, [r0, -r0]

#endif

#ifdef CONFIG_TRACE_IRQFLAGS

bl trace_hardirqs_on

#endif

mov why, #0

b ret_to_user @中斷處理完成,返回中斷產(chǎn)生的位置,3.7節(jié)有實(shí)現(xiàn)過(guò)程

上面代碼中的usr_entry是一個(gè)宏,主要實(shí)現(xiàn)了將usr模式下的寄存器、中斷返回地址保存到堆棧中。

.macro usr_entry

sub sp, sp, #S_frame_SIZE @ S_FRAME_SIZE的值在archarmkernelasm-offsets.c

@ 中定義 DEFINE(S_FRAME_SIZE, sizeof(struct pt_regs));實(shí)際上等于72

stmib sp, {r1 - r12}

ldmia r0, {r1 - r3}

add r0, sp, #S_PC @ here for interlock avoidance

mov r4, #-1 @ "" "" "" ""

str r1, [sp] @ save the "real" r0 copied

@ from the exception stack

@

@ We are now ready to fill in the remaining blanks on the stack:[!--empirenews.page--]

@

@ r2 - lr_, already fixed up for correct return/restart

@ r3 - spsr_

@ r4 - orig_r0 (see pt_regs definition in ptrace.h)

@

@ Also, separately save sp_usr and lr_usr

@

stmia r0, {r2 - r4}

stmdb r0, {sp, lr}^

@

@ Enable the alignment trap while in kernel mode

@

alignment_trap r0

@

@ Clear FP to mark the first stack frame

@

zero_fp

.endm

上面的這段代碼主要在填充結(jié)構(gòu)體pt_regs ,這里提到的struct pt_regs,在include/asm/ptrace.h中定義。此時(shí)sp指向struct pt_regs。

struct pt_regs {

long uregs[18];

};

#define ARM_cpsr uregs[16]

#define ARM_pc uregs[15]

#define ARM_lr uregs[14]

#define ARM_sp uregs[13]

#define ARM_ip uregs[12]

#define ARM_fp uregs[11]

#define ARM_r10 uregs[10]

#define ARM_r9 uregs[9]

#define ARM_r8 uregs[8]

#define ARM_r7 uregs[7]

#define ARM_r6 uregs[6]

#define ARM_r5 uregs[5]

#define ARM_r4 uregs[4]

#define ARM_r3 uregs[3]

#define ARM_r2 uregs[2]

#define ARM_r1 uregs[1]

#define ARM_r0 uregs[0]

#define ARM_ORIG_r0 uregs[17]

3.4 irq_handler的實(shí)現(xiàn)過(guò)程,archarmkernelentry-armv.S

.macro irq_handler

get_irqnr_preamble r5, lr

@在include/asm/arch-s3c2410/entry-macro.s中定義了宏get_irqnr_preamble為空操作,什么都不做

1: get_irqnr_and_base r0, r6, r5, lr @判斷中斷號(hào),通過(guò)R0返回,3.5節(jié)有實(shí)現(xiàn)過(guò)程

movne r1, sp

@

@ routine called with r0 = irq number, r1 = struct pt_regs *

@

adrne lr, 1b

bne asm_do_IRQ @進(jìn)入中斷處理。

……

.endm

3.5 get_irqnr_and_base中斷號(hào)判斷過(guò)程,include/asm/arch-s3c2410/entry-macro.s

.macro get_irqnr_and_base, irqnr, irqstat, base, tmp

mov base, #S3C24XX_VA_IRQ

@@ try the interrupt offset register, since it is there

ldr irqstat, [ base, #INTPND ]

teq irqstat, #0

beq 1002f

ldr irqnr, [ base, #INTOFFSET ] @通過(guò)判斷INTOFFSET寄存器得到中斷位置

mov tmp, #1

tst irqstat, tmp, lsl irqnr

bne 1001f

@@ the number specified is not a valid irq, so try

@@ and work it out for ourselves

mov irqnr, #0 @@ start here

@@ work out which irq (if any) we got

movs tmp, irqstat, lsl#16

addeq irqnr, irqnr, #16

moveq irqstat, irqstat, lsr#16

tst irqstat, #0xff

addeq irqnr, irqnr, #8

moveq irqstat, irqstat, lsr#8

tst irqstat, #0xf

addeq irqnr, irqnr, #4

moveq irqstat, irqstat, lsr#4

tst irqstat, #0x3

addeq irqnr, irqnr, #2

moveq irqstat, irqstat, lsr#2

tst irqstat, #0x1

addeq irqnr, irqnr, #1

@@ we have the value

1001:

adds irqnr, irqnr, #IRQ_EINT0 @加上中斷號(hào)的基準(zhǔn)數(shù)值,得到最終的中斷號(hào),注意:此時(shí)沒(méi)有考慮子中斷的具體情況,(子中斷的問(wèn)題后面會(huì)有講解)。IRQ_EINT0在include/asm/arch-s3c2410/irqs.h中定義.從這里可以看出,中斷號(hào)的具體值是有平臺(tái)相關(guān)的代碼決定的,和硬件中斷掛起寄存器中的中斷號(hào)是不等的。

1002:

@@ exit here, Z flag unset if IRQ

.endm

3.6 asm_do_IRQ實(shí)現(xiàn)過(guò)程,arch/arm/kernel/irq.c

asmlinkage void __exception asm_do_IRQ(unsigned int irq, struct pt_regs *regs)

{

struct pt_regs *old_regs = set_irq_regs(regs);

struct irq_desc *desc = irq_desc + irq;//根據(jù)中斷號(hào)找到對(duì)應(yīng)的irq_desc

/*

* Some hardware gives randomly wrong interrupts. Rather

* than crashing, do something sensible.

*/

if (irq >= NR_IRQS)

desc = &bad_irq_desc;

irq_enter();//沒(méi)做什么特別的工作,可以跳過(guò)不看

desc_handle_irq(irq, desc);// 根據(jù)中斷號(hào)和desc進(jìn)入中斷處理

/* AT91 specific workaround */

irq_finish(irq);

irq_exit();

set_irq_regs(old_regs);

}

static inline void desc_handle_irq(unsigned int irq, struct irq_desc *desc)

{

desc->handle_irq(irq, desc);//中斷處理

}

上述asmlinkage void __exception asm_do_IRQ(unsigned int irq, struct pt_regs *regs)使用了asmlinkage標(biāo)識(shí)。那么這個(gè)標(biāo)識(shí)的含義如何理解呢?

該符號(hào)定義在kernel/include/linux/linkage.h中,如下所示:

#include //各個(gè)具體處理器在此文件中定義asmlinkage

#ifdef __cplusplus

#define CPP_ASMLINKAGE extern "C"

#else

#define CPP_ASMLINKAGE

#endif

#ifndef asmlinkage//如果以前沒(méi)有定義asmlinkage

#define asmlinkage CPP_ASMLINKAGE

#endif

對(duì)于ARM處理器的,沒(méi)有定義asmlinkage,所以沒(méi)有意義(不要以為參數(shù)是從堆棧傳遞的,對(duì)于ARM平臺(tái)來(lái)說(shuō)還是符合ATPCS過(guò)程調(diào)用標(biāo)準(zhǔn),通過(guò)寄存器傳遞的)。

但對(duì)于X86處理器的中是這樣定義的:[!--empirenews.page--]

#define asmlinkage CPP_ASMLINKAGE __attribute__((regparm(0)))

表示函數(shù)的參數(shù)傳遞是通過(guò)堆棧完成的。

3.7 描述3.3節(jié)中的ret_to_user 中斷返回過(guò)程,/arch/arm/kernel/entry-common.S

ENTRY(ret_to_user)

ret_slow_syscall:

disable_irq @ disable interrupts

ldr r1, [tsk, #TI_FLAGS]

tst r1, #_TIF_WORK_MASK

bne work_pending

no_work_pending:

/* perform. architecture specific actions before user return */

arch_ret_to_user r1, lr

@ slow_restore_user_regs

ldr r1, [sp, #S_PSR] @ get calling cpsr

ldr lr, [sp, #S_PC]! @ get pc

msr spsr_cxsf, r1 @ save in spsr_svc

ldmdb sp, {r0 - lr}^ @ get calling r0 - lr

mov r0, r0

add sp, sp, #S_FRAME_SIZE - S_PC

movs pc, lr @ return & move spsr_svc into cpsr

第三章主要跟蹤了從中斷發(fā)生到調(diào)用到對(duì)應(yīng)中斷號(hào)的desc->handle_irq(irq, desc)中斷函數(shù)的過(guò)程。后面的章節(jié)還會(huì)繼續(xù)講解后面的內(nèi)容。

本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實(shí)性等。需要轉(zhuǎn)載請(qǐng)聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請(qǐng)及時(shí)聯(lián)系本站刪除。
換一批
延伸閱讀

LED驅(qū)動(dòng)電源的輸入包括高壓工頻交流(即市電)、低壓直流、高壓直流、低壓高頻交流(如電子變壓器的輸出)等。

關(guān)鍵字: 驅(qū)動(dòng)電源

在工業(yè)自動(dòng)化蓬勃發(fā)展的當(dāng)下,工業(yè)電機(jī)作為核心動(dòng)力設(shè)備,其驅(qū)動(dòng)電源的性能直接關(guān)系到整個(gè)系統(tǒng)的穩(wěn)定性和可靠性。其中,反電動(dòng)勢(shì)抑制與過(guò)流保護(hù)是驅(qū)動(dòng)電源設(shè)計(jì)中至關(guān)重要的兩個(gè)環(huán)節(jié),集成化方案的設(shè)計(jì)成為提升電機(jī)驅(qū)動(dòng)性能的關(guān)鍵。

關(guān)鍵字: 工業(yè)電機(jī) 驅(qū)動(dòng)電源

LED 驅(qū)動(dòng)電源作為 LED 照明系統(tǒng)的 “心臟”,其穩(wěn)定性直接決定了整個(gè)照明設(shè)備的使用壽命。然而,在實(shí)際應(yīng)用中,LED 驅(qū)動(dòng)電源易損壞的問(wèn)題卻十分常見(jiàn),不僅增加了維護(hù)成本,還影響了用戶體驗(yàn)。要解決這一問(wèn)題,需從設(shè)計(jì)、生...

關(guān)鍵字: 驅(qū)動(dòng)電源 照明系統(tǒng) 散熱

根據(jù)LED驅(qū)動(dòng)電源的公式,電感內(nèi)電流波動(dòng)大小和電感值成反比,輸出紋波和輸出電容值成反比。所以加大電感值和輸出電容值可以減小紋波。

關(guān)鍵字: LED 設(shè)計(jì) 驅(qū)動(dòng)電源

電動(dòng)汽車(EV)作為新能源汽車的重要代表,正逐漸成為全球汽車產(chǎn)業(yè)的重要發(fā)展方向。電動(dòng)汽車的核心技術(shù)之一是電機(jī)驅(qū)動(dòng)控制系統(tǒng),而絕緣柵雙極型晶體管(IGBT)作為電機(jī)驅(qū)動(dòng)系統(tǒng)中的關(guān)鍵元件,其性能直接影響到電動(dòng)汽車的動(dòng)力性能和...

關(guān)鍵字: 電動(dòng)汽車 新能源 驅(qū)動(dòng)電源

在現(xiàn)代城市建設(shè)中,街道及停車場(chǎng)照明作為基礎(chǔ)設(shè)施的重要組成部分,其質(zhì)量和效率直接關(guān)系到城市的公共安全、居民生活質(zhì)量和能源利用效率。隨著科技的進(jìn)步,高亮度白光發(fā)光二極管(LED)因其獨(dú)特的優(yōu)勢(shì)逐漸取代傳統(tǒng)光源,成為大功率區(qū)域...

關(guān)鍵字: 發(fā)光二極管 驅(qū)動(dòng)電源 LED

LED通用照明設(shè)計(jì)工程師會(huì)遇到許多挑戰(zhàn),如功率密度、功率因數(shù)校正(PFC)、空間受限和可靠性等。

關(guān)鍵字: LED 驅(qū)動(dòng)電源 功率因數(shù)校正

在LED照明技術(shù)日益普及的今天,LED驅(qū)動(dòng)電源的電磁干擾(EMI)問(wèn)題成為了一個(gè)不可忽視的挑戰(zhàn)。電磁干擾不僅會(huì)影響LED燈具的正常工作,還可能對(duì)周圍電子設(shè)備造成不利影響,甚至引發(fā)系統(tǒng)故障。因此,采取有效的硬件措施來(lái)解決L...

關(guān)鍵字: LED照明技術(shù) 電磁干擾 驅(qū)動(dòng)電源

開(kāi)關(guān)電源具有效率高的特性,而且開(kāi)關(guān)電源的變壓器體積比串聯(lián)穩(wěn)壓型電源的要小得多,電源電路比較整潔,整機(jī)重量也有所下降,所以,現(xiàn)在的LED驅(qū)動(dòng)電源

關(guān)鍵字: LED 驅(qū)動(dòng)電源 開(kāi)關(guān)電源

LED驅(qū)動(dòng)電源是把電源供應(yīng)轉(zhuǎn)換為特定的電壓電流以驅(qū)動(dòng)LED發(fā)光的電壓轉(zhuǎn)換器,通常情況下:LED驅(qū)動(dòng)電源的輸入包括高壓工頻交流(即市電)、低壓直流、高壓直流、低壓高頻交流(如電子變壓器的輸出)等。

關(guān)鍵字: LED 隧道燈 驅(qū)動(dòng)電源
關(guān)閉