为了用内核驱动程序点亮一个LED灯,真是费尽周折,参考了韦东山的《嵌入式linux驱动开发完全手册》(以下简称《完全手册》)和网上很多人的blog,最终在@Carlos·Wei的指引下,终于点亮了LED灯,见下图!
其中的一些弯路主要是没严格按照韦东山的linux版本和其编译器来编译内核和驱动程序,二来是因为韦东山这本书当时写的不是那么详细,在理解上有些许偏差。
本文地址:https://www.cnblogs.com/multimicro/p/9262196.html
作者:multimicro
下面在写这篇博客时列出我的开发环境等信息
开发环境
- linux Ubuntu 16.04
- arm-linux-gcc-3.4.5-glibc-2.3.6 版本(用《完全手册》指定的编译器,我当时用的arm-linux-gcc4.4.3版本,结果编译出的程序在JZ2440开发板上无法运行)
- 开发板中u-boot为板载资料提供
- 开发板中linux内核版本为linux-2.6.22.6
- 开发板中yaffs文件系统为板载资料提供
P.S. 为了获取图片,我没在同一个内核文件中操作,所以,读者在操作使用时,一定要在同一个内核文件中!
**实测Ubuntu 18.04 LTS同样可用,在上面一定要配置好编译器! **
一、点亮一个LED灯需要做的准备工作
首先引用宋宝华《linux设备驱动开发详解》中P66的一段话
在linux内核中增加程序需要完成以下3项工作。
- 将编写的源代码复制到linux内核源代码的相应目录中。
- 在目录的Kconfig文件中增加关于新源代码对应项目的编译配置选项。
- 在目录的Makefile文件中增加对新源代码的编译条目。
确保按照韦东山的那个PDF对内核文件进行打补丁在进行后续工作哦!
执行命令(非常关键,否则编译出的内核不好使,这是韦东山配置好的.config文件,直接使用就行了,然后结合后面的menuconfig就可以把要加载的LED驱动程序信息更新到.config里面)
cp config_ok .config
如果执行
make s3c2410_defconfig
那么生成的.config配置文件不能够编译出运行在JZ2440板子上的内核uImage文件,这里先挖个坑,文章末尾稍微解释一下为什么不能
那个mkimage文件要是缺失的话,就要按照PDF上的要求操作了哦(复制到linux操作系统的/usr/bin/目录下)
第一步:修改linux-2.6.22.6内核文件
1)配置顶层Makefile(主要是配置编译器为arm-linux-gcc-3.4.5-glibc-2.3.6所在路径)
2)增加s3c2440配套的内核驱动源程序到 /drivers/char/ 目录下
由于韦东山在《完全手册》的资料里提供的/drivers_and_test/leds/s3c24xx_leds.c是适配V1版本的,笔者使用的是JZ2440_V3版本,不做修改就执行以下步骤你在V3版本上是点不亮的哦。V3版本的LED是链接到GPF上的,不是GPB上,如图:
所以,这里要做一下调整才行的:
3)配置 /drivers/char 目录下的Kconfig
4)配置 /drivers/char目录下的Makefile
第二步:配置menuconfig
在内核linux-2.6.22.6根文件目录下执行
make menuconfig
如果出错了,那有可能是你调整终端界面尺寸了,关闭后进入内核文件后再执行该命令即可,若还是错,那就是你的问题了哦!
在内核目录树内依次选择
Device Drivers --->
Character devices --->
<*> S3C2440_LEDS MULTIMICRO(NEW)
我这个已经保存过了,所以就没有NEW标志了
在光标停留在S3C2440...选项上时,可以通过敲击键盘空格来配置是将改驱动程序编译到内核中还是编译为一个.ko文件(独立的文件,可供内核加载),本文加载到内核汇里面去了,免去了加载到内核中的繁琐。然后配置完后,一路Exit然后Yes即可,配置后终端会提示如下信息:
第三步:将驱动程序编译至内核中
然后在执行
make -j8
make uImage -j8
结果如图,可以看出编译好的内核文件uImage已经生产(大小约1.8M,若大小为1.4M左右,那就需要先执行cp config_ok .config
然后make menuconfig
才能生成这个约1.8M的内核文件),在/arch/arm/boot/目录下面,此时的内核文件中已经包含了s3c2400的LED驱动程序。
第四步:编译驱动测试程序
该程序目的是为了调用内核中的LED驱动函数
改程序在韦东山《完全手册》配套的光盘资料里面的/drivers_and_test/leds/s3c24xx_leds.c中
在编译改.c程序前,首先修改.c同一目录下得Makefile文件,主要是配置为与编译内核一致的编译器
然后make一下就会生产可执行文件
make
至此,准备工作都已经完成,接下来开始使用这些生成的uImage 和 led_test文件
二、测试LED内核驱动
第一步:烧录uImage内核文件
首先把上文产生的内核文件uImage烧录至jz2440开发板中(默认你已经烧录了yaffs文件系统哦,否则无法再终端进行一下步骤),重启开发板后,可以在终端看到如下界面
然后在终端按下回车会看到如下界面,现在就可以使用cd、ls等命令了
第二步:将上文生产的led_test可执行文件传输至开发板中
- 可以用ftp传
- 可以用scp传
- 可以用U盘传(本文选用此种方式)
用u盘传就要挂载U盘了,以此处为基准倒数第二个图片可以看到 [sda] 这些信息行,其上还有我的U盘型号 SanDisk Cruzer Force,表示开发板已经检测到了U盘,因为我的在U盘一直在开发板上插着,所以启动时就自动检测了。当然你插上U盘后也会显示这些信息,通过
fdisk -l
可以查看U盘的的设备点,然后下一步就是在开发板的/mnt/目录下建立一个文件夹,用于将U盘的里的文件都挂载到这个文件夹下,我在/mnt/文件夹下建立了一个sandisk的文件夹。
接下来就可以挂载U盘到sandisk文件夹下了,执行以下命令:
mount -t auto /dev/sda1 /mnt/sandisk
然后cd到sandisk文件夹下就可以ls出U盘里的内容了,将led_test文件cp到开发板/usr/bin/文件夹下就ok了
第三步:建立led驱动设备文件
执行命令(详见《完全手册》P395)
mknod /dev/leds c 231 0
第四步:执行内核驱动测试程序
执行命令
led_test 1 on
led_test 1 off
可以看到开发板的第一个led点亮和熄灭(Open LED!等信息是我自己修改程序后加入的)
若你的led_test可执行文件不在开发板/usr/bin/文件夹下,那在改可执行文件所在目录下执行
./led_test 1 on
./led_test 1 off
也可以的
若提示Illegal instruction那说明你编译led_test执行文件所使用的编译器和编译内核的编译器不是同一个!改成同一个编译器就好了
为什么不能使用make s3c2410_defconfig命令生成.config文件
s3c2410_defconfig是官方提供的默认配置文件,make此文件可以生成默认的配置.config文件,但这个默认的配置文件是不能直接使用的,还需要在menuconfig里面配置好多选项才能生成合适的.config文件,下图左边为韦东山修改过的.config文件内容,右边为经make s3c2410_defconfig
后生成的.config文件
可以看出,韦东山的.config文件相对比默认的.config文件修改了不少配置,这里只粘贴出一部分。所以要想使用make s3c2410_defconfig
命令的话,就要在之后的make menuconfig
里面修改很多配置,现在我还不会配置,不过知道有这回事,以后说不定哪天就可以自己配置了。