当前位置:首页 » 操作系统 » linux芯片驱动

linux芯片驱动

发布时间: 2022-04-17 16:53:36

1. 解释一下linux驱动程序结构框架及工作原理

一、Linux device driver 的概念

系统调用是操作系统内核和应用程序之间的接口,设备驱动程序是操作系统内核和机器硬件之间的接口。设备驱动程序为应用程序屏蔽了硬件的细节,这样在应用程序看来,硬件设备只是一个设备文件,应用程序可以象操作普通文件一样对硬件设备进行操作。设备驱动程序是内核的一部分,它完成以下的功能:

1、对设备初始化和释放;

2、把数据从内核传送到硬件和从硬件读取数据;

3、读取应用程序传送给设备文件的数据和回送应用程序请求的数据;

4、检测和处理设备出现的错误。

在Linux操作系统下有三类主要的设备文件类型,一是字符设备,二是块设备,三是网络设备。字符设备和块设备的主要区别是:在对字符设备发出读/写请求时,实际的硬件I/O一般就紧接着发生了,块设备则不然,它利用一块系统内存作缓冲区,当用户进程对设备请求能满足用户的要求,就返回请求的数据,如果不能,就调用请求函数来进行实际的I/O操作。块设备是主要针对磁盘等慢速设备设计的,以免耗费过多的CPU时间来等待。

已经提到,用户进程是通过设备文件来与实际的硬件打交道。每个设备文件都都有其文件属性(c/b),表示是字符设备还是块设备?另外每个文件都有两个设备号,第一个是主设备号,标识驱动程序,第二个是从设备号,标识使用同一个设备驱动程序的不同的硬件设备,比如有两个软盘,就可以用从设备号来区分他们。设备文件的的主设备号必须与设备驱动程序在登记时申请的主设备号一致,否则用户进程将无法访问到驱动程序。

最后必须提到的是,在用户进程调用驱动程序时,系统进入核心态,这时不再是抢先式调度。也就是说,系统必须在你的驱动程序的子函数返回后才能进行其他的工作。如果你的驱动程序陷入死循环,不幸的是你只有重新启动机器了,然后就是漫长的fsck。

二、实例剖析

我们来写一个最简单的字符设备驱动程序。虽然它什么也不做,但是通过它可以了解Linux的设备驱动程序的工作原理。把下面的C代码输入机器,你就会获得一个真正的设备驱动程序。

由于用户进程是通过设备文件同硬件打交道,对设备文件的操作方式不外乎就是一些系统调用,如 open,read,write,close…, 注意,不是fopen, fread,但是如何把系统调用和驱动程序关联起来呢?这需要了解一个非常关键的数据结构:

STruct file_operatiONs {

int (*seek) (struct inode * ,struct file *, off_t ,int);

int (*read) (struct inode * ,struct file *, char ,int);

int (*write) (struct inode * ,struct file *, off_t ,int);

int (*readdir) (struct inode * ,struct file *, struct dirent * ,int);

int (*select) (struct inode * ,struct file *, int ,select_table *);

int (*ioctl) (struct inode * ,struct file *, unsined int ,unsigned long);

int (*mmap) (struct inode * ,struct file *, struct vm_area_struct *);

int (*open) (struct inode * ,struct file *);

int (*release) (struct inode * ,struct file *);

int (*fsync) (struct inode * ,struct file *);

int (*fasync) (struct inode * ,struct file *,int);

int (*check_media_change) (struct inode * ,struct file *);

int (*revalidate) (dev_t dev);

}

这个结构的每一个成员的名字都对应着一个系统调用。用户进程利用系统调用在对设备文件进行诸如read/write操作时,系统调用通过设备文件的主设备号找到相应的设备驱动程序,然后读取这个数据结构相应的函数指针,接着把控制权交给该函数。这是linux的设备驱动程序工作的基本原理。既然是这样,则编写设备驱动程序的主要工作就是编写子函数,并填充file_operations的各个域。

下面就开始写子程序。

#include <linux/types.h> 基本的类型定义

#include <linux/fs.h> 文件系统使用相关的头文件

#include <linux/mm.h>

#include <linux/errno.h>

#include <asm/segment.h>

unsigned int test_major = 0;

static int read_test(struct inode *inode,struct file *file,char *buf,int count)

{

int left; 用户空间和内核空间

if (verify_area(VERIFY_WRITE,buf,count) == -EFAULT )

return -EFAULT;

for(left = count ; left > 0 ; left--)

{

__put_user(1,buf,1);

buf++;

}

return count;

}

这个函数是为read调用准备的。当调用read时,read_test()被调用,它把用户的缓冲区全部写1。buf 是read调用的一个参数。它是用户进程空间的一个地址。但是在read_test被调用时,系统进入核心态。所以不能使用buf这个地址,必须用__put_user(),这是kernel提供的一个函数,用于向用户传送数据。另外还有很多类似功能的函数。请参考,在向用户空间拷贝数据之前,必须验证buf是否可用。这就用到函数verify_area。为了验证BUF是否可以用。

static int write_test(struct inode *inode,struct file *file,const char *buf,int count)

{

return count;

}

static int open_test(struct inode *inode,struct file *file )

{

MOD_INC_USE_COUNT; 模块计数加以,表示当前内核有个设备加载内核当中去

return 0;

}

static void release_test(struct inode *inode,struct file *file )

{

MOD_DEC_USE_COUNT;

}

这几个函数都是空操作。实际调用发生时什么也不做,他们仅仅为下面的结构提供函数指针。

struct file_operations test_fops = {?

read_test,

write_test,

open_test,

release_test,

};

设备驱动程序的主体可以说是写好了。现在要把驱动程序嵌入内核。驱动程序可以按照两种方式编译。一种是编译进kernel,另一种是编译成模块(moles),如果编译进内核的话,会增加内核的大小,还要改动内核的源文件,而且不能动态的卸载,不利于调试,所以推荐使用模块方式。

int init_mole(void)

{

int result;

result = register_chrdev(0, "test", &test_fops); 对设备操作的整个接口

if (result < 0) {

printk(KERN_INFO "test: can't get major number\n");

return result;

}

if (test_major == 0) test_major = result; /* dynamic */

return 0;

}

在用insmod命令将编译好的模块调入内存时,init_mole 函数被调用。在这里,init_mole只做了一件事,就是向系统的字符设备表登记了一个字符设备。register_chrdev需要三个参数,参数一是希望获得的设备号,如果是零的话,系统将选择一个没有被占用的设备号返回。参数二是设备文件名,参数三用来登记驱动程序实际执行操作的函数的指针。

如果登记成功,返回设备的主设备号,不成功,返回一个负值。

void cleanup_mole(void)

{

unregister_chrdev(test_major,"test");

}

在用rmmod卸载模块时,cleanup_mole函数被调用,它释放字符设备test在系统字符设备表中占有的表项。

一个极其简单的字符设备可以说写好了,文件名就叫test.c吧。

下面编译 :

$ gcc -O2 -DMODULE -D__KERNEL__ -c test.c –c表示输出制定名,自动生成.o文件

得到文件test.o就是一个设备驱动程序。

如果设备驱动程序有多个文件,把每个文件按上面的命令行编译,然后

ld ?-r ?file1.o ?file2.o ?-o ?molename。

驱动程序已经编译好了,现在把它安装到系统中去。

$ insmod ?–f ?test.o

如果安装成功,在/proc/devices文件中就可以看到设备test,并可以看到它的主设备号。要卸载的话,运行 :

$ rmmod test

下一步要创建设备文件。

mknod /dev/test c major minor

c 是指字符设备,major是主设备号,就是在/proc/devices里看到的。

用shell命令

$ cat /proc/devices

就可以获得主设备号,可以把上面的命令行加入你的shell script中去。

minor是从设备号,设置成0就可以了。

我们现在可以通过设备文件来访问我们的驱动程序。写一个小小的测试程序。

#include <stdio.h>

#include <sys/types.h>

#include <sys/stat.h>

#include <fcntl.h>

main()

{

int testdev;

int i;

char buf[10];

testdev = open("/dev/test",O_RDWR);

if ( testdev == -1 )

{

printf("Cann't open file \n");

exit(0);

}

read(testdev,buf,10);

for (i = 0; i < 10;i++)

printf("%d\n",buf[i]);

close(testdev);

}

编译运行,看看是不是打印出全1

以上只是一个简单的演示。真正实用的驱动程序要复杂的多,要处理如中断,DMA,I/O port等问题。这些才是真正的难点。上述给出了一个简单的字符设备驱动编写的框架和原理,更为复杂的编写需要去认真研究LINUX内核的运行机制和具体的设备运行的机制等等。希望大家好好掌握LINUX设备驱动程序编写的方法。

2. 求Linux下CH452数码管芯片的驱动程序

是什么设备使用的 可以问问厂家

3. linux 驱动真的很难吗Linux驱动和裸机的驱动有什么区别那个更难

Linux驱动和裸机驱动(例如安卓系统)没什么区别,因为都是用的Linux的内核;硬要说区别,那应该是不同芯片之间的个性化的差异,但都是在同一个框架下修修补补,基本上弄懂一个,其他的也就能了解个十之八九了。要说Linux驱动难不难,这要看你是否下定决心想学,了解汇编(基本上不会用,但有的项目非它不可)、精通C语言(达不到要求就努力达到要求,求!!!),掌握C++(做驱动的有时候需要弄中间层,这部分全是C++)、学好数据结构、英语能有多好有多好,实在太low过火那就自求多福吧!!!有以上基础后还需要会看电路图,会用万用表和示波器,这些是你调试过程中的好伙伴。目前学习驱动的书太多了,但是国内的话韦东山老师的《嵌入式linux应用开发完全手册》比较不错,最主要的是他的视频讲得很nice。有前辈带着做项目的话进步会很快,要是既没项目又没人带那就静下心来慢慢学,坚持就是胜利。如果还在学校得话那就多花点时间学一下,多问问老师,恋爱必须要谈,至于游戏什么的消遣一下就OK了。

4. 为什么Linux驱动不用配置芯片引脚

摘要 、芯片的新功能Linux驱动里未必就有。

5. 无线网卡如何看芯片型号,需要linux驱动

无线网卡可通过以下步骤查看芯片型号:
1、在电脑右下方找到网络连接图标表,选择“打开网络和共享中心”,点击进入“更改适配器设置“;
2、右击“无线网络连接”,选择“属性”;
3、红框内显示的即是无线网卡的型号。‍
4、通过linux驱动,可打开终端,输入iwconfig,显示出无线网卡的相关的信息,一般在 Nickname后面的即是具体的芯片型号。

6. linux需要安装芯片组驱动吗

显卡驱动和网卡驱动有时候需要安装,主板芯片组驱动一般不需要,安装好一个Linux系统后,有些型号的显卡和网卡没有默认驱动,就需要另外安装了,还有一小部分硬件型号Linux压根就不支持。

7. linux如何安装驱动

在Intel网站直接下载的Linux驱动是e1000-5.2.52.tar.gz(版本可能会有改变),这个压缩包里面没有编译好的.o的文件,需要在Linux系统下编译之后才能使用,
因为网卡需要编译,所以要先确认将内核源文件安装好,下面是关于内核源文件的安装
● Linux下添加内核源文件
1. 用rpm –qa|grep kernel-source查看是否安装了这个包;
如果返回结果中有kernel-source-xxx(其中xxx为当前redhat的内核版本,如rhel3为2.4.21-4EL), 即已经 安装。如无返回结果则需要安装kernel-source包。到安装光盘中找到kernel-source-xxx.i386.rpm,用下面命令安装此rpm包:
2.如果安装了用rpm -V kernel-source校验是否有文件丢失,如果没有输出,表示文件完整;
3.如果有丢失用rpm -ivh --force kernel-source-xxxx...把包重新安装一下;
这个kernel-source包,在您的RH安装光盘中,在Redhat/RPMS中,如果以前没有安装过这个包,那么用rpm -ivh kernel-source-xxxx...来安装,如果安装过,需要覆盖安装,使用rpm -ivh --force kernel-source-xxxx...这个命令强制安装。
注:AS 4 开始,没有kernel-source这个包了,取而代之的是kernel-dev这个包,检查这个包有没有安装的方法同上
● 驱动安装步骤:
1. 把这个tar文件拷贝到用户自己定义的目录中,例如:
/home/username/e1000 or /usr/local/src/e1000
2. 用tar命令解这个压缩包:
tar zxf e1000-5.2.52.tar.gz
3. 切换到驱动的src目录下:
cd e1000-5.2.52/src/
4. 编译这个驱动模块:
make
然后安装这个模块
make install
这个二进制元将被安装到如下位置:
/lib/moles//kernel/drivers/net/e1000.o
以上的路径是默认的安装位置,在某些linux版本中可能是其他位置,具体信息可以查看在驱动的 tar压缩包中的ldistrib.txt文件.
5. 安装模块:
insmod e1000 (2.6以上的版本最好使用全路径安装 P insmod /lib/moles//kernel/drivers/net/e1000/e1000.ko)
6. 设定网卡IP地址:
ifconfig ethx <IP_address> x是网卡接口的号
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
若多个网卡的芯片相同可以cp ifcfg-eth0 ifcfg-eth1~~~~~~
修改下里面的drive名称就OK
!!!!!!!!!!!!!!!!!!!
在网卡的编译中很可能不能进行下去~这个原因除了kernel的开发包没有安装外还可能是由于开发环境不完全所引起的!
这时就需要你讲开发环境安装完成,最简单的办法就是通过 sysconfig-config-packet 安装gcc
安装完成后继续执行 make ;make install

了解更多开源相关,去LUPA社区看看吧

8. 如何编写Linux 驱动程序

以装载和卸载模块为例:

1、首先输入代码

#include <linux/init.h>

#include <linux/mole.h>

9. linux 内核驱动问题

1,重新编译内核浪费时间,可以考虑把fedora的it20驱动移植过来!参考网上的makefile写个,自己编译一下。把编译得到的ko放到某目录下, 在启动脚本里加载它!

2, 如果想重新编译内核也可以,把fedora9的it驱动替换你的驱动(把源文件名字改成一样的),前提是你有内核源代码!一般安装完fedora后,在源码里有个.config文件,这就是默认的配置文件,你也不许要再make menuconfig了,直接make oldconfig make 就行。

10. linux驱动有哪些

1、将驱动程序文件bcm5700src.rpm复制到一个临时目录中,并在此目录中运行以下命令;

2、运行以下命令切换到驱动目录中;

3、此目录中会生成一个名字为bcm5700.spec的文件,运行以下命令对驱动程序进行编译;

4、运行以下命令切换到RPM目录中;

5、运行以下命令安装驱动程序;

6、运行以下命令加载驱动模块;

7、运行kudzu命令,系统会自动搜索到硬件,进行配置即可。

linux是文件型系统,在linux中,一切皆文件,所有硬件都会在对应的目录(/dev)下面用相应的文件表示。 文件系统的linux下面,都有对于文件与这些设备关联的,访问这些文件就可以访问实际硬件。 通过访问文件去操作硬件设备,一切都会简单很多,不需要再调用各种复杂的接口。 直接读文件,写文件就可以向设备发送、接收数据。 按照读写存储数据方式,我们可以把设备分为以下几种:字符设备(character device)、块设备(Block device)和网络设备( network interface)。

字符设备(character device):指应用程序采用字符流方式访问的设备。这些设备节点通常为传真、虚拟终端和串口调制解调器、键盘之类设备提供流通信服务, 它通常只支持顺序访问。字符设备在实现时,大多不使用缓存器。系统直接从设备读取/写入每一个字符。

块设备(Block device):通常支持随机存取和寻址,并使用缓存器,支持mount文件系统。典型的块设备有硬盘、SD卡、闪存等,但此类设备一般不需要自己开发,linux对此提过了大部分的驱动。

网络设备(network interface):是一种特殊设备,它并不存在于/dev下面,主要用于网络数据的收发。网络驱动同块驱动最大的不同在于网络驱动异步接受外界数据,而块驱动只对内核的请求作出响应。

上述设备中,字符设备驱动程序适合于大多数简单的硬件设备,算是各类驱动程序中最简单的一类,一般也是从这类驱动开始学习,然后再开始学习采用IIC、SPI等通讯接口的一些设备驱动。可以基于此类驱动调试LKT和LCS系列加密芯片。注意7位IIC地址是0x28。

热点内容
关联规则apriori算法 发布:2024-09-30 03:10:29 浏览:404
codeblocks安装后没编译器 发布:2024-09-30 03:09:50 浏览:634
iisftp怎么添加用户 发布:2024-09-30 02:55:05 浏览:452
致炫加装什么配置好 发布:2024-09-30 02:05:58 浏览:543
头像脚本 发布:2024-09-30 01:56:53 浏览:867
u盘文件夹快捷方式 发布:2024-09-30 01:32:32 浏览:367
健康水密码是什么 发布:2024-09-30 01:09:50 浏览:59
卸载安卓应用怎么清理 发布:2024-09-30 01:09:40 浏览:582
薯仔上传视频格式 发布:2024-09-30 01:08:36 浏览:820
腾讯视频大王卡缓存 发布:2024-09-30 00:47:18 浏览:78