Linux驱动
开发板 ITOP4412
1、什么是linux驱动
基于OS的编程方式和单片机开发(裸机开发)截然不同
应用程序的执行是依赖于操作系统的
应用程序需要调用linux操作系统的库函数来实现
驱动程序是操作系统和硬件之间的桥梁, 应用程序不能直接操作硬件
2、Linux驱动的分类
1、字符设备驱动
2、块设备驱动(存储相关的 tf 、 flash 、 emmc)
3、网络设备
其中,理解和掌握字符设备驱动的概念最重要,因为工作中遇到的大部分都是字符设备(如LED、蜂鸣器、GPIO控制等)
3、驱动编程
1、驱动分为四个部分:
1、头文件
2、驱动模块的入口和出口
3、声明信息
4、功能实现
1、头文件
#include <linux/init.h> //包含宏定义的头文件
#include <linux/module.h> //包含初始化加载模块的头文件
2、模块驱动的入口和出口
moudule_init(); //入口 函数参数是入口功能函数
moudule_exit(); //出口
3、声明信息(开源协议)
MODULE_LICENSE("GPL");
4、功能实现
2、最简单的驱动程序helloworld
#include <linux/init.h>
#include <linux/module.h>
static int hello_init(void)
{
printk("hello world\n");
return 0;
}
static void hello_exit(void)
{
printk("byb byb\n"); // 这里打印函数需要用printk 因为printf是C库函数
}
module_init(hello_init); //入口
module_exit(hello_exit); //出口
MODULE_LICENSE("GPL");
1、加载驱动模块 insmod
示例、最简单的linux驱动 helloworld
insmod xxx.ko
YUAN@root:/mnt/mydriver# insmod helloworld.ko
[ 250.276373] hello world
YUAN@root:/mnt/mydriver#
2、查看模块 lsmod
YUAN@root:/mnt/mydriver# lsmod
helloworld 680 0 - Live 0xbf000000
3、卸载驱动模块 rmmod
YUAN@root:/mnt/mydriver# rmmod helloworld
rmmod: can't change directory to '3.0.15': No such file or directory
执行rmmod出现错误,提示在lib/modules/目录下没有3.0.15目录, 解决办法在 modules目录下创建3.0.15目录
然后再次卸载驱动模块 成功
YUAN@root:/mnt/mydriver# rmmod helloworld
[ 701.536467] byb byb
4、编译驱动
一共有两种方法
1、编译成模块
把驱动编译成模块,然后使用命令把驱动加载到内核里面
第一步:写一个makefile
obj-m += helloworld.o
# 内核路径
KDIR := /home/now/kernel3.0/iTop4412_Kernel_3.0
#获取当前路径
PWD = $(shell pwd)
all:
make -C $(KDIR) M=$(PWD) modules
#这句是Makefile的规则:-C 选项的作用是指将当前工作目录转移到你所指定的位置。“M=”选项的作用是,当用户需要以某个内核为基础编译一个外部模块的话,需要在make modules 命令中加入“M=dir”,程序会自动到你所指定的dir目录中查找模块源码,将其编译,生成KO文件
第二步:编译驱动
编译驱动之前要注意的问题:
1、内核源码一定要先编译通过
2、我们编译驱动模块用的内核源码一定要和我们的开发板上运行的内核镜像是同一套
3、修改编译器 为arm交叉编译器
准备工作做完之后,执行make
这个ko文件就是我们编译好的驱动,将ko文件copy到nfs文件下,然后挂载到开发版
mount -o nolock -t nfs 192.168.51.183:/home/nfs /mnt/
然后执行insmod helloworld.ko 即可加载驱动
2、直接把驱动编译到内核
2.1使用make menuconfig 图形化配置界面
如果出现 如下错误
scripts/kconfig/mconf Kconfig
Your display is too small to run Menuconfig!
It must be at least 19 lines by 80 columns.
make[1]: *** [/home/now/kernel3.0/iTop4412_Kernel_3.0/scripts/kconfig/Makefile:21:menuconfig] 错误 1
make: *** [Makefile:502:menuconfig] 错误 2
表示当前终端窗口大小过小,无法显示完全 窗口大小至少为19行 80列 ,调整窗口大小即可
1、搜索功能
输入" / " 即可弹出搜索界面,然后输入我们想要搜索的内容
2、配置驱动的状态
(1) 把驱动编译成模块
(2) 把驱动编译到内核里面
(3) 不编译
选择相应的模块然后按"空格"来选择状态
[*] 代表编译到内核 [M] 表示编译成模块 [ ] 不编译
3、退出
保存退出
不保存退出
4、make menuconfig 相关的配置文件
Makefile 里面是编译规则, 告诉我们在make的时候要怎么编译, 就相当于菜的做法
Kconfig **内核配置的选项,**相当于我们去饭店吃饭服务员给我的菜单
.config 配置完内核后生成的配置选项, 相当于点完的菜单
5、make menuconfig 会读取哪个目录下的Kconfig文件?
arch/$ARCH/Kconfig文件、各级目录下的Kconfig
$arch 是根据makefile中的ARCH指定的平台
/arch/arm/configs 目录下面有好多配置文件。 相当于饭店的特色菜, 也就是有一些厂家提供的默认配置文件
例如可以将某些deconfig配置文件复制为.config 文件
6、为什么要复制成.config 而不复制成其他的文件呢?
因为内核默认读取Linux内核根目录下的.config作为默认的配置选项,所以我们不能给他改名字
7、 复制的默认配置选项不符合我们的需求怎么办?
执行make menuconfig 进行配置即可,当我们配置完成后,会将新的配置信息保存到.config中去
当再次make menuconfig时,配置的选项信息就是当前的.config配置信息
8、怎么和Makefile文件建立的关系呢?
当我们make menuconfig 保存退出以后,Linux会将所有的配置选项以宏定义的形式保存到 include/generated/autoconf.h 文件中去
2.2 添加驱动
1、修改Kconfig文件, 这里可以选择修改arch/$(arch)/Kconfig 文件 也可以选择修改,设备驱动中的Kconfig文件
因为arch/$(arch)/Kconfig 文件 已经指定了drivers下的Kconfig文件,这里就不需要再次修改arch/arm/Kconfig文件了,需要修改的是设备驱动下的 driver/下的
2、 Kconfig配置文件语法
soucre "drivers/redled/Kconfig"
config LED_4412 #配置选项的名称
tristate "Led Support for GPIO Led" #驱动的状态 在make menuconfig 中可以看到这句话 然后使用 空格 切换3种状态 [*] 编译到内核 [M] 编译成模块 [ ] 不编译
depends on LEDS_CLASS
help
This option enable support for led
soucre “drivers/redled/Kconfig” 包含drivers/redled/ 这个路径下的驱动文件 source 在当前shell中执行脚本
config LED_4412 配置选项的名称 全称 CONFIG_LED_4412 这里是吧CONFIG_ 省略了
tristate 表示驱动的状态, * 编译到内核 M编译成模块 [ ] 不编译
还有一个是bool , 与上面相比少了 编译成模块
depends on LEDS_CLASS 依赖信息 A depends on B 表示只有在选择B的时候才可以选择A
help 帮助信息
3、将驱动编译进内核(hello world)
1、首先进入drivers/char 目录下 创建一个文件夹 hello,然后将helloworld.c 拷贝到hello下
2、 编写Kconfig文件
config HELLO
tristate "Hello support"
help
This opention enable support for hello
3、 编写Makefile
obj-$(CONFIG_HELLO) += helloworld.o
#这里的CONFIG_HELLO 是Kconfig文件中的config HELLO 这里的CONFIG_ 省略了,当使用make menuconfig 选择时,[*] 这里就相当于时obj-y [M] 就是 obj-m
4、修改drivers/char/Makefile文件
obj-y 是将驱动编译进内核中 -m 是编译成模块
5、修改/drivers/char/Kconfig文件
6、make menuconfig
Device Drivers —>
Character devices —>
7 、 编译内核 make -j8
使用fastboot 刷写
上电启动 便可以看到加载的驱动打印信息
5、开发板加载驱动
1、加载驱动模块 insmod
示例、最简单的linux驱动 helloworld
insmod xxx.ko
YUAN@root:/mnt/mydriver# insmod helloworld.ko
[ 250.276373] hello world
YUAN@root:/mnt/mydriver#
2、查看模块 lsmod
YUAN@root:/mnt/mydriver# lsmod
helloworld 680 0 - Live 0xbf000000
3、卸载驱动模块 rmmod
YUAN@root:/mnt/mydriver# rmmod helloworld
rmmod: can't change directory to '3.0.15': No such file or directory
执行rmmod出现错误,提示在lib/modules/目录下没有3.0.15目录, 解决办法在 modules目录下创建3.0.15目录
然后再次卸载驱动模块 成功
YUAN@root:/mnt/mydriver# rmmod helloworld
[ 701.536467] byb byb