五分钟带你掌握Linux编译驱动、内核及应用程序
小王是一名刚接触Linux的新手,看了一些关于Linux驱动的书籍之后,买了一块Cortex®-A9的Arm®开发板,准备大干一场。编写了第一个属于自己的驱动程序并命名为hellodrv.c,程序源码如下所示。
这个驱动程序怎么编译成可以在板子上跑的程序呢,小王经过一番网上查询,原来需要交叉编译工具链,小王找到了光盘资料里的交叉编译工具并按说明正确安装了交叉编译工具。
小王编写好的驱动程序为hellodrv.c,要把该驱动程序编译为模块,在同一目录下新建了一个Makefile文件。编写的Makefile如下。
驱动编译
小王经过查询,编译驱动主要有两种方式,一种是修改内核源码顶层目录下的Makefile文件,另外也可以在编译命令指定架构及交叉编译工具。
1. 修改Makefile
例如Linux内核源码的目录为/home/vmuser/kernel-imx,打开该目录下的Makefile文件,找到ARCH及CROSS_COMPILE相关语句,修改为如下所示语句。
如果交叉编译工具链未设置环境变量则CROSS_COMPILE设置为交叉编译工具链的绝对路径,设置如下。
ARCH ?=arm
CROSS_COMPILE ?=/opt/toolchain/bin/arm-none-linux-gnueabi-
修改完之后,直接执行make命令,生成了hellodrv.ko文件。
2. 在编译命令指定
执行如下命令进行编译。
$make ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi-
这种方式也可以生成hellodrv.ko,可是驱动要依赖于内核才能跑起来,小王于是开始了Linux内核的配置及编译。
Linux内核配置及编译
编译内核时指定架构和交叉编译工具的方式同编译模块一样,经过上面的操作,小王已经轻车熟路了。小王还学会了首先导环境变量然后进行编译的方法。
$export ARCH=arm
$export CROSS_COMPILE=arm-none-linux-gnueabi-
在首次进行配置编译之前,需要清除之前编译生成的文件,可用如下命令进行清除。
$make distclean
接下来进行内核的配置,内核的配置可以使用如下命令中的一个。
$make config #基于文本的最为传统的配置界面,不推荐使用
$make menuconfig #基于文本菜单的配置界面
$make xconfig #要求QT被安装
$make gconfig #要求GTK+被安装
这四种方式中,值得推荐的是make menuconfig,它不依赖于QT或GTK+,且非常直观。使用make menuconfig命令后,会进入如图1所示的界面,在该界面根据需求对需要编译进内核的选项进行裁剪。对于bool型选项,按Y或者N决定是否选择编译进内核。[*]表示选中,[]表示未选中。对于tristate型选项,根据需求可以有Y、M、N三种选择,<*>表示静态编译,
图1内核配置界面
配置完成后,选择保存,然后退出。配置后会生成.config文件,该文件保存了配置信息,供Makefile在编译内核时使用。
在配置界面我们根据需求把需要的功能以及相应设备驱动的支持等配置好,然后进行内核及设备树的编译。内核及设备树编译用以下命令。
$make zImage /* 编译为zImage镜像 */
$make imx6dl-sabresd.dtb /* 单独编译某个设备数 */
$make dtbs /* 编译所有的设备树 */
为了加快编译速度可以在编译命令后加“-j”选项,例如PC的CPU为4核,则编译命令如下。
$make zImage -j4
如果要把某些驱动编译为模块,则使用如下命令。
$make modules
针对相应的开发板,厂家一般都会有默认的配置,这些配置文件位于内核源码arch/arm/configs目录下。例如使用如下的默认配置。
$make imx_v7_defconfig
如果已有.config文件,可以使用如下命令载入既有的.config配置文件。
$make oldconfig
内核及设备树编译完成后将会生成zImage和相应的dtb文件,按照厂家提供的烧写方式将镜像烧写到目标板。
应用程序编译及文件传输
应用程序编译
例如需要编译的应用程序文件为test.c,需要把该程序编译放到Arm®开发板上运行。编译命令如下。
$arm-none-linux-gnueabi-gcc test.c -o test
这是一个非常简单的程序,并且只有一个文件,所以可以采用直接输入命令进行交叉编译。如果工程较大,这种方式就不可取了,通常需要编写Makefile文件,通过make程序来进行工程管理。应用程序的Makefile范例如下。
编写完Makefile后执行make命令即可生成目标文件test。
编译生成的可执行文件可以通过TFTP,NFS等方式下载到开发板,关于TFTP,NFS服务器在PC上的搭建可参考网络上相关文章,这里不赘述。
1.NFS文件传输
将目标板接入局域网或通过交叉网线与PC主机相连,设定目标板的IP,使之与主机在同一网段,然后进行远程mount操作。将需要传输的文件放在PC机搭建的NFS服务器目录下。在开发板上执行如下操作。
root@M6708-T:~#ifconfig eth0 192.168.1.136 #设定开发板IP
root@M6708-T:~#ping 192.168.1.168 #ping主机IP
root@M6708-T:~#mount -t nfs 192.168.1.168:/home/vmuser/nfs/mnt/-o nolock
在进行远程挂载之前,最好先用ping命令检查网络通信是否正常,只有在能ping通的情况下,才能进行正常挂载,否则请检查网络。如果在已经ping通的情况下,远程挂载出现错误,请检查主机和目标机的其它设置。
2.TFTP文件传输
把需要传输的文件放在PC机的tftp服务器目录下。TFTP下载命令格式如下。
root@M6708-T: ~#tftp -g -r server-file server-ip
例如:下载IP为192.168.1.168的tftp服务器的hellodrv.ko文件,在开发板的当前目录下执行如下命令。
root@M6708-T: ~#tftp -g -r hellodrv.ko 192.168.1.168
通过以上任一方式将在PC机上编译完成的驱动模块hellodrv.ko和test应用程序拷贝到目标板上。
驱动模块的加载及移除
执行如下命令把驱动模块动态加载进内核。
$insmod hellodrv.ko
查看加载的模块使用如下命令。
$lsmod #查看内核中的模块信息
$modinfo hellodrv.ko #查看模块的描述信息
如需要移除模块使用如下命令。
$rmmod hellodrv
IoT9000A-LI是广州ok138太阳集团中国官方网站有限公司开发的基于M6708-T系列核心板的Arm®工控主板,核心板标配处理器为i.MX 6U,Cortex®-A9简单双核。板上集成了大量的外设接口,包括千兆以太网、音频、USB、HDMI、LVDS、LCD、miniPCIE、摄像头、CAN信号、UART信号等接口,同时整合的多功能HD视频引擎可提供1080P 60fps视频解码、1080P 30fps视频编码,并带有2D、3D图形引擎,可满足消费电子、工业和汽车车载娱乐系统等新一代应用,以及医疗应用的丰富图形和高响应需求。
IoT9000A-LI工控主板产品如下图所示。