// 申请IO资源
int gpio_request(unsigned gpio, const char *label);
// 释放IO资源
void gpio_free(unsigned gpio);
// 将IO引脚配置为输入
int gpio_direction_input(unsigned gpio);
// 将IO引脚配置为输出并设置引脚电平
int gpio_direction_output(unsigned gpio, int value);
// 读取引脚电平
int gpio_get_value(unsigned gpio);
// 设置引脚电平
void gpio_set_value(unsigned gpio, int value);

// 应用层的open/close/read/write/ioctl/llseek会调用以下对应的函数
struct file_operations {
int (*open) (struct inode *, struct file *);
int (*release) (struct inode *, struct file *);
ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);
loff_t (*llseek) (struct file *, loff_t, int);
};

//此命令用于应用和驱动之间的ioctl通信

// 参数1--表示一个魔幻数--用一个字符表示
 //参数2--区分不同命令的整数
 //参数3--传递的数据的类型

// 自动生成一个普通的命令号
_IO(type,nr)
// 自动生成一个带可读参数的命令号
_IOR(type,nr,size)
// 自动生成一个带可写参数的命令号
_IOW(type,nr,size)
// 自动生成一个带可读写参数的命令号
_IOWR(type,nr,size)
// 例:
#define LED_ON_IOW('L', 0x90, int)
#define LED_OFF_IOW('L', 0x91, int)
#define LED_ON_ALL_IO('L', 0x92)
#define LED_OFF_ALL_IO('L', 0x93)

// 1,向系统申请设备号
//参数1:需要申请的主设备号,次设备号默认为0---如果参数1大于0表示静态指定,等于由系统分配
//参数2:用于描述设备信息--自定义--会显示在/proc/devices
//参数3:文件操作对象,为用户提供文件IO操作集合
//返回值:错误返回负数,成功返回0
static inline int register_chrdev(unsigned int major, const char *name,
  const struct file_operations *fops);
// 释放设备号
static inline void unregister_chrdev(unsigned int major, const char *name);

// 在/sys/class目录下创建一个目录,目录名是name指定的
// 参数1:THIS_MODULE
// 参数2:设备名
// 返回值:class指针
struct class *class_create(struct module *owner, const char *name);

// 删除class指针指向的目录
// 参数:class指针
void class_destroy(struct class *cls);

// 在class指针指向的目录下再创建一个目录
// 参数1:class指针
// 参数2:父对象,一般写NULL
// 参数3:设备号
// 参数4:私有数据,一般写NULL
// 参数5:/dev下的设备名,可变参数
// 返回值:device指针
struct device *device_create(struct class *cls, struct device *parent, dev_t devt, void *drvdata, const char *fmt, ...);

// 删除device_create创建的目录
// 参数:class指针

void device_destroy(struct class *cls, dev_t devt);

led_drv.c

#include <linux/module.h>
#include <linux/init.h> #include <linux/fs.h>
#include <linux/gpio.h>
#include <linux/device.h>
#include <linux/slab.h> #include <asm/ioctl.h> //根据参数由内核生成一个唯一的命令号供ioctl使用
#define LED_ON _IOW('L', 0x90, int)
#define LED_OFF _IOW('L', 0x91, int)
#define LED_ON_ALL _IO('L', 0x92)
#define LED_OFF_ALL _IO('L', 0x93) struct samsung
{
int major;
struct class *cls;
struct device *dev;
}; static struct samsung *led_dev; static int led_open(struct inode *inode, struct file *filp)
{
int ret; printk(KERN_INFO "^_^ %s\n", __FUNCTION__); //申请IO资源,并起名为led0
ret = gpio_request(EXYNOS4_GPL2(), "led0");
if (ret < )
{
printk("gpio_request fail!\n");
return -EBUSY;
} //将IO口配置为输出并设置为低电平
gpio_direction_output(EXYNOS4_GPL2(), ); ret = gpio_request(EXYNOS4_GPK1(), "led1");
if (ret < )
{
printk("gpio_request fail!\n");
return -EBUSY;
}
gpio_direction_output(EXYNOS4_GPK1(), ); return ;
}
static int led_close(struct inode *inode, struct file *filp)
{
printk(KERN_INFO "^_^ %s\n", __FUNCTION__); gpio_direction_output(EXYNOS4_GPL2(), );
//释放IO口资源
gpio_free(EXYNOS4_GPL2()); gpio_direction_output(EXYNOS4_GPK1(), );
gpio_free(EXYNOS4_GPK1()); return ;
}
static ssize_t led_read(struct file *filp, char __user *buf, size_t len, loff_t *pos)
{
printk(KERN_INFO "^_^ %s\n", __FUNCTION__); return ;
}
static ssize_t led_write(struct file *filp, const char __user *buf, size_t len, loff_t *pos)
{
printk(KERN_INFO "^_^ %s\n", __FUNCTION__); return ;
}
static long led_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
printk(KERN_INFO "^_^ %s\n", __FUNCTION__); switch (cmd)
{
case LED_ON:
if (arg == )
gpio_direction_output(EXYNOS4_GPL2(), );
else
gpio_direction_output(EXYNOS4_GPK1(), );
break; case LED_OFF:
if (arg == )
gpio_direction_output(EXYNOS4_GPL2(), );
else
gpio_direction_output(EXYNOS4_GPK1(), );
break; case LED_ON_ALL:
gpio_direction_output(EXYNOS4_GPL2(), );
gpio_direction_output(EXYNOS4_GPK1(), );
break; case LED_OFF_ALL:
gpio_direction_output(EXYNOS4_GPL2(), );
gpio_direction_output(EXYNOS4_GPK1(), );
break; default:
printk(KERN_ERR "cmd is error!\n");
break;
} return ;
} struct file_operations led_fops =
{
.open = led_open,
.release = led_close,
.read = led_read,
.write = led_write,
.unlocked_ioctl = led_ioctl,
}; static int __init led_init(void)
{
int ret; printk(KERN_INFO "^_^ %s\n", __FUNCTION__); //向内核申请内存
led_dev = kmalloc(sizeof(struct samsung), GFP_KERNEL);
if (led_dev == NULL)
{
printk("kmalloc err!\n");
return -ENOMEM;
} //申请设备号
ret = register_chrdev(, "led", &led_fops);
if (ret < )
{
printk(KERN_ERR "register_chrdev error!\n");
goto major_err;;
}
led_dev->major = ret;
printk(KERN_INFO "major = %d\n", led_dev->major); //在/sys/class目录下创建一个名为"led"的目录
led_dev->cls = class_create(THIS_MODULE, "led");
if (led_dev->cls == NULL)
{
printk(KERN_ERR "class_create error!\n");
ret = -EEXIST;
goto class_err;
} //在class指针指向的目录下再创建一个名为"led0"的目录
led_dev->dev= device_create(led_dev->cls, NULL, MKDEV(led_dev->major, ), NULL, "led0");
if (led_dev->dev == NULL)
{
printk(KERN_ERR "device_create error!\n");
ret = -EEXIST;
goto device_err;
} return ; device_err:
class_destroy(led_dev->cls);
class_err:
unregister_chrdev(led_dev->major, "led");
major_err:
kfree(led_dev); return ret;
} static void __exit led_exit(void)
{
printk(KERN_INFO "^_^ %s\n", __FUNCTION__); //删除device_create创建的目录
device_destroy(led_dev->cls, MKDEV(led_dev->major, ));
//删除class指针指向的目录
class_destroy(led_dev->cls);
//释放设备号
unregister_chrdev(led_dev->major, "led");
//释放内存
kfree(led_dev);
} module_init(led_init);
module_exit(led_exit); MODULE_LICENSE("GPL");
MODULE_AUTHOR("Aaron Lee");

led_app.c

#include <stdio.h>

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h> #define LED_ON _IOW('L', 0x90, int)
#define LED_OFF _IOW('L', 0x91, int)
#define LED_ON_ALL _IO('L', 0x92)
#define LED_OFF_ALL _IO('L', 0x93) int main(void)
{
int fd; fd = open("/dev/led0", O_RDWR); while()
{
ioctl(fd,LED_ON,);
sleep(); ioctl(fd,LED_OFF,);
sleep(); ioctl(fd,LED_ON,);
sleep(); ioctl(fd,LED_OFF,);
sleep(); ioctl(fd,LED_ON_ALL,);
sleep(); ioctl(fd,LED_OFF_ALL,);
sleep();
} return ;
}

Makefile文件请参照:http://www.cnblogs.com/lialong1st/p/7756677.html

Linux LED字符设备驱动的更多相关文章

  1. fl2440 platform总线led字符设备驱动

    首先需要知道的是,设备跟驱动是分开的.设备通过struct device来定义,也可以自己将结构体封装到自己定义的device结构体中: 例如:struct platform_device: 在inc ...

  2. Linux实现字符设备驱动的基础步骤

    Linux应用层想要操作kernel层的API,比方想操作相关GPIO或寄存器,能够通过写一个字符设备驱动来实现. 1.先在rootfs中的 /dev/ 下生成一个字符设备.注意主设备号 和 从设备号 ...

  3. linux driver ------ 字符设备驱动 之 “ 创建设备节点流程 ”

    在字符设备驱动开发的入门教程中,最常见的就是用device_create()函数来创建设备节点了,但是在之后阅读内核源码的过程中却很少见device_create()的踪影了,取而代之的是device ...

  4. linux学习--字符设备驱动

    目录 1.字符设备驱动抽象结构 2.设备号及设备节点 2.1 设备号分配与管理 2.2 设备节点的生成 3.打开设备文件 linux驱动有基本的接口进行注册和卸载,这里不再做详细说明,本文主要关注li ...

  5. Tiny6410 LED字符设备驱动

    1.查看用户手册 led1.led2.led3.led4 连接的分别是 GPK4.GPK5.GPK6.GPK7 2.查询6410芯片手册 下面还需要3个步骤: 1.设置GPIO为OUTPUT. 将GP ...

  6. LED字符设备驱动实例及测试代码

    驱动代码如下: #include <linux/kernel.h>//内核头文件 #include <linux/init.h>//__init等 #include <l ...

  7. Linux高级字符设备驱动

    转载:http://www.linuxidc.com/Linux/2012-05/60469p4.htm 1.什么是Poll方法,功能是什么? 2.Select系统调用(功能)      Select ...

  8. linux 高级字符设备驱动 ioctl操作介绍 例程分析实现【转】

    转自:http://my.oschina.net/u/274829/blog/285014 1,ioctl介绍 ioctl控制设备读写数据以及关闭等. 用户空间函数原型:int ioctl(int f ...

  9. Linux高级字符设备驱动 poll方法(select多路监控原理与实现)

    1.什么是Poll方法,功能是什么? 2.Select系统调用(功能)      Select系统调用用于多路监控,当没有一个文件满足要求时,select将阻塞调用进程.      int selec ...

随机推荐

  1. bootstrap重置校验方法

    $(function (){ $("select").change(function(){ $('#DepartForm').bootstrapValidator('resetFo ...

  2. mysql——主键自动增长&唯一索引

    首先说一下主键和唯一索引的区别 主键:一个数据库的一张表有且仅有一个主键,而且主键不能重复 唯一索引:一个数据库的一张表上唯一索引可以有多个,只是所在唯一索引上的值不能重复,这一点和主键一样 下面我们 ...

  3. oracle数据库插入优化

    通过程序要把1000万的数据插入到数据表中,刚开始每100条数据耗时50ms左右,但是越往后越慢,最慢到了十几秒的都有,真实好坑了. 于是在网上百度了一波,如何进行insert优化.倒是有了一点小小的 ...

  4. 转 IOS动态类型isKindOfClass, isMemberOfClass

    对象在运行时获取其类型的能力称为内省.内省可以有多种方法实现. 判断对象类型 -(BOOL) isKindOfClass: classObj判断是否是这个类或者这个类的子类的实例 -(BOOL) is ...

  5. Python正则表达式------进阶

    Python正则表达式 正则表达式是一个特殊的字符序列,它能帮助你方便的检查一个字符串是否与某种模式匹配. Python 自1.5版本起增加了re 模块,它提供 Perl 风格的正则表达式模式. re ...

  6. C#—序列化(Serialize)和反序列化(NonSerialize)

    (转自:http://www.cnblogs.com/Abel-Zhang/p/Serialize.html) 一.概述 序列化是把对象转变成流.相反的过程就是反序列化. 哪些场合用到这项技术呢? 1 ...

  7. MySQL index merge

    深入理解 index merge 是使用索引进行优化的重要基础之一. [ index merge]       当where谓词中存在多个条件(或者join)涉及到多个字段,它们之间进行 AND 或者 ...

  8. 使用ettercap构建arp欺骗构建

    0.准备: 安装:ettercap apt-get install cmake libncurses5-dev libssl-dev libpcap-dev libnet1-dev git clone ...

  9. linux文件组、权限等

    文件所有者.所在组合其他组  --改变用户所在组    组和在oa系统中的组差不多,用户代表的好像是个体,组有点像角色的意思.不过权限的话并不是个体从组中获得,组仅仅是一个机制,进行部分文件控制与共享 ...

  10. 关于HashMap,HashTable,HashSet浅析

    首先,最重要的,HashMap  作为一个我们使用非常多的集合.最常被大家认知的是,它是一个key-value形式存储数据的数据结构,可以实现快速的存,取操作.  关于HashMap的源码,我们截取一 ...