首先贴上代码:

字符设备驱动代码:

/**
 *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. Android 视频播放器,在线播放

    1. Bilibili https://github.com/Bilibili/ijkplayer 1.测试的时候总是崩溃,不知道是我不会用还是怎么回事. 2016-04-15 2.AndroidVi ...

  2. Android java传递int类型数据给C

    本文根据<Android jni简便开发流程>中的开发流程来实现一个java传递int类型数据给C 新建项目,进行简单的布局 <LinearLayout xmlns:android= ...

  3. Facebook开源动画库 POP-POPDecayAnimation运用

    关于POPDecayAnimation的介绍先引用别人写的一些内容,基本上把它的一些注意点都说明了: Decay Animation 就是 POP 提供的另外一个非常特别的动画,他实现了一个衰减的效果 ...

  4. 深入.net(数据类型)

    C#究竟为我们提供了哪些“数据类型”供我们使用?这些类型有什么样的“特征”? 数据类型的分类: --- 数据类型是存放数据的容器.那么我们就以它们“存放数据的方式”分类! 1.值类型:变量中直接存放着 ...

  5. OC字符串NSString

    ========================== 面向对象编程进阶和字符串 ========================== Δ一.类的设计模式—单例 [单例]程序允许过程中,有且仅有一块内存 ...

  6. Swift开发第十篇——可变参数函数&初始化方法顺序

    本篇分为两部分: 一.Swift中的可变参数函数 二.初始化方法的顺序 一.Swift中的可变参数函数 可变参数函数指的是可以接受任意多个参数的函数,在 OC 中,拼接字符串的函数就属于可变参数函数 ...

  7. django tmeplate 循环基数

    {% for item in item_list %} {{ forloop.counter }} {# starting index 1 #} {{ forloop.counter0 }} {# s ...

  8. 使用getopts处理shell中的输入参数

    在编写shell脚本中,经常要处理一些输入参数,在使用过程中发现getopts更加方便,能够很好的处理用户输入的参数和参数值.   getopts用于处理用户输入参数,举例说明使用方法: while ...

  9. Review 代码

    最近需要 Review 代码,学习了<代码整洁之道>.<代码质量>等书籍. 把对这些代码之道的学习心得整理成文

  10. Mysql hql字符串字段中是否包含某个字符串,用 find_in_set

    有这样一个需求,在Mysql数据库字符串字段(权限)中,有范围在 1 到 N 之间代表不同权限的值,分别被','分开,现在要取出具有某权限的所有成员列表. 创建表: 1 CREATE TABLE us ...