在延遲中斷處理機制上,workqueue是另一個可以使用的方式,workqueue是執行在低優先級別上,因此,可以讓Context Switch繼續執行,意味著使用者可以在workqueue裡面呼叫sleep()相關的函式,這也是跟softirq、tasklet最大的差別,因此,workqueue是相當適合應用在耗時處理的場合
使用步驟:
1. __alloc_workqueue_key() 2. queue_work_on() 3. destroy_workqueue()
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"
.equ work_struct.data, 0
.equ work_struct.entry, 4
.equ work_struct.entry.next, 4
.equ work_struct.entry.prev, 8
.equ work_struct.func, 12
.struct 0
work_struct_s:
i0: .struct . + 4
i1: .struct . + 8
i2: .struct . + 4
work_struct_e:
work_struct_l = work_struct_e - work_struct_s
.section .data
btn_irq: .dcb 4
irq_name: .asciz "gpio_irq"
work_name: .asciz "myworkqueue"
work_msg: .asciz "workqueue_handler\n"
mywork: .space work_struct_l
myworkqueue: .dcb 4
.align 2
.section .text
workqueue_handler:
push {lr}
ldr r0, =work_msg
bl printk
pop {pc}
irq_handler:
push {lr}
mov r0, #2
ldr r1, =myworkqueue
ldr r1, [r1]
ldr r2, =mywork
bl queue_work_on
mov r0, #1
pop {pc}
init_module:
push {r4, r5, lr}
ldr r0, =work_name
mov r1, #0
mov r2, #0
mov r3, #0
mov r4, #0
push {r4}
bl __alloc_workqueue_key
pop {r4}
ldr r1, =myworkqueue
str r0, [r1]
ldr r0, =mywork
add r0, #work_struct.data
ldr r1, =#0xffffffe0
str r1, [r0]
ldr r0, =mywork
add r0, #work_struct.entry @next
mov r1, r0
str r1, [r0]
add r0, #work_struct.entry @prev
str r1, [r0]
ldr r0, =mywork
add r0, #work_struct.func
ldr r1, =workqueue_handler
str r1, [r0]
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
ldr r0, =myworkqueue
ldr r0, [r0]
bl destroy_workqueue
pop {pc}
.end
init_module: 設定GPIO中斷以及workqueue延遲處理副程式
irq_handler: 安排一個workqueue延遲處理
workqueue_handler: 列印字串
cleanup_module: 釋放中斷資源以及刪除workqueue
完成

# workqueue_handler