📄 gpio_driv.c~
字号:
#include <linux/fs.h> //FILE: gpio_driv.c
#include <linux/iobuf.h>
#include <linux/major.h>
#include <linux/blkdev.h>
#include <linux/capability.h>
#include <linux/smp_lock.h>
#include <asm/uaccess.h>
#include <asm/hardware.h>
#include <asm/arch/cpu_s3c2440.h>
#include <asm/io.h>
#include <linux/vmalloc.h>
#define IOPORT_MAJOR 220 //定义主设备号,和前面的mknod/dev/gpiotestc 220 0匹配
typedef char ioport_device_t; long port_addr;
static ioport_device_t gpio_devices[257];
int gpio_open(struct inode*, structfile *);
int gpio_release(struct inode*, structfile *);
int gpio_ctl_ioctl(struct inode *, struct file *, unsigned int, unsigned long);
static structfile_operations gpio_ctl_fops = {
ioctl: gpio_ctl_ioctl,
open: gpio_open,
release: gpio_release,
};
//所有的操作系统将硬件设备当作文件处理,所有外设的操作就封装在这个file_operations 结构体里面
//就是文件的open/read/write/close等操作,剩余的都放到一个ioctl函数里面做处理。
int__init gpio_init(void)
{
inti;
//可以看到下面这句向操作系统注册的函数里面和前面我们在minicom里面手工创建的设备文件是
//要完全匹配的:mknod/dev/gpiotestc 220 0,这表明创建的是一个字符设备(chrdev),
//主设备号220,次设备号0,因为操作系统不理会“gpiotest”这个设备名字符串的,它只认数字的主次
//设备号,而应用程序到时是open(“/dev/gpiotest”,xx)的,中间就是通过这两个数字联系起来的。
register_chrdev(IOPORT_MAJOR, "gpiotest", &gpio_ctl_fops);
return 0;
}
module_init(gpio_init);
//用户加载该驱动时执行insmod gpio_driv.o就会自动调用gpio_init函数,它是驱动
//的入口点,相当于应用程序的main函数。
module_exit(gpio_release);
//用户卸载该驱动rmmod gpio_driv时执行
int gpio_open(struct inode*inode, structfile *filp)
{
intminor;
minor = MINOR(inode->i_rdev);
#if 0 //这里是通常的做法,因为S3C2410的LINUX内核提供了set_gpio_ctrl专用函数,所以不要下面这样做了,但2440有没有呢?
(void *)(port_addr) = ioremap(0x56000020,0x8);
*(volatile unsigned int*)(port_addr)|=0x00008000;
#endif
//驱动里面在open这个设备的时候设置这个口为输出(因为GPIO必须设置方向,做输入还是输出)
set_gpio_ctrl(GPIO_MODE_OUT | GPIO_C6);
gpio_devices[minor]++;
return 0;
}
int gpio_release(struct inode*inode, structfile *filp)
{ intminor;
minor = MINOR(inode->i_rdev);
if (gpio_devices[minor])
gpio_devices[minor]--;
return 0;
}
int gpio_ctl_ioctl(struct inode*inode,structfile *flip,unsigned intcommand,unsigned long arg)
{
int err = 0;
intminor = MINOR(inode->i_rdev);
switch (command) {
case IOWRITE:
write_gpio_bit(GPIO_MODE_OUT | GPIO_C6,1); //输出3.3V电平
return 0;
case IOCLEAR:
write_gpio_bit(GPIO_MODE_OUT | GPIO_C6,0); //输出0电平
return 0;
}
return err;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -