linux裝置驅動的學習之一

來源:互聯網
上載者:User

標籤:style   blog   io   color   os   使用   sp   for   檔案   

由於項目上要用到,於是乎我要學習linux裝置驅動的編寫,開始的時候還比較清楚,能夠對簡單的GPIO控制操作實現出來,但是項目上要用到的是SPI和GPIO的輸入中斷來讀取AD的電壓值,然後就陷入到了一個龐大的裝置代碼閱讀中去了,尤其是platform device的學習,到現在都還沒有理清其中的關係,雖然搜尋了很多網上的文章,但慶幸的是我有一種比著框框買鴨蛋的精神,我想要比著這些源碼畫一個出來。以前沒有在LPC1768上使用過SPI,導致對SPI是一個完全陌生的狀態,不清楚他的傳輸方式,這也是學習中的一個問題,也是一開始我的盲目無方向感的原因,因為這裡的linux SPI裝置驅動和SPI協議就是兩個要學習的問題。

先來把“簡單”的中斷實現出來吧,其實中斷處理並不簡單,他是很多項目中必須要用到的東西,這裡使用的S5PV210的GPH3(2)這一個GPIO來實現,查看晶片手冊其對應的外部中斷號為EINT26,所以在驅動中定義一個結構體來描述他如下:

struct s5pv210_gpio_key{    int pin;//引腳號    int eint;//外部中斷號    int eintcfg;//外部中斷使能    int inputcfg;//輸入使能};struct s5pv210_gpio_key my_gpio_key={        .pin = S5PV210_GPH3(2),     .eintcfg = 0X0f<<4,          .inputcfg = 0<<4,    .eint = IRQ_EINT(26),    };

然後構建一個驅動的架構代碼:

static int __init gpio_interrupt_init(void){    int err=0;    gpio_int_num = MKDEV(MY_MAJOR,MY_MINOR);    err = register_chrdev_region(gpio_int_num, 1, "GPH3_2_interrupt");    if(err < 0)    {        printk("register error, num: %d have been used!\n", gpio_int_num);        return err;    }    cdev_init(&my_cdev , &gpio_interrupt_ops);     my_cdev.owner = THIS_MODULE;    err = cdev_add(&my_cdev, gpio_int_num, 1);    if(err < 0)    {        printk("add my_cdev error!\n");           return err;    }        printk("init ok\n");        return 0;    }static void __exit gpio_interrupt_exit(void){    cdev_del(&my_cdev);    unregister_chrdev_region(gpio_int_num, 1);    printk("exit ok\n");   }module_init(gpio_interrupt_init);module_exit(gpio_interrupt_exit);MODULE_LICENSE("GPL");MODULE_AUTHOR("galuo");

 在載入模組的函數中,register_chrdev_region註冊了一個裝置號,在載入了該模組後,使用mknod命令來建立裝置檔案節點;然後使用cdev_init來初始化字元裝置結構體變數cdev,將file_operations結構體gpio_interrupt_ops載入進來,就可以在使用者空間使用的時候明確調用的關係;使用cdev_add向核心註冊字元I/O裝置。字元模組的退出函數使用cdev_del函數來刪除核心中的字元裝置;使用unregister_chrdev_region來釋放裝置號。

定義file_operations結構體執行個體gpio_interrupt_ops,在使用者空間操作的時候實現調用對應的功能,其定義如下:

struct file_operations gpio_interrupt_ops={    .open=gpio_interrupt_open,    .release=gpio_interrupt_close,    };

.open實現中斷的請求,並且使能中斷

.release實現中斷的釋放

int gpio_interrupt_open(struct inode *inode,struct file *file){    int error;    error = request_irq(my_gpio_key.eint, //中斷號                        gpio_keys_isr,//中斷處理函數                        IRQF_TRIGGER_FALLING ,//下降沿觸發                        "interrupt_test",                        NULL);    if(error){        printk("request irq failed!\n");        return -1;    }    printk("hello irq\n");    return 0;    }int gpio_interrupt_close(struct inode *inode,struct file *file){    free_irq(my_gpio_key.eint, NULL);    printk("good bye irq\n");    return 0;}

在中斷處理函數gpio_keys_isr中就可以實現中斷的需求:

static irqreturn_t gpio_keys_isr(int irq, void *dev_id){    printk("this is interrupt function\n");        return IRQ_HANDLED;}

這裡中斷處理函數的定義類型和傳回值固定不變。

linux裝置驅動的學習之一

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.