‘壹’ 配置linux内核的时候,驱动的静态编译和动态编译有什么区别
驱动的动态编译会生成.ko文件,系统启动后需要加载该驱动后才能使用相应设备。
而静态编译则直接编译进内核,系统启动的时候会自动加载该驱动。
静态编译太多驱动至内核,会导致内核体积过大,启动时间较长。而动态编译则比较自由灵活,需要用的时候即加载,不需要的时候即卸载。我以前在EasyARM-iMX280的学习手册里看到写得很清楚,你可以去看看的。
‘贰’ linux内核编译问题
根据你的警告是提示,找不到这些驱动模块,应该是没有编译驱动模块或者没有安装驱动模块造成的。
1、要确保你的内核包是完整的,而且是centos配套版本(因为各大发行版都会针对自己的情况对内核进行配置和改动,直接用kernel.org的原版内核可能会有些故障)
2、编译前要 先make clean一下,把以前编译剩下的东西清掉,重头再来。
3、编译时顺序执行如下命令
make bzImage 生成内核映像
make moles 生成驱动模块
make moles_install 安装驱动模块
make install 安装内核
‘叁’ 如何调整Linux内核启动中的驱动初始化顺序
【问题】 此处我要实现的是将芯片的ID用于网卡MAC地址,网卡驱动是enc28j60_init。 但是,读取芯片ID的函数,在as352x_afe_init模块中,所以要先初始化as352x_afe_init。 此处,内核编译完之后,在生成的system.map中可以看到, enc28j60_init在as352x_afe_init之前,所以,无法去读芯片ID。 所以我们的目标是,将as352x_afe_init驱动初始化放到enc28j60_init之前, 然后才能读取芯片ID,才能用于网卡初始化的时候的,将芯片ID设置成网卡MAC地址。
【解决过程】
【1】
最简单想到的,是内核里面的
archarmmach-as352xcore.c
中,去改devices设备列表中的顺序。
enc28j60_init对应的是ssp_device,因为网卡初始化用到的是SPI驱动去进行和通讯的。
as352x_afe_init对应的是afe_device。
原先是:
把afe改到最前面:
但是,实际结果是,没有任何影响,连systemp.map生成的,那么模块初始化顺序,都没有任何变化。 也就说明,想要实现驱动加载顺序的改变,改core.c里面的设备列表顺序是没有用的。
更多linux内核视频教程文档资料免费领取后台私信 【内核】 自行获取.
Linux内核源码/内存调优/文件系统/进程管理/设备驱动/网络协议栈-学习视频教程-腾讯课堂
【2】
在网上看到很多帖子,其说明的也很清楚了,就是:
Linux内核为不同驱动的加载顺序对应不同的优先级,定义了一些宏:
includelinuxinit.h
把自己的驱动的函数名用这些宏去定义之后, 就会对应不同的加载时候的优先级。
其中,我们写驱动中所用到的mole_init对应的是 #define mole_init(x) __initcall(x); 而 #define __initcall(fn) device_initcall(fn) 所以,驱动对应的加载的优先级为6
在上面的不同的优先级中, 数字越小,优先级越高。 同一等级的优先级的驱动,加载顺序是链接过程决定的,结果是不确定的,我们无法去手动设置谁先谁后。 不同等级的驱动加载的顺序是先优先级高,后优先级低,这是可以确定的。
所以,像我们之前在驱动中用:
所以,大家都是同一个优先级去初始化,
最后这些驱动加载的顺序,可以查看在根目录下,
生成的system.map:
此处就是由于 c0019920 t __initcall_i2c_dev_init6 c0019924 t __initcall_as352x_afe_i2c_init6 c0019928 t __initcall_as352x_afe_init6 在c00198e4 t __initcall_enc28j60_init6之前,所以我这里才要去改。。。 知道原理,能想到的,就是要么把as352x_afe_init改到enc28j60_init之前一级,即优先级为5。即在驱动中,调用:fs_initcall(as352x_afe_init);要么把enc28j60_init改到as352x_afe_init之后,即优先级为7即在驱动中,调用:late_initcall(enc28j60_init);但是,此处麻烦就麻烦在,如果把as352x_afe_init改到enc28j60_init之前一级,发现后面网卡初始化enc28j60_init中,虽然读取芯片ID对了,但是后面的IP-auto configure 有问题。所以放弃。 如果把enc28j60_init改到as352x_afe_init之后,但是,从system.map中看到的是,优先级为7的驱动中,明显有几个驱动,也是和网卡初始化相关的,所以,这样改,尝试后,还是失败了。 所以,没法简单的通过调整现有的驱动的顺序,去实现顺序的调整。最后,被逼无奈,想到了一个可以实现我们需求的办法,那就是,单独定义一个优先级,把afe相关的初始化都放到那里面去,这样,就可以保证,其他没什么相关的冲突了。最后证实,这样是可以实现目的的。
具体添加一个新的优先级的步骤如下: 1.定义新的优先级 includelinuxinit.h中:
2.用对应新的宏,定义我们的驱动:
做到这里,本以为可以了,但是编译后,在system.map中,发现之前优先级为7的那几个函数,被放到system.map最后了,而不是预想的,在优先级7之后,在
之前。最后,发现时没有把对应的链接文件中的宏加进去:
3.includeasm-genericvmlinux.lds.h
最后,再重新编译,就可以实现我们要的,和afe相关的驱动初始化,都在网卡enc28j60_init之前了。也就可以在网卡里面读芯片ID了。当然,对应编译生成的system.map文件中,对应的通过mole_init定义的驱动,优先级也都变成7了。而late_initcall对应优先级8了。 注:当前开发板arm的板子,所以,对应的load 脚本在:
linux-2.6.28.4archarmkernelvmlinux.lds 看起来,应该是这个文件: linux-2.6.28.4archarmkernelvmlinux.lds.S 生成上面那个脚本的。vmlinux.lds中的这一行:
就是将之前那些对应的init类型的函数,展开,放到这对应的位置。
【3】 不过,最后的最后,竟然发现网卡还是工作不正常,结果第二天,无意间发现是网卡地址设置导致网卡工作不正常的。 也就是说,实际是直接将afe设置到原先的优先级5就可以的,而不用这么麻烦去改系统的东西的...
不过,至少这也是一种办法,虽然不是那么的好...
‘肆’ 内核添加spi驱动的问题,急求助
设备和驱动要匹配,除了要满足match函数,还需要挂到同样的总虚帆猜线上.
要差型确认这几个问题,设轿中备成功添加没,驱动成功添加没,是否都在同一总线上.
‘伍’ linux内核编译时,怎么添加spi
出现这种情况主要是下面的段知原因造成的: 1、系统安装文件或GHO文件燃告兼容性差,或者安装文件损坏。 2、U盘系统功能不正常,安装过程中断。 建议用下面的方法处理: 第一,制作启动u盘。以大白皮燃明菜U盘系统为例说明。还有深度U盘系统等等。
‘陆’ 如何把新驱动编译进内核 ubuntu
工具/原料
Ubuntu12.04操作系统和测试驱动程序(beep_arv.c)
方法/步骤
在介绍2种方法前,必须知道的知识点:
1.关联文件Makefile:
Makefile:分布在Linux内核源代码中的Makefile用于定义Linux内核的编译规则;
2.管理文件Kconfig:
给用户提供配置选择的功能;
配置工具:
1)包括配置命令解析器;
2)配置用户界面;menuconfig || xconfig;
3)通过脚本语言编写的;
3.
---tristate 代表三种状态:1.[ ]不选择,2.[*]选择直接编译进内核,加载驱动到内核里,3.[m]动态加载驱动;
---bool 代表两种状态,1.[ ]不选择,2.[*]选择;
---"Mini2440 mole sample"这个是在make menuconfig时刷出的提示字符;
---depends on MACH_MINI2440 这个配置选项出现在make menuconfig菜单栏下,在内核配置中必须选中、MACH_MINI2440;
---default m if MACH_MINI2440 这个如果选中了MACH_MINI2440,默认是手
动加载这个驱动;
help:提示帮助信息;
在了解了基本的知识点,便开始进行第一种添加驱动的方法,本次交流是以beep_arv.c蜂鸣驱动程序为基础的
方法一:
1)进入内核的驱动目录;
#cp beep_arv.c /XXX/.../linux-XXXl/drivers/char
2)进入Kconfig添加驱动信息;
#cd /XXX/linux-XXX/.../drivers/char
#vim Kconfig
添加基本信息:
config BEEP_MINI2440
tristate "---HAH--- BEEP"
default
help
this is test makefile!
3)进入Makefile添加驱动编译信息;
#vim Makefile
添加基本信息:
obj-$(CONFIG-BEEP_MINI2440) +=beep_drv.o
方法一结果:
在--Character devices下就能看到配置信息了;
方法二:
1)进入驱动目录,创建BEED目录;
#cd /XXX/.../linux-XXX/drivers/char
#mkdir beep
2)将beep_arv.c驱动程序复制到新建目录下;
#cp beep_arv.c /XXX/.../linux-XXXl/drivers/char/beep
3)创建Makefile和Kconfig文件
#cd char/beep
#mkdir Makefile Kconfig
#chmod 755 Makefile
#chmod 755 Kconfig
4)进入Kconfig添加驱动信息;
#vim Kconfig
添加基本信息:
config BEEP_MINI2440
tristate "---HAH--- BEEP"
default
help
this is test makefile!
5)进入Makefile添加驱动编译信息;
#vim Makefile
添加基本信息:
obj-$(CONFIG_BEEP_MINI2440) +=beep_drv.o
6)并且要到上一级目录的Makefile和Kconfig添加驱动信息;
#cd ../
#vim Makefile
#vim Kconfig
‘柒’ linx下如何驱动spi
1、驱动分为平台驱动、控制器驱动、设备驱动、设备。
2、拿到一个开发板后,烧上橡余察系统,那我们基本上就有了平台驱动、控制器驱动。设备驱动基本都有的,官方实现了一个设备驱动,文件是spidev.c,它是一个设备驱动毁数,它会在开机之后自动注册一个主设备号为153的字符设备。
3、当注册了SPI设备到系统中时,会根据名字进行匹配,如果名字是spidev则会调用 spidev.c中的probe函数,随后会在/dev/device/下面生成如spidevx.x的设备文件,通过该设备文件即可操作SPI设备。
4、如何注册SPI设备到系统。在kernel/arch/arm/mach-xxxx,xxx是板子芯片型号,我用的事 mach-smdk6410.c。在里面找到spi_board_info结构体位置,例如:
static struct spi_board_info __initdata forlinx6410_mc251x_info[] = {
{
.modalias = "mcp2515",
.platform_data = &mcp251x_info,
.irq = IRQ_EINT(16),
.max_speed_hz = 10*1000*1000,
.bus_num = 1,
.chip_select = 0,
.mode = SPI_MODE_0,
.controller_data=&s3c64xx_spi1_csinfo,
},
};
本结构体就是SPI的板级信息,会在后面被spi_register_board_info()调用,随后在系统中注册这个设备。
我们需要做的是添加我们自己的信息
static struct spi_board_info __initdata forlinx6410_mc251x_info[] = {
{
.modalias = "mcp2515",
.platform_data = &mcp251x_info,
.irq = IRQ_EINT(16),
.max_speed_hz = 10*1000*1000,
.bus_num = 1,
.chip_select = 0,
.mode = SPI_MODE_0,
.controller_data=&s3c64xx_spi1_csinfo,
},
{
.modalias = "spidev", //用来匹配设备驱动,SPI的设备驱动叫spidev
.max_speed_hz = 10*1000*1000, //最大速率
.bus_num = 0, //在(0)号总线上
.chip_select = 0, //使用片选spi0_cs0
.mode = SPI_MODE_0, //SPI模式
.controller_data=&s3c64xx_spi0_csinfo,//控制器信息 },
};
其中的static struct s3c64xx_spi_csinfo s3c64xx_spi0_csinfo = {
.fb_delay=0x3,
.line=S3C64XX_GPC(3),//这个是片选控制引脚
.set_level=cs_set_level,
};
然后编译内核下载开发板上,重新启动过后就能后在/dev下面看到spidev0.0设备文件。
猜想:
写一个模块,收到填写该结构体,然后调用spi_register_board_info()来注册。我没有试过,应该是可以的。
5、使用的时候在用户应用空间中就使用open打开设备文件即可使用。
需要在封装一次。由于spidev.c仅提供数据接收与发送,但是对于梁茄具体的SPI怎么发的好像没有做。
因此我们具体的收发函数应该在此分装为如下
int fd;
fd=open(device, O_RDWR);
读函数
输入:fd文件描述符,addr读的地址,read_data读出来数据存放的地址
输出:成功操作的字节数,这个没有做好,需要改
unsigned char read_reg(int fd,unsigned char addr,unsigned char *read_data)
{
int ret=0;
addr=addr<<1;
addr=addr|0x80;
ret=write(fd,&addr,sizeof(unsigned char));
ret|=read(fd,read_data,sizeof(unsigned char));
return ret;
}
写函数
unsigned char write_reg(int fd,unsigned char addr,unsigned data)
{
int ret=0;
unsigned char buff[2]={0};
buff[0]=addr<<1;
buff[0]=buff[0]&0x7f;
buff[1]=data;
ret=write(fd,&buff,sizeof(buff));
return ret;
}
然后其他具体操作看我们的实际需要了,以上两个就可以正确读写了,你可以先用读函数读取设备各个寄存器的默认值,来观察读取是否正确。
‘捌’ 怎么用Visual Studio编译内核驱动
在Win8以前开发内核驱动,准备编译环境是个较繁琐的事情。程序员需要手动下载WDK并安装(注1),开发环境就在安装好的WDK中。WDK是Windows Driver Kit缩写,即Windows驱搏陵告动开发包。它提供的开发环境简陋得很,它不是一个便于开发的IDE环境,而仅仅是一些散装的编译工具包。
安装好WDK后,WDK的编译环境链接就显示在开始菜单中了,要小心不能将它们删掉,否则会麻烦,因为手动生成链接是麻烦事,后文会讲。
编译环境是分类的。首先根据目标系统分类,也就是要编译生成运行在什么OS上的目标文件。微软大部分的产品都保持了向后兼容的习惯,这条规律也适用于此处:使用Win7子系统环境编译出来的驱动文件,一般都能运行在Vista和XP系统上,反之就不会成立(注2)。
其次根据硬件平台分类,现在Windows系统能够运行的平台有四个:X86,X64,IA64和ARM。其中ARM是Win8才开始的故事,这里还轮不到它出场,这样就只有前面三个硬件平台(注3)。
最后又要根据编译版本来分,即Checked(也可认做Debug)和Free(也可认作Release)这两种。这样来看,每个OS组别下面,就一汪滚定有6个编译环境链接。
在这本书里面,如果用旧版本WDK编译驱动,就默认使用Win7目标系统的编译环境,生成Checked版本,目标平台是X86或X64。所以就只会选两种:X86 Checked Build Environment和X64 Checked Build Environment.
编译环境打开来其实就是个控制台。它当然不同于直接从cmd.exe运行起来的控制台环境,区别在哪里呢?我们已经知道,上图的这些黑色的编译环境图标,其实都是快捷方式。不妨就看看它的快捷方式的Target内容,或许就知道端倪了。以X64 Checked Build Environment这个环境为例,打开来看到如下内容:
C:\Windows\System32\cmd.exe /k C:\WinDDK\7600.16385.1\bin\setenv.bat C:\WinDDK\7600.16385.1\ chk x64 WIN7
这一行内容仔细一看就很简单了。原来所谓的编译环境,就是一个运行cmd.exe的控制台进程,只不过它执行了用于初始化的/k参数。在Cmd.exe命令的帮助中,/k参数是这样描述的:Carries out the command specified by string but remains(执行一个命令,执行完之后不退出程序)。也就是说,启动控制台进程并执行命令,执行完后,控制台程序留给用户继续使用。
那么/k之后的所有内容,都是一条初始化的命令:
C:\WinDDK\7600.16385.1\bin\setenv.bat C:\WinDDK\7600.16385.1\ chk x64 WIN7
它却又可拆成几个部分来分析。第一个setenv.bat是初始化编译环境的批文件。后面的是它的参数:第一个参数,是WDK的路径,通过它可以找到编译器程序;第二个参数是指明要编译生成checked版本目标文件;第三个指明硬件平台是x64;第三个指明目标系统是Win7。
位于WDK中的Setenv.bat文件是负责编译环境配置的总厨,你把什么参数递给它,它就给你配出什么类型的编译环境来(菜也)。
怎么在这个控制台里面编译驱动呢?我们统一用使用以下步骤:
通过CD命令,定位到含有source文件的那个驱动目录;
输入build或bld(build –cz的简写)命令进行编译;
如果编译成功,将生成驱动文件,否则会有错误或警告信息显示出来;也可通过查看目录文件夹下面的相关log文件查看详细的错误或警告信息。
走到这里,基明编译的事情算弄明白了。可能还会有朋友问我,我用什么东西写代码呢?不好意思,关于这个问题,此时还没有康庄大道供大家驷马高车,不过千万条小路却是现成的。您可以用notepad记事本或者任何文本编辑器来编辑代码,如果不嫌麻烦,用Visual Studio写代码也可以,只不过仅作代码编辑而已。
‘玖’ Linux内核自带的SPI驱动怎么用能提供一些资料吗
下载一份内核源代码,比如说我下载的是2.6.36的,解压老亮,里面有一个例程,位置是linux-2.6.36.4/Documentation/spi/薯含搜spidev_test.c,另外里面还有些文档,数历最好也看看。
‘拾’ linux显卡驱动怎么编译进内核
一、 驱动程序编译进内核的步骤
在 linux 内核中增加程序需要完成以下三项工作:
1. 将编写的源代码复制到 Linux 内核源代码的相应目录;
2. 在目录的 Kconfig 文件中增加新源代码对应项目的编译配置选项;
3. 在目录的 Makefile 文件中增加对新源代码的编译条目。
bq27501驱动编译到内核中具体步骤如下:
1. 先将驱动代码bq27501文件夹复制到 ti-davinci/drivers/ 目录下。
确定bq27501驱动模块应在内核源代码树中处于何处。
设备驱动程序存放在内核源码树根目录 drivers/ 的子目录下,在其内部,设备驱动文件进一步按照类别,类型等有序地组织起来。
a. 字符设备存在于 drivers/char/ 目录下
b. 块设备存放在 drivers/block/ 目录下
c. USB 设备则存放在 drivers/usb/ 目录下。