这篇文档重在记述TQ2440的LED驱动,重点在于将LED作为混杂设备注册的方法
即 misc_register(&dev)和misc_deregister(®ister)
这篇文档所基于的环境如下
硬件环境:TQ2440开发板
kernel :linux 2.6.32
文件系统: busybox1.13.1,yaffs2
效果图如下
一、code
- /*
- name: leds driver for tq2660
- author :keytounix
- as char devices
- */
- #include <linux/module.h>
- #include <linux/kernel.h>
- #include <linux/init.h>
- #include <linux/sched.h>
- #include <linux/poll.h>
- #include <linux/timer.h>
- #include <linux/irq.h>
- #include <linux/cdev.h>
- #include <linux/wait.h>//waitqueue
- #include <linux/errno.h>
- #include <linux/interrupt.h>//irq
- #include <linux/io.h>
- #include <linux/types.h>
- #include <linux/delay.h>
- #include <linux/semaphore.h>//sem
- #include <linux/fs.h>
- #include <linux/platform_device.h>//
- #include <linux/miscdevice.h>
- #include <linux/device.h>
- #include <linux/workqueue.h>//workqueue
- #include <asm/uaccess.h>
- #include <asm/irq.h>
- //soc相关
- #include <mach/gpio.h>
- #include <mach/regs-clock.h>
- #include <mach/regs-gpio.h>
- #include <mach/hardware.h>
- #include <mach/irqs.h>
- #define led_name "usr_leds"
- #define LED_NAME "usr_leds"
- //这个,是为了实现
- //任何时刻只能有一个
- //使用者能操作led
- struct semaphore sem[4];
- //打开
- static int led_open0(struct inode *nodep,struct file * filep);
- static int led_open1(struct inode *nodep,struct file * filep);
- static int led_open2(struct inode *nodep,struct file * filep);
- static int led_open3(struct inode *nodep,struct file * filep);
- //关闭
- static int led_release(struct inode *nodep,struct file * filep);
- //ioctrl函数
- static int led_ioctl(struct inode *nodep,struct file * filep,unsigned int cmd,long args);
- //写数据
- static int led_write(struct file * filep,char * __user buff,size_t count, loff_t *offt);
- //这个函数用来实现对led的读写
- static void led_display(int ledno,int status);
- struct file_operations fops[]=
- {
- [0]={
- .owner=THIS_MODULE,
- .open= led_open0,
- .release=led_release,
- .write =led_write,
- .ioctl=led_ioctl,
- },
- [1]=
- {
- .owner=THIS_MODULE,
- .open=led_open1,
- .release=led_release,
- .write =led_write,
- .ioctl=led_ioctl,
- },
- [2]=
- {
- .owner=THIS_MODULE,
- .open=led_open2,
- .release=led_release,
- .write =led_write,
- .ioctl=led_ioctl,
- },
- [3]=
- {
- .owner=THIS_MODULE,
- .open=led_open3,
- .release=led_release,
- .write =led_write,
- .ioctl=led_ioctl,
- },
- };
- struct LED_INFO
- {
- char * name;
- unsigned pin;
- }led_info[]=
- {
- [0]={
- .name="led1",
- .pin=S3C2410_GPB(5)
- },
- [1]={
- .name="led2",
- .pin=S3C2410_GPB(6)
- },
- [2]={
- .name="led3",
- .pin=S3C2410_GPB(7)
- },
- [3]={
- .name="led4",
- .pin=S3C2410_GPB(8)
- }
- };
- static struct miscdevice led_dev[]=
- {
- [0]=
- {
- .minor =MISC_DYNAMIC_MINOR,
- .name ="led0",
- .fops =&fops[0]
- },
- [1]=
- {
- .minor =MISC_DYNAMIC_MINOR,
- .name ="led1",
- .fops=&fops[1]
- },
- [2]=
- {
- .minor=MISC_DYNAMIC_MINOR,
- .name ="led2",
- .fops =&fops[2]
- },
- [3]=
- {
- .minor=MISC_DYNAMIC_MINOR,
- .name ="led3",
- .fops=&fops[3]
- }
- };
- #define LED_ON 0
- #define LED_OFF 1
- #define pin(x) led_info[x].pin
- #define _DEBUG_ 1
- #if _DEBUG_
- #define debug(format,msg...) printk(format,##msg)
- #else
- #define debug(format,msg...) (void *)(0)
- #endif
- #define dbgi(name,i) debug("in %s ,%s is %d\n",__func__,name,i)
- //打开函数,这个 函数里面我们需要获得sem
- static int led_open0(struct inode * nodep,struct file *filep)
- {
- down(&sem[0]);
- dbgi("filep->private_data",0);
- filep->private_data=0;
- return 0;
- }
- static int led_open1(struct inode * nodep,struct file *filep)
- {
- down(&sem[1]);
- dbgi("filep->private_data",1);
- filep->private_data=1;
- return 0;
- }
- static int led_open2(struct inode * nodep,struct file *filep)
- {
- down(&sem[2]);
- dbgi("filep->private_data",2);
- filep->private_data=2;
- return 0;
- }
- static int led_open3(struct inode * nodep,struct file *filep)
- {
- down(&sem[3]);
- dbgi("filep->private_data",3);
- filep->private_data=3;
- return 0;
- }
- //关闭函数
- static int led_release(struct inode *nodep,struct file *filep)
- {
- int i=filep->private_data;
- dbgi("filep->private_data",i);
- i=(i<=3 && i>=0?i:0);
- up(&sem[i]);
- return 0;
- }
- //ioctrl函数
- static int led_ioctl(struct inode * nodep,struct file *filep,unsigned int cmd ,long args)
- {
- return 0;
- }
- static void led_display(int ledno,int status)
- {
- s3c2410_gpio_setpin(pin(ledno),status);
- debug("in %s,ledno=%d,ledstatus=%d\n",__func__,ledno,status);
- return;
- }
- //
- static int led_write(struct file * filep,char * __user buff,size_t count, loff_t *offt)
- {
- int i=filep->private_data;
-
- char led_status[6];
- int cmd;
- dbgi("before i =(i<=3 && i>=0 ? i: 0),i=",i);
- i =(i<=3 && i>=0 ? i: 0);
- dbgi("after i =(i<=3 && i>=0 ? i: 0),i=",i);
- copy_from_user(led_status,buff,count);
- if(led_status[0]=='1' || led_status[0]==1)
- cmd=LED_ON;
- else
- cmd=LED_OFF;
-
- led_display(i,cmd);
- return 0;
- }
- ////
- static void __init led_init()
- {
- int i=4;
- for(i=0;i<=3;i++)
- {
- misc_register(&led_dev[i]);
- init_MUTEX(&sem[i]);
- }
- }
- static void __exit led_exit()
- { int i=4;
- for(i=0;i<=3;i++)
- misc_deregister(&led_dev[i]);
- }
- MODULE_AUTHOR("keytounix");
- MODULE_LICENSE("GPL");
- MODULE_DESCRIPTION("driver leds for TQ2440");
- module_init(led_init);
- module_exit(led_exit);
二、Makefile
- TARGET=led
- KERNEL=2.6.32
- CC=arm-linux-gcc -w
- obj-m :=$(TARGET).o
- KERNELDIR :=/kernel/linux-$(KERNEL)
- default:
- make -C $(KERNELDIR) M=$(shell pwd) modules
三、test code
- //arm-linux-gcc -marcharmv4t t.c -o t
- //#insmod led.ko
- //#mdev -s
- //#./t /dev/ledx 1or0
- #include <stdio.h>
- #include <stdlib.h>
- #include <fcntl.h>
- #include <unistd.h>
- int main(int argn,char*argv[])
- {
- int fd=open(argv[1],O_WRONLY,0640);
- int w_size=write(fd,argv[2],sizeof(argv[2]));
- close(fd);
- return 0;
- }
阅读(2443) | 评论(0) | 转发(0) |