已经很久没写过驱动了,今天突然说要控制一个LED灯,闲来无事便自己写了一个,权当复习,闲话少说直接代码......
驱动代码(gpg7.c):
- #include <linux/module.h>
- #include <linux/kernel.h>
- #include <linux/fs.h>
- #include <linux/init.h>
- #include <linux/delay.h>
- #include <asm/irq.h>
- #include <linux/device.h>
- #include <asm/uaccess.h>
- #include <linux/ioport.h>
- #include <asm/io.h>
- #define GPB_ON 1
- #define GPB_OFF 0
- static unsigned int oam_major=0;
- static struct class *oam_class =NULL;
- static volatile unsigned long *gpfcon;
- static volatile unsigned long *gpfdat;
- /*1. 实现对硬件的操作方法*/
- static int oam_open(struct inode *inode, struct file *file)
- {
- /*初始化硬件*/
- /*将GPB7设置为输出管脚*/
- *gpfcon &= ~(0x3<<14);
- *gpfcon |= (0x1<<14);
- return 0;
- }
- ssize_t oam_read(struct file *file, char __user *buf, size_t size, loff_t *ppos)
- {
- //TODO
- return 0;
- }
- static ssize_t oam_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
- {
- char val;
- int ret;
- /*获取用户空间传入的值*/
- ret =copy_from_user(&val,buf,1);
- if(!val)
- {
- *gpfdat |= (0x1 << 7);
- }
- else
- {
- *gpfdat &= ~(0x1 << 7);
- }
- return 0;
- }
- static int oam_ioctl(struct inode *inode, struct file *file, unsigned int cmd,unsigned long arg)
- {
- switch(cmd)
- {
- case GPB_OFF:
- *gpfdat |= (0x1 << 7);
- break;
- case GPB_ON:
- *gpfdat &= ~(0x1 << 7);
- break;
- default:break;
- }
- return 0;
- }
- /*2. 构建file_operations结构体*/
- static struct file_operations oam_fops={
- .owner = THIS_MODULE,
- .open = oam_open,
- .write = oam_write,
- .read = oam_read,
- .ioctl = oam_ioctl,
- };
- /*3. 实现入口函数*/
- static int __init oam_init(void)
- {
- /*1.注册*/
- oam_major =register_chrdev(0,"gpb7",&oam_fops);
- /*2. 构建设备节点*/
- oam_class =class_create(THIS_MODULE,"gpb7_class");
- device_create(oam_class,NULL,MKDEV(oam_major,0),NULL,"gpb7");
- /*3.将物理地址映射为虚拟地址*/
- gpfcon =ioremap(0x56000010,4096);
- gpfdat =gpfcon +1;
- return 0;
- }
- /*4.实现出口函数*/
- static void __exit oam_exit(void )
- {
- unregister_chrdev(oam_major,"gpb7");
- class_destroy(oam_class);
- device_destroy(oam_class,MKDEV(oam_major,0));
- iounmap(gpfcon);
- }
- module_init(oam_init);
- module_exit(oam_exit);
- MODULE_LICENSE("GPL");
测试代码(gpg7_test.c):
- #include <stdio.h>
- #include <string.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <fcntl.h>
- #include <sys/ioctl.h>
- #define GPB_ON 1
- #define GPB_OFF 0
- void print_usage(char *str)
- {
- printf("please input follow this!\n");
- printf("%s <dev> <on/off> \n",str);
- }
- int main(int argc, char **argv)
- {
- int fd = 0;
- //char buf[1];
- int cmd = 0;
- if(argc!=3&&argc!=2)
- {
- print_usage(argv[0]);
- return -1;
- }
- fd =open(argv[1], O_RDWR);
- if(fd <0)
- {
- printf("cannot open the dev!\n");
- return -1;
- }
- if(strcmp(argv[2],"on")==0)
- {
- cmd=GPB_ON;
- }
- else if(strcmp(argv[2],"off")==0)
- {
- cmd=GPB_OFF;
- }
- //write(fd, buf, 1);
- ioctl(fd,cmd,NULL);
- return 0;
- }
Makefile:
- all:
- make -C /home/farsight/anyk/s3c2440/kernal/linux-2.6.30.4 M=`pwd` modules
- clean:
- make -C /home/farsight/anyk/s3c2440/kernal/linux-2.6.30.4 M=`pwd` clean
- obj-m += gpb7.o
相对而言,字符设备还是挺简单的。