相信自己,只有不想做的,没有做不到的。
分类: LINUX
2013-09-24 20:13:42
LED驱动
#include
#include
#include
#include
#include
#include
#include
#include "led.h" //外部引用头文件包含
int led_major = 250;//主设备号
int led_minor = 0;//次设备号
int number_of_devices = 1; //申请设备个数
struct cdev cdev; //字符设备结构体
dev_t dev = 0;
struct led{
char action[5];
int nr;
};
unsigned long *gpg3con; //根据芯片手册定义管脚
unsigned long *gpg3dat;
static int led_open(struct inode *inode, struct file *file) //在Open函数中配置管脚
{
*gpg3con &= ~(0xffff);
*gpg3con |= (0x1111); //配置引脚为输出引脚
*gpg3dat = *gpg3dat & (~(0xf)); //全灭
return 0;
}
static int led_release(struct inode *inode, struct file *file)
{
return 0;
}
/*
ssize_t led_write (struct file *filp, const char *buf, size_t count, loff_t *f_pos)
{
if(strcmp(buf,"on") == 0)
{
*gpg3dat = (*gpg3dat & (~(0xf))) | 0xf;
}
if(strcmp(buf,"off") == 0)
{
*gpg3dat = *gpg3dat & (~(0xf));
}
*/
return 0;
}
long led_unlock_ioctl(struct file *file,unsigned int cmd,unsigned long arg)
{
switch(cmd)
{
case LEDON: //根据应用层ioctl(fd,cmd,arg),来配置相应的功能,根据自己的需求来做
writel(readl(gpg3dat) | 1 << arg,gpg3dat);
break;
case LEDOFF:
writel(readl(gpg3dat) | 1 << arg,gpg3dat);
break;
}
return 0;
}
struct file_operations led_fops = { //核心函数,led_fops对led等进行操作
.owner = THIS_MODULE,
.open = led_open,
.release = led_release,
.write = led_write,
.ioctl = led_unlock_ioctl ,
};
static void char_reg_setup_cdev(void)
{
int error,devno;
devno = MKDEV(led_major,led_minor);
cdev_init(&cdev,&led_fops); //字符设备初始化,获得led_fops的功能
cdev.owner = THIS_MODULE;
cdev.ops = &led_fops; 初始化ops
error = cdev_add(&cdev,devno,1); 加载设备
if (error)
printk (KERN_NOTICE "Error %d adding char_reg_setup_cdev", error);
}
static int __init led_init (void)
{
int result;
dev = MKDEV (led_major, led_minor); //获得设备号
result = register_chrdev_region (dev, number_of_devices, "leds"); //根据获得的设备号 注册设备号
if (result<0) {
printk (KERN_WARNING "hello: can't get major number %d\n", led_major);
return result;
}
char_reg_setup_cdev(); //注册设备 获得对设备操作函数fops
//根据芯片手册地址映射
gpg3con = ( unsigned long *)ioremap(0xE03001C0,16);
gpg3dat = gpg3con + 1;
printk (KERN_INFO "char device registered\n");
return 0;
}
static void __exit led_exit (void) //与init相反, 释放的顺序也要相反 例如 led_init 第一个是register_chrdev_region那么Led_exit最后一个unregister_chrdev_region
{
dev_t devno = MKDEV (led_major, led_minor);
iounmap(gpg3con);
cdev_del (&cdev);
unregister_chrdev_region (devno, number_of_devices);
}
module_init (led_init); //修饰led_init
module_exit (led_exit); //修饰led_exit
MODULE_LICENSE ("GPL"); //准许GPL协议
*************************************************************************************
led.h
#ifndef __LED_HHHHHH
#define __LED_HHHHHH
#define led1 _IO('L', 0) //arg = 0/1/2/3
#define led2 _IO('L', 1) //arg = 0/1/2/3
#define led3 _IO('L', 2) //arg = 0/1/2/3
#define led4 _IO('L', 3) //arg = 0/1/2/3
#endif
*************************************************************************************
测试程序
int main(int argc, const char *argv[])
{
int fd;
struct led leds;
char buf[1024];
char *p_action,*p_nr;
int i = 1;
fd = open("/dev/leds",O_RDWR);
if (fd < 0)
{
perror("open");
exit(1);
}
while(1)
{
ioctl(fd,LEDON,i);
usleep(100000);
ioctl(fd,LEDOFF,i);
usleep(100000);
if(i == 4)
i = 0;
#if 1
}
#endif
}
close(fd);
return 0;
*******************************************