嵌入式Linux驱动学习之路(十)字符设备驱动-my_led
首先贴上代码:
字符设备驱动代码:
/**
*file name: led.c
*/
#include <linux/sched.h>
#include <linux/signal.h>
#include <linux/spinlock.h>
#include <linux/errno.h>
#include <linux/random.h>
#include <linux/poll.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/wait.h>
#include <linux/mutex.h>
#include <linux/io.h> #include <linux/fs.h> static struct class *led_class; //创建类
static struct class_device *led_class_devs[]; //创建类对应的设备 1个总设备文件 3个单个灯的设备文件 volatile unsigned long *gpfcon = NULL;
volatile unsigned long *gpfdat = NULL; int led_open(struct inode *inode, struct file *fp)
{
int minor = MINOR(inode->i_rdev); //获取打开设备文件的次设备号
switch(minor)
{
case :
*gpfcon &= ~((0x3<<(*))|(0x3<<(*))|(0x3<<(*)));
*gpfcon |= (0x1<<(*))|(0x1<<(*))|(0x1<<(*));
break;
case :
*gpfcon &= ~(0x3<<(*));
*gpfcon |= (0x1<<(*));
break;
case :
*gpfcon &= ~(0x3<<(*));
*gpfcon |= (0x1<<(*));
break;
case :
*gpfcon &= ~(0x3<<(*));
*gpfcon |= (0x1<<(*));
break;
}
return ;
} ssize_t led_read(struct file *fp, char __user *c, size_t *t){
int minor = MINOR(fp->f_dentry->d_inode->i_rdev);
char leds_status;
switch(minor)
{
case 0:
leds_status = (~((*gpfdat & ((1<<4)|(1<<5)|(1<<6)))>>4))&0x7;
copy_to_user(buff,(const void *)&leds_status,1); //将数据从用户拷贝到内核空间
break;
case 1:
leds_status = (~(*gpfdat>>4))&0x1;
copy_to_user(buff,(const void *)&leds_status,1);
break;
case 2:
leds_status = (~(*gpfdat>>5))&0x1;
copy_to_user(buff,(const void *)&leds_status,1);
break;
case 3:
leds_status = (~(*gpfdat>>6))&0x1;
copy_to_user(buff,(const void *)&leds_status,1);
break;
}
} ssize_t led_write(struct file *fp, const char __user *buf, size_t count, loff_t *ppos){
int minor = MINOR(fp->f_dentry->d_inode->i_rdev);
int val;
copy_from_user(&val, buf, );
switch(minor)
{
case :
val &= 0x1;
*gpfdat &= ~((<<)|(<<)|(<<));
*gpfdat |= (val<<)|(val<<)|(val<<);
break;
case :
*gpfdat &= ~(<<);
*gpfdat |= (val&0x1)<<;
break; case :
*gpfdat &= ~(<<);
*gpfdat |= (val&0x1)<<;
break;
case :
*gpfdat &= ~(<<);
*gpfdat |= (val&0x1)<<;
break;
}
} struct file_operations led_fops={
.owner = THIS_MODULE,
.open = led_open,
.write = led_write, }; int major;
static int led_init(void)
{
int minor;
major = register_chrdev( ,"led_drv", &led_fops ); //当指定的设备号为0时,系统会自动生成一个设备号
led_class = class_create(THIS_MODULE, "my_leds");
if(IS_ERR(led_class))
return PTR_ERR(led_class); led_class_devs[] = class_device_create(led_class,NULL,MKDEV(major,),NULL,"my_leds"); //创建设备文件
if(unlikely(IS_ERR(led_class_devs)))
return PTR_ERR(led_class_devs);
for( minor=; minor<; minor++ )
{
led_class_devs[minor] = class_device_create(led_class,NULL,MKDEV(major,minor),NULL,"my_led%d",minor);
if(unlikely(IS_ERR(led_class_devs)))
return PTR_ERR(led_class_devs);
}
gpfcon = (volatile unsigned long *)ioremap(0x56000050,); //物理地址映射为虚拟地址
gpfdat = gpfcon + ; printk("led install Module\n"); return ;
} static void led_exit(void)
{
unregister_chrdev( major, "led_drv" );
class_device_unregister(led_class_devs[]); //注销设备文件
class_device_unregister(led_class_devs[]);
class_device_unregister(led_class_devs[]);
class_device_unregister(led_class_devs[]);
class_destroy(led_class); //销毁类
iounmap(gpfcon); //取消物理地址映射
printk("led Module exit\n");
} module_init(led_init);
module_exit(led_exit);
MODULE_LICENSE("GPL");
模块的Makefile:
obj-m:=led.o
KERNELDIR:=/home/jz2440/linux-2.6.22.6
PWD:=$(shell pwd)
default:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
clean:
rm -rf *.o *.mod.c *.mod.o *.ko *.symvers
测试文件:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h> int main( int argc, char **argv )
{
int fd;
int val = ;
if(argc != )
{
printf("please input righ data\n");
printf("eg:/dev/my_leds <on\"off>\n");
return ;
}
fd = open(argv[], O_RDWR);
if(fd<)
{
printf("open failed\n");
return ;
} if(strcmp(argv[],"on")==)
{
val = ;
}
else
{
val = ;
}
write(fd, &val, );
read(fd, &val,1);
printf("led status =%d\n",val);
return ; }
完
嵌入式Linux驱动学习之路(十)字符设备驱动-my_led的更多相关文章
- 嵌入式Linux驱动学习之路(十八)LCD驱动
驱动代码: /************************************************************************* > File Name: lcd ...
- 嵌入式Linux驱动学习之路(十五)按键驱动-定时器防抖
在之前的定时器驱动程序中,我们发现在连续按下按键的时候,正常情况下应该是一次按下对应一次松开.而程序有时候会显示是两次按下,一次松开.这个问题是因为在按下的时候,因为是机械按键,所以电压信号会产生一定 ...
- 嵌入式Linux驱动学习之路(十四)按键驱动-同步、互斥、阻塞
目的:同一个时刻,只能有一个应用程序打开我们的驱动程序. ①原子操作: v = ATOMIC_INIT( i ) 定义原子变量v并初始化为i atomic_read(v) 返回原子变量 ...
- 嵌入式Linux驱动学习之路(十二)按键驱动-poll机制
实现的功能是在读取按键信息的时候,如果没有产生按键,则程序休眠在read函数中,利用poll机制,可以在没有退出的情况下让程序自动退出. 下面的程序就是在读取按键信息的时候,如果5000ms内没有按键 ...
- 嵌入式Linux驱动学习之路(十九)触摸屏驱动、tslib测试
触摸屏使用流程: 1. 按下产生中断. 2.在中断处理程序中启动AD转换XY坐标. 3.AD转换结束并产生AD中断. 4. 在AD的中断处理函数中上报信息,启动定时器. 5. 定时器时间到后进入中断, ...
- Linux内核分析(五)----字符设备驱动实现
原文:Linux内核分析(五)----字符设备驱动实现 Linux内核分析(五) 昨天我们对linux内核的子系统进行简单的认识,今天我们正式进入驱动的开发,我们今后的学习为了避免大家没有硬件的缺陷, ...
- 嵌入式Linux驱动学习之路(十六)输入子系统
以前写的一些输入设备的驱动都是采用字符设备处理的.问题由此而来,Linux开源社区的大神们看到了这大量输入设备如此分散不堪,有木有可以实现一种机制,可以对分散的.不同类别的输入设备进行统一的驱动,所以 ...
- 嵌入式linux的学习之路[转]
我认为的一条学习嵌入式Linux的路: 1)学习 Linux系统安装. 常用命令.应用程序安装. 2) 学习 Linux 下的 C 编程.这本书必学<UNIX 环境高级编程>.<UN ...
- Linux内核驱动学习(四)Platform设备驱动模型
Linux platform设备驱动模型 文章目录 Linux platform设备驱动模型 前言 框架 设备与驱动的分离 设备(device) 驱动(driver) 匹配(match) 参考 前言 ...
随机推荐
- ReCap 360 photo照片建模技术的又一个例子
这是我做的又一个利用Autodesk ReCap 360 照片建模技术做的一个例子.你可以下载模型自己把玩,或者下载原始照片自己试一试. 拍摄工具: 小米手机 照片数量:约120张 后期处理工具: p ...
- IDA在内存中dump出android的Dex文件
转载自http://drops.wooyun.org/tips/6840 在现在的移动安全环境中,程序加壳已经成为家常便饭了,如果不会脱壳简直没法在破解界混的节奏.ZJDroid作为一种万能脱壳器是非 ...
- Xcode插件
Xcode插件-2016-03-10Xcode插件管理神器 —— Alcatraz 说明 Alcatraz是一个管理Xcode开源包的,你可以用它查找安装你想要的插件,模板以及配色方案,而你无需手动克 ...
- Android实现欢迎界面,点击进入应用
在主线程中开启一个新线程,每隔100ms检查一下时间是否到达自己预设的显示时间,到达则进入应用 实现屏幕的触摸事件,当触摸的时候,进入应用 package com.example.administra ...
- 使用 PHPMailer 发送邮件
转载 http://blog.csdn.net/liruxing1715/article/details/7914974 PHPMailer 的官方网站:http://phpmailer.worxwa ...
- 机器数据的价值 - Web 访问日志和数据库审计日志
计算机数据 大量的数据流,不断增长的来源,蕴含着巨大的价值 在 Splunk,我们大量谈及计算机数据.这些数据是指在数据中心.“物联网”和互联设备世界中运行的所有系统产生的数据.其中包括支撑组织的应用 ...
- SQL Tune Report–sqltrpt.sql
ORACLE 10g提供了一个脚本sqltrpt.sql用来查询最耗费资源的SQL语句,其输出的结果分为两部分: 15 Most expensive SQL in the cursor cache 1 ...
- 十五天精通WCF——第十一天 如何对wcf进行全程监控
说点题外话,我们在玩asp.net的时候,都知道有一个叼毛玩意叫做“生命周期”,我们可以用httpmodule在先于页面的page_load中 做一些拦截,这样做的好处有很多,比如记录日志,参数过滤, ...
- Sql Server之旅——第十一站 简单说说sqlserver的执行计划
我们知道sql在底层的执行给我们上层人员开了一个窗口,那就是执行计划,有了执行计划之后,我们就清楚了那些烂sql是怎么执行的,这样 就可以方便的找到sql的缺陷和优化点. 一:执行计划生成过程 说到执 ...
- SQL Server调优系列进阶篇(如何维护数据库索引)
前言 上一篇我们研究了如何利用索引在数据库里面调优,简要的介绍了索引的原理,更重要的分析了如何选择索引以及索引的利弊项,有兴趣的可以点击查看. 本篇延续上一篇的内容,继续分析索引这块,侧重索引项的日常 ...