首先贴上代码:

字符设备驱动代码:

/**
 *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. ionic rang在弹出modal中不可拖拽的问题

  2. SharePoint Error - The current user is not an SharePoint Server farm administrator

    错误截图 错误日志 位置:C:\Program Files\Common Files\microsoft shared\Web Server Extensions\15\LOGS 主要错误 The c ...

  3. Lock同步锁--线程同步

    Lock-同步锁 Lock是java5提供的一个强大的线程同步机制--通过显示定义同步锁对象来实现同步.Lock可以显示的加锁.解锁.每次只能有一个线程对lock对象加锁. Lock有ReadLock ...

  4. JNI在C 和 C++ 函数实现的不同

    在C中,JNI 函数调用由“(*env)->”作前缀,目的是为了取出函数指针所引用的值. 在 C++ 中,JNIEnv 类拥有处理函数指针查找的内联成员函数. 下面这两行代码访问同一函数,但每种 ...

  5. iOS中的UI

    • 不管你是学习android开发还是iOS开发• 都建议先学习UI,原因如下:UI是app的根基:⼀一个app应该是先有UI界⾯面,然后在UI的基础上增加实⽤用功能 UI相对简单易学:UI普遍是学 ...

  6. classpath: 和classpath*:的区别

    classpath本质是jvm的根路径,jvm获取资源都是从该根路径下找的,注意这个根路径是个逻辑路径,并不是磁盘路径.比如两个jar包的路径是/a/a.jar和/b/b.jar,但是用classpa ...

  7. Java高级编程之URL处理

    Java URL处理 URL(Uniform Resource Locator)中文名为统一资源定位符,有时也被俗称为网页地址.表示为互联网上的资源,如网页或者FTP地址. 本章节我们将介绍Java是 ...

  8. MongoDB学习——基础入门

    MongoDB--基础入门 MongoDB是目前比较流行的一种非关系型数据库(NoSql),他的优势这里不废话,我们关注怎么使用它. 安装 下载,首先肯定要去下载,我们去官网下载,在国内,可能没FQ可 ...

  9. sql server ,sql语句,练习笔记

    一.删除冗余记录 DELETE [学生表] WHERE id NOT IN (SELECT MIN(id) FROM [学生表] GROUP BY [学号],[姓名],[课程编号],[课程],[分数] ...

  10. mysql 触发器的创建 修改 删除

    //做一个简单的练习,创建一个简单的触发器 完成添加文章的时候,自动加上时间,默认作者 为 ‘日记本的回忆‘ show columns from test; //查看表结构 //查看已存在触发器 sh ...