LED字符设备驱动实例及测试代码
驱动代码如下:
#include <linux/kernel.h>//内核头文件
#include <linux/init.h>//__init等
#include <linux/module.h>//模块加载的头文件
#include <linux/fs.h>//file_operations
#include <linux/errno.h>//错误状态常数
#include <linux/types.h>//size_t,ssize_t等 //--------------cdev----------------
#include <linux/cdev.h> //-------------class_create,device_create------
#include <linux/device.h> //--------------GPIO-----------------
#include <mach/gpio.h>
#include <plat/gpio-cfg.h>
#include <mach/regs-gpio.h> //-------CMD COMMAND----------------
#define LED1_ON 0x1
#define LED1_OFF 0x0 #define DEVICE_NAME "LED1" static int led1_gpios[]=
{
S5PV210_MP04(),
S5PV210_MP04(),
S5PV210_MP04(),
S5PV210_MP04()
}; #define LED1_NUM ARRAY_SIZE(led1_gpios) /*用udev机制自动添加设备节点*/
struct class *led1_class; /*设备结构体*/
struct led1_dev_t
{
struct cdev cdev;
}led1_dev; /*
// ------------------- READ ------------------------
ssize_t led1_read (struct file * file ,char * buf, size_t count, loff_t * f_ops)
{
return count;
} // ------------------- WRITE -----------------------
ssize_t led1_write (struct file * file ,const char * buf, size_t count, loff_t * f_ops)
{
return count;
}
// ------------------- OPEN ------------------------
ssize_t led1_open (struct inode * inode ,struct file * file)
{
return 0;
}
// ------------------- RELEASE/CLOSE ---------------
ssize_t led1_release (struct inode * inode ,struct file * file)
{
return 0;
}
// -------------------------------------------------
*/ // ------------------- IOCTL -----------------------
static int led1_ioctl (struct inode * inode ,struct file * file, unsigned int cmd, unsigned long arg)
{
if(arg > LED1_NUM)
{
printk("arg is %u ,led num is %d\n",arg,LED1_NUM);
printk("num is err!!\n");
return - EINVAL;
}
switch (cmd)
{
case LED1_ON:
{
/*code*/
gpio_set_value(led1_gpios[arg],);
printk("led1 is on!!\n");
break;
}
case LED1_OFF:
{
/*code*/
gpio_set_value(led1_gpios[arg],);
printk("led1 is off!!\n");
break;
}
default :
{
printk ("CMD err!!\n");
return - EINVAL;
}
}
return ; } struct file_operations led1_fops ={ .owner = THIS_MODULE,
// .open = led1_open,
// .read = led1_read,
// .write = led1_write,
.ioctl = led1_ioctl,
// .release = led1_release,
}; // ------------------- INIT ------------------------
static int __init led1_init(void)
{
printk("led num is : %d\n",LED1_NUM);
int i,ret;
for (i = ; i < LED1_NUM; i++)
{ /*
ret=gpio_request(led1_gpios[i],"LED1");
if(ret)//注意,是ret
{
printk("%s:request GPIO %d for LED1 failed,ret= %d\n",DEVICE_NAME,led1_gpios[i],ret);
return ret;
}
*/
s3c_gpio_cfgpin(led1_gpios[i],S3C_GPIO_SFN());
gpio_set_value(led1_gpios[i],);
} /*init cdev*/
cdev_init(&led1_dev.cdev,&led1_fops);
led1_dev.cdev.owner=THIS_MODULE; /*向系统动态申请未被占用的设备号*/
ret = alloc_chrdev_region(&led1_dev.cdev.dev,,,DEVICE_NAME);//int alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count,const char *name) if (ret)
{
printk("register failed\n");
return ret;
} /*添加字符设备*/
ret = cdev_add(&led1_dev.cdev, led1_dev.cdev.dev, );
if (ret)
{
printk("cdev add failed\n");
goto fail1;
}
/*udev机制可以自动添加设备节点,只需要添加xxx_class这个类,以及device_create()*/
led1_class = class_create(THIS_MODULE, "led1_class");/*在sys目录下创建xx_class这个类,/sys/class/~*/
if (IS_ERR(led1_class))
{
printk("class create failed\n");
goto fail2;
}
device_create(led1_class, NULL, led1_dev.cdev.dev, DEVICE_NAME, DEVICE_NAME);/*自动创建设备/dev/$DEVICE_NAME*/
return ret; fail2:
cdev_del(&led1_dev.cdev);
fail1:
unregister_chrdev_region(led1_dev.cdev.dev, );
return ret;
} static void __exit led1_exit(void)
{
int i;
/*
for (i = 0; i < LED1_NUM; i++)
{ gpio_free(led1_gpios[i]);
}
*/
device_destroy(led1_class, led1_dev.cdev.dev);
class_destroy(led1_class);
cdev_del(&led1_dev.cdev);
unregister_chrdev_region(led1_dev.cdev.dev, );
} module_init(led1_init);
module_exit(led1_exit); MODULE_LICENSE("GPL");
MODULE_AUTHOR("mhb@seu");
测试代码如下:
#include <stdio.h>
//#include "sys/types.h"
#include <sys/ioctl.h>
#include <stdlib.h>
#include <unistd.h>
//#include "termios.h"
//#include "sys/stat.h"
#include <fcntl.h> #define LED1_ON 0x1
#define LED1_OFF 0x0 main(int argc,char *argv[])
{
int fd; if ((fd=open("/dev/LED1",O_RDWR /*| O_NDELAY | O_NOCTTY*/)) < )
{
printf("Open Device failed.\r\n");
exit();
}
else
{
printf("Open Device successed.\r\n");
}
if (argc<)
{
/* code */
printf("Usage: %s <on|off num>\n",argv[]);
exit();
}
if(!strcmp(argv[],"on"))
{
printf("led1 will on!!\n");
printf("argv[2]=%d\n",atoi(argv[]));
if(ioctl(fd,LED1_ON,atoi(argv[]))<)
{
printf("ioctl err!!\n");
} }
if(!strcmp(argv[],"off"))
{
printf("led1 will off!!\n");
if(ioctl(fd,LED1_OFF,atoi(argv[]))<)
{
printf("ioctl err!!\n");
}
}
close(fd);
}
LED字符设备驱动实例及测试代码的更多相关文章
- fl2440 platform总线led字符设备驱动
首先需要知道的是,设备跟驱动是分开的.设备通过struct device来定义,也可以自己将结构体封装到自己定义的device结构体中: 例如:struct platform_device: 在inc ...
- Tiny6410 LED字符设备驱动
1.查看用户手册 led1.led2.led3.led4 连接的分别是 GPK4.GPK5.GPK6.GPK7 2.查询6410芯片手册 下面还需要3个步骤: 1.设置GPIO为OUTPUT. 将GP ...
- Linux字符设备驱动实例—globalmem驱动
1.globalmem虚拟设备实例 globalmem为“全局内存”的意思,在globalmem字符设备中会分配一片大小为GLOBALMEM_SIZE(4KB)的内存空间,并在驱动中提供对这片内存的读 ...
- Linux_2.6字符设备驱动实例
第一步:my74hc595.c #include <linux/module.h> //模块所需的大量符号和函数定义#include <linux/init.h> //指定初始 ...
- Linux LED字符设备驱动
// 申请IO资源 int gpio_request(unsigned gpio, const char *label); // 释放IO资源 void gpio_free(unsigned gpio ...
- 【转】linux设备驱动程序之简单字符设备驱动
原文网址:http://www.cnblogs.com/geneil/archive/2011/12/03/2272869.html 一.linux系统将设备分为3类:字符设备.块设备.网络设备.使用 ...
- 【Linux驱动】字符设备驱动
一.linux系统将设备分为3类:字符设备.块设备.网络设备.使用驱动程序: 1.字符设备:是指只能一个字节一个字节读写的设备,不能随机读取设备内存中的某一数据,读取数据需要按照先后数据.字符设备是面 ...
- arm-linux字符设备驱动开发之---简单字符设备驱动
一.linux系统将设备分为3类:字符设备.块设备.网络设备.使用驱动程序: 1.字符设备:是指只能一个字节一个字节读写的设备,不能随机读取设备内存中的某一数据,读取数据需要按照先后数据.字符设备是面 ...
- 谈谈Linux字符设备驱动的实现
@ 目录 字符设备驱动基础 申请设备号 创建设备节点 在驱动中实现操作方法 文件IO调用驱动中的操作 应用程序与驱动的数据交互 内核驱动如何控制外设 控制LED的简单驱动实例 驱动程序的改进 框架复盘 ...
随机推荐
- PDF转换成二进制字符串写入 HTTP 输出流
最近项目需要做电子签章,需要网页打开PDF签章后保存:正好复习哈二进制和流的转换: 文件转换成二进制字符串写入HTTP输出流 protected void Page_Load(object sende ...
- windows 7文件共享方法
现在家里有几台电脑是很常见的,把家里的几台电脑组成局域网,共享文件.联机游戏是非常有必要的,但是组建局域网又是很多朋友永远的痛,需要设置工作组.设置登录方式.打开服务等等,时常还会出点小问题而无法共享 ...
- Flume简介与使用(三)——Kafka Sink消费数据之Kafka安装
前面已经介绍了如何利用Thrift Source生产数据,今天介绍如何用Kafka Sink消费数据. 其实之前已经在Flume配置文件里设置了用Kafka Sink消费数据 agent1.sinks ...
- 带有可点击区域的图像映射:HTML <map> 标签
实例 带有可点击区域的图像映射: <img src="planets.jpg" border="0" usemap="#planetmap&qu ...
- Divide and conquer method
分治法是最广泛使用的算法设计方法之一,其基本思想:把大问题分解成一些较小的问题,然后由小问题的解方便地构造出大问题的解. 分治法说穿了就是把问题放小,如果被分的问题还是比较大,那么久继续分下去.为了能 ...
- 为ubuntu只带的network-manager添加latp/ipsec VPN
sudo apt-add-repository ppa:seriy-pr/network-manager-l2tp sudo apt-get update sudo apt-get install n ...
- JavaScript高级程序设计(第三版)学习笔记13、14章
第13章,事件 事件冒泡 IE的事件叫做事件冒泡:由具体到不具体 <!DOCTYPE html> <html> <head> <title>E ...
- angularjs的一些优化小技巧
尽可能少调用 ng-repeat ng-repeat默认会创建很多监听器,所以在数据量很大的时候,这个非常消耗页面性能,我觉的只有在当需要经常更新数据列表的时候才需要用ng-repeat,要不然放那么 ...
- foo,bar,baz
https://en.wikipedia.org/wiki/Foobar 原文: The terms foobar, foo, bar, baz and qux are sometimes used ...
- ASP.Net_入门准备
基础篇:(学习能力取决于你的基础扎不扎实) 第一步 掌握一门.NET面向对象语言,C#或VB.NET 我强烈反对在没系统学过一门面向对象(OO)语言的前提下去学ASP.NET. ASP.NET是一个全 ...