Linux设备驱动开发

来源:互联网 发布:淘宝上奇怪的东西 编辑:程序博客网 时间:2024/05/01 23:02

设备驱动概念

1.操作硬件:让硬件能够正常工作;2.要给用户提供访问操作硬件的接口;

linux内核设备的分配

1.字符设备:    特点:操作时,数据都是按照字节流形式进行    访问:    例子:串口, LED,按键,触摸屏,LCD显示屏,蓝牙         GPS,GPRS,各种传感器,摄像头,声卡,震子,电源管理IC等2.块设备    特点:操作时,数据按照一定的数据块来进行访问,比如一次访问512字节或者1K    例子:硬盘,U盘,SD卡,TF卡, nandflash (SLC, MLC, TLC)(容易出错), norflash(很稳定,采用总线形式,和内存访问一样), emmc    注意: linux内核对于块设备支持得比较完美,无需做相应的驱动开发3.网络设备    特点:操作时,一般都要结合TCP/IP网络协议栈来进行操作        例子:有线网卡,无线网卡,以太交换芯片        注意:一般来说网卡芯片驱动都是由芯片厂家来提供   

如何编写一个字符设备驱动

明确: 对于linux系统,铭记“一切皆文件”      “一切”:就是指计算机系统的硬件部分;      例如:串口设备将来在用户空间(rootfs)就是以文件的形式存在;           将来用户访问这个文件本质上就是在访问硬件设备本身!       文件: 硬件设备在用户空间(rootfs)以文件的形式存在,这个文件不是普通的文本文件,而是设备文件,将来用户利用系统调用函数来对设备文件进行访问

设备文件有什么特点

1.设备文件存在于根文件系统的dev目录
2.设备文件的属性(包含的内容):
以串口为例:
第一个串口的设备文件属性
crw-rw—- 204, 64 s3c2410_serial0
第二个串口的设备文件属性
crw-rw—- 204, 65 s3c2410_serial1
说明:
“c”:表示这个设备是字符设备
“204”表示设备的主设备号
“64或者65”表示设备的次设备号
“s3c2410_serial0”:第一个串口的设备文件
“s3c2410_serial1”:第二个串口的设备文件

总结:设备文件包含此设备是字符设备还是块设备,主设备号,次设备号,设备文件名。
以U盘为例:
brw-rw—- 8, 1 /dev/sda1
说明:
“b”:块设备
“8”:主设备号
“1”:次设备号
“sda1”:设备文件名

注意:网络设备没有设备文件,网络设备的访问都是通过socket进行

字符设备或者块设备的访问要利用系统调用函数,
例如:

打开串口:
int fd = open ("dev/s3c2410_serial0", O_RDWR);
写串口:
write(fd, "hello,world", 12);
读串口:
char buf[1024] = {0};
read(fd, buf, 1024);
关闭串口:
close(fd);

总结:linux系统访问硬件首先获取硬件设备的设备文件,最后利用系统调用进行访问即可!没有设备文件,网络设备的访问都是通过socket进行

如何创建设备文件

1.手动创建
设备文件名 字符设备 主设备号 次设备号
mknod /dev/mytest c 250 0

2.自动创建

主设备号,次设备号作用

主设备号作用:应用程序根据设备文件中的主设备号,能够在茫茫的内核驱动中找到属于自己的驱动程序;也就说驱动程序要和这个主设备号进行关联;也就说明一个驱动程序仅有一个主设备号;也就说主设备号对于内核来说是一种宝贵的资源;

次设备号:如果多个硬件设备共享一个设备驱动,设备驱动将来根据次设备号来区分用户具体操作的哪个硬件设备;如果仅有一个设备,一般此设备号给0

内核如何描述主,次设备号

内核描述主,次设备号是通过设备号进行描述;
设备号的数据类型是dev_t (本质就是unsigned int)
设备号的高12位保存主设备号的信息;
设备号的低20位保存次设备号的信息;

切记:驱动要和设备号进行绑定,设备号对于内核来说是一种宝贵的资源

如何向申请和释放设备号资源

内核提供了以下函数供驱动来申请设备号资源:

int alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count, const char *name)
函数功能:让内核来帮你分配设备号资源
参数:
dev:保存这内核帮你分配的设备号
baseminor:希望的起始此设备号,一般给0
count:申请的此设备号的个数
name:设备名称,而不是设备文件名,将来出现在 cat /proc/devices中
函数的返回值无需记忆,只需要看内核别人怎么用即可

提取主设备号MAJOR
主设备号 = MAJOR(设备号)
提取此设备号MINOR
次设备号 = MINOR(设备号)
合并设备号:
设备号 = MKDEV(主设备号,次设备号);

设备号不再使用,要记得释放设备号  


void unregister_chrdev_region(dev_t from, unsigned count)
功能:释放设备号
参数:
from:申请的设备号
count:申请的次设备号的个数

案例

编写内核程序,申请设备号

  1.mkdir /opt/drivers/dev/2.0    2.cd /opt/drivers/dev/2.0    3.vim led_drv.c    4.vim Makefile    5.make    6.cp led_drv.ko /opt/rootfs    ARM执行:    1.insmod led_drv.ko    2.cat /proc/devices //查看申请的主设备号    3.rmmod led_drv
#include <linux/init.h>#include <linux/module.h>#include <linux/fs.h>#include <linux/cdev.h>static dev_t dev; //保存申请的设备号static int led_init(void){    //申请设备号资源    alloc_chrdev_region(&dev, 0, 1, "usb");    //打印主设备号    printk("主设备号=%d\n", MAJOR(dev));    return 0;}static void led_exit(void){    //释放设备号资源    unregister_chrdev_region(dev, 1);}module_init(led_init);module_exit(led_exit);MODULE_LICENSE("GPL");
原创粉丝点击