字符驱动入门,FL2440-LED驱动

这篇博客详细介绍了Linux字符设备驱动的步骤,特别是针对FL2440开发板的LED驱动。内容涵盖了设备初始化、字符设备主次设备号的注册、cdev结构体的分配与初始化、主次设备号的绑定及注册,以及硬件初始化。通过示例代码解析了如何使用register_chrdev_region()、alloc_chrdev_region()动态申请主次设备号,并展示了如何创建和释放设备节点。最后,博主提供了完整的LED驱动代码及测试用例。
摘要由CSDN通过智能技术生成

Linux内核里,绝大部分的设备都是字符设备,所写的驱动99%也都是处理字符设备。

一、字符设备驱动

字符设备的驱动大致步骤:

1、相应的设备初始化(根据开发板的原理图以及芯片datasheet配置引脚等)-->

2、注册字符设备主次设备号[register_chrdev_region()或alloc_chrdev_region()]-->

3、分配字符结构体[struct cdev *cdev_alloc(void)或者struct cdev led_cdev;]-->

4、初始化字符设备结构体,绑定fops到cdev结构体中[void cdev_init(struct cdev *cdev, struct file_operations *fops);]-->

5、绑定主次设备号,并注册给Linux内核[int cdev_add(struct cdev *p, dev_t dev, unsigned count);

3、4、5、步骤字符设备的注册

相应的设备初始化会根据开发板需要驱动的模块原理图芯片datasheet的不同会改变,而后面的步骤一般都基本上一样,所以相应的设备初始化留到最后来说

 

2、注册字符设备主次设备号:

内核提供了三个函数来注册一组字符设备编号,这三个函数分别是 register_chrdev_region()alloc_chrdev_region() 和 register_chrdev()

register_chrdev(unsigned int major, const char *name,const struct file_operations *fops);这个函数是linux版本2.4之前的注册方式:

(1)确定一个主设备号,如果major=0,则会自动分配设备号

(2)构造一个file_operations结构体, 然后放在chrdevs数组中

(3)注册:register_chrdev,cat /proc/devices查看内核中已经注册过的字符设备驱动(和块设备驱动),注意这里并不是驱动文件设备节点!

 

静态设定主次设备号

int register_chrdev_region(dev_t first, unsigned int count, char *name);

第一个参数first,是你要分配的起始设备编号.first 的次编号部分常常是 0, 但不是强制的.

第二个参数count是你请求的连续设备编号的总数. 注意, 如果 count 太大, 你要求的范围可能溢出到下一个主设备号;但是只要你要求的编号范围可用, 一切都仍然会正确工作.

第三个name是应当连接到这个编号范围的设备的名字; 它会出现在 /proc/devices 和 sysfs 中.

如同大部分内核函数, 如果分配成功进行, register_chrdev_region 的返回值是 0. 出错的情况下, 返回一个负的错误码, 你不能存取请求的区域。

 

Linux系统中正在使用的主设备号会保存在 /proc/devices 文件中:

~ >: cat /proc/devices

 

编写驱动时可以选定一个未用的主设备号,如251来使用:

dev_t devno;

int result;

int major=251;

devno = MKDEV(major, 0);

result = register_chrdev_region (devno, 4, "led");

if (result < 0)

{

printk(KERN_ERR "LED driver can't use major %d\n", major);

return -ENODEV;

}

MKDEV(ma,mi)

#define MKDEV(ma,mi)    ((ma)<<8 | (mi))

所以MKDEV(5, 0),最后得到的值为【5*(2的8次幂)+0】,等于1280。

dev_t

typedef __u32 __kernel_dev_t;

typedef __kernel_dev_t    dev_t;

当驱动的主、次设备号申请成功后,/proc/devices里将会出现该设备,但是/dev 路径下并不会创建该设备文件。需要创建该文件,则需要使用mknod命令创建。当然我们也可以在驱动里调用相应的函数,来通知应用程序空间自动创建该设备文件。

~ >: mknod --help

BusyBox v1.27.1 (2019-05-01 20:12:50 CST) multi-call binary.

 

Usage: mknod [-m MODE] NAME TYPE MAJOR MINOR

 

Create a special file (block, character, or pipe)

 

        -m MODE Creation mode (default a=rw)

TYPE:

        b       Block device

        c or u  Character device

        p       Named pipe (MAJOR and MINOR are ignored)

~ >: mknod -m 755 /dev/led0 c 251 0

~ >: mknod -m 755 /dev/led1 c 251 1

~ >: mknod -m 755 /dev/led2 c 251 2

~ >: mknod -m 755 /dev/led3 c 251 3

动态申请主次设备号 

int alloc_chrdev_region(dev_t *dev, unsigned int firstminor, unsigned int count, char *name);

第一个参数:dev是一个只输出的参数, 获得一个分配到的设备号。可以用MAJOR宏和MINOR宏,将主设备号和次设备号,提取打印出来,看是自动分配的是多少.

第二个参数 fisetminor 应当是请求的第一个要用的次编号; 它常常是0.

count name 参数如同给 request_chrdev_region 的一样。

使用动态申请主次设备号示例:

int result;

int dev_major

dev_t devno;

result = alloc_chrdev_region(&devno, 0, 4, "led");

dev_major = MAJOR(devno);

/* Alloc for device major failure */

if (result < 0)

{

printk(KERN_ERR "led driver allocate device major number failure: %d\n",result);

return -ENODEV;

}

printk(KERN_ERR "led driver choose device major number: %d\n", dev_major);

/* MAJOR 和 MINOR
#define MAJOR(dev)    ((dev)>>8)
#define MINOR(dev)    ((dev) & 0xff) */

如果使用alloc_chrdev_region()函数来动态分配主设备号,那我们驱动在安装后并不知道这个主设备号是多少,那么只能通过 查看 /proc/devices 文件才能知道它的值,然后再创建设备节点mknod

释放主次设备号 

在Linux内核中,主、次设备号是一种资源,不管你使用何种方式分配的设备编号, 你应当在不再使用它们时释放它. 设备编号的释放使用下面函数:

void unregister_chrdev_region(dev_t first, unsigned int count);  

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值