驅動程式 - Linux Device Driver (LDD) - 使用範例 - Assembly (ARM) - IRQ



中斷本身是一種高優先權處理的機制,一旦硬體中斷觸發後,系統會馬上跳到使用者設定的Callback執行,在Callback中,不應該執行太過耗時的程式,否則將拖垮系統效能,這是由於Context Switch優先級一般會比中斷來得低,在中斷副程式尚未將權限交回給系統時,系統無法做Context Switch(單核心系統來說),也就是其它程式將無法被系統執行,Context Switch是系統交換程式執行的意思

使用步驟:

1. gpiod_to_irq()
2. request_threaded_irq()
3. free_irq()

request_irq()其實就是呼叫request_threaded_irq(),只是bottom-half傳入NULL

ldd.S

    .global init_module
    .global cleanup_module

    .equ BUTTON, 27
    .equ IRQF_TRIGGER_RISING, 1

    .section .modinfo, "ae"
__UNIQUE_ID_0: .asciz "license=GPL"
__UNIQUE_ID_1: .asciz "author=Steward Fu"
__UNIQUE_ID_2: .asciz "description=Linux Driver"

    .section .data
btn_irq:  .dcb 4
irq_name: .asciz "gpio_irq"
irq_msg:  .asciz "irq_handler\n"

    .align 2
    .section .text
irq_handler:
    push {lr}
    ldr r0, =irq_msg
    bl printk
    mov r0, #1
    pop {pc}

init_module:
    push {r4, r5, lr}

    mov r0, #BUTTON
    bl gpio_to_desc
    bl gpiod_to_irq
    ldr r1, =btn_irq
    str r0, [r1]

    ldr r1, =irq_handler
    mov r2, #0
    mov r3, #IRQF_TRIGGER_RISING
    ldr r4, =irq_name
    mov r5, #0
    push {r4, r5}
    bl request_threaded_irq
    pop {r4, r5}

    mov r0, #0
    pop {r4, r5, pc}

cleanup_module:
    push {lr}
    ldr r0, =btn_irq
    ldr r0, [r0]
    mov r1, #0
    bl free_irq
    pop {pc}
    .end

init_module: 設定中斷並且使用上緣觸發方式(IRQF_TRIGGER_RISING)
irq_handler: 輸出中斷訊息
cleanup_module: 釋放中斷

完成

# irq_handler