这是 一个S3C2410的GPIO的驱动是以字符方式写的格式是比较完整的可以做为字符型驱动的一个模版
内核的版本是2.6.13 被注掉的是2.6.8.1的
#include
#include
#include
#include
#include
/* printk() */
#include /* kmalloc() */
#include /* everything... */
#include /* error codes */
#include /* size_t */
#include
#include
#include
#include
#include
#include
#include
#include
#define GPF4_ON 0x4800 //ioctl的幻数
#define GPF4_OFF 0x4801
#define GPF5_ON 0x4802
#define GPF5_OFF 0x4803
#define GPF6_ON 0x4804
#define GPF6_OFF 0x4805
#define GPF7_ON 0x4806
#define GPF7_OFF 0x4807
#define BEEP_ON 0x4808
#define BEEP_OFF 0x4809
static int simple_major = 0;
module_param(simple_major, int, 0);
MODULE_AUTHOR("machuanlong");
MODULE_LICENSE("Dual BSD/GPL");
//char *mybuff;
#define BUFF_SIZE 100
char data[50]="foobar not equal to barfoo";
static DECLARE_WAIT_QUEUE_HEAD(wq);
static int flag = 0;
/*
* Open the device; in fact, there's nothing to do here.
*/
int simple_open (struct inode *inode, struct file *filp)
{
printk (KERN_INFO "Hey! device opened\n");
return 0;
}
ssize_t simple_read(struct file *file, char __user *buff, size_t count, loff_t *offp)
{
ssize_t result = 0;
if (copy_to_user (buff, data, sizeof(data)-1))
result = -EFAULT;
else
printk (KERN_INFO "wrote %d bytes\n", count);
return result;
}
ssize_t simple_write(struct file *file, const char __user *buff, size_t count, loff_t *offp)
{
return 0;
}
void beep_stop(void)
{
//GPBDAT=GPBDAT&(~(1<<0));
s3c2410_gpio_setpin(S3C2410_GPB0,0);
}
void beep_start(void)
{
//GPBDAT=GPBDAT|(1<<0);
s3c2410_gpio_setpin(S3C2410_GPB0,1);
}
void GPF4_START(void)
{
//GPFDAT=GPFDAT&(~(1<<4));
s3c2410_gpio_setpin(S3C2410_GPF4,0);
}
void GPF4_STOP(void)
{
//GPFDAT=GPFDAT|(1<<4);
s3c2410_gpio_setpin(S3C2410_GPF4,1);
}
void GPF5_START(void)
{
//GPFDAT=GPFDAT&(~(1<<5));
s3c2410_gpio_setpin(S3C2410_GPF5,0);
}
void GPF5_STOP(void)
{
//GPFDAT=GPFDAT|(1<<5);
s3c2410_gpio_setpin(S3C2410_GPF5,1);
}
void GPF6_START(void)
{
//GPFDAT=GPFDAT&(~(1<<6));
s3c2410_gpio_setpin(S3C2410_GPF6,0);
}
void GPF6_STOP(void)
{
// GPFDAT=GPFDAT|(1<<6);
s3c2410_gpio_setpin(S3C2410_GPF6,1);
}
void GPF7_START(void)
{
//GPFDAT=GPFDAT&(~(1<<7));
s3c2410_gpio_setpin(S3C2410_GPF7,0);
}
void GPF7_STOP(void)
{
// GPFDAT=GPFDAT|(1<<7);
s3c2410_gpio_setpin(S3C2410_GPF7,1);
}
static int simple_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
{
switch ( cmd ) {
case GPF4_ON:
{
GPF4_START();
break;
}
case GPF4_OFF:
{
GPF4_STOP();
break;
}
case GPF5_ON:
{
GPF5_START();
break;
}
case GPF5_OFF:
{
GPF5_STOP();
break;
}
case GPF6_ON:
{
GPF6_START();
break;
}
case GPF6_OFF:
{
GPF6_STOP();
break;
}
case GPF7_ON:
{
GPF7_START();
break;
}
case GPF7_OFF:
{
GPF7_STOP();
break;
}
case BEEP_ON:
{
beep_start();
break;
}
case BEEP_OFF:
{
beep_stop();
break;
}
default:
{
break;
}
}
return 0;
}
static int simple_release(struct inode *node, struct file *file)
{
printk (KERN_INFO "Hmmm... device closed\n");
return 0;
}
/*
* Set up the cdev structure for a device.
*/
static void simple_setup_cdev(struct cdev *dev, int minor,
struct file_operations *fops)
{
int err, devno = MKDEV(simple_major, minor);
cdev_init(dev, fops);
dev->owner = THIS_MODULE;
dev->ops = fops;
err = cdev_add (dev, devno, 1);
/* Fail gracefully if need be */
if (err)
printk (KERN_NOTICE "Error %d adding simple%d", err, minor);
}
/*
* Our various sub-devices.
*/
/* Device 0 uses remap_pfn_range */
static struct file_operations simple_remap_ops = {
.owner = THIS_MODULE,
.open = simple_open,
.release = simple_release,
.read = simple_read,
.write = simple_write,
.ioctl = simple_ioctl,
};
/*
* We export two simple devices. There's no need for us to maintain any
* special housekeeping info, so we just deal with raw cdevs.
*/
static struct cdev SimpleDevs;
/*
* Module housekeeping.
*/
static int simple_init(void)
{
int result;
dev_t dev = MKDEV(simple_major, 0); //获取主次设备号
/* Figure out our device number. */
if (simple_major)
result = register_chrdev_region(dev, 1, "simple"); //初始化字符设备资源
else {
result = alloc_chrdev_region(&dev, 0, 1, "simple"); //自动分配设备号
simple_major = MAJOR(dev);
}
if (result < 0) {
printk(KERN_WARNING "simple: unable to get major %d\n", simple_major);
return result;
}
if (simple_major == 0)
simple_major = result;
printk("<1>hello GPIO_TESTdrv!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n");
s3c2410_gpio_cfgpin(S3C2410_GPF4, S3C2410_GPF4_OUTP); //把GPF4初始化为输出口
s3c2410_gpio_setpin(S3C2410_GPF4,1); //GPF4输出1
s3c2410_gpio_cfgpin(S3C2410_GPF5, S3C2410_GPF5_OUTP);
s3c2410_gpio_setpin(S3C2410_GPF5,1);
s3c2410_gpio_cfgpin(S3C2410_GPF6, S3C2410_GPF6_OUTP);
s3c2410_gpio_setpin(S3C2410_GPF6,1);
s3c2410_gpio_cfgpin(S3C2410_GPF7, S3C2410_GPF7_OUTP);
s3c2410_gpio_setpin(S3C2410_GPF7,1);
s3c2410_gpio_cfgpin(S3C2410_GPB0, S3C2410_GPB0_OUTP);
s3c2410_gpio_setpin(S3C2410_GPB0,0);
/* Now set up two cdevs. */
simple_setup_cdev(&SimpleDevs, 0, &simple_remap_ops);
printk("simple device installed, with major %d\n", simple_major);
return 0;
}
static void simple_cleanup(void)
{
cdev_del(&SimpleDevs);
unregister_chrdev_region(MKDEV(simple_major, 0), 1);
printk("simple device uninstalled\n");
}
module_init(simple_init);
module_exit(simple_cleanup);
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
下边的是调试函数
#include
#include
#include
#include
#include
#include
#include
#define GPF4_ON 0x4800
#define GPF4_OFF 0x4801
#define GPF5_ON 0x4802
#define GPF5_OFF 0x4803
#define GPF6_ON 0x4804
#define GPF6_OFF 0x4805
#define GPF7_ON 0x4806
#define GPF7_OFF 0x4807
#define BEEP_ON 0x4808
#define BEEP_OFF 0x4809
int main()
{
int i = 0;
char buff[50];
int dev_fd;
dev_fd = open("/dev/simple",O_RDWR | O_NONBLOCK);
if ( dev_fd == -1 ) {
printf("Cann't open file /dev/simple\n");
exit(0);
}
printf ("\n/dev/simple opened, fd=%d\n",dev_fd);
memset (buff, '\0', 50);
printf ("Read returns %d\n", read (dev_fd, buff, sizeof(buff)));
buff[50]='0';
printf ("buff = %s\n", buff);
//close (dev_fd);
//printf ("/dev/hello closed :)\n");
while(1)
{
ioctl(dev_fd,GPF4_ON,0);
printf("GPF4_ON\n");
sleep(1);
ioctl(dev_fd,GPF5_ON,0);
printf("GPF5_ON\n");
sleep(1);
ioctl(dev_fd,GPF6_ON,0);
printf("GPF6_ON\n");
sleep(1);
ioctl(dev_fd,GPF7_ON,0);
printf("GPF7_ON\n");
sleep(1);
ioctl(dev_fd,BEEP_ON,0);
printf("BEEP_ON\n");
sleep(1);
ioctl(dev_fd,BEEP_OFF,0);
printf("BEEP_OFF\n");
sleep(1);
ioctl(dev_fd,GPF7_OFF,0);
printf("GPF7_OFF\n");
sleep(1);
ioctl(dev_fd,GPF6_OFF,0);
printf("GPF6_OFF\n");
sleep(1);
ioctl(dev_fd,GPF5_OFF,0);
printf("GPF5_OFF\n");
sleep(1);
ioctl(dev_fd,GPF4_OFF,0);
printf("GPF4_OFF\n");
sleep(1);
printf ("buff = %s\n", buff);
}
//getchar();
return 0;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Makefile:
ifeq ($(KERNELRELEASE),)
KERNELDIR ?= /disk3/linux-2.6.13-mcl+lcd+yaffs2+nand+cs8900
PWD := $(shell pwd)
modules:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
modules_install:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules_install
clean:
rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions
.PHONY: modules modules_install clean
else
obj-m := beep_drv.o
endif
///////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////
遇到Makefile文件报make: Nothing to be done for `modules'.的错误时是由于在modules下一行开头应该用TAB键而不是空格键
我们编译这个驱动是以模块的方式挂载的方法是:
insmod beep_drv.ko
下面会打印出主设备号如:253
mknod /dev/simple c 253 0
./main