最近尝试给海思开发板加载了TVP7002的驱动模块,已经成功生成.ko文件insmod进开发板了。虽然目前开发板没有相应硬件接口可以做测试,不知道驱动是否有问题,但是从一头雾水到处抓瞎到成功加载驱动进开发板,整个过程还是学到了很多东西,特此整理记录,也希望能帮助到有需要的人。
一、加载失败
要给板子集成驱动,第一步当然是去网上找资源了。TI官网貌似没有提供官方驱动(也可能是没找到),于是把网上关于tvp7002的驱动都下载了,CSDN有一个,PUDN有一个。但内容一模一样,有生成好的.ko文件,Makefile,.c和.h文件。而且声称是加载在Hi3531D中的,主芯片型号一致,高兴坏了,以为把.ko文件放在相应目录,然后在板子上insmod一下就可以了。结果版本不兼容,报错如下
报错:
tvp7002: version magic '3.0.8 SMP mod_unload ARMv7 ’ should be '3.18.20 SMP mod_
unload ARMv7 p2v8 ’
insmod: can’t insert ‘tvp7002.ko’: invalid module format
出现以上错误是由于加载的驱动所使用的内核版本和系统运行的版本不一致。
二、尝试写Makefile
不成功,只能自己来了。查了一下怎么给板子加载驱动,基本都是在说有驱动程序,写个Makefile生成.ko放到加载,如果不成功可能要重新编译内核。很笼统,自己既看不懂Makefile也不会编译内核,硬着头皮一点点查。
首先看了一篇介绍Makefile规则的博客:一篇文章看懂makefile编写规则
大致能看懂Makefile了,回头看自己下载文件中的Makefile,明显少东西,用到的变量前面都没定义,于是尝试修改。发现网上有很多关于生成.ko文件的Makefile模板,各式各样。有的要写交叉编译工具链目录,有的要写ARCH和CROSS_COMPILE,有的又没写。不太理解,先找交叉编译工具链目录吧。
参考博文:寻找交叉编译工具链安装位置的方法,$PATH找到自己交叉编译工具链路径,知道自己的ARCH=arm,CROSS_COMPILE=arm-hisiv500-linux- 。但还是不太懂有什么用。
尝试写了多个版本的Makefile文件,记录一下自己遇到的错误。先贴一下最开始写的Makefile,其实这个交叉编译链路径好像可以不要吧。
ARCH=arm
CC=arm-hisiv500-linux-gcc
LDFLAGS = /home/linkpi/work/3531D/opt/hisi-linux/x86-arm/arm-hisiv500-linux/target/bin
obj-m :=tvp7002.o
KERNELDIR :=/home/linkpi/work/3531D/SDK/Hi3531D_SDK_V1.0.3.0/osdrv/opensource/kernel/linux-3.18.y
PWD :=$(shell pwd)
modules:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
clean:
rm *.ko *.mod* *.symvers *.order
- 第一次报错
最开始自己新建了一个文件夹,傻不拉唧的命名为My Driver Device。没错,中间有个空格,导致make的时候一直报错没有规则生成Driver。郁闷了很久,我的Makefile里面没有Driver这个东西啊。。。网上关于这个报错的修改基本都是什么Makefile不规范,该用Tab的地方用了空格什么的。思考了很久才发现这个Driver是自己文件夹的名字里的,打了空格之后可能让makefile认为他不属于前面的路径,而是一个要生成的目标。所以,文件夹命名千万不要有空格。
2.第二次报错
改了文件夹名称后,又make了一下,报错了一大段。网上说让把什么总的Makefile中带’-m64’的全删掉,感觉不太靠谱,而且我也不知道总的Makefile是啥。找不到原因,想起有人说make不成功要重新编译内核,于是开始尝试编译内核。。。
linkpi@ubuntu:~/work/MyDriver/tvp7002PUDN/tvp7002_1080p$ make
make -C /home/linkpi/work/3531D/SDK/Hi3531D_SDK_V1.0.3.0/osdrv/opensource/kernel/linux-3.18.y M=/home/linkpi/work/MyDriver/tvp7002PUDN/tvp7002_1080p modules
make[1]: Entering directory '/home/linkpi/work/3531D/SDK/Hi3531D_SDK_V1.0.3.0/osdrv/opensource/kernel/linux-3.18.y'
CC [M] /home/linkpi/work/MyDriver/tvp7002PUDN/tvp7002_1080p/tvp7002.o
arm-hisiv500-linux-gcc: error: unrecognized command line option ‘-m64’
arm-hisiv500-linux-gcc: error: unrecognized command line option ‘-mno-80387’
arm-hisiv500-linux-gcc: error: unrecognized command line option ‘-mno-fp-ret-in-387’
arm-hisiv500-linux-gcc: error: unrecognized command line option ‘-mno-red-zone’
arm-hisiv500-linux-gcc: error: unrecognized command line option ‘-mcmodel=kernel’
arm-hisiv500-linux-gcc: error: unrecognized command line option ‘-maccumulate-outgoing-args’
arm-hisiv500-linux-gcc: error: unrecognized command line option ‘-mno-sse’
arm-hisiv500-linux-gcc: error: unrecognized command line option ‘-mno-mmx’
arm-hisiv500-linux-gcc: error: unrecognized command line option ‘-mno-sse2’
arm-hisiv500-linux-gcc: error: unrecognized command line option ‘-mno-3dnow’
arm-hisiv500-linux-gcc: error: unrecognized command line option ‘-mno-avx’
scripts/Makefile.build:263: recipe for target '/home/linkpi/work/MyDriver/tvp7002PUDN/tvp7002_1080p/tvp7002.o' failed
make[2]: *** [/home/linkpi/work/MyDriver/tvp7002PUDN/tvp7002_1080p/tvp7002.o] Error 1
Makefile:1381: recipe for target '_module_/home/linkpi/work/MyDriver/tvp7002PUDN/tvp7002_1080p' failed
make[1]: *** [_module_/home/linkpi/work/MyDriver/tvp7002PUDN/tvp7002_1080p] Error 2
make[1]: Leaving directory '/home/linkpi/work/3531D/SDK/Hi3531D_SDK_V1.0.3.0/osdrv/opensource/kernel/linux-3.18.y'
Makefile:11: recipe for target 'modules' failed
make: *** [modules] Error 2
三、尝试编译内核
第一次接触,不知道什么是编译内核。网上看了一些文章都只有几步操作指令,但是自己连一句指令都看不懂,完全无法理解。于是找了个视频看,发现韦东山老师一二期衔接部分的视频讲的就是这块,而且还免费,太好了。看完大概知道了怎么打补丁、配置内核、编译内核,但是我在第一次编译内核时也犯了一个很搞笑的错误。先总结一下整个流程吧。
参考博文:海思[Hi3531]uboot、kernel和系统的镜像制作和烧写
- 下载内核,打补丁
有一个文档写的很清楚
一、将Hi3531DV100的补丁打到v3.18.20的linux kernel上。
1、从linux开源社区下载v3.18.20版本的内核:
1)进入网站:www.kernel.org
2)选择HTTP协议资源的https://www.kernel.org/pub/选项,进入子页面
3)选择linux/菜单项,进入子页面
4)选择kernel/菜单项,进入子页面
5)选择v3.x/菜单项,进入子页面
6)下载linux-3.18.20.tar.gz(或者linux-3.18.20.tar.xz)
2、打补丁
1)将下载的 linux-3.18.20.tar.gz 存放到 hi3531dv100 svn osdrv的opensource/kernel目录中
2)在linux服务器中进入 hi3531dv100 svn osdrv 的根目录,执行如下命令:
cd opensource/kernel
tar -zxf linux-3.18.20.tar.gz
mv linux-3.18.20 linux-3.18.y
cd linux-3.18.y
patch -p1 < ../hi3531dv100_for_linux_v3.18.y.patch
cd ../
cd ../../
二、差异补丁说明
diff_hi3531dv100_from_last_version.patch是当前版本跟上一个版本的差异补丁,主要用于罗列当前版本的改动点。
-
切换到内核源码目录,使用厂家提供的配置文件,将厂家config文件复制为 .config。
厂家提供配置文件一般叫“ *.defconfig”,会在arch/arm/configs目录下。(自己第一次不知道defconfig在哪,当前目录下又只有一个Kconfig长得比较像,恩就是它了哈哈哈)会有特别多的defconfig文件,根据自己板子型号和实际情况具体选择。我这里选的是hi3531d_nand_defconfig。
hi3531d_xxx_defconfig参数设置说明:
hi3531d_full_defconfig,使用SPI Nor Flash或SPI Nand Flash,PCIE选择主片模式;
hi3531d_full_slave_defconfig,使用SPI Nor Flash或SPI NandFlash,PCIE选择从片模式;
hi3531d_nand_defconfig,使用Nand Flash,PCIE选择主片模式;
hi3531d_nand_slave_defconfig,使用Nand Flash,PCIE选择从片模式
具体指令:$cp arch/arm/configs/hi3531d_nand_defconfig .config
-
配置内核
cp defconfig后可以在源码目录下看到.config。
配置内核指令:$make ARCH=arm CROSS_COMPILE=arm-hisiv500-linux- menuconfig
会弹出一个配置窗口,没有特殊更改可以直接退出。出于好奇,我在这里搜索了一下tvp7002,发现这个内核本身就有tvp7002的驱动。。。
于是找到对应位置,将其选择为M(生成动态驱动模块)。- VIDEO_TVP7002=m,表示可以用驱动模块的形式向内核添加驱动或移除驱动,也就是生成.ko文件,insmod或者lsmod,比较方便。 - VIDEO_TVP7002=y,表示静态加载,也就是驱动直接集成的内核里去了,更改不方便