首先贴上代码:

字符设备驱动代码:

/**
 *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. DevExpress VCL 13.1.4支持Delphi /C++Builder XE5

    DevExpress VCL 13.1.4支持Delphi /C++Builder XE5 重大变化 ExpressLibrary dxHalfOfPi常数声明已经从cxGeometry单元移到了cx ...

  2. Android开发学习——搭建开发环境

    在学校开课学习了android的一些简单的UI组件,布局,四大组件学习了2个,数据存储及网络通信,都是一些简单的概念,入门而已.许多东西需要自己去学习. 学习一下 Android开发环境的搭建,两种方 ...

  3. PULL解析XML的运行机制详解

    PULL解析简单易上手,基本上看一遍,基本上就会解析啦,但总是感觉对PULL解析的运行机制不是很了解,就总结了以下事件驱动到底是怎么执行的.. PULL: Android内置了PULL解析器.PULL ...

  4. 如何让光标处于EditText的末尾

    经测试发现,如果EditText预先有内容,光标自然会在文字的末尾 . 但是如果预先内容为空,然后设置好内容,这种情况下光标自然会在文字的开头,所以这种情况下可以这样做让光标位于末尾: editTex ...

  5. Android 网络图片查看器

    今天来实现一下android下的一款简单的网络图片查看器 界面如下: 代码如下: <LinearLayout xmlns:android="http://schemas.android ...

  6. 在iOS开发过程中你遇到这个问题了么?

    1.问题:加载UIWebView底部有黑色边框问题. 设置UIWebView opaque为NO,然后设置其背景色为clearColor. 2.问题:iPhone真机输出[UIScreen mainS ...

  7. 修改mac host

    /etc/hosts 把host 复制到桌面  修改  然后  替换原来的

  8. [Android]proguard重新编译和如何不混淆第三方jar包

    转载自:http://glblong.blog.51cto.com/3058613/1536516 一.ant安装.环境变量配置及验证 (一)安装ant 到官方主页http://ant.apache. ...

  9. js 判断多个一样的name

    var items = document.getElementsByName("spec_spec_1[]"); alert(items.length); for (i = 0; ...

  10. nav布局 在线演示 DIVCSS5

    <!doctype html> nav布局 在线演示 DIVCSS5 传统 div ul li布局导航条效果 网站首页 HTML教程 HTML入门 HTML5教程 CSS教程 CSS入门 ...