【北京迅为】《STM32MP157开发板嵌入式开发指南》- 第三十七章 Linux内核模块

iTOP-STM32MP157开发板采用ST推出的双核cortex-A7+单核cortex-M4异构处理器,既可用Linux、又可以用于STM32单片机开发。开发板采用核心板+底板结构,主频650M、1G内存、8G存储,核心板采用工业级板对板连接器,高可靠,牢固耐用,可满足高速信号环境下使用。共240PIN,CPU功能全部引出:底板扩展接口丰富底板板载4G接口(选配)、千兆以太网、WIFI蓝牙模块HDMI、CAN、RS485、LVDS接口、温湿度传感器(选配)光环境传感器、六轴传感器、2路USB OTG、3路串口,CAMERA接口、ADC电位器、SPDIF、SDIO接口等


第二部分 Linux内核裁剪与定制

第三十七Linux内核模块

本章导读

Linux设备驱动会以内核模块的形式出现,因此,学会编写Linux内核模块编程是学习Linux设备驱动的先决条件。

37.1章节讲解了linux内核模块的概念,并以helloworld为例,将其编译为驱动模块。

37.2 章节讲解了以 ch34x 驱动为例,将其编译为驱动模块。

37.1 Linux内核模块简介

Linux内核的整体架构本就非常庞大,其包含的组件也非常多。而我们怎样把需要驱动都包含在内

核中呢?

编译驱动有俩种方法

第一种方法:Linux提供了这样的机制,这种机制被称为模块(Module)。把驱动编译成模块,然后使用命令把驱动加载到内核里面。模块本身不被编译入内核映像,从而控制了内核的大小。模块一旦被加载,它就和内核中的其他部分完全一样。

第二种方法:直接把驱动编译到内核中

为了使读者初步建立对模块的感性认识,在第36.3章节我们已经写了一个最简单的驱动helloworld,那么这个章节将来学习怎么将我们写的驱动编译成驱动文件。

我们以STM32MP157开发板为例,我们编译驱动为内核模块。我们将36.3章节编写的helloworld.c拷贝到Ubuntu的任意路径目录下,这里作者拷贝到/home/nfs/01目录下。

以 module 的方式编译驱动,需要以下几个部分:

1  内核成功编译过;

2 找到内核的 arm 编译器;

3 编译简单驱动;

4 编译简单的 Makefile 文件,Makefile 文件中需要指向内核源码目录(成功编译过的内核源码目录);

要动态的编译内核,首先需要将内核源码编译通过 ,内核的编译请参考使用手册35.2.1章节。

37.1.1 内核和编译器路径

本节介绍内核路径、编译器路径。

如下图所示,作者的内核源码在“/home/topeet/work/linux-5.4.31”目录下:

 

如上图所示,我们可以得到一些信息,在后面编译内核模块的时候,需要设置编译目标平台为 arm,  

编译器的路径为:

“/usr/local/arm/gcc-arm-10.3-2021.07-x86_64-arm-none-linux-gnueabihf/bin/arm-none-linux-gnueabihf-”

如下图所示:

 

综上我们在编译之前需要使用以下命令设置编译环境,或者将环境设置,卸载Makefile中。

export ARCH=arm

export CROSS_COMPILE=arm-none-linux-gnueabihf-

37.1.2 Makefile 和测试驱动源码以及编译

作者在  “/home/nfs”目录下新建一个 “01”目录,将要编译的驱动和 Makefile 文件放到这个目录下。

37.1.2.1 Makefile

首先我们进入“/home/nfs/01”目录下,如下图所示:

 

首先根据36.3 最简单的设备驱动-helloworld章节编写helloworld.c文件,文件整体内容如下

#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("goodbye! \n");
}
module_init(hello_init);
module_exit(hello_exit);
MODULE_LICENSE("GPL");

添加完成如下图所示:

随后我们使用命令“vim Makefile”创建Makefile 脚本文件,并写入以下内容:

obj-m += helloworld.o
KDIR =/home/topeet/work/linux-5.4.31
PWD ?= $(shell pwd)
all:
        make -C  $(KDIR) M=$(PWD) modules modules ARCH=arm CROSS_COMPILE=/usr/local/arm/gcc-arm-10.3-2021.07-x86_64-arm-none-linux-gnueabihf/bin/arm-none-linux-gnueabihf-
clean:
        rm -rf modules.order *.o workqueue.o  Module.symvers *.mod.c *.ko

脚本中:

第一行:obj-m += helloworld.o 表示编译的源文件为helloworld.c ,如果源文件名有变化,则需要修改成对应的。

第二行:KDIR 参数指向对应的内核源码目录。作者的内核源码是在/home/topeet/work/linux-5.4.31目录下,用户要根据自己的具体情况来修改。

第三行:PWD ?= $(shell pwd)表示将当前目录的路径赋值给 PWD 变量,也就是 /home/nfs/01。作者将会把 Makefile 文件和驱动源码放到这个目录下编译。

第五行:其中 make -C   $(KDIR) M=$(PWD) modules ,表示将当前目录下的文件编译 为模块,并且制定了内核源码的路径;

其中 ARCH=arm 表示设置目标 CPU 类别为 arm ,也就是编译的依赖内核和驱动模块目标 CPU 为 ARM ;

其中 CROSS_COMPILE=/usr/local/arm/gcc-arm-10.3-2021.07-x86_64-arm-none-linux-gnueabihf/bin/arm-none-linux-gnueabihf-,这里的路径,指向内核编译器的路径。

37.1.2.2 编译

我们进到/home/driver/01目录下,如下图所示:

使用命令 “make” ,如下图所示,可以看到有 “helloworld.ko”文件生成。 

我们通过 nfs 将编译好的驱动程序在开发板上加载驱动模块,注意!nfs 的配置和使用,请参考本手册35.2.3章节搭建nfs 共享目录章节配置。

我们进入到共享目录/mnt/ ,我们输入命令“insmod helloworld.ko”,可以看到我们编写的helloworld驱动加载成功,如图所示:

 我们输入命令“rmmod helloworld”,可以看到我们编写的helloworld驱动拆卸成功,如下图所示

 

我们输入命令“rmmod helloworld”,可以看到我们编写的helloworld驱动拆卸成功,如下图所示 

 

在Linux中,使用lsmod命令可以获得系统中已加载的所有模块以及模块间的依赖关系,如下图所示:

37.2 ch34x驱动实验

经过 37.1 章节的学习,我们已经清楚地掌握了把一个驱动编译成一个模块的完整的流程,虽然说这个 知识点非常简单,但是这个小的知识点可是有大用处的,那么这个章节将以实践课的方式给大家做一个演 示。

任务需求:假如开发板上自带的串口不够用了,若需要用 usb 转串口来扩展一路串口。如下图所示是 usb 转串口的元器件

我们只要这个元器件的 usb 口插到我们开发板上,那么它会转出一路串口,这样则完成了使用 usb 转串口来 扩展一路串口的需求。但是内核并不支持元器件里芯片的驱动,假设这个芯片是 ch340 的,假设现在的内 核不支持 ch340 驱动,我们则需要把 ch340 驱动移植进去。

分析需求:首先我们来分析下需求,现在硬件开发平台是 STM32MP157 开发板,我们要做的就是把驱动移植上去。 但是我们移植驱动,首先要有驱动源码,然后还要有相应的 Makefile。那这个驱动源码需要我们写吗?当然不用我们写了,像这种 ch340 比较成熟的芯片,芯片厂商都有相应的驱动来供我们下载。

实践步骤 

1 先去内核源码里面去搜索,如果有的话,我们可以直接选择这个驱动,然后直接使用

2 假如没有这个驱动,我们需要自己编译一个驱动,然后加载到内核里面去运行

因为 usb 转串口上用的这些芯片比较成熟,比如说这个芯片是 ch340,那么 ch340 支持的驱动是非常齐全 的,比如说 linux,windows,android,macos,wince 这些平台都支持这个驱动,我们只要去他的官网下载就可 以了。打开浏览器 https://blog.csdn.net/JAZZSOLDIER/article/details/70169732 这篇博客给总结了各平台支持 的 ch340 驱动,因为我们现在这里用的是 linux,所以我们只需要下载 linux 版本的驱动就可以了。

打开下载链接 http://www.wch.cn/download/CH341SER_LINUX_ZIP.html 如下图所示,然后直接点击下载。

 我们在 Ubuntu 的/home/nfs/目录下新建一个文件夹 02,然后将“iTOP-STM32MP157开发板网盘资料汇总\09_嵌入式Linux开发指南(iTOP-STM32MP157)手册配套资料\驱动程序例程\02-ch340驱动实验”下ch34x.c文件拷贝到这个文件夹,然后将上次编译 helloworld 的 Makefile 拷贝 到同级目录下,并修改 Makefile 为如下图所示:

 

修改完毕,保存退出。我们将 ch34x.c 文件里面的这俩行注释掉,如下图所示: 

 

 

然后我们需要添加以下头文件

#include <linux/sched/signal.h>

添加完成如下图所示:

 

保存修改,然后退出。我们按照上一章学习的编译驱动的方法,编译好 ch340驱动,如下图所示:

接下来我们进入到开发板的共享文件目录,输入以下命令加载驱动,如下图所示:

insmod ch34x.ko

 

加载完驱动后,U 转串会转出一路串口。 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值