Linux裝置驅動之《玩轉GPIO》

來源:互聯網
上載者:User

    在Linux裝置驅動之《點亮一盞LED》 中,編寫了ioctl_c.h這樣的標頭檔,在本文中將繼續使用這一標頭檔,代碼如下:

 

#ifndef __IOCTL_C_H__<br />#define __IOCTL_C_H__<br />typedef struct GPIO_Data_t<br />{<br />unsigned int port;<br />unsigned int bit;<br />unsigned int value;<br />unsigned int v;<br />}GPIO_Data_S;<br />#define GPIO_IOC_MAGIC 12 //Documentation/ioctl-number.txt<br />#define GPIO_IO_SET _IOW(GPIO_IOC_MAGIC,0,sizeof(GPIO_Data_S))<br />#define GPIO_IO_GET _IOWR(GPIO_IOC_MAGIC,1,sizeof(GPIO_Data_S))<br />#define GPIO_IO_WRITE _IOW(GPIO_IOC_MAGIC,2,sizeof(GPIO_Data_S))<br />#define GPIO_IO_READ _IOWR(GPIO_IOC_MAGIC,3,sizeof(GPIO_Data_S))<br />#endif

 

    然後則是驅動模組程式,代碼如下所示:

#include <linux/types.h><br />#include <linux/fs.h><br />#include <linux/mm.h><br />#include <linux/errno.h><br />#include <linux/module.h><br />#include <linux/moduleparam.h><br />#include <linux/kernel.h><br />#include <asm/uaccess.h><br />#include <linux/cdev.h><br />#include <linux/ioctl.h><br />#include <linux/slab.h><br />#include <linux/fcntl.h><br />#include <asm/segment.h><br />#include <asm/io.h><br />#include <asm/arch/regs-gpio.h><br />#include "ioctl_c.h"<br />unsigned int test_major=253;<br />unsigned int test_minor=0;<br />struct cdev cdevc;<br />MODULE_LICENSE("Dual BSD/GPL");<br />GPIO_Data_S ioctl;<br />static int read_test(struct file *file,char *buf,int count ,loff_t *f_pos)<br />{<br />printk("/n read_test");<br />printk("%d",count);<br />return count;<br />}<br />static int write_test(struct file *file,const char *buf,int count, loff_t *f_pos)<br />{<br />printk("/n write_test");<br />return count;<br />}<br />static void gpio_cfg()<br />{<br />size_t Data;<br />printk("gpio_cfg start!/n");<br />Data = __raw_readl(ioctl.port*0x10+S3C2410_GPACON);<br />Data &= ~(3<<2*ioctl.bit);<br />Data |= (ioctl.value<<2*ioctl.bit);<br />__raw_writel(Data,ioctl.port*0x10+S3C2410_GPACON);<br />}<br />static void gpio_read()<br />{<br />printk("gpio_read start!!/n");<br />size_t Data_con,Data_dat;<br />Data_con = __raw_readl(ioctl.port*0x10+S3C2410_GPACON);<br />Data_dat = __raw_readl(ioctl.port*0x10+S3C2410_GPADAT);<br />printk("%ld/n%ld/n",Data_con,Data_dat);<br />}<br />static void gpio_write()<br />{<br />printk("gpio-write start!!/n");<br />size_t Data;<br />Data = __raw_readl(ioctl.port*0x10+S3C2410_GPADAT);<br />Data &= ~(1<<ioctl.bit);<br />Data |=(ioctl.v<<ioctl.bit);<br />__raw_writel(Data,ioctl.port*0x10+S3C2410_GPADAT);<br />}<br />static int ioctl_test(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)<br />{<br />if(copy_from_user(&ioctl,arg,sizeof(GPIO_Data_S)))<br />{<br />return - EFAULT;<br />}<br />printk("/n ioctl_test");<br />switch(cmd)<br />{<br />case GPIO_IO_SET:gpio_cfg();break;<br />//case GPIO_IO_GET:;break;<br />case GPIO_IO_WRITE:gpio_write();break;<br />case GPIO_IO_READ:gpio_read();break;<br />default:break;<br />}<br />return cmd;<br />}<br />static int open_test(struct inode *inode,struct file *file)<br />{<br />printk("/n open_test");<br />return 0;<br />}<br />static void release_test(struct inode *inode,struct file *file)<br />{<br />printk("/n release_test");<br />}<br />struct file_operations test_fops = {<br />.owner=THIS_MODULE,<br />.read=read_test,<br />.write=write_test,<br />.open=open_test,<br />.ioctl=ioctl_test,<br />.release=release_test,<br />};<br />int simple_c_init_module(void)<br />{<br />int result;<br />dev_t dev = 0;</p><p>dev=MKDEV(test_major,test_minor);<br />result = register_chrdev_region(dev,1,"test");</p><p>printk("major= %d,minor=%d /n",test_major,test_minor);</p><p>if(result < 0)<br />{<br />printk(KERN_INFO "test : can't get major number/n");<br />return result;<br />}</p><p>cdev_init(&cdevc,&test_fops);<br />cdevc.owner= THIS_MODULE;<br />cdevc.ops=&test_fops;<br />result=cdev_add(&cdevc,dev,1);<br />if(result)<br />printk("Error %d adding test",result);<br />return 0;<br />}<br />void simple_c_cleanup_module(void)<br />{<br />dev_t dev=0;<br />dev = MKDEV(test_major,test_minor);<br />cdev_del(&cdevc);<br />unregister_chrdev_region(dev,1);<br />}<br />module_init(simple_c_init_module);<br />module_exit(simple_c_cleanup_module);

 

    這裡只說明與前面模組程式的區別,首先是ioctl_test函數

static int ioctl_test(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
{
    if(copy_from_user(&ioctl,arg,sizeof(GPIO_Data_S)))
    {
        return - EFAULT;
    }
    printk("/n ioctl_test");
    switch(cmd)
    {
        case GPIO_IO_SET:gpio_cfg();break;
//      case GPIO_IO_GET:;break;
        case GPIO_IO_WRITE:gpio_write();break;
        case GPIO_IO_READ:gpio_read();break;
        default:break;
    }
    return cmd;
}

這裡多出了       

case GPIO_IO_SET:gpio_cfg();break;

case GPIO_IO_WRITE:gpio_write();break;
case GPIO_IO_READ:gpio_read();break;

三個函數,從名稱上可以得知分別是對IO的配置和讀寫操作,具體是怎麼實現的呢,那麼馬上轉移到這三個函數去瞅瞅

 

static void gpio_cfg()
{
    size_t Data;
    printk("gpio_cfg start!/n");
    Data = __raw_readl(ioctl.port*0x10+S3C2410_GPACON);
    Data &= ~(3<<2*ioctl.bit);
    Data |= (ioctl.value<<2*ioctl.bit);
    __raw_writel(Data,ioctl.port*0x10+S3C2410_GPACON);
}
函數說明:這個函數是用來配置GPGCON的函數。

static void gpio_read()
{
    printk("gpio_read start!!/n");
    size_t Data_con,Data_dat;
    Data_con = __raw_readl(ioctl.port*0x10+S3C2410_GPACON);
    Data_dat = __raw_readl(ioctl.port*0x10+S3C2410_GPADAT);
    printk("%ld/n%ld/n",Data_con,Data_dat);
}
函數說明:讀取GPIO函數。

static void gpio_write()
{
    printk("gpio-write start!!/n");
    size_t Data;
    Data = __raw_readl(ioctl.port*0x10+S3C2410_GPADAT);
    Data &= ~(1<<ioctl.bit);
    Data |=    (ioctl.v<<ioctl.bit);
    __raw_writel(Data,ioctl.port*0x10+S3C2410_GPADAT);
}

函數說明:寫GPIO函數。 

 

下面是應用程式,這裡編寫應用程式就變得方便多了,需要什麼IO就先配置,再讀寫

#include <stdio.h><br />#include <sys/types.h><br />#include <sys/stat.h><br />#include <fcntl.h><br />#include <unistd.h><br />#include <linux/ioctl.h><br />#include "../ioctl_c.h"<br />GPIO_Data_S io_ctl;<br />void main(void)<br />{<br />int testdev;<br />int i;<br />char buf[10];<br />testdev = open ("/dev/test",O_RDWR);<br />if(testdev == -1)<br />{<br />printf("Cann't open file...../n");<br />exit(0);<br />}<br />printf("buf = 0x%x/n",buf);<br />read(testdev,buf,10);<br />write(testdev,buf,1);<br />while(1)<br />{<br />io_ctl.port=6;<br />io_ctl.bit=5;<br />io_ctl.value=1;<br />io_ctl.v=0;<br />ioctl(testdev,GPIO_IO_SET,&io_ctl);<br />ioctl(testdev,GPIO_IO_WRITE,&io_ctl);<br />ioctl(testdev,GPIO_IO_READ,&io_ctl);<br />io_ctl.port=6;<br /> io_ctl.bit=6;<br /> io_ctl.value=1;<br /> io_ctl.v=1;<br /> ioctl(testdev,GPIO_IO_SET,&io_ctl);<br /> ioctl(testdev,GPIO_IO_WRITE,&io_ctl);<br /> ioctl(testdev,GPIO_IO_READ,&io_ctl);<br />sleep(1);<br />io_ctl.port=6;<br />io_ctl.bit=6;<br />io_ctl.value=1;<br />io_ctl.v=0;<br />ioctl(testdev,GPIO_IO_SET,&io_ctl);<br />ioctl(testdev,GPIO_IO_WRITE,&io_ctl);<br />ioctl(testdev,GPIO_IO_READ,&io_ctl);<br />io_ctl.port=6;<br /> io_ctl.bit=5;<br /> io_ctl.value=1;<br /> io_ctl.v=1;<br /> ioctl(testdev,GPIO_IO_SET,&io_ctl);<br /> ioctl(testdev,GPIO_IO_WRITE,&io_ctl);<br /> ioctl(testdev,GPIO_IO_READ,&io_ctl);<br />sleep(1);<br />}<br />//ioctl(testdev,GPIO_IO_WRITE,sizeof(GPIO_Data_S));<br />//ioctl(testdev,GPIO_IO_READ,sizeof(GPIO_Data_S));<br />printf("%s",buf);<br />//for(i = 0;i<10;i++)<br />//printf("[%d]/n",buf[i]);<br />close(testdev);<br />}<br />/*<br />mknod /dev/test c 253 0<br />*/

 

 

 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.