(一)嵌入式 Linux驱动程序设计之驱动模块编译

嵌入式 Linux驱动程序设计

用于嵌入式 Linux系统的內核、驱动和应用程序开发人员,ARM嵌入式系统接口设计人员的参考

嵌入式:
交叉学科,知识体系庞杂
C语言 
数电(单片机)
arm体系结构
硬件设计(arm接口技术)
Linux系统开发
Linux驱动开发
BootLoader(UBOOT)
QT(C++)
Android系统和JAVA

(一)嵌入式 Linux驱动程序设计之驱动模块编译_第1张图片
(一)嵌入式 Linux驱动程序设计之驱动模块编译_第2张图片

Linux驱动分类:
字符设备驱动
块设备驱动(EMMC等存储相关)
网络设备驱动

驱动分为4部分:
头文件
驱动模块入口和出口
声明信息 
功能实现

注意:先下载内核在window解压后使用source insight创建工程打开;将外面新建的文件拖入工程编辑代码,这样就可以方便使用编辑过程中使用内核函数;可以参考driver/misc.c;头文件可以全部拷贝过来使用;然后按照以下步骤写代码

在这里插入图片描述
(一)嵌入式 Linux驱动程序设计之驱动模块编译_第3张图片

//第一步  包含头文件
#include//包含宏定义头文件
#include//初始化加载模块头文件

//第四步  功能实现
static int hello_init(void)
{
    printk("hello world\n");
    return 0;
}
static int hello_exit(void)
{
    printk("bye bye\n");
    return 0;
}

//第二步  驱动模块入口和出口
module_init(hello_init);
module_exit(hello_exit);

//第三步 声明模块拥有开源许可证
MODULE_LICENSE("GPL");
注意:内核加载时候打印hello world,内核卸载时候打印bye bye;内核打印哈数不能用printf因为内核没有办法调用C库函数.
linux 驱动模块编译
法1:
把驱动编译成模块,然后使用命令把驱动加载到内核里面
法2:
直接把驱动编译到内核
第一步:写makefile
obj-m +=hello.o
KDIR:=/home/linux-imx-4.1.13.2.ga    #写内核源码路径
PWD?=$(shell pwd)  #获取当前目录的编码
all:
	make -C $(KDIR) M=$(PWD) modules
第二步:编译驱动
编译之前注意问题:
1.内核源码一定要先编译通过(就是内核源码路径下源码编译必须通过)
2.编译驱动模块用的内核源码一定要和我们开发板上运行的内核镜像是同一套(否则会报版本不正确错误)
3.看一下ubuntu环境是不是arm
在源码路径下输入:make menuconfig查看,如果不是输入命令export ARCH=arm后再查看

设置环境变量:
export CROSS_COMPILE=arm-linux-gnueabihf-
export ARCH=arm
编译成功后就可以看见KO文件了,这个ko文件就是编译好的驱动。

将驱动拷到开发板使用:
加载驱动模块:insmod hello.ko
查看加载的模块:lsmod
卸载驱动模块:rmmod hello   注意没有ko后缀


(一)嵌入式 Linux驱动程序设计之驱动模块编译_第4张图片

需求:开发板上自带串口不够用,需要将USB转串口扩展一路串口

1.先去内核源码搜索,有就可以直接使用;
2.没有时,需要编译一个驱动,然后加载到内核运行即可。
比如:usb转串口,这个上面的芯片因为比较成熟,如CH340,就可以百度官网下载驱动:https://sparks.gogo.co.nz/ch340.html

下载如下:此Makefile我们不需要,我们只需要将.c拷贝过去即可,然后使用自己Makefile,改目标和开发板使用的内核源码路径即可
(一)嵌入式 Linux驱动程序设计之驱动模块编译_第5张图片

obj-m +=ch34x.o
KDIR:=/home/linux-imx-4.1.13.2.ga    #写内核源码路径
PWD?=$(shell pwd)  #获取当前目录的编码
all:
	make -C $(KDIR) M=$(PWD) modules
总结:
 第一步:建立Linux驱动的骨架
	linux内核使用驱动时候,需要先初始化,包括建立设备文件,分配内存地址空间等,退出的时候要释放资源,删除设备文件,释放内存地址空间等。所以在linux驱动中需要提供两个函数来分别处理驱动初始化和退出的工作,这两个函数分别用module_init和module_exit宏来指定,linux驱动一般都需要指定这两个函数,所以linux驱动有一个C文件,文件中包含处理驱动初始化和退出的函数,以及指定这两个函数的module_init和module_exit宏.
第二步:注册和注销设备文件
	任何一个驱动都有设备文件,misc_register,misc_deregister
第三步:指定与驱动相关的信息
   驱动程序带自描述内容,比如用modinfo可以获取包括作者名称,版本号等等,有MODULE_AUTHOR,MODULE_LICENSE,MODULE_ALIAS,MODULE_DESCRIPTION等宏
第四步:指定回调函数
    linux驱动的各个动作也可称为事件,这些时间就有相应的回调函数,
第五步:编写功能逻辑
    编写程序,来实现该驱动所要求达到的功能,可以由多个函数/多个文件/甚至多个模块组成
第六步:编写Makefile
    一个新的驱动程序必须要有一个Makefile,obj-m表示将驱动作为模块编译,obj-y则表示将驱动编译进内核, echo 'obj-m := led.o' > Makefile
   上句表示新建一个Makefile文件,文件中只有一个话:obj-m := led.o
   该句表示用make指令编译时,会将源代码目录中的led.c或led.s文件编译成led.o文件,并且led.o会被编译进led.ko文件,然后使用insmod或modprobe命令来装载led.ko.如果使用的不是obj-m,而是obj-y,则led.o将会被编译进build-in.o,最终被连接进内核。build-in.o是连接同一类程序的.o文件生产的中间目标文件。make menuconfig可以配置是否最终编译进内核。
    如果驱动依赖其他程序,如process.c,data.c,则Makefile需要按如下写:
obj-m := led.o
  led-y := process.o data.o
   依赖文件由module-y或module-objs决定,module就是指led。
第七步:编译驱动程序
    可以直接将驱动编译进内核,也可以作为模块单独编译
第八步:安装/卸载驱动
    将驱动编译进内核,则只要linux使用该内核,则驱动将自动加载。如果不编译进内核,而是以模块存在,在需要使用insmod或modprobe命令来装载驱动模块,用rmmod命令来卸载驱动模块。

你可能感兴趣的:(Linux,linux)