1. 程式人生 > >基於迅為4412的一個GPIO輸出高低電平的驅動

基於迅為4412的一個GPIO輸出高低電平的驅動

窗外的天空不再湛藍,我知道北京的冬天快要來了,自己也即將走上一段新的旅途。過去的時光如民大秋天的銀杏葉,靜靜的飄落,隨風而來,隨風而逝。
最近在實驗室除錯一個語音模組,就用GPIO做了一個數據接收的開關。參考網上的資料弄了一個輸出高低電平的驅動。
驅動程式:

/*包含初始化巨集定義的標頭檔案,程式碼中的module_init和module_exit在此檔案中*/
#include <linux/init.h>
/*包含初始化載入模組的標頭檔案,程式碼中的MODULE_LICENSE在此標頭檔案中*/
#include <linux/module.h>
/*三個字元裝置函式*/
#include <linux/fs.h>
/*定義字元裝置的結構體*/ #include <linux/cdev.h> /*分配記憶體空間函式標頭檔案*/ #include <linux/slab.h> /*定義module_param module_param_array中perm的標頭檔案*/ #include <linux/stat.h> /*MKDEV轉換裝置號資料型別的巨集定義*/ #include <linux/kdev_t.h> /*字元定義*/ #include <linux/string.h> /*linux系統提供的申請埠函式和設定埠狀態的函式*/ #include <linux/gpio.h>
/*設定GPIO狀態,上下拉,輸入輸出就,複用等等相關函式*/ #include <plat/gpio-cfg.h> /*包含GPIO埠的巨集定義*/ #include <mach/gpio-exynos4.h> #include <linux/mm.h> /*dev_t等的定義*/ #include <linux/types.h> /*包含copy_to_user和copy_from_user的標頭檔案*/ #include <asm/uaccess.h> /*包含暫存器操作函式的標頭檔案*/ #include <asm/io.h> /*延時定義*/
#include <linux/delay.h> /*包含函式device_create 結構體class等標頭檔案*/ #include <linux/device.h> /*錯誤診斷和輸出需要的標頭檔案*/ #include <linux/errno.h> #define PT (EXYNOS4_GPA0(7))/*4412開發板的gpio部分,gpio第13引腳,控制匯流排*/ #define PORT_MAJOR 245 #define PORT_MINOR 0 #define DEVICE_NAME "gpio_hl" #define IO_WRITE 0 #define IO_READ 1 static int pt_major = PORT_MAJOR; static int pt_minor = PORT_MINOR; /*字元裝置結構體*/ struct elec_cdev{ struct cdev cdev; }; struct elec_cdev *dev; static struct class *pt_class; static char gpio_devices[220]; static gpio_open(struct inode *inode,struct file *flip) { int minor,ret; ret = gpio_request(PT, "PT_CTRL"); if(ret<0){ printk("gpio_request is failed!\n"); return ret; } minor = MINOR(inode->i_rdev); s3c_gpio_cfgpin(PT,S3C_GPIO_OUTPUT); /*設定為輸出*/ gpio_set_value(PT,0); gpio_devices[minor]++; return 0; } static int gpio_release(struct inode *inode,struct file *flip) { int minor; minor = MINOR(inode->i_rdev); if(gpio_devices[minor]) gpio_devices[minor]--; /*釋放gpiio*/ gpio_free(PT); printk("gpio_release is success!\n"); return 0; } static long gpio_ioctl(struct inode *inode, struct file *flip,unsigned int cmd, unsigned long arg) { switch(cmd){ case IO_WRITE: gpio_set_value(PT,0); /*輸出低電平*/ break; case IO_READ: gpio_set_value(PT,1); /*輸出高電平*/ break; } return 0; } static struct file_operations gpio_fops = { .owner = THIS_MODULE, .open = gpio_open, .release = gpio_release, .unlocked_ioctl = gpio_ioctl, }; static int __init gpio_init (void) { int ret = 0; dev_t pt_dev; pt_dev = MKDEV(PORT_MAJOR,PORT_MINOR); ret = register_chrdev_region(pt_dev,1,DEVICE_NAME); dev = kmalloc(sizeof(struct elec_cdev),GFP_KERNEL); memset(dev,0,sizeof(struct elec_cdev)); pt_class = class_create(THIS_MODULE,DEVICE_NAME); cdev_init(&dev->cdev,&gpio_fops); /*字元設備註冊三部曲*/ dev->cdev.owner = THIS_MODULE; dev->cdev.ops = &gpio_fops; ret = cdev_add(&dev->cdev,MKDEV(pt_major,pt_minor),1); device_create(pt_class,NULL,MKDEV(pt_major,pt_minor),NULL,DEVICE_NAME); /*建立裝置節點*/ printk(KERN_EMERG "gpio init!\n"); return 0; } static void __exit gpio_exit(void) { /*摧毀裝置節點*/ device_destroy(pt_class,MKDEV(pt_major,pt_minor)); /*登出裝置*/ cdev_del(&dev->cdev); /*釋放匯流排*/ class_destroy(pt_class); /*釋放記憶體*/ kfree(dev); /*登出裝置號*/ unregister_chrdev_region(MKDEV(pt_major,pt_minor),1); printk(KERN_EMERG "gpio exit!\n"); } module_init(gpio_init); module_exit(gpio_exit); MODULE_AUTHOR("star sky");/*作者*/ MODULE_DESCRIPTION("ITOP4412 Gpio driver:high or low level");/*模組功能描述*/ MODULE_LICENSE("Dual BSD/GPL");/*開源宣告*/ MODULE_VERSION("V1.0");/*程式碼修訂版本*/

測試程式碼:

#include <stdio.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

#define PATH "/dev/gpio_hl"
#define IO_WRITE  0
#define IO_READ   1

int main()
{
    int fd;
    int val = -1;

    if((fd = open(PATH,O_RDWR|O_NOCTTY|O_NDELAY|O_NONBLOCK))<0){
        perror("open gpio is failea!\n");
        exit(1);
    }
    else{
        printf("open gpio is success!\n");
        while(1){
            printf("0:low,1:high,2:quit:");
            scanf("%d",&val);
            if(val == 0)
                ioctl(fd,IO_READ,0);
            else if(val == 1)
                ioctl(fd,IO_WRITE,1);
            else if(val == 2){
                close(fd);
                exit(1);
            }
        }
    }
}