mini2440之Linux驱动学习_2_字符设备学习

今天开始学习字符设备驱动。学习这个分为两个部分,字符设备的使用和字符设备的编写

第一部分:字符设备的使用

 1.使用字符设备,先编写Makefile

object -m := memdev.o

KDIR := /需要编写到内核的内核路径

all:

       make -C $(KDIR) M=$(PWD) modules CROSS_COMPILE=arm-linux- ARCH=arm

2.make生成memdev.ko

安装字符设备

insmod memdev.ko

然后查看设备号

创建字符设备文件

mknod /dev/文件名 c 主设备号 次设备号

3.应用层程序,可以调用open函数直接打开创建的字符设备设备文件,并且可以用其他函数进行操作。

第二部分:字符设备的编写

1.编写内核模块:

#include<linux/module.h>

#include<linux/init.h>

int memdev_init()

{

    return 0;

}

void memdev_exit()

{

 

}

module_init(memdev_init);

module_exit(memdev_exit);

2.驱动初始化

在模块的初始化函数中。

(1)分配cdev。

静态分配:struct cdev mdev

动态分配:mdev = cdev_alloc()

(2)初始化cdev,用cdev_init

这个函数的原型可以在Linux内核中直接复制

static const struct file_operations mem_fops =
{
  .llseek = mem_llseek,
  .read = mem_read,
  .write = mem_write,
  .open = mem_open,
  .release = mem_release,
};

cdev_init(&cdev, &mem_fops);

(3)注册cdev,用cdev_add

这里面用到了设备号

设备号的分配有两种:

静态分配:自己直接定义一个设备号,然后用register_chrdev_region( 0, 2, "memdev");申请设备号

动态分配:alloc_chrdev_region(&devno, 0, 2, "memdev");

  alloc_chrdev_region(&devno, 0, 2, "memdev");
  cdev_add(&cdev, devno, 2);

3.实现设配操作

函数原型在内核中可以直接找到。

先将五个函数的原型进行修改成5个函数。

然后对每一个进行编写。

**************************************************************************************************************\

打开函数的实现:

int mem_open(struct inode *inode, struct file *filp)
{
  
}

(1)先打开硬件(这次是虚拟的所以省略)

(2)提取次设备号,次设备号在inode中

         int num=MINOR(inode->i_rdev)

(3)把设备的寄存器的基地址保存在struct file的private_data这个成员中,这里用数组来表示寄存器

       int dev1_regs[5];

       int dev2_regs[5];

       if(num == 0)

            file->private_data = dev1_regs;

       if(num == 1)

           file->private_data = dev1_regs;

       return 0;

**************************************************************************************

关闭函数的实现:

因为是虚拟的所以只需要返回就可以了。

/*文件释放函数*/
int mem_release(struct inode *inode, struct file *filp)
{
  return 0;
}


******************************************************************************************

读函数的实现:

(1)从struct file中取出寄存器的基地址。

  int *register_addr = filp->private_data; /*获取设备的寄存器基地址*/

(2)通过copy_form_user,将从设备中读到的数据返回给应用程序

copy_to_user(buf,register_addr+ (*ppos/*偏移*/),size/*大小*/)

(3)收尾

将读写指针修改为刚才读到的位置

file->f_pos += size;

*********************************************************************

写函数

写和读类似

(1)从struct file中取出寄存器的基地址。

  int *register_addr = filp->private_data; /*获取设备的寄存器基地址*/

(2)通过copy_from_user,将从设备中读到的数据返回给应用程序

copy_from_user(register_addr + p, buf, count))

(3)收尾

将读写指针修改为刚才读到的位置

file->f_pos += size;

*************************************************************************

偏移函数:

switch(whence) {
      case SEEK_SET:
        newpos = offset;
        break;

      case SEEK_CUR:
        newpos = filp->f_pos + offset;
        break;

      case SEEK_END:
        newpos = 5*sizeof(int)-1 + offset;
        break;

      default:
        return -EINVAL;
    }
    if ((newpos<0) || (newpos>5*sizeof(int)))
        return -EINVAL;
        
    filp->f_pos = newpos;

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值