Chinaunix首页 | 论坛 | 博客
  • 博客访问: 702350
  • 博文数量: 152
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 1793
  • 用 户 组: 普通用户
  • 注册时间: 2013-09-12 12:26
个人简介

相信自己,只有不想做的,没有做不到的。

文章分类

全部博文(152)

文章存档

2021年(1)

2015年(2)

2014年(74)

2013年(75)

分类: 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;

*******************************************

 

阅读(976) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~