{"id":74394,"date":"2026-02-09T18:25:27","date_gmt":"2026-02-09T10:25:27","guid":{"rendered":"https:\/\/www.wsisp.com\/helps\/74394.html"},"modified":"2026-02-09T18:25:27","modified_gmt":"2026-02-09T10:25:27","slug":"day73-imx6ull-linux-key-driver-practice-a-complete-analysis-from-gpio-polling-to-device-tree-interr","status":"publish","type":"post","link":"https:\/\/www.wsisp.com\/helps\/74394.html","title":{"rendered":"DAY73 IMX6ULL Linux Key Driver Practice: A Complete Analysis from GPIO Polling to Device Tree Interr"},"content":{"rendered":"<h2>IMX6ULL Linux Key Driver Practice: A Complete Analysis from GPIO Polling to Device Tree Interrupts &#043; Wait Queues<\/h2>\n<p>In embedded Linux development, key drivers are a classic case for understanding character devices, Platform bus, interrupt mechanisms, and blocking I\/O. Based on the IMX6ULL development board, this article integrates the core highlights of three blog posts, using \u201cdriver version evolution\u201d as the main thread to comprehensively dissect the optimization path of key drivers\u2014from basic GPIO polling to standard device tree interrupts &#043; wait queues. It balances theoretical depth, code details, and practical implementation, helping developers master the core design philosophy of Linux drivers.<\/p>\n<h3>I. Core Technology Stack and Design Philosophy<\/h3>\n<h4>1.1 Core Technology System<\/h4>\n<table>\n<tr>TechnologyDescription<\/tr>\n<tbody>\n<tr>\n<td>Device Tree (DTS\/DTB)<\/td>\n<td>Uniformly describes hardware resources like key GPIOs and interrupts, decoupling drivers from hardware via the compatible property.<\/td>\n<\/tr>\n<tr>\n<td>GPIO Subsystem<\/td>\n<td>Encapsulates low-level register operations, providing standardized APIs like gpio_request and gpio_get_value to simplify hardware operations.<\/td>\n<\/tr>\n<tr>\n<td>Interrupt Handling<\/td>\n<td>Uses \u201cevent triggering\u201d instead of polling, triggering interrupts on key press\/release to reduce CPU usage (request_irq &#043; ISR).<\/td>\n<\/tr>\n<tr>\n<td>Wait Queue<\/td>\n<td>Implements \u201csleep-wake\u201d mechanism, releasing CPU when the application waits for key events and waking up after interrupts, achieving efficient blocking I\/O.<\/td>\n<\/tr>\n<tr>\n<td>Platform Bus<\/td>\n<td>Automatically matches device tree nodes with drivers via the compatible property, standardizing driver initialization (probe function).<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h4>1.2 Driver Evolution Design Philosophy<\/h4>\n<p>From \u201cfunctional implementation\u201d to \u201chigh performance &#043; high portability,\u201d the evolution of the three versions perfectly illustrates the Linux driver design principle of \u201clow coupling, high cohesion\u201d:<\/p>\n<table>\n<tr>VersionCore ImplementationCPU UsagePortabilityKey Highlights<\/tr>\n<tbody>\n<tr>\n<td>V1<\/td>\n<td>Pure GPIO Polling<\/td>\n<td>High<\/td>\n<td>Medium<\/td>\n<td>Minimal logic, ideal for understanding GPIO operations.<\/td>\n<\/tr>\n<tr>\n<td>V2<\/td>\n<td>GPIO-to-Interrupt &#043; Wait Queue<\/td>\n<td>Low<\/td>\n<td>Medium<\/td>\n<td>Introduces blocking I\/O, solving CPU usage issues.<\/td>\n<\/tr>\n<tr>\n<td>V3<\/td>\n<td>Device Tree Interrupt &#043; Wait Queue<\/td>\n<td>Low<\/td>\n<td>High<\/td>\n<td>Fully decouples hardware details, standard Linux practice.<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h3>II. Device Tree (DTS) Writing: Standardizing Hardware Description<\/h3>\n<p>The device tree serves as the \u201cbridge\u201d between drivers and hardware, uniformly describing key GPIO and interrupt resources without hardcoding hardware details in the driver.<\/p>\n<h4>2.1 DTS Node Example (Added to IMX6ULL Device Tree File)<\/h4>\n<p>ptkey {<br \/>\n    compatible &#061; &#034;pt-key&#034;;          \/\/ Matches driver&#039;s &#096;of_device_id&#096;, the core matching property.<br \/>\n    ptkey-gpio &#061; &lt;&amp;gpio1 4 GPIO_ACTIVE_LOW&gt;; \/\/ Key GPIO (GPIO1_IO04, active low).<br \/>\n    interrupt-parent &#061; &lt;&amp;gpio1&gt;;    \/\/ Interrupt parent controller (GPIO1).<br \/>\n    interrupts &#061; &lt;4 IRQ_TYPE_EDGE_FALLING&gt;; \/\/ Interrupt number 4, falling-edge triggered (key press).<br \/>\n};<\/p>\n<ul>\n<li>&amp;gpio1: References the IMX6ULL\u2019s GPIO1 controller node.<\/li>\n<li>GPIO_ACTIVE_LOW: Indicates the GPIO is active low (key press pulls GPIO low).<\/li>\n<li>interrupts: Defines interrupt trigger mode; IRQ_TYPE_EDGE_FALLING means falling-edge triggered.<\/li>\n<\/ul>\n<h4>2.2 Device Tree Matching Mechanism<\/h4>\n<li>The driver declares supported compatible properties via the of_device_id structure.<\/li>\n<li>During kernel startup, the device tree node is automatically matched with the driver\u2019s compatible property.<\/li>\n<li>Upon successful matching, the Platform bus triggers the driver\u2019s probe function to complete initialization.<\/li>\n<h3>III. Driver Code Analysis: Detailed Evolution of Three Versions<\/h3>\n<h4>3.1 V1: Pure GPIO Polling Driver (key.c)<\/h4>\n<p>The most basic implementation, polling GPIO levels to determine key status, ideal for beginners to understand the GPIO subsystem.<\/p>\n<h5>Core Code<\/h5>\n<p><span class=\"token macro property\"><span class=\"token directive-hash\">#<\/span><span class=\"token directive keyword\">define<\/span> <span class=\"token macro-name\">DEV_NAME<\/span> <span class=\"token string\">&#034;key&#034;<\/span><\/span><br \/>\n<span class=\"token keyword\">static<\/span> <span class=\"token keyword\">int<\/span> key_gpio<span class=\"token punctuation\">;<\/span><\/p>\n<p><span class=\"token comment\">\/\/ Read key status (1&#061;not pressed, 0&#061;pressed).<\/span><br \/>\n<span class=\"token keyword\">static<\/span> <span class=\"token keyword\">inline<\/span> <span class=\"token keyword\">int<\/span> <span class=\"token function\">get_key_status<\/span><span class=\"token punctuation\">(<\/span><span class=\"token keyword\">void<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n    <span class=\"token keyword\">return<\/span> <span class=\"token function\">gpio_get_value<\/span><span class=\"token punctuation\">(<\/span>key_gpio<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span> <span class=\"token comment\">\/\/ GPIO subsystem API, reads level.<\/span><br \/>\n<span class=\"token punctuation\">}<\/span><\/p>\n<p><span class=\"token comment\">\/\/ &#096;read&#096; function: Returns key status when the application calls &#096;read&#096;.<\/span><br \/>\n<span class=\"token keyword\">static<\/span> <span class=\"token class-name\">ssize_t<\/span> <span class=\"token function\">read<\/span><span class=\"token punctuation\">(<\/span><span class=\"token keyword\">struct<\/span> <span class=\"token class-name\">file<\/span> <span class=\"token operator\">*<\/span>file<span class=\"token punctuation\">,<\/span> <span class=\"token keyword\">char<\/span> __user <span class=\"token operator\">*<\/span>buf<span class=\"token punctuation\">,<\/span> <span class=\"token class-name\">size_t<\/span> size<span class=\"token punctuation\">,<\/span> <span class=\"token class-name\">loff_t<\/span> <span class=\"token operator\">*<\/span>loff<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n    <span class=\"token keyword\">int<\/span> status <span class=\"token operator\">&#061;<\/span> <span class=\"token function\">get_key_status<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token comment\">\/\/ Copies data from kernel space to user space.<\/span><br \/>\n    <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token function\">copy_to_user<\/span><span class=\"token punctuation\">(<\/span>buf<span class=\"token punctuation\">,<\/span> <span class=\"token operator\">&amp;<\/span>status<span class=\"token punctuation\">,<\/span> <span class=\"token keyword\">sizeof<\/span><span class=\"token punctuation\">(<\/span>status<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span><br \/>\n        <span class=\"token keyword\">return<\/span> <span class=\"token operator\">&#8211;<\/span>EFAULT<span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token keyword\">return<\/span> <span class=\"token keyword\">sizeof<\/span><span class=\"token punctuation\">(<\/span>status<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n<span class=\"token punctuation\">}<\/span><\/p>\n<p><span class=\"token comment\">\/\/ &#096;probe&#096; function: Core driver initialization flow.<\/span><br \/>\n<span class=\"token keyword\">static<\/span> <span class=\"token keyword\">int<\/span> <span class=\"token function\">probe<\/span><span class=\"token punctuation\">(<\/span><span class=\"token keyword\">struct<\/span> <span class=\"token class-name\">platform_device<\/span> <span class=\"token operator\">*<\/span>pdev<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n    <span class=\"token keyword\">struct<\/span> <span class=\"token class-name\">device_node<\/span> <span class=\"token operator\">*<\/span>pdts<span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token keyword\">int<\/span> ret <span class=\"token operator\">&#061;<\/span> <span class=\"token function\">misc_register<\/span><span class=\"token punctuation\">(<\/span><span class=\"token operator\">&amp;<\/span>misc_dev<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span> <span class=\"token comment\">\/\/ Registers a miscellaneous device, auto-creates &#096;\/dev\/key&#096;.<\/span><br \/>\n    <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>ret<span class=\"token punctuation\">)<\/span> <span class=\"token keyword\">goto<\/span> err_misc_register<span class=\"token punctuation\">;<\/span><\/p>\n<p>    pdts <span class=\"token operator\">&#061;<\/span> <span class=\"token function\">of_find_node_by_path<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string\">&#034;\/ptkey&#034;<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span> <span class=\"token comment\">\/\/ Finds the device tree node.<\/span><br \/>\n    key_gpio <span class=\"token operator\">&#061;<\/span> <span class=\"token function\">of_get_named_gpio<\/span><span class=\"token punctuation\">(<\/span>pdts<span class=\"token punctuation\">,<\/span> <span class=\"token string\">&#034;ptkey-gpio&#034;<\/span><span class=\"token punctuation\">,<\/span> <span class=\"token number\">0<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span> <span class=\"token comment\">\/\/ Gets GPIO number from the node.<\/span><br \/>\n    ret <span class=\"token operator\">&#061;<\/span> <span class=\"token function\">gpio_request<\/span><span class=\"token punctuation\">(<\/span>key_gpio<span class=\"token punctuation\">,<\/span> <span class=\"token string\">&#034;key&#034;<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span> <span class=\"token comment\">\/\/ Requests GPIO resources to avoid conflicts.<\/span><br \/>\n    <span class=\"token function\">gpio_direction_input<\/span><span class=\"token punctuation\">(<\/span>key_gpio<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span> <span class=\"token comment\">\/\/ Configures GPIO as input mode.<\/span><\/p>\n<p>    <span class=\"token function\">printk<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string\">&#034;V1: GPIO polling driver initialized.\\\\n&#034;<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token keyword\">return<\/span> <span class=\"token number\">0<\/span><span class=\"token punctuation\">;<\/span><\/p>\n<p><span class=\"token comment\">\/\/ Error handling: Releases allocated resources to avoid memory leaks.<\/span><br \/>\nerr_misc_register<span class=\"token operator\">:<\/span><br \/>\n    <span class=\"token function\">misc_deregister<\/span><span class=\"token punctuation\">(<\/span><span class=\"token operator\">&amp;<\/span>misc_dev<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token function\">printk<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string\">&#034;Driver initialization failed, ret&#061;%d\\\\n&#034;<\/span><span class=\"token punctuation\">,<\/span> ret<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token keyword\">return<\/span> ret<span class=\"token punctuation\">;<\/span><br \/>\n<span class=\"token punctuation\">}<\/span><\/p>\n<h5>Workflow and Drawbacks<\/h5>\n<ul>\n<li>Workflow: Application calls read in a while(1) loop \u2192 driver reads GPIO level \u2192 returns status.<\/li>\n<li>Drawbacks: High CPU usage (up to 99%), inability to capture transient key actions, poor real-time performance.<\/li>\n<\/ul>\n<h4>3.2 V2: Interrupt &#043; Wait Queue (key_irq.c)<\/h4>\n<p>Core optimization: Replaces polling with interrupts and implements \u201csleep-wake\u201d via wait queues, solving CPU usage issues.<\/p>\n<h5>3.2.1 Core Mechanism: Wait Queue<\/h5>\n<p>Wait queues are the core of Linux blocking I\/O, acting as a \u201cprocess waiting room\u201d:<\/p>\n<ul>\n<li>When no key event occurs, the application sleeps, releasing CPU.<\/li>\n<li>When a key triggers an interrupt, the driver wakes the sleeping process for efficient event response.<\/li>\n<\/ul>\n<h5>3.2.2 Core Code Modifications<\/h5>\n<p><span class=\"token comment\">\/\/ Defines wait queue and condition variable.<\/span><br \/>\n<span class=\"token keyword\">static<\/span> <span class=\"token class-name\">wait_queue_head_t<\/span> wq<span class=\"token punctuation\">;<\/span> <span class=\"token comment\">\/\/ Wait queue head.<\/span><br \/>\n<span class=\"token keyword\">static<\/span> <span class=\"token keyword\">int<\/span> condition <span class=\"token operator\">&#061;<\/span> <span class=\"token number\">0<\/span><span class=\"token punctuation\">;<\/span>    <span class=\"token comment\">\/\/ Event readiness flag (0&#061;not ready, 1&#061;ready).<\/span><br \/>\n<span class=\"token keyword\">static<\/span> <span class=\"token keyword\">int<\/span> key_irq<span class=\"token punctuation\">;<\/span>          <span class=\"token comment\">\/\/ Interrupt number.<\/span><\/p>\n<p><span class=\"token comment\">\/\/ Interrupt service function (top half): Triggered on key press.<\/span><br \/>\n<span class=\"token keyword\">static<\/span> <span class=\"token class-name\">irqreturn_t<\/span> <span class=\"token function\">key_irq_handler<\/span><span class=\"token punctuation\">(<\/span><span class=\"token keyword\">int<\/span> irq<span class=\"token punctuation\">,<\/span> <span class=\"token keyword\">void<\/span> <span class=\"token operator\">*<\/span>dev<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n    <span class=\"token keyword\">int<\/span> arg <span class=\"token operator\">&#061;<\/span> <span class=\"token operator\">*<\/span><span class=\"token punctuation\">(<\/span><span class=\"token keyword\">int<\/span> <span class=\"token operator\">*<\/span><span class=\"token punctuation\">)<\/span>dev<span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token number\">100<\/span> <span class=\"token operator\">!&#061;<\/span> arg<span class=\"token punctuation\">)<\/span> <span class=\"token keyword\">return<\/span> IRQ_NONE<span class=\"token punctuation\">;<\/span> <span class=\"token comment\">\/\/ Validates private data to avoid false triggers.<\/span><\/p>\n<p>    condition <span class=\"token operator\">&#061;<\/span> <span class=\"token number\">1<\/span><span class=\"token punctuation\">;<\/span>              <span class=\"token comment\">\/\/ Marks event as ready.<\/span><br \/>\n    <span class=\"token function\">wake_up_interruptible<\/span><span class=\"token punctuation\">(<\/span><span class=\"token operator\">&amp;<\/span>wq<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span> <span class=\"token comment\">\/\/ Wakes up the waiting application process.<\/span><br \/>\n    <span class=\"token keyword\">return<\/span> IRQ_HANDLED<span class=\"token punctuation\">;<\/span>         <span class=\"token comment\">\/\/ Informs the kernel the interrupt is handled.<\/span><br \/>\n<span class=\"token punctuation\">}<\/span><\/p>\n<p><span class=\"token comment\">\/\/ Modified &#096;read&#096; function: Implements blocking I\/O.<\/span><br \/>\n<span class=\"token keyword\">static<\/span> <span class=\"token class-name\">ssize_t<\/span> <span class=\"token function\">read<\/span><span class=\"token punctuation\">(<\/span><span class=\"token keyword\">struct<\/span> <span class=\"token class-name\">file<\/span> <span class=\"token operator\">*<\/span>file<span class=\"token punctuation\">,<\/span> <span class=\"token keyword\">char<\/span> __user <span class=\"token operator\">*<\/span>buf<span class=\"token punctuation\">,<\/span> <span class=\"token class-name\">size_t<\/span> size<span class=\"token punctuation\">,<\/span> <span class=\"token class-name\">loff_t<\/span> <span class=\"token operator\">*<\/span>loff<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n    condition <span class=\"token operator\">&#061;<\/span> <span class=\"token number\">0<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token comment\">\/\/ Sleeps if condition is unmet (0% CPU usage).<\/span><br \/>\n    <span class=\"token function\">wait_event_interruptible<\/span><span class=\"token punctuation\">(<\/span>wq<span class=\"token punctuation\">,<\/span> condition<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><\/p>\n<p>    <span class=\"token keyword\">int<\/span> status <span class=\"token operator\">&#061;<\/span> <span class=\"token number\">1<\/span><span class=\"token punctuation\">;<\/span> <span class=\"token comment\">\/\/ Marks key press event.<\/span><br \/>\n    <span class=\"token function\">copy_to_user<\/span><span class=\"token punctuation\">(<\/span>buf<span class=\"token punctuation\">,<\/span> <span class=\"token operator\">&amp;<\/span>status<span class=\"token punctuation\">,<\/span> <span class=\"token keyword\">sizeof<\/span><span class=\"token punctuation\">(<\/span>status<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token keyword\">return<\/span> <span class=\"token keyword\">sizeof<\/span><span class=\"token punctuation\">(<\/span>status<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n<span class=\"token punctuation\">}<\/span><\/p>\n<p><span class=\"token comment\">\/\/ &#096;probe&#096; function: Adds interrupt initialization.<\/span><br \/>\n<span class=\"token keyword\">static<\/span> <span class=\"token keyword\">int<\/span> <span class=\"token function\">probe<\/span><span class=\"token punctuation\">(<\/span><span class=\"token keyword\">struct<\/span> <span class=\"token class-name\">platform_device<\/span> <span class=\"token operator\">*<\/span>pdev<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n    <span class=\"token comment\">\/\/ (GPIO initialization omitted, same as V1.)<\/span><br \/>\n    key_irq <span class=\"token operator\">&#061;<\/span> <span class=\"token function\">gpio_to_irq<\/span><span class=\"token punctuation\">(<\/span>key_gpio<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span> <span class=\"token comment\">\/\/ Converts GPIO to interrupt number (depends on GPIO-IRQ binding).<\/span><\/p>\n<p>    <span class=\"token comment\">\/\/ Registers interrupt: interrupt number, ISR, trigger mode, name, private data.<\/span><br \/>\n    ret <span class=\"token operator\">&#061;<\/span> <span class=\"token function\">request_irq<\/span><span class=\"token punctuation\">(<\/span>key_irq<span class=\"token punctuation\">,<\/span> key_irq_handler<span class=\"token punctuation\">,<\/span><br \/>\n                     IRQF_TRIGGER_FALLING<span class=\"token punctuation\">,<\/span> <span class=\"token string\">&#034;key0_irq&#034;<\/span><span class=\"token punctuation\">,<\/span> <span class=\"token operator\">&amp;<\/span>arg<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token function\">init_waitqueue_head<\/span><span class=\"token punctuation\">(<\/span><span class=\"token operator\">&amp;<\/span>wq<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span> <span class=\"token comment\">\/\/ Initializes wait queue.<\/span><\/p>\n<p>    <span class=\"token function\">printk<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string\">&#034;V2: Interrupt &#043; wait queue driver initialized.\\\\n&#034;<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token keyword\">return<\/span> <span class=\"token number\">0<\/span><span class=\"token punctuation\">;<\/span><br \/>\n<span class=\"token punctuation\">}<\/span><\/p>\n<h5>Core Advantages<\/h5>\n<ul>\n<li>0% CPU usage when the application is blocked, responding only on key press.<\/li>\n<li>Timely interrupt response, capturing transient key actions with improved real-time performance.<\/li>\n<li>Retains miscellaneous device features, auto-creating \/dev\/key without manual mknod.<\/li>\n<\/ul>\n<h4>3.3 V3: Interrupt Parsing via Device Tree (key_irq_sub.c)<\/h4>\n<p>The gpio_to_irq approach in V2 still relies on \u201cfixed GPIO-interrupt number binding.\u201d V3 resolves interrupt numbers directly from the device tree, fully decoupling hardware details\u2014the standard Linux implementation.<\/p>\n<h5>Key Improvement: Interrupt Number Resolution<\/h5>\n<p><span class=\"token comment\">\/\/ V2 approach: Depends on GPIO-interrupt binding  <\/span><br \/>\n<span class=\"token comment\">\/\/ key_irq &#061; gpio_to_irq(key_gpio);  <\/span><\/p>\n<p><span class=\"token comment\">\/\/ V3 approach: Parses interrupt number from device tree (recommended)  <\/span><br \/>\nkey_irq <span class=\"token operator\">&#061;<\/span> <span class=\"token function\">irq_of_parse_and_map<\/span><span class=\"token punctuation\">(<\/span>pdts<span class=\"token punctuation\">,<\/span> <span class=\"token number\">0<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span> <span class=\"token comment\">\/\/ pdts: device tree node pointer, 0: interrupt index  <\/span><br \/>\n<span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>key_irq <span class=\"token operator\">&lt;<\/span> <span class=\"token number\">0<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n    <span class=\"token function\">printk<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string\">&#034;Failed to parse interrupt number\\\\n&#034;<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token keyword\">return<\/span> <span class=\"token operator\">&#8211;<\/span>EINVAL<span class=\"token punctuation\">;<\/span><br \/>\n<span class=\"token punctuation\">}<\/span>  <\/p>\n<h5>Core Advantages<\/h5>\n<ul>\n<li>No dependency on fixed GPIO-interrupt binding; hardware changes only require device tree updates.<\/li>\n<li>Driver code is generic and portable to other Linux platforms supporting device trees.<\/li>\n<li>Fully aligns with Linux device driver models, adhering to the \u201chardware-description-and-driver-logic-separation\u201d philosophy.<\/li>\n<\/ul>\n<h4>3.4 Unified Platform Driver Framework<\/h4>\n<p>All three versions are built on the standard Platform driver framework, ensuring scalability and compatibility:<\/p>\n<p><span class=\"token comment\">\/\/ Device tree match table: Matches DTS node&#039;s &#039;compatible&#039; property  <\/span><br \/>\n<span class=\"token keyword\">static<\/span> <span class=\"token keyword\">struct<\/span> <span class=\"token class-name\">of_device_id<\/span> key_table<span class=\"token punctuation\">[<\/span><span class=\"token punctuation\">]<\/span> <span class=\"token operator\">&#061;<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n    <span class=\"token punctuation\">{<\/span><span class=\"token punctuation\">.<\/span>compatible <span class=\"token operator\">&#061;<\/span> <span class=\"token string\">&#034;pt-key&#034;<\/span><span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">,<\/span><br \/>\n    <span class=\"token punctuation\">{<\/span><span class=\"token punctuation\">}<\/span> <span class=\"token comment\">\/\/ Sentinel  <\/span><br \/>\n<span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">;<\/span>  <\/p>\n<p><span class=\"token comment\">\/\/ Platform driver structure  <\/span><br \/>\n<span class=\"token keyword\">static<\/span> <span class=\"token keyword\">struct<\/span> <span class=\"token class-name\">platform_driver<\/span> pdrv <span class=\"token operator\">&#061;<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n    <span class=\"token punctuation\">.<\/span>probe <span class=\"token operator\">&#061;<\/span> probe<span class=\"token punctuation\">,<\/span>    <span class=\"token comment\">\/\/ Executed on successful match  <\/span><br \/>\n    <span class=\"token punctuation\">.<\/span>remove <span class=\"token operator\">&#061;<\/span> remove<span class=\"token punctuation\">,<\/span>  <span class=\"token comment\">\/\/ Executed on driver unload  <\/span><br \/>\n    <span class=\"token punctuation\">.<\/span>driver <span class=\"token operator\">&#061;<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n        <span class=\"token punctuation\">.<\/span>name <span class=\"token operator\">&#061;<\/span> DEV_NAME<span class=\"token punctuation\">,<\/span><br \/>\n        <span class=\"token punctuation\">.<\/span>of_match_table <span class=\"token operator\">&#061;<\/span> key_table<span class=\"token punctuation\">,<\/span> <span class=\"token comment\">\/\/ Device tree match table  <\/span><br \/>\n    <span class=\"token punctuation\">}<\/span><br \/>\n<span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">;<\/span>  <\/p>\n<p><span class=\"token comment\">\/\/ Driver entry\/exit (simplified via macros)  <\/span><br \/>\n<span class=\"token function\">module_platform_driver<\/span><span class=\"token punctuation\">(<\/span>pdrv<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n<span class=\"token function\">MODULE_LICENSE<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string\">&#034;GPL&#034;<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span> <span class=\"token comment\">\/\/ Open-source license declaration  <\/span><\/p>\n<h3>IV. Application: Efficient Blocking I\/O<\/h3>\n<p>The application avoids polling by using read to block until key events occur, ensuring simplicity and efficiency.<\/p>\n<h4>4.1 Application Code<\/h4>\n<p><span class=\"token macro property\"><span class=\"token directive-hash\">#<\/span><span class=\"token directive keyword\">include<\/span> <span class=\"token string\">&lt;stdio.h&gt;<\/span>  <\/span><br \/>\n<span class=\"token macro property\"><span class=\"token directive-hash\">#<\/span><span class=\"token directive keyword\">include<\/span> <span class=\"token string\">&lt;fcntl.h&gt;<\/span>  <\/span><br \/>\n<span class=\"token macro property\"><span class=\"token directive-hash\">#<\/span><span class=\"token directive keyword\">include<\/span> <span class=\"token string\">&lt;unistd.h&gt;<\/span>  <\/span><\/p>\n<p><span class=\"token keyword\">int<\/span> <span class=\"token function\">main<\/span><span class=\"token punctuation\">(<\/span><span class=\"token keyword\">int<\/span> argc<span class=\"token punctuation\">,<\/span> <span class=\"token keyword\">const<\/span> <span class=\"token keyword\">char<\/span> <span class=\"token operator\">*<\/span>argv<span class=\"token punctuation\">[<\/span><span class=\"token punctuation\">]<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n    <span class=\"token keyword\">int<\/span> fd <span class=\"token operator\">&#061;<\/span> <span class=\"token function\">open<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string\">&#034;\/dev\/key&#034;<\/span><span class=\"token punctuation\">,<\/span> O_RDWR<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>fd <span class=\"token operator\">&lt;<\/span> <span class=\"token number\">0<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n        <span class=\"token function\">perror<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string\">&#034;Failed to open \/dev\/key&#034;<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n        <span class=\"token keyword\">return<\/span> <span class=\"token number\">1<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token punctuation\">}<\/span>  <\/p>\n<p>    <span class=\"token keyword\">int<\/span> status <span class=\"token operator\">&#061;<\/span> <span class=\"token number\">0<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token keyword\">while<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token number\">1<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n        <span class=\"token comment\">\/\/ Blocks until key event; process sleeps when idle  <\/span><br \/>\n        <span class=\"token keyword\">int<\/span> ret <span class=\"token operator\">&#061;<\/span> <span class=\"token function\">read<\/span><span class=\"token punctuation\">(<\/span>fd<span class=\"token punctuation\">,<\/span> <span class=\"token operator\">&amp;<\/span>status<span class=\"token punctuation\">,<\/span> <span class=\"token keyword\">sizeof<\/span><span class=\"token punctuation\">(<\/span>status<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n        <span class=\"token function\">printf<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string\">&#034;Key pressed! ret&#061;%d, status&#061;%d\\\\n&#034;<\/span><span class=\"token punctuation\">,<\/span> ret<span class=\"token punctuation\">,<\/span> status<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token punctuation\">}<\/span>  <\/p>\n<p>    <span class=\"token function\">close<\/span><span class=\"token punctuation\">(<\/span>fd<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token keyword\">return<\/span> <span class=\"token number\">0<\/span><span class=\"token punctuation\">;<\/span><br \/>\n<span class=\"token punctuation\">}<\/span>  <\/p>\n<h4>4.2 Performance Comparison<\/h4>\n<table>\n<tr>VersionCPU UsageResponse Behavior<\/tr>\n<tbody>\n<tr>\n<td>V1<\/td>\n<td>~99%<\/td>\n<td>Polling, potential missed events<\/td>\n<\/tr>\n<tr>\n<td>V2\/V3<\/td>\n<td>0% (sleep)<\/td>\n<td>Interrupt-triggered, real-time<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h3>V. Practical Verification: Compilation to Execution<\/h3>\n<h4>5.1 Compilation Setup<\/h4>\n<h5>(1) Driver Module Compilation (Makefile)<\/h5>\n<p># Select driver version (choose one)<br \/>\nobj-m &#043;&#061; key.o          # V1: GPIO polling<br \/>\n# obj-m &#043;&#061; key_irq.o     # V2: Interrupt &#043; wait queue<br \/>\n# obj-m &#043;&#061; key_irq_sub.o # V3: Device tree interrupt parsing<br \/>\nKERNELDIR ?&#061; \/home\/linux\/IMX6ULL\/linux-imx-rel_imx_4.1.15_2.1.0_ga_alientek<br \/>\nPWD :&#061; $(shell pwd)  <\/p>\n<p>all:<br \/>\n    $(MAKE) -C $(KERNELDIR) M&#061;$(PWD) modules CROSS_COMPILE&#061;arm-linux-gnueabihf- ARCH&#061;arm  <\/p>\n<p>clean:<br \/>\n    $(MAKE) -C $(KERNELDIR) M&#061;$(PWD) clean  <\/p>\n<p>Run: make to generate .ko driver module.<\/p>\n<h5>(2) Application Compilation<\/h5>\n<p>arm-linux-gnueabihf-gcc key_app.c -o key_app  <\/p>\n<h5>(3) Device Tree Compilation<\/h5>\n<p><span class=\"token function\">make<\/span> <span class=\"token assign-left variable\">ARCH<\/span><span class=\"token operator\">&#061;<\/span>arm <span class=\"token assign-left variable\">CROSS_COMPILE<\/span><span class=\"token operator\">&#061;<\/span>arm-linux-gnueabihf- dtbs  <\/p>\n<p>Generates updated device tree (e.g., imx6ull-14&#215;14-evk.dtb).<\/p>\n<h4>5.2 Driver Loading and Validation (V3 Recommended)<\/h4>\n<li>Copy imx6ull-14&#215;14-evk.dtb, key_irq_sub.ko, and key_app to the board.<\/li>\n<li>Power on the board and load the new device tree.<\/li>\n<li>Load the driver module:insmod key_irq_sub.ko<br \/>\n<span class=\"token function\">ls<\/span> \/dev\/key  <span class=\"token comment\"># Verify device node creation  <\/span>\n <\/li>\n<li>Run the application:.\/key_app\n <\/li>\n<li>Test: Press the key; app prints \u201cKey pressed! ret&#061;4, status&#061;1\u201d.<\/li>\n<li>Check kernel logs:<span class=\"token function\">dmesg<\/span> <span class=\"token operator\">|<\/span> <span class=\"token function\">grep<\/span> -E <span class=\"token string\">&#034;probe|irq&#034;<\/span><br \/>\n Expected output:key platform_driver_register success<br \/>\n#########################  key_driver  probe<br \/>\nirq &#061; 123 dev &#061; 100  # Interrupt number and private data\n <\/li>\n<li>Unload the driver:rmmod key_irq_sub.ko\n <\/li>\n<h3>VI. Troubleshooting Guide<\/h3>\n<h4>6.1 Driver Match Failure (probe Not Executed)<\/h4>\n<ul>\n<li>compatible mismatch: Ensure of_device_id in the driver exactly matches the DTS node.<\/li>\n<li>Incorrect DTS node path: Verify of_find_node_by_path(&#034;\/ptkey&#034;) matches the DTS path.<\/li>\n<li>Device tree not updated: Confirm the compiled DTB file is flashed.<\/li>\n<\/ul>\n<h4>6.2 Interrupt Registration Failure (request_irq Returns Negative)<\/h4>\n<ul>\n<li>Incorrect interrupt number: Check irq_of_parse_and_map return value; validate DTS interrupt configuration.<\/li>\n<li>Interrupt conflict: Use cat \/proc\/interrupts to check occupied interrupts.<\/li>\n<li>Trigger mode error: Ensure the interrupt trigger matches hardware (e.g., falling edge for keys).<\/li>\n<\/ul>\n<h4>6.3 Application Not Sleeping (100% CPU Usage)<\/h4>\n<ul>\n<li>Uninitialized wait queue: Call init_waitqueue_head(&amp;wq).<\/li>\n<li>ISR not waking queue: Ensure condition&#061;1 and wake_up_interruptible(&amp;wq) are called.<\/li>\n<li>Condition variable not reset: Set condition&#061;0 in read before waiting.<\/li>\n<\/ul>\n<h4>6.4 Unresponsive Key<\/h4>\n<ul>\n<li>GPIO misconfiguration: Confirm gpio_direction_input sets GPIO as input.<\/li>\n<li>Hardware wiring error: GPIO should be high when idle, low when pressed.<\/li>\n<li>Incorrect interrupt trigger: For key-release events, use IRQF_TRIGGER_RISING.<\/li>\n<\/ul>\n<h3>VII. Key Takeaways<\/h3>\n<h4>7.1 Essential API Reference<\/h4>\n<table>\n<tr>API FunctionPurpose<\/tr>\n<tbody>\n<tr>\n<td>of_find_node_by_path<\/td>\n<td>Locates device tree node by path<\/td>\n<\/tr>\n<tr>\n<td>of_get_named_gpio<\/td>\n<td>Retrieves GPIO number from DTS node<\/td>\n<\/tr>\n<tr>\n<td>gpio_request<\/td>\n<td>Reserves GPIO resources<\/td>\n<\/tr>\n<tr>\n<td>gpio_to_irq<\/td>\n<td>Converts GPIO to interrupt (V2)<\/td>\n<\/tr>\n<tr>\n<td>irq_of_parse_and_map<\/td>\n<td>Parses interrupt from DTS (V3 recommended)<\/td>\n<\/tr>\n<tr>\n<td>request_irq<\/td>\n<td>Registers interrupt handler<\/td>\n<\/tr>\n<tr>\n<td>init_waitqueue_head<\/td>\n<td>Initializes wait queue<\/td>\n<\/tr>\n<tr>\n<td>wait_event_interruptible<\/td>\n<td>Puts process to sleep until condition<\/td>\n<\/tr>\n<tr>\n<td>wake_up_interruptible<\/td>\n<td>Wakes sleeping process<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h4>7.2 Design Principles<\/h4>\n<li>Decoupling: Device tree describes hardware; drivers focus on logic.<\/li>\n<li>Efficiency: Interrupts replace polling; blocking I\/O maximizes CPU utilization.<\/li>\n<li>Standardization: Follows Linux driver models (Platform bus, misc devices) for compatibility.<\/li>\n<h3>VIII. Conclusion<\/h3>\n<p>This guide demonstrates the evolution of a Linux key driver from \u201cbasic functionality\u201d to \u201chigh-performance &#043; high portability\u201d:<\/p>\n<ul>\n<li>V1: Introduces GPIO subsystem basics.<\/li>\n<li>V2: Core interrupt and wait queue mechanisms to eliminate CPU waste.<\/li>\n<li>V3: Device tree standardization for full hardware-driver decoupling.<\/li>\n<\/ul>\n<p>This methodology applies to all Linux input devices (e.g., touch keys, encoders, IR receivers) and forms the foundation for advanced driver development (e.g., input subsystems, touchscreen drivers).<\/p>\n","protected":false},"excerpt":{"rendered":"<p>IMX6ULL Linux Key Driver Practice: A Complete Analysis from GPIO Polling to Device Tree Interrupts  Wait Queues<br \/>\nIn embedded Linux development, key drivers are a classic case for understanding character devices, Platform bus, interrupt mech<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[58,270,269,100,43,78],"topic":[],"class_list":["post-74394","post","type-post","status-publish","format-standard","hentry","category-server","tag-linux","tag-270","tag-269","tag-100","tag-43","tag-78"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v20.3 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>DAY73 IMX6ULL Linux Key Driver Practice: A Complete Analysis from GPIO Polling to Device Tree Interr - \u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.wsisp.com\/helps\/74394.html\" \/>\n<meta property=\"og:locale\" content=\"zh_CN\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"DAY73 IMX6ULL Linux Key Driver Practice: A Complete Analysis from GPIO Polling to Device Tree Interr - \u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3\" \/>\n<meta property=\"og:description\" content=\"IMX6ULL Linux Key Driver Practice: A Complete Analysis from GPIO Polling to Device Tree Interrupts Wait Queues In embedded Linux development, key drivers are a classic case for understanding character devices, Platform bus, interrupt mech\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.wsisp.com\/helps\/74394.html\" \/>\n<meta property=\"og:site_name\" content=\"\u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3\" \/>\n<meta property=\"article:published_time\" content=\"2026-02-09T10:25:27+00:00\" \/>\n<meta name=\"author\" content=\"admin\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"\u4f5c\u8005\" \/>\n\t<meta name=\"twitter:data1\" content=\"admin\" \/>\n\t<meta name=\"twitter:label2\" content=\"\u9884\u8ba1\u9605\u8bfb\u65f6\u95f4\" \/>\n\t<meta name=\"twitter:data2\" content=\"10 \u5206\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.wsisp.com\/helps\/74394.html\",\"url\":\"https:\/\/www.wsisp.com\/helps\/74394.html\",\"name\":\"DAY73 IMX6ULL Linux Key Driver Practice: A Complete Analysis from GPIO Polling to Device Tree Interr - \u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3\",\"isPartOf\":{\"@id\":\"https:\/\/www.wsisp.com\/helps\/#website\"},\"datePublished\":\"2026-02-09T10:25:27+00:00\",\"dateModified\":\"2026-02-09T10:25:27+00:00\",\"author\":{\"@id\":\"https:\/\/www.wsisp.com\/helps\/#\/schema\/person\/358e386c577a3ab51c4493330a20ad41\"},\"breadcrumb\":{\"@id\":\"https:\/\/www.wsisp.com\/helps\/74394.html#breadcrumb\"},\"inLanguage\":\"zh-Hans\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.wsisp.com\/helps\/74394.html\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.wsisp.com\/helps\/74394.html#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"\u9996\u9875\",\"item\":\"https:\/\/www.wsisp.com\/helps\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"DAY73 IMX6ULL Linux Key Driver Practice: A Complete Analysis from GPIO Polling to Device Tree Interr\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.wsisp.com\/helps\/#website\",\"url\":\"https:\/\/www.wsisp.com\/helps\/\",\"name\":\"\u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3\",\"description\":\"\u9999\u6e2f\u670d\u52a1\u5668_\u9999\u6e2f\u4e91\u670d\u52a1\u5668\u8d44\u8baf_\u670d\u52a1\u5668\u5e2e\u52a9\u6587\u6863_\u670d\u52a1\u5668\u6559\u7a0b\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.wsisp.com\/helps\/?s={search_term_string}\"},\"query-input\":\"required name=search_term_string\"}],\"inLanguage\":\"zh-Hans\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.wsisp.com\/helps\/#\/schema\/person\/358e386c577a3ab51c4493330a20ad41\",\"name\":\"admin\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"zh-Hans\",\"@id\":\"https:\/\/www.wsisp.com\/helps\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/gravatar.wp-china-yes.net\/avatar\/?s=96&d=mystery\",\"contentUrl\":\"https:\/\/gravatar.wp-china-yes.net\/avatar\/?s=96&d=mystery\",\"caption\":\"admin\"},\"sameAs\":[\"http:\/\/wp.wsisp.com\"],\"url\":\"https:\/\/www.wsisp.com\/helps\/author\/admin\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"DAY73 IMX6ULL Linux Key Driver Practice: A Complete Analysis from GPIO Polling to Device Tree Interr - \u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.wsisp.com\/helps\/74394.html","og_locale":"zh_CN","og_type":"article","og_title":"DAY73 IMX6ULL Linux Key Driver Practice: A Complete Analysis from GPIO Polling to Device Tree Interr - \u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3","og_description":"IMX6ULL Linux Key Driver Practice: A Complete Analysis from GPIO Polling to Device Tree Interrupts Wait Queues In embedded Linux development, key drivers are a classic case for understanding character devices, Platform bus, interrupt mech","og_url":"https:\/\/www.wsisp.com\/helps\/74394.html","og_site_name":"\u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3","article_published_time":"2026-02-09T10:25:27+00:00","author":"admin","twitter_card":"summary_large_image","twitter_misc":{"\u4f5c\u8005":"admin","\u9884\u8ba1\u9605\u8bfb\u65f6\u95f4":"10 \u5206"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/www.wsisp.com\/helps\/74394.html","url":"https:\/\/www.wsisp.com\/helps\/74394.html","name":"DAY73 IMX6ULL Linux Key Driver Practice: A Complete Analysis from GPIO Polling to Device Tree Interr - \u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3","isPartOf":{"@id":"https:\/\/www.wsisp.com\/helps\/#website"},"datePublished":"2026-02-09T10:25:27+00:00","dateModified":"2026-02-09T10:25:27+00:00","author":{"@id":"https:\/\/www.wsisp.com\/helps\/#\/schema\/person\/358e386c577a3ab51c4493330a20ad41"},"breadcrumb":{"@id":"https:\/\/www.wsisp.com\/helps\/74394.html#breadcrumb"},"inLanguage":"zh-Hans","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.wsisp.com\/helps\/74394.html"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/www.wsisp.com\/helps\/74394.html#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"\u9996\u9875","item":"https:\/\/www.wsisp.com\/helps"},{"@type":"ListItem","position":2,"name":"DAY73 IMX6ULL Linux Key Driver Practice: A Complete Analysis from GPIO Polling to Device Tree Interr"}]},{"@type":"WebSite","@id":"https:\/\/www.wsisp.com\/helps\/#website","url":"https:\/\/www.wsisp.com\/helps\/","name":"\u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3","description":"\u9999\u6e2f\u670d\u52a1\u5668_\u9999\u6e2f\u4e91\u670d\u52a1\u5668\u8d44\u8baf_\u670d\u52a1\u5668\u5e2e\u52a9\u6587\u6863_\u670d\u52a1\u5668\u6559\u7a0b","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.wsisp.com\/helps\/?s={search_term_string}"},"query-input":"required name=search_term_string"}],"inLanguage":"zh-Hans"},{"@type":"Person","@id":"https:\/\/www.wsisp.com\/helps\/#\/schema\/person\/358e386c577a3ab51c4493330a20ad41","name":"admin","image":{"@type":"ImageObject","inLanguage":"zh-Hans","@id":"https:\/\/www.wsisp.com\/helps\/#\/schema\/person\/image\/","url":"https:\/\/gravatar.wp-china-yes.net\/avatar\/?s=96&d=mystery","contentUrl":"https:\/\/gravatar.wp-china-yes.net\/avatar\/?s=96&d=mystery","caption":"admin"},"sameAs":["http:\/\/wp.wsisp.com"],"url":"https:\/\/www.wsisp.com\/helps\/author\/admin"}]}},"_links":{"self":[{"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/posts\/74394","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/comments?post=74394"}],"version-history":[{"count":0,"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/posts\/74394\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/media?parent=74394"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/categories?post=74394"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/tags?post=74394"},{"taxonomy":"topic","embeddable":true,"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/topic?post=74394"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}