基於迅為4412的一個GPIO輸出高低電平的驅動
阿新 • • 發佈:2019-01-01
窗外的天空不再湛藍,我知道北京的冬天快要來了,自己也即將走上一段新的旅途。過去的時光如民大秋天的銀杏葉,靜靜的飄落,隨風而來,隨風而逝。
最近在實驗室除錯一個語音模組,就用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);
}
}
}
}