Notes
main
main
  • Introduction
  • linuxKernel
    • tips
    • make_help
    • old linux
      • compile_linux0.11
      • TestEnvironment
      • load_setup
      • get_hard_data
    • list
    • plist
    • fifo
    • idr
    • xarray
    • rbtree
    • maple_tree
    • syscall
    • bitmap
    • page
    • page_flags
    • page_size
    • page mapcount
    • page refcount
    • folio
    • slub
      • proc_slabinfo
      • slub_theory
      • kmalloc_kfree
      • kmem_cache
      • slab_alloc
      • slab_free
      • proc_meminfo_SReclaimable_SReclaimable
    • vmalloc
    • brk
    • mmap
    • mremap
    • mprotect
    • madvise
    • read
    • write
    • shmem
    • huge_page
    • page_fault
    • rmap
    • lru
    • multi-gen-LRU
    • page_reclaim
    • page_cache
    • page_table
    • rcu
    • kvm
    • aarch64_boot
    • tracing_system
    • cache_coherence_and_memory_consistency
    • cpu_speculates
    • mmap_lock
    • per-vma_lock
    • cgroup
    • symbol
    • campact
    • page_ext
    • mempool
    • kernelstack
    • filesystem
    • io_stack
    • workingset
    • ioremap
    • sched_period
  • linuxDebug
    • openocd_openjtag
    • i2c_tools
    • objdump
    • addr2line
    • gdb_useage
    • debug_linux_kernel_via_gdb
    • debug_linux_module_via_gdb
    • early_boot
    • sequentially_execute
    • dynamic_debug
    • research_linuxKernel_by_patch
    • tracefs
    • ebpf
    • bpftrace
    • perf
    • flame_graph
    • crash
    • ASAN_HWASAN_MTE_check_mem_bug
    • page_owner
    • vmtouch
    • fio
    • benchmark
  • linuxSystem
    • common
      • system_version
      • procfs
      • proc_sys_vm
      • cmd_ps
      • makefile
      • file_descriptor
      • psi
      • ulimit
      • top
      • delay_accounting
    • ubuntu
      • custom_kernel
      • get_cmd_src
      • record_ssh_info
      • log
      • run_custom_script
      • repo
      • cockpit
      • nfs
      • tftp
      • misc
    • fedora
      • system_upgrade
      • custom_kernel
      • lvextend
      • yt-dlp
      • jellyfin
  • linuxDriver
    • i2c_peripherals_driver
    • spi_peripherals_driver
    • gpio_subsystem
    • IRQ_driver
    • blockIO_unblockIO_async
    • linux_own_driver
    • misc_device
    • input_device
    • timer
    • atomic_spinlock_semaphore_mutex
    • lcd
    • touch_screen
    • debugfs
    • v4l2
    • mmap
  • hardware
    • paging_mmu_pt
    • iommu
  • process_thread_scheduler
    • scheduler01
    • scheduler02
    • scheduler03
    • scheduler04
    • scheduler05
    • scheduler06
  • memory_management
    • mm1
    • mm2
    • mm3
    • mm4
    • mm5
  • input_output_filesystem
    • io_fs_01
    • io_fs_02
    • io_fs_03
    • io_fs_04
  • lock_and_lockup_detector
    • general_lock
    • hung_task
    • softLockup_hardLockup
    • crash_experiment
  • MIT_6.S081
    • 6.S081_Operating_System_Engineering
    • Schedule.md
    • Class
      • Overview
      • Administrivia
    • Labs
      • Tools
      • Guidance
      • startup
      • syscall
      • page_table
      • Calling_Convention
      • traps
    • xv6
      • xv6
    • References.md
  • qemu
    • qemu_buildroot
    • qemu_busybox.md
    • Serial.md
    • demo_mini2440
      • 0_compilation_error_summary
      • 1_compilation_steps
      • 2_operation_mode
      • 3_transplant_tools_libraries
      • 4_tools_use
      • reference_website
  • tools
    • getKernelSourceCodeList
    • nat
    • shell
    • translating
    • YouCompleteMe
    • cscope
    • global
    • vscode
    • vim
    • binary
    • markdown
    • draw
    • git
    • tig
    • tmux
    • mail_client
    • download_patchset_from_LKML
    • minicom
    • clash
  • other
    • interview
    • interview_c_base
    • know_dontknow
    • Stop-Ask-Questions-The-Stupid-Ways
    • How-To-Ask-Questions-The-Smart-Way
    • docker
    • buildroot
    • rv32_to_rv64
Powered by GitBook
On this page
  • tasklet context
  • 1. 配置设备树dts
  • 2. 从设备树dts获得与申请中断号
  • 3. 设置中断处理函数
  • 4. 下半部处理(tasklet context)
  • 5. 释放中断号
  • workqueue context
  • 1. 配置设备树dts(同上)
  • 2. 从设备树dts获得与申请中断号(同上)
  • 3. 设置中断处理函数
  • 4. 下半部处理(workqueue context)
  • 5. 释放中断号(同上)

Was this helpful?

  1. linuxDriver

IRQ_driver

linux kernel IRQ驱动的编写,可以分为四步,但是中断处理函数的下半部处理有 tasklet context, workqueue context等等,所以此处分开讲解:

tasklet context

  1. 配置设备树dts

  2. 从设备树dts获得与申请中断号

  3. 设置中断处理函数

  4. 下半部处理(tasklet context)

  5. 释放中断号

workqueue context

  1. 配置设备树dts(同上)

  2. 从设备树dts获得与申请中断号(同上)

  3. 设置中断处理函数

  4. 下半部处理(workqueue context)

  5. 释放中断号(同上)

tasklet context

1. 配置设备树dts

xxx {
    compatible = "xxx,xxx";

    // GPIO1_18对应的中断号, 下降沿触发
    interrupt-parent = <&gpio1>;
    interrupts = <18 IRQ_TYPE_EDGE_FALLING>;
    state = "okay";
};

2. 从设备树dts获得与申请中断号

  • 获得中断号

    unsigned int xxx_irq;
    
    xxx_irq = irq_of_parse_and_map(np, 0); // 0代表interrupts属性的第一个中断号
  • 申请中断号

    unsigned int ret;
    
    /*
     * 中断号               : xxx_irq
     * 中断处理函数          :xxx_irq_handler()
     * 触发条件             :IRQF_TRIGGER_FALLING, 下降沿触发
     * 中断名               :xxxIRQ
     * 传递给中断处理函数的参数:xxxDev指针
     */
    ret = request_irq(xxx_irq, xxx_irq_handler, IRQF_TRIGGER_FALLING, "xxxIRQ", &xxxDev);
    if(ret != 0) {
        dev_err(&dev, "request irq failed, ret %d\n", ret);
        return ret;
    }
    或
    // 中断线程化,中断处理函数与线程函数是同一优先级,可以相互竞争CPU资源
    ret = request_threaded_irq(xxx_irq, NULL, xxx_irq_handler,
        IRQF_TRIGGER_FALLING | IRQF_ONESHOT, "xxxIRQ", &xxxDev);
    if(ret != 0) {
        dev_err(&dev, "request irq failed, ret %d\n", ret);
        return ret;
    }

3. 设置中断处理函数

static irqreturn_t xxx_irq_handler(int irq, void *dev)
{
    struct xxx_dev *p_xxxDev = (struct xxx_dev *)dev;

    tasklet_schedule(&xxx_irq_tasklet); // 调用tasklet_func()

    return IRQ_HANDLED;
}

4. 下半部处理(tasklet context)

void tasklet_func(unsigned long data)
{
    struct xxx_dev *p_xxxDev = (struct xxx_dev *)data;

}

/*
 * 定义xxx_irq_tasklet
 * 传递给tasklet_func()的参数是xxxDev指针
 */
DECLARE_TASKLET(xxx_irq_tasklet, tasklet_func, (unsigned long)&xxxDev);

5. 释放中断号

/*
 * 中断号               : xxx_irq
 * 传递给中断处理函数的参数:xxxDev指针
 */
free_irq(xxx_irq, &xxxDev);

workqueue context

1. 配置设备树dts(同上)

2. 从设备树dts获得与申请中断号(同上)

3. 设置中断处理函数

static irqreturn_t xxx_irq_handler(int irq, void *dev)
{
    struct xxx_dev *p_xxxDev = (struct xxx_dev *)dev;

    schedule_work(&xxx_irq_work); // 调用work_func()

    return IRQ_HANDLED;
}

4. 下半部处理(workqueue context)

void work_func(struct work_struct *work)
{

}

// 定义xxx_irq_work
DECLARE_WORK(xxx_irq_work, work_func);

5. 释放中断号(同上)

Previousgpio_subsystemNextblockIO_unblockIO_async

Last updated 4 years ago

Was this helpful?