首先贴上代码:

字符设备驱动代码:

/**
 *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的更多相关文章

  1. 嵌入式Linux驱动学习之路(十八)LCD驱动

    驱动代码: /************************************************************************* > File Name: lcd ...

  2. 嵌入式Linux驱动学习之路(十五)按键驱动-定时器防抖

    在之前的定时器驱动程序中,我们发现在连续按下按键的时候,正常情况下应该是一次按下对应一次松开.而程序有时候会显示是两次按下,一次松开.这个问题是因为在按下的时候,因为是机械按键,所以电压信号会产生一定 ...

  3. 嵌入式Linux驱动学习之路(十四)按键驱动-同步、互斥、阻塞

    目的:同一个时刻,只能有一个应用程序打开我们的驱动程序. ①原子操作: v = ATOMIC_INIT( i )  定义原子变量v并初始化为i atomic_read(v)        返回原子变量 ...

  4. 嵌入式Linux驱动学习之路(十二)按键驱动-poll机制

    实现的功能是在读取按键信息的时候,如果没有产生按键,则程序休眠在read函数中,利用poll机制,可以在没有退出的情况下让程序自动退出. 下面的程序就是在读取按键信息的时候,如果5000ms内没有按键 ...

  5. 嵌入式Linux驱动学习之路(十九)触摸屏驱动、tslib测试

    触摸屏使用流程: 1. 按下产生中断. 2.在中断处理程序中启动AD转换XY坐标. 3.AD转换结束并产生AD中断. 4. 在AD的中断处理函数中上报信息,启动定时器. 5. 定时器时间到后进入中断, ...

  6. Linux内核分析(五)----字符设备驱动实现

    原文:Linux内核分析(五)----字符设备驱动实现 Linux内核分析(五) 昨天我们对linux内核的子系统进行简单的认识,今天我们正式进入驱动的开发,我们今后的学习为了避免大家没有硬件的缺陷, ...

  7. 嵌入式Linux驱动学习之路(十六)输入子系统

    以前写的一些输入设备的驱动都是采用字符设备处理的.问题由此而来,Linux开源社区的大神们看到了这大量输入设备如此分散不堪,有木有可以实现一种机制,可以对分散的.不同类别的输入设备进行统一的驱动,所以 ...

  8. 嵌入式linux的学习之路[转]

    我认为的一条学习嵌入式Linux的路: 1)学习 Linux系统安装. 常用命令.应用程序安装. 2) 学习 Linux 下的 C 编程.这本书必学<UNIX 环境高级编程>.<UN ...

  9. Linux内核驱动学习(四)Platform设备驱动模型

    Linux platform设备驱动模型 文章目录 Linux platform设备驱动模型 前言 框架 设备与驱动的分离 设备(device) 驱动(driver) 匹配(match) 参考 前言 ...

随机推荐

  1. 用JSON.parse和eval出现的问题

    json格式非常受欢迎,而解析json的方式通常用JSON.parse()但是eval()方法也可以解析,这两者之间有什么区别呢? JSON.parse()之可以解析json格式的数据,并且会对要解析 ...

  2. ArcGIS JS 学习笔记2 实现仿百度的拖拽画圆

    一.前言 吐槽一下,百度在国内除了百度地图是良心产品外,其他的真的不敢恭维.在上一篇笔记里,我已经实现了自定义的地图测量模块.在百度地图里面(其他地图)都有一个周边搜索的功能,拖拽画一个圆,然后以圆半 ...

  3. Office 365 - SharePoint 2013 Online 中创建母版页

    1.登陆SharePoint Online站点,点击右上角的设置按钮,如下图: 2.点击进入网站设置,到下面两个地方开启SharePoint Server 发布基础架构: 网站集管理 – 网站集功能 ...

  4. spring理解

    Struts与Hibernate可以做什么事? Struts,Mvc中控制层解决方案,可以进行请求数据自动封装.类型转换.文件上传.效验… Hibernate,持久层的解决方案:可以做到,把对象保存到 ...

  5. nginx反向代理配置及优化

    nginx反向代理配置及优化前言: 由于服务器apache抗不住目前的并发.加上前端squid配置后,问题依然无法解决.而页面程序大部分是动态.无法使用fastcgi来处理.因此想使用nginx做为反 ...

  6. CATransform3D方法汇总

    CATransform3D三维变换 struct CATransform3D { CGFloat m11, m12, m13, m14; CGFloat m21, m22, m23, m24; CGF ...

  7. Xcode常用快捷键的使用

    熟练使用Xcode的一些快捷方式,会大大加快项目开发的速度.

  8. iOS Xcode编译报错问题解决办法汇总

    1. 编译出现错误:linker command failed with exit code 1 第一种方法:找到Build settings->Linking->Other Linker ...

  9. 1.2 《硬啃设计模式》 第2章 学习设计模式需掌握的UML知识

    要看懂设计模式,你需要懂类图(Class Diagram),也需要懂一点对象图(Object Diagram),下面介绍一些UML的必要知识,以便你学习设计模式. 属性.操作 下图简单介绍类的属性和操 ...

  10. 利用webview实现在andorid中嵌入swf

    项目背景是这样的,一套系统有三个客户端分别是网页,flex和android,现在已经在flex上面做好了一个在线客户视频聊天系统,然后在这个基础上修改打包成了SWF,放在网页上面使用效果不错,但是利用 ...