// 申请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

  1. #include <linux/module.h>
  2. #include <linux/init.h>
  3.  
  4. #include <linux/fs.h>
  5. #include <linux/gpio.h>
  6. #include <linux/device.h>
  7. #include <linux/slab.h>
  8.  
  9. #include <asm/ioctl.h>
  10.  
  11. //根据参数由内核生成一个唯一的命令号供ioctl使用
  12. #define LED_ON _IOW('L', 0x90, int)
  13. #define LED_OFF _IOW('L', 0x91, int)
  14. #define LED_ON_ALL _IO('L', 0x92)
  15. #define LED_OFF_ALL _IO('L', 0x93)
  16.  
  17. struct samsung
  18. {
  19. int major;
  20. struct class *cls;
  21. struct device *dev;
  22. };
  23.  
  24. static struct samsung *led_dev;
  25.  
  26. static int led_open(struct inode *inode, struct file *filp)
  27. {
  28. int ret;
  29.  
  30. printk(KERN_INFO "^_^ %s\n", __FUNCTION__);
  31.  
  32. //申请IO资源,并起名为led0
  33. ret = gpio_request(EXYNOS4_GPL2(), "led0");
  34. if (ret < )
  35. {
  36. printk("gpio_request fail!\n");
  37. return -EBUSY;
  38. }
  39.  
  40. //将IO口配置为输出并设置为低电平
  41. gpio_direction_output(EXYNOS4_GPL2(), );
  42.  
  43. ret = gpio_request(EXYNOS4_GPK1(), "led1");
  44. if (ret < )
  45. {
  46. printk("gpio_request fail!\n");
  47. return -EBUSY;
  48. }
  49. gpio_direction_output(EXYNOS4_GPK1(), );
  50.  
  51. return ;
  52. }
  53. static int led_close(struct inode *inode, struct file *filp)
  54. {
  55. printk(KERN_INFO "^_^ %s\n", __FUNCTION__);
  56.  
  57. gpio_direction_output(EXYNOS4_GPL2(), );
  58. //释放IO口资源
  59. gpio_free(EXYNOS4_GPL2());
  60.  
  61. gpio_direction_output(EXYNOS4_GPK1(), );
  62. gpio_free(EXYNOS4_GPK1());
  63.  
  64. return ;
  65. }
  66. static ssize_t led_read(struct file *filp, char __user *buf, size_t len, loff_t *pos)
  67. {
  68. printk(KERN_INFO "^_^ %s\n", __FUNCTION__);
  69.  
  70. return ;
  71. }
  72. static ssize_t led_write(struct file *filp, const char __user *buf, size_t len, loff_t *pos)
  73. {
  74. printk(KERN_INFO "^_^ %s\n", __FUNCTION__);
  75.  
  76. return ;
  77. }
  78. static long led_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
  79. {
  80. printk(KERN_INFO "^_^ %s\n", __FUNCTION__);
  81.  
  82. switch (cmd)
  83. {
  84. case LED_ON:
  85. if (arg == )
  86. gpio_direction_output(EXYNOS4_GPL2(), );
  87. else
  88. gpio_direction_output(EXYNOS4_GPK1(), );
  89. break;
  90.  
  91. case LED_OFF:
  92. if (arg == )
  93. gpio_direction_output(EXYNOS4_GPL2(), );
  94. else
  95. gpio_direction_output(EXYNOS4_GPK1(), );
  96. break;
  97.  
  98. case LED_ON_ALL:
  99. gpio_direction_output(EXYNOS4_GPL2(), );
  100. gpio_direction_output(EXYNOS4_GPK1(), );
  101. break;
  102.  
  103. case LED_OFF_ALL:
  104. gpio_direction_output(EXYNOS4_GPL2(), );
  105. gpio_direction_output(EXYNOS4_GPK1(), );
  106. break;
  107.  
  108. default:
  109. printk(KERN_ERR "cmd is error!\n");
  110. break;
  111. }
  112.  
  113. return ;
  114. }
  115.  
  116. struct file_operations led_fops =
  117. {
  118. .open = led_open,
  119. .release = led_close,
  120. .read = led_read,
  121. .write = led_write,
  122. .unlocked_ioctl = led_ioctl,
  123. };
  124.  
  125. static int __init led_init(void)
  126. {
  127. int ret;
  128.  
  129. printk(KERN_INFO "^_^ %s\n", __FUNCTION__);
  130.  
  131. //向内核申请内存
  132. led_dev = kmalloc(sizeof(struct samsung), GFP_KERNEL);
  133. if (led_dev == NULL)
  134. {
  135. printk("kmalloc err!\n");
  136. return -ENOMEM;
  137. }
  138.  
  139. //申请设备号
  140. ret = register_chrdev(, "led", &led_fops);
  141. if (ret < )
  142. {
  143. printk(KERN_ERR "register_chrdev error!\n");
  144. goto major_err;;
  145. }
  146. led_dev->major = ret;
  147. printk(KERN_INFO "major = %d\n", led_dev->major);
  148.  
  149. //在/sys/class目录下创建一个名为"led"的目录
  150. led_dev->cls = class_create(THIS_MODULE, "led");
  151. if (led_dev->cls == NULL)
  152. {
  153. printk(KERN_ERR "class_create error!\n");
  154. ret = -EEXIST;
  155. goto class_err;
  156. }
  157.  
  158. //在class指针指向的目录下再创建一个名为"led0"的目录
  159. led_dev->dev= device_create(led_dev->cls, NULL, MKDEV(led_dev->major, ), NULL, "led0");
  160. if (led_dev->dev == NULL)
  161. {
  162. printk(KERN_ERR "device_create error!\n");
  163. ret = -EEXIST;
  164. goto device_err;
  165. }
  166.  
  167. return ;
  168.  
  169. device_err:
  170. class_destroy(led_dev->cls);
  171. class_err:
  172. unregister_chrdev(led_dev->major, "led");
  173. major_err:
  174. kfree(led_dev);
  175.  
  176. return ret;
  177. }
  178.  
  179. static void __exit led_exit(void)
  180. {
  181. printk(KERN_INFO "^_^ %s\n", __FUNCTION__);
  182.  
  183. //删除device_create创建的目录
  184. device_destroy(led_dev->cls, MKDEV(led_dev->major, ));
  185. //删除class指针指向的目录
  186. class_destroy(led_dev->cls);
  187. //释放设备号
  188. unregister_chrdev(led_dev->major, "led");
  189. //释放内存
  190. kfree(led_dev);
  191. }
  192.  
  193. module_init(led_init);
  194. module_exit(led_exit);
  195.  
  196. MODULE_LICENSE("GPL");
  197. MODULE_AUTHOR("Aaron Lee");

led_app.c

  1. #include <stdio.h>
  2.  
  3. #include <sys/types.h>
  4. #include <sys/stat.h>
  5. #include <fcntl.h>
  6. #include <sys/ioctl.h>
  7.  
  8. #define LED_ON _IOW('L', 0x90, int)
  9. #define LED_OFF _IOW('L', 0x91, int)
  10. #define LED_ON_ALL _IO('L', 0x92)
  11. #define LED_OFF_ALL _IO('L', 0x93)
  12.  
  13. int main(void)
  14. {
  15. int fd;
  16.  
  17. fd = open("/dev/led0", O_RDWR);
  18.  
  19. while()
  20. {
  21. ioctl(fd,LED_ON,);
  22. sleep();
  23.  
  24. ioctl(fd,LED_OFF,);
  25. sleep();
  26.  
  27. ioctl(fd,LED_ON,);
  28. sleep();
  29.  
  30. ioctl(fd,LED_OFF,);
  31. sleep();
  32.  
  33. ioctl(fd,LED_ON_ALL,);
  34. sleep();
  35.  
  36. ioctl(fd,LED_OFF_ALL,);
  37. sleep();
  38. }
  39.  
  40. return ;
  41. }

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. centos上mailx通过465端口发送邮件

    最近在看zabbix发送邮件的时候,发现自己的邮件总是无法发送,这里可能是外网防火墙禁止25端口,那么如何绕过25端口呢?  我使用的是163邮箱的TSL加密协议465端口 由于mailx基本配置很简 ...

  2. java官网下载

    安装版 http://javadl.oracle.com/webapps/download/AutoDL?BundleId=234471_96a7b8442fe848ef90c96a2fad6ed6d ...

  3. java父类调用被子类重写的方法

    [转][原文]  1.如果父类构造器调用了被子类重写的方法,且通过子类构造函数创建子类对象,调用了这个父类构造器(无论显示还是隐式),就会导致父类在构造时实际上调用的是子类覆盖的方法(你需要了解jav ...

  4. java类敏感词过滤类

    package com.fpx.pcs.prealert.process.service.impl; import java.util.HashMap;import java.util.HashSet ...

  5. SpringCloud之eureka服务注册和服务发现

    服务注册中心 :eureka-server 作用:服务注册中心提供服务注册功能 服务提供方:eureka-client 作用:注册服务到服务注册中心 服务注册中心 :eureka-server 创建 ...

  6. VUE 结合 vue-resource 进行ajax操作

    有意思的! 初始化需要ajax获取数据! 搜索商品需要ajax获取数据! 提交数据需要ajax传递数据! 有了 vue-resource ,操作挺方便的. 这是html <form class= ...

  7. mysql 出现Host 'localhost' is not allowed to connect to this MySQL server 错误

    MySql数据库:Host 'localhost' is not allowed to connect to this MySQL server 修改mysql的root密码后,出现Host 'loc ...

  8. Selenium with Python 008 - WebDriver 元素等待

    如今大多数Web应用程序使用Ajax技术,当浏览器在加载页面时,页面上的元素可能并不是同时被加载完成的,这给元素的定位增加了困难.如果因为在加载某个元素时延迟而造成ElementNotVisibleE ...

  9. git网站

    https://backlog.com/git-tutorial/cn/   ------------------------------------------------------------- ...

  10. 关于inline函数

    本文为大便一箩筐的原创内容,转载请注明出处,谢谢:http://www.cnblogs.com/dbylk/p/4975474.html 今天我在优化公司项目代码的过程中,借助了Intel的VTune ...