第一种用脚本文件:
Firstchardevice.c
#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
MODULE_LICENSE("GPL");
static int myfirst_open(struct inode *inode,struct file *file)
{
printk("first_char_deviceopen test!\n");
return0;
}
static ssize_t myfirst_write(struct file*file, const char __user *buf,
size_t count, loff_t *ppos)
{
printk("first_char_devicewrite test!\n");
return0;
}
static const struct file_operationsmyfirst_fops = {
.owner = THIS_MODULE,
.open = myfirst_open,
.write = myfirst_write,
};
static int __init myfirst_init(void)
{
printk("welcometo init function!\n");
register_chrdev(111,"first_drv",&myfirst_fops);
printk("major:%d\n",major);
return0;
}
static void __exit myfirst_exit(void)
{
unregister_chrdev(111,"first_drv");
}
module_init(myfirst_init);
module_exit(myfirst_exit);
test….c
#include <stdio.h>
#include <fcntl.h>
int main(int argc,char** argv)
{
intfd;
intval=1;
fd=open("/dev/my_led",O_RDWR);
if(fd<0)
printf("can'topen!\n");
write(fd,&val,4);
return0;
}
Insertmodule.sh
#!/bin/bash
module="firstchardevice"
device="my_led"
/sbin/insmod ./$module.ko
major=$(awk"\$2==\"first_drv\" {print \$1}" /proc/devices)
echo $major
rm -f /dev/$device
/bin/mknod /dev/${device} c $major 0
Rmmodule.sh
#!/bin/bash
module="firstchardevice"
device="my_led"
/sbin/rmmod ./$module
/etc/rm -f $device
Makefile
KERNALDIR=/root/opt/EmbedSky/linux-2.6.30.4/
MODULENAME=firstchardevice
obj-m :=$(MODULENAME).o
all:
make-C $(KERNALDIR) M=`pwd` modules
arm-linux-gcc-o test$(MODULENAME) test$(MODULENAME).c
clean:
make-C $(KERNALDIR) M=`pwd` clean
自动mkmod
#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/device.h>
#include <linux/kernel.h>
MODULE_LICENSE("GPL");
int major;
static struct class *firstdrv_class;
static struct device *firstdrv_dev;
static int myfirst_open(struct inode *inode,struct file *file)
{
printk("first_char_deviceopen test!\n");
return0;
}
static ssize_t myfirst_write(struct file*file, const char __user *buf,
size_t count, loff_t *ppos)
{
printk("first_char_devicewrite test!\n");
return0;
}
static const struct file_operationsmyfirst_fops = {
.owner = THIS_MODULE,
.open = myfirst_open,
.write = myfirst_write,
};
static int __init myfirst_init(void)
{
printk("welcometo init function!\n");
major=register_chrdev(0,"first_drv",&myfirst_fops);
printk("major:%d\n",major);
firstdrv_class=class_create(THIS_MODULE,"myclass");
firstdrv_dev=device_create(firstdrv_class,NULL,MKDEV(major,0),NULL,"my_led");
return0;
}
static void __exit myfirst_exit(void)
{
unregister_chrdev(major,"first_drv");
device_destroy(firstdrv_class,MKDEV(major,0));
class_destroy(firstdrv_class);
}
module_init(myfirst_init);
module_exit(myfirst_exit);
#include <stdio.h>
#include <fcntl.h>
int main(int argc,char** argv)
{
intfd;
intval=1;
fd=open("/dev/my_led",O_RDWR);
if(fd<0)
printf("can'topen!\n");
write(fd,&val,4);
return0;
}
KERNALDIR=/root/opt/EmbedSky/linux-2.6.30.4/
MODULENAME=firstchardevice
obj-m :=$(MODULENAME).o
all:
make-C $(KERNALDIR) M=`pwd` modules
arm-linux-gcc-o test$(MODULENAME) test$(MODULENAME).c
clean:
make-C $(KERNALDIR) M=`pwd` clean
自动设备号
#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
MODULE_LICENSE("GPL");
int major;
static int myfirst_open(struct inode *inode,struct file *file)
{
printk("first_char_deviceopen test!\n");
return0;
}
static ssize_t myfirst_write(struct file*file, const char __user *buf,
size_t count, loff_t *ppos)
{
printk("first_char_devicewrite test!\n");
return0;
}
static const struct file_operationsmyfirst_fops = {
.owner = THIS_MODULE,
.open = myfirst_open,
.write = myfirst_write,
};
static int __init myfirst_init(void)
{
printk("welcometo init function!\n");
major=register_chrdev(0,"first_drv",&myfirst_fops);
printk("major:%d\n",major);
return0;
}
static void __exit myfirst_exit(void)
{
unregister_chrdev(major,"first_drv");
}
module_init(myfirst_init);
module_exit(myfirst_exit);
#include <stdio.h>
#include <fcntl.h>
int main(int argc,char** argv)
{
intfd;
intval=1;
fd=open("/dev/my_led",O_RDWR);
if(fd<0)
printf("can'topen!\n");
write(fd,&val,4);
return0;
}
KERNALDIR=/root/opt/EmbedSky/linux-2.6.30.4/
MODULENAME=firstchardevice
obj-m :=$(MODULENAME).o
all:
make-C $(KERNALDIR) M=`pwd` modules
arm-linux-gcc-o test$(MODULENAME) test$(MODULENAME).c
clean:
make-C $(KERNALDIR) M=`pwd` clean
杂项驱动默认主设备号为10
#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/miscdevice.h>
#include <linux/kernel.h>
MODULE_LICENSE("GPL")
static int myfirst_open(struct inode *inode,struct file *file)
{
printk("first_char_deviceopen test!\n");
return0;
}
static ssize_t myfirst_write(struct file*file, const char __user *buf,
size_t count, loff_t *ppos)
{
printk("first_char_devicewrite test!\n");
return0;
}
static const struct file_operationsmyfirst_fops = {
.owner = THIS_MODULE,
.open = myfirst_open,
.write = myfirst_write,
};
static struct miscdevice led_drv_misc={
.minor=255,
.name="my_led",
.fops=&myfirst_fops,
};
static int __init myfirst_init(void)
{
printk("welcometo init function!\n");
misc_register(&led_drv_misc);
return0;
}
static void __exit myfirst_exit(void)
{
misc_deregister(&led_drv_misc);
}
module_init(myfirst_init);
module_exit(myfirst_exit);
#include <stdio.h>
#include <fcntl.h>
int main(int argc,char** argv)
{
intfd;
intval=1;
fd=open("/dev/my_led",O_RDWR);
if(fd<0)
printf("can'topen!\n");
write(fd,&val,4);
return0;
}
KERNALDIR=/root/opt/EmbedSky/linux-2.6.30.4/
MODULENAME=firstchardevice
obj-m :=$(MODULENAME).o
all:
make-C $(KERNALDIR) M=`pwd` modules
arm-linux-gcc-o test$(MODULENAME) test$(MODULENAME).c
clean:
make-C $(KERNALDIR) M=`pwd` clean
cdev标准字符设备需要手动mknod
#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/cdev.h>
MODULE_LICENSE("GPL");
#define DEVICE_NAME "first_drv"
int major;
dev_t dev_nr=0; //定义一个变量存放设备号
struct cdev my_cdev;
static int myfirst_open(struct inode *inode,struct file *file)
{
printk("first_char_deviceopen test!\n");
return0;
}
static ssize_t myfirst_write(struct file*file, const char __user *buf,
size_t count, loff_t *ppos)
{
printk("first_char_devicewrite test!\n");
return0;
}
static const struct file_operationsmyfirst_fops = {
.owner = THIS_MODULE,
.open = myfirst_open,
.write = myfirst_write,
};
static int __init myfirst_init(void)
{
intret;
printk("welcometo init function!\n");
if(major>0)
{
ret=register_chrdev_region(MKDEV(major,0),1,DEVICE_NAME);
if(ret<0)
{
printk("err!\n");
returnret;
}
}
else
{
ret=alloc_chrdev_region(&dev_nr,0,1,DEVICE_NAME);
if(ret<0)
{
printk("err!\n");
returnret;
}
major=MAJOR(dev_nr);
printk("major:%d\n",major);
}
cdev_init(&my_cdev,&myfirst_fops);
my_cdev.owner=THIS_MODULE;
ret=cdev_add(&my_cdev,dev_nr,1);
if(ret<0)
{
printk("registererr!\n");
unregister_chrdev_region(dev_nr,1);
}
returnret;
}
static void __exit myfirst_exit(void)
{
cdev_del(&my_cdev);
unregister_chrdev_region(dev_nr,1);
printk("bye!\n");
}
module_init(myfirst_init);
module_exit(myfirst_exit);
#include <stdio.h>
#include <fcntl.h>
int main(int argc,char** argv)
{
intfd;
intval=1;
fd=open("/dev/my_led",O_RDWR);
if(fd<0)
printf("can'topen!\n");
write(fd,&val,4);
return0;
}
Led灯驱动
#include <linux/init.h>
#include <asm/io.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/device.h>
#include <asm/uaccess.h>
MODULE_LICENSE("GPL");
int major;
static struct class *firstdrv_class;
static struct device*firstdrv_device;
volatile unsigned long *gpbcon;
volatile unsigned long *gpbdat;
static int myfirst_open(struct inode *inode,struct file *file)
{
printk("first_char_deviceopen test!\n");
*gpbcon&=~((0x3<<(2*5))|(0x3<<(2*6))|(0x3<<(2*7))|(0x3<<(2*8)));
*gpbcon|=((0x1<<(2*5))|(0x1<<(2*6))|(0x1<<(2*7))|(0x1<<(2*8)));
*gpbdat&=~((1<<5)|(1<<6)|(1<<7)|(1<<8));
return0;
}
static ssize_t myfirst_write(struct file*file, const char __user *buf,
size_t count, loff_t *ppos)
{
intval;
printk("first_char_devicewrite test!\n");
copy_from_user(&val,buf,count);
if(val==1)
{
*gpbdat&=~((1<<5)|(1<<6)|(1<<7)|(1<<8));
}
else
{
*gpbdat
=((1<<5)|(1<<6)|(1<<7)|(1<<8));
}
return0;
}
static const struct file_operationsmyfirst_fops = {
.owner = THIS_MODULE,
.open = myfirst_open,
.write = myfirst_write,
};
static int __init myfirst_init(void)
{
printk("welcometo init function!\n");
gpbcon=(unsignedlong*)ioremap(0x56000010,16);
gpbdat=gpbcon+1;
major=register_chrdev(0,"first_drv",&myfirst_fops);
printk("major:%d\n",major);
firstdrv_class=class_create(THIS_MODULE,"myclass");
firstdrv_device=device_create(firstdrv_class,NULL,MKDEV(major,0),NULL,"my_led");
return0;
}
static void __exit myfirst_exit(void)
{
iounmap(gpbcon);
unregister_chrdev(major,"first_drv");
device_destroy(firstdrv_class,MKDEV(major,0));
class_destroy(firstdrv_class);
}
module_init(myfirst_init);
module_exit(myfirst_exit);
#include <stdio.h>
#include <fcntl.h>
#include <sys/types.h>
#include <unistd.h>
int main(int argc,char** argv)
{
intfd;
intval;
fd=open("/dev/my_led",O_RDWR);
if(fd<0)
printf("can'topen!\n");
if(argc!=2)
{
printf("usage:\n");
printf("%s<on|off>\n",argv[0]);
}
if(strcmp("on",argv[1])==0)
val=1;
else
val=0;
write(fd,&val,4);
return0;
}
insmod 后
执行 /etc/rc.d/init.d/leds stop
接着执行 test。。。。
就是测试那句
启动
/etc/rc.d/init.d/leds start
利用系统现成的函数做led驱动
#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/device.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#include <mach/regs-gpio.h>
#include <mach/hardware.h>
MODULE_LICENSE("GPL");
int major;
static struct class *firstdrv_class;
static struct device*firstdrv_device;
static unsigned long led_table[]=
{
S3C2410_GPB5,
S3C2410_GPB6,
S3C2410_GPB7,
S3C2410_GPB8,
};
static unsigned int gpio_cfg_table[]=
{
S3C2410_GPB5_OUTP,
S3C2410_GPB6_OUTP,
S3C2410_GPB7_OUTP,
S3C2410_GPB8_OUTP,
};
static int myfirst_open(struct inode *inode,struct file *file)
{
printk("first_char_deviceopen test!\n");
return0;
}
static ssize_t myfirst_write(struct file*file, const char __user *buf,
size_t count, loff_t *ppos)
{
intval;
inti;
printk("first_char_devicewrite test!\n");
copy_from_user(&val,buf,count);
if(val==1)
{
for(i=0;i<4;i++)
s3c2410_gpio_setpin(led_table[i],0);
}
else
{
for(i=0;i<4;i++)
s3c2410_gpio_setpin(led_table[i],1);
}
return0;
}
static const struct file_operationsmyfirst_fops = {
.owner = THIS_MODULE,
.open = myfirst_open,
.write = myfirst_write,
};
static int __init myfirst_init(void)
{
inti;
printk("welcometo init function!\n");
for(i=0;i<4;i++)
{
s3c2410_gpio_cfgpin(led_table[i],gpio_cfg_table[i]);
s3c2410_gpio_setpin(led_table[i],1);
}
major=register_chrdev(0,"first_drv",&myfirst_fops);
printk("major:%d\n",major);
firstdrv_class=class_create(THIS_MODULE,"myclass");
firstdrv_device=device_create(firstdrv_class,NULL,MKDEV(major,0),NULL,"my_led");
return0;
}
static void __exit myfirst_exit(void)
{
unregister_chrdev(major,"first_drv");
device_destroy(firstdrv_class,MKDEV(major,0));
class_destroy(firstdrv_class);
}
module_init(myfirst_init);
module_exit(myfirst_exit);
#include <stdio.h>
#include <fcntl.h>
#include <sys/types.h>
#include <unistd.h>
int main(int argc,char** argv)
{
intfd;
intval;
fd=open("/dev/my_led",O_RDWR);
if(fd<0)
printf("can'topen!\n");
if(argc!=2)
{
printf("usage:\n");
printf("%s<on|off>\n",argv[0]);
}
if(strcmp("on",argv[1])==0)
val=1;
else
val=0;
write(fd,&val,4);
return0;
}
insmod 后
执行 /etc/rc.d/init.d/leds stop
接着执行 test。。。。
就是测试那句
启动
/etc/rc.d/init.d/leds start
Ioctl自编的
#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/device.h>
#include <asm/uaccess.h>
#include <mach/regs-gpio.h>
#include <mach/hardware.h>
MODULE_LICENSE("GPL");
int major;
static struct class *firstdrv_class;
static struct device*firstdrv_device;
static unsigned long gpio_table [] =
{
S3C2410_GPB5,
S3C2410_GPB6,
S3C2410_GPB7,
S3C2410_GPB8,
};
static unsigned int gpio_cfg_table [] =
{
S3C2410_GPB5_OUTP,
S3C2410_GPB6_OUTP,
S3C2410_GPB7_OUTP,
S3C2410_GPB8_OUTP,
};
static int myfirst_open(struct inode *inode,struct file *file)
{
inti;
printk("first_char_deviceopen test!\n");
for(i = 0; i < 4; i++)
{
s3c2410_gpio_cfgpin(gpio_table[i],gpio_cfg_table[i]);
s3c2410_gpio_setpin(gpio_table[i],0);
}
return0;
}
static ssize_t myfirst_write(struct file*file, const char __user *buf,
size_t count, loff_t *ppos)
{
intval;
inti;
printk("first_char_devicewrite test!\n");
return0;
}
static int myfirst_ioctl(struct inode*inode, struct file *file, unsigned int cmd, unsigned long arg)
{
inti;
if(arg>4)
{
printk("error!\n");
return-EINVAL;
}
if(cmd==0)
{
if(arg==4)
{
for(i=0;i<4;i++)
s3c2410_gpio_setpin(gpio_table[i],1);
}
else
s3c2410_gpio_setpin(gpio_table[arg],1);
}
else
{
if(arg==4)
{
for(i=0;i<4;i++)
s3c2410_gpio_setpin(gpio_table[i],0);
}
else
s3c2410_gpio_setpin(gpio_table[arg],0);
}
}
static int myfirst_close(struct inode*inode, struct file *file)
{
printk("bye!\n");
return0;
}
static const struct file_operationsmyfirst_fops = {
.owner = THIS_MODULE,
.open = myfirst_open,
.write = myfirst_write,
.ioctl =myfirst_ioctl,
.release =myfirst_close,
};
static int __init myfirst_init(void)
{
printk("welcometo init function!\n");
major=register_chrdev(0,"first_drv",&myfirst_fops);
printk("major:%d\n",major);
firstdrv_class=class_create(THIS_MODULE,"myclass");
firstdrv_device=device_create(firstdrv_class,NULL,MKDEV(major,0),NULL,"my_led");
return0;
}
static void __exit myfirst_exit(void)
{
unregister_chrdev(major,"first_drv");
device_destroy(firstdrv_class,MKDEV(major,0));
class_destroy(firstdrv_class);
}
module_init(myfirst_init);
module_exit(myfirst_exit);
#include <stdio.h>
#include <fcntl.h>
int main(int argc,char** argv)
{
intfd;
intval=1;
intled_nu;
inton;
fd=open("/dev/my_led",O_RDWR);
if(fd<0)
printf("can'topen!\n");
if((argc!=3)||sscanf(argv[1],"%d",&led_nu)!=1||sscanf(argv[2],"%d",&on)!=1||on<0||on>1||led_nu>4)
{
printf("usage:\n");
printf("%sled_nu 0|1>\n",argv[0]);
return0;
}
ioctl(fd,on,led_nu);
return0;
}
KERNALDIR=/root/opt/EmbedSky/linux-2.6.30.4/
MODULENAME=firstchardevice
obj-m :=$(MODULENAME).o
all:
make-C $(KERNALDIR) M=`pwd` modules
arm-linux-gcc-o test$(MODULENAME) test$(MODULENAME).c
clean:
make-C $(KERNALDIR) M=`pwd` clean
跑马灯自编
My_misc_led.c
#include <linux/miscdevice.h>
#include <linux/delay.h>
#include <asm/irq.h>
#include <mach/regs-gpio.h>
#include <mach/hardware.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/mm.h>
#include <linux/fs.h>
#include <linux/types.h>
#include <linux/delay.h>
#include <linux/moduleparam.h>
#include <linux/slab.h>
#include <linux/errno.h>
#include <linux/ioctl.h>
#include <linux/cdev.h>
#include <linux/string.h>
#include <linux/list.h>
#include <linux/pci.h>
#include <asm/uaccess.h>
#include <asm/atomic.h>
#include <asm/unistd.h>
#include "mycmdioctl.h"
#define DEVICE_NAME "myled"
/*用来实现宏名打印*/
#define MACRO_(x) #x
/* 鐢ㄦ潵鎸囧畾LED鎵€鐢ㄧ殑GPIO寮曡剼 */
static unsigned long gpio_table [] =
{
S3C2410_GPB5,
S3C2410_GPB6,
S3C2410_GPB7,
S3C2410_GPB8,
};
/* 鐢ㄦ潵鎸囧畾GPIO寮曡剼鐨勫姛鑳斤細杈撳嚭 */
static unsigned int gpio_cfg_table [] =
{
S3C2410_GPB5_OUTP,
S3C2410_GPB6_OUTP,
S3C2410_GPB7_OUTP,
S3C2410_GPB8_OUTP,
};
static int my_tq2440_gpio_ioctl(
structinode *inode,
structfile *file,
unsignedint cmd,
unsignedlong arg)
{
interr = 0;
intret = 0;
inttemp = 0;
intvalue =0;
inti;
printk(KERN_EMERG"\r\n/*--------------------------------------------------------------*/\r\n");
/*提取命令cmd的type位域和number位域
* 不解码错误命令
*/
if(_IOC_TYPE(cmd) != MYCMD_IOC_MAGIC)
return-ENOTTY;
if(_IOC_NR(cmd) > MYCMD_IOC_MAXNR)
return-ENOTTY;
/*cmd的"Type"域 是针对用户空间而言的
* access_ok是面向内核的
* 因此,"读取"和"写入"的概念是相反的
*/
/*_IOC_DIR(cmd) & _IOC_READ分析:
* 判断CMD的dir字段是否是read
* 之所以可以这样判断,是因为_IOC_READ、_IOC_WRITE、_IOC_NONE
* 各对应位是互斥的,任何两两交叉AND操作均会得到0
*/
if(_IOC_DIR(cmd) & _IOC_READ)
/*access_ok返回布尔值:
* 1:访问成功
* 0:访问失败
*/
err= !access_ok(VERIFY_WRITE, (void __user *)arg, _IOC_SIZE(cmd));
elseif (_IOC_DIR(cmd) & _IOC_WRITE)
err= !access_ok(VERIFY_READ, (void __user*)arg, _IOC_SIZE(cmd));
if(err)
return-EFAULT;
switch(cmd)
{
caseMYCMD_IOC_LEDS_NUM_ON:
/*打印宏名和内容*/
printk("%s:\r\n\r\n",MACRO_(MYCMD_IOC_LEDS_NUM_ON));
get_user(value,(int *)arg);
s3c2410_gpio_setpin(gpio_table[value],0);
return 0;
break;
caseMYCMD_IOC_LEDS_NUM_OFF:
/*打印宏名和内容*/
printk("%s:\r\n\r\n",MACRO_(MYCMD_IOC_LEDS_NUM_OFF));
get_user(value,(int *)arg);
s3c2410_gpio_setpin(gpio_table[value],1);
return 0;
break;
caseMYCMD_IOC_LEDS_ALL_ON_SET:
/*打印宏名和内容*/
printk("%s:\r\n\r\n",MACRO_(MYCMD_IOC_LEDS_All_ON_SET));
for(i = 0; i < 4; i++)
{
s3c2410_gpio_setpin(gpio_table[i],0);
}
return0;
break;
caseMYCMD_IOC_LEDS_ALL_OFF_SET:
/*打印宏名和内容*/
printk("%s:\r\n\r\n",MACRO_(MYCMD_IOC_LEDS_ALL_OFF_SET));
for(i = 0; i < 4; i++)
{
s3c2410_gpio_setpin(gpio_table[i],1);
}
return0;
break;
default:
printk("ivcmd:%d \r\n",cmd);
return-ENOTTY;;
}
return0; /* 返回值根据命令的不同,意义不同
* 一般情况
* 成功执行,返回0
* 失败,返回负错误码
*/
}
static struct file_operations my_dev_fops ={
.owner = THIS_MODULE,
.ioctl = my_tq2440_gpio_ioctl,
};
static struct miscdevice misc = {
.minor= MISC_DYNAMIC_MINOR,
.name= DEVICE_NAME,
.fops= &my_dev_fops,
};
static int __init dev_init(void)
{
intret;
inti;
for(i = 0; i < 4; i++)
{
s3c2410_gpio_cfgpin(gpio_table[i],gpio_cfg_table[i]);
s3c2410_gpio_setpin(gpio_table[i],0);
}
ret= misc_register(&misc);
printk(DEVICE_NAME" initialized\n");
returnret;
}
static void __exit dev_exit(void)
{
misc_deregister(&misc);
}
module_init(dev_init);
module_exit(dev_exit);
mycmdioctl.h
#ifndef __MY_CMD_IOCTL_H__
#define __MY_CMD_IOCTL_H__
#include <linux/ioctl.h>
/* Use 't' as magic number */
#define MYCMD_IOC_MAGIC 't'
#define MYCMD_IOC_LEDS_NUM_ON _IOW(MYCMD_IOC_MAGIC, 0,int) //点亮当前led
#define MYCMD_IOC_LEDS_NUM_OFF _IOW(MYCMD_IOC_MAGIC, 1,int) //熄灭当前led
#define MYCMD_IOC_LEDS_ALL_ON_SET _IO(MYCMD_IOC_MAGIC,2) //全部开led
#define MYCMD_IOC_LEDS_ALL_OFF_SET _IO(MYCMD_IOC_MAGIC,3) //全部关led
#define MYCMD_IOC_MAXNR 3
#endif
Test-----
#include <stdio.h>
#include <fcntl.h>
#include "mycmdioctl.h"
unsigned long cmd_buf[]={
MYCMD_IOC_LEDS_NUM_ON,MYCMD_IOC_LEDS_NUM_OFF,
MYCMD_IOC_LEDS_ALL_ON_SET,MYCMD_IOC_LEDS_ALL_OFF_SET,
};
int main(int argc,char** argv)
{
intfd;
intcmd_arg;
fd=open("/dev/myled",O_RDWR);
if(fd<0)
printf("can'topen!\n");
while (1)
{
for(cmd_arg=0;cmd_arg<4;cmd_arg++)
{
ioctl(fd,MYCMD_IOC_LEDS_NUM_ON,&cmd_arg);
sleep(1);
ioctl(fd,MYCMD_IOC_LEDS_NUM_OFF,&cmd_arg);
}
sleep(1);
ioctl(fd,MYCMD_IOC_LEDS_ALL_ON_SET);
sleep(1);
ioctl(fd,MYCMD_IOC_LEDS_ALL_OFF_SET);
sleep(1);
}
return0;
}
MODNAME=my_misc_led
KERNALDIR=/root/opt/EmbedSky/linux-2.6.30.4
obj-m=$(MODNAME).o
all:
make-C $(KERNALDIR) SUBDIRS=`pwd` modules
arm-linux-gcctest$(MODNAME).c -o test$(MODNAME)
clean:
make-C $(KERNALDIR) SUBDIRS=`pwd` clean
myclean:
@rm-rf *.o *.ko *.mod.c modules.* Module.*
杂项设备
#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/miscdevice.h>
MODULE_LICENSE("GPL");
static int canopen=1;
static int myfirst_open(struct inode *inode,struct file *file)
{
if(--canopen!=0)
{
printk("filewas already opend,only once!\n");
canopen++;
return-EBUSY;
}
printk("first_char_deviceopen test!\n");
return0;
}
static ssize_t myfirst_write(struct file*file, const char __user *buf,
size_t count, loff_t *ppos)
{
printk("first_char_devicewrite test!\n");
return0;
}
static int myfirst_close(struct inode*inode, struct file *file)
{
printk("first_char_deviceclose test!\n");
canopen++;
return0;
}
static const struct file_operationsmyfirst_fops = {
.owner = THIS_MODULE,
.open = myfirst_open,
.write = myfirst_write,
.release =myfirst_close,
};
static struct miscdevice my_misc_test={
.minor=MISC_DYNAMIC_MINOR,
.name="my_led",
.fops=&myfirst_fops,
};
static int __init myfirst_init(void)
{
intret;
printk("welcometo init function!\n");
ret=misc_register(&my_misc_test);
if(ret<0)
printk("registermiscdevice failed!\n");
returnret;
}
static void __exit myfirst_exit(void)
{
printk("bye!\n");
misc_deregister(&my_misc_test);
}
module_init(myfirst_init);
module_exit(myfirst_exit);
#include <stdio.h>
#include <fcntl.h>
int main(int argc,char** argv)
{
intfd;
intval=1;
fd=open("/dev/my_led",O_RDWR);
if(fd<0)
printf("can'topen!\n");
write(fd,&val,4);
sleep(15);
close(fd);
return0;
}
KERNALDIR=/root/opt/EmbedSky/linux-2.6.30.4/
MODULENAME=firstchardevice
obj-m :=$(MODULENAME).o
all:
make-C $(KERNALDIR) M=`pwd` modules
arm-linux-gcc-o test$(MODULENAME) test$(MODULENAME).c
clean:
make-C $(KERNALDIR) M=`pwd` clean
等待队列
#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/device.h>
#include <linux/wait.h>
#include <linux/sched.h>
#include <linux/uaccess.h>
MODULE_LICENSE("GPL");
int major;
static struct class *firstdrv_class;
static struct device*firstdrv_device;
static DECLARE_WAIT_QUEUE_HEAD(key_queue);
static int vpress=0;
static int testval=55;
static int myfirst_open(struct inode *inode,struct file *file)
{
printk("first_char_deviceopen test!\n");
return0;
}
static ssize_t myfirst_read(struct file*file, char __user *buf, size_t size, loff_t *ppos)
{
printk("first_char_deviceread test!\n");
//直接进入休眠,挂在等待队列中
wait_event_interruptible(key_queue,vpress);
printk("%d\n",testval);
copy_to_user(buf,&testval,4);
vpress=0;
printk("waitqueue:finishedto read data from device!\n");
return0;
}
static ssize_t myfirst_write(struct file*file, const char __user *buf,
size_t count, loff_t *ppos)
{
printk("first_char_devicewrite test!\n");
copy_from_user(&vpress,buf,count);
wake_up_interruptible(&key_queue);
printk("waitqueue:finishedto write data to device!\n");
return0;
}
static int myfirst_close(struct inode*inode, struct file *file)
{
printk("first_char_deviceclose !\n");
return0;
}
static const struct file_operationsmyfirst_fops = {
.owner = THIS_MODULE,
.open = myfirst_open,
.read =myfirst_read,
.write = myfirst_write,
.release =myfirst_close,
};
static int __init myfirst_init(void)
{
printk("welcometo init function!\n");
init_waitqueue_head(&key_queue);
major=register_chrdev(0,"first_drv",&myfirst_fops);
printk("major:%d\n",major);
firstdrv_class=class_create(THIS_MODULE,"myclass");
firstdrv_device=device_create(firstdrv_class,NULL,MKDEV(major,0),NULL,"my_led");
return0;
}
static void __exit myfirst_exit(void)
{
unregister_chrdev(major,"first_drv");
device_destroy(firstdrv_class,MKDEV(major,0));
class_destroy(firstdrv_class);
}
module_init(myfirst_init);
module_exit(myfirst_exit);
#include <stdio.h>
#include <fcntl.h>
int main(int argc,char** argv)
{
intfd;
intval=1;
inttest;
charch;
fd=open("/dev/my_led",O_RDWR);
if(fd<0)
printf("can'topen!\n");
while(1)
{
//显示菜单
printf("\t1.presskey \'r\' to read device!\n");
printf("\t1.presskey \'w\' to write device!\n");
printf("\t1.presskey \'q\' to exit!\n");
ch=getchar();
getchar();
//根据输入进行判断
if('q'==ch)
break;
switch(ch){
case'r':
printf("testbefore reading...\n");
read(fd,&test,4);
printf("val=%d\n",test);
printf("testafter reading...\n");
break;
case'w':
printf("testbefore writing...\n");
val=5;
write(fd,&val,4);
printf("testafter writing...\n");
break;
default:
break;
sleep(1);
}
}
close(fd);
return0;
}
KERNALDIR=/root/opt/EmbedSky/linux-2.6.30.4/
MODULENAME=firstchardevice
obj-m :=$(MODULENAME).o
all:
make-C $(KERNALDIR) M=`pwd` modules
arm-linux-gcc-o test$(MODULENAME) test$(MODULENAME).c
clean:
make-C $(KERNALDIR) M=`pwd` clean
led灯按键操作
#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/device.h>
#include <asm/uaccess.h>
#include <asm/io.h>
MODULE_LICENSE("GPL");
int major;
static struct class *firstdrv_class;
static struct device*firstdrv_device;
volatile unsigned long *gpfcon;
volatile unsigned long *gpfdat;
static int myfirst_open(struct inode *inode,struct file *file)
{
printk("first_char_deviceopen test!\n");
*gpfcon&=~((0x3<<0)|(0x3<<2)|(0x3<<4)|(0x3<<8));
return0;
}
static ssize_t myfirst_read(struct file*file, char __user *buf, size_t size, loff_t *ppos)
{
intkey_val=0;
printk("first_char_deviceread test!\n");
if(!(*gpfdat&(0x1<<0)))
{key_val=1;printk("%d\n",key_val);}
if(!(*gpfdat&(0x1<<1)))
{key_val=2;printk("%d\n",key_val);}
if(!(*gpfdat&(0x1<<2)))
{key_val=3;printk("%d\n",key_val);}
if(!(*gpfdat&(0x1<<4)))
{key_val=4;printk("%d\n",key_val);}
copy_to_user(buf,&key_val,4);
return0;
}
static ssize_t myfirst_write(struct file*file, const char __user *buf,
size_t count, loff_t *ppos)
{
printk("first_char_devicewrite test!\n");
return0;
}
static const struct file_operationsmyfirst_fops = {
.owner = THIS_MODULE,
.open = myfirst_open,
.write = myfirst_write,
.read =myfirst_read,
};
static int __init myfirst_init(void)
{
printk("welcometo init function!\n");
gpfcon=(unsignedlong*)ioremap(0x56000050,16);
gpfdat=gpfcon+1;
major=register_chrdev(0,"first_drv",&myfirst_fops);
printk("major:%d\n",major);
firstdrv_class=class_create(THIS_MODULE,"myclass");
firstdrv_device=device_create(firstdrv_class,NULL,MKDEV(major,0),NULL,"my_led");
return0;
}
static void __exit myfirst_exit(void)
{
iounmap(gpfcon);
unregister_chrdev(major,"first_drv");
device_destroy(firstdrv_class,MKDEV(major,0));
class_destroy(firstdrv_class);
}
module_init(myfirst_init);
module_exit(myfirst_exit);
#include <stdio.h>
#include <fcntl.h>
#include <sys/types.h>
#include <unistd.h>
int main(int argc,char** argv)
{
intfd;
intval;
fd=open("/dev/my_led",O_RDWR);
if(fd<0)
printf("can'topen!\n");
while(1)
{
if(read(fd,&val,4)==0)
if(val)
printf("keynumber is %d\n",val);
}
return0;
}
KERNALDIR=/root/opt/EmbedSky/linux-2.6.30.4/
MODULENAME=firstchardevice
obj-m :=$(MODULENAME).o
all:
make-C $(KERNALDIR) M=`pwd` modules
arm-linux-gcc-o test$(MODULENAME) test$(MODULENAME).c
clean:
make-C $(KERNALDIR) M=`pwd` clean
led按键驱动
#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/device.h>
#include <linux/uaccess.h>
#include <mach/regs-gpio.h>
#include <mach/hardware.h>
#include <asm/io.h>
MODULE_LICENSE("GPL");
int major;
static struct class *firstdrv_class;
static struct device*firstdrv_device;
static int myfirst_open(struct inode *inode,struct file *file)
{
printk("first_char_deviceopen test!\n");
s3c2410_gpio_cfgpin(S3C2410_GPF0,S3C2410_GPF0_INP);
s3c2410_gpio_cfgpin(S3C2410_GPF1,S3C2410_GPF1_INP);
s3c2410_gpio_cfgpin(S3C2410_GPF2,S3C2410_GPF2_INP);
s3c2410_gpio_cfgpin(S3C2410_GPF4,S3C2410_GPF4_INP);
return0;
}
static ssize_t myfirst_read(struct file*file, __user char *buf, size_t count,
loff_t*ppos)
{
intkey_val;
//printk("first_char_deviceread test!\n");
if(!(s3c2410_gpio_getpin(S3C2410_GPF0)))
key_val=1;
if(!(s3c2410_gpio_getpin(S3C2410_GPF1)))
key_val=2;
if(!(s3c2410_gpio_getpin(S3C2410_GPF2)))
key_val=3;
if(!(s3c2410_gpio_getpin(S3C2410_GPF4)))
key_val=4;
copy_to_user(buf,&key_val,4);
return0;
}
static ssize_t myfirst_write(struct file*file, const char __user *buf,
size_t count, loff_t *ppos)
{
printk("first_char_devicewrite test!\n");
return0;
}
static const struct file_operationsmyfirst_fops = {
.owner = THIS_MODULE,
.open = myfirst_open,
.read =myfirst_read,
.write = myfirst_write,
};
static int __init myfirst_init(void)
{
printk("welcometo init function!\n");
major=register_chrdev(0,"first_drv",&myfirst_fops);
printk("major:%d\n",major);
firstdrv_class=class_create(THIS_MODULE,"myclass");
firstdrv_device=device_create(firstdrv_class,NULL,MKDEV(major,0),NULL,"my_led");
return0;
}
static void __exit myfirst_exit(void)
{
unregister_chrdev(major,"first_drv");
device_destroy(firstdrv_class,MKDEV(major,0));
class_destroy(firstdrv_class);
}
module_init(myfirst_init);
module_exit(myfirst_exit);
#include <stdio.h>
#include <fcntl.h>
int main(int argc,char** argv)
{
intfd;
intval=0;
fd=open("/dev/my_led",O_RDWR);
if(fd<0)
printf("can'topen!\n");
while(1)
{
if(read(fd,&val,4)==0)
{
if((val==1) || (val==2) || (val==3) || (val==4))
printf("keynumber is %d\n",val);
}
}
return0;
}
KERNALDIR=/root/opt/EmbedSky/linux-2.6.30.4/
MODULENAME=firstchardevice
obj-m :=$(MODULENAME).o
all:
make-C $(KERNALDIR) M=`pwd` modules
arm-linux-gcc-o test$(MODULENAME) test$(MODULENAME).c
clean:
make-C $(KERNALDIR) M=`pwd` clean
led按键驱动for循环
#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/device.h>
#include <linux/uaccess.h>
#include <mach/regs-gpio.h>
#include <mach/hardware.h>
#include <asm/io.h>
MODULE_LICENSE("GPL");
int major;
static struct class *firstdrv_class;
static struct device*firstdrv_device;
struct keynumdata {
unsigned long pin_key;
unsignedint pin_key_cfg;
};
static struct keynumdata mykeydata[4]=
{
{S3C2410_GPF0,S3C2410_GPF0_INP},
{S3C2410_GPF1,S3C2410_GPF1_INP},
{S3C2410_GPF2,S3C2410_GPF2_INP},
{S3C2410_GPF4,S3C2410_GPF4_INP},
};
static int myfirst_open(struct inode *inode,struct file *file)
{
inti;
printk("first_char_deviceopen test!\n");
for(i=0;i<4;i++)
s3c2410_gpio_cfgpin(mykeydata[i].pin_key,mykeydata[i].pin_key_cfg);
return0;
}
static ssize_t myfirst_read(struct file*file, __user char *buf, size_t count,
loff_t*ppos)
{
intkey_val;
inti;
for(i=0;i<4;i++)
if(!(s3c2410_gpio_getpin(mykeydata[i].pin_key)))
key_val=i+1;
copy_to_user(buf,&key_val,4);
return0;
}
static ssize_t myfirst_write(struct file*file, const char __user *buf,
size_t count, loff_t *ppos)
{
printk("first_char_devicewrite test!\n");
return0;
}
static const struct file_operationsmyfirst_fops = {
.owner = THIS_MODULE,
.open = myfirst_open,
.read =myfirst_read,
.write = myfirst_write,
};
static int __init myfirst_init(void)
{
printk("welcometo init function!\n");
major=register_chrdev(0,"first_drv",&myfirst_fops);
printk("major:%d\n",major);
firstdrv_class=class_create(THIS_MODULE,"myclass");
firstdrv_device=device_create(firstdrv_class,NULL,MKDEV(major,0),NULL,"my_led");
return0;
}
static void __exit myfirst_exit(void)
{
unregister_chrdev(major,"first_drv");
device_destroy(firstdrv_class,MKDEV(major,0));
class_destroy(firstdrv_class);
}
module_init(myfirst_init);
module_exit(myfirst_exit);
#include <stdio.h>
#include <fcntl.h>
int main(int argc,char** argv)
{
intfd;
intval=0;
fd=open("/dev/my_led",O_RDWR);
if(fd<0)
printf("can'topen!\n");
while(1)
{
if(read(fd,&val,4)==0)
{
if((val==1) || (val==2) || (val==3) || (val==4))
printf("keynumber is %d\n",val);
}
}
return0;
}
KERNALDIR=/root/opt/EmbedSky/linux-2.6.30.4/
MODULENAME=firstchardevice
obj-m :=$(MODULENAME).o
all:
make-C $(KERNALDIR) M=`pwd` modules
arm-linux-gcc-o test$(MODULENAME) test$(MODULENAME).c
clean:
make-C $(KERNALDIR) M=`pwd` clean
内核修改中断
#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/device.h>
#include <linux/uaccess.h>
#include <asm/io.h>
#include <mach/regs-gpio.h>
#include <mach/hardware.h>
#include <linux/interrupt.h>
#include <mach/irqs.h>
#include <linux/wait.h>
MODULE_LICENSE("GPL");
int major;
static struct class *firstdrv_class;
static struct device*firstdrv_device;
static int vpress=0;
static DECLARE_WAIT_QUEUE_HEAD(key_queue);
static unsigned char key_val;
struct keynumdata {
unsignedlong pin_key;
unsignedint pin_key_cfg;
unsignedchar pin_key_val;
char* name;
intirq_nu;
};
static struct keynumdata mykeydata[4]=
{
{S3C2410_GPF0,S3C2410_GPF0_EINT0,0x01,"key1",IRQ_EINT0},
{S3C2410_GPF1,S3C2410_GPF1_EINT1,0x02,"key2",IRQ_EINT1},
{S3C2410_GPF2,S3C2410_GPF2_EINT2,0x03,"key3",IRQ_EINT2},
{S3C2410_GPF4,S3C2410_GPF4_EINT4,0x04,"key4",IRQ_EINT4},
};
static irqreturn_t key_int_function(int irq,void *mypoint)
{
printk("enterinterrupt!");
structkeynumdata *mykeydata_tmp=(structkeynumdata *)(mypoint);
if(!(s3c2410_gpio_getpin(mykeydata_tmp->pin_key)))
key_val=mykeydata_tmp->pin_key_val|0x80;
else
key_val=mykeydata_tmp->pin_key_val;
vpress=1;
wake_up_interruptible(&key_queue);
returnIRQ_HANDLED;
}
static int myfirst_open(struct inode *inode,struct file *file)
{
inti;
printk("first_char_deviceopen test!\n");
for(i=0;i<4;i++)
{
s3c2410_gpio_cfgpin(mykeydata[i].pin_key,mykeydata[i].pin_key_cfg);
request_irq(mykeydata[i].irq_nu,key_int_function,IRQF_TRIGGER_RISING|IRQF_TRIGGER_FALLING|IRQF_SHARED,mykeydata[i].name, (void *)&mykeydata[i]);
}
return0;
}
static ssize_t myfirst_read(struct file*file, __user char *buf, size_t count,
loff_t*ppos)
{
//当vpress=0时,该进程挂入等待队列,休眠
//当vpress=1时,通过wake_up_interruptible();唤醒队列
printk("entermyfirst_read!\n");
wait_event_interruptible(key_queue,vpress);
vpress=0;
copy_to_user(buf,&key_val,count);
return0;
}
static ssize_t myfirst_write(struct file*file, const char __user *buf,
size_t count, loff_t *ppos)
{
printk("first_char_devicewrite test!\n");
return0;
}
static const struct file_operationsmyfirst_fops = {
.owner = THIS_MODULE,
.open = myfirst_open,
.read =myfirst_read,
.write = myfirst_write,
};
static int __init myfirst_init(void)
{
printk("welcometo init function!\n");
major=register_chrdev(0,"first_drv",&myfirst_fops);
printk("major:%d\n",major);
firstdrv_class=class_create(THIS_MODULE,"myclass");
firstdrv_device=device_create(firstdrv_class,NULL,MKDEV(major,0),NULL,"my_led");
return0;
}
static void __exit myfirst_exit(void)
{
inti;
unregister_chrdev(major,"first_drv");
device_destroy(firstdrv_class,MKDEV(major,0));
class_destroy(firstdrv_class);
for(i=0;i<4;i++)
{
free_irq(mykeydata[i].irq_nu, (void *)&mykeydata[i]);
}
}
module_init(myfirst_init);
module_exit(myfirst_exit);
#include <stdio.h>
#include <fcntl.h>
int main(int argc,char** argv)
{
intfd;
unsignedchar val;
fd=open("/dev/my_led",O_RDWR);
if(fd<0)
printf("can'topen!\n");
while(1)
{
read(fd,&val,1);
printf("keys:0x%02x\n",val);
}
return0;
}
KERNALDIR=/root/opt/EmbedSky/linux-2.6.30.4/
MODULENAME=firstchardevice
obj-m :=$(MODULENAME).o
all:
make-C $(KERNALDIR) M=`pwd` modules
arm-linux-gcc-o test$(MODULENAME) test$(MODULENAME).c
clean:
make-C $(KERNALDIR) M=`pwd` clean
需要生成一个zimage
中断按键驱动
#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/device.h>
#include <linux/uaccess.h>
#include <mach/regs-gpio.h>
#include <mach/hardware.h>
#include <asm/io.h>
#include <linux/wait.h>
#include <linux/interrupt.h>
#include <linux/poll.h>
MODULE_LICENSE("GPL");
int major;
static struct class *firstdrv_class;
static struct device*firstdrv_device;
static int vpress=0;
static DECLARE_WAIT_QUEUE_HEAD(key_queue);
static char key_val;
struct keynumdata {
unsignedlong pin_key;
unsignedint pin_key_cfg;
intirq_nu;
char* name;
unsignedchar pin_key_val;
};
static struct keynumdata mykeydata[4]=
{
{S3C2410_GPF0,S3C2410_GPF0_EINT0,IRQ_EINT0,"key1",0x01},
{S3C2410_GPF1,S3C2410_GPF1_EINT1,IRQ_EINT1,"key2",0x02},
{S3C2410_GPF2,S3C2410_GPF2_EINT2,IRQ_EINT2,"key3",0x03},
{S3C2410_GPF4,S3C2410_GPF4_EINT4,IRQ_EINT4,"key4",0x04},
};
irqreturn_t key_inter_function(int irq, void*mypoint)
{
structkeynumdata *mykeydata_tmp=(struct keynumdata *)mypoint;
if(!s3c2410_gpio_getpin(mykeydata_tmp->pin_key))
key_val=mykeydata_tmp->pin_key_val|0x80;
else
key_val=mykeydata_tmp->pin_key_val;
vpress=1;
wake_up_interruptible(&key_queue);
returnIRQ_HANDLED;
}
static int myfirst_open(struct inode *inode,struct file *file)
{
inti;
printk("first_char_deviceopen test!\n");
for(i=0;i<4;i++)
{
s3c2410_gpio_cfgpin(mykeydata[i].pin_key,mykeydata[i].pin_key_cfg);
request_irq(mykeydata[i].irq_nu,key_inter_function,IRQF_TRIGGER_FALLING|IRQF_TRIGGER_RISING|IRQF_SHARED,mykeydata[i].name,(void*)&mykeydata[i]);
}
return0;
}
static ssize_t myfirst_read(struct file*file, __user char *buf, size_t count,
loff_t*ppos)
{
vpress=0;
copy_to_user(buf,&key_val,count);
return0;
}
static ssize_t myfirst_write(struct file*file, const char __user *buf,
size_t count, loff_t *ppos)
{
printk("first_char_devicewrite test!\n");
return0;
}
static int myfirst_close(struct inode *inode, struct file * file)
{
inti;
for(i=0;i<4;i++)
free_irq(mykeydata[i].irq_nu,(void*)&mykeydata[i]);
return0;
}
static unsigned int myfirst_poll (structfile *file, struct poll_table_struct * wait)
{
unsignedint mask=0;
poll_wait(file,&key_queue, wait);
if(vpress)
mask|= POLLIN | POLLRDNORM;
returnmask;
}
static const struct file_operationsmyfirst_fops = {
.owner = THIS_MODULE,
.open = myfirst_open,
.read =myfirst_read,
.write = myfirst_write,
.release =myfirst_close,
.poll =myfirst_poll,
};
static int __init myfirst_init(void)
{
printk("welcometo init function!\n");
major=register_chrdev(0,"first_drv",&myfirst_fops);
printk("major:%d\n",major);
firstdrv_class=class_create(THIS_MODULE,"myclass");
firstdrv_device=device_create(firstdrv_class,NULL,MKDEV(major,0),NULL,"my_led");
return0;
}
static void __exit myfirst_exit(void)
{
unregister_chrdev(major,"first_drv");
device_destroy(firstdrv_class,MKDEV(major,0));
class_destroy(firstdrv_class);
}
module_init(myfirst_init);
module_exit(myfirst_exit);
#include <stdio.h>
#include <fcntl.h>
#include <poll.h>
int main(int argc,char** argv)
{
intfd;
intret;
unsignedchar val=0;
structpollfd key_pollfd[1];
fd=open("/dev/my_led",O_RDWR);
if(fd<0)
printf("can'topen!\n");
key_pollfd[0].fd=fd;
key_pollfd[0].events=POLLIN;
while(1)
{
ret=poll(key_pollfd,1, 5000);
if(ret==-1)
printf("error!\n");
elseif (ret==0)
{
printf("timeout!\n");
}
else
{
read(fd,&val,1);
printf("keynumber:0x%02x\n",val);
}
}
return0;
}
KERNALDIR=/root/opt/EmbedSky/linux-2.6.30.4/
MODULENAME=firstchardevice
obj-m :=$(MODULENAME).o
all:
make-C $(KERNALDIR) M=`pwd` modules
arm-linux-gcc-o test$(MODULENAME) test$(MODULENAME).c
clean:
make-C $(KERNALDIR) M=`pwd` clean
定时器
Key_timer.c
#include <linux/init.h>
#include <linux/module.h>
#include <linux/timer.h>
MODULE_LICENSE("GPL");
static struct timer_list key_timer;
static void timer_function(unsigned longdata)
{
staticunsigned int i = 0;
printk("timer:%ld!\n",data);
#if 0
my_timer.expires = jiffies + 2*HZ
add_timer(&key_timer);
#endif
if(i++<5)
mod_timer(&key_timer,jiffies + 2*HZ);
}
static int __init timer_init(void)
{
init_timer(&key_timer);
key_timer.expires=jiffies+5*HZ;
key_timer.function=timer_function;
key_timer.data=5;
add_timer(&key_timer);
return0;
}
static void __exit timer_exit(void)
{
del_timer(&key_timer);
}
module_init(timer_init);
module_exit(timer_exit);
KERNALDIR=/root/opt/EmbedSky/linux-2.6.30.4/
MODULENAME=key_timer
obj-m :=$(MODULENAME).o
all:
make-C $(KERNALDIR) M=`pwd` modules
#arm-linux-gcc-o test$(MODULENAME) test$(MODULENAME).c
clean:
make-C $(KERNALDIR) M=`pwd` clean
定时器消除中断抖动
#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/device.h>
#include <linux/uaccess.h>
#include <asm/io.h>
#include <mach/regs-gpio.h>
#include <mach/hardware.h>
#include <linux/interrupt.h>
#include <mach/irqs.h>
#include <linux/wait.h>
#include <linux/poll.h>
MODULE_LICENSE("GPL");
int major;
static struct class *firstdrv_class;
static struct device*firstdrv_device;
static int vpress=0;
static DECLARE_WAIT_QUEUE_HEAD(key_queue);
static unsigned char key_val;
static struct timer_list key_timer;
struct keynumdata {
unsignedlong pin_key;
unsignedint pin_key_cfg;
unsignedchar pin_key_val;
char* name;
intirq_nu;
};
static struct keynumdata mykeydata[4]=
{
{S3C2410_GPF0,S3C2410_GPF0_EINT0,0x01,"key1",IRQ_EINT0},
{S3C2410_GPF1,S3C2410_GPF1_EINT1,0x02,"key2",IRQ_EINT1},
{S3C2410_GPF2,S3C2410_GPF2_EINT2,0x03,"key3",IRQ_EINT2},
{S3C2410_GPF4,S3C2410_GPF4_EINT4,0x04,"key4",IRQ_EINT4},
};
struct keynumdata *mykeydata_tmp=&mykeydata[0];
static void key_timer_funciton(unsigned longdata)
{
if(!(s3c2410_gpio_getpin(mykeydata_tmp->pin_key)))
key_val=mykeydata_tmp->pin_key_val|0x80;
else
key_val=mykeydata_tmp->pin_key_val;
vpress=1;
wake_up_interruptible(&key_queue);
}
static irqreturn_t key_int_function(int irq,void *mypoint)
{
mykeydata_tmp=(structkeynumdata *)(mypoint);
mod_timer(&key_timer,jiffies+HZ/100);
returnIRQ_HANDLED;
}
static int myfirst_open(struct inode *inode,struct file *file)
{
inti;
printk("first_char_deviceopen test!\n");
for(i=0;i<4;i++)
{
s3c2410_gpio_cfgpin(mykeydata[i].pin_key,mykeydata[i].pin_key_cfg);
request_irq(mykeydata[i].irq_nu,key_int_function,IRQF_TRIGGER_RISING|IRQF_TRIGGER_FALLING|IRQF_SHARED,mykeydata[i].name, (void *)&mykeydata[i]);
}
init_timer(&key_timer);
key_timer.function=key_timer_funciton;
add_timer(&key_timer);
return0;
}
static ssize_t myfirst_read(struct file*file, __user char *buf, size_t count,
loff_t*ppos)
{
//当vpress=0时,该进程挂入等待队列,休眠
//当vpress=1时,通过wake_up_interruptible();唤醒队列
vpress=0;
copy_to_user(buf,&key_val,count);
return0;
}
static ssize_t myfirst_write(struct file*file, const char __user *buf,
size_t count, loff_t *ppos)
{
printk("first_char_devicewrite test!\n");
return0;
}
static unsigned int myfirst_poll(struct file*file , struct poll_table_struct *wait)
{
unsignedint mask=0;
poll_wait(file,&key_queue,wait);
if(vpress)
mask|=POLLIN|POLLRDNORM;
returnmask;
}
static const struct file_operationsmyfirst_fops = {
.owner = THIS_MODULE,
.open = myfirst_open,
.read =myfirst_read,
.write = myfirst_write,
.poll =myfirst_poll,
};
static int __init myfirst_init(void)
{
printk("welcometo init function!\n");
major=register_chrdev(0,"first_drv",&myfirst_fops);
printk("major:%d\n",major);
firstdrv_class=class_create(THIS_MODULE,"myclass");
firstdrv_device=device_create(firstdrv_class,NULL,MKDEV(major,0),NULL,"my_led");
return0;
}
static void __exit myfirst_exit(void)
{
inti;
unregister_chrdev(major,"first_drv");
device_destroy(firstdrv_class,MKDEV(major,0));
class_destroy(firstdrv_class);
for(i=0;i<4;i++)
{
free_irq(mykeydata[i].irq_nu, (void *)&mykeydata[i]);
}
}
module_init(myfirst_init);
module_exit(myfirst_exit);
#include <stdio.h>
#include <fcntl.h>
#include <poll.h>
int main(int argc,char** argv)
{
intfd;
intret;
unsignedchar val;
structpollfd key_pollfd[1];
fd=open("/dev/my_led",O_RDWR);
if(fd<0)
printf("can'topen!\n");
key_pollfd[0].fd=fd;
key_pollfd[0].events=POLLIN;
while(1)
{
ret=poll(key_pollfd,1,5000);
if(ret==-1)
printf("error!\n");
elseif (ret==0)
printf("timeout!\n");
else
{
printf("ret=0x%02x\n",ret);
read(fd,&val,1);
printf("keys:0x%02x\n",val);
}
}
return0;
}
KERNALDIR=/root/opt/EmbedSky/linux-2.6.30.4/
MODULENAME=firstchardevice
obj-m :=$(MODULENAME).o
all:
make-C $(KERNALDIR) M=`pwd` modules
arm-linux-gcc-o test$(MODULENAME) test$(MODULENAME).c
clean:
make-C $(KERNALDIR) M=`pwd` clean
平台设备驱动
led_device_platform.c
#include <linux/init.h>
#include <linux/module.h>
#include <linux/platform_device.h>
MODULE_LICENSE("GPL");
static struct resource led_resource[] = {
[0]={
.start = 0x56000010,
.end = 0x56000010+ 8 - 1,
.flags = IORESOURCE_MEM,
},
[1]={
.start = 5,
.end = 5,
.flags = IORESOURCE_IRQ,
}
};
static void my_led_release(struct device*dev)
{
printk("my_led_release\n");
}
struct platform_device led_pdevice = {
.name ="led_device_driver_platform",
.id = -1,
.resource = led_resource,
.num_resources = ARRAY_SIZE(led_resource),
.dev = {
.release =my_led_release,
},
};
static int __init led_device_init(void)
{
platform_device_register(&led_pdevice);
return0;
}
static void __exit led_device_exit(void)
{
platform_device_unregister(&led_pdevice);
}
module_init(led_device_init);
module_exit(led_device_exit);
led_driver_platform.c
#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/platform_device.h>
#include <asm/io.h>
MODULE_LICENSE("GPL");
static int led_major;
static struct class *led_cls;
static int led_pin;
static volatile unsigned long *gpbcon;
static volatile unsigned long *gpbdat;
static int led_platform_open(struct inode*inode, struct file *file)
{
printk("led_platform_open!\n");
//初始化gpbcon,设置为输出状态10-17
*gpbcon&=~(0x3<<(led_pin*2));
*gpbcon|=(0x1<<(led_pin*2));
//初始化gpbdat,设置灯的初始状态
//*gpbdat|=(1<<led_pin);
return0;
}
static ssize_t led_platform_write(structfile *file, const char __user *buf,
size_t count, loff_t *ppos)
{
unsignedchar led_val=0;
printk("led_platform_write!\n");
//接收应用程序传递来的参数,根据参数的不同控制灯的亮灭
copy_from_user(&led_val,buf,count);
if(led_val) //如果传递来是1,点亮灯
{
*gpbdat&=~(1<<led_pin);
}
else //如果传递来是0,熄灭灯
{
*gpbdat|=(1<<led_pin);
}
return0;
}
static int led_platform_close (struct inode*inode, struct file *file)
{
printk("led_platform_close!\n");
return0;
}
static const struct file_operationsled_fops={
.owner =THIS_MODULE,
.open =led_platform_open,
.write =led_platform_write,
.release =led_platform_close,
};
static int led_platform_probe(struct platform_device *pdevice)
{
//获取资源
structresource *res=platform_get_resource(pdevice,IORESOURCE_MEM,0);
gpbcon=ioremap(res->start,res->end-res->start+1);
gpbdat=gpbcon+1;
res=platform_get_resource(pdevice,IORESOURCE_IRQ,0);
led_pin=res->start;
//普通字符设备驱动完成的工作,
//例如注册字符设备,创建类,创建设备文件节点
led_major=register_chrdev(0,"led_platform",&led_fops);
led_cls=class_create(THIS_MODULE,"led_platform_class");
device_create(led_cls,NULL,MKDEV(led_major,0),NULL,"myled");
return0;
}
static int led_platform_remove(structplatform_device *pdevice)
{
device_destroy(led_cls,MKDEV(led_major,0));
class_destroy(led_cls);
unregister_chrdev(led_major,"led_platform");
return0;
}
static struct platform_driver led_pdriver ={
.probe = led_platform_probe,
.remove = led_platform_remove,
.driver = {
.name = "led_device_driver_platform",
.owner = THIS_MODULE,
},
};
static int __init led_driver_init(void)
{
returnplatform_driver_register(&led_pdriver);
}
static void __exit led_driver_exit(void)
{
platform_driver_unregister(&led_pdriver);
}
module_init(led_driver_init);
module_exit(led_driver_exit);
test_led_devdri_platform.c
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
static void print_usage(char *str)
{
printf("Usage:\n");
printf("%s<on|off>\n", str);
}
int main(int argc, char **argv)
{
intled_fd;
unsignedchar led_val = 0;
led_fd= open("/dev/myled", O_RDWR);
if(led_fd< 0)
{
printf("can'topen!\n");
return0;
}
if(argc!= 2)
{
print_usage(argv[0]);
return0;
}
if(strcmp(argv[1],"on") == 0)
{
led_val= 1; //点灯
}
else
{
led_val= 0; //灭灯
}
write(led_fd,&led_val, 1);
close(led_fd);
return0;
}
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
static void print_usage(char *str)
{
printf("Usage:\n");
printf("%s<on|off>\n", str);
}
int main(int argc, char **argv)
{
intled_fd;
unsignedchar led_val = 0;
led_fd= open("/dev/myled", O_RDWR);
if(led_fd< 0)
{
printf("can'topen!\n");
return0;
}
if(argc!= 2)
{
print_usage(argv[0]);
return0;
}
if(strcmp(argv[1],"on") == 0)
{
led_val= 1; //点灯
}
else
{
led_val= 0; //灭灯
}
write(led_fd,&led_val, 1);
close(led_fd);
return0;
}
KERNELDIR?=/root/opt/EmbedSky/linux-2.6.30.4
obj-m +=led_device_platform.oled_driver_platform.o
default:
arm-linux-gcctest_led_devdri_platform.c -o test_led_devdri_platform
$(MAKE)-C $(KERNELDIR) M=`pwd` modules
clean:
rm-rf *.o *.mod.* *.ko .$(MODNAME).* .tmp* module* Module*
先插入模块device
再插入模块driver
/etc/rc.d/init.d/leds stop 关掉
卸载的时候先 driver
再 device
块设备驱动
01
myramblock.c
#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/genhd.h>
#include <linux/blkdev.h>
MODULE_LICENSE("GPL");
#define RAMBLOCKSIZE (1024*1024)
static struct gendisk *myramblock_disk;
static struct request_queue *myramblock_queue;
static int major;
static DEFINE_SPINLOCK(myramblock_lock);
static struct block_device_operationsmyramblock_fops =
{
.owner = THIS_MODULE,
};
static void do_myramblock_request(structrequest_queue *q)
{
staticint cnt=0;
printk("do_myramblock_request%d\n",++cnt);
}
static int __init myramblock_init(void)
{
/*1、分配一个gendisk结构体*/
myramblock_disk=alloc_disk(16); /*次设备的个数*/
/*2、设置*/
/*2.1 设置队列 request_queue*/
myramblock_queue=blk_init_queue(do_myramblock_request,&myramblock_lock);
myramblock_disk->queue=myramblock_queue;
/*2.2设置其他属性,例如容量等*/
major=register_blkdev(0,"myramblock");
myramblock_disk->major=major;
myramblock_disk->first_minor=0;
sprintf(myramblock_disk->disk_name,"myramblick");
myramblock_disk->fops=&myramblock_fops;
set_capacity(myramblock_disk,RAMBLOCKSIZE/512);
/*3、添加块设备*/
add_disk(myramblock_disk);
return0;
}
static void __exit myramblock_exit(void)
{
unregister_blkdev(major,"myramblock");
del_gendisk(myramblock_disk);
}
module_init(myramblock_init);
module_exit(myramblock_exit);
KERNELDIR?=/root/opt/EmbedSky/linux-2.6.30.4
obj-m +=myramblock.o
default:
#arm-linux-gcctest_led_devdri_platform.c -o test_led_devdri_platform
$(MAKE)-C $(KERNELDIR) M=`pwd` modules
clean:
rm-rf *.o *.mod.* *.ko .$(MODNAME).* .tmp* module* Module*
02
#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/genhd.h>
#include <linux/blkdev.h>
MODULE_LICENSE("GPL");
#define RAMBLOCKSIZE (1024*1024)
static struct gendisk *myramblock_disk;
static struct request_queue*myramblock_queue;
static int major;
static DEFINE_SPINLOCK(myramblock_lock);
static struct block_device_operationsmyramblock_fops =
{
.owner = THIS_MODULE,
};
static void do_myramblock_request(structrequest_queue *q)
{
structrequest *req;
staticint cnt=0;
printk("do_myramblock_request%d\n",++cnt);
while((req= elv_next_request(q)) != NULL)
end_request(req,1); //第二个参数为1,表示正确处理了请求
}
static int __init myramblock_init(void)
{
/*1、分配一个gendisk结构体*/
myramblock_disk=alloc_disk(16); /*次设备的个数*/
/*2、设置*/
/*2.1 设置队列 request_queue*/
myramblock_queue=blk_init_queue(do_myramblock_request,&myramblock_lock);
myramblock_disk->queue=myramblock_queue;
/*2.2设置其他属性,例如容量等*/
major=register_blkdev(0,"myramblock");
myramblock_disk->major=major;
myramblock_disk->first_minor=0;
sprintf(myramblock_disk->disk_name,"myramblick");
myramblock_disk->fops=&myramblock_fops;
set_capacity(myramblock_disk,RAMBLOCKSIZE/512);
/*3、添加块设备*/
add_disk(myramblock_disk);
return0;
}
static void __exit myramblock_exit(void)
{
unregister_blkdev(major,"myramblock");
del_gendisk(myramblock_disk);
}
module_init(myramblock_init);
module_exit(myramblock_exit);
KERNELDIR ?=/root/opt/EmbedSky/linux-2.6.30.4
obj-m +=myramblock.o
default:
#arm-linux-gcctest_led_devdri_platform.c -o test_led_devdri_platform
$(MAKE)-C $(KERNELDIR) M=`pwd` modules
clean:
rm-rf *.o *.mod.* *.ko .$(MODNAME).* .tmp* module* Module*
块设备修改
01
#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/genhd.h>
#include <linux/blkdev.h>
MODULE_LICENSE("GPL");
static struct gendisk *myramblock_disk;
static int mymajor;
static struct request_queue*myramblock_queue;
static DEFINE_SPINLOCK(myramblock_lock);
#define MYRAMBLOCK_SIZE (1024*1024)
static unsigned char *ramblock_buffer;
static struct block_device_operationsmyramblock_fops = {
.owner = THIS_MODULE,
};
static void do_myramblock_request (structrequest_queue * q)
{
structrequest *req;
staticint cnt=0;
printk("do_myramblock_request!%d\n",++cnt);
while((req = elv_next_request(q)) != NULL) {
/*判读读写方向,进行数据传递*/
/*数据传递三要素:源,目的,大小*/
unsignedlong offset = req->sector*512;
unsignedlong len = req->nr_sectors*512;
if(rq_data_dir(req) == READ)
memcpy(req->buffer, ramblock_buffer+offset,len);
else
memcpy(ramblock_buffer+offset, req->buffer,len);
end_request(req,1);
}
}
static int __init myramblock_init(void)
{
mymajor=register_blkdev(0,"myramblock");
/*1、分配一个gendisk结构体*/
myramblock_disk= alloc_disk(8);
/*2、设置*/
/*2.1设置队列*/
myramblock_queue= blk_init_queue(do_myramblock_request, &myramblock_lock);
myramblock_disk->queue=myramblock_queue;
/*2.2设置其他属性*/
myramblock_disk->major=mymajor;
myramblock_disk->first_minor=0;
sprintf(myramblock_disk->disk_name,"myramblock");
myramblock_disk->fops=&myramblock_fops;
set_capacity(myramblock_disk,MYRAMBLOCK_SIZE/512);
/*硬件操作,分配空间*/
ramblock_buffer=kmalloc(MYRAMBLOCK_SIZE,GFP_KERNEL);
/*4、添加块设备*/
add_disk(myramblock_disk);
return0;
}
static void __exit myramblock_exit(void)
{
del_gendisk(myramblock_disk);
kfree(ramblock_buffer);
unregister_blkdev(mymajor,"myramblock");
}
module_init(myramblock_init);
module_exit(myramblock_exit);
KERNELDIR?=/root/opt/EmbedSky/linux-2.6.30.4
obj-m +=myramblock.o
default:
#arm-linux-gcctest_led_devdri_platform.c -o test_led_devdri_platform
$(MAKE)-C $(KERNELDIR) M=`pwd` modules
clean:
rm-rf *.o *.mod.* *.ko .$(MODNAME).* .tmp* module* Module*
02
#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/genhd.h>
#include <linux/blkdev.h>
#include <linux/hdreg.h>
MODULE_LICENSE("GPL");
static struct gendisk *myramblock_disk;
static int mymajor;
static struct request_queue*myramblock_queue;
static DEFINE_SPINLOCK(myramblock_lock);
#define MYRAMBLOCK_SIZE (1024*1024)
static unsigned char *ramblock_buffer;
static int
myramblock_getgeo(struct block_device *bdev,struct hd_geometry *geo)
{
geo->cylinders=32;
geo->heads= 2;
geo->sectors=MYRAMBLOCK_SIZE/2/32/512;
return0;
}
static struct block_device_operationsmyramblock_fops = {
.owner = THIS_MODULE,
.getgeo =myramblock_getgeo,
};
static void do_myramblock_request (struct request_queue* q)
{
structrequest *req;
staticint r_cnt=0;
staticint w_cnt=0;
while((req = elv_next_request(q)) != NULL) {
/*判读读写方向,进行数据传递*/
/*数据传递三要素:源,目的,大小*/
unsignedlong offset = req->sector*512;
unsignedlong len = req->nr_sectors*512;
if(rq_data_dir(req) == READ)
{
memcpy(req->buffer,ramblock_buffer+offset, len);
printk("do_myramblock_request!read %d\n",++r_cnt);
}
else
{
memcpy(ramblock_buffer+offset,req->buffer, len);
printk("do_myramblock_request!write %d\n",++w_cnt);
}
end_request(req,1);
}
}
static int __init myramblock_init(void)
{
mymajor=register_blkdev(0,"myramblock");
/*1、分配一个gendisk结构体*/
myramblock_disk= alloc_disk(8);
/*2、设置*/
/*2.1设置队列*/
myramblock_queue= blk_init_queue(do_myramblock_request, &myramblock_lock);
myramblock_disk->queue=myramblock_queue;
/*2.2设置其他属性*/
myramblock_disk->major=mymajor;
myramblock_disk->first_minor=0;
sprintf(myramblock_disk->disk_name,"myramblock");
myramblock_disk->fops=&myramblock_fops;
set_capacity(myramblock_disk,MYRAMBLOCK_SIZE/512);
/*硬件操作,分配空间*/
ramblock_buffer=kzalloc(MYRAMBLOCK_SIZE,GFP_KERNEL);
/*4、添加块设备*/
add_disk(myramblock_disk);
return0;
}
static void __exit myramblock_exit(void)
{
del_gendisk(myramblock_disk);
kfree(ramblock_buffer);
unregister_blkdev(mymajor,"myramblock");
}
module_init(myramblock_init);
module_exit(myramblock_exit);
KERNELDIR?=/root/opt/EmbedSky/linux-2.6.30.4
obj-m +=myramblock.o
default:
#arm-linux-gcctest_led_devdri_platform.c -o test_led_devdri_platform
$(MAKE)-C $(KERNELDIR) M=`pwd` modules
clean:
rm-rf *.o *.mod.* *.ko .$(MODNAME).* .tmp* module* Module*