<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    posts - 189,comments - 115,trackbacks - 0

    linux下的GPIO驅動 2009-06-05 08:29

    字號:    

    編寫驅動程序,首先要了解是什么類型的設備。linux下的設備分為三類,分別為:字符設備,塊設備和網絡設備。字符設備類型是根據是否以字符流為數據的交換方式,大部分設備都是字符設備,如鍵盤,串口等,塊設備則是以塊為單位進行管理的設備,如,磁盤。網絡設備就是網卡等。

    其次要了解應用程序和驅動程序的區別,兩者的主要區別分為以下三點:

    1入口函數的任務不相同,應用程序完成一個任務,驅動只完成初始化工作,比如中斷

          申請,寄存器設置,定時器設置。

    2運行時的cpu模式不相同,驅動具有很高的權限,應用程序是在用戶態下運行,而驅

      動程序是在內核態下執行。

    3 驅動程序不能調用C庫函數,內核為驅動程序提供一些函數。如printk(KERN_NOTICE fmt, ##arg),第一個參數為打印級別,有如下的打印級別:

    KERN_EMERG 用于緊急事件,一般是系統崩潰前的提示信息

    KERN_ALERT 用于需要立即采取動作的場合

    KERN_CRIT 臨界狀態,通常設計驗證的硬件或軟件操作失敗

    KERN_ERR 用于報告錯誤狀態.設備驅動程序通常會用它報告來自硬件的問題

    KERN_WARNING 就可能出現的問題提出警告.這些問題通常不會對系統造成嚴重破壞

    KERN_NOTICE 有必要提示的正常情況.許多安全相關的情況用這個級別匯報

    KERN_INFO 提示性信息.有很多驅動程序在啟動時用這個級別打印相關信息

    KERN_DEBUG 用于調試的信息

    u_long copy_from_user(void *to, const void *from, u_long len),由用戶態拷貝到內核態;

    u_long copy_to_user(void * to, const void *from, u_long len),由內核態拷貝到用戶態。

    鑒于以上區別,驅動程序需要完成以下三點基本功能:

    1:要對設備進行初始化和釋放功能模塊,就如上面的寄存器設置,中斷的申請,向內核注 

       冊驅動程序(register_chrdev()),卸載驅動程序(unregister_chrdev())。

    2:能進行數據傳輸,在read(),write()函數里具體實現,數據傳輸工作。

    3:能進行控制操作,給用戶提供的ioctl()函數里可實現一些用戶的選擇性設置功能。

    確定一個設備的執行函數集(結構體)

    static struct file_operations myGPIO_fops = {

    owner: THIS_MODULE,

    write: myGPIO_write,

    read: myGPIO_read,

    ioctl: myGPIO_ioctl,

    open: myGPIO_open,

    release: myGPIO_release,

    };

    接下來是初始化工作,需要寫在一個init()函數中,這個函數是獨立的也是自動執行的,在這之中主要是對一些寄存器進行初始化操作。同樣需要完成卸載驅動模塊。

    myGPIO_Major = register_chrdev(0, DRIVER_NAME, &myDriver_fops);

    上面的程序完成設備號的注冊,第一個參數為主設備號,一般為0,由系統來分配。

    第二個參數為設備名,這需要在/dev/(/dev目錄下設備名由命令 <mknod  設備名 C 主設備號  從設備號>來生成)目錄下出現的設備名相符合。相反的在卸載中就取消注冊

    unregister_chrdev(myGPIO_Major, DRIVER_NAME);

    最后將這兩個模塊加入到內核中,由程序段的最后兩行完成。

    static int __init myGPIO_init(void)

    {

    PRINTK("GPIO init\n");

    myGPIO_Major = register_chrdev(0, DRIVER_NAME, &myGPIO_fops);

    if(myGPIO_Major < 0)

    {

    PRINTK("register char device fail!\n");

    return myGPIO_Major;

    }

    PRINTK("register myGPIO OK! Major = %d\n", myGPIO_Major);

    #ifdef CONFIG_DEVFS_FS

    devfs_myDriver_dir = devfs_mk_dir(NULL, "GPIO", NULL);

    devfs_myDriver_raw = devfs_register(devfs_myDriver_dir, "raw0", DEVFS_FL_DEFAULT, myGPIO_Major, 0, S_IFCHR | S_IRUSR | S_IWUSR, &myGPIO_fops, NULL);

    PRINTK("add dev file to devfs OK!\n");

    #endif

    return 0;

    }

    static void __exit myGPIO_exit(void)

    {

    /* Module exit code */

    PRINTK("GPIO exit\n");

    /* Driver unregister */

    if(myGPIO_Major > 0)

    {

    #ifdef CONFIG_DEVFS_FS

    devfs_unregister(devfs_myDriver_raw);

    devfs_unregister(devfs_myDriver_dir);

    #endif

    unregister_chrdev(myGPIO_Major, DRIVER_NAME);

    }

    return;

    }

    MODULE_AUTHOR("LiuFan");

    MODULE_LICENSE("Dual BSD/GPL");

    module_init(myGPIO_init);

    module_exit(myGPIO_exit);

    設備執行函數功能的實現將在下面完成。如結構體的函數,但并不是全都需要實現。open()函數中是執行一些設備工作前的初始化工作。rlease()則是將設備的相關寄存器恢復到原來的值。read()函數是將設備中的數據拷貝到內核,write()函數是將內核數據拷貝到對應的設備中。MOD_INC_USE_COUNT和MOD_DEC_USE_COUNT兩個宏是提供給系統對硬件資源進行控制訪問的。在open()和rlease()兩個函數中最基本的操作應是實現以上兩個宏的操作。

    static unsigned char myGPIO_Buffer[1024*1024];

    /* Driver Operation Functions */

    static int myGPIO_open(struct inode *inode, struct file *filp)

    {

    // int Minor = MINOR(inode->i_rdev);

    // filp->private_data = 0;

    MOD_INC_USE_COUNT;

    PRINTK("myDriver open called!\n");

    return 0;

    }

    static int myGPIO_release(struct inode *inode, struct file *filp)

    {

    // int Minor = MINOR(inode->i_rdev);

    MOD_DEC_USE_COUNT;

    PRINTK("myDriver release called!\n");

    return 0;

    }

    static ssize_t myGPIO_read(struct file *filp, char *buf, size_t count, loff_t *f_pos)

    {

    char dat;

    size_t read_size = count;

    PRINTK("GPIO read called!\n");

    PRINTK("\tcount=%d, pos=%d\n", count, (int)*f_pos);

    /* if(*f_pos >= sizeof(myGPIO_Buffer))

    {

    PRINTK("[GPIO read]Buffer Overlap\n");

    *f_pos = sizeof(myGPIO_Buffer);

    return 0;

    }

    if((count + *f_pos) > sizeof(myGPIO_Buffer))

    {

    PRINTK("count + f_pos > sizeof buffer\n");

    read_size = sizeof(myGPIO_Buffer) - *f_pos;

    }*/

    dat= GPFDAT;

    copy_to_user(buf,&dat,1);

    // *f_pos += read_size;

    return read_size;

    }

    static ssize_t myGPIO_write(struct file *filp,const char *buf, size_t count, loff_t *f_pos)

    {

    char dat;

    size_t fill_size = count;

    PRINTK("myDriver write called!\n");

    PRINTK("\tcount=%d, pos=%d\n", count, (int)*f_pos);

    if(*f_pos >= sizeof(myGPIO_Buffer))

    {

    PRINTK("[myDriver write]Buffer Overlap\n");

    *f_pos = sizeof(myGPIO_Buffer);

    return 0;

    }

    if((count + *f_pos) > sizeof(myGPIO_Buffer))

    {

    PRINTK("count + f_pos > sizeof buffer\n");

    fill_size = sizeof(myGPIO_Buffer) - *f_pos;

    }

    copy_from_user(&dat,buf,fill_size);

    GPFDAT = dat;

    // *f_pos += fill_size;

    return fill_size;

    }

    控制ioctl() 函數則是提供給應用層的接口函數,功能并不是固定的,由開發者定義,一般都是對硬件的一些除過上述功能的其他操作。

    static int myGPIO_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)

    {

    int i;

    unsigned int mask=0x01;

    GPFUP = 0x00;

    PRINTK("myGPIO ioctl called(%d)!\n", cmd);

        switch(cmd)

    {

    case MOD_IN:

    for(i=0;i<8;i++)

    {

    if((mask & arg)!=0x0)

    {

    GPFCON &=~(3<<i*2); 

    }

    mask =mask << 1;

    }

    break;

    case MOD_OUT:

     PRINTK("IOCTRL 0 called(0x%lx)!\n", arg);

     for(i=0;i<8;i++)

     {

     if((mask & arg)!=0x00)

     {

            GPFCON &= ~(3 <<( i*2));

    GPFCON |=(0x01<<(i*2));

     }

    mask=mask<<1;

     }

     break;

    case MOD_EXIT_INT:

    PRINTK("IOCTRL 1 called(0x%lx)!\n", arg);

    GPFDAT = 0xFFFFFF00;

    break;

    default:

    break;

    }

    return 0;

    }

    posted on 2009-06-11 21:30 MEYE 閱讀(2620) 評論(0)  編輯  收藏

    只有注冊用戶登錄后才能發表評論。


    網站導航:
    博客園   IT新聞   Chat2DB   C++博客   博問  
     
    主站蜘蛛池模板: 国产成人精品123区免费视频| 亚洲精品国产成人中文| 亚洲好看的理论片电影| 美女无遮挡免费视频网站| 啦啦啦完整版免费视频在线观看 | 亚洲成人黄色在线| 大地资源在线资源免费观看| 啊v在线免费观看| 看亚洲a级一级毛片| 色www永久免费视频| 亚洲中文字幕精品久久| 台湾一级毛片永久免费| 亚洲一区二区三区高清不卡| 91网站免费观看| 亚洲欧美国产欧美色欲| 免费黄色小视频网站| a级毛片免费观看视频| 亚洲国产日韩在线视频| 在线观看免费播放av片| 中文字幕无码精品亚洲资源网久久 | 国产免费人成视频在线播放播| 亚洲国产精品尤物YW在线观看| 亚洲狠狠婷婷综合久久蜜芽| 国产jizzjizz免费视频| 久久www免费人成看国产片| 亚洲一卡2卡4卡5卡6卡残暴在线| 全免费a级毛片免费看无码| 久久久久久成人毛片免费看| 亚洲另类激情综合偷自拍| 免费一区二区三区四区五区| 天天影院成人免费观看| 久久久久亚洲国产AV麻豆 | 亚洲国产成人精品91久久久| 亚洲成人免费网站| 精品一区二区三区免费视频| 亚洲AV无码专区在线观看成人| 78成人精品电影在线播放日韩精品电影一区亚洲 | 亚洲精品卡2卡3卡4卡5卡区| 又黄又爽一线毛片免费观看| 四虎永久在线精品免费观看视频| 久久99精品国产免费观看|